I've been trying to split my terraform code from one large file into separate modules. I keep running into an issue where the following error appears when running Terraform Plan.
Error: Incorrect attribute value type
on modules/nsg/main.tf line 11, in resource "azurerm_network_security_group" "InternalProdNSGPrivate":
11: resource_group_name = "${module.rg.main-rg-id}"
Inappropriate value for attribute "resource_group_name": string required.
I created an outputs.tf file which has the following:
output "main-rg-id" {
value = "${azurerm_resource_group.InternalProd}"
}
The main.tf for this module has the following:
module "global_variables" {
source = "../global_variables"
}
resource "azurerm_resource_group" "InternalProd" {
name = "Internal"
location = "${module.global_variables.location}"
}
In the main.tf file for the NSG i have the following configured:
module "rg" {
source = "../rg"
}
module "global_variables" {
source = "../global_variables"
}
resource "azurerm_network_security_group" "InternalProdNSGPrivate" {
name = "Internal-NSG"
location = "${module.global_variables.location}"
resource_group_name = "${module.rg.main-rg-id}"
....
}
Not sure where im going wrong here with the configuration. Tried looking at multiple different resources, blogs, etc. but no luck.
azurerm_resource_group.InternalProd is an object representing the whole of resource "azurerm_resource_group" "InternalProd".
To produce just the id of that object, you can access attribute id like this:
output "main-rg-id" {
value = azurerm_resource_group.InternalProd.id
}
Related
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.
I would not normally ask a question like this, however I feel stuck and I do not want to hack things, but rather take the time to understand. I am new to terraform and trying to learn it, a simple task that I have set myself is to create a SQL server.
My Environment
I have some resource groups created before, anytime I try to use the same name, I get the error.
Error: A resource with the ID "/subscriptions/000000-0000-0000-0000-00000000005/resourceGroups/tf_learning" already exists - to be managed via Terraform this resource needs to be imported into the State. Please see the resource documentation for "azurerm_resource_group" for more information.
Now, you look at the error and after 2 days of google research, i followed the steps here.
Using Terraform to import existing resources on Azure
and https://gmusumeci.medium.com/how-to-import-an-existing-azure-resource-in-terraform-6d585f93ea02 and Terraform resource with the ID already exists
I create a file called existing_statee.tf with the content below.
resource "azurerm_resource_group" "tf_learning" {
}
Ran
terraform import azurerm_resource_group.tf_learning /subscriptions/000000-0000-0000-0000-00000000005/resourceGroups/tf_learningterraform import azurerm_resource_group.tf_learning /subscriptions/000000-0000-0000-0000-00000000005/resourceGroups/tf_learning
I edited the file again and saved it.
resource "azurerm_resource_group" "tf_learning" {
# (resource arguments)
name = "tf_learning"
location = "UK South"
}
Then ran the following.
terraform init
terraform plan
terraform apply
To my surprise I am still getting the error.
Error: A resource with the ID "/subscriptions/00000-00000-0000-0000-00000000000/resourceGroups/tf_learning" already exists - to be managed via Terraform this resource needs to be imported into the State. Please see the resource documentation for "azurerm_resource_group" for more information.
│
│ with azurerm_resource_group.RG-Terraform,
│ on main.tf line 1, in resource "azurerm_resource_group" "RG-Terraform":
│ 1: resource "azurerm_resource_group" "RG-Terraform" {
My tf.main file.
resource "azurerm_resource_group" "RG-Terraform" {
name = var.resource-group-name
location = var.my_location
}
resource "azurerm_sql_server" "test" {
name = var.my_dev_server
resource_group_name = azurerm_resource_group.RG-Terraform.name
location = azurerm_resource_group.RG-Terraform.location
version = var.my_dev_sql_version
administrator_login = var.my_dev_sql_login
administrator_login_password = "change_me"
}
resource "azurerm_sql_database" "test" {
name = var.my_dev_sql_database
resource_group_name = azurerm_resource_group.RG-Terraform.name
location = azurerm_resource_group.RG-Terraform.location
server_name = azurerm_sql_server.test.name
edition = var.my_dev_sql_database_sku
requested_service_objective_name = var.my_dev_sql_database_objective
tags = {
environment = "dev_database_build"
}
}
variables.tf file
variable "resource-group-name" {
default = "tf_learning"
description = "The prefix used for all resources in this example"
}
variable "app-service-name" {
default = "terraform-app-service"
description = "The name of the Web App"
}
variable "location" {
default = "UK South"
description = "The Azure location where all resources in this example should be created"
}
variable "my_location" {
type = string
default = "UK South"
}
variable "my_dev_server"{
type = string
default = "test-server-test"
}
variable "my_dev_sql_login" {
type = string
default = "mylogin"
}
variable "my_dev_sql_version" {
type = string
default = "12.0"
}
variable "my_dev_sql_database" {
type = string
default = "dev_db"
}
variable "my_dev_sql_database_tag" {
type = string
default = "dev sql database from TF"
}
variable "my_dev_sql_database_sku" {
type = string
default = "Basic"
}
variable "my_dev_sql_database_objective" {
type = string
default = "Basic"
}
I am lost as to what to do next, for now I will carry on researching.
I would like to point out this, you have configured in existing_statee.tf after importing the state
resource "azurerm_resource_group" "tf_learning" {
name = "tf_learning"
location = "UK South"
}
But in main.tf you also define again
resource "azurerm_resource_group" "RG-Terraform" {
name = var.resource-group-name
location = var.my_location
}
variable "resource-group-name" {
default = "tf_learning"
description = "The prefix used for all resources in this example"
}
variable "my_location" {
type = string
default = "UK South"
}
Since you have already declared this resource in existing_statee.tf, maybe you should remove it from main.tf
I am optimizing my terraform code by using modules. When i create a resource group module it works perfectly well but it creates two resource groups
i.e.
Temp-AppConfiguration-ResGrp
Temp-AppServices-ResGrp
instead it should only create
Temp-AppConfiguration-ResGrp
Code Resourcegroup.tf.
resource "azurerm_resource_group" "resource" {
name = "${var.environment}-${var.name_apptype}-ResGrp"
location = var.location
tags = {
environment = var.environment
}
}
output "resource_group_name" {
value = "${var.environment}-${var.name_apptype}-ResGrp"
}
output "resource_group_location" {
value = var.location
}
Variable.tf
variable "name_apptype" {
type = string
default = "AppServices"
}
variable "environment" {
type = string
default = "Temp"
}
variable "location" {
type = string
default = "eastus"
}
Main.tf
module "resourcegroup" {
source = "../Modules"
name_apptype = "AppConfiguration"
}
I want to pass name_apptype in main.tf when calling resource group module. So that i don't need to update variable.tf every time.
Any suggestions
where i am doing wrong. Plus i am also unable to output the value, i need it so that i could pass resource group name in the next module i want to create.
Thanks
You need to do that in the Main.tf
module "resourcegroup" {
source = "../Modules"
name_apptype = "AppConfiguration"
}
module "resourcegroup-appservices" {
source = "../Modules"
name_apptype = "AppServices"
}
These create a 2 resources groups with the values that you need, additionally you can remove the default value from the name_apptype variable.
If you want to create with the same module both resource groups you need to use count to iterate over an array of names
I have following structure:
modules
|_ test1
| |_vpc.tf
|_test2
|_subnet.tf
I have created a vpc in test1/vpc.tf
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
}
I am getting vpc id in output like:
output "vpc_id" {
value = aws_vpc.main.id
}
How can I pass this id to test2/subnet.tf file? I am searching online and can't seem to find an answer for this.
Create a variable in subnet.tf:
variable "vpc_id" {
type = string
}
Then in your main terraform file where you are utilizing both of these modules, you would take the output from the vpc module and pass it to the input of the subnet module:
module "vpc" {
source = "modules/test1"
}
module "subnet" {
source = "modules/test2"
vpc_id = module.vpc.vpc_id
}
I'm trying to setup some IaC for a new project using Hashicorp Terraform on AWS. I'm using modules because I want to be able to reuse stuff across multiple environments (staging, prod, dev, etc.)
I'm struggling to understand where I have to set an output variable within a module, and how I then use that in another module. Any pointers to this would be greatly appreciated!
I need to use some things created in my VPC module (subnet IDs) when creating EC2 machines. My understanding is that you can't reference something from one module in another, so I am trying to use an output variable from the VPC module.
I have the following in my site main.tf
module "myapp-vpc" {
source = "dev/vpc"
aws_region = "${var.aws_region}"
}
module "myapp-ec2" {
source = "dev/ec2"
aws_region = "${var.aws_region}"
subnet_id = "${module.vpc.subnetid"}
}
dev/vpc simply sets some values and uses my vpc module:
module "vpc" {
source = "../../modules/vpc"
aws_region = "${var.aws_region}"
vpc-cidr = "10.1.0.0/16"
public-subnet-cidr = "10.1.1.0/24"
private-subnet-cidr = "10.1.2.0/24"
}
In my vpc main.tf, I have the following at the very end, after the aws_vpc and aws_subnet resources (showing subnet resource):
resource "aws_subnet" "public" {
vpc_id = "${aws_vpc.main.id}"
map_public_ip_on_launch = true
availability_zone = "${var.aws_region}a"
cidr_block = "${var.public-subnet-cidr}"
}
output "subnetid" {
value = "${aws_subnet.public.id}"
}
When I run terraform plan I get the following error message:
Error: module 'vpc': "subnetid" is not a valid output for module "vpc"
Outputs need to be passed up through each module explicitly each time.
For example if you wanted to output a variable to the screen from a module nested below another module you would need something like this:
child-module.tf
output "child_foo" {
value = "foobar"
}
parent-module.tf
module "child" {
source = "path/to/child"
}
output "parent_foo" {
value = "${module.child.child_foo}"
}
main.tf
module "parent" {
source = "path/to/parent"
}
output "main_foo" {
value = "${module.parent.parent_foo}"
}