diff --git a/README.md b/README.md index 478aa874..db35eb4d 100644 --- a/README.md +++ b/README.md @@ -369,9 +369,3 @@ Builds are automatically launched on tagging. Tags with the format image-0.0.0 automatically launch a Docker images build that are available through Docker Hub. Tags with the format v0.0.0 automatically launch a new release on Github for the TGF executable. - -Tests that involve docker builds are not compatible with docker buildkit. Run them with: - -```bash -DOCKER_BUILDKIT=0 go test ./... -``` diff --git a/cli.go b/cli.go index 1b31f250..ece6bf3b 100644 --- a/cli.go +++ b/cli.go @@ -87,6 +87,7 @@ type TGFApplication struct { AwsProfile string ConfigFiles string ConfigLocation string + ConfigDump bool DisableUserConfig bool DockerBuild bool DockerInteractive bool @@ -164,6 +165,7 @@ func NewTGFApplication(args []string) *TGFApplication { app.Flag("ssm-path", "Parameter Store path used to find AWS common configuration shared by a team").PlaceHolder("").Default(defaultSSMParameterFolder).StringVar(&app.PsPath) app.Flag("config-files", "Set the files to look for (default: "+remoteDefaultConfigPath+")").PlaceHolder("").StringVar(&app.ConfigFiles) app.Flag("config-location", "Set the configuration location").PlaceHolder("").StringVar(&app.ConfigLocation) + app.Flag("config-dump", "Print the TGF configuration and exit").BoolVar(&app.ConfigDump) app.Flag("update", "Run auto update script").IsSetByUser(&app.AutoUpdateSet).BoolVar(&app.AutoUpdate) kingpin.CommandLine = app.Application @@ -266,14 +268,5 @@ func (app *TGFApplication) ShowHelp(c *kingpin.ParseContext) error { // Run execute the application func (app *TGFApplication) Run() int { - if app.GetCurrentVersion { - if version == locallyBuilt { - fmt.Println("tgf (built from source)") - } else { - fmt.Printf("tgf v%s\n", version) - } - return 0 - } - return RunWithUpdateCheck(InitConfig(app)) } diff --git a/config.go b/config.go index b0cc048a..0a935ce7 100644 --- a/config.go +++ b/config.go @@ -252,7 +252,10 @@ func (config *TGFConfig) InitAWS() error { "AWS_REGION": *session.Config.Region, } { os.Setenv(key, value) - config.Environment[key] = value + if !config.tgf.ConfigDump { + // If we are saving the current configuration, we do not want to save the current credentials + config.Environment[key] = value + } } return nil } @@ -279,6 +282,7 @@ func (config *TGFConfig) setDefaultValues() { if err := config.InitAWS(); err != nil { log.Fatal(err) } + if app.ConfigLocation == "" { values := config.readSSMParameterStore(app.PsPath) app.ConfigLocation = values[remoteConfigLocationParameter] diff --git a/config_run.go b/config_run.go index f3eb9c64..e08d8c48 100644 --- a/config_run.go +++ b/config_run.go @@ -31,6 +31,20 @@ func (config *TGFConfig) Run() int { return 1 } + if app.GetCurrentVersion { + if version == locallyBuilt { + fmt.Println("tgf (built from source)") + } else { + fmt.Printf("tgf v%s\n", version) + } + return 0 + } + + if app.ConfigDump { + fmt.Println(config.String()) + return 0 + } + if app.GetAllVersions { if filepath.Base(config.EntryPoint) != "terragrunt" { log.Error("--all-version works only with terragrunt as the entrypoint") diff --git a/config_run_test.go b/config_run_test.go index 27ca51f0..8b863902 100644 --- a/config_run_test.go +++ b/config_run_test.go @@ -3,16 +3,18 @@ package main import ( "bytes" "fmt" + "github.com/coveooss/gotemplate/v3/yaml" "io/ioutil" "os" "path/filepath" "strings" "testing" + "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" ) -func setup(t *testing.T, testFunction func()) string { +func setup(t *testing.T, testFunction func()) (string, string) { // To ensure that the test is not altered by the environment env := os.Environ() os.Clearenv() @@ -45,12 +47,13 @@ func setup(t *testing.T, testFunction func()) string { testFunction() w.Close() out, _ := ioutil.ReadAll(r) - return string(out) + logBuffer.String() + return string(out), logBuffer.String() } func TestCurrentVersion(t *testing.T) { version = locallyBuilt - output := setup(t, func() { + output, _ := setup(t, func() { + log.SetDefaultConsoleHookLevel(logrus.WarnLevel) app := NewTGFApplication([]string{"--current-version"}) exitCode := app.Run() assert.Equal(t, 0, exitCode, "exitCode") @@ -59,10 +62,21 @@ func TestCurrentVersion(t *testing.T) { } func TestAllVersions(t *testing.T) { - output := setup(t, func() { + _, logOutput := setup(t, func() { app := NewTGFApplication([]string{"--all-versions", "--no-aws", "--ignore-user-config", "--entrypoint=OTHER_FILE"}) exitCode := InitConfig(app).Run() assert.Equal(t, 1, exitCode, "exitCode") }) - assert.Contains(t, output, "ERROR: --all-version works only with terragrunt as the entrypoint\n") + assert.Contains(t, logOutput, "ERROR: --all-version works only with terragrunt as the entrypoint\n") +} + +func TestConfigDump_isValidYAML(t *testing.T) { + output, _ := setup(t, func() { + app := NewTGFApplication([]string{"-L=5", "--config-dump", "--no-aws", "--ignore-user-config", "--entrypoint=OTHER_FILE"}) + exitCode := InitConfig(app).Run() + assert.Equal(t, 0, exitCode, "exitCode") + }) + + // --config-dump output can be redirected to a file, so it must be valid YAML. + assert.NoError(t, yaml.UnmarshalStrict([]byte(output), &TGFConfig{})) } diff --git a/config_test.go b/config_test.go index 45167779..98fb501f 100644 --- a/config_test.go +++ b/config_test.go @@ -126,6 +126,42 @@ func TestSetConfigDefaultValues(t *testing.T) { assert.Nil(t, config.ImageVersion) } +/* +Test that --config-dump filters out AWS secrets. +This allows the dumped configuration to be used in more contexts, without exposing secrets. +See https://coveord.atlassian.net/browse/DT-3750 +*/ +func TestConfigDumpFiltersOutAWSEnvironment(t *testing.T) { + log.SetOut(os.Stdout) + + // We must reset the cached AWS config check since it could have been modified by another test + resetCache() + tempDir, _ := filepath.EvalSymlinks(must(ioutil.TempDir("", "TestGetConfig")).(string)) + currentDir, _ := os.Getwd() + assert.NoError(t, os.Chdir(tempDir)) + defer func() { + assert.NoError(t, os.Chdir(currentDir)) + assert.NoError(t, os.RemoveAll(tempDir)) + }() + + testTgfConfigFile := fmt.Sprintf("%s/.tgf.config", tempDir) + + tgfConfig := []byte(String(` + docker-image: coveo/stuff + docker-image-build: RUN ls test2 + docker-image-build-tag: hello + docker-image-build-folder: my-folder + `).UnIndent().TrimSpace()) + ioutil.WriteFile(testTgfConfigFile, tgfConfig, 0644) + + app := NewTestApplication([]string{"--config-dump"}, true) + config := InitConfig(app) + + for key := range config.Environment { + assert.False(t, strings.Contains(key, "AWS"), "Environment must not contain any AWS_* key, but found %s", key) + } +} + func TestTwoLevelsOfTgfConfig(t *testing.T) { tempDir, _ := filepath.EvalSymlinks(must(ioutil.TempDir("", "TestGetConfig")).(string)) currentDir, _ := os.Getwd() diff --git a/docker_test.go b/docker_test.go index bee76c11..64fa1fd2 100644 --- a/docker_test.go +++ b/docker_test.go @@ -17,6 +17,7 @@ import ( func TestGetImage(t *testing.T) { + os.Setenv("DOCKER_BUILDKIT", "0") // For docker tests to pass on Mac, docker buildkit must be disabled testImageName := "test-image" + strconv.Itoa(randInt()) testTag := "test" + strconv.Itoa(randInt()) testImageNameTagged := testImageName + ":" + testTag