Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
}
32 changes: 18 additions & 14 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 @@ -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()
Expand All @@ -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
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