How to set the terraform provider.other_region variable? - amazon-web-services

Looking at this example:
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/elasticache_global_replication_group
The secondary region is referencing the aws.other_region variable, however the aws provider spec does not have an 'other_region' field
When I try to set that manually to 'us-west-1' for example it fails with failed to install provider

other_region provider can be defined like.
provider "aws" {
region = "us-west-2"
}
provider "aws" {
alias = "other_region"
region = "us-west-1"
}
Then you can use it on resources like.
resource "aws_elasticache_replication_group" "secondary" {
provider = aws.other_region
replication_group_id = "example-secondary"
}

Related

How to fix Terraform Provider configuration not present

Using Terraform v1.2.5 I am attempting to deploy an AWS VPC Peer. However, the following code fails validation:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.1"
}
}
}
provider "aws" {
region = "us-east-1"
}
data "aws_vpc" "accepter" {
provider = aws.accepter
id = "${var.accepter_vpc_id}"
}
locals {
accepter_account_id = "${element(split(":", data.aws_vpc.accepter.arn), 4)}"
}
resource "aws_vpc_peering_connection" "requester" {
description = "peer_to_${var.accepter_profile}"
vpc_id = "{$var.requester_vpc_id}"
peer_vpc_id = "${data.aws_vpc.accepter.id}"
peer_owner_id = "${local.accepter_account_id}"
}
When validating this terraform code I am receiving the following error :
$ terraform validate
╷
│ Error: Provider configuration not present
│
│ To work with data.aws_vpc.accepter its original provider configuration at provider["registry.terraform.io/hashicorp/aws"].accepter is
│ required, but it has been removed. This occurs when a provider configuration is removed while objects created by that provider still exist
│ in the state. Re-add the provider configuration to destroy data.aws_vpc.accepter, after which you can remove the provider configuration
│ again.
What am I missing or misconfigured that is causing this error?
You need to provide the aliased provider version you are referencing here:
data "aws_vpc" "accepter" {
provider = aws.accepter # <--- missing aliased provider
id = var.accepter_vpc_id
}
To fix this, you just need to add the corresponding aliased provider block [1]:
provider "aws" {
alias = "accepter"
region = "us-east-1" # make sure the region is right
}
[1] https://developer.hashicorp.com/terraform/language/providers/configuration#alias-multiple-provider-configurations
Since VPC Peering is an "inter-region" Peering we need 2 AWS regions. Hence the way to achhieve this is creating AWS provider and AWS alias provider blocks.
See an example:
provider "aws" {
region = "us-east-1"
# Requester's credentials.
}
provider "aws" {
alias = "peer"
region = "us-west-2"
# Accepter's credentials.
}
Your resource doesn't know what provider to use, the one you provided does not exist.
You have two options:
Add alias to provider:
provider "aws" {
region = "us-east-1"
alias = "accepter"
}
remove line provider = aws.accepter from data "aws_vpc" "accepter"
Somehow, the first will be more valid for you, I suppose.

It is possible to store terraform state file in one aws account and deploy into another using environmental variables?

I would like to store a terraform state file in one aws account and deploy infrastructure into another. Is it possible to provide different set of credentials for backend and aws provider using environmental variables(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)? Or maybe provide credentials to one with environmental variables and another through shared_credentials_file?
main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "=3.74.3"
}
}
backend "s3" {
encrypt = true
bucket = "bucket-name"
region = "us-east-1"
key = "terraform.tfstate"
}
}
variable "region" {
default = "us-east-1"
}
provider "aws" {
region = "${var.region}"
}
resource "aws_vpc" "test" {
cidr_block = "10.0.0.0/16"
}
Yes, the AWS profile/access keys configuration used by the S3 backend are separate from the AWS profile/access keys configuration used by the AWS provider. By default they are both going to be looking in the same place, but you could configure the backend to use a different profile so that it connects to a different AWS account.
Yes, and you can even keep them in separated files in the same folder to avoid confusion
backend.tf
terraform {
backend "s3" {
profile = "profile-1"
region = "eu-west-1"
bucket = "your-bucket"
key = "terraform-state/terraform.tfstate"
dynamodb_table = "terraform-locks"
encrypt = true
}
}
main.tf
provider "aws" {
profile = "profile-2"
region = "us-east-1"
}
resource .......
This way, the state file will be stored in the profile-1, and all the code will run in the profile-2

Terraform - Multiple accounts with multiple environments (regions)

I am developing the infrastructure (IaC) I want to have in AWS with Terraform. To test, I am using an EC2 instance.
This code has to be able to be deployed across multiple accounts and **multiple regions (environments) per developer **. This is an example:
account-999
developer1: us-east-2
developer2: us-west-1
developerN: us-east-1
account-666:
Staging: us-east-1
Production: eu-west-2
I've created two .tfvars variables, account-999.env.tfvars and account-666.env.tfvars with the following content:
profile="account-999" and profile="account-666" respectively
This is my main.tf which contains the aws provider with the EC2 instance:
provider "aws" {
version = "~> 2.0"
region = "us-east-1"
profile = var.profile
}
data "aws_ami" "ubuntu" {
most_recent = true
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["099720109477"]
}
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
instance_type = "t3.micro"
tags = {
Name = "HelloWorld"
}
}
And the variable.tf file:
variable "profile" {
type=string
}
variable "region" {
description = "Region by developer"
type = map
default = {
developer1 = "us-west-2"
developer2 = "us-east-2"
developerN = "ap-southeast-1"
}
}
But I'm not sure if I'm managing it well. For example, the region variable only contains the values of the account-999 account. How can I solve that?
On the other hand, with this structure, would it be possible to implement modules?
You could use a provider alias to accomplish this. More info about provider aliases can be found here.
provider "aws" {
region = "us-east-1"
}
provider "aws" {
alias = "west"
region = "us-west-2"
}
resource "aws_instance" "foo" {
provider = aws.west
# ...
}
Another way to look at is, is by using terraform workspaces. Here is an example:
terraform workspace new account-999
terraform workspace new account-666
Then this is an example of your aws credentials file:
[account-999]
aws_access_key_id=xxx
aws_secret_access_key=xxx
[account-666]
aws_access_key_id=xxx
aws_secret_access_key=xxx
A reference to that account can be used within the provider block:
provider "aws" {
region = "us-east-1"
profile = "${terraform.workspace}"
}
You could even combine both methods!

create the vpc flow log from terraform in existing environment

I am new to terraform and still learing.
I know there is way you can import your existing infrastructure to terraform and have the state file created. But As if now I have multiple AWS accounts and multiple regions in those accounts which have multiple VPCs.
My task is to create vpc flow log through terraform.
Is it possible?
If it is, could you please help me or direct me how to get this thing done.
It is possible, albeit a little messy. You will need to create a provider block (with a unique alias) for each account/region combination you have (you can use profiles but I think roles is best), and select those providers in your resources appropriately.
provider "aws" {
alias = "acct1uswest2"
region = "us-west-2"
assume_role {
role_arn = "arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME"
}
}
provider "aws" {
alias = "acct2useast1"
region = "us-east-1"
assume_role {
role_arn = "arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME"
}
}
resource "aws_flow_log" "flow1" {
provider = aws.acct1uswest2
vpc_id = "vpc id in account 1" # you mentioned the vpc already exists, so you can either import the vpc and reference it's .id attribute here, or just put the id here as a string
...
}
resource "aws_flow_log" "flow2" {
provider = aws.acct2useast1
vpc_id = "vpc id in account 2"
...
}
Suggest you read up on importing resources (and the implications) here
More on multiple providers here

Terraform multiple region aws_ses_domain_identity

I want to create a aws_ses_domain_identity resource in multiple regions but as far as I can see, this is only possible by changing the region of the AWS provider.
I've attempted to use a for_each with no luck. I then want to create a aws_route53_record from the verification_tokens. I suspect this also won't work.
Ultimately, I'm aiming for creating an SES domain identity and corresponding Route 53 verification records for the regions specified in a variable (ses_regions).
Code:
provider "aws" {
alias = "eu-central-1"
region = "eu-central-1"
}
provider "aws" {
alias = "us-west-2"
region = "us-west-2"
}
variable "ses_regions" {
description = "The aws region in which to operate"
default = {
region1 = "us-west-2"
region2 = "eu-central-1"
}
}
resource "aws_ses_domain_identity" "example" {
for_each = var.ses_regions
provider = each.value
domain = var.ses_domain
}
resource "aws_route53_record" "example_amazonses_verification_record" {
for_each = aws_ses_domain_identity.example.verification_token
zone_id = var.zone_id
name = "_amazonses.${var.ses_domain}"
type = "TXT"
ttl = "600"
records = each.value
}
Error:
Error: Invalid provider configuration reference
on .terraform/modules/ses/main.tf line 8, in resource "aws_ses_domain_identity" "example":
8: provider = aws.each.value
The provider argument requires a provider type name, optionally followed by a
period and then a configuration alias.