From 956fbf5d56362cf75ac2d9963a1670a9e3e50b4c Mon Sep 17 00:00:00 2001 From: Leo Antoli <430982+lantoli@users.noreply.github.com> Date: Fri, 28 Mar 2025 08:49:52 +0100 Subject: [PATCH 1/5] update version to 2.0.2 --- .github/workflows/code-health.yml | 4 ++-- Makefile | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/code-health.yml b/.github/workflows/code-health.yml index 9005a20..befc4db 100644 --- a/.github/workflows/code-health.yml +++ b/.github/workflows/code-health.yml @@ -46,9 +46,9 @@ jobs: go-version-file: 'go.mod' cache: false # see https://github.com/golangci/golangci-lint-action/issues/807 - name: golangci-lint - uses: golangci/golangci-lint-action@55c2c1448f86e01eaae002a5a3a9624417608d84 + uses: golangci/golangci-lint-action@1481404843c368bc19ca9406f87d6e0fc97bdcfd with: - version: v1.64.7 # Also update GOLANGCI_VERSION variable in GNUmakefile when updating this version + version: v2.0.2 # Also update GOLANGCI_VERSION variable in GNUmakefile when updating this version - name: actionlint run: | make tools diff --git a/Makefile b/Makefile index 124838b..afdebdf 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ CLI_DESTINATION=./bin/$(CLI_BINARY_NAME) MANIFEST_FILE?=./bin/manifest.yml WIN_MANIFEST_FILE?=./bin/manifest.windows.yml -GOLANGCI_VERSION=v1.64.7 # Also update golangci-lint GH action in code-health.yml when updating this version +GOLANGCI_VERSION=v2.0.2 # Also update golangci-lint GH action in code-health.yml when updating this version .PHONY: build build: ## Generate the binary in ./bin From 3d35e31080913e277f397da87b873e9f306ee0fd Mon Sep 17 00:00:00 2001 From: Leo Antoli <430982+lantoli@users.noreply.github.com> Date: Fri, 28 Mar 2025 08:51:46 +0100 Subject: [PATCH 2/5] golangci-lint migrate --- .golangci.yml | 181 ++++++++++++++++++++++++++------------------------ 1 file changed, 93 insertions(+), 88 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index db8910f..fc9efee 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,107 +1,112 @@ -linters-settings: - gocritic: - enabled-tags: - - diagnostic - - experimental - - opinionated - - performance - - style - govet: - enable-all: true - - revive: - # see https://github.com/mgechev/revive#available-rules for details. - ignore-generated-header: true - severity: warning - rules: - - name: blank-imports - - name: context-as-argument - - name: context-keys-type - - name: dot-imports - - name: error-return - - name: error-strings - - name: error-naming - - name: errorf - - name: exported - - name: indent-error-flow - - name: if-return - - name: increment-decrement - - name: var-naming - - name: var-declaration - - name: package-comments - - name: range - - name: receiver-naming - - name: time-naming - - name: unexported-return - - name: indent-error-flow - - name: errorf - - name: empty-block - - name: superfluous-else - - name: struct-tag - # Too many unusued parameters, skipping this check for now - #- name: unused-parameter - - name: unreachable-code - - name: redefines-builtin-id - misspell: - locale: US - ignore-words: - - cancelled - lll: - # Default is 120. '\t' is counted as 1 character. - # set our project to 500, as we are adding open api field description in the schema. - # also, for anyone using vscode, use the following configs: - # "rewrap.wrappingColumn": 500 ... requires the rewrap plugin - # "editor.rulers": [500] - line-length: 500 - nestif: - # minimal complexity of if statements to report, 5 by default - min-complexity: 7 - mnd: - checks: - - case - - operation - - return - funlen: - lines: 360 - statements: 120 +version: "2" +run: + build-tags: + - integration + modules-download-mode: readonly + tests: true linters: - disable-all: true + default: none enable: + - copyloopvar - dogsled - errcheck + - exhaustive - funlen - gocritic - - gofmt - - goimports - - revive - - mnd - goprintffuncname - gosec - - gosimple - govet - ineffassign - lll + - makezero - misspell + - mnd - nakedret + - noctx - nolintlint + - revive - rowserrcheck - - copyloopvar - staticcheck - - stylecheck - - typecheck - - unconvert - - unused - - whitespace - - thelper - testifylint - - exhaustive - - makezero - - noctx - testpackage + - thelper + - unconvert + - unused - usetesting -run: - timeout: 10m - tests: true - build-tags: - - integration - modules-download-mode: readonly + - whitespace + settings: + funlen: + lines: 360 + statements: 120 + gocritic: + enabled-tags: + - diagnostic + - experimental + - opinionated + - performance + - style + govet: + enable-all: true + lll: + line-length: 500 + misspell: + locale: US + ignore-rules: + - cancelled + mnd: + checks: + - case + - operation + - return + nestif: + min-complexity: 7 + revive: + severity: warning + rules: + - name: blank-imports + - name: context-as-argument + - name: context-keys-type + - name: dot-imports + - name: error-return + - name: error-strings + - name: error-naming + - name: errorf + - name: exported + - name: indent-error-flow + - name: if-return + - name: increment-decrement + - name: var-naming + - name: var-declaration + - name: package-comments + - name: range + - name: receiver-naming + - name: time-naming + - name: unexported-return + - name: indent-error-flow + - name: errorf + - name: empty-block + - name: superfluous-else + - name: struct-tag + - name: unreachable-code + - name: redefines-builtin-id + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + paths: + - third_party$ + - builtin$ + - examples$ +formatters: + enable: + - gofmt + - goimports + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ From 2943b551354fa80b58fed2ab13ed302550954293 Mon Sep 17 00:00:00 2001 From: Leo Antoli <430982+lantoli@users.noreply.github.com> Date: Fri, 28 Mar 2025 09:08:03 +0100 Subject: [PATCH 3/5] keep lll with default line length --- .golangci.yml | 2 -- internal/cli/clu2adv/clu2adv.go | 16 ++++++++++------ internal/convert/convert.go | 32 ++++++++++++++++++-------------- 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index fc9efee..a36246e 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -47,8 +47,6 @@ linters: - style govet: enable-all: true - lll: - line-length: 500 misspell: locale: US ignore-rules: diff --git a/internal/cli/clu2adv/clu2adv.go b/internal/cli/clu2adv/clu2adv.go index 691a5d3..68bbb9d 100644 --- a/internal/cli/clu2adv/clu2adv.go +++ b/internal/cli/clu2adv/clu2adv.go @@ -9,9 +9,10 @@ import ( func Builder() *cobra.Command { o := &opts{fs: afero.NewOsFs()} cmd := &cobra.Command{ - Use: "clusterToAdvancedCluster", - Short: "Convert cluster to advanced_cluster preview provider 2.0.0", - Long: "Convert a Terraform configuration from mongodbatlas_cluster to mongodbatlas_advanced_cluster preview provider 2.0.0", + Use: "clusterToAdvancedCluster", + Short: "Convert cluster to advanced_cluster preview provider 2.0.0", + Long: "Convert a Terraform configuration from mongodbatlas_cluster to " + + "mongodbatlas_advanced_cluster preview provider 2.0.0", Aliases: []string{"clu2adv"}, RunE: func(_ *cobra.Command, _ []string) error { if err := o.PreRun(); err != nil { @@ -24,8 +25,11 @@ func Builder() *cobra.Command { _ = cmd.MarkFlagRequired(flag.File) cmd.Flags().StringVarP(&o.output, flag.Output, flag.OutputShort, "", "output file") _ = cmd.MarkFlagRequired(flag.Output) - cmd.Flags().BoolVarP(&o.replaceOutput, flag.ReplaceOutput, flag.ReplaceOutputShort, false, "replace output file if exists") - cmd.Flags().BoolVarP(&o.watch, flag.Watch, flag.WatchShort, false, "keeps the plugin running and watches the input file for changes") - cmd.Flags().BoolVarP(&o.includeMoved, flag.IncludeMoved, flag.IncludeMovedShort, false, "include moved blocks in the output file") + cmd.Flags().BoolVarP(&o.replaceOutput, flag.ReplaceOutput, flag.ReplaceOutputShort, false, + "replace output file if exists") + cmd.Flags().BoolVarP(&o.watch, flag.Watch, flag.WatchShort, false, + "keeps the plugin running and watches the input file for changes") + cmd.Flags().BoolVarP(&o.includeMoved, flag.IncludeMoved, flag.IncludeMovedShort, false, + "include moved blocks in the output file") return cmd } diff --git a/internal/convert/convert.go b/internal/convert/convert.go index 23b2d32..c8ad0d4 100644 --- a/internal/convert/convert.go +++ b/internal/convert/convert.go @@ -48,7 +48,8 @@ type attrVals struct { // ClusterToAdvancedCluster transforms all mongodbatlas_cluster definitions in a // Terraform configuration file into mongodbatlas_advanced_cluster schema 2.0.0. // All other resources and data sources are left untouched. -// Note: hclwrite.Tokens are used instead of cty.Value so expressions with interpolations like var.region can be preserved. +// Note: hclwrite.Tokens are used instead of cty.Value so expressions with +// interpolations like var.region can be preserved. // cty.Value only supports literal expressions. func ClusterToAdvancedCluster(config []byte, includeMoved bool) ([]byte, error) { var moveLabels []string @@ -216,7 +217,7 @@ func fillReplicationSpecs(resourceb *hclwrite.Body, root attrVals) error { break } specbSrc := specSrc.Body() - d, err := fillReplicationSpecsWithDynamicRegionConfigs(specbSrc, root, false) + d, err := fillWithDynamicRegionConfigs(specbSrc, root, false) if err != nil { return err } @@ -333,7 +334,7 @@ func fillReplicationSpecsWithDynamicBlock(resourceb *hclwrite.Body, root attrVal return dynamicBlock{}, err } transformDynamicBlockReferences(dSpec.content.Body(), nRepSpecs, nSpec) - dConfig, err := fillReplicationSpecsWithDynamicRegionConfigs(dSpec.content.Body(), root, true) + dConfig, err := fillWithDynamicRegionConfigs(dSpec.content.Body(), root, true) if err != nil { return dynamicBlock{}, err } @@ -344,8 +345,8 @@ func fillReplicationSpecsWithDynamicBlock(resourceb *hclwrite.Body, root attrVal return dSpec, nil } -// fillReplicationSpecsWithDynamicRegionConfigs is used for dynamic blocks in region_configs -func fillReplicationSpecsWithDynamicRegionConfigs(specbSrc *hclwrite.Body, root attrVals, transformRegionReferences bool) (dynamicBlock, error) { +// fillWithDynamicRegionConfigs is used for dynamic blocks in region_configs +func fillWithDynamicRegionConfigs(specbSrc *hclwrite.Body, root attrVals, changeReferences bool) (dynamicBlock, error) { d, err := getDynamicBlock(specbSrc, nConfigSrc) if err != nil || !d.IsPresent() { return dynamicBlock{}, err @@ -356,15 +357,16 @@ func fillReplicationSpecsWithDynamicRegionConfigs(specbSrc *hclwrite.Body, root repSpecb.SetAttributeRaw(nZoneName, hcl.TokensFromExpr(zoneName)) } forEach := hcl.GetAttrExpr(d.forEach) - if transformRegionReferences { + if changeReferences { forEach = replaceDynamicBlockReferences(forEach, nRepSpecs, nSpec) } - regionFor, err := getDynamicBlockRegionConfigsRegionArray(forEach, d.content, root) + regionFor, err := getDynamicBlockRegionArray(forEach, d.content, root) if err != nil { return dynamicBlock{}, err } + priorityForStr := fmt.Sprintf("for %s in range(%d, %d, -1) : ", nPriority, valMaxPriority, valMinPriority) priorityFor := hcl.TokensComment(commentPriorityFor) - priorityFor = append(priorityFor, hcl.TokensFromExpr(fmt.Sprintf("for %s in range(%d, %d, -1) : ", nPriority, valMaxPriority, valMinPriority))...) + priorityFor = append(priorityFor, hcl.TokensFromExpr(priorityForStr)...) priorityFor = append(priorityFor, regionFor...) repSpecb.SetAttributeRaw(nConfig, hcl.TokensFuncFlatten(priorityFor)) @@ -425,7 +427,7 @@ func getRegionConfig(configSrc *hclwrite.Block, root attrVals, isDynamicBlock bo return file, nil } -func getSpecs(configSrc *hclwrite.Block, countName string, root attrVals, isDynamicBlock bool) (hclwrite.Tokens, error) { +func getSpecs(configSrc *hclwrite.Block, countName string, root attrVals, dynamicBlock bool) (hclwrite.Tokens, error) { var ( file = hclwrite.NewEmptyFile() fileb = file.Body() @@ -449,7 +451,7 @@ func getSpecs(configSrc *hclwrite.Block, countName string, root attrVals, isDyna fileb.SetAttributeRaw(nDiskIOPS, root.opt[nDiskIOPSSrc]) } tokens := hcl.TokensObject(fileb) - if isDynamicBlock { + if dynamicBlock { tokens = append(hcl.TokensFromExpr(fmt.Sprintf("%s == 0 ? null :", hcl.GetAttrExpr(count))), tokens...) } return tokens, nil @@ -556,9 +558,9 @@ func replaceDynamicBlockExpr(attr *hclwrite.Attribute, blockName, attrName strin return strings.ReplaceAll(expr, fmt.Sprintf("%s.%s", blockName, attrName), attrName) } -// getDynamicBlockRegionConfigsRegionArray returns the region array for a dynamic block in replication_specs. +// getDynamicBlockRegionArray returns the region array for a dynamic block in replication_specs. // e.g. [ for region in var.replication_specs.regions_config : { ... } if priority == region.priority ] -func getDynamicBlockRegionConfigsRegionArray(forEach string, configSrc *hclwrite.Block, root attrVals) (hclwrite.Tokens, error) { +func getDynamicBlockRegionArray(forEach string, configSrc *hclwrite.Block, root attrVals) (hclwrite.Tokens, error) { transformDynamicBlockReferences(configSrc.Body(), nConfigSrc, nRegion) priorityStr := hcl.GetAttrExpr(configSrc.Body().GetAttribute(nPriority)) if priorityStr == "" { @@ -581,7 +583,8 @@ func transformDynamicBlockReferences(configSrcb *hclwrite.Body, blockName, varNa } } -// replaceDynamicBlockReferences changes value references, e.g. regions_config.value.electable_nodes to region.electable_nodes +// replaceDynamicBlockReferences changes value references, +// e.g. regions_config.value.electable_nodes to region.electable_nodes func replaceDynamicBlockReferences(expr, blockName, varName string) string { return strings.ReplaceAll(expr, fmt.Sprintf("%s.%s.", blockName, nValue), @@ -606,7 +609,8 @@ func setKeyValue(body *hclwrite.Body, key, value *hclwrite.Attribute) { keyStr, err := hcl.GetAttrString(key, "") if err == nil { if !hclsyntax.ValidIdentifier(keyStr) { - keyStr = strconv.Quote(keyStr) // wrap in quotes so invalid identifiers (e.g. with blanks) can be used as attribute names + // wrap in quotes so invalid identifiers (e.g. with blanks) can be used as attribute names + keyStr = strconv.Quote(keyStr) } } else { keyStr = strings.TrimSpace(string(key.Expr().BuildTokens(nil).Bytes())) From 20b0b1b5801557c20776cd8702c95ab14e6d2e5b Mon Sep 17 00:00:00 2001 From: Leo Antoli <430982+lantoli@users.noreply.github.com> Date: Fri, 28 Mar 2025 09:13:55 +0100 Subject: [PATCH 4/5] simplify config --- .golangci.yml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index a36246e..18f77ef 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,7 +1,5 @@ version: "2" run: - build-tags: - - integration modules-download-mode: readonly tests: true linters: @@ -49,8 +47,6 @@ linters: enable-all: true misspell: locale: US - ignore-rules: - - cancelled mnd: checks: - case @@ -94,17 +90,7 @@ linters: - common-false-positives - legacy - std-error-handling - paths: - - third_party$ - - builtin$ - - examples$ formatters: enable: - gofmt - goimports - exclusions: - generated: lax - paths: - - third_party$ - - builtin$ - - examples$ From 5deea8ef4c96b4527c783b0b541336fe660a9dca Mon Sep 17 00:00:00 2001 From: Leo Antoli <430982+lantoli@users.noreply.github.com> Date: Fri, 28 Mar 2025 09:18:56 +0100 Subject: [PATCH 5/5] getSpec --- internal/convert/convert.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/convert/convert.go b/internal/convert/convert.go index c8ad0d4..ca76441 100644 --- a/internal/convert/convert.go +++ b/internal/convert/convert.go @@ -412,13 +412,13 @@ func getRegionConfig(configSrc *hclwrite.Block, root attrVals, isDynamicBlock bo if err := hcl.MoveAttr(configSrc.Body(), fileb, nPriority, nPriority, errRepSpecs); err != nil { return nil, err } - if electable, _ := getSpecs(configSrc, nElectableNodes, root, isDynamicBlock); electable != nil { + if electable, _ := getSpec(configSrc, nElectableNodes, root, isDynamicBlock); electable != nil { fileb.SetAttributeRaw(nElectableSpecs, electable) } - if readOnly, _ := getSpecs(configSrc, nReadOnlyNodes, root, isDynamicBlock); readOnly != nil { + if readOnly, _ := getSpec(configSrc, nReadOnlyNodes, root, isDynamicBlock); readOnly != nil { fileb.SetAttributeRaw(nReadOnlySpecs, readOnly) } - if analytics, _ := getSpecs(configSrc, nAnalyticsNodes, root, isDynamicBlock); analytics != nil { + if analytics, _ := getSpec(configSrc, nAnalyticsNodes, root, isDynamicBlock); analytics != nil { fileb.SetAttributeRaw(nAnalyticsSpecs, analytics) } if autoScaling := getAutoScalingOpt(root.opt); autoScaling != nil { @@ -427,7 +427,7 @@ func getRegionConfig(configSrc *hclwrite.Block, root attrVals, isDynamicBlock bo return file, nil } -func getSpecs(configSrc *hclwrite.Block, countName string, root attrVals, dynamicBlock bool) (hclwrite.Tokens, error) { +func getSpec(configSrc *hclwrite.Block, countName string, root attrVals, isDynamicBlock bool) (hclwrite.Tokens, error) { var ( file = hclwrite.NewEmptyFile() fileb = file.Body() @@ -451,7 +451,7 @@ func getSpecs(configSrc *hclwrite.Block, countName string, root attrVals, dynami fileb.SetAttributeRaw(nDiskIOPS, root.opt[nDiskIOPSSrc]) } tokens := hcl.TokensObject(fileb) - if dynamicBlock { + if isDynamicBlock { tokens = append(hcl.TokensFromExpr(fmt.Sprintf("%s == 0 ? null :", hcl.GetAttrExpr(count))), tokens...) } return tokens, nil