Skip to content

Commit 34cc497

Browse files
aknyshautofix-ci[bot]osterman
authored
Add CLI flags to atmos terraform commands to control processing the templates and YAML functions in Atmos stack manifests (#1157)
* updates * updates * updates * updates * updates * updates * [autofix.ci] apply automated fixes * updates * updates * add unit tests * [autofix.ci] apply automated fixes * add unit tests * add unit tests * update docs * Apply suggestions from code review Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <erik@cloudposse.com> * updates * updates * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <erik@cloudposse.com>
1 parent daf9c22 commit 34cc497

39 files changed

+1354
-321
lines changed

atmos.yaml

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,6 @@
88
# It supports POSIX-style Globs for file names/paths (double-star '**' is supported)
99
# https://en.wikipedia.org/wiki/Glob_(programming)
1010

11-
# Base path for components, stacks and workflows configurations.
12-
# Can also be set using 'ATMOS_BASE_PATH' ENV var, or '--base-path' command-line argument.
13-
# Supports both absolute and relative paths.
14-
# If not provided or is an empty string, 'components.terraform.base_path', 'components.helmfile.base_path', 'stacks.base_path' and 'workflows.base_path'
15-
# are independent settings (supporting both absolute and relative paths).
16-
# If 'base_path' is provided, 'components.terraform.base_path', 'components.helmfile.base_path', 'stacks.base_path' and 'workflows.base_path'
17-
# are considered paths relative to 'base_path'.
18-
1911
vendor:
2012
# Path to vendor configuration file or directory containing vendor files
2113
# Supports both absolute and relative paths

cmd/terraform.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,30 @@ func terraformRun(cmd *cobra.Command, actualCmd *cobra.Command, args []string) e
6464
return nil
6565
}
6666

67+
flags := cmd.Flags()
68+
69+
processTemplates, err := flags.GetBool("process-templates")
70+
if err != nil {
71+
u.PrintErrorMarkdownAndExit("", err, "")
72+
}
73+
74+
processYamlFunctions, err := flags.GetBool("process-functions")
75+
if err != nil {
76+
u.PrintErrorMarkdownAndExit("", err, "")
77+
}
78+
79+
skip, err := flags.GetStringSlice("skip")
80+
if err != nil {
81+
u.PrintErrorMarkdownAndExit("", err, "")
82+
}
83+
84+
info.ProcessTemplates = processTemplates
85+
info.ProcessFunctions = processYamlFunctions
86+
info.Skip = skip
87+
88+
err = e.ExecuteTerraform(info)
6789
// For plan-diff, ExecuteTerraform will call OsExit directly if there are differences
6890
// So if we get here, it means there were no differences or there was an error
69-
err := e.ExecuteTerraform(info)
7091
if err != nil {
7192
if errors.Is(err, terrerrors.ErrPlanHasDiff) {
7293
// Print the error message but return the error to be handled by main.go

cmd/terraform_commands.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,10 @@ Arguments:
269269
// attachTerraformCommands attaches static Terraform commands to a provided parent command
270270
func attachTerraformCommands(parentCmd *cobra.Command) {
271271
parentCmd.PersistentFlags().String("append-user-agent", "", fmt.Sprintf("Sets the TF_APPEND_USER_AGENT environment variable to customize the User-Agent string in Terraform provider requests. Example: `Atmos/%s (Cloud Posse; +https://atmos.tools)`. This flag works with almost all commands.", version.Version))
272-
parentCmd.PersistentFlags().Bool("skip-init", false, "Skip running `terraform init` before executing the command")
272+
parentCmd.PersistentFlags().Bool("skip-init", false, "Skip running `terraform init` before executing terraform commands")
273+
parentCmd.PersistentFlags().Bool("process-templates", true, "Enable/disable Go template processing in Atmos stack manifests when executing terraform commands")
274+
parentCmd.PersistentFlags().Bool("process-functions", true, "Enable/disable YAML functions processing in Atmos stack manifests when executing terraform commands")
275+
parentCmd.PersistentFlags().StringSlice("skip", nil, "Skip executing specific YAML functions in the Atmos stack manifests when executing terraform commands")
273276

274277
commands := getTerraformCommands()
275278

cmd/terraform_generate_backend_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ func TestTerraformGenerateBackendCmd(t *testing.T) {
3131
err = Execute()
3232
assert.NoError(t, err, "'TestTerraformGenerateBackendCmd' should execute without error")
3333

34-
// Close the writer and restore stdout
34+
// Close the writer and restore stderr
3535
err = w.Close()
3636
assert.NoError(t, err, "'TestTerraformGenerateBackendCmd' should execute without error")
3737

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package cmd
2+
3+
import (
4+
"bytes"
5+
"io"
6+
"os"
7+
"testing"
8+
9+
"github.com/stretchr/testify/assert"
10+
)
11+
12+
func TestTerraformGenerateVarfileCmd(t *testing.T) {
13+
stacksPath := "../tests/fixtures/scenarios/stack-templates"
14+
15+
err := os.Setenv("ATMOS_CLI_CONFIG_PATH", stacksPath)
16+
assert.NoError(t, err, "Setting 'ATMOS_CLI_CONFIG_PATH' environment variable should execute without error")
17+
18+
err = os.Setenv("ATMOS_BASE_PATH", stacksPath)
19+
assert.NoError(t, err, "Setting 'ATMOS_BASE_PATH' environment variable should execute without error")
20+
21+
err = os.Setenv("ATMOS_LOGS_LEVEL", "Debug")
22+
assert.NoError(t, err, "Setting 'ATMOS_LOGS_LEVEL' environment variable should execute without error")
23+
24+
// Capture stderr
25+
oldStderr := os.Stderr
26+
r, w, _ := os.Pipe()
27+
os.Stderr = w
28+
29+
// Execute the command
30+
RootCmd.SetArgs([]string{"terraform", "generate", "varfile", "component-1", "-s", "nonprod"})
31+
err = Execute()
32+
assert.NoError(t, err, "'TestTerraformGenerateVarfileCmd' should execute without error")
33+
34+
// Close the writer and restore stderr
35+
err = w.Close()
36+
assert.NoError(t, err, "'TestTerraformGenerateVarfileCmd' should execute without error")
37+
38+
os.Stderr = oldStderr
39+
40+
// Read captured output
41+
var output bytes.Buffer
42+
_, err = io.Copy(&output, r)
43+
assert.NoError(t, err, "'TestTerraformGenerateVarfileCmd' should execute without error")
44+
45+
// Check if output contains the expected output
46+
assert.Contains(t, output.String(), "foo: component-1-a", "'TestTerraformGenerateVarfileCmd' output should contain 'foo: component-1-a'")
47+
assert.Contains(t, output.String(), "bar: component-1-b", "'TestTerraformGenerateVarfileCmd' output should contain 'bar: component-1-b'")
48+
assert.Contains(t, output.String(), "baz: component-1-c", "'TestTerraformGenerateVarfileCmd' output should contain 'baz: component-1-c'")
49+
}

cmd/terraform_test.go

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
package cmd
2+
3+
import (
4+
"os"
5+
"os/exec"
6+
"testing"
7+
8+
"github.com/pkg/errors"
9+
"github.com/spf13/cobra"
10+
"github.com/stretchr/testify/assert"
11+
)
12+
13+
func TestTerraformRun1(t *testing.T) {
14+
if os.Getenv("TEST_EXIT") == "1" {
15+
stacksPath := "../tests/fixtures/scenarios/stack-templates-2"
16+
17+
err := os.Setenv("ATMOS_CLI_CONFIG_PATH", stacksPath)
18+
assert.NoError(t, err, "Setting 'ATMOS_CLI_CONFIG_PATH' environment variable should execute without error")
19+
20+
err = os.Setenv("ATMOS_BASE_PATH", stacksPath)
21+
assert.NoError(t, err, "Setting 'ATMOS_BASE_PATH' environment variable should execute without error")
22+
23+
// Unset env values after testing
24+
defer func() {
25+
os.Unsetenv("ATMOS_BASE_PATH")
26+
os.Unsetenv("ATMOS_CLI_CONFIG_PATH")
27+
}()
28+
29+
cmd := &cobra.Command{
30+
Use: "test",
31+
Short: "test",
32+
}
33+
34+
terraformRun(cmd, cmd, []string{})
35+
return
36+
}
37+
execPath, err := exec.LookPath(os.Args[0])
38+
assert.Nil(t, err)
39+
cmd := exec.Command(execPath, "-test.run=TestTerraformRun1")
40+
cmd.Env = append(os.Environ(), "TEST_EXIT=1")
41+
err = cmd.Run()
42+
var exitError *exec.ExitError
43+
if errors.As(err, &exitError) {
44+
assert.Equal(t, 1, exitError.ExitCode())
45+
} else {
46+
assert.Fail(t, "Expected an exit error with code 1")
47+
}
48+
}
49+
50+
func TestTerraformRun2(t *testing.T) {
51+
if os.Getenv("TEST_EXIT") == "1" {
52+
stacksPath := "../tests/fixtures/scenarios/stack-templates-2"
53+
54+
err := os.Setenv("ATMOS_CLI_CONFIG_PATH", stacksPath)
55+
assert.NoError(t, err, "Setting 'ATMOS_CLI_CONFIG_PATH' environment variable should execute without error")
56+
57+
err = os.Setenv("ATMOS_BASE_PATH", stacksPath)
58+
assert.NoError(t, err, "Setting 'ATMOS_BASE_PATH' environment variable should execute without error")
59+
60+
// Unset env values after testing
61+
defer func() {
62+
os.Unsetenv("ATMOS_BASE_PATH")
63+
os.Unsetenv("ATMOS_CLI_CONFIG_PATH")
64+
}()
65+
66+
cmd := &cobra.Command{
67+
Use: "test",
68+
Short: "test",
69+
}
70+
71+
cmd.PersistentFlags().Bool("process-templates", true, "Enable/disable Go template processing in Atmos stack manifests when executing terraform commands")
72+
73+
terraformRun(cmd, cmd, []string{})
74+
return
75+
}
76+
execPath, err := exec.LookPath(os.Args[0])
77+
assert.Nil(t, err)
78+
cmd := exec.Command(execPath, "-test.run=TestTerraformRun2")
79+
cmd.Env = append(os.Environ(), "TEST_EXIT=1")
80+
err = cmd.Run()
81+
var exitError *exec.ExitError
82+
if errors.As(err, &exitError) {
83+
assert.Equal(t, 1, exitError.ExitCode())
84+
} else {
85+
assert.Fail(t, "Expected an exit error with code 1")
86+
}
87+
}
88+
89+
func TestTerraformRun3(t *testing.T) {
90+
if os.Getenv("TEST_EXIT") == "1" {
91+
stacksPath := "../tests/fixtures/scenarios/stack-templates-2"
92+
93+
err := os.Setenv("ATMOS_CLI_CONFIG_PATH", stacksPath)
94+
assert.NoError(t, err, "Setting 'ATMOS_CLI_CONFIG_PATH' environment variable should execute without error")
95+
96+
err = os.Setenv("ATMOS_BASE_PATH", stacksPath)
97+
assert.NoError(t, err, "Setting 'ATMOS_BASE_PATH' environment variable should execute without error")
98+
99+
// Unset env values after testing
100+
defer func() {
101+
os.Unsetenv("ATMOS_BASE_PATH")
102+
os.Unsetenv("ATMOS_CLI_CONFIG_PATH")
103+
}()
104+
105+
cmd := &cobra.Command{
106+
Use: "test",
107+
Short: "test",
108+
}
109+
110+
cmd.PersistentFlags().Bool("process-templates", true, "Enable/disable Go template processing in Atmos stack manifests when executing terraform commands")
111+
cmd.PersistentFlags().Bool("process-functions", true, "Enable/disable YAML functions processing in Atmos stack manifests when executing terraform commands")
112+
113+
terraformRun(cmd, cmd, []string{})
114+
return
115+
}
116+
execPath, err := exec.LookPath(os.Args[0])
117+
assert.Nil(t, err)
118+
cmd := exec.Command(execPath, "-test.run=TestTerraformRun3")
119+
cmd.Env = append(os.Environ(), "TEST_EXIT=1")
120+
err = cmd.Run()
121+
var exitError *exec.ExitError
122+
if errors.As(err, &exitError) {
123+
assert.Equal(t, 1, exitError.ExitCode())
124+
} else {
125+
assert.Fail(t, "Expected an exit error with code 1")
126+
}
127+
}

examples/quick-start-advanced/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ ARG GEODESIC_OS=debian
66
# https://atmos.tools/
77
# https://github.com/cloudposse/atmos
88
# https://github.com/cloudposse/atmos/releases
9-
ARG ATMOS_VERSION=1.165.3
9+
ARG ATMOS_VERSION=1.167.0
1010

1111
# Terraform: https://github.com/hashicorp/terraform/releases
1212
ARG TF_VERSION=1.5.7

0 commit comments

Comments
 (0)