Update `atmos describe affected` command @aknysh (#1267)
what
- Update
atmos describe affected
command - Add
affected_all
attribute to the output ofatmos describe affected
to show all component sections and attributes that were changed - Update docs
- Add unit tests
why
-
Improve usage of the
atmos describe affected
command in CI/CD, e.g. GitHub actions -
affected_all
will allow detecting everything that was changed for a component in a stack (including Terraform configurations/components/modules) and ack on the changesFor example, if you make changes to the
vars
andsettings
sections of the componentcomponent-1
in the
nonprod
stack, and executeatmos describe affected
, you will get the following result:[ { "component": "component-1", "component_type": "terraform", "stack": "nonprod", "stack_slug": "nonprod-component-1", "affected": "stack.vars", "affected_all": [ "stack.vars", "stack.settings" ] } ]
If you create a new Terraform/Tofu component, configure a new Atmos component
component-1
in the
nonprod
stack, and executeatmos describe affected
, you will get the following result:[ { "component": "component-1", "component_type": "terraform", "stack": "nonprod", "stack_slug": "nonprod-component-1", "affected": "stack.metadata", "affected_all": [ "stack.metadata", "stack.vars", "stack.env", "stack.settings", "component" ] } ]
where:
-
affected
shows that the Atmos component'smetadata
section was changed
(since the component is new and themetadata
section is the first section that Atmos processes) -
affected_all
shows all the affected sections and attributes:component
- the Terraform component (Terraform configuration) was affected (since it was just added)stack.metadata
- the Atmos component'smetadata
section was changedstack.vars
- the Atmos component'svars
section was changedstack.env
- the Atmos component'senv
section was changedstack.settings
- the Atmos component'ssettings
section was changed
-
Add Atmos Validation Policy Execution Context. Update docs @aknysh (#1261)
what
- Add Atmos Validation Policy Execution Context
- Update docs
- Add unit tests
why
Policy Execution Context
Atmos allows enforcing custom governance rules based on metadata about Atmos commands and provides a powerful
policy evaluation mechanism by passing structured metadata to OPA policies at runtime.
This metadata enables fine-grained control over when certain actions (like terraform apply
) are allowed or denied,
based on the context in which they're executed.
Policy Metadata
When Atmos runs a command, it supplies an input object to OPA policies that contains detailed contextual information, such as:
cli_args
: a list of the command line arguments and flags (e.g., executing theatmos terraform apply
command will generate the["terraform", "apply"]
list)vars
: a map of variables passed to the command, either via the stack config files or CLI flags- other contextual attributes such as the stack and component names
Policy Execution Context Example
Below is an OPA policy rule to enforce infrastructure governance during command execution.
Specifically, this rule blocks the execution of atmos terraform apply
if the variable foo
is set to the string "foo"
.
# 'package atmos' is required in all Atmos OPA policies
package atmos
# Atmos looks for the 'errors' (array of strings) output from all OPA policies
# If the 'errors' output contains one or more error messages, Atmos considers the policy failed
# Don't allow `terraform apply` if the `foo` variable is set to `foo`
# The `input` map contains the `cli_args` attribute (a list of the command line arguments and flags)
errors[message] {
count(input.cli_args) >= 2
input.cli_args[0] == "terraform"
input.cli_args[1] == "apply"
input.vars.foo == "foo"
message = "the component can't be applied if the 'foo' variable is set to 'foo'"
}
The rule checks if:
- The
cli_args
list has at least two items - The command (first item in the
cli_args
list) isterraform
- The subcommand (second item in the
cli_args
list) isapply
- The variable
foo
is set to"foo"
If all conditions are true, the rule generates an error message.
The generated error message is added to the errors
array.
Atmos interprets the presence of any messages in errors
as a policy violation and blocks the operation with the
following error:
the component can't be applied if the 'foo' variable is set to 'foo'
exit status 1
[Stores] Add user-managed replication support to GSM @ohaibbq (#1260)
what
- Add support for user-managed replication locations to the Google Secret Manager store
why
- GCP projects often have policies that constrain where resources are physically located
Update `stacks.name_template`. Update docs @aknysh (#1264)
what
- Update
stacks.name_template
- Update docs
- Add unit tests
why
For the remote-state terraform module and terraform-provider-utils, allow using the stacks.name_template
setting in atmos.yaml
with a limited context:
.vars.namespace
.vars.tenant
.vars.environment
.vars.stage
name_template: "{{.vars.tenant}}-{{.vars.environment}}-{{.vars.stage}}"
This will allow using name_template
(instead of name_pattern
) in both Atmos CLI and the remote-state
module (to get the outputs of TF components)
stacks.name_template
serves the same purpose as stacks.name_pattern
(defines the naming convention for the top-level Atmos stacks), but provides much more functionality. Instead of using the predefined context variables as tokens, it uses Go templates.
Atmos Template Functions, Sprig Functions, Gomplate Functions, and Gomplate Datasources are supported as well
name_template
can have complex logic and use template expressions and functions. The following template defines a name_template
that builds a stack_name
string by validating and concatenating several input variables in a hierarchical order.
name_template: |-
{{- $ns := .vars.namespace -}}
{{- $tenant := .vars.tenant -}}
{{- $env := .vars.environment -}}
{{- $stage := .vars.stage -}}
{{- $stack_name := "" -}}
{{- if eq $ns "" -}}
{{- fail "Error: 'namespace' is required." -}}
{{- end -}}
{{- if and (ne $tenant "") (eq $ns "") -}}
{{- fail "Error: 'tenant' requires 'namespace'." -}}
{{- end -}}
{{- if and (ne $env "") (or (eq $tenant "") (eq $ns "")) -}}
{{- fail "Error: 'environment' requires 'tenant' and 'namespace'." -}}
{{- end -}}
{{- if and (ne $stage "") (or (eq $env "") (eq $tenant "") (eq $ns "")) -}}
{{- fail "Error: 'stage' requires 'environment', 'tenant', and 'namespace'." -}}
{{- end -}}
{{- if ne $tenant "" -}}
{{- $stack_name = $tenant -}}
{{- end -}}
{{- if ne $env "" -}}
{{- $stack_name = printf "%s-%s" $stack_name $env -}}
{{- end -}}
{{- if ne $stage "" -}}
{{- $stack_name = printf "%s-%s" $stack_name $stage -}}
{{- end -}}
{{- $stack_name -}}
It pulls values from the Atmos section vars
and assigns them to local template variables:
namespace
tenant
environment
stage
The template enforces hierarchical dependencies between variables:
namespace
is required- If
tenant
is provided,namespace
must also be set - If
environment
is provided, bothtenant
andnamespace
must be set - If
stage
is provided, thenenvironment
,tenant
, andnamespace
must all be set
If validations pass, it constructs the stack_name
progressively:
- Starts with
tenant
if it exists - Appends
environment
if it exists - Appends
stage
if it exists
The template outputs the resulting stack name. For example, if the variables are:
namespace: acme
tenant: plat
environment: ue2
stage: prod
The resulting stack name will be plat-ue2-prod
.