Skip to content

Instantly share code, notes, and snippets.

@huynhbaoan
Last active December 8, 2024 17:16
Show Gist options
  • Save huynhbaoan/ec6b23c0744c1e3b52ac90b1ce276be1 to your computer and use it in GitHub Desktop.
Save huynhbaoan/ec6b23c0744c1e3b52ac90b1ce276be1 to your computer and use it in GitHub Desktop.
provider "aws" {
alias = "ap_southeast_2"
region = "ap-southeast-2"
}
provider "aws" {
alias = "ap_southeast_4"
region = "ap-southeast-4"
}
variable "service_account_id" {
description = "The AWS account ID of the service account that owns the source AMI"
type = string
}
variable "source_ami_id" {
description = "The ID of the source AMI in ap-southeast-2"
type = string
}
variable "source_ami_suffix" {
description = "Unique suffix to append to the copied AMI name"
type = string
default = "latest"
}
data "aws_amis" "matching_amis" {
provider = aws.ap_southeast_4
owners = [var.service_account_id]
filter {
name = "name"
values = ["copied-ami-*"] # Replace with your naming convention pattern
}
}
locals {
# Filter the AMIs and ensure we only work with non-null creation dates
sorted_amis = [
for ami in data.aws_amis.matching_amis.images :
ami if ami.creation_date != null
]
# Get the latest AMI by sorting on creation date
latest_ami = length(local.sorted_amis) > 0 ? sort(local.sorted_amis, ami => ami.creation_date)[-1] : null
# Extract the ID of the latest AMI
latest_ami_id = local.latest_ami != null ? local.latest_ami.image_id : null
}
resource "aws_ami_copy" "copy_ami_to_ap_southeast_4" {
provider = aws.ap_southeast_4
count = local.latest_ami_id == null ? 1 : 0
name = "copied-ami-${var.source_ami_suffix}"
source_ami_id = var.source_ami_id
source_region = "ap-southeast-2"
tags = {
Environment = "POC"
Application = "YourApp"
}
}
output "latest_ami_id" {
value = local.latest_ami_id != null ? local.latest_ami_id : "No AMI found in ap-southeast-4"
}
output "ami_copy_status" {
value = aws_ami_copy.copy_ami_to_ap_southeast_4.count > 0 ? "AMI copied to ap-southeast-4" : "No copy needed, AMI already exists"
}
# Data source to get the IDs of all matching AMIs in Melbourne region
data "aws_ami_ids" "melbourne_ami_ids" {
provider = aws.cfpocnpnonprod_mel
owners = ["803264201466"] # Replace with correct service account ID
filter {
name = "name"
values = ["hip-hui-rhelarm-9-copied-AMI-from-Sydney*"] # Adjust pattern as needed
}
}
# Fetch details for each AMI ID
data "aws_ami" "melbourne_amis" {
count = length(data.aws_ami_ids.melbourne_ami_ids.ids)
provider = aws.cfpocnpnonprod_mel
ami_id = data.aws_ami_ids.melbourne_ami_ids.ids[count.index]
}
# Local variables for processing
locals {
# Filter valid AMIs with a creation_date and sort by creation_date
valid_amis = [
for ami in data.aws_ami.melbourne_amis :
ami if ami.creation_date != null
]
sorted_amis = sort_by(local.valid_amis, "creation_date", "desc")
latest_ami = length(local.sorted_amis) > 0 ? local.sorted_amis[0] : null
latest_ami_id = local.latest_ami != null ? local.latest_ami.id : null
}
# Resource to copy AMI to Melbourne region if it doesn't exist
resource "aws_ami_copy" "melbourne_ami" {
provider = aws.cfpocnpnonprod_mel
count = local.latest_ami_id == null ? 1 : 0
name = "hip-hui-rhelarm-9-copied-AMI-from-Sydney"
description = "hip-hui-rhelarm-9 AMI copied from Sydney to Melbourne"
source_ami_id = var.ami_id
source_ami_region = "ap-southeast-2"
tags = {
Name = "hip-hui-rhelarm-9-copied-AMI-from-Sydney"
SourceAMI = var.ami_id
SourceOwner = "803264201466" # Replace with service account ID
}
}
# Outputs
output "latest_ami_id" {
value = local.latest_ami_id != null ? local.latest_ami_id : "No AMI found in Melbourne region"
}
output "ami_copy_status" {
value = aws_ami_copy.melbourne_ami.count > 0 ? "AMI copied to Melbourne region" : "No copy needed, AMI already exists"
}
Here’s the Terraform configuration split into three files: main.tf, variables.tf, and outputs.tf. This configuration deploys 10 EC2 instances (1 per eligible VPC).
main.tf
# Providers
provider "aws" {
alias = "cfpocnpnonprod_syd"
region = "ap-southeast-2"
assume_role {
role_arn = "arn:aws:iam::175808441602:role/AUR-Resource-AWS-cfpocnpnonprod-2FA-hip-admin"
}
}
provider "aws" {
alias = "cfpocnpnonprod_mel"
region = "ap-southeast-4"
assume_role {
role_arn = "arn:aws:iam::175808441602:role/AUR-Resource-AWS-cfpocnpnonprod-2FA-hip-admin"
}
}
# EC2 Instances for Sydney VPCs
module "sydney_internal_1_ec2" {
source = "../modules/tf_cloud_wan_engineering/compute_ec2"
vpc_id = module.sydney_internal_vpc_1.vpc_id
subnet_id = module.sydney_internal_vpc_1.subnet_a_id
instance_name = "sydney-internal-1-ec2"
ami_id = var.ami_id
instance_type = var.instance_type
volume_size = var.volume_size
}
module "sydney_internal_2_ec2" {
source = "../modules/tf_cloud_wan_engineering/compute_ec2"
vpc_id = module.sydney_internal_vpc_2.vpc_id
subnet_id = module.sydney_internal_vpc_2.subnet_a_id
instance_name = "sydney-internal-2-ec2"
ami_id = var.ami_id
instance_type = var.instance_type
volume_size = var.volume_size
}
module "sydney_external_1_ec2" {
source = "../modules/tf_cloud_wan_engineering/compute_ec2"
vpc_id = module.sydney_external_vpc_1.vpc_id
subnet_id = module.sydney_external_vpc_1.subnet_a_id
instance_name = "sydney-external-1-ec2"
ami_id = var.ami_id
instance_type = var.instance_type
volume_size = var.volume_size
}
module "sydney_protected_1_ec2" {
source = "../modules/tf_cloud_wan_engineering/compute_ec2"
vpc_id = module.sydney_protected_vpc_1.vpc_id
subnet_id = module.sydney_protected_vpc_1.subnet_a_id
instance_name = "sydney-protected-1-ec2"
ami_id = var.ami_id
instance_type = var.instance_type
volume_size = var.volume_size
}
module "sydney_sdwan_ec2" {
source = "../modules/tf_cloud_wan_engineering/compute_ec2"
vpc_id = module.sydney_sdwan_vpc.vpc_id
subnet_id = module.sydney_sdwan_vpc.subnet_a_id
instance_name = "sydney-sdwan-ec2"
ami_id = var.ami_id
instance_type = var.instance_type
volume_size = var.volume_size
}
# EC2 Instances for Melbourne VPCs
module "melbourne_internal_1_ec2" {
source = "../modules/tf_cloud_wan_engineering/compute_ec2"
providers = { aws = aws.cfpocnpnonprod_mel }
vpc_id = module.melbourne_internal_vpc_1.vpc_id
subnet_id = module.melbourne_internal_vpc_1.subnet_a_id
instance_name = "melbourne-internal-1-ec2"
ami_id = var.ami_id
instance_type = var.instance_type
volume_size = var.volume_size
}
module "melbourne_internal_2_ec2" {
source = "../modules/tf_cloud_wan_engineering/compute_ec2"
providers = { aws = aws.cfpocnpnonprod_mel }
vpc_id = module.melbourne_internal_vpc_2.vpc_id
subnet_id = module.melbourne_internal_vpc_2.subnet_a_id
instance_name = "melbourne-internal-2-ec2"
ami_id = var.ami_id
instance_type = var.instance_type
volume_size = var.volume_size
}
module "melbourne_external_1_ec2" {
source = "../modules/tf_cloud_wan_engineering/compute_ec2"
providers = { aws = aws.cfpocnpnonprod_mel }
vpc_id = module.melbourne_external_vpc_1.vpc_id
subnet_id = module.melbourne_external_vpc_1.subnet_a_id
instance_name = "melbourne-external-1-ec2"
ami_id = var.ami_id
instance_type = var.instance_type
volume_size = var.volume_size
}
module "melbourne_protected_1_ec2" {
source = "../modules/tf_cloud_wan_engineering/compute_ec2"
providers = { aws = aws.cfpocnpnonprod_mel }
vpc_id = module.melbourne_protected_vpc_1.vpc_id
subnet_id = module.melbourne_protected_vpc_1.subnet_a_id
instance_name = "melbourne-protected-1-ec2"
ami_id = var.ami_id
instance_type = var.instance_type
volume_size = var.volume_size
}
module "melbourne_sdwan_ec2" {
source = "../modules/tf_cloud_wan_engineering/compute_ec2"
providers = { aws = aws.cfpocnpnonprod_mel }
vpc_id = module.melbourne_sdwan_vpc.vpc_id
subnet_id = module.melbourne_sdwan_vpc.subnet_a_id
instance_name = "melbourne-sdwan-ec2"
ami_id = var.ami_id
instance_type = var.instance_type
volume_size = var.volume_size
}
variables.tf
# EC2 Instance Configuration Variables
variable "ami_id" {
description = "AMI ID for EC2 instances"
type = string
default = "ami-0de4f6f1540e50e93"
}
variable "instance_type" {
description = "Instance type for EC2"
type = string
default = "t4g.small"
}
variable "volume_size" {
description = "Volume size for the root block device in GB"
type = number
default = 20
}
outputs.tf
# Outputs for EC2 Instances
output "sydney_internal_1_instance_id" {
value = module.sydney_internal_1_ec2.instance_id
}
output "sydney_internal_2_instance_id" {
value = module.sydney_internal_2_ec2.instance_id
}
output "sydney_external_1_instance_id" {
value = module.sydney_external_1_ec2.instance_id
}
output "sydney_protected_1_instance_id" {
value = module.sydney_protected_1_ec2.instance_id
}
output "sydney_sdwan_instance_id" {
value = module.sydney_sdwan_ec2.instance_id
}
output "melbourne_internal_1_instance_id" {
value = module.melbourne_internal_1_ec2.instance_id
}
output "melbourne_internal_2_instance_id" {
value = module.melbourne_internal_2_ec2.instance_id
}
output "melbourne_external_1_instance_id" {
value = module.melbourne_external_1_ec2.instance_id
}
output "melbourne_protected_1_instance_id" {
value = module.melbourne_protected_1_ec2.instance_id
}
output "melbourne_sdwan_instance_id" {
value = module.melbourne_sdwan_ec2.instance_id
}
Summary
• 10 EC2 instances are deployed across eligible VPCs using t4g.small.
• Configuration is modular and organized for scalability.
• The variables are reusable, and the outputs are well-structured.
Let me know if you’d like further refinements!
# Security Group
resource "aws_security_group" "ec2_sg" {
name_prefix = "${var.instance_name}-sg-"
description = "Security group for EC2 instance"
vpc_id = var.vpc_id
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["172.16.0.0/16"]
description = "Allow SSH from internal network"
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
description = "Allow all outbound traffic"
}
tags = {
Name = "${var.instance_name}-sg"
LDAPAuthGroup = "NA"
CostCentre = "V_HIPServices"
ApplicationID = "APP-18672"
Environment = var.environment
SecurityAgentRequired = "no"
}
}
# EC2 Instance
resource "aws_instance" "ec2_instance" {
ami = var.ami_id
instance_type = var.instance_type
subnet_id = var.subnet_id
vpc_security_group_ids = [aws_security_group.ec2_sg.id]
root_block_device {
volume_size = var.volume_size
volume_type = "gp3"
}
tags = {
Name = var.instance_name
LDAPAuthGroup = "NA"
CostCentre = "V_HIPServices"
ApplicationID = "APP-18672"
Environment = var.environment
SecurityAgentRequired = "no"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment