#atmos (2024-11)

2024-11-01

jose.amengual avatar
jose.amengual

with the atmos github actions I can plan/apply no problem but now I want to destroy and I do not have a count = module.this.enabled ? 1 : 0, how do you guys destroy? I will like to be able to find the delete yaml from the stack and destroy that one if possible

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

Interesting. So we are working on supporting an enabled flag for components.

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

The scope is not currently to destroy. However, it might be worth considering that.

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

In the current implementation, enabled would make the component “invisible”

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

an alternative to commenting it out.

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

I can see a component as having 3 states

• enabled

• disabled

• destroyed

jose.amengual avatar
jose.amengual

I think if the components are commented out or deleted from the stack file, describe affected should know what to do with it or output a destroyed flag or something like that for another job to use that matrix to destroy it

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

Ok, that makes sense.

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

So enabled = true/false affects the visibility, but removal from the configuration is visible via atmos describe affected

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

@Andriy Knysh (Cloud Posse) what happens today in describe affected if the component is removed? is that surfaced?

jose.amengual avatar
jose.amengual

I renamed a component from pepetest to pepetest1, describe affected saw the new pepetest1 component got deployed, but the old one is still there in the cloud environment

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

the key is do we have the information in describe affected JSON output

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

The right behavior might not be implemented, but maybe we have the data there to act on

1
Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)

if a component is removed, Atmos does not see it (it will not consider it affected) - this is the current implementation. This is b/c Atmos compares the current branch with a remote branch/tag/sha - if the current branch does not have the component, then it’s “not affected”.

Setting enabled: false is not “removal”, so describe affected sees that

jose.amengual avatar
jose.amengual

but with that, you need a two-step approach, one to say enable: false and then another PR to remove the yaml from the stack file

Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)

yes

Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)

i would say we didn’t consider a complete component removal with describe affected - we need to revisit this

1
Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

Added a task to the backlog

1

2024-11-02

github3 avatar
github3
10:28:40 PM

Improve terraform and helmfile help. Enable Go templating in the command field. Clean Terraform workspace before executing terraform init @aknysh (#759)

what

• Improve terraform and helmfile help • Enable Go templating in the command field of stack config • Clean Terraform workspace before executing terraform init

why

• Improve the help messages. When a user executes atmos terraform --help or atmos helmfile --help (or help for a subcommand), print a message describing the command and how to execute the terraform and helmfile help command
atmos terraform –help

image

• Enable Go templating in the command stack config in addition to the already supported sections.
You can now use Go templates in the following Atmos sections to refer to values in the same or other sections:
vars
settings
env
providers
overrides
backend
backend_type
component
metadata.component
command
Enabling Go templates in the command section allows specifying different Terraform/OpenTofu/Helmfile versions per component/stack, and get the value from different Atmos sections or from external data sources • Clean Terraform workspace before executing terraform init. When using multiple backends for the same component (e.g. separate backends per tenant or account), and if an Atmos command was executed that selected a Terraform workspace, Terraform will prompt the user to select one of the following workspaces:

  1. default
  2. The prompt forces the user to always make a selection (which is error-prone), and also makes it complicated when running on CI/CD. The PR adds the logic that deletes the `.terraform/environment` file from the component directory before executing `terraform init`. The `.terraform/environment` file contains the name of the currently selected workspace, helping Terraform identify the active workspace context for managing your infrastructure. We delete the file before executing `terraform init` to prevent the Terraform prompt asking to select the default or the previously used workspace.
Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

@jose.amengual another one for you

Improve terraform and helmfile help. Enable Go templating in the command field. Clean Terraform workspace before executing terraform init @aknysh (#759)

what

• Improve terraform and helmfile help • Enable Go templating in the command field of stack config • Clean Terraform workspace before executing terraform init

why

• Improve the help messages. When a user executes atmos terraform --help or atmos helmfile --help (or help for a subcommand), print a message describing the command and how to execute the terraform and helmfile help command
atmos terraform –help

image

• Enable Go templating in the command stack config in addition to the already supported sections.
You can now use Go templates in the following Atmos sections to refer to values in the same or other sections:
vars
settings
env
providers
overrides
backend
backend_type
component
metadata.component
command
Enabling Go templates in the command section allows specifying different Terraform/OpenTofu/Helmfile versions per component/stack, and get the value from different Atmos sections or from external data sources • Clean Terraform workspace before executing terraform init. When using multiple backends for the same component (e.g. separate backends per tenant or account), and if an Atmos command was executed that selected a Terraform workspace, Terraform will prompt the user to select one of the following workspaces:

  1. default
  2. The prompt forces the user to always make a selection (which is error-prone), and also makes it complicated when running on CI/CD. The PR adds the logic that deletes the `.terraform/environment` file from the component directory before executing `terraform init`. The `.terraform/environment` file contains the name of the currently selected workspace, helping Terraform identify the active workspace context for managing your infrastructure. We delete the file before executing `terraform init` to prevent the Terraform prompt asking to select the default or the previously used workspace.
jose.amengual avatar
jose.amengual

this feels like Xmas

2024-11-03

Kalman Speier avatar
Kalman Speier

hey folks, for some reason atmos generate wrong terraform workspace name, i have a component named nats and stack named dev and instead of dev-nats the workspace is simply dev what could cause that ?

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

Something is wrong with your name_pattern or name_template

Kalman Speier avatar
Kalman Speier

i didn’t change those.

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

Share your atmos config, if you can

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)
Customize Stack Behavior | atmos

Use the atmos.yaml to configure where Atmos will discover stack configurations.

Kalman Speier avatar
Kalman Speier
base_path: .

components:
  terraform:
    command: tofu
    base_path: components/terraform
    apply_auto_approve: false
    deploy_run_init: true
    init_run_reconfigure: true
    auto_generate_backend_file: true

stacks:
  base_path: stacks
  included_paths:
    - "deploy/**/*"
  excluded_paths:
    - "**/_defaults.yaml"
  name_pattern: "{stage}"

workflows:
  base_path: stacks/workflows

templates:
  settings:
    enabled: true
    sprig:
      enabled: true

logs:
  file: /dev/stderr
  level: Info
Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

Ok, I think I initially misunderstood.

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

Are you setting workspace key prefix anywhere?

Kalman Speier avatar
Kalman Speier

nope

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

@Andriy Knysh (Cloud Posse) any ideas

Kalman Speier avatar
Kalman Speier

is the workspaces are port of the terraform state right?

Kalman Speier avatar
Kalman Speier

i’ve tried to clean all tf files and deleted this workspace, but still got back named as dev so maybe the default workspace holds some information?

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

Yes, in atmos we use one workspace for each instance of a component deployed.

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

Have you updated to the latest atmos? We just fixed a problem related to workspaces and changing backends

Kalman Speier avatar
Kalman Speier

yes, i’m using the very latest

Kalman Speier avatar
Kalman Speier
Workspace "dev" doesn't exist.

You can create this workspace with the "new" subcommand
or include the "-or-create" flag with the "select" subcommand.
Created and switched to workspace "dev"!
Kalman Speier avatar
Kalman Speier

but i bet it’s atmos what is switching to the workspace so the name dev comes from atmos not from the state

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

Yes, atmos dynamically computes the workspace name and switches to it

Kalman Speier avatar
Kalman Speier

i see.

Kalman Speier avatar
Kalman Speier
vars:
  stage: dev

import:
  - deploy/_defaults
  - catalog/do/project
  - catalog/do/doks
  - catalog/nats

components:
  terraform:
    project:
      vars:
        name: "platform-{{ .stack }}"
        environment: Development
    cluster:
      vars:
        name: doks-cluster-1
        project: '{{ (atmos.Component "project" .stack).outputs.id }}'
    nats:
      vars:
        kube_host: '{{ (atmos.Component "cluster" .stack).outputs.kube_host }}'
        kube_token: '{{ (atmos.Component "cluster" .stack).outputs.kube_token }}'
        kube_cert: '{{ (atmos.Component "cluster" .stack).outputs.kube_cert }}'
Kalman Speier avatar
Kalman Speier

this is my dev stack file

Kalman Speier avatar
Kalman Speier

and interestingly for the project and the cluster the names are generated correctly

Kalman Speier avatar
Kalman Speier
❯ tofu -chdir=components/terraform/nats workspace list
  default
* dev
  dev-cluster
  dev-project
Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)


i have a component named nats and stack named dev and instead of dev-nats the workspace is simply dev

Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)

this is the correct behavior for Atmos components that don’t inherit from other components

Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)

in this case, the TF workspace is simply the stack name

Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)

only if you have a derived component (inherited from a base component), then TF workspace will be <stack>+<component>

Kalman Speier avatar
Kalman Speier

hmm. what you mean by “inherit” the do cluster and project name is correct and didn’t inherit from anything. or i miss something here.

Kalman Speier avatar
Kalman Speier
components:
  terraform:
    nats:
      metadata:
        component: nats
      vars:
        ...

vs

components:
  terraform:
    cluster:
      metadata:
        component: do/doks
Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)
Inherit Configurations in Atmos Stacks | atmos

Inheritance provides a template-free way to customize Stack configurations. When combined with imports, it provides the ability to combine multiple configurations through ordered deep-merging of configurations. Inheritance is how you manage configuration variations, without resorting to templating.

Kalman Speier avatar
Kalman Speier

ok i read that before. but i didn’t us that in any catalog so far.

Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)

in the two examples above, both nats and cluster Atmos components do not inherit from any other Atmos components, so the TF workspaces for both of them will be dev

Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)

so what you have is 100% correct, the workspaces for these two components are just dev - the stack name

Kalman Speier avatar
Kalman Speier
❯ tofu -chdir=components/terraform/do/doks workspace list
  default
  dev
* dev-cluster
  dev-project
Kalman Speier avatar
Kalman Speier

maybe those were generated wrongly because i made a lot changes back and forth since.

Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)

yes, looks like it

Kalman Speier avatar
Kalman Speier

anyhow i’ fine with a single dev workspace named after the stack. as long as the states are correctly separated.

Kalman Speier avatar
Kalman Speier

i’m not fully familiar with tf workspaces, but that means if all these components are in the same workspace they are sharing the state or not ?

Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)

each component has workspace_key_prefix - it’s usually generated by Atmos, but you can override it per component

Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)

workspace_key_prefix is, if you look at the backend s3 bucket, the top-level folder

Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)

so each component will have it’s own top-level folder in the bucket, and each stack, in a separate TF worksapce, will have its own subfolder in the folder

Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)

so yes, each component state is separated from any other component state (diff folders in the state bucket)

Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)

note that it’s still in the same backend (same S3 bucket). If you want to separate backends (e.g. per tenant/OU, per account, etc.), you need to create and configure multiple backends

Kalman Speier avatar
Kalman Speier

sure. but i don’t see workspace_key_prefix generated anywhere.

Kalman Speier avatar
Kalman Speier
{
  "terraform": {
    "backend": {
      "gcs": {
        "bucket": "mw-tf-state",
        "encryption_key": "...",
        "prefix": "platform/infra"
      }
    }
  }
}
Kalman Speier avatar
Kalman Speier

it’s gcs, not s3 actually.

Kalman Speier avatar
Kalman Speier

_defaults.yaml:

terraform:
  backend_type: gcs
  backend:
    gcs:
      bucket: mw-tf-state
      prefix: platform/infra
      encryption_key: '{{ env "GCS_ENCRYPTION_KEY" }}'
Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)

GCP has prefix

Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)

which is the same

Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)
If the prefix is not specified for a component, Atmos will use the component name (my-component in the example above) to auto-generate the prefix. In the component name, all occurrences of / (slash) will be replaced with - (dash).
Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)

you don’t need to hardcode it here

backend:
    gcs:
      bucket: mw-tf-state
      prefix: platform/infra
Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)

in this case, all components will use the same prefix

Kalman Speier avatar
Kalman Speier

hmm ok, let me check that

Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)

please review the doc, if you don’t specify prefix, Atmos will auto-generate it

Kalman Speier avatar
Kalman Speier

thank you!

Kalman Speier avatar
Kalman Speier

so if i understand it correctly, without setting the prefix atmos will generate it and because of that my component states will end up in separate folders in the gcs bucket, so even they share a workspace states are separated.

1
Kalman Speier avatar
Kalman Speier

good to know that.:)

Kalman Speier avatar
Kalman Speier

only problem is that i prefer to store them in some folder instead of the root of the bucket but i can leave with that

Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)

note that you can specify the prefix per component, in which case Atmos will just use it

Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)

i can review your config, let me know

Kalman Speier avatar
Kalman Speier

it’s fine. this bucket is solely for tf states so it’s ok even in the root. i prefer to leave it to atmos to generate.

1
Kalman Speier avatar
Kalman Speier

on a different topic while we chat.. any chance to add support for command like this in atmos.yaml :

components:
  terraform:
    command: xy command -- tofu
Kalman Speier avatar
Kalman Speier

so support command with double dash

Kalman Speier avatar
Kalman Speier

it would be perfect that way i could load secrets as env vars. and i won’t need custom commands.

Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)

i don’t remember if command: xy command -- tofu is supported now (need to look at the code). Did you test it?

Kalman Speier avatar
Kalman Speier

yes. i just tested unfortunately it’s not working.

Kalman Speier avatar
Kalman Speier
atmos terraform plan cluster --stack dev

template: all-atmos-sections:100:35: executing "all-atmos-sections" at <atmos.Component>: error calling Component: exec: "op run --no-masking --env-file=.env -- tofu": executable file not found in $PATH
Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

I have done that with asdf and it works

Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)

ok, we’ll create a task for this, thank you

Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)

did you try to quote it?

Kalman Speier avatar
Kalman Speier

thanks a lot!!

Kalman Speier avatar
Kalman Speier

@Erik Osterman (Cloud Posse) do you have an example maybe with asdf?

Kalman Speier avatar
Kalman Speier

i’ve just tried with quote but not working.

Kalman Speier avatar
Kalman Speier

trying with a small shell script:

command: ./optofu.sh

but still not working

Kalman Speier avatar
Kalman Speier
#762 add support to exec shell commands with args

what

Add support for shell commands.

why

To support complex commands, for example:

components: terraform: command: op run –no-masking –env-file=.env – tofu

Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)

thanks, i’ll review it today. Did you test it?

Kalman Speier avatar
Kalman Speier

roughly. is there any go test(s) i can run?

Kalman Speier avatar
Kalman Speier

strange but for some reason it’s not working with my atmos config. it’s working fine with atmos.yaml in the repository. i will dig into it.

Kalman Speier avatar
Kalman Speier

problem is that when the template executed it uses tfexec

Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)

ah, yes, tfexec doesn’t understand those commands, it needs terraform

2024-11-04

Kalman Speier avatar
Kalman Speier

possible to organize a few smaller components into one catalog?

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

Of course… this is what we frequently do

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

you can create a catalog stack file for a solution.

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

E.g. here’s how we do “EKS” and all related components

Kalman Speier avatar
Kalman Speier

ok. is there any related example in the repo?

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)
Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

Here you can see we created a default cluster config, that imports a bunch of other componetns

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

Those could be inline, but we chose to import them

Kalman Speier avatar
Kalman Speier

thanks!

2024-11-05

Kalman Speier avatar
Kalman Speier

whats the best way to share vars between some components but not all of them? if i place in the stack yaml vars section, i got warnings from the components which are not using them.
Warning: Value for undeclared variable

Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)

yes, please don’t use globals

Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)

there are a few ways to share vars b/w components

Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)

e.g. create a base abstract component (with the default values) and inherit it in the other components

Andriy Knysh (Cloud Posse) avatar
Andriy Knysh (Cloud Posse)
Abstract Component | atmos

Abstract Component Atmos Design Pattern

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

And multiple inheritance

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)
Inherit Configurations in Atmos Stacks | atmos

Inheritance provides a template-free way to customize Stack configurations. When combined with imports, it provides the ability to combine multiple configurations through ordered deep-merging of configurations. Inheritance is how you manage configuration variations, without resorting to templating.

Kalman Speier avatar
Kalman Speier

thx!

    keyboard_arrow_up