From 4d884a75c952794e80dd5d35db0d6b7585f239f0 Mon Sep 17 00:00:00 2001 From: Tomer Heber Date: Tue, 24 Sep 2024 11:59:35 -0500 Subject: [PATCH] linter fixes --- .github/workflows/ci.yml | 5 ---- .golangci.yaml | 33 ++++++++++++++++++++++++ cli/args.go | 4 ++- cmd/terratag/main.go | 4 +++ internal/convert/convert.go | 10 ++++++++ internal/convert/terratag_locals.go | 8 ++++-- internal/file/file.go | 3 +++ internal/providers/providers.go | 22 ++++++++++------ internal/tag_keys/tag_keys.go | 4 ++- internal/tagging/aws.go | 9 ++++++- internal/tagging/azure.go | 3 +++ internal/tagging/gcp.go | 2 ++ internal/tagging/tagging.go | 2 ++ internal/terraform/terraform.go | 11 +++++--- internal/tfschema/tfschema.go | 9 ++++++- internal/utils/utils.go | 5 +++- terratag.go | 26 ++++++++++++++++--- terratag_test.go | 40 +++++++++++++++++++++-------- 18 files changed, 163 insertions(+), 37 deletions(-) create mode 100644 .golangci.yaml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 567e44b..33cb99e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,11 +22,6 @@ jobs: - name: Go vet run: | ! go vet ./... | read - - name: Go staticcheck - uses: dominikh/staticcheck-action@v1.3.0 - with: - version: "2023.1.3" - install-go: false - name: Go Test run: SKIP_INTEGRATION_TESTS=1 go test -v ./... diff --git a/.golangci.yaml b/.golangci.yaml new file mode 100644 index 0000000..c2815a2 --- /dev/null +++ b/.golangci.yaml @@ -0,0 +1,33 @@ +linters: + enable: + - errname + - errorlint + - gocheckcompilerdirectives + - gochecknoglobals + - gochecknoinits + - goconst + - gocritic + - misspell + - nilerr + - nilnil + - nlreturn + - perfsprint + - prealloc + - predeclared + - reassign + - sloglint + - spancheck + - testifylint + - unparam + - unused + - usestdlibvars + - wsl + +linters-settings: + errorlint: + asserts: false + errcheck: + exclude-functions: + - (*github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.ResourceData).Set + goconst: + ignore-tests: true diff --git a/cli/args.go b/cli/args.go index fa0eac7..36abdc5 100644 --- a/cli/args.go +++ b/cli/args.go @@ -27,9 +27,11 @@ func validate(args Args) error { if args.Tags == "" { return errors.New("missing tags") } + if args.Type != string(common.Terraform) && args.Type != string(common.Terragrunt) { return fmt.Errorf("invalid type %s, must be either 'terratag' or 'terragrunt'", args.Type) } + return nil } @@ -52,7 +54,7 @@ func InitArgs() (Args, error) { fs.BoolVar(&args.DefaultToTerraform, "default-to-terraform", false, "By default uses OpenTofu (if installed), if set will use Terraform even when Opentofu is installed") // Set cli args based on environment variables. - //The command line flags have precedence over environment variables. + // The command line flags have precedence over environment variables. fs.VisitAll(func(f *flag.Flag) { if f.Name == "version" { return diff --git a/cmd/terratag/main.go b/cmd/terratag/main.go index dd2b67f..9e4e3b8 100644 --- a/cmd/terratag/main.go +++ b/cmd/terratag/main.go @@ -19,15 +19,19 @@ func main() { if err != nil { fmt.Println(err) fmt.Println("Usage: terratag -tags='{ \"some_tag\": \"value\" }' [-dir=\".\"]") + return } if args.Version { var versionPrefix string + if !strings.HasPrefix(version, "v") { versionPrefix = "v" } + fmt.Printf("Terratag %s%s\n", versionPrefix, version) + return } diff --git a/internal/convert/convert.go b/internal/convert/convert.go index af84f58..fcfac33 100644 --- a/internal/convert/convert.go +++ b/internal/convert/convert.go @@ -21,6 +21,7 @@ func GetExistingTagsExpression(tokens hclwrite.Tokens) string { func isHclMap(tokens hclwrite.Tokens) bool { maybeHclMap := strings.TrimSpace(string(tokens.Bytes())) + return strings.HasPrefix(maybeHclMap, "{") && strings.HasSuffix(maybeHclMap, "}") } @@ -42,6 +43,7 @@ func AppendLocalsBlock(file *hclwrite.File, filename string, terratag common.Ter if block.Type() != "locals" { continue } + if block.Body().GetAttribute(key) == nil { continue } @@ -64,7 +66,9 @@ func AppendTagBlocks(resource *hclwrite.Block, tags string) error { if err := json.Unmarshal([]byte(tags), &tagsMap); err != nil { return err } + keys := utils.SortObjectKeys(tagsMap) + for _, key := range keys { resource.Body().AppendNewline() tagBlock := resource.Body().AppendNewBlock("tag", nil) @@ -91,6 +95,7 @@ func UnquoteTagsAttribute(swappedTagsStrings []string, text string) string { text = strings.ReplaceAll(text, escapedByWriter, swappedTagString) } + return text } @@ -103,6 +108,7 @@ func MoveExistingTags(filename string, terratag common.TerratagLocal, block *hcl if tagsAttribute != nil { // If attribute found, get its value log.Print("Pre-existing " + tagId + " ATTRIBUTE found on resource. Merging.") + existingTags = quoteAttributeKeys(tagsAttribute) } else { // Otherwise, we try to get tags as block @@ -120,8 +126,10 @@ func MoveExistingTags(filename string, terratag common.TerratagLocal, block *hcl if existingTags != nil { terratag.Found[tag_keys.GetResourceExistingTagsKey(filename, block)] = existingTags + return true, nil } + return false, nil } @@ -132,6 +140,7 @@ func quoteBlockKeys(tagsBlock *hclwrite.Block) *hclwrite.Block { for key, value := range tagsBlock.Body().Attributes() { quotedTagBlock.Body().SetAttributeRaw("\""+key+"\"", value.Expr().BuildTokens(hclwrite.Tokens{})) } + return quotedTagBlock } @@ -141,6 +150,7 @@ func isTagKeyUnquoted(tags hclwrite.Tokens, index int) bool { func quoteAttributeKeys(tagsAttribute *hclwrite.Attribute) hclwrite.Tokens { var newTags hclwrite.Tokens + tags := tagsAttribute.Expr().BuildTokens(hclwrite.Tokens{}) // if attribute is a variable diff --git a/internal/convert/terratag_locals.go b/internal/convert/terratag_locals.go index 56245aa..10d351f 100644 --- a/internal/convert/terratag_locals.go +++ b/internal/convert/terratag_locals.go @@ -34,11 +34,13 @@ func decodeTerratagLocals(locals Locals, s string) error { func encodeTerratagLocals(locals Locals) string { ret := "{" - // Return it in ordered manner for order consistency (primarly when running tests). - var keys []string + // Return it in ordered manner for order consistency (primarily when running tests). + keys := []string{} + for key := range locals { keys = append(keys, key) } + sort.Strings(keys) for _, key := range keys { @@ -47,6 +49,7 @@ func encodeTerratagLocals(locals Locals) string { ret = strings.TrimSuffix(ret, ", ") ret += "}" + return ret } @@ -54,6 +57,7 @@ func MergeTerratagLocals(attribute *hclwrite.Attribute, added string) (string, e localsAttribute := Locals{} tokens := hclwrite.Tokens{} existingLocalsExpression := stringifyExpression(attribute.BuildTokens(tokens)) + if err := decodeTerratagLocals(localsAttribute, existingLocalsExpression); err != nil { return "", err } diff --git a/internal/file/file.go b/internal/file/file.go index d9e2563..8b06301 100644 --- a/internal/file/file.go +++ b/internal/file/file.go @@ -22,6 +22,7 @@ func ReplaceWithTerratagFile(path string, textContent string, rename bool) error } log.Print("[INFO] Backing up ", path, " to ", backupFilename) + if err := os.Rename(path, backupFilename); err != nil { return err } @@ -37,6 +38,7 @@ func ReplaceWithTerratagFile(path string, textContent string, rename bool) error func CreateFile(path string, textContent string) error { log.Print("[INFO] Creating file ", path) + return os.WriteFile(path, []byte(textContent), 0644) } @@ -44,6 +46,7 @@ func GetFilename(path string) string { _, filename := filepath.Split(path) filename = strings.TrimSuffix(filename, filepath.Ext(path)) filename = strings.ReplaceAll(filename, ".", "-") + return filename } diff --git a/internal/providers/providers.go b/internal/providers/providers.go index 1dec27f..4558aed 100644 --- a/internal/providers/providers.go +++ b/internal/providers/providers.go @@ -4,18 +4,23 @@ import ( "strings" ) +const AWS = "aws" +const GCP = "gcp" +const AZURE = "azure" + var resourcesToSkip = []string{"azurerm_api_management_named_value"} func getProviderByResource(resourceType string) Provider { - if strings.HasPrefix(resourceType, "aws_") { - return "aws" - } else if strings.HasPrefix(resourceType, "google_") { - return "gcp" - } else if strings.HasPrefix(resourceType, "azurerm_") || strings.HasPrefix(resourceType, "azurestack_") { - return "azure" + switch { + case strings.HasPrefix(resourceType, "aws_"): + return AWS + case strings.HasPrefix(resourceType, "google_"): + return GCP + case strings.HasPrefix(resourceType, "azurerm_") || strings.HasPrefix(resourceType, "azurestack_"): + return AZURE + default: + return "" } - - return "" } func IsTaggableByAttribute(resourceType string, attribute string) bool { @@ -25,6 +30,7 @@ func IsTaggableByAttribute(resourceType string, attribute string) bool { if (provider != "") && attribute == tagBlockId { return true } + return false } diff --git a/internal/tag_keys/tag_keys.go b/internal/tag_keys/tag_keys.go index a2d1f70..3a77bf7 100644 --- a/internal/tag_keys/tag_keys.go +++ b/internal/tag_keys/tag_keys.go @@ -1,8 +1,9 @@ package tag_keys import ( - "github.com/hashicorp/hcl/v2/hclwrite" "strings" + + "github.com/hashicorp/hcl/v2/hclwrite" ) func GetTerratagAddedKey(filname string) string { @@ -11,5 +12,6 @@ func GetTerratagAddedKey(filname string) string { func GetResourceExistingTagsKey(filename string, resource *hclwrite.Block) string { delimiter := "__" + return "terratag_found_" + filename + delimiter + strings.Join(resource.Labels(), delimiter) } diff --git a/internal/tagging/aws.go b/internal/tagging/aws.go index b3a2753..17efc41 100644 --- a/internal/tagging/aws.go +++ b/internal/tagging/aws.go @@ -16,6 +16,7 @@ func tagAwsInstance(args TagBlockArgs) (*Result, error) { if err != nil { return nil, err } + swappedTagsStrings = append(swappedTagsStrings, tagBlock) // Tag 'volume_tags' if it exists. @@ -28,10 +29,12 @@ func tagAwsInstance(args TagBlockArgs) (*Result, error) { // Add tags to 'volume_tags' attribute. volumeTagBlockArgs := args volumeTagBlockArgs.TagId = "volume_tags" + volumeTagBlock, err := TagBlock(volumeTagBlockArgs) if err != nil { return nil, err } + swappedTagsStrings = append(swappedTagsStrings, volumeTagBlock) } else { rootBlockDevice := args.Block.Body().FirstMatchingBlock("root_block_device", nil) @@ -43,11 +46,14 @@ func tagAwsInstance(args TagBlockArgs) (*Result, error) { // Add tags to 'root_block_device' block. origArgsBlock := args.Block args.Block = rootBlockDevice + tagBlock, err := TagBlock(args) if err != nil { return nil, err } + swappedTagsStrings = append(swappedTagsStrings, tagBlock) + args.Block = origArgsBlock // Add tags to any 'ebs_block_device' blocks (if any exist). @@ -58,10 +64,12 @@ func tagAwsInstance(args TagBlockArgs) (*Result, error) { origArgsBlock := args.Block args.Block = block + tagBlock, err := TagBlock(args) if err != nil { return nil, err } + swappedTagsStrings = append(swappedTagsStrings, tagBlock) args.Block = origArgsBlock } @@ -72,7 +80,6 @@ func tagAwsInstance(args TagBlockArgs) (*Result, error) { func tagAutoscalingGroup(args TagBlockArgs) (*Result, error) { // https://www.terraform.io/docs/providers/aws/r/autoscaling_group.html - var tagsMap map[string]string if err := json.Unmarshal([]byte(args.Tags), &tagsMap); err != nil { return nil, err diff --git a/internal/tagging/azure.go b/internal/tagging/azure.go index 6732e50..e2bdac8 100644 --- a/internal/tagging/azure.go +++ b/internal/tagging/azure.go @@ -8,16 +8,19 @@ func tagAksK8sCluster(args TagBlockArgs) (*Result, error) { if err != nil { return nil, err } + swappedTagsStrings = append(swappedTagsStrings, tagBlock) // handle default_node_pool tags attribute nodePool := args.Block.Body().FirstMatchingBlock("default_node_pool", nil) if nodePool != nil { args.Block = nodePool + tagBlock, err := TagBlock(args) if err != nil { return nil, err } + swappedTagsStrings = append(swappedTagsStrings, tagBlock) } diff --git a/internal/tagging/gcp.go b/internal/tagging/gcp.go index c304bda..7917f4e 100644 --- a/internal/tagging/gcp.go +++ b/internal/tagging/gcp.go @@ -4,9 +4,11 @@ func tagContainerCluster(args TagBlockArgs) (*Result, error) { rootBlockArgs := args rootBlockArgs.TagId = "resource_labels" tagBlock, err := TagBlock(rootBlockArgs) + if err != nil { return nil, err } + rootBlockSwappedTagsStrings := []string{tagBlock} return &Result{SwappedTagsStrings: rootBlockSwappedTagsStrings}, nil diff --git a/internal/tagging/tagging.go b/internal/tagging/tagging.go index 7dee409..9e3d97a 100644 --- a/internal/tagging/tagging.go +++ b/internal/tagging/tagging.go @@ -26,7 +26,9 @@ func ParseHclValueStringToTokens(hclValueString string) hclwrite.Tokens { log.Print("error parsing hcl value string " + hclValueString) panic(diags.Errs()[0]) } + tempAttribute := file.Body().GetAttribute("tempKey") + return tempAttribute.Expr().BuildTokens(hclwrite.Tokens{}) } diff --git a/internal/terraform/terraform.go b/internal/terraform/terraform.go index 95eb938..fddec52 100644 --- a/internal/terraform/terraform.go +++ b/internal/terraform/terraform.go @@ -28,6 +28,7 @@ func getRootDir(dir string, iacType string) string { return "" } } + return "/.terragrunt-cache" } else { return "/.terraform" @@ -42,7 +43,7 @@ func ValidateInitRun(dir string, iacType string) error { return fmt.Errorf("%s init must run before running terratag", iacType) } - return fmt.Errorf("couldn't determine if %s init has run: %v", iacType, err) + return fmt.Errorf("couldn't determine if %s init has run: %w", iacType, err) } return nil @@ -58,9 +59,11 @@ func GetFilePaths(dir string, iacType string) ([]string, error) { func getTerragruntFilePath(rootDir string) ([]string, error) { var tfFiles []string + if err := filepath.WalkDir(rootDir, func(path string, d fs.DirEntry, err error) error { if err != nil { log.Printf("[WARN] skipping %s due to an error: %v", path, err) + return filepath.SkipDir } @@ -111,10 +114,11 @@ func getTerraformFilePaths(rootDir string) ([]string, error) { } func getTerraformModulesDirPaths(dir string) ([]string, error) { - var paths []string - var modulesJson ModulesJson + paths := []string{} + modulesJson := ModulesJson{} jsonFile, err := os.Open(dir + "/.terraform/modules/modules.json") + //lint:ignore SA5001 not required to check file close status. defer jsonFile.Close() @@ -135,6 +139,7 @@ func getTerraformModulesDirPaths(dir string) ([]string, error) { modulePath, err := filepath.EvalSymlinks(dir + "/" + module.Dir) if os.IsNotExist(err) { log.Print("[WARN] Module not found, skipping.", dir+"/"+module.Dir) + continue } diff --git a/internal/tfschema/tfschema.go b/internal/tfschema/tfschema.go index da8399d..7227525 100644 --- a/internal/tfschema/tfschema.go +++ b/internal/tfschema/tfschema.go @@ -56,13 +56,15 @@ type ProviderSchemas struct { func IsTaggable(dir string, iacType common.IACType, defaultToTerraform bool, resource hclwrite.Block) (bool, error) { var isTaggable bool + resourceType := terraform.GetResourceType(resource) if providers.IsSupportedResource(resourceType) { resourceSchema, err := getResourceSchema(resourceType, resource, dir, iacType, defaultToTerraform) if err != nil { - if err == ErrResourceTypeNotFound { + if errors.Is(err, ErrResourceTypeNotFound) { log.Print("[WARN] Skipped ", resourceType, " as it is not YET supported") + return false, nil } @@ -114,6 +116,7 @@ func getTerragruntCacheFolderPath(dir string) string { func getTerragruntPluginPath(dir string) string { dir += "/.terragrunt-cache" + return getFolderPathHelper(dir, "/.terraform") } @@ -122,6 +125,7 @@ func extractProviderNameFromResourceType(resourceType string) (string, error) { if len(s) < 2 { return "", fmt.Errorf("failed to detect a provider name: %s", resourceType) } + return s[0], nil } @@ -131,6 +135,7 @@ func detectProviderName(resource hclwrite.Block) (string, error) { if providerAttribute != nil { providerTokens := providerAttribute.Expr().BuildTokens(hclwrite.Tokens{}) providerName := strings.Trim(string(providerTokens.Bytes()), "\" ") + if funk.Contains(customSupportedProviderNames, providerName) { return providerName, nil } @@ -176,6 +181,7 @@ func getResourceSchema(resourceType string, resource hclwrite.Block, dir string, for _, line := range bytes.Split(out, []byte("\n")) { if len(line) > 0 && line[0] == '{' { out = line + break } } @@ -184,6 +190,7 @@ func getResourceSchema(resourceType string, resource hclwrite.Block, dir string, if e, ok := err.(*json.SyntaxError); ok { log.Printf("syntax error at byte offset %d", e.Offset) } + return nil, fmt.Errorf("failed to unmarshal returned provider schemas: %w", err) } diff --git a/internal/utils/utils.go b/internal/utils/utils.go index 91bb620..68183e8 100644 --- a/internal/utils/utils.go +++ b/internal/utils/utils.go @@ -3,10 +3,13 @@ package utils import "sort" func SortObjectKeys(tagsMap map[string]string) []string { - var keys []string + keys := []string{} + for key := range tagsMap { keys = append(keys, key) } + sort.Strings(keys) + return keys } diff --git a/terratag.go b/terratag.go index b20bbe2..bd08b52 100644 --- a/terratag.go +++ b/terratag.go @@ -63,6 +63,7 @@ func Terratag(args cli.Args) error { } counters := tagDirectoryResources(taggingArgs) + log.Print("[INFO] Summary:") log.Print("[INFO] Tagged ", counters.taggedResources, " resource/s (out of ", counters.totalResources, " resource/s processed)") log.Print("[INFO] In ", counters.taggedFiles, " file/s (out of ", counters.totalFiles, " file/s processed)") @@ -72,6 +73,7 @@ func Terratag(args cli.Args) error { func tagDirectoryResources(args *common.TaggingArgs) counters { var total counters + for _, path := range args.Matches { if args.IsSkipTerratagFiles && strings.HasSuffix(path, "terratag.tf") { log.Print("[INFO] Skipping file ", path, " as it's already tagged") @@ -94,6 +96,7 @@ func tagDirectoryResources(args *common.TaggingArgs) counters { perFile, err := tagFileResources(path, args) if err != nil { log.Printf("[ERROR] failed to process %s due to an error\n%v", path, err) + return } @@ -109,7 +112,9 @@ func tagDirectoryResources(args *common.TaggingArgs) counters { func tagFileResources(path string, args *common.TaggingArgs) (*counters, error) { perFileCounters := counters{} + log.Print("[INFO] Processing file ", path) + var swappedTagsStrings []string hcl, err := file.ReadHCLFile(path) @@ -133,6 +138,7 @@ func tagFileResources(path string, args *common.TaggingArgs) (*counters, error) switch resource.Type() { case "resource": log.Print("[INFO] Processing resource ", resource.Labels()) + perFileCounters.totalResources += 1 matched, err := regexp.MatchString(args.Filter, resource.Labels()[0]) @@ -142,6 +148,7 @@ func tagFileResources(path string, args *common.TaggingArgs) (*counters, error) if !matched { log.Print("[INFO] Resource excluded by filter, skipping.", resource.Labels()) + continue } @@ -150,8 +157,10 @@ func tagFileResources(path string, args *common.TaggingArgs) (*counters, error) if err != nil { return nil, err } + if matched { log.Print("[INFO] Resource excluded by skip, skipping.", resource.Labels()) + continue } } @@ -163,7 +172,9 @@ func tagFileResources(path string, args *common.TaggingArgs) (*counters, error) if isTaggable { log.Print("[INFO] Resource taggable, processing...", resource.Labels()) + perFileCounters.taggedResources += 1 + result, err := tagging.TagResource(tagging.TagBlockArgs{ Filename: filename, Block: resource, @@ -185,19 +196,20 @@ func tagFileResources(path string, args *common.TaggingArgs) (*counters, error) // Instead should override it. attributes := resource.Body().Attributes() key := tag_keys.GetTerratagAddedKey(filename) + for attributeKey, attribute := range attributes { if attributeKey == key { mergedAdded, err := convert.MergeTerratagLocals(attribute, terratag.Added) if err != nil { return nil, err } + terratag.Added = mergedAdded break } } } - } if len(swappedTagsStrings) > 0 { @@ -211,34 +223,40 @@ func tagFileResources(path string, args *common.TaggingArgs) (*counters, error) if err := file.ReplaceWithTerratagFile(path, text, args.Rename); err != nil { return nil, err } + perFileCounters.taggedFiles = 1 } else { log.Print("[INFO] No taggable resources found in file ", path, " - skipping") } + return &perFileCounters, nil } func toHclMap(tags string) (string, error) { var tagsMap map[string]string - err := json.Unmarshal([]byte(tags), &tagsMap) - if err != nil { + + if err := json.Unmarshal([]byte(tags), &tagsMap); err != nil { // If it's not a JSON it might be "key1=value1,key2=value2". tagsMap = make(map[string]string) pairs := strings.Split(tags, ",") + for _, pair := range pairs { match := pairRegex.FindStringSubmatch(pair) if match == nil { return "", fmt.Errorf("invalid input tags! must be a valid JSON or pairs of key=value.\nInput: %s", tags) } + tagsMap[match[1]] = match[2] } } keys := utils.SortObjectKeys(tagsMap) - var mapContent []string + mapContent := []string{} + for _, key := range keys { mapContent = append(mapContent, "\""+key+"\"="+"\""+tagsMap[key]+"\"") } + return "{" + strings.Join(mapContent, ",") + "}", nil } diff --git a/terratag_test.go b/terratag_test.go index f0ac51d..f623139 100644 --- a/terratag_test.go +++ b/terratag_test.go @@ -165,22 +165,29 @@ func testTerraformWithFilter(t *testing.T, version string, filter string, skip s func itShouldGenerateExpectedTerratagFiles(entryDir string, g *GomegaWithT) { expectedPattern := strings.Split(entryDir, "/out/")[0] + "/expected/*.tf" + var expectedTerratag []string + var actualTerratag []string + expectedTerratag, _ = doublestar.Glob(expectedPattern) if len(expectedTerratag) == 0 { expectedPattern = strings.Split(entryDir, "/out/")[0] + "/expected/**/*.tf" expectedTerratag, _ = doublestar.Glob(expectedPattern) } + actualTerratag, _ = doublestar.Glob(entryDir + "/*.tf") + if len(actualTerratag) == 0 { actualTerratag, _ = doublestar.Glob(entryDir + "/**/*.tf") } + actualTerratag = filterSymlink(actualTerratag) g.Expect(len(actualTerratag)).Should(BeNumerically(">", 0)) g.Expect(len(expectedTerratag)).Should(BeNumerically(">", 0)) g.Expect(len(actualTerratag)).To(BeEquivalentTo(len(expectedTerratag)), "it should generate the same number of terratag files as expected") + for i, expectedTerratagFile := range expectedTerratag { expectedFile, _ := os.Open(expectedTerratagFile) expectedContent, _ := io.ReadAll(expectedFile) @@ -194,7 +201,9 @@ func itShouldGenerateExpectedTerratagFiles(entryDir string, g *GomegaWithT) { func getFileSha256(filename string, g *GomegaWithT) string { f, err := os.Open(filename) g.Expect(err).To(BeNil()) + defer f.Close() + h := sha256.New() _, err = io.Copy(h, f) g.Expect(err).To(BeNil()) @@ -271,6 +280,7 @@ func getConfig(terraformDir string) (*TestCaseConfig, error) { if err := viper.ReadInConfig(); err != nil { return nil, err } + if err := viper.Unmarshal(&config); err != nil { return nil, err } @@ -285,7 +295,9 @@ func getEntries(t *testing.T, version string) []TestCase { if err != nil { t.Fatalf("failed to load test case config for version %s: %v", version, err) } + suitesMap := make(map[string]interface{}) + for _, suite := range config.Suites { suitesMap[suite] = nil } @@ -297,7 +309,8 @@ func getEntries(t *testing.T, version string) []TestCase { entryFilesMatcher := "/**/out" + terraformDir + "/**/main.tf" entryFiles, _ := doublestar.Glob(testsDir + entryFilesMatcher) - var testEntries []TestCase + testEntries := []TestCase{} + for _, entryFile := range entryFiles { // convert windows paths to use forward slashes slashed := filepath.ToSlash(entryFile) @@ -356,18 +369,21 @@ func run_terratag(entryDir string, filter string, skip string, terragrunt bool) args, err := cli.InitArgs() os.Args = cleanArgs osArgsLock.Unlock() + if err != nil { return err } - Terratag(args) - return nil + return Terratag(args) } func run(prog string, entryDir string, cmd string) error { println(prog, cmd) + var stdout bytes.Buffer + var stderr bytes.Buffer + command := exec.Command(prog, cmd) command.Dir = entryDir command.Stdout = &stdout @@ -375,6 +391,7 @@ func run(prog string, entryDir string, cmd string) error { if err := command.Run(); err != nil { log.Println(stderr.String()) + return err } @@ -402,6 +419,7 @@ func filterSymlink(ss []string) (ret []string) { ret = append(ret, s) } } + return ret } @@ -417,7 +435,7 @@ func TestToHclMap(t *testing.T) { input, expectedOutput := input, output t.Run("valid input "+input, func(t *testing.T) { output, err := toHclMap(input) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, expectedOutput, output) }) } @@ -466,21 +484,23 @@ func TestEnvVariables(t *testing.T) { os.Args = []string{programName} args, err := cli.InitArgs() os.Args = cleanArgs - require.Nil(t, err) + + require.NoError(t, err) assert.Equal(t, `{"a":"b"}`, args.Tags) assert.Equal(t, "./dir", args.Dir) - assert.Equal(t, true, args.IsSkipTerratagFiles) + assert.True(t, args.IsSkipTerratagFiles) assert.Equal(t, "filter", args.Filter) - assert.Equal(t, "skip", args.Skip) - assert.Equal(t, true, args.Verbose) - assert.Equal(t, false, args.Rename) + assert.True(t, args.Verbose) + assert.False(t, args.Rename) assert.Equal(t, string(common.Terragrunt), args.Type) // The command line flags have precedence over environment variables. os.Args = []string{programName, `-tags={"c":"d"}`} args, err = cli.InitArgs() os.Args = cleanArgs - require.Nil(t, err) + + require.NoError(t, err) + assert.Equal(t, `{"c":"d"}`, args.Tags) }