Unknown resource referenced in variable with Terraform - terraform

I am a beginner to Terraform.
I am trying to execute following code from Terraform Getting started guide.
provider "aws" {
access_key = "${var.access_key}"
secret_key = "${var.secret_key}"
region = "${var.region}"
}
resource "aws_instance" "example" {
ami = "${lookup(var.amis, var.region)}"
instance_type = "t2.micro"
tags {
Name = "newprovisionerstest"
}
provisioner "local-exec" {
command = "echo ${aws_instance.example.public_ip} > ip_address.txt"
}
}
output "ip" {
value = "${aws_eip.ip.public_ip}"
}
When I run
terraform apply
or
terraform refresh
It gives following error:
Error: output 'ip': unknown resource 'aws_eip.ip' referenced in variable aws_eip.ip.public_ip
Why is it so? Is it because "aws_eip" resource is not declared anywhere?

Like you said it yourself, there is no aws_eip resource called ip.
If you use the
aws_instance.example.public_ip
it should work totally fine

Related

Create Resource group in Terraform in sequence

I want to create a resource group in Azure with the help of Terraform and while creating it, I want to follow a naming convention.
Let's say, I have created a resource group rg-dev-001 with the help of terraform. And if I run the terraform script again next time then It should create rg-dev-002. How can I achieve it in terraform?
resource "azurerm_resource_group" "example" {
name = "rg-dev-xxx"
location = "West Europe"
}
Please use the below code to create resource groups in sequence in Terraform :
terraform {
required_version = ">=0.12"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~>2.0"
}
}
}
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "rg" {
count = number of resource groups to be created
name = "rg-dev-00${count.index+1}"
location = "LocationName"
}

Terraform simple script says "Error: Error launching source instance: VPCIdNotSpecified: No default VPC for this user"

Getting started on Terraform. I am trying to provision an EC2 instance using the following .tf file. I have a default VPC already in my account in the AZ I am trying to provision the EC2 instance.
# Terraform Settings Block
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
#version = "~> 3.21" # Optional but recommended in production
}
}
}
# Provider Block
provider "aws" {
profile = "default"
region = "us-east-1"
}
# Resource Block
resource "aws_instance" "ec2demo" {
ami = "ami-c998b6b2"
instance_type = "t2.micro"
}
I do the following Terraform commands.
terraform init
terraform plan
terraform apply
aws_instance.ec2demo: Creating...
Error: Error launching source instance: VPCIdNotSpecified: No default VPC for this user. GroupName is only supported for EC2-Classic and default VPC.
status code: 400, request id: 04274b8c-9fc2-47c0-8d51-5b627e6cf7cc
on ec2-instance.tf line 18, in resource "aws_instance" "ec2demo":
18: resource "aws_instance" "ec2demo" {
As the error suggests, it doesn't find the default VPC in the us-east-1 region.
You can provide the subnet_id within your VPC to create your instance as below.
resource "aws_instance" "ec2demo" {
ami = "ami-c998b6b2"
instance_type = "t2.micro"
subnet_id = "subnet-0b1250d733767bafe"
}
I'm only create a Default VPC in AWS
AWS VPC
actions
create default VPC
it's done, you try again now
terraform plan
terraform apply
As of now if there is any default VPC available in the AWS account then using terraform resource aws_instance instance can be created without any network spec input.
Official AWS-terraform example:
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance#basic-example-using-ami-lookup
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id ## Or use static AMI ID for testing.
instance_type = "t3.micro"
}
The error message: Error: Error launching source instance: VPCIdNotSpecified: No default VPC for this user. states that the EC2 instance did not find any networking configuration in your terraform code where it needs to create the instance.
This is probably because of the missing default VPC in your AWS account and it seems that you are not passing any network config input to terraform resource.
Basically, you have two ways to fix this
Create a default VPC and then use the same code.
Document: https://docs.aws.amazon.com/vpc/latest/userguide/default-vpc.html#create-default-vpc
Another and better way would be to inject the network config to aws_instance resource. I have used the example from the official aws_instance resource. Feel free to update any attributes accordingly.
resource "aws_vpc" "my_vpc" {
cidr_block = "172.16.0.0/16"
tags = {
Name = "tf-example"
}
}
resource "aws_subnet" "my_subnet" {
vpc_id = aws_vpc.my_vpc.id
cidr_block = "172.16.10.0/24"
availability_zone = "us-west-2a"
tags = {
Name = "tf-example"
}
}
resource "aws_network_interface" "foo" {
subnet_id = aws_subnet.my_subnet.id
private_ips = ["172.16.10.100"]
tags = {
Name = "primary_network_interface"
}
}
resource "aws_instance" "foo" {
ami = "ami-005e54dee72cc1d00" # us-west-2
instance_type = "t2.micro"
network_interface {
network_interface_id = aws_network_interface.foo.id
device_index = 0
}
credit_specification {
cpu_credits = "unlimited"
}
}
Another way of passing network config to ec2 instance is to use subnet_id in aws_instance resource as suggested by others.
Are there probabilities that you deleted the default vpc, if u did u can recreate going to the VPC Section -> My Vpcs -> At the right corner you will see a dropdown called actions click and select create a default vpc
As the AWS announcement last year On August 15, 2022 we expect all migrations to be complete, with no remaining EC2-Classic resources present in any AWS account. From now on you will need to specify while you are creating any new resources the subnet_id and declare it inside your while creating.
Example :
resource "aws_instance" "test" {
ami = "ami-xxxxx"
instance_type = var.instance_type
vpc_security_group_ids = ["sg-xxxxxxx"]
subnet_id = "subnet-xxxxxx"

Terraform: Interpolation could be replaced by HCL2 expression

When I try to use interpolation syntax like this:
vpc_id = "${aws_vpc.prod-vpc.id}"
I get the suggestion in IntelliJ that "Interpolation could be replaced by HCL2 expression", so if I change the line into this:
vpc_id = "aws_vpc.prod-vpc.id"
and issue terraform apply, I get:
C:\tf_ptojects\aws\subnet>terraform apply -auto-approve
aws_subnet.prod-subnet: Creating...
aws_vpc.prod-vpc: Creating...
aws_vpc.prod-vpc: Creation complete after 2s [id=vpc-0cfb27255522bdf15]
Error: error creating subnet: InvalidVpcID.NotFound: The vpc ID 'aws_vpc.prod-vpc.id' does not exist
status code: 400, request id: dab3fb03-424d-4bf2-ace6-bef93a94ee9c
If I re-apply interpolation syntax and run terraform apply again, then the resources get deployed but I get the warning in Terraform, saying that interpolation-only expressions are deprecated:
Warning: Interpolation-only expressions are deprecated
on main.tf line 16, in resource "aws_subnet" "prod-subnet":
16: vpc_id = "${aws_vpc.prod-vpc.id}"
So TF is discouraging the use of interpolation syntax, yet issues an error if it's not used. Is it some kind of bug or something?
C:\tf_ptojects\aws\subnet>terraform -version
Terraform v0.14.4
+ provider registry.terraform.io/hashicorp/aws v3.25.0
Entire TF code for reference:
provider "aws" {
region = "eu-central-1"
}
resource "aws_vpc" "prod-vpc" {
cidr_block = "10.100.0.0/16"
tags = {
name = "production vpc"
}
}
resource "aws_subnet" "prod-subnet" {
cidr_block = "10.100.1.0/24"
vpc_id = "aws_vpc.prod-vpc.id"
tags = {
name = "prod-subnet"
}
}
You just have to get the id without using double quotes vpc_id = aws_vpc.prod-vpc.id because you are getting vpc id from the resource.
If you use the double quotes, it will be considered as a string and no evaluation will be done, and terraform will consider "aws_vpc.prod-vpc.id" as the id.
This is the corrected code:
provider "aws" {
region = "eu-central-1"
}
resource "aws_vpc" "prod-vpc" {
cidr_block = "10.100.0.0/16"
tags = {
name = "production vpc"
}
}
resource "aws_subnet" "prod-subnet" {
cidr_block = "10.100.1.0/24"
vpc_id = aws_vpc.prod-vpc.id
tags = {
name = "prod-subnet"
}
}
I had tested the above code snippet and it is working perfectly fine.

Default subnet not found

When I run terraform apply with the resource:
resource "aws_default_subnet" "my_az_default_subnet" {
availability_zone = "eu-north-1"
}
I get the error:
aws_default_subnet.learntf_default_subnet: Creating...
Error: Default subnet not found
even if the default VPC and subnet exists in the specified availability_zone "eu-north-1".
provider.tf:
provider "aws" {
access_key = var.aws_access_key
secret_key = var.aws_secret_key
region = "eu-north-1"
}
variables.tf:
variable "aws_access_key" {}
variable "aws_secret_key" {}
network.tf:
resource "aws_default_subnet" "learntf_default_subnet" {
availability_zone = "eu-north-1"
}
My mistake. It worked with.
resource "aws_default_subnet" "def_subnet" {
availability_zone = "eu-north-1a"
}

provisioner local-exec access to each.key

Terraform v0.12.6, provider.aws v2.23.0
Am trying to create two aws instances using the new for_each construct. Don't actually think this is an aws provider issue, more a terraform/for_each/provisioner issues.
Worked as advertised until I tried to add a local-exec provisioning step.
Don't know how to modify the local-exec example to work with the for.each variable. Am getting a terraform error about a cycle.
locals {
instances = {
s1 = {
private_ip = "192.168.47.191"
},
s2 = {
private_ip = "192.168.47.192"
},
}
}
provider "aws" {
profile = "default"
region = "us-east-1"
}
resource "aws_instance" "example" {
for_each = local.instances
ami = "ami-032138b8a0ee244c9"
instance_type = "t2.micro"
availability_zone = "us-east-1c"
private_ip = each.value["private_ip"]
ebs_block_device {
device_name = "/dev/sda1"
volume_size = 2
}
provisioner "local-exec" {
command = "echo ${aws_instance.example[each.key].public_ip} >> ip_address.txt"
}
}
But get this error.
./terraform apply
Error: Cycle: aws_instance.example["s2"], aws_instance.example["s1"]
Should the for_each each.key variable be expected to work in a provisioning step? There are other ways to get the public_ip later, by either using the testate file or querying aws given the instance ids, but accessing the resource variables within the local-exec provisioning would seem to come in handy in many ways.
Try using the self variable:
provisioner "local-exec" {
command = "echo ${self.public_ip} >> ip_address.txt"
}
Note to readers that resource-level for_each is a relatively new feature in Terraform and requires version >=0.12.6.

Resources