From b85d0db69da5e20960da1b944bb0430c469cee7d Mon Sep 17 00:00:00 2001 From: oycyc Date: Sun, 4 Aug 2024 00:16:28 -0400 Subject: [PATCH 1/2] fix: instance type and architecture incompatiblity --- data.tf | 2 +- main.tf | 22 ++++++++++++++++++++++ variables.tf | 6 ++++++ versions.tf | 4 ++++ 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/data.tf b/data.tf index 54331a9..b244405 100644 --- a/data.tf +++ b/data.tf @@ -13,7 +13,7 @@ data "aws_ami" "amazon_linux_2023" { filter { name = "architecture" - values = ["x86_64"] + values = [var.architecture] } filter { diff --git a/main.tf b/main.tf index 792ba37..3d9df3c 100644 --- a/main.tf +++ b/main.tf @@ -1,3 +1,25 @@ +locals { + # Validate that only 'arm64' architecture is used with 'g' processor instances to ensure compatibility. + # https://docs.aws.amazon.com/ec2/latest/instancetypes/instance-type-names.html + is_instance_compatible = ( + # True if does not contain 'g' when architecture is x86_64 + (var.architecture == "x86_64" && !can(regex("g", var.instance_type))) || + # True if contains 'g' when architecture is arm64 + (var.architecture == "arm64" && can(regex("g", var.instance_type))) + ) +} + +resource "null_resource" "validate_instance_type" { + count = local.is_instance_compatible ? 0 : 1 + + lifecycle { + precondition { + condition = local.is_instance_compatible + error_message = "The instance_type must be compatible with the specified architecture. For x86_64, you cannot use instance types with ARM processors (e.g., t3, m5, c5). For arm64, use instance types with 'g' indicating ARM processor (e.g., t4g, c6g, m6g)." + } + } +} + module "role_label" { source = "cloudposse/label/null" version = "0.25.0" diff --git a/variables.tf b/variables.tf index 26b4a32..9f16f98 100644 --- a/variables.tf +++ b/variables.tf @@ -30,6 +30,12 @@ variable "ami" { description = "The AMI to use for the SSM Agent EC2 Instance. If not provided, the latest Amazon Linux 2023 AMI will be used. Note: This will update periodically as AWS releases updates to their AL2023 AMI. Pin to a specific AMI if you would like to avoid these updates." } +variable "architecture" { + description = "The architecture of the AMI (e.g., x86_64, arm64)" + type = string + default = "arm64" +} + variable "user_data" { default = < Date: Sun, 4 Aug 2024 11:46:53 -0400 Subject: [PATCH 2/2] fix: instance type and architecture incompatiblity + tests --- main.tf | 9 ++-- tests/main.tftest.hcl | 104 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+), 4 deletions(-) create mode 100644 tests/main.tftest.hcl diff --git a/main.tf b/main.tf index 3d9df3c..75ac7d0 100644 --- a/main.tf +++ b/main.tf @@ -1,11 +1,12 @@ locals { + instance_type_chars = split("", var.instance_type) # Validate that only 'arm64' architecture is used with 'g' processor instances to ensure compatibility. # https://docs.aws.amazon.com/ec2/latest/instancetypes/instance-type-names.html is_instance_compatible = ( - # True if does not contain 'g' when architecture is x86_64 - (var.architecture == "x86_64" && !can(regex("g", var.instance_type))) || - # True if contains 'g' when architecture is arm64 - (var.architecture == "arm64" && can(regex("g", var.instance_type))) + # True if does not contain 'g' in the third position when architecture is x86_64 + (var.architecture == "x86_64" && element(local.instance_type_chars, 2) != "g") || + # True if contains 'g' in the third position when architecture is arm64 + (var.architecture == "arm64" && element(local.instance_type_chars, 2) == "g") ) } diff --git a/tests/main.tftest.hcl b/tests/main.tftest.hcl new file mode 100644 index 0000000..95a358d --- /dev/null +++ b/tests/main.tftest.hcl @@ -0,0 +1,104 @@ +variables { + vpc_id = "vpc-12345678" + subnet_ids = ["subnet-12345678", "subnet-87654321"] + stage = "test" + namespace = "mp" + name = "ssm-agent" + region = "us-east-1" + availability_zones = ["us-east-1a"] + nat_gateway_enabled = true + ipv6_enabled = true +} + +### TESTING INSTANCE and ARCHITECTURE COMPATIBILITY ### +# https://docs.aws.amazon.com/ec2/latest/instancetypes/instance-type-names.html +# https://aws.amazon.com/ec2/instance-types/ + +# Test valid x86_64 instance type +run "valid_x86_64_instance" { + command = plan + + variables { + instance_type = "t3.micro" + architecture = "x86_64" + } + + assert { + condition = local.is_instance_compatible + error_message = "Expected instance type t3.micro to be compatible with x86_64 architecture" + } +} + +# Test valid arm64 instance type +run "valid_arm64_instance" { + command = plan + + variables { + instance_type = "t4g.micro" + architecture = "arm64" + } + + assert { + condition = local.is_instance_compatible + error_message = "Expected instance type t4g.micro to be compatible with arm64 architecture" + } +} + +# Test invalid x86_64 instance type (using arm64 instance type) +run "invalid_x86_64_instance" { + command = plan + + variables { + instance_type = "t4g.micro" + architecture = "x86_64" + } + + expect_failures = [ + null_resource.validate_instance_type + ] +} + +# Test invalid arm64 instance type (using x86_64 instance type) +run "invalid_arm64_instance" { + command = plan + + variables { + instance_type = "t3.micro" + architecture = "arm64" + } + + expect_failures = [ + null_resource.validate_instance_type + ] +} + +# Test edge case, where the 'g' is defined as the instance family rather than the processor family +# It has 'g' in the name, but it's still an x86_64 instance type because the 'g' is the instance family +run "graphics_instance_arm_incompatiblity_edge_case" { + command = plan + + variables { + instance_type = "g3s.xlarge" + architecture = "arm64" + } + + expect_failures = [ + null_resource.validate_instance_type + ] +} + +# Test edge case, where the 'g' is defined as the instance family rather than the processor family +# It has 'g' in the name, but it still is compatible with x86_64 since the 'g' is the instance family +run "graphics_instance_x86_compatibility_edge_case" { + command = plan + + variables { + instance_type = "g4dn.xlarge" + architecture = "x86_64" + } + + assert { + condition = local.is_instance_compatible + error_message = "Expected instance type g3s.xlarge to be compatible with x86_64 architecture" + } +}