Skip to content

Commit 1312a94

Browse files
committed
includeMoved
1 parent 109ad0b commit 1312a94

File tree

10 files changed

+299
-10
lines changed

10 files changed

+299
-10
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,11 @@ you can also use shorter aliases, e.g.:
3232
atlas tf clu2adv -f in.tf -o out.tf
3333
```
3434

35-
If you want to overwrite the output file if it exists, or even use the same output file as the input file, use the `--replaceOutput true` or the `-r` flag.
35+
If you want to include the `moved blocks` in the output file, use the `--includeMoved` or the `-m` flag.
3636

37-
You can use the `--watch true` or the `-w` flag to keep the plugin running and watching for changes in the input file. You can have input and output files open in an editor and see easily how changes to the input file affect the output file.
37+
If you want to overwrite the output file if it exists, or even use the same output file as the input file, use the `--replaceOutput` or the `-r` flag.
38+
39+
You can use the `--watch` or the `-w` flag to keep the plugin running and watching for changes in the input file. You can have input and output files open in an editor and see easily how changes to the input file affect the output file.
3840

3941
### Limitations
4042

internal/cli/clu2adv/opts.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ type opts struct {
1616
output string
1717
replaceOutput bool
1818
watch bool
19+
includeMoved bool
1920
}
2021

2122
func (o *opts) PreRun() error {
@@ -43,7 +44,7 @@ func (o *opts) generateFile(allowParseErrors bool) error {
4344
if err != nil {
4445
return fmt.Errorf("failed to read file %s: %w", o.file, err)
4546
}
46-
outConfig, err := convert.ClusterToAdvancedCluster(inConfig)
47+
outConfig, err := convert.ClusterToAdvancedCluster(inConfig, o.includeMoved)
4748
if err != nil {
4849
if allowParseErrors {
4950
outConfig = []byte("# CONVERT ERROR: " + err.Error() + "\n\n")

internal/convert/const_names.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,7 @@ const (
4848
nKey = "key"
4949
nValue = "value"
5050
nUseRepSpecsPerShard = "use_replication_spec_per_shard"
51+
nMoved = "moved"
52+
nFrom = "from"
53+
nTo = "to"
5154
)

internal/convert/convert.go

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,24 +40,33 @@ type attrVals struct {
4040
// All other resources and data sources are left untouched.
4141
// Note: hclwrite.Tokens are used instead of cty.Value so expressions with interpolations like var.region can be preserved.
4242
// cty.Value only supports literal expressions.
43-
func ClusterToAdvancedCluster(config []byte) ([]byte, error) {
43+
func ClusterToAdvancedCluster(config []byte, includeMoved bool) ([]byte, error) {
44+
var moveLabels []string
4445
parser, err := hcl.GetParser(config)
4546
if err != nil {
4647
return nil, err
4748
}
48-
for _, block := range parser.Body().Blocks() {
49-
converted, err := convertResource(block)
49+
parserb := parser.Body()
50+
for _, block := range parserb.Blocks() {
51+
convertedResource, err := convertResource(block)
5052
if err != nil {
51-
return nil, err
53+
return nil,
54+
err
5255
}
53-
converted = converted || convertDataSource(block)
54-
if converted {
56+
if includeMoved && convertedResource {
57+
if moveLabel := getResourceLabel(block); moveLabel != "" {
58+
moveLabels = append(moveLabels, moveLabel)
59+
}
60+
}
61+
convertedDataSource := convertDataSource(block)
62+
if convertedResource || convertedDataSource {
5563
blockb := block.Body()
5664
blockb.AppendNewline()
5765
hcl.AppendComment(blockb, "Generated by atlas-cli-plugin-terraform.")
5866
hcl.AppendComment(blockb, "Please confirm that all references to this resource are updated.")
5967
}
6068
}
69+
fillMovedBlocks(parserb, moveLabels)
6170
return parser.Bytes(), nil
6271
}
6372

@@ -99,6 +108,24 @@ func convertDataSource(block *hclwrite.Block) bool {
99108
return false
100109
}
101110

111+
func fillMovedBlocks(body *hclwrite.Body, moveLabels []string) {
112+
if len(moveLabels) == 0 {
113+
return
114+
}
115+
body.AppendNewline()
116+
hcl.AppendComment(body, "Moved blocks")
117+
body.AppendNewline()
118+
for i, moveLabel := range moveLabels {
119+
block := body.AppendNewBlock(nMoved, nil)
120+
blockb := block.Body()
121+
hcl.SetAttrExpr(blockb, nFrom, fmt.Sprintf("%s.%s", cluster, moveLabel))
122+
hcl.SetAttrExpr(blockb, nTo, fmt.Sprintf("%s.%s", advCluster, moveLabel))
123+
if i < len(moveLabels)-1 {
124+
body.AppendNewline()
125+
}
126+
}
127+
}
128+
102129
// fillFreeTierCluster is the entry point to convert clusters in free tier
103130
func fillFreeTierCluster(resourceb *hclwrite.Body) error {
104131
resourceb.SetAttributeValue(nClusterType, cty.StringVal(valClusterType))
@@ -346,6 +373,14 @@ func getResourceName(resource *hclwrite.Block) string {
346373
return labels[0]
347374
}
348375

376+
func getResourceLabel(resource *hclwrite.Block) string {
377+
labels := resource.Labels()
378+
if len(labels) <= 1 {
379+
return ""
380+
}
381+
return labels[1]
382+
}
383+
349384
func checkDynamicBlock(body *hclwrite.Body) error {
350385
for _, block := range body.Blocks() {
351386
if block.Type() == "dynamic" {

internal/convert/convert_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ func TestClusterToAdvancedCluster(t *testing.T) {
3838
t.Run(testName, func(t *testing.T) {
3939
inConfig, err := afero.ReadFile(fs, inputFile)
4040
require.NoError(t, err)
41-
outConfig, err := convert.ClusterToAdvancedCluster(inConfig)
41+
includeMoved := strings.Contains(testName, "includeMoved")
42+
outConfig, err := convert.ClusterToAdvancedCluster(inConfig, includeMoved)
4243
if err == nil {
4344
g.Assert(t, testName, outConfig)
4445
} else {
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
resource "mongodbatlas_cluster" "cluster1" {
2+
project_id = var.project_id
3+
name = "clu1"
4+
cluster_type = "REPLICASET"
5+
provider_name = "AWS"
6+
provider_instance_size_name = "M10"
7+
replication_specs {
8+
num_shards = 1
9+
regions_config {
10+
region_name = "US_EAST_1"
11+
electable_nodes = 3
12+
priority = 7
13+
}
14+
}
15+
}
16+
17+
resource "mongodbatlas_cluster" "cluster2" {
18+
project_id = var.project_id
19+
name = "clu2"
20+
cluster_type = "REPLICASET"
21+
provider_name = "AWS"
22+
provider_instance_size_name = "M30"
23+
replication_specs {
24+
num_shards = 1
25+
regions_config {
26+
region_name = "US_WEST_2"
27+
electable_nodes = 3
28+
priority = 7
29+
}
30+
}
31+
}
32+
33+
resource "mongodbatlas_cluster" "count" {
34+
# count doesn't affect moved blocks, it works in the same way
35+
count = local.create_cluster ? 1 : 0
36+
project_id = var.project_id
37+
name = "count"
38+
cluster_type = "REPLICASET"
39+
provider_name = "AWS"
40+
provider_instance_size_name = "M30"
41+
replication_specs {
42+
num_shards = 1
43+
regions_config {
44+
region_name = "US_WEST_2"
45+
electable_nodes = 3
46+
priority = 7
47+
}
48+
}
49+
}
50+
51+
resource "mongodbatlas_cluster" "forEach" {
52+
# for_each doesn't affect moved blocks, it works in the same way
53+
for_each = toset(["clu1", "clu2", "clu3"])
54+
project_id = var.project_id
55+
name = each.key
56+
cluster_type = "REPLICASET"
57+
provider_name = "AWS"
58+
provider_instance_size_name = "M30"
59+
replication_specs {
60+
num_shards = 1
61+
regions_config {
62+
region_name = "US_WEST_2"
63+
electable_nodes = 3
64+
priority = 7
65+
}
66+
}
67+
}
68+
69+
resource "another_resource" "another" {
70+
hello = "there"
71+
}
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
resource "mongodbatlas_advanced_cluster" "cluster1" {
2+
project_id = var.project_id
3+
name = "clu1"
4+
cluster_type = "REPLICASET"
5+
replication_specs = [
6+
{
7+
region_configs = [
8+
{
9+
provider_name = "AWS"
10+
region_name = "US_EAST_1"
11+
priority = 7
12+
electable_specs = {
13+
node_count = 3
14+
instance_size = "M10"
15+
}
16+
}
17+
]
18+
}
19+
]
20+
21+
# Generated by atlas-cli-plugin-terraform.
22+
# Please confirm that all references to this resource are updated.
23+
}
24+
25+
resource "mongodbatlas_advanced_cluster" "cluster2" {
26+
project_id = var.project_id
27+
name = "clu2"
28+
cluster_type = "REPLICASET"
29+
replication_specs = [
30+
{
31+
region_configs = [
32+
{
33+
provider_name = "AWS"
34+
region_name = "US_WEST_2"
35+
priority = 7
36+
electable_specs = {
37+
node_count = 3
38+
instance_size = "M30"
39+
}
40+
}
41+
]
42+
}
43+
]
44+
45+
# Generated by atlas-cli-plugin-terraform.
46+
# Please confirm that all references to this resource are updated.
47+
}
48+
49+
resource "mongodbatlas_advanced_cluster" "count" {
50+
# count doesn't affect moved blocks, it works in the same way
51+
count = local.create_cluster ? 1 : 0
52+
project_id = var.project_id
53+
name = "count"
54+
cluster_type = "REPLICASET"
55+
replication_specs = [
56+
{
57+
region_configs = [
58+
{
59+
provider_name = "AWS"
60+
region_name = "US_WEST_2"
61+
priority = 7
62+
electable_specs = {
63+
node_count = 3
64+
instance_size = "M30"
65+
}
66+
}
67+
]
68+
}
69+
]
70+
71+
# Generated by atlas-cli-plugin-terraform.
72+
# Please confirm that all references to this resource are updated.
73+
}
74+
75+
resource "mongodbatlas_advanced_cluster" "forEach" {
76+
# for_each doesn't affect moved blocks, it works in the same way
77+
for_each = toset(["clu1", "clu2", "clu3"])
78+
project_id = var.project_id
79+
name = each.key
80+
cluster_type = "REPLICASET"
81+
replication_specs = [
82+
{
83+
region_configs = [
84+
{
85+
provider_name = "AWS"
86+
region_name = "US_WEST_2"
87+
priority = 7
88+
electable_specs = {
89+
node_count = 3
90+
instance_size = "M30"
91+
}
92+
}
93+
]
94+
}
95+
]
96+
97+
# Generated by atlas-cli-plugin-terraform.
98+
# Please confirm that all references to this resource are updated.
99+
}
100+
101+
resource "another_resource" "another" {
102+
hello = "there"
103+
}
104+
105+
# Moved blocks
106+
107+
moved {
108+
from = mongodbatlas_cluster.cluster1
109+
to = mongodbatlas_advanced_cluster.cluster1
110+
}
111+
112+
moved {
113+
from = mongodbatlas_cluster.cluster2
114+
to = mongodbatlas_advanced_cluster.cluster2
115+
}
116+
117+
moved {
118+
from = mongodbatlas_cluster.count
119+
to = mongodbatlas_advanced_cluster.count
120+
}
121+
122+
moved {
123+
from = mongodbatlas_cluster.forEach
124+
to = mongodbatlas_advanced_cluster.forEach
125+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
resource "mongodbatlas_cluster" "cluster" {
2+
project_id = var.project_id
3+
name = "clu"
4+
cluster_type = "REPLICASET"
5+
provider_name = "AWS"
6+
provider_instance_size_name = "M10"
7+
replication_specs {
8+
num_shards = 1
9+
regions_config {
10+
region_name = "US_EAST_1"
11+
electable_nodes = 3
12+
priority = 7
13+
}
14+
}
15+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
resource "mongodbatlas_advanced_cluster" "cluster" {
2+
project_id = var.project_id
3+
name = "clu"
4+
cluster_type = "REPLICASET"
5+
replication_specs = [
6+
{
7+
region_configs = [
8+
{
9+
provider_name = "AWS"
10+
region_name = "US_EAST_1"
11+
priority = 7
12+
electable_specs = {
13+
node_count = 3
14+
instance_size = "M10"
15+
}
16+
}
17+
]
18+
}
19+
]
20+
21+
# Generated by atlas-cli-plugin-terraform.
22+
# Please confirm that all references to this resource are updated.
23+
}
24+
25+
# Moved blocks
26+
27+
moved {
28+
from = mongodbatlas_cluster.cluster
29+
to = mongodbatlas_advanced_cluster.cluster
30+
}

internal/hcl/hcl.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ func PopAttr(body *hclwrite.Body, attrName, errPrefix string) (hclwrite.Tokens,
3030
return tokens, nil
3131
}
3232

33+
// SetAttrExpr sets an attribute to an expression (possibly with interpolations) without quotes.
34+
func SetAttrExpr(body *hclwrite.Body, attrName, expresion string) {
35+
tokens := hclwrite.Tokens{{Type: hclsyntax.TokenIdent, Bytes: []byte(expresion)}}
36+
body.SetAttributeRaw(attrName, tokens)
37+
}
38+
3339
// SetAttrInt sets an attribute to a number.
3440
func SetAttrInt(body *hclwrite.Body, attrName string, number int) {
3541
tokens := hclwrite.Tokens{

0 commit comments

Comments
 (0)