Skip to content

Releases: cloudposse/atmos

v1.33.2

13 Apr 21:11
e92d6ce
Compare
Choose a tag to compare

what

  • Rename atmos describe dependants to atmos describe dependents
  • Add alias to allow atmos describe dependants

why

  • There are two acceptable ways to spell dependent depending (no pun intended) on whether you are speaking American English (dependent) or British English (dependant)

v1.33.1

12 Apr 22:37
72354a6
Compare
Choose a tag to compare
Update documentation and examples for vendoring modules as components…

v1.33.0

08 Apr 13:39
2ea2f04
Compare
Choose a tag to compare

what

why

  • Allow specifying a file for Atmos to write logs to
  • Allow specifying a log level to control the amount of Atmos logging

Logs

Atmos logs are configured in the logs section:

logs:
  file: "/dev/stdout"
  # Supported log levels: Trace, Debug, Info, Warning, Off (Off is the default and is used if logs.level is not set)
  level: Info
  • logs.file - the file to write Atmos logs to. Logs can be written to any file or any standard file descriptor, including /dev/stdout, /dev/stderr and /dev/null). If omitted, /dev/stdout will be used. The ENV variable ATMOS_LOGS_FILE can also be used to specify the log file

  • logs.level - Log level. Supported log levels are Off, Trace, Info. If the log level is set to Off, Atmos will not log any messages (note that this does not prevent other tools like Terraform from logging). The ENV variable ATMOS_LOGS_LEVEL can also be used to specify the log level

To prevent Atmos from logging any messages, you can do one of the following:

  • Set logs.file or the ENV variable ATMOS_LOGS_FILE to /dev/null

  • Set logs.level or the ENV variable ATMOS_LOGS_LEVEL to Off

v1.32.5

07 Apr 17:38
6c2e908
Compare
Choose a tag to compare

v1.32.4

25 Mar 22:09
38e11fd
Compare
Choose a tag to compare

what

  • Update atmos describe affected command

why

  • Check if not only the files in the component folder itself have changed, but also the files in all sub-folders at any level

test

For example, if we have the policies sub-folder in the component folder components/terraform/top-level-component1, and we have some files in the sub-folder (e.g. components/terraform/top-level-component1/policies/policy1.rego), and if the files changed, atmos describe affected would mark all Atmos components that use the components/terraform/top-level-component1 Terraform component as changed:

Cloning repo 'https://github.com/cloudposse/atmos' into the temp dir '/var/folders/g5/lbvzy_ld2hx4mgrgyp19bvb00000gn/T/16797114913176545339'

Checking out Git ref 'refs/heads/master' ...

Enumerating objects: 4320, done.
Counting objects: 100% (105/105), done.
Compressing objects: 100% (70/70), done.
Total 4320 (delta 39), reused 56 (delta 22), pack-reused 4215

Checked out Git ref 'refs/heads/master'

Current working repo HEAD: 2d995c21cb3fff46f39da1eeadb9d7b0f8faf72c refs/heads/update-describe-affected-2
Remote repo HEAD: 38b8fe6ca1221e16f0b969815bddfe98928cd1b5 refs/heads/master

Getting current working repo commit object...
Got current working repo commit object
Getting current working repo commit tree...
Got current working repo commit tree
Getting remote repo commit object...
Got remote repo commit object
Getting remote repo commit tree...
Got remote repo commit tree
Finding diff between the current working branch and remote target branch ...
Found diff between the current working branch and remote target branch

Changed files:
examples/complete/components/terraform/top-level-component1/policies/policy1.rego

Affected components and stacks:

  - component: top-level-component1
    component_type: terraform
    component_path: examples/complete/components/terraform/top-level-component1
    stack: tenant1-ue2-prod
    stack_slug: tenant1-ue2-prod-top-level-component1
    spacelift_stack: tenant1-ue2-prod-top-level-component1
    atlantis_project: tenant1-ue2-prod-top-level-component1
    affected: component
  - component: top-level-component1
    component_type: terraform
    component_path: examples/complete/components/terraform/top-level-component1
    stack: tenant2-ue2-staging
    stack_slug: tenant2-ue2-staging-top-level-component1
    spacelift_stack: tenant2-ue2-staging-top-level-component1
    atlantis_project: tenant2-ue2-staging-top-level-component1
    affected: component
  - component: top-level-component1
    component_type: terraform
    component_path: examples/complete/components/terraform/top-level-component1
    stack: tenant1-ue2-staging
    stack_slug: tenant1-ue2-staging-top-level-component1
    spacelift_stack: tenant1-ue2-staging-top-level-component1
    atlantis_project: tenant1-ue2-staging-top-level-component1
    affected: component
  - component: top-level-component1
    component_type: terraform
    component_path: examples/complete/components/terraform/top-level-component1
    stack: tenant1-ue2-test-1
    stack_slug: tenant1-ue2-test-1-top-level-component1
    spacelift_stack: tenant1-ue2-test-1-top-level-component1
    atlantis_project: tenant1-ue2-test-1-top-level-component1
    affected: component
  - component: top-level-component2
    component_type: terraform
    component_path: examples/complete/components/terraform/top-level-component1
    stack: tenant1-ue2-test-1
    stack_slug: tenant1-ue2-test-1-top-level-component2
    atlantis_project: tenant1-ue2-test-1-top-level-component2
    affected: component
  - component: top-level-component1
    component_type: terraform
    component_path: examples/complete/components/terraform/top-level-component1
    stack: tenant2-ue2-dev
    stack_slug: tenant2-ue2-dev-top-level-component1
    spacelift_stack: tenant2-ue2-dev-top-level-component1
    atlantis_project: tenant2-ue2-dev-top-level-component1
    affected: component
  - component: top-level-component1
    component_type: terraform
    component_path: examples/complete/components/terraform/top-level-component1
    stack: tenant2-ue2-prod
    stack_slug: tenant2-ue2-prod-top-level-component1
    spacelift_stack: tenant2-ue2-prod-top-level-component1
    atlantis_project: tenant2-ue2-prod-top-level-component1
    affected: component
  - component: top-level-component1
    component_type: terraform
    component_path: examples/complete/components/terraform/top-level-component1
    stack: tenant1-ue2-dev
    stack_slug: tenant1-ue2-dev-top-level-component1
    spacelift_stack: tenant1-ue2-dev-top-level-component1
    atlantis_project: tenant1-ue2-dev-top-level-component1
    affected: component
  - component: vpc
    component_type: terraform
    component_path: examples/complete/components/terraform/infra/vpc
    stack: tenant1-ue2-dev
    stack_slug: tenant1-ue2-dev-vpc
    spacelift_stack: tenant1-ue2-dev-vpc
    atlantis_project: tenant1-ue2-dev-vpc
    affected: stack.vars

v1.32.3

24 Mar 20:04
af84fc3
Compare
Choose a tag to compare

what & why

  • Use consolidated search index between atmos.tools and docs.cloudposse.com #351
  • Fix panic on "index out of range" in terraform two-words commands (if atmos component is not provided on the command line) #352

v1.32.2

22 Mar 18:45
16cfc0a
Compare
Choose a tag to compare

what & why

  • Converted 'Get Help' nav bar item to CTA button
  • More user friendly 404 page

v1.32.1

21 Mar 15:14
ad314ac
Compare
Choose a tag to compare

what

  • Update atmos describe affected command

why

  • Handle atmos absolute base path when working with the cloned remote repo in the describe affected command
  • Absolute base path can be set in the base_path attribute in atmos.yaml, or using the ENV var ATMOS_BASE_PATH (as it's done in geodesic)
  • If the atmos base path is absolute, find the relative path between the local repo path and the atmos base path. This relative path (the difference) is then used to join with the remote (cloned) repo path

v1.32.0

20 Mar 19:28
5c5f0f4
Compare
Choose a tag to compare

what

why

  • Allow creating complex hierarchical stack configurations and make them DRY
  • In Hierarchical Inheritance, every component can act as a base component for one or more child (derived) components, and each child component can inherit from one of more base components.

description

Multilevel Inheritance

Multilevel Inheritance is used when an Atmos component inherits from a base Atmos component, which in turn inherits from another base Atmos component.

In the diagram below, ComponentC directly inherits from ComponentB.
ComponentB directly inherits from ComponentA.

After this Multilevel Inheritance chain gets processed by Atmos, ComponentC will inherit all the configurations (vars, settings, env and other sections) from both ComponentB and ComponentA.

Note that ComponentB overrides the values from ComponentA. ComponentC overrides the values from both ComponentB and ComponentA.


classDiagram
      ComponentA --> ComponentB
      ComponentB --> ComponentC
      ComponentA : vars
      ComponentA : settings
      ComponentA : env
      class ComponentB {
          vars
          settings
          env
          metadata:
            inherits:
              - ComponentA  
      }
      class ComponentC {
          vars
          settings
          env
          metadata:
            inherits:
              - ComponentB  
      }

Hierarchical Inheritance

Hierarchical Inheritance is a combination of Multiple Inheritance and Multilevel Inheritance.

In Hierarchical Inheritance, every component can act as a base component for one or more child (derived) components, and each child component can inherit from one of more base components.


classDiagram
      ComponentA --> ComponentB
      ComponentA --> ComponentC
      ComponentB --> ComponentD
      ComponentB --> ComponentE
      ComponentC --> ComponentF
      ComponentC --> ComponentG
      ComponentH --> ComponentE
      ComponentI --> ComponentG
      ComponentA : vars
      ComponentA : settings
      ComponentA : env
      class ComponentB {
          vars
          settings
          env
          metadata:
            inherits:
              - ComponentA  
      }
      class ComponentC {
          vars
          settings
          env
          metadata:
            inherits:
              - ComponentA  
      }
      class ComponentD {
          vars
          settings
          env
          metadata:
            inherits:
              - ComponentB  
      }
      class ComponentE {
          vars
          settings
          env
          metadata:
            inherits:
              - ComponentB  
              - ComponentH  
      }
      class ComponentF {
          vars
          settings
          env
          metadata:
            inherits:
              - ComponentC  
      }
      class ComponentG {
          vars
          settings
          env
          metadata:
            inherits:
              - ComponentI  
              - ComponentC  
      }
      class ComponentH {
          vars
          settings
          env
      }
      class ComponentI {
          vars
          settings
          env
      }

In the diagram above:

  • ComponentA is the base component of the whole hierarchy

  • ComponentB and ComponentC inherit from ComponentA

  • ComponentD inherits from ComponentB directly, and from ComponentA via Multilevel Inheritance

  • ComponentE is an example of using both Multiple Inheritance and Multilevel Inheritance.
    It inherits from ComponentB and ComponentH directly, and from ComponentA via Multilevel Inheritance


For ComponentE, the inherited components are processed and deep-merged in the order they are specified in the inherits list:

  • ComponentB overrides the configuration from ComponentA

  • ComponentH overrides the configuration from ComponentB and ComponentA (since it's defined after ComponentB in the inherits section)

  • And finally, ComponentE overrides ComponentH, ComponentB and ComponentA


For ComponentG:

  • ComponentI is processed first (since it's the first item in the inherits list)

  • Then ComponentA is processed (since it's the base component for ComponentC which is the second item in the inherits list)

  • Then ComponentC is processed, and it overrides the configuration from ComponentA and ComponentI

  • And finally, ComponentG is processed, and it overrides ComponentC, ComponentA and ComponentI

Hierarchical Inheritance Example

Let's consider the following configuration for Atmos components base-component-1, base-component-2, derived-component-1 and derived-component-2:

components:
  terraform:

    base-component-1:
      metadata:
        type: abstract
      vars:
        hierarchical_inheritance_test: "base-component-1"

    base-component-2:
      metadata:
        type: abstract
      vars:
        hierarchical_inheritance_test: "base-component-2"

    derived-component-1:
      metadata:
        component: "test/test-component"
        inherits:
          - base-component-1
      vars: {}

    derived-component-2:
      metadata:
        component: "test/test-component"
        inherits:
          - base-component-2
          - derived-component-1
      vars: {}

This configuration can be represented by the following diagram:


classDiagram
      `base-component-1` --> `derived-component-1`
      `derived-component-1` --> `derived-component-2`
      `base-component-2` --> `derived-component-2`
      class `base-component-1` {
          settings
          env
          vars:
            hierarchical_inheritance_test: base-component-1
      }
      class `base-component-2` {
          settings
          env
          vars:
            hierarchical_inheritance_test: base-component-2
      }
      class `derived-component-1` {
          settings
          env
          vars
          metadata:
            inherits:
              - base-component-1  
      }
      class `derived-component-2` {
          settings
          env
          vars
          metadata:
            inherits:
              - base-component-2  
              - derived-component-1  
      }

In the configuration above, derived-component-1 inherits from base-component-1.

derived-component-2 inherits from base-component-2 and derived-component-1 via Multiple Inheritance, and from base-component-1 via Multilevel Inheritance.

The derived-component-2 component is processed in the following order:

  • base-component-2 is processed first (since it's the first item in the inherits list)

  • Then base-component-1 is processed (since it's the base component for derived-component-1 which is the second item in the inherits list), and
    it overrides the configuration from base-component-2

  • Then derived-component-1 is processed, and it overrides the configuration from base-component-2 and base-component-1

  • And finally, derived-component-2 is processed, and it overrides derived-component-1, base-component-1 and base-component-2

When we run the following command to provision the derived-component-2 component:

atmos terraform plan derived-component-2 -s tenant1-ue2-test-1

Atmos will show the following output:

Variables for the component 'derived-component-2' in the stack 'tenant1-ue2-test-1':
environment: ue2
hierarchical_inheritance_test: base-component-1
namespace: cp
region: us-east-2
stage: test-1
tenant: tenant1

Command info:
Terraform binary: terraform
Terraform command: plan
Component: derived-component-2
Terraform component: test/test-component
Inheritance: derived-component-2 -> derived-component-1 -> base-component-1 -> base-component-2

Note that the hierarchical_inheritance_test variable was inherited from base-component-1 because it overrode the configuration from base-component-2.


If we change the order of the components in the inherits list for derived-component-2:

components:
  terraform:

    derived-component-2:
      metadata:
        component: "test/test-component"
        inherits:
          - derived-component-1
          - base-component-2
      vars: {}

base-component-2 will be processed after base-component-1 and derived-component-1, and the hierarchical_inheritance_test variable will be inherited from base-component-2:

Variables for the component 'derived-component-2' in the stack 'tenant1-ue2-test-1':
environment: ue2
hierarchical_inheritance_test: base-component-2
namespace: cp
region: us-east-2
stage: test-1
tenant: tenant1

Command info:
Terraform binary: terraform
Terraform command: plan
Component: derived-component-2
Terraform component: test/test-component
Inheritance: derived-component-2 -> base-component-2 -> derived-component-1 -> base-component-1

v1.31.0

15 Mar 21:46
afe40e0
Compare
Choose a tag to compare

what

  • Fix an issue when the terraform components were in subfolders in the components/terraform folder deeper than the second level
  • Add atmos describe dependants command
  • Update docs

why

  • Fix an issue when the terraform components were in subfolders in the components/terraform folder deeper than second level. For example:

    image

    The component test-component-2 is in the subfolder components/terraform/test/test2, for which the filesystem path to the generated varfile was created incorrectly (when used just components/terraform/test subfolder, it was correct). The PR fixes the issue, and now components can be in any subfolder at any level.

  • The atmos describe dependants command produces a list of Atmos components in Atmos stacks that depend on the provided Atmos component

description

In Atmos, you can define component dependencies by using the settings.depends_on section. The section used to define all the Atmos components (in the same or different stacks) that the current component depends on.

The settings.depends_on section is a map of objects. The map keys are just the descriptions of dependencies and can be strings or numbers. Provide meaningful descriptions so that people can understand what the dependencies are about.

Each object in the settings.depends_on section has the following schema:

  • component (required) - an Atmos component that the current component depends on
  • namespace (optional) - the namespace where the Atmos component is provisioned
  • tenant (optional) - the tenant where the Atmos component is provisioned
  • environment (optional) - the environment where the Atmos component is provisioned
  • stage (optional) - the stage where the Atmos component is provisioned

The component attribute is required. The rest are the context variables and are used to define Atmos stacks other than the current stack. For example, you can specify:

  • namespace if the component is from a different Organization
  • tenant if the component is from a different Organizational Unit
  • environment if the component is from a different region
  • stage if the component is from a different account
  • tenant, environment and stage if the component is from a different Atmos stack (e.g. tenant1-ue2-dev)

In the following example, we define that the top-level-component1 component depends on the following:

  • The test/test-component-override component in the same Atmos stack
  • The test/test-component component in Atmos stacks identified by the dev stage
  • The my-component component from the tenant1-ue2-staging Atmos stack
components:
  terraform:
    top-level-component1:
      settings:
        depends_on:
          1:
            # If the `context` (namespace, tenant, environment, stage) is not provided, 
            # the `component` is from the same Atmos stack as this component
            component: "test/test-component-override"
          2:
            # This component (in any stage) depends on `test/test-component` 
            # from the `dev` stage (in any `environment` and any `tenant`)
            component: "test/test-component"
            stage: "dev"
          3:
            # This component depends on `my-component` 
            # from the `tenant1-ue2-staging` Atmos stack
            component: "my-component"
            tenant: "tenant1"
            environment: "ue2"
            stage: "staging"
      vars:
        enabled: true

In the following example, we specify that the top-level-component2 component depends on the following:

  • The test/test-component component in the same Atmos stack
  • The test/test2/test-component-2 component in the same Atmos stack
components:
  terraform:
    top-level-component2:
      metadata:
        component: "top-level-component1"
      settings:
        depends_on:
          1:
            # If the `context` (namespace, tenant, environment, stage) is not provided, 
            # the `component` is from the same Atmos stack as this component
            component: "test/test-component"
          2:
            # If the `context` (namespace, tenant, environment, stage) is not provided, 
            # the `component` is from the same Atmos stack as this component
            component: "test/test2/test-component-2"
      vars:
        enabled: true

Having the top-level-component and top-level-component2 components configured as shown above, we can now execute the following Atmos command to show all the components and stacks that are dependants of the test/test-component component in the tenant1-ue2-dev stack:

atmos describe dependants test/test-component -s tenant1-ue2-dev
[
  {
    "component": "top-level-component1",
    "component_type": "terraform",
    "component_path": "examples/complete/components/terraform/top-level-component1",
    "namespace": "cp",
    "tenant": "tenant1",
    "environment": "ue2",
    "stage": "dev",
    "stack": "tenant1-ue2-dev",
    "spacelift_stack": "tenant1-ue2-dev-top-level-component1",
    "atlantis_project": "tenant1-ue2-dev-top-level-component1"
  }
]

Similarly, the following Atmos command shows all the components and stacks that are dependants of the test/test-component component in the tenant1-ue2-test-1 stack:

atmos describe dependants test/test-component -s tenant1-ue2-test-1
[
  {
    "component": "top-level-component1",
    "component_type": "terraform",
    "component_path": "examples/complete/components/terraform/top-level-component1",
    "namespace": "cp",
    "tenant": "tenant1",
    "environment": "ue2",
    "stage": "test-1",
    "stack": "tenant1-ue2-test-1",
    "spacelift_stack": "tenant1-ue2-test-1-top-level-component1",
    "atlantis_project": "tenant1-ue2-test-1-top-level-component1"
  },
  {
    "component": "top-level-component2",
    "component_type": "terraform",
    "component_path": "examples/complete/components/terraform/top-level-component1",
    "namespace": "cp",
    "tenant": "tenant1",
    "environment": "ue2",
    "stage": "test-1",
    "stack": "tenant1-ue2-test-1",
    "atlantis_project": "tenant1-ue2-test-1-top-level-component2"
  }
]

After the test/test-component has been provisioned, you can use the outputs to perform the following actions:

  • Provision the dependent components by executing the Atmos commands atmos terraform apply top-level-component1 -s tenant1-ue2-test-1 and atmos terraform apply top-level-component2 -s tenant1-ue2-test-1 (on the command line or from a GitHub Action)

  • Trigger the dependent Spacelift stack (from a GitHub Action by using the spacectl CLI, or by using an OPA Trigger policy, or by using the spacelift_stack_dependency resource)

  • Trigger the dependent Atlantis project