Terraform: dynamic nested groups for EKS module - dynamic

I'm trying to configure EKS on different environments with Terraform AWS EKS module (https://registry.terraform.io/modules/terraform-aws-modules/eks/). Environments differ by number of EKS-managed node groups. I'm using list of objects to describe nodegroups in a varibale:
node_groups = [
{
"name" = "nodegroup_name"
"desired_capacity" = 1,
"max_capacity" = 3,
"min_capacity" = 1,
"subnets" = "internal",
"instance_types" = "r5.xlarge",
"k8s_labels" = {
NodeGroup = "internal"
}
}
]
And here's the module code for node groups definition:
for_each = { for node_group in var.node_groups : node_group.name => node_group }
eks_managed_node_groups = {
nodegroup={
name = each.key
desired_capacity = each.value.desired_capacity
max_capacity = each.value.max_capacity
min_capacity = each.value.min_capacity
subnets = each.value.subnets != "external" ? data.aws_subnets.eks_external_subnets.ids : data.aws_subnets.eks_internal_subnets.ids
instance_types = [each.value.instance_types]
source_security_group_ids = each.value.subnets != "external" ? [ aws_security_group.eks-external-sec-group.id ] : [ aws_security_group.eks-internal-sec-group.id ]
capacity_type = "ON_DEMAND"
k8s_labels = each.value.k8s_labels
additional_tags = local.tags
}
}
But terraform plan returns errors:
Error: Incorrect attribute value type
on ../../../modules/aws/eks/main.tf line 66, in data "aws_eks_cluster_auth" "this":
66: name = module.eks_remote.cluster_id
Inappropriate value for attribute "name": string required.
Error: Invalid function argument
on ../../../modules/aws/eks/main.tf line 101, in locals:
101: ${chomp(module.eks_remote.aws_auth_configmap_yaml)}
Invalid value for "str" parameter: string required.
And in logs I see a lot of the following messages:
[WARN] ReferenceTransformer: reference not found: "each.value"
Can somebody, please, help me with this?

Related

I am trying to add custom validation for variables in my terraform script using map but i am facing error

I am trying to add custom validation for the variables in my terraform script for S3 bucket. But i am facing an error that is mentioned as below:
Reference to undeclared input variable
on main.tf line 2, in resource "aws_s3_bucket" "gouth_bucket_1_apr_2021":
2: bucket = var.bucket #"terraform-s3-bucket"
An input variable with the name "bucket" has not been declared. This variable
can be declared with a variable "bucket" {} block."
Can anyone help me on the same.please let me know which file needs the necessary changes and how.
Thanks in Advance
Below is my code :
main.tf :
resource "aws_s3_bucket" "gouth_bucket_1_apr_2021" {
bucket = var.bucket
acl = "private"
tags= var.tags
}
s3.tfvars :
bucket = "first-bucket-gouth"
#Variables of Tags
tags= {
name = "s3bucket",
account_id = "1234567",
owner = "abc#def.com",
os= "windows",
backup = "N",
application = "abc",
description = "s3 bucket",
env = "dev",
ticketid = "101",
marketami = "NA",
patching = "NA",
dc = "bangalore"
}
validation.tf :
variable "tags" {
type = map(string)
validation {
condition = length(var.tags["env"]) > 0
error_message = "Environment tag is required !!"
}
validation {
condition = length(var.tags["owner"]) > 0
error_message = "Owner tag is required !!"
}
validation {
condition = length(var.tags["dc"]) > 0
error_message = "DC tag is required !!"
}
validation {
condition = can(var.tags["account_id"])
error_message = "Acoount ID tag is required!!"
}
}
I can see two potential issues.
You are referencing var.bucket in your resource, but you are not defining a variable for it anywhere in your definition. This could simply look like:
variable "bucket" {}
You may not be picking up your tfvars file, if you are running Terraform with the tfvars file as an option like so terraform plan -var-file=s3.tfvars then thats ok, or you can rename your tfvars file to something.auto.tfvars or terraform.tfvars to get automatically used. (See > https://www.terraform.io/docs/language/values/variables.html#variable-definitions-tfvars-files)
I hope this answers your question.

An argument named "instance_type" is not expected here...amongst other unexpected arguments

I've got some code form a Udemy course and it's giving the following errors. Can anybody point me in the right direction with this...it's probably really easy, but I'm really new to this to be honest.
Error: Unsupported argument
on lesson100.tf line 83, in module "ec2":
83: instance_type = "m4.large"
An argument named "instance_type" is not expected here.
Error: Unsupported argument
on lesson100.tf line 85, in module "ec2":
85: subnet_id = element(data.aws_subnet_ids.all.ids, 0)
An argument named "subnet_id" is not expected here.
Error: Unsupported argument
on lesson100.tf line 87, in module "ec2":
87: vpc_security_group_ids = ["${module.security_group.this_security_group_id}"]
An argument named "vpc_security_group_ids" is not expected here.
Error: Unsupported argument
on lesson100.tf line 89, in module "ec2":
89: associate_public_ip_address = true
An argument named "associate_public_ip_address" is not expected here.
the full code is
provider "aws" {
region = "eu-west-1"
}
##################################################################
# Data sources to get VPC, subnet, security group and AMI details
##################################################################
data "aws_vpc" "default" {
default = true
}
data "aws_subnet_ids" "all" {
vpc_id = data.aws_vpc.default.id
}
data "aws_ami" "amazon_linux" {
most_recent = true
filter {
name = "name"
values = [
"amzn-ami-hvm-*-x86_64-gp2",
]
}
filter {
name = "owner-alias"
values = [
"amazon",
]
}
}
module "security_group" {
source = "terraform-aws-modules/security-group/aws"
name = "example"
description = "Security group for example usage with EC2 instance"
vpc_id = data.aws_vpc.default.id
ingress_cidr_blocks = ["0.0.0.0/0"]
ingress_rules = ["http-80-tcp", "all-icmp"]
egress_rules = ["all-all"]
}
module "ec2" {
source = "../../"
instance_count = 2
name = "example-normal"
ami = data.aws_ami.amazon_linux.id
instance_type = "m4.large"
subnet_id = element(data.aws_subnet_ids.all.ids, 0)
vpc_security_group_ids = ["${module.security_group.this_security_group_id}"]
associate_public_ip_address = true
}
make sure that your ec2 module 4 variables are matching the 4 arguments you are passing:
associate_public_ip_address
vpc_security_group_ids
subnet_id
instance_type

how to associate floating ip address to a instance in openstack using terraform

I am using terraform to create couple of instances in openstack and I would like to automatically assign floatings ip address to them without any manual intervention.
My .tf file is as below:
resource "openstack_networking_floatingip_v2" "floating-ip" {
count = 4
pool = "floating-ip-pool"
}
resource "openstack_compute_floatingip_associate_v2" "fip-associate" {
floating_ip = openstack_networking_floatingip_v2.floating-ip.address[count.0]
instance_id = openstack_compute_instance_v2.terraform-vm.id[count.0]
}`
I am getting an error
"Error: Missing resource instance key
on image-provisioning.tf line 33, in resource "openstack_compute_floatingip_associate_v2" "fip-associate":
33: instance_id = openstack_compute_instance_v2.terraform-vm.id[count.0]"
My terraform version is : Terraform v0.12.24
+ provider.openstack 1.26.0
able to resolve using for_each option in terraform :
resource "openstack_compute_instance_v2" "terraform_vm" {
image_id = "f8b9189d-2518-4a32-b1ba-2046ea8d47fd"
for_each = var.instance_name
name = each.key
flavor_id = "3"
key_pair = "openstack vm key"
security_groups = ["default"]
network {
name = "webapps-network"
}
}
resource "openstack_networking_floatingip_v2" "floating_ip" {
pool = "floating-ip-pool"
for_each = var.instance_name
}
resource "openstack_compute_floatingip_associate_v2" "fip_associate" {
for_each = var.instance_name
floating_ip = openstack_networking_floatingip_v2.floating_ip[each.key].address
instance_id = openstack_compute_instance_v2.terraform_vm[each.key].id
}

Declaring list and map variable values in terraform.tfvars

I recently moved over the values for my variables within my terraform code to terraform.tfvars. I am now getting an error that is due to how I am declaring my list and map variables. The code where I am getting the error is replicated below:
image_id = var.web_amis[var.region]
this is how I have these variables specified in terraform.tfvars:
web_amis = ["ami-0dacb0c129b49f529", "ami-00068cd7555f543d5", ]
this is the error code I am getting:
Error: Invalid index
on autoscaling.tf line 3, in resource "aws_launch_configuration" "web_lc":
3: image_id = var.web_amis[var.region]
|----------------
| var.region is "us-east-2"
| var.web_amis is tuple with 2 elements
The given key does not identify an element in this collection value: a number
is required.
You're trying to access a list element with a non index key instead of by position.
What you probably want instead is to have your web_amis variable be a map that is keyed by the region name:
main.tf
variable "region" {}
variable "web_amis" {}
resource "foo_bar" "baz" {
# ...
image_id = var.web_amis[var.region]
}
terraform.tfvars
web_amis = {
us-east-2 = "ami-0dacb0c129b49f529"
us-west-2 = "ami-00068cd7555f543d5"
}
But, this is a very old school and inelegant way of doing things with Terraform nowadays. Instead you could use the aws_ami data source to look up the AMI for the region based on filters such as tags or the name of the AMI.
A basic example is given in the aws_instance resource documentation:
provider "aws" {
region = "us-west-2"
}
data "aws_ami" "ubuntu" {
most_recent = true
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-trusty-14.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["099720109477"] # Canonical
}
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
instance_type = "t2.micro"
tags = {
Name = "HelloWorld"
}
}

Terraform 0.12.5 | Bigquery table resource doesn't support external data configuration block

I'm creating a module to make easy to provision a BigQuery table in GCP.
My module is working, but now I'm trying to add the option to create the table based in external data, like a GCS bucket.
In the doc (https://www.terraform.io/docs/providers/google/r/bigquery_table.html#external_data_configuration) are saying this configuration is supported, but I get only this error:
Acquiring state lock. This may take a few moments...
Error: Unsupported block type
on ../../modules/bq_table/main.tf line 24, in resource "google_bigquery_table" "default":
24: external_data_configuration {
Blocks of type "external_data_configuration" are not expected here.
Im using the last Terraform version (0.12.5) and google provider v2.10.0 in Mac OS.
Here is my module code in HCL2:
resource "google_bigquery_table" "default" {
dataset_id = "${terraform.workspace}_${var.bq_dataset_id}"
table_id = "${terraform.workspace}_${var.bq_table_id}"
project = (var.project_id != "" ? var.project_id : null)
description = (var.bq_table_description != "" ? var.project_id : null)
expiration_time = (var.bq_table_expiration_time != null ? var.project_id : null)
friendly_name = (var.bq_table_name != "" ? var.project_id : null)
dynamic "external_data_configuration" {
for_each = var.bq_table_external_data_configuration
content {
autodetect = true
source_format = "NEWLINE_DELIMITED_JSON"
source_uris = [external_data_configuration.value]
}
}
time_partitioning {
type = "DAY"
field = var.bq_table_partition_field
}
labels = var.bq_table_labels
schema = (var.bq_table_schema != "" ? var.bq_table_schema : null)
dynamic "view" {
for_each = (var.bq_table_view_query != "" ? {query = var.bq_table_view_query} : {})
content {
query = view.value
}
}
depends_on = ["null_resource.depends_on"]
}
Above im using Dynamic blocks, but tried to use normally and the error is the same.
The for_each property inside your dynamic block expects an array value. Try wrapping the input variable in an array:
dynamic "external_data_configuration" {
for_each = var.bq_table_external_data_configuration ? [var.bq_table_external_data_configuration] : []
content {
autodetect = true
source_format = "NEWLINE_DELIMITED_JSON"
source_uris = [external_data_configuration.value]
}
}
Conditional blocks are still a bit of a hassle even after Terraform 0.12; read here for more.