Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/code-health.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
165 changes: 77 additions & 88 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,107 +1,96 @@
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice to use line-length 🎉

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:
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
misspell:
locale: US
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
formatters:
enable:
- gofmt
- goimports
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
16 changes: 10 additions & 6 deletions internal/cli/clu2adv/clu2adv.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 " +
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

keep line len under 120 chars

"mongodbatlas_advanced_cluster preview provider 2.0.0",
Aliases: []string{"clu2adv"},
RunE: func(_ *cobra.Command, _ []string) error {
if err := o.PreRun(); err != nil {
Expand All @@ -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
}
36 changes: 20 additions & 16 deletions internal/convert/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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
}
Expand All @@ -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
Expand All @@ -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))

Expand Down Expand Up @@ -410,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 {
Expand All @@ -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 getSpec(configSrc *hclwrite.Block, countName string, root attrVals, isDynamicBlock bool) (hclwrite.Tokens, error) {
var (
file = hclwrite.NewEmptyFile()
fileb = file.Body()
Expand Down Expand Up @@ -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 == "" {
Expand All @@ -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),
Expand All @@ -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()))
Expand Down