Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE] Command to get stack ID #1960

Open
AJCandfield opened this issue Nov 19, 2024 · 6 comments
Open

[FEATURE] Command to get stack ID #1960

AJCandfield opened this issue Nov 19, 2024 · 6 comments
Labels
enhancement New feature or request

Comments

@AJCandfield
Copy link

Feature Request

I would like there to be a way of extracting the stack ID so it can be used in other parts of the IAC tool stack.

Describe the solution you'd like

This could be done in different ways, either via a terramate command, or with the ability to write the stack.tm.hcl file in a parseable format, like json or yaml.

Example via command flag:

terramate -C path/to/stack get id

Example via file:

terramate create --all-terragrunt --format=json
{
  "id": "foo",
  "name": "bar"
}
locals {
  stack_id = jsondecode("path/to/stack").id
}

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context

I would like to adopt the state management approach introduced by terramate where state files are stored in a flat folder structure by stack ID, while also using terragrunt.

remote_state {
  backend = "gcs"

  config = {
    project  = local.project_id
    bucket   = "${local.project_id}-tf-states"
    location = "europe-west2"
    # prefix   = "${basename(get_parent_terragrunt_dir())}/${path_relative_to_include()}" <== current
    # prefix   = local.stack_id <== I would like to use that information here <== desired
    gcs_bucket_labels = {
      project = local.project_id
      name    = "${local.project_id}-tf-states"
    }
  }

  generate = {
    path      = "_backend.tf"
    if_exists = "overwrite_terragrunt"
  }
}
@AJCandfield AJCandfield added the enhancement New feature or request label Nov 19, 2024
@soerenmartius
Copy link
Contributor

Do you orchestrate Terragrunt with Terramate? If so you could pass the stack.id at runtime, e.g. terramate run --eval -- bash -c 'TF_VAR_stack_id=/${terramate.stack.id} env | grep TF_VAR_stack_id'.

Other than that, a potential workaround for now would be just to use generate_file to generate a file e.g. metadata.json in each stack directory containing the ID and whatever other metadata you might want to parse with jsondecode.

For example, the following code generation snipped will generate the above mentioned approach:

generate_file "metadata.json" {
  content = tm_jsonencode({
    stack_id = terramate.stack.id
  })
}

@soerenmartius
Copy link
Contributor

terramate -C path/to/stack get id

Something like this sounds like a good idea, especially taking into consideration that terramate debug show metadata -C some/path currently not only returns the targeted stack but also all nested stacks

@AJCandfield
Copy link
Author

Do you orchestrate Terragrunt with Terramate? If so you could pass the stack.id at runtime, e.g. terramate run --eval -- bash -c 'TF_VAR_stack_id=/${terramate.stack.id} env | grep TF_VAR_stack_id'.

Other than that, a potential workaround for now would be just to use generate_file to generate a file e.g. metadata.json in each stack directory containing the ID and whatever other metadata you might want to parse with jsondecode.

For example, the following code generation snipped will generate the above mentioned approach:

generate_file "metadata.json" {
  content = tm_jsonencode({
    stack_id = terramate.stack.id
  })
}

Yes, I'm using terramate for the orchestration part.

Can that snippet go in the main terramate.tm.hcl? If not, where would you recommend placing it? 😄

@soerenmartius
Copy link
Contributor

Do you orchestrate Terragrunt with Terramate? If so you could pass the stack.id at runtime, e.g. terramate run --eval -- bash -c 'TF_VAR_stack_id=/${terramate.stack.id} env | grep TF_VAR_stack_id'.
Other than that, a potential workaround for now would be just to use generate_file to generate a file e.g. metadata.json in each stack directory containing the ID and whatever other metadata you might want to parse with jsondecode.
For example, the following code generation snipped will generate the above mentioned approach:

generate_file "metadata.json" {
  content = tm_jsonencode({
    stack_id = terramate.stack.id
  })
}

Yes, I'm using terramate for the orchestration part.

Can that snippet go in the main terramate.tm.hcl? If not, where would you recommend placing it? 😄

Terramate configuration files(*.tm.hcl, *.tm*) that are on the same hierarchical level in your project structure are merged at compile time, very similar to how Terraform treats `.tf files at run-time. So in fact, it doesn't matter if you put it in the same file or separate it. I personally prefer separating my project configuration and code generation configurations.

For example, I would put the generate_file statement in a imports/generate_metadata.tm.hcl and import it at the root of your directory:

imports.tm.hcl

import {
    source = "/imports/*.tm.hcl"
}

But that's just my personal preference :)

@soerenmartius
Copy link
Contributor

Also don't forget to run terramate fmt or add it as a pre-commit hook to always keep your Terramate configuration files well formatted

@AJCandfield
Copy link
Author

The workaround you provided works! I added your block into my main terramate.tm.hcl file for now and the following into my terragrunt.hcl to use the stack ID to namespace the state files in my GCP backend:

locals {
  # We read the stack ID from the file created by terramate
  stack_id = try(jsondecode(file("${get_original_terragrunt_dir()}/metadata.json")).stack_id, "None")
}
remote_state {
  backend = "gcs"
  config = {
    # Every project will use a separate state bucket.
    project  = local.project_id
    bucket   = "${local.project_id}-tf-states"
    location = "europe-west2"
    prefix   = local.stack_id

    gcs_bucket_labels = {
      project = local.project_id
      name    = "${local.project_id}-tf-states"
    }
  }

  generate = {
    path      = "_backend.tf"
    if_exists = "overwrite_terragrunt"
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants