Cloud Provider : Azure
Can I declare resource group , Virtual network , or subnets in Azure as terraform Variable - Infrastructure as code
without variable :-
resource "azurerm_resource_group" "example" {
name = "example"
location = var.location
}
Yes you can
resource "azurerm_resource_group" "example" {
name = "${var.prefix}-resources"
location = "westeurope"
}
Related
I have a pipeline that downloads standard Terraform modules and creates resources.
"Module-ResourceGroup" deploys resource group.
"Module-Vnet" which deploys vnet.
"Module-Subnet" which deploys subnets.
My problem is when I kick the pipeline for the first time my pipeline fails reason because Module-Subnet gives me an error message that Vnet does not exist.
However, when I run the same pipeline for a second time, my Subnets get deployed without any issues as during the first run, then Vnet gets created.
I guess I have two solutions :
depends_on where I can say that by subnet module is dependent on vnet module.
Introduce a wait of 3 mins in the subnet module before it gets executed.
Q1. why it is happening? whereas as per terraform "Most of the time, Terraform infers dependencies between resources based on the configuration given" https://learn.hashicorp.com/tutorials/terraform/dependencies
if anything is wrong with the way I have written modules?
Q2. What is a better solution depends_on OR introduce wait
Q3. Is there any other way to fix it?
Below are my modules.
Module-ResourceGroup/main.tf
resource "azurerm_resource_group" "my-resourcegroup" {
name = format("%s-%s",var.resource_group_name,var.env)
location = var.location
}
Module-Vnet/main.tf
resource "azurerm_virtual_network" "my-vnet" {
name = format("%s-%s",var.vnet_name,var.env)
resource_group_name = format("%s-%s",var.resource_group_name,var.env)
location = var.location
address_space = var.address_space
}
Module-Subnet/main.tf
resource "azurerm_subnet" "my-subnet" {
for_each = var.subnetsconfig
name = format("%s-%s",each.key,var.env)
address_prefixes = each.value["address_prefixes"]
virtual_network_name = format("%s-%s",var.vnet_name,var.env)
resource_group_name = format("%s-%s",var.resource_group_name,var.env)
}
If you use the output of a resource as the input of another resource then Terraform will understand it as an implicit dependency. For example (as you did not post all of your code):
Module-ResourceGroup/main.tf
resource "azurerm_resource_group" "my-resourcegroup" {
name = format("%s-%s",var.resource_group_name,var.env)
location = var.location
}
Module-Vnet/main.tf
resource "azurerm_virtual_network" "my-vnet" {
name = format("%s-%s",var.vnet_name,var.env)
resource_group_name = azurerm_resource_group.my-resourcegroup.name
location = var.location
address_space = var.address_space
}
Module-Subnet/main.tf
resource "azurerm_subnet" "my-subnet" {
for_each = var.subnetsconfig
name = format("%s-%s",each.key,var.env)
address_prefixes = each.value["address_prefixes"]
virtual_network_name = azurerm_virtual_network.my-vnet.name
resource_group_name = azurerm_resource_group.my-resourcegroup.name
}
I'm using Terraform to manage my Infrastructure and Terratest for Testing.
In terraform, I have a module called ResourceGroup (located in the Modules folder)
resource "azurerm_resource_group" "azResourceGroup" {
name = var.resource_group_name
location = var.resource_region
tags = var.tags
}
output "resource_group_name" {
value = azurerm_resource_group.azResourceGroup.id
}
And I'm using this module in the main.tf to create an Azure Resource Group.
module "azResourceGroup" {
source = "./Modules/ResourceGroup"
resource_group_name = var.resource_group_name
tags = var.tags
}
output "resource_group_name" {
value = "${module.azResourceGroup.resource_group_name}"
}
When I execute terraform apply the output of main.tf is returning the full path of the newly created Resource Group instead of its ID.
Here's the Output
Changes to Outputs:
- resource_group_name = "/subscriptions/xxxxxxx-xxxx-xxxx-xxxx-x/resourceGroups/rg-svf-nprd-test" -> null
Preferably, it should return only rg-svf-nprd-test (Id from output variable).
Am I missing anything here? Please help me with this.
In my main terraform file I have:
resource "azurerm_resource_group" "rg" {
name = var.rg_name
location = var.location
}
resource "azurerm_public_ip" "public_ip" {
name = "PublicIP"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
domain_name_label = var.domain_name_label
allocation_method = "Dynamic"
}
And in my outputs file I have:
data "azurerm_public_ip" "public_ip" {
name = "PublicIP"
resource_group_name = azurerm_resource_group.rg.name
depends_on = [azurerm_resource_group.rg, azurerm_public_ip.public_ip]
}
output "public_ip" {
value = data.azurerm_public_ip.public_ip.ip_address
}
All the resources including IP get created, however the output is blank. How can I fix this?
Make sure output.tf contains only output tags and main.tf contains resources tags
The following works just fine for me:
Main.tf
resource "azurerm_resource_group" "example" {
name = "resourceGroup1"
location = "West US"
}
resource "azurerm_public_ip" "example" {
name = "acceptanceTestPublicIp1"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
allocation_method = "Static"
tags = {
environment = "Production"
}
}
Output.tf
output "azurerm_public_ip" {
value = azurerm_public_ip.example.ip_address
}
In case you want to have a dependency between resources, use depends_on inside the resource tag.
For example:
depends_on = [azurerm_resource_group.example]
Steps to reproduce:
terraform init
terraform plan
terraform apply
terraform output
Update-
The reason you get blank public IP is since declaring allocation_method = "Dynamic"
From the docs:
Note Dynamic - Public IP Addresses aren't allocated until they're assigned to a
resource (such as a Virtual Machine or a Load Balancer) by design
within Azure.
Full working example with dynamic allocation.
I had the same issue. The actual problem seems to be the dynamic allocation. The IP address is not known until it is actually used by a VM.
In my case, I could solve the issue by adding the VM (azurerm_linux_virtual_machine.testvm) to the depends_on list in the data source:
data "azurerm_public_ip" "public_ip" {
name = "PublicIP"
resource_group_name = azurerm_resource_group.rg.name
depends_on = [ azurerm_public_ip.public_ip, azurerm_linux_virtual_machine.testvm ]
}
Unfortunately, this seems not to be documented in https://www.terraform.io/docs/providers/azurerm/d/public_ip.html
I want to create resources in a new resource group but i want to use a virtual network for those resources which is in another resource group. How do i do this? For example, i want to create redis/postgresql in resourcegroupA but i want to make use of the virtual network which is in resourcegroupB. Is it possible?
This is the resource group from where i am retrieving the vnet-
resource "azurerm_resource_group" "azresourcegroup" {
name =
"resourcegroupA"
location = var.resource_group_location
}
#-----CREATING VIRTUAL NETWORK-----
resource "azurerm_virtual_network" "vnet2" {
name = "virtualnetworkA"
location = azurerm_resource_group.azresourcegroup.location
resource_group_name = azurerm_resource_group.azresourcegroup.name
address_space = [var.virtual_network_address_prefix_infra,var.virtual_network_address_prefix]
I retrieved it while using it for another resource group like this-
data "azurerm_resource_group" "azresourcegroup" {
name = "resoucegroupA"
}
data "azurerm_virtual_network" "vnet2" {
name = "virtualnetworkA"
resource_group_name = data.azurerm_resource_group.azresourcegroup.name
}
I want to use the above virtual network but want to create the other resources in the new resource group which is-
resource "azurerm_resource_group" "main" {
name = "resourcegroupB"
location = var.resource_group_location
}
I am making use of module to create redis cache that requires the vnet which is created in other RG-
module "rediscache" {
source = "../../modules/rediscache"
prefix = var.prefix
environmentType = var.environmentType
virtual_network_name = var.virtual_network_name
unique_identifier = var.unique_identifier_kube
resource_group_name = azurerm_resource_group.main.name
resource_group_location = var.resource_group_location
redis_subnet_address_prefix = var.redis_subnet_address_prefix
azurerm_virtual_network_name = data.azurerm_virtual_network.vnet2.name
azurerm_log_analytics_workspace_id = azurerm_log_analytics_workspace.workspace.id
}
To simplify this, vnet is created in other resource group and redis in another one.But i want to use that vnet. also if i change the resource group name argument used in module, from azurerm_resource_group.main.name to data.azurerm_resource_group.azresourcegroup.name then it creates the redis in the 1st resource group which i dont want.
Please help.
Of course, it's possible. The only condition is that the virtual network should be in the same location. Then you can quote it in the Terraform code via the Terraform Data Source azurerm_virtual_network like this:
data "azurerm_virtual_network" "example" {
name = "production"
resource_group_name = "networking"
}
I'm trying to create network Interface in Azure through terraform using below script :
resource "azurerm_subnet" "internal" {
name = "Subnet1"
resource_group_name = "${var.VNetResourceGroup}"
virtual_network_name = "${var.VNetName}"
address_prefix = "10.0.2.0/24"
}
resource "azurerm_network_interface" "main" {
name = "${var.prefix}-nic"
location = "${var.location}"
resource_group_name = "${var.resourceGroup}"
ip_configuration {
name = "ipconfig1"
subnet_id = "${azurerm_subnet.internal.id}"
private_ip_address_allocation = "dynamic"
}
}
This script creates the Subnet Subnet1 and assigning that Subnet.id in ipconfiguration.
But if I have to create another network interface again through another .tf file with the same Subnet1 , how to do I get the ${azurerm_subnet.internal.id} value again.
That is if the Subnet is already existing and I do not want to create it, how to I set those values and use them?
EDIT
I have figured out, in powershell this is the script used to determine Subnet id :
$vnetId= "[resourceId("VNetRG",'Microsoft.Network/virtualNetworks', "VNetName")]"
$subnetRef = "[concat($vnetId, '/subnets/', "Subnet1")]"
where VNetRG - resource group of VNet ,
VNetName - Name of VNet ,
Subnet1 - Name of Subnet.
Can anyone tell me what is the equivalent script in terraform?
Use a subnet data source:
data "azurerm_subnet" "subnet1" {
name = "Subnet1"
virtual_network_name = "${var.VNetName}"
resource_group_name = "${var.VNetResourceGroup}"
}
Then reference it in your NIC code with
subnet_id = "${data.azurerm_subnet.subnet1.id}"