Terraform unable to import transit gateway route - amazon-web-services

I am trying to import an existing transit gateway route to my terraform project.
my setup is like this:
resource "aws_ec2_transit_gateway" "tgw" {
description = "gateway for vpn"
tags = {
"Name" = "openvpn-gateway"
"managed_by_terraform" = "true"
}
}
resource "aws_ec2_transit_gateway_vpc_attachment" "tgw-attachments-private-vpc" {
transit_gateway_id = aws_ec2_transit_gateway.tgw.id
vpc_id = var.private-vpc-id
subnet_ids = var.private-vpc-subnets
tags = {
"Name" = "private-vpc-gateway-attachment"
"managed_by_terraform" = "true"
}
}
resource "aws_ec2_transit_gateway_route_table" "tgw-route-table" {
transit_gateway_id = aws_ec2_transit_gateway.tgw.id
tags = {
"Name" = "openvpn-gateawy-route-table"
"managed_by_terraform" = "true"
}
}
resource "aws_ec2_transit_gateway_route" "private-vpc-route" {
destination_cidr_block = var.private-vpc-cidr
transit_gateway_attachment_id = aws_ec2_transit_gateway_vpc_attachment.tgw-attachments-private-vpc.id
transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.tgw-route-table.id
}
And this configuration is on a module named gateway, for the import command I tried:
terraform import
'module.gateway.aws_ec2_transit_gateway_route.private-vpc-route'
'tgw-rtb-xxx_10.0.0.0/16'
as the documentation says at this page: documantation
but I am getting the following error:
Error: Cannot import non-existent remote object │ │ While attempting
to import an existing object to
"module.gateway.aws_ec2_transit_gateway_route.private-vpc-route", the
provider detected that no object exists with the given id. Only
pre-existing objects can be imported; check that the id is correct and
that it is associated with the provider's configured region or │
endpoint, or use "terraform apply" to create a new remote object for
this resource.
I have double checked transit gateway route table id and destination cidr block and active region.
edit: This is how I use the module:
module "vpc" {
source = "../modules/vpc"
public-subnets-name = var.public-subnets-name
public-subnets-cidr = var.public-subnets-cidr
private-cidr = var.private-cidr
private-subnets-name = var.private-subnets-name
private-subnets-cidr = var.private-subnets-cidr
igw-id = module.gateway.igw-id
private-igw-id = module.gateway.private-igw-id
tg-id = module.gateway.tgw-id
pcx-id = var.pcx-id
nat-id = module.gateway.nat-id
development-private-vpc-cidr = var.development-private-vpc-cidr
}
module "gateway" {
source = "../modules/gateway"
public-vpc-id = module.vpc.public-vpc-id
public-vpc-cidr = var.public-cidr
private-vpc-id = module.vpc.private-vpc-id
private-vpc-cidr = var.private-cidr
nat-subnet = module.vpc.private-vpcs_public-subnet-id
nat-allocation = var.nat-allocation
private-vpc-subnets = module.vpc.private-vpc-subnet_ids
public-vpc-subnets = module.vpc.public-vpc-subnet_ids
}

Related

Terraform AWS: Cannot output VPC endpoints. Unsupported attribute

I cannot output vpc endpoints. I got
module.vpc-endpoints-oregon is an object. This object does not have an attribute named "endpoints".
In the modules/vpc_endpoints folder, there are three files,
main.tf outputs.tf variables.tf
cat modules/vpc_endpoints/main.tf
module "vpc_endpoints" {
source = "terraform-aws-modules/vpc/aws//modules/vpc-endpoints"
version = "3.16.0"
vpc_id = var.vpc_id
security_group_ids = [data.aws_security_group.default.id]
endpoints = {
s3 = {
service = "s3"
tags = { Name = "s3-vpc-endpoint" }
},
dynamodb = {
service = "dynamodb"
service_type = "Gateway"
route_table_ids = flatten([var.intra_route_table_ids,
var.private_route_table_ids,
var.public_route_table_ids])
policy = data.aws_iam_policy_document.dynamodb_endpoint_policy.json
tags = { Name = "dynamodb-vpc-endpoint" }
},
lambda = {
service = "lambda"
private_dns_enabled = true
subnet_ids = var.private_subnets
tags = { Name = "lambda-vpc-endpoint" }
},
}
}
cat modules/vpc_endpoints/outputs.tf
cat outputs.tf
# VPC endpoints
output "vpc_endpoints" {
description = "Array containing the full resource object and attributes for all endpoints created"
value = module.vpc_endpoints.endpoints
}
In the vpc_endpoints folder, there are three files,
main.tf outputs.tf variables.tf
cat main.tf
module "vpc-endpoints-oregon" {
source = "../../modules/vpc_endpoints"
#version = "3.16.0"
cluster_name = var.cluster_name
environment = var.environment
vpc_id = var.vpc_id
intra_route_table_ids = var.intra_route_table_ids
private_route_table_ids = var.private_route_table_ids
public_route_table_ids = var.public_route_table_ids
private_subnets = var.private_subnets
vpc_cidr_block = var.vpc_cidr_block
name_prefix = "vpc_tls"
}
cat outputs.tf:
output "vpc-endpoints-oregon" {
description = "Array containing the full resource object and attributes for all endpoints created"
value = module.vpc-endpoints-oregon.endpoints
}
terragrunt validate
Error: Unsupported attribute
on outputs.tf line 4, in output "vpc-endpoints-oregon":
4: value = module.vpc-endpoints-oregon.endpoints
module.vpc-endpoints-oregon is a object
This object does not have an attribute named "endpoints".
ERRO[0002] Terraform invocation failed in path-to/vpc_endpoints
ERRO[0002] 1 error occurred:
* exit status 1
Why does it claim This object does not have an attribute named "endpoints"?
The output is called vpc_endpoints, not endpoints. So it should be:
value = module.vpc-endpoints-oregon.vpc_endpoints

The subnet does not exist error in terraform

I want to create elastic beanstalk with tf. Here is the main.tf
resource "aws_elastic_beanstalk_application" "elasticapp" {
name = var.elasticapp
}
resource "aws_elastic_beanstalk_environment" "beanstalkappenv" {
name = var.beanstalkappenv
application = aws_elastic_beanstalk_application.elasticapp.name
solution_stack_name = var.solution_stack_name
tier = var.tier
setting {
namespace = "aws:ec2:vpc"
name = "VPCId"
value = var.vpc_id
}
setting {
namespace = "aws:ec2:vpc"
name = "Subnets"
value = var.public_subnets
}
setting {
namespace = "aws:elasticbeanstalk:environment:process:default"
name = "MatcherHTTPCode"
value = "200"
}
setting {
namespace = "aws:elasticbeanstalk:environment"
name = "LoadBalancerType"
value = "application"
}
setting {
namespace = "aws:autoscaling:launchconfiguration"
name = "InstanceType"
value = "t2.micro"
}
setting {
namespace = "aws:ec2:vpc"
name = "ELBScheme"
value = "internet facing"
}
setting {
namespace = "aws:autoscaling:asg"
name = "MinSize"
value = 1
}
setting {
namespace = "aws:autoscaling:asg"
name = "MaxSize"
value = 2
}
setting {
namespace = "aws:elasticbeanstalk:healthreporting:system"
name = "SystemType"
value = "enhanced"
}
}
I have variables defined in vars.tf.
This is the provider.tf
provider "aws" {
region = "eu-west-3"
}
When I try to apply I get the following message
Error: ConfigurationValidationException: Configuration validation exception: Invalid option value: 'subnet-xxxxxxxxxxxxxxx' (Namespace: 'aws:ec2:vpc', OptionName: 'ELBSubnets'): The subnet 'subnet-xxxxxxxxxxxxxxx' does not exist.
│ status code: 400, request id: be485042-a653-496b-8510-b310d5796eef
│
│ with aws_elastic_beanstalk_environment.beanstalkappenv,
│ on main.tf line 9, in resource "aws_elastic_beanstalk_environment" "beanstalkappenv":
│ 9: resource "aws_elastic_beanstalk_environment" "beanstalkappenv" {
I created the subnet inside the vpc that I provided in main.tf.
EDIT: I have only one subnet.
EDIT: adding vars.tf
variable "elasticapp" {
default = "pos-eb"
}
variable "beanstalkappenv" {
type = string
default = "pos-eb-env"
}
variable "solution_stack_name" {
type = string
default = "64bit Amazon Linux 2 v3.2.0 running Python 3.8"
}
variable "tier" {
type = string
default = "WebServer"
}
variable "vpc_id" {
default = "vpc-xxxxxxxxxxx"
}
variable "public_subnets" {
type = string
default = "subnet-xxxxxxxxxxxxxxx"
}
Ok, so first, check if the error message is correct.
As mentioned above, there is a chance you are working in the wrong account/region.
So check if terraform can find that subnet by using a datasource:
data "aws_subnet" "selected" {
id = var.public_subnets # based on your code above, this is a single subnet_id
}
output "subnet_detail" {
value = data.aws_subnet.selected
}
If the above code fails, that means terraform is not able to use/find that subnet.
So, if the subnet was created by terraform there is a chance regions/alias/account got mixed on the way to this module.
If it was manually created and you are only using the ID as manually inputted string, than the chances are that you copied the wrong subnet_id, vpc_id or that you are working in the wrong account/region.
If the above return data, and terraform can indeed find that subnet, check if it belongs to the VPC you are using on elastic_beanstalk.
If all the above is correct, than the issue may by in the "aws_elastic_beanstalk_environment" definition.
As you have an ELBScheme but you don't have the rest of the fields related to that ELB it could be throwing an error.
Since ELBSubnets was not provided in the "aws_elastic_beanstalk_environment" definition, it may be trying to use a default subnet from the default vpc.

Terraform: get account id for provider + for_each + account module

I'm trying to create multiple AWS Accounts in an Organization containing ressources.
The resources should owned by the created accounts.
for that I created a module for the accounts:
resource "aws_organizations_account" "this" {
name = var.customer
email = var.email
parent_id = var.parent_id
role_name = "OrganizationAccountAccessRole"
provider = aws.src
}
resource "aws_s3_bucket" "this" {
bucket = "exconcept-terraform-state-${var.customer}"
provider = aws.dst
depends_on = [
aws_organizations_account.this
]
}
output "account_id" {
value = aws_organizations_account.this.id
}
output "account_arn" {
value = aws_organizations_account.this.arn
}
my provider file for the module:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
configuration_aliases = [ aws.src, aws.dst ]
}
}
}
In the root module I'm calling the module like this:
module "account" {
source = "./modules/account"
for_each = var.accounts
customer = each.value["customer"]
email = each.value["email"]
# close_on_deletion = true
parent_id = aws_organizations_organizational_unit.testing.id
providers = {
aws.src = aws.default
aws.dst = aws.customer
}
}
Since the provider information comes from the root module, and the accounts are created with a for_each map, how can I use the current aws.dst provider?
Here is my root provider file:
provider "aws" {
region = "eu-central-1"
profile = "default"
alias = "default"
}
provider "aws" {
assume_role {
role_arn = "arn:aws:iam::${module.account[each.key].account_id}:role/OrganizationAccountAccessRole"
}
alias = "customer"
region = "eu-central-1"
}
With Terraform init I got this error:
Error: Cycle: module.account.aws_s3_bucket_versioning.this, module.account.aws_s3_bucket.this, provider["registry.terraform.io/hashicorp/aws"].customer, module.account.aws_s3_bucket_acl.this, module.account (close)

Error - Missing resource instance key : Because google_compute_instance has "count" set, its attributes must be accessed on specific instances

I am trying to pass mat_ip of google compute instances created in module "microservice-instance" to another module "database". Since I am creating more than one instance, I am getting following error for output variable in module "microservice-instance".
Error: Missing resource instance key
on modules/microservice-instance/ms-outputs.tf line 3, in output "nat_ip": 3: value = google_compute_instance.apps.network_interface[*].access_config[0].nat_ip
Because google_compute_instance.apps has "count" set, its attributes must be accessed on specific instances.
For example, to correlate with indices of a referring resource, use:
google_compute_instance.apps[count.index]
I have looked at following and using the same way of accessing attribute but its not working. Here is code -
main.tf
provider "google" {
credentials = "${file("../../service-account.json")}"
project = var.project
region =var.region
}
# Include modules
module "microservice-instance" {
count = var.appserver_count
source = "./modules/microservice-instance"
appserver_count = var.appserver_count
}
module "database" {
count = var.no_of_db_instances
source = "./modules/database"
nat_ip = module.microservice-instance.nat_ip
no_of_db_instances = var.no_of_db_instances
}
./modules/microservice-instance/microservice-instance.tf
resource "google_compute_instance" "apps" {
count = var.appserver_count
name = "apps-${count.index + 1}"
# name = "apps-${random_id.app_name_suffix.hex}"
machine_type = "f1-micro"
boot_disk {
initialize_params {
image = "ubuntu-os-cloud/ubuntu-1804-lts"
}
}
network_interface {
network = "default"
access_config {
// Ephemeral IP
}
}
}
./modules/microservice-instance/ms-outputs.tf
output "nat_ip" {
value = google_compute_instance.apps.network_interface[*].access_config[0].nat_ip
}
./modules/database/database.tf
resource "random_id" "db_name_suffix" {
byte_length = 4
}
resource "google_sql_database_instance" "postgres" {
name = "postgres-instance-${random_id.db_name_suffix.hex}"
database_version = "POSTGRES_11"
settings {
tier = "db-f1-micro"
ip_configuration {
dynamic "authorized_networks" {
for_each = var.nat_ip
# iterator = ip
content {
# value = ni.0.access_config.0.nat_ip
value = each.key
}
}
}
}
}
You are creating var.appserver_count number of google_compute_instance.apps resources. So you will have:
google_compute_instance.apps[0]
google_compute_instance.apps[1]
...
google_compute_instance.apps[var.appserver_count - 1]
Therefore, in your output, instead of:
output "nat_ip" {
value = google_compute_instance.apps.network_interface[*].access_config[0].nat_ip
}
you have to reference individual apps resources or all of them using [*], for example:
output "nat_ip" {
value = google_compute_instance.apps[*].network_interface[*].access_config[0].nat_ip
}

Terraform GCP - NAT Gateway not creating

Using terraform to create nat-gateway using this module.
https://registry.terraform.io/modules/GoogleCloudPlatform/nat-gateway/google/1.1.3
using this code :
module "nat" {
source = "GoogleCloudPlatform/nat-gateway/google"
region = "${var.gcloud-region}"
network = "${google_compute_network.vpc-network.name}"
subnetwork = "${google_compute_subnetwork.vpc-subnetwork-public.name}"
machine_type = "${var.vm-type-nat-gateway}"
}
Other snippets :
variable "gcloud-region" { default = "europe-west1" }
variable "vm-type-nat-gateway" { default = "n1-standard-2"}
resource "google_compute_network" "vpc-network" {
name = "foobar-vpc-network"
auto_create_subnetworks = false
}
resource "google_compute_subnetwork" "vpc-subnetwork-public" {
name = "foobar-vpc-subnetwork-public"
ip_cidr_range = "10.0.1.0/24"
network = "${google_compute_network.vpc-network.self_link}"
region = "${var.gcloud-region}"
private_ip_google_access = false
}
================
module.nat.google_compute_route.nat-gateway: 1 error(s) occurred:
module.nat.google_compute_route.nat-gateway: element: element() may not be used with an empty list in:
${element(split("/", element(module.nat-gateway.instances[0], 0)),
10)}
Above errror coming up and whole terraform script get stop , and unable to run
terraform apply or terraform destroy at any changes,
any possible issue causing this ?