terramate-io / terramate

Terramate CLI is an open-source Infrastructure as Code (IaC) Orchestration and Code Generation tool for Terraform, OpenTofu and Terragrunt.
https://terramate.io
Mozilla Public License 2.0
3.12k stars 86 forks source link

[BUG] "terramate generate" behaves differently on Ubuntu 22 x macOS Ventura 13.6 (22G120) #1686

Closed oieduardorabelo closed 2 months ago

oieduardorabelo commented 2 months ago

Describe the bug

i have the following terramate.tm.hcl in the root of my git repository:

terramate {
  required_version = "~> 0.8"
  config {
    disable_safeguards = ["git"]
  }
}

globals {
  infra_folder = "${terramate.root.path.fs.absolute}/infrastructure"
}

generate_hcl "__env.tf" {
  stack_filter {
    project_paths = ["infrastructure/my-app-stacks/*"]
  }

  lets {
    active_tenant_id    = tm_file("${global.infra_folder}/${let.project_name}/active-tenant-id")
    aws_accounts        = tm_jsondecode(tm_file("${global.infra_folder}/aws-accounts.json"))
    tenants             = tm_jsondecode(tm_file("${global.infra_folder}/terraform-tenants.json"))
    other_app_remote_state = tm_jsondecode(tm_file("${global.infra_folder}/terraform-other-app-remote-state.json"))

    project_name = "my-app-stacks"

    active_tenant             = let.tenants[let.active_tenant_id]
    active_tenant_aws_account = let.aws_accounts[let.active_tenant.aws_account_name]

    tenant = tm_merge(
      let.active_tenant,
      {
        aws_account_id : let.active_tenant_aws_account.id
        aws_provider_assume_role_arn : "arn:aws:iam::${let.active_tenant_aws_account.id}:role/${let.active_tenant_aws_account.assume_role}"
      }
    )
  }

  content {
    locals {
      tenant = let.tenant
    }

    terraform {
      backend "s3" {
        assume_role    = { role_arn = let.other_app_remote_state.assume_role.role_arn }
        bucket         = let.other_app_remote_state.bucket
        dynamodb_table = let.other_app_remote_state.dynamodb_table
        encrypt        = let.other_app_remote_state.encrypt
        key            = "terramate/${let.project_name}/${terramate.stack.name}/terraform.tfstate"
        region         = let.other_app_remote_state.region
      }
    }

    data "terraform_remote_state" "other_app" {
      backend = "s3"
      config = {
        assume_role    = { role_arn = let.other_app_remote_state.assume_role.role_arn }
        bucket         = let.other_app_remote_state.bucket
        dynamodb_table = let.other_app_remote_state.dynamodb_table
        encrypt        = let.other_app_remote_state.encrypt
        key            = "${let.tenant.aws_account_id}-${let.tenant.aws_account_region}-${let.tenant.name}-${let.tenant.stage}/tfstate"
        region         = let.other_app_remote_state.region
      }
    }
  }
}

Log Output

When I execute terramate generate in my local machine (macOS Ventura 13.6 (22G120))

The files are generated correctly

When I try to run terramate generate on Azure Pipelines using the Ubuntu 22.04 Runner

I receive the following errors:

Code generation report

Failures:

- /infrastructure/my-app-stacks/250-backend
    error: /home/vsts/work/1/s/terramate.tm.hcl:32,14-38,6: lets eval: undefined let tenant
    error: /home/vsts/work/1/s/terramate.tm.hcl:27,44-66: lets eval: let.active_tenant: eval expression: The given key does not identify an element in this collection value.
    error: /home/vsts/work/1/s/terramate.tm.hcl:28,33-85: lets eval: undefined let active_tenant_aws_account

- /infrastructure/my-app-stacks/300-frontend
    error: /home/vsts/work/1/s/terramate.tm.hcl:32,14-38,6: lets eval: undefined let tenant
    error: /home/vsts/work/1/s/terramate.tm.hcl:27,44-66: lets eval: let.active_tenant: eval expression: The given key does not identify an element in this collection value.
    error: /home/vsts/work/1/s/terramate.tm.hcl:28,33-85: lets eval: undefined let active_tenant_aws_account

Environment:

Works on:

Doesn't work on:

Additional context:

I can confirm all JSON files are present in the file system and the correct path in CI

I'm using terramate v0.8.1 installed via Linux Homebrew

export HOMEBREW_NO_INSTALL_CLEANUP=1
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
brew install terramate

I have tried to move the JSON to globals

or using multiple lets {}:

lets {
  active_tenant_id    = tm_file("${global.infra_folder}/${let.project_name}/active-tenant-id")
  aws_accounts        = tm_jsondecode(tm_file("${global.infra_folder}/aws-accounts.json"))
  tenants             = tm_jsondecode(tm_file("${global.infra_folder}/terraform-tenants.json"))
  other_app_remote_state = tm_jsondecode(tm_file("${global.infra_folder}/terraform-other-app-remote-state.json"))
}

lets {
  project_name = "my-app-stacks"

  active_tenant             = let.tenants[let.active_tenant_id]
  active_tenant_aws_account = let.aws_accounts[let.active_tenant.aws_account_name]

lets {
  tenant = tm_merge(
    let.active_tenant,
    {
      aws_account_id : let.active_tenant_aws_account.id
      aws_provider_assume_role_arn : "arn:aws:iam::${let.active_tenant_aws_account.id}:role/${let.active_tenant_aws_account.assume_role}"
    }
  )
}

But it doesn't work on Ubuntu 22

Any guidance is welcome! Thank you

oieduardorabelo commented 2 months ago

somehow the active_tenant_id had extra space when reading the file in Ubuntu

Using:

tm_trimspace(tm_file("${global.infra_folder}/${let.project_name}/active-tenant-id"))

Fixed the problem