diff --git a/generate/generate.go b/generate/generate.go index f07a4cdf1..6687484a6 100644 --- a/generate/generate.go +++ b/generate/generate.go @@ -93,6 +93,7 @@ func Do(root string, workingDir string) Report { } logger.Trace().Msg("Checking for invalid paths on generated files.") + if err := checkGeneratedFilesPaths(genfiles); err != nil { report.err = errors.E(ErrInvalidFilePath, err) return report @@ -122,13 +123,16 @@ func Do(root string, workingDir string) Report { for filename, genfile := range genfiles { path := filepath.Join(stackpath, filename) + emptyBody := genfile.Body() == "" logger := logger.With(). Str("filename", filename). + Bool("condition", genfile.Condition()). + Bool("emptyBody", emptyBody). Logger() // We don't want to generate files just with a header inside. - if genfile.Body() == "" { - logger.Trace().Msg("ignoring empty code") + if emptyBody || !genfile.Condition() { + logger.Debug().Msg("ignoring") continue } @@ -142,8 +146,7 @@ func Do(root string, workingDir string) Report { ) } - // Change detection + remove code that got deleted but - // was re-generated from the removed files map + // Change detection + remove entries that got re-generated removedFileBody, ok := removedFiles[filename] if !ok { report.addCreatedFile(filename) @@ -228,37 +231,36 @@ func CheckStack(root string, st stack.S) ([]string, error) { return nil, errors.E(err, "checking for outdated code") } + stackpath := st.HostPath() + targetGenFiles := generatedFiles{} + + err = loadGenerateHCL(root, stackpath, st, globals, targetGenFiles) + if err != nil { + return nil, err + } + + err = loadGenerateFile(root, stackpath, st, globals, targetGenFiles) + if err != nil { + return nil, err + } + logger.Trace().Msg("Listing current generated files.") - generatedFiles, err := ListStackGenFiles(st) + actualGenFiles, err := ListStackGenFiles(st) if err != nil { return nil, errors.E(err, "checking for outdated code") } // We start with the assumption that all gen files on the stack // are outdated and then update the outdated files set as we go. - outdatedFiles := newStringSet(generatedFiles...) - stackpath := st.HostPath() - err = updateGenHCLOutdatedFiles( - root, + outdatedFiles := newStringSet(actualGenFiles...) + err = updateOutdatedFiles( stackpath, - st, - globals, + targetGenFiles, outdatedFiles, ) if err != nil { - return nil, errors.E(err, "checking for outdated generate_hcl files") - } - - err = updateGenFileOutdatedFiles( - root, - stackpath, - st, - globals, - outdatedFiles, - ) - if err != nil { - return nil, errors.E(err, "checking for outdated generate_hcl files") + return nil, errors.E(err, "checking for outdated files") } outdated := outdatedFiles.slice() @@ -266,17 +268,17 @@ func CheckStack(root string, st stack.S) ([]string, error) { return outdated, nil } -// TODO: rename to fileInfo -type generatedFile interface { +type fileInfo interface { Origin() string Header() string Body() string + Condition() bool } // generatedFiles maps filenames to generated files -type generatedFiles map[string]generatedFile +type generatedFiles map[string]fileInfo -func (g generatedFiles) add(filename string, genfile generatedFile) error { +func (g generatedFiles) add(filename string, genfile fileInfo) error { if other, ok := g[filename]; ok { return errors.E(ErrConflictingConfig, "configs from %q and %q generate a file with same name %q", @@ -289,102 +291,54 @@ func (g generatedFiles) add(filename string, genfile generatedFile) error { return nil } -func updateGenFileOutdatedFiles( - root, stackpath string, - stackMeta stack.Metadata, - globals stack.Globals, +func updateOutdatedFiles( + stackpath string, + genfiles generatedFiles, outdatedFiles *stringSet, ) error { logger := log.With(). - Str("action", "generate.updateGenFileOutdatedFiles()"). - Str("root", root). + Str("action", "generate.updateOutdatedFiles()"). Str("stackpath", stackpath). Logger() - logger.Trace().Msg("Checking for outdated generated_file code on stack.") - - stackFiles, err := genfile.Load(root, stackMeta, globals) - if err != nil { - return err - } + logger.Trace().Msg("Checking for outdated generated code on stack.") - logger.Trace().Msg("Loaded generated_file code, checking") - - for filename, genFile := range stackFiles.GeneratedFiles() { + for filename, genfile := range genfiles { targetpath := filepath.Join(stackpath, filename) logger := logger.With(). Str("blockName", filename). Str("targetpath", targetpath). Logger() - logger.Trace().Msg("Checking if file content is updated.") + logger.Trace().Msg("Checking if code is updated.") - fileContents, found, err := readFile(targetpath) + currentCode, codeFound, err := readFile(targetpath) if err != nil { return err } - if !found && genFile.Body() == "" { - logger.Trace().Msg("Not outdated since file not found and generated_file is empty") - continue + if !codeFound { + if genfile.Body() == "" { + logger.Trace().Msg("Not outdated since file not found and content is empty") + continue + } + if !genfile.Condition() { + logger.Trace().Msg("Not outdated since file not found and condition is false") + continue + } } - if genFile.Body() != fileContents { - logger.Trace().Msg("generate_file code is outdated") + if !genfile.Condition() { + logger.Trace().Msg("Outdated since condition is false and file should not exist") outdatedFiles.add(filename) - } else { - logger.Trace().Msg("generate_file code is updated") - outdatedFiles.remove(filename) - } - } - - return nil -} - -func updateGenHCLOutdatedFiles( - root, stackpath string, - stackMeta stack.Metadata, - globals stack.Globals, - outdatedFiles *stringSet, -) error { - logger := log.With(). - Str("action", "generate.updateGenHCLOutdatedFiles()"). - Str("root", root). - Str("stackpath", stackpath). - Logger() - - logger.Trace().Msg("Checking for outdated generated_hcl code on stack.") - - stackHCLs, err := genhcl.Load(root, stackMeta, globals) - if err != nil { - return err - } - - logger.Trace().Msg("Loaded generated_hcl code, checking") - - for filename, genHCL := range stackHCLs.GeneratedHCLs() { - targetpath := filepath.Join(stackpath, filename) - logger := logger.With(). - Str("blockName", filename). - Str("targetpath", targetpath). - Logger() - - logger.Trace().Msg("Checking if code is updated.") - - currentHCLcode, codeFound, err := readGeneratedFile(targetpath) - if err != nil { - return err - } - if !codeFound && genHCL.Body() == "" { - logger.Trace().Msg("Not outdated since file not found and generated_hcl is empty") continue } - genHCLCode := genHCL.Header() + genHCL.Body() - if genHCLCode != currentHCLcode { - logger.Trace().Msg("generate_hcl code is outdated") + generatedCode := genfile.Header() + genfile.Body() + if generatedCode != currentCode { + logger.Trace().Msg("Generated code doesn't match file, is outdated") outdatedFiles.add(filename) } else { - logger.Trace().Msg("generate_hcl code is updated") + logger.Trace().Msg("Generated code matches file, it is updated") outdatedFiles.remove(filename) } } @@ -454,7 +408,7 @@ func loadGenerateFile( return nil } -func writeGeneratedCode(target string, genfile generatedFile) error { +func writeGeneratedCode(target string, genfile fileInfo) error { logger := log.With(). Str("action", "writeGeneratedCode()"). Str("file", target). diff --git a/generate/generate_file_check_test.go b/generate/generate_file_check_test.go index 72b53f523..9b98ebcbf 100644 --- a/generate/generate_file_check_test.go +++ b/generate/generate_file_check_test.go @@ -41,7 +41,7 @@ func TestCheckReturnsOutdatedStackFilenamesForGeneratedFile(t *testing.T) { stackConfig( generateFile( labels("test.txt"), - strAttr("content", "test"), + str("content", "test"), ), ).String()) assertOutdatedFiles([]string{"test.txt"}) @@ -55,7 +55,7 @@ func TestCheckReturnsOutdatedStackFilenamesForGeneratedFile(t *testing.T) { stackConfig( generateFile( labels("test.txt"), - strAttr("content", "changed"), + str("content", "changed"), ), ).String()) @@ -69,7 +69,7 @@ func TestCheckReturnsOutdatedStackFilenamesForGeneratedFile(t *testing.T) { stackConfig( generateFile( labels("testnew.txt"), - strAttr("content", "changed"), + str("content", "changed"), ), ).String()) @@ -80,11 +80,11 @@ func TestCheckReturnsOutdatedStackFilenamesForGeneratedFile(t *testing.T) { stackConfig( generateFile( labels("testnew.txt"), - strAttr("content", "changed"), + str("content", "changed"), ), generateFile( labels("another.txt"), - strAttr("content", "changed"), + str("content", "changed"), ), ).String()) @@ -120,7 +120,7 @@ func TestCheckOutdatedIgnoresEmptyGenerateFileContent(t *testing.T) { stackConfig( generateFile( labels("test.txt"), - strAttr("content", ""), + str("content", ""), ), ).String()) @@ -131,7 +131,7 @@ func TestCheckOutdatedIgnoresEmptyGenerateFileContent(t *testing.T) { stackConfig( generateFile( labels("test.txt"), - strAttr("content", "test"), + str("content", "test"), ), ).String()) @@ -145,7 +145,7 @@ func TestCheckOutdatedIgnoresEmptyGenerateFileContent(t *testing.T) { stackConfig( generateFile( labels("test.txt"), - strAttr("content", ""), + str("content", ""), ), ).String()) @@ -155,3 +155,50 @@ func TestCheckOutdatedIgnoresEmptyGenerateFileContent(t *testing.T) { assertOutdatedFiles([]string{}) } + +func TestCheckOutdatedIgnoresWhenGenFileConditionIsFalse(t *testing.T) { + const filename = "test.txt" + + s := sandbox.New(t) + + stackEntry := s.CreateStack("stacks/stack") + stack := stackEntry.Load() + + assertOutdatedFiles := func(want []string) { + t.Helper() + + got, err := generate.CheckStack(s.RootDir(), stack) + assert.NoError(t, err) + assertEqualStringList(t, got, want) + } + + createConfig := func(filename string, condition bool) { + stackEntry.CreateConfig( + stackConfig( + generateFile( + labels(filename), + boolean("condition", condition), + str("content", "some content"), + ), + ).String()) + } + + // Checking detection when the config has condition = false + createConfig(filename, false) + assertOutdatedFiles([]string{}) + + // Checking detection when the condition is set to true + createConfig(filename, true) + assertOutdatedFiles([]string{filename}) + + s.Generate() + assertOutdatedFiles([]string{}) + + // Setting it back to false is detected as change since it should be deleted + createConfig(filename, false) + assertOutdatedFiles([]string{"test.txt"}) + + s.Generate() + + assertOutdatedFiles([]string{}) +} diff --git a/generate/generate_file_test.go b/generate/generate_file_test.go index a4b15a7fb..200de65d8 100644 --- a/generate/generate_file_test.go +++ b/generate/generate_file_test.go @@ -16,11 +16,14 @@ package generate_test import ( "fmt" + "os" + "path/filepath" "testing" "github.com/google/go-cmp/cmp" "github.com/mineiros-io/terramate/errors" "github.com/mineiros-io/terramate/generate" + "github.com/mineiros-io/terramate/test/sandbox" ) func TestGenerateFile(t *testing.T) { @@ -45,7 +48,24 @@ func TestGenerateFile(t *testing.T) { path: "/stacks", add: generateFile( labels("empty"), - strAttr("content", ""), + str("content", ""), + ), + }, + }, + }, + { + name: "generate_file with false condition generates nothing", + layout: []string{ + "s:stacks/stack-1", + "s:stacks/stack-2", + }, + configs: []hclconfig{ + { + path: "/stacks", + add: generateFile( + labels("test"), + boolean("condition", false), + str("content", "content"), ), }, }, @@ -62,11 +82,11 @@ func TestGenerateFile(t *testing.T) { add: hcldoc( generateFile( labels("file1.txt"), - exprAttr("content", "terramate.path"), + expr("content", "terramate.path"), ), generateFile( labels("file2.txt"), - exprAttr("content", "terramate.name"), + expr("content", "terramate.name"), ), ), }, @@ -75,15 +95,15 @@ func TestGenerateFile(t *testing.T) { { stack: "/stacks/stack-1", files: map[string]fmt.Stringer{ - "file1.txt": str("/stacks/stack-1"), - "file2.txt": str("stack-1"), + "file1.txt": stringer("/stacks/stack-1"), + "file2.txt": stringer("stack-1"), }, }, { stack: "/stacks/stack-2", files: map[string]fmt.Stringer{ - "file1.txt": str("/stacks/stack-2"), - "file2.txt": str("stack-2"), + "file1.txt": stringer("/stacks/stack-2"), + "file2.txt": stringer("stack-2"), }, }, }, @@ -112,11 +132,11 @@ func TestGenerateFile(t *testing.T) { add: hcldoc( generateFile( labels("file1.txt"), - exprAttr("content", "terramate.path"), + expr("content", "terramate.path"), ), generateFile( labels("file2.txt"), - exprAttr("content", "terramate.name"), + expr("content", "terramate.name"), ), ), }, @@ -125,8 +145,8 @@ func TestGenerateFile(t *testing.T) { { stack: "/stacks/stack-2", files: map[string]fmt.Stringer{ - "file1.txt": str("/stacks/stack-2"), - "file2.txt": str("stack-2"), + "file1.txt": stringer("/stacks/stack-2"), + "file2.txt": stringer("stack-2"), }, }, }, @@ -156,28 +176,28 @@ func TestGenerateFile(t *testing.T) { path: "/stacks/stack-1", add: generateFile( labels("/name"), - strAttr("content", "something"), + str("content", "something"), ), }, { path: "/stacks/stack-2", add: generateFile( labels("./name"), - strAttr("content", "something"), + str("content", "something"), ), }, { path: "/stacks/stack-3", add: generateFile( labels("./dir/name"), - strAttr("content", "something"), + str("content", "something"), ), }, { path: "/stacks/stack-4", add: generateFile( labels("dir/name"), - strAttr("content", "something"), + str("content", "something"), ), }, }, @@ -212,3 +232,71 @@ func TestGenerateFile(t *testing.T) { }, }) } + +func TestGenerateFileRemoveFilesWhenConditionIsFalse(t *testing.T) { + const filename = "file.txt" + + s := sandbox.New(t) + stackEntry := s.CreateStack("stack") + + assertFileExist := func(file string) { + t.Helper() + + path := filepath.Join(stackEntry.Path(), file) + if _, err := os.Stat(path); err != nil { + t.Fatalf("want file %q to exist, instead got: %v", path, err) + } + } + assertFileDontExist := func(file string) { + t.Helper() + + path := filepath.Join(stackEntry.Path(), file) + _, err := os.Stat(path) + + if errors.Is(err, os.ErrNotExist) { + return + } + + t.Fatalf("want file %q to not exist, instead got: %v", path, err) + } + + createConfig := func(filename string, condition bool) { + stackEntry.CreateConfig( + stackConfig( + generateFile( + labels(filename), + boolean("condition", condition), + str("content", "some content"), + ), + ).String()) + } + + createConfig(filename, false) + report := s.Generate() + assertEqualReports(t, report, generate.Report{}) + assertFileDontExist(filename) + + createConfig(filename, true) + report = s.Generate() + assertEqualReports(t, report, generate.Report{ + Successes: []generate.Result{ + { + StackPath: "/stack", + Created: []string{filename}, + }, + }, + }) + assertFileExist(filename) + + createConfig(filename, false) + report = s.Generate() + assertEqualReports(t, report, generate.Report{ + Successes: []generate.Result{ + { + StackPath: "/stack", + Deleted: []string{filename}, + }, + }, + }) + assertFileDontExist(filename) +} diff --git a/generate/generate_hcl_check_test.go b/generate/generate_hcl_check_test.go index 60b4bf544..dece7979d 100644 --- a/generate/generate_hcl_check_test.go +++ b/generate/generate_hcl_check_test.go @@ -44,7 +44,7 @@ func TestCheckReturnsOutdatedStackFilenamesForGeneratedHCL(t *testing.T) { labels("test.tf"), content( terraform( - strAttr("required_version", "1.10"), + str("required_version", "1.10"), ), ), ), @@ -62,7 +62,7 @@ func TestCheckReturnsOutdatedStackFilenamesForGeneratedHCL(t *testing.T) { labels("test.tf"), content( terraform( - strAttr("required_version", "1.11"), + str("required_version", "1.11"), ), ), ), @@ -80,7 +80,7 @@ func TestCheckReturnsOutdatedStackFilenamesForGeneratedHCL(t *testing.T) { labels("testnew.tf"), content( terraform( - strAttr("required_version", "1.11"), + str("required_version", "1.11"), ), ), ), @@ -95,7 +95,7 @@ func TestCheckReturnsOutdatedStackFilenamesForGeneratedHCL(t *testing.T) { labels("testnew.tf"), content( terraform( - strAttr("required_version", "1.11"), + str("required_version", "1.11"), ), ), ), @@ -181,3 +181,53 @@ func TestCheckOutdatedIgnoresEmptyGenerateHCLBlocks(t *testing.T) { assertOutdatedFiles([]string{}) } + +func TestCheckOutdatedIgnoresWhenGenHCLConditionIsFalse(t *testing.T) { + const filename = "test.tf" + + s := sandbox.New(t) + + stackEntry := s.CreateStack("stacks/stack") + stack := stackEntry.Load() + + assertOutdatedFiles := func(want []string) { + t.Helper() + + got, err := generate.CheckStack(s.RootDir(), stack) + assert.NoError(t, err) + assertEqualStringList(t, got, want) + } + + createConfig := func(filename string, condition bool) { + stackEntry.CreateConfig( + stackConfig( + generateHCL( + labels(filename), + boolean("condition", condition), + content( + block("whatever"), + ), + ), + ).String()) + } + + // Checking detection when the condition is false + createConfig(filename, false) + assertOutdatedFiles([]string{}) + + // Checking detection when the condition is true + createConfig(filename, true) + assertOutdatedFiles([]string{filename}) + + s.Generate() + + assertOutdatedFiles([]string{}) + + // Checking the condition back to false triggers detection + createConfig(filename, false) + assertOutdatedFiles([]string{filename}) + + s.Generate() + + assertOutdatedFiles([]string{}) +} diff --git a/generate/generate_hcl_test.go b/generate/generate_hcl_test.go index 62b8cba6c..cedcdf7df 100644 --- a/generate/generate_hcl_test.go +++ b/generate/generate_hcl_test.go @@ -64,6 +64,27 @@ func TestGenerateHCL(t *testing.T) { }, }, }, + { + name: "generate_hcl with false condition generates nothing", + layout: []string{ + "s:stacks/stack-1", + "s:stacks/stack-2", + }, + configs: []hclconfig{ + { + path: "/stacks", + add: generateHCL( + labels("test"), + boolean("condition", false), + content( + backend( + labels("test"), + ), + ), + ), + }, + }, + }, { name: "generate HCL for all stacks on parent", layout: []string{ @@ -79,7 +100,7 @@ func TestGenerateHCL(t *testing.T) { content( backend( labels("test"), - exprAttr("prefix", "global.backend_prefix"), + expr("prefix", "global.backend_prefix"), ), ), ), @@ -87,11 +108,11 @@ func TestGenerateHCL(t *testing.T) { labels("locals.tf"), content( locals( - exprAttr("stackpath", "terramate.path"), - exprAttr("local_a", "global.local_a"), - exprAttr("local_b", "global.local_b"), - exprAttr("local_c", "global.local_c"), - exprAttr("local_d", "tm_try(global.local_d.field, null)"), + expr("stackpath", "terramate.path"), + expr("local_a", "global.local_a"), + expr("local_b", "global.local_b"), + expr("local_c", "global.local_c"), + expr("local_d", "tm_try(global.local_d.field, null)"), ), ), ), @@ -100,18 +121,18 @@ func TestGenerateHCL(t *testing.T) { content( provider( labels("name"), - exprAttr("data", "global.provider_data"), + expr("data", "global.provider_data"), ), terraform( requiredProviders( - exprAttr("name", `{ + expr("name", `{ source = "integrations/name" version = global.provider_version }`), ), ), terraform( - exprAttr("required_version", "global.terraform_version"), + expr("required_version", "global.terraform_version"), ), ), ), @@ -120,27 +141,27 @@ func TestGenerateHCL(t *testing.T) { { path: "/stacks/stack-1", add: globals( - strAttr("local_a", "stack-1-local"), - boolAttr("local_b", true), - numberAttr("local_c", 666), + str("local_a", "stack-1-local"), + boolean("local_b", true), + number("local_c", 666), attr("local_d", `{ field = "local_d_field"}`), - strAttr("backend_prefix", "stack-1-backend"), - strAttr("provider_data", "stack-1-provider-data"), - strAttr("provider_version", "stack-1-provider-version"), - strAttr("terraform_version", "stack-1-terraform-version"), + str("backend_prefix", "stack-1-backend"), + str("provider_data", "stack-1-provider-data"), + str("provider_version", "stack-1-provider-version"), + str("terraform_version", "stack-1-terraform-version"), ), }, { path: "/stacks/stack-2", add: globals( - strAttr("local_a", "stack-2-local"), - boolAttr("local_b", false), - numberAttr("local_c", 777), + str("local_a", "stack-2-local"), + boolean("local_b", false), + number("local_c", 777), attr("local_d", `{ oopsie = "local_d_field"}`), - strAttr("backend_prefix", "stack-2-backend"), - strAttr("provider_data", "stack-2-provider-data"), - strAttr("provider_version", "stack-2-provider-version"), - strAttr("terraform_version", "stack-2-terraform-version"), + str("backend_prefix", "stack-2-backend"), + str("provider_data", "stack-2-provider-data"), + str("provider_version", "stack-2-provider-version"), + str("terraform_version", "stack-2-terraform-version"), ), }, }, @@ -150,19 +171,19 @@ func TestGenerateHCL(t *testing.T) { files: map[string]fmt.Stringer{ "backend.tf": backend( labels("test"), - strAttr("prefix", "stack-1-backend"), + str("prefix", "stack-1-backend"), ), "locals.tf": locals( - strAttr("local_a", "stack-1-local"), - boolAttr("local_b", true), - numberAttr("local_c", 666), - strAttr("local_d", "local_d_field"), - strAttr("stackpath", "/stacks/stack-1"), + str("local_a", "stack-1-local"), + boolean("local_b", true), + number("local_c", 666), + str("local_d", "local_d_field"), + str("stackpath", "/stacks/stack-1"), ), "provider.tf": hcldoc( provider( labels("name"), - strAttr("data", "stack-1-provider-data"), + str("data", "stack-1-provider-data"), ), terraform( requiredProviders( @@ -173,7 +194,7 @@ func TestGenerateHCL(t *testing.T) { ), ), terraform( - strAttr("required_version", "stack-1-terraform-version"), + str("required_version", "stack-1-terraform-version"), ), ), }, @@ -183,19 +204,19 @@ func TestGenerateHCL(t *testing.T) { files: map[string]fmt.Stringer{ "backend.tf": backend( labels("test"), - strAttr("prefix", "stack-2-backend"), + str("prefix", "stack-2-backend"), ), "locals.tf": locals( - strAttr("local_a", "stack-2-local"), - boolAttr("local_b", false), - numberAttr("local_c", 777), + str("local_a", "stack-2-local"), + boolean("local_b", false), + number("local_c", 777), attr("local_d", "null"), - strAttr("stackpath", "/stacks/stack-2"), + str("stackpath", "/stacks/stack-2"), ), "provider.tf": hcldoc( provider( labels("name"), - strAttr("data", "stack-2-provider-data"), + str("data", "stack-2-provider-data"), ), terraform( requiredProviders( @@ -206,7 +227,7 @@ func TestGenerateHCL(t *testing.T) { ), ), terraform( - strAttr("required_version", "stack-2-terraform-version"), + str("required_version", "stack-2-terraform-version"), ), ), }, @@ -239,9 +260,9 @@ func TestGenerateHCL(t *testing.T) { labels("traversal.tf"), content( block("traversal", - exprAttr("locals", "local.hi"), - exprAttr("some_anything", "something.should_work"), - exprAttr("multiple_traversal", "one.two.three.four.five"), + expr("locals", "local.hi"), + expr("some_anything", "something.should_work"), + expr("multiple_traversal", "one.two.three.four.five"), ), ), ), @@ -254,9 +275,9 @@ func TestGenerateHCL(t *testing.T) { files: map[string]fmt.Stringer{ "traversal.tf": hcldoc( block("traversal", - exprAttr("locals", "local.hi"), - exprAttr("multiple_traversal", "one.two.three.four.five"), - exprAttr("some_anything", "something.should_work"), + expr("locals", "local.hi"), + expr("multiple_traversal", "one.two.three.four.five"), + expr("some_anything", "something.should_work"), ), ), }, @@ -266,9 +287,9 @@ func TestGenerateHCL(t *testing.T) { files: map[string]fmt.Stringer{ "traversal.tf": hcldoc( block("traversal", - exprAttr("locals", "local.hi"), - exprAttr("multiple_traversal", "one.two.three.four.five"), - exprAttr("some_anything", "something.should_work"), + expr("locals", "local.hi"), + expr("multiple_traversal", "one.two.three.four.five"), + expr("some_anything", "something.should_work"), ), ), }, @@ -387,7 +408,7 @@ func TestWontOverwriteManuallyDefinedTerraform(t *testing.T) { labels(genFilename), content( terraform( - strAttr("required_version", "1.11"), + str("required_version", "1.11"), ), ), ) @@ -416,12 +437,12 @@ func TestGenerateHCLOverwriting(t *testing.T) { labels(genFilename), content( terraform( - strAttr("required_version", "1.11"), + str("required_version", "1.11"), ), ), ) firstWant := terraform( - strAttr("required_version", "1.11"), + str("required_version", "1.11"), ) s := sandbox.New(t) @@ -446,12 +467,12 @@ func TestGenerateHCLOverwriting(t *testing.T) { labels(genFilename), content( terraform( - strAttr("required_version", "2.0"), + str("required_version", "2.0"), ), ), ) secondWant := terraform( - strAttr("required_version", "2.0"), + str("required_version", "2.0"), ) rootConfig.Write(secondConfig.String()) @@ -487,7 +508,7 @@ func TestGeneratedHCLHeaders(t *testing.T) { labels(rootFilename), content( block("root", - strAttr("attr", "root"), + str("attr", "root"), ), ), ).String(), @@ -500,7 +521,7 @@ func TestGeneratedHCLHeaders(t *testing.T) { labels(stackFilename), content( block("stack", - strAttr("attr", "stack"), + str("attr", "stack"), ), ), ), @@ -532,7 +553,7 @@ func TestGenerateHCLCleanupOldFiles(t *testing.T) { labels("file1.tf"), content( block("block1", - boolAttr("whatever", true), + boolean("whatever", true), ), ), ), @@ -540,7 +561,7 @@ func TestGenerateHCLCleanupOldFiles(t *testing.T) { labels("file2.tf"), content( block("block2", - boolAttr("whatever", true), + boolean("whatever", true), ), ), ), @@ -567,7 +588,7 @@ func TestGenerateHCLCleanupOldFiles(t *testing.T) { labels("file1.tf"), content( block("changed", - boolAttr("newstuff", true), + boolean("newstuff", true), ), ), ), @@ -608,8 +629,64 @@ func TestGenerateHCLCleanupOldFiles(t *testing.T) { }, }) + // Block with condition = false will be ignored + rootConfig.Write( + hcldoc( + generateHCL( + labels("file1.tf"), + boolean("condition", false), + content( + block("test", + boolean("test", true), + ), + ), + ), + generateHCL( + labels("file2.tf"), + boolean("condition", true), + content( + block("test", + boolean("test", true), + ), + ), + ), + ).String(), + ) + + assertEqualReports(t, s.Generate(), generate.Report{ + Successes: []generate.Result{ + { + StackPath: "/stack", + Created: []string{"file2.tf"}, + }, + }, + }) + got = stackEntry.ListGenFiles() + assertEqualStringList(t, got, []string{"file2.tf"}) + + // Block changed to condition = false will be deleted + rootConfig.Write( + hcldoc( + generateHCL( + labels("file2.tf"), + boolean("condition", false), + content( + block("test", + boolean("test", true), + ), + ), + ), + ).String(), + ) + + assertEqualReports(t, s.Generate(), generate.Report{ + Successes: []generate.Result{ + { + StackPath: "/stack", + Deleted: []string{"file2.tf"}, + }, + }, + }) got = stackEntry.ListGenFiles() assertEqualStringList(t, got, []string{}) - - assertEqualReports(t, s.Generate(), generate.Report{}) } diff --git a/generate/generate_hclwrite_utils_test.go b/generate/generate_hclwrite_utils_test.go index 2494989cb..8c398c12a 100644 --- a/generate/generate_hclwrite_utils_test.go +++ b/generate/generate_hclwrite_utils_test.go @@ -42,19 +42,19 @@ func content(builders ...hclwrite.BlockBuilder) *hclwrite.Block { return hclwrite.BuildBlock("content", builders...) } -func exprAttr(name string, expr string) hclwrite.BlockBuilder { +func expr(name string, expr string) hclwrite.BlockBuilder { return hclwrite.Expression(name, expr) } -func strAttr(name string, val string) hclwrite.BlockBuilder { +func str(name string, val string) hclwrite.BlockBuilder { return hclwrite.String(name, val) } -func numberAttr(name string, val int64) hclwrite.BlockBuilder { +func number(name string, val int64) hclwrite.BlockBuilder { return hclwrite.NumberInt(name, val) } -func boolAttr(name string, val bool) hclwrite.BlockBuilder { +func boolean(name string, val bool) hclwrite.BlockBuilder { return hclwrite.Boolean(name, val) } diff --git a/generate/generate_test.go b/generate/generate_test.go index c671c2e4b..20105a753 100644 --- a/generate/generate_test.go +++ b/generate/generate_test.go @@ -31,7 +31,7 @@ import ( ) type ( - str string + stringer string genFileChecker func(*testing.T, string, string) @@ -54,7 +54,7 @@ type ( } ) -func (s str) String() string { +func (s stringer) String() string { return string(s) }