Skip to content

Commit

Permalink
fix: support launch templates references which use prefix (#3069)
Browse files Browse the repository at this point in the history
This PR adds support for launch templates which are referenced by `name` in
a resource but use a `prefix` to launch. This means that the `name` attribute
can be `null` and prior to this change, references would not work. This change
adds a Infracost generated `name` if it is detected that the `launch_template`
has a `null` name.
  • Loading branch information
hugorut committed May 15, 2024
1 parent 33fea20 commit 5df9774
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 12 deletions.
32 changes: 26 additions & 6 deletions internal/hcl/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -1359,15 +1359,35 @@ var (
defaultGCPRegion = "us-central1"

blockValueFuncs = map[string]BlockValueFunc{
"data.aws_availability_zones": awsAvailabilityZonesValues,
"data.google_compute_zones": googleComputeZonesValues,
"data.aws_region": awsCurrentRegion,
"data.aws_default_tags": awsDefaultTagValues,
"resource.random_shuffle": randomShuffleValues,
"resource.time_static": timeStaticValues,
"data.aws_availability_zones": awsAvailabilityZonesValues,
"data.google_compute_zones": googleComputeZonesValues,
"data.aws_region": awsCurrentRegion,
"data.aws_default_tags": awsDefaultTagValues,
"resource.random_shuffle": randomShuffleValues,
"resource.time_static": timeStaticValues,
"resource.aws_launch_template": launchTemplateValues,
}
)

// launchTemplateValues returns the values for the launch template but if the
// name attribute is not set it will generate a unique name based on the block
// address. This is done to ensure that we can properly reference the launch
// template, when users uses the name-prefix attribute to set a name.
func launchTemplateValues(b *Block) cty.Value {
values := b.values()
launchTemplateData := values.AsValueMap()
v, ok := launchTemplateData["name"]

if !ok || v.IsNull() {
h := sha256.New()
h.Write([]byte(b.FullName()))
addressSha := hex.EncodeToString(h.Sum(nil))
launchTemplateData["name"] = cty.StringVal("hcl-" + addressSha)
}

return cty.ObjectVal(launchTemplateData)
}

// timeStaticValues mocks the values returned from resource.time_static which is
// a resource that returns the attributes of the provided rfc3339 time. If none
// is provided, it defaults to the current time.
Expand Down
5 changes: 4 additions & 1 deletion internal/providers/terraform/aws/eks_node_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/shopspring/decimal"

"github.com/infracost/infracost/internal/config"
"github.com/infracost/infracost/internal/schema"
"github.com/infracost/infracost/internal/testutil"

Expand All @@ -17,7 +18,9 @@ func TestEKSNodeGroupGoldenFile(t *testing.T) {
t.Skip("skipping test in short mode")
}

tftest.GoldenFileResourceTests(t, "eks_node_group_test")
tftest.GoldenFileHCLResourceTestsWithOpts(t, "eks_node_group_test", tftest.DefaultGoldenFileOptions(), func(ctx *config.RunContext) {
ctx.Config.GraphEvaluator = true
})
}

func TestEKSNodeGroup_spot(t *testing.T) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@
└─ block_device_mapping[0]
└─ Storage (general purpose SSD, gp2) 60 GB $6.00

aws_eks_node_group.example_with_launch_template_with_prefix
└─ aws_launch_template.prefix
├─ Instance usage (Linux/UNIX, on-demand, m5.large) 2,190 hours $210.24
├─ EBS-optimized usage 2,190 hours $0.00
├─ Inference accelerator (eia1.medium) 2,190 hours $284.70
└─ block_device_mapping[0]
└─ Storage (general purpose SSD, gp3) 300 GB $24.00

aws_eks_node_group.example_with_launch_template_3
└─ aws_launch_template.foo3
├─ Instance usage (Linux/UNIX, on-demand, m5.large) 2,190 hours $210.24
Expand Down Expand Up @@ -64,17 +72,17 @@
├─ Instance usage (Linux/UNIX, on-demand, t3.medium) 730 hours $30.37
└─ Storage (general purpose SSD, gp2) 20 GB $2.00

OVERALL TOTAL $2,762.37
OVERALL TOTAL $3,281.31

*Usage costs can be estimated by updating Infracost Cloud settings, see docs for other options.

──────────────────────────────────
16 cloud resources were detected:
11 were estimated
5 were free
18 cloud resources were detected:
12 were estimated
6 were free

┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ Project ┃ Baseline cost ┃ Usage cost* ┃ Total cost ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━╋━━━━━━━━━━━━┫
┃ main ┃ $2,762 ┃ $0.00 ┃ $2,762
┃ main ┃ $3,281 ┃ $0.00 ┃ $3,281
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━┻━━━━━━━━━━━━┛
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ provider "aws" {
secret_key = "mock_secret_key"
}

locals {
launch_template_name = aws_launch_template.prefix.name
}

resource "aws_eks_node_group" "example" {
cluster_name = "test_aws_eks_node_group"
node_group_name = "example"
Expand Down Expand Up @@ -341,6 +345,102 @@ resource "aws_eks_node_group" "example_with_launch_template_3" {
}
}

resource "aws_launch_template" "prefix" {
name = null
name_prefix = "prefix-"

block_device_mappings {
device_name = "/dev/sda1"

ebs {
volume_type = "gp3"
volume_size = 100
}
}

capacity_reservation_specification {
capacity_reservation_preference = "open"
}

cpu_options {
core_count = 4
threads_per_core = 2
}

credit_specification {
cpu_credits = "standard"
}

disable_api_termination = true

ebs_optimized = true

elastic_gpu_specifications {
type = "test"
}

elastic_inference_accelerator {
type = "eia1.medium"
}

iam_instance_profile {
name = "test"
}

image_id = "ami-test"

instance_initiated_shutdown_behavior = "terminate"

instance_type = "m5.xlarge"

kernel_id = "test"

key_name = "test"

license_specification {
license_configuration_arn = "arn:aws:license-manager:eu-west-1:123456789012:license-configuration:lic-0123456789abcdef0123456789abcdef"
}

metadata_options {
http_endpoint = "enabled"
http_tokens = "required"
http_put_response_hop_limit = 1
}

network_interfaces {
associate_public_ip_address = true
}

placement {
availability_zone = "us-west-2a"
}

ram_disk_id = "test"

vpc_security_group_ids = ["example"]

}

resource "aws_eks_node_group" "example_with_launch_template_with_prefix" {
cluster_name = "test_aws_eks_node_group"
node_group_name = "example"
node_role_arn = "node_role_arn"
subnet_ids = ["subnet_id"]

instance_types = ["m5.large"]

scaling_config {
desired_size = 3
max_size = 1
min_size = 1
}

launch_template {
name = local.launch_template_name
version = "default_version"
}
}

resource "aws_launch_template" "foo3" {
name = "foo3"

Expand Down

0 comments on commit 5df9774

Please sign in to comment.