Skip to content

Commit

Permalink
Update Atmos to 1.50.0. Use te latest tests from Atmos (#339)
Browse files Browse the repository at this point in the history
  • Loading branch information
aknysh authored Nov 5, 2023
1 parent 3c0425f commit a6833a0
Show file tree
Hide file tree
Showing 18 changed files with 228 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ spec:
# In 'uri', Golang templates are supported https://pkg.go.dev/text/template
# If 'version' is provided, '{{.Version}}' will be replaced with the 'version' value before pulling the files from 'uri'
uri: github.com/cloudposse/terraform-aws-components.git//modules/account-map?ref={{.Version}}
version: 1.240.0
version: 1.323.0
# Only include the files that match the 'included_paths' patterns
# If 'included_paths' is not specified, all files will be matched except those that match the patterns from 'excluded_paths'
# 'included_paths' support POSIX-style Globs for file names/paths (double-star `**` is supported)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

# > atmos vendor pull -c infra/vpc-flow-logs-bucket
# Pulling sources for the component 'infra/vpc-flow-logs-bucket' from 'github.com/cloudposse/terraform-aws-components.git//modules/vpc-flow-logs-bucket?ref=0.194.0'
# and writing to 'examples/complete/components/terraform/infra/vpc-flow-logs-bucket'
# into 'examples/complete/components/terraform/infra/vpc-flow-logs-bucket'
#
# Including the file 'README.md' since it matches the '**/*.md' pattern from 'included_paths'
# Excluding the file 'context.tf' since it matches the '**/context.tf' pattern from 'excluded_paths'
Expand All @@ -17,9 +17,9 @@
# Including the file 'versions.tf' since it matches the '**/*.tf' pattern from 'included_paths'
#
# Pulling the mixin 'https://raw.githubusercontent.com/cloudposse/terraform-null-label/0.25.0/exports/context.tf'
# for the component 'infra/vpc-flow-logs-bucket' and writing to 'examples/complete/components/terraform/infra/vpc-flow-logs-bucket'
# for the component 'infra/vpc-flow-logs-bucket' into 'examples/complete/components/terraform/infra/vpc-flow-logs-bucket'
# Pulling the mixin 'https://raw.githubusercontent.com/cloudposse/terraform-aws-components/0.194.0/modules/datadog-agent/introspection.mixin.tf'
# for the component 'infra/vpc-flow-logs-bucket' and writing to 'examples/complete/components/terraform/infra/vpc-flow-logs-bucket'
# for the component 'infra/vpc-flow-logs-bucket' into 'examples/complete/components/terraform/infra/vpc-flow-logs-bucket'

apiVersion: atmos/v1
kind: ComponentVendorConfig
Expand All @@ -33,7 +33,7 @@ spec:
# In 'uri', Golang templates are supported https://pkg.go.dev/text/template
# If 'version' is provided, '{{.Version}}' will be replaced with the 'version' value before pulling the files from 'uri'
uri: github.com/cloudposse/terraform-aws-components.git//modules/vpc-flow-logs-bucket?ref={{.Version}}
version: 1.240.0
version: 1.323.0
# Only include the files that match the 'included_paths' patterns
# If 'included_paths' is not specified, all files will be matched except those that match the patterns from 'excluded_paths'
# 'included_paths' support POSIX-style Globs for file names/paths (double-star `**` is supported)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module "flow_logs_s3_bucket" {
source = "cloudposse/vpc-flow-logs-s3-bucket/aws"
version = "0.18.0"
version = "1.0.1"

lifecycle_prefix = var.lifecycle_prefix
lifecycle_tags = var.lifecycle_tags
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ spec:
# In 'uri', Golang templates are supported https://pkg.go.dev/text/template
# If 'version' is provided, '{{.Version}}' will be replaced with the 'version' value before pulling the files from 'uri'
uri: github.com/cloudposse/terraform-aws-components.git//modules/vpc?ref={{.Version}}
version: 1.240.0
version: 1.323.0
# Only include the files that match the 'included_paths' patterns
# If 'included_paths' is not specified, all files will be matched except those that match the patterns from 'excluded_paths'
# 'included_paths' support POSIX-style Globs for file names/paths (double-star `**` is supported)
Expand Down
26 changes: 26 additions & 0 deletions examples/complete/components/terraform/infra/vpc2/component.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# This is an example of how to download a Terraform component from an OCI registry (https://opencontainers.org), e.g. AWS Public ECR

# 'component.yaml' in the component folder is processed by the 'atmos' commands
# 'atmos vendor pull -c infra/vpc2' or 'atmos vendor pull --component infra/vpc2'

apiVersion: atmos/v1
kind: ComponentVendorConfig
metadata:
name: stable/aws/vpc
description: Config for vendoring of 'stable/aws/vpc' component
spec:
source:
# Source 'uri' supports the following protocols: OCI (https://opencontainers.org), Git, Mercurial, HTTP, HTTPS, Amazon S3, Google GCP,
# and all URL and archive formats as described in https://github.com/hashicorp/go-getter
# In 'uri', Golang templates are supported https://pkg.go.dev/text/template
# If 'version' is provided, '{{.Version}}' will be replaced with the 'version' value before pulling the files from 'uri'
# Download the component from the AWS public ECR registry (https://docs.aws.amazon.com/AmazonECR/latest/public/public-registries.html)
uri: "oci://public.ecr.aws/cloudposse/components/terraform/stable/aws/vpc:{{.Version}}"
version: "latest"
# Only include the files that match the 'included_paths' patterns
# If 'included_paths' is not specified, all files will be matched except those that match the patterns from 'excluded_paths'
# 'included_paths' support POSIX-style Globs for file names/paths (double-star `**` is supported)
# https://en.wikipedia.org/wiki/Glob_(programming)
# https://github.com/bmatcuk/doublestar#patterns
included_paths:
- "**/*.*"
12 changes: 7 additions & 5 deletions examples/complete/stacks/catalog/terraform/eks_cluster_tmpl.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ components:
component: "test/test-component"
# Parameterize variables
vars:
enabled: "{{ .enabled }}"
name: "eks-{{ .flavor }}"
service_1_name: "{{ .service_1_name }}"
service_2_name: "{{ .service_2_name }}"
enabled: '{{ .enabled }}'
# http://masterminds.github.io/sprig/defaults.html
name: 'eks-{{ .flavor | default "foo" }}'
# http://masterminds.github.io/sprig/os.html
service_1_name: '{{ env "service_1_name" }}'
service_2_name: '{{ expandenv "Service 2 name is $service_2_name" }}'
tags:
flavor: "{{ .flavor }}"
flavor: '{{ .flavor }}'
3 changes: 3 additions & 0 deletions examples/complete/stacks/orgs/cp/_defaults.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ components:
helmfile: {}

settings:
spacelift:
workspace_enabled: false
autodeploy: false
atlantis:
# Select a config template defined in `atmos.yaml` in the `integrations.atlantis.config_templates` section
config_template_name: "config-1"
Expand Down
7 changes: 7 additions & 0 deletions examples/complete/stacks/orgs/cp/tenant1/dev/us-west-2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import:
- mixins/region/us-west-2
- orgs/cp/tenant1/dev/_defaults
# Import all components that the `devops` Team manages
- teams/devops
# Import all components that the `testing` Team manages
- teams/testing
4 changes: 2 additions & 2 deletions examples/complete/stacks/orgs/cp/tenant1/test1/us-west-1.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import:

# This import with the provided hierarchical context will dynamically generate
# a new Atmos component `eks-blue/cluster` in the `tenant1-uw1-test1` stack
# a new Atmos component `eks-blue/cluster` in the `tenant1-uw1-test-1` stack
- path: catalog/terraform/eks_cluster_tmpl_hierarchical
context:
# Context variables for the EKS component
Expand All @@ -17,7 +17,7 @@ import:
stage: "test1"

# This import with the provided hierarchical context will dynamically generate
# a new Atmos component `eks-green/cluster` in the `tenant1-uw1-test1` stack
# a new Atmos component `eks-green/cluster` in the `tenant1-uw1-test-1` stack
- path: catalog/terraform/eks_cluster_tmpl_hierarchical
context:
# Context variables for the EKS component
Expand Down
2 changes: 2 additions & 0 deletions examples/complete/stacks/orgs/cp/tenant1/test1/us-west-2.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import:
# This import with the provided context will dynamically generate
# a new Atmos component `eks-blue/cluster` in the current stack
- path: catalog/terraform/eks_cluster_tmpl
ignore_missing_template_values: true
context:
flavor: "blue"
enabled: true
Expand All @@ -14,6 +15,7 @@ import:
# This import with the provided context will dynamically generate
# a new Atmos component `eks-green/cluster` in the current stack
- path: catalog/terraform/eks_cluster_tmpl
ignore_missing_template_values: true
context:
flavor: "green"
enabled: false
Expand Down
122 changes: 122 additions & 0 deletions examples/complete/stacks/schemas/opa/examples/example1.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# https://www.openpolicyagent.org/docs/v0.13.5/how-do-i-write-policies
# https://www.openpolicyagent.org/docs/latest/policy-language
# https://www.openpolicyagent.org/docs/latest/policy-reference
# https://www.openpolicyagent.org/docs/v0.12.2/language-reference/#regex

# '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

# 'package atmos' is required in all 'atmos' OPA policies
package atmos

# Function `object_has_key` checks if an object has the specified key with a string value
# https://www.openpolicyagent.org/docs/latest/policy-reference/#types
object_has_key(o, k) {
some item
item = o[k]
type_name(item) == "string"
}

# Check the app hostname usign Regex
errors[message] {
not re_match("^([a-z0-9]+([\\-a-z0-9]*[a-z0-9]+)?\\.){1,}([a-z0-9]+([\\-a-z0-9]*[a-z0-9]+)?){1,63}(\\.[a-z0-9]{2,7})+$", input.vars.app_config.hostname)
message = "'app_config.hostname' must contain at least a subdomain and a top level domain. Example: subDomain1.topLevelDomain.com"
}

# Check the email address usign Regex
errors[message] {
not re_match("^([a-zA-Z0-9_\\-\\.]+)@([a-zA-Z0-9_\\-\\.]+)\\.([a-zA-Z]{2,5})$", input.vars.app_config.contact.email)
message = "'app_config.contact.email' must be a valid email address"
}

# Check the phone number usign Regex
errors[message] {
not re_match("^[\\+]?[(]?[0-9]{3}[)]?[-\\s\\.]?[0-9]{3}[-\\s\\.]?[0-9]{4,6}", input.vars.app_config.contact.phone)
message = "'app_config.contact.phone' must be a valid phone number"
}

# Check if the component has a `Team` tag
errors[message] {
not object_has_key(input.vars.tags, "Team")
message = "All components must have 'Team' tag defined to specify which team is responsible for managing and provisioning them"
}

# Check if the Team has permissions to provision components in an OU (tenant)
errors[message] {
input.vars.tags.Team == "devs"
input.vars.tenant == "corp"
message = "'devs' team cannot provision components into 'corp' OU"
}

# Check the message of the day from the manager
# If `settings.notes.allowed` is set to `false`, output the message from the manager
errors[message] {
input.settings.notes.allowed == false
message = concat("", [input.settings.notes.manager, " says: ", input.settings.notes.message])
}

# Check `notes2` config in the free-form Atmos section `settings`
errors[message] {
input.settings.notes2.message == ""
message = "'notes2.message' should not be empty"
}

# Check that the `app_config.hostname` variable is defined only once for the stack accross all stack config files
# Refer to https://atmos.tools/cli/commands/describe/component#sources-of-component-variables for details on how 'atmos' detects sources for all variables
# https://www.openpolicyagent.org/docs/latest/policy-language/#universal-quantification-for-all
errors[message] {
hostnames := {app_config | some app_config in input.sources.vars.app_config; app_config.hostname}
count(hostnames) > 0
message = "'app_config.hostname' variable must be defined only once for the stack accross all stack config files"
}

# This policy checks that the 'bar' variable is not defined in any of the '_defaults.yaml' Atmos stack config files
# Refer to https://atmos.tools/cli/commands/describe/component#sources-of-component-variables for details on how 'atmos' detects sources for all variables
# https://www.openpolicyagent.org/docs/latest/policy-language/#universal-quantification-for-all
errors[message] {
# Get all 'stack_dependencies' of the 'bar' variable
stack_dependencies := input.sources.vars.bar.stack_dependencies
# Get all stack dependencies of the 'bar' variable where 'stack_file' ends with '_defaults'
defaults_stack_dependencies := {stack_dependency | some stack_dependency in stack_dependencies; endswith(stack_dependency.stack_file, "_defaults")}
# Check the count of the stack dependencies of the 'bar' variable where 'stack_file' ends with '_defaults'
count(defaults_stack_dependencies) > 0
# Generate the error message
message = "The 'bar' variable must not be defined in any of '_defaults.yaml' stack config files"
}

# This policy checks that if the 'foo' variable is defined in the 'stack1.yaml' stack config file, it cannot be overriden in 'stack2.yaml'
# Refer to https://atmos.tools/cli/commands/describe/component#sources-of-component-variables for details on how 'atmos' detects sources for all variables
# https://www.openpolicyagent.org/docs/latest/policy-language/#universal-quantification-for-all
errors[message] {
# Get all 'stack_dependencies' of the 'foo' variable
stack_dependencies := input.sources.vars.foo.stack_dependencies
# Check if the 'foo' variable is defined in the 'stack1.yaml' stack config file
stack1_dependency := endswith(stack_dependencies[0].stack_file, "stack1")
stack1_dependency == true
# Get all stack dependencies of the 'foo' variable where 'stack_file' ends with 'stack2' (this means that the variable is redefined in one of the files 'stack2')
stack2_dependencies := {stack_dependency | some stack_dependency in stack_dependencies; endswith(stack_dependency.stack_file, "stack2")}
# Check the count of the stack dependencies of the 'foo' variable where 'stack_file' ends with 'stack2'
count(stack2_dependencies) > 0
# Generate the error message
message = "If the 'foo' variable is defined in 'stack1.yaml', it cannot be overriden in 'stack2.yaml'"
}

# This policy shows an example on how to check the imported files in the stacks
# All stack files (root stacks and imported) that the current component depends on are in the `deps` section
# For example:
# deps:
# - catalog/xxx
# - catalog/yyy
# - orgs/zzz/_defaults
errors[message] {
input.vars.tags.Team == "devs"
input.vars.tenant == "corp"
input.deps[_] == "catalog/xxx"
message = "'devs' team cannot import the 'catalog/xxx' file when provisioning components into 'corp' OU"
}

# Note:
# If a regex pattern in the 're_match' function contains a backslash to escape special chars (e.g. '\.' or '\-'),
# it must be escaped with another backslash when represented as a regular Go string ('\\.', '\\-').
# The reason is that backslash is also used to escape special characters in Go strings like newline (\n).
# If you want to match the backslash character itself, you'll need four slashes.
3 changes: 3 additions & 0 deletions examples/complete/stacks/teams/devops.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import:
# The `devops` Team manages all the components defined in the following stack manifests:
- catalog/terraform/top-level-component1
43 changes: 43 additions & 0 deletions examples/complete/stacks/teams/testing.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import:
# The `testing` Team manages all the components defined in the following stack manifests:
- catalog/terraform/test-component
- catalog/terraform/test-component-override

# Global overrides.
# Override the variables, env, command and settings ONLY in the components managed by the `testing` Team.
overrides:
env:
# This ENV variable will be added or overridden in all the components managed by the `testing` Team
TEST_ENV_VAR1: "test-env-var1-overridden"
settings: {}
vars: {}

# Terraform overrides.
# Override the variables, env, command and settings ONLY in the Terraform components managed by the `testing` Team.
# The Terraform `overrides` are deep-merged with the global `overrides`
# and takes higher priority (it will override the same keys from the global `overrides`).
terraform:
overrides:
settings:
spacelift:
# All the components managed by the `testing` Team will have the Spacelift stacks auto-applied
# if the planning phase was successful and there are no plan policy warnings
# https://docs.spacelift.io/concepts/stack/stack-settings#autodeploy
autodeploy: true
vars:
# This variable will be added or overridden in all the Terraform components managed by the `testing` Team
test_1: 1
# The `testing` Team uses `tofu` instead of `terraform`
# https://opentofu.org
# The commands `atmos terraform <sub-command> ...` will execute the `tofu` binary
command: tofu

# Helmfile overrides.
# Override the variables, env, command and settings ONLY in the Helmfile components managed by the `testing` Team.
# The Helmfile `overrides` are deep-merged with the global `overrides`
# and takes higher priority (it will override the same keys from the global `overrides`).
helmfile:
overrides:
env:
# This ENV variable will be added or overridden in all the Helmfile components managed by the `testing` Team
TEST_ENV_VAR2: "test-env-var2-overridden"
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func TestSpaceliftStackProcessorWithTerraform(t *testing.T) {
terraform.OutputStruct(t, terraformOptions, "output", &output)
spaceliftStacks := output.(map[string]any)

assert.Equal(t, 44, len(spaceliftStacks))
assert.Equal(t, 47, len(spaceliftStacks))

tenant1Ue2DevInfraVpcStack := spaceliftStacks["tenant1-ue2-dev-infra-vpc"].(map[string]any)
tenant1Ue2DevInfraVpcStackInfrastructureStackName := tenant1Ue2DevInfraVpcStack["stack"].(string)
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/cloudposse/terraform-provider-utils
go 1.21

require (
github.com/cloudposse/atmos v1.49.0
github.com/cloudposse/atmos v1.50.0
github.com/gruntwork-io/terratest v0.46.5
github.com/hashicorp/terraform-plugin-docs v0.16.0
github.com/hashicorp/terraform-plugin-sdk/v2 v2.29.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,8 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
github.com/cloudposse/atmos v1.49.0 h1:a3MbdG0hDzVxbP87j3+WOyji32dXFWAIk9j6BqgA6rE=
github.com/cloudposse/atmos v1.49.0/go.mod h1:3u4Xzjkdys3LjSHwmGOd1UKl8lE4VC7HYMZ5o/W8SHc=
github.com/cloudposse/atmos v1.50.0 h1:t8zuoXRdjXEwEmi8Tgc4BDBoBW3d17+Lr9zcG3uHERY=
github.com/cloudposse/atmos v1.50.0/go.mod h1:3u4Xzjkdys3LjSHwmGOd1UKl8lE4VC7HYMZ5o/W8SHc=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
Expand Down
2 changes: 1 addition & 1 deletion internal/describe/describe_stacks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func TestDescribeStacksWithFilter5(t *testing.T) {

stacks, err := describe.ExecuteDescribeStacks(cliConfig, "", components, componentTypes, sections, false)
assert.Nil(t, err)
assert.Equal(t, 7, len(stacks))
assert.Equal(t, 8, len(stacks))

tenant1Ue2DevStack := stacks["tenant1-ue2-dev"].(map[string]any)
tenant1Ue2DevStackComponents := tenant1Ue2DevStack["components"].(map[string]any)
Expand Down
2 changes: 1 addition & 1 deletion internal/spacelift/spacelift_stack_processor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func TestSpaceliftStackProcessor(t *testing.T) {
)

assert.Nil(t, err)
assert.Equal(t, 44, len(spaceliftStacks))
assert.Equal(t, 47, len(spaceliftStacks))

tenant1Ue2DevInfraVpcStack := spaceliftStacks["tenant1-ue2-dev-infra-vpc"].(map[string]any)
tenant1Ue2DevInfraVpcStackInfrastructureStackName := tenant1Ue2DevInfraVpcStack["stack"].(string)
Expand Down

0 comments on commit a6833a0

Please sign in to comment.