@@ -4,7 +4,10 @@ import (
4
4
"errors"
5
5
"fmt"
6
6
"sort"
7
+ "strconv"
8
+ "strings"
7
9
10
+ "github.com/hashicorp/hcl/v2/hclsyntax"
8
11
"github.com/hashicorp/hcl/v2/hclwrite"
9
12
"github.com/mongodb-labs/atlas-cli-plugin-terraform/internal/hcl"
10
13
"github.com/zclconf/go-cty/cty"
@@ -86,11 +89,11 @@ func fillFreeTier(resourceb *hclwrite.Body) error {
86
89
if err := hcl .MoveAttr (resourceb , electableSpec .Body (), nInstanceSizeSrc , nInstanceSize , errFreeCluster ); err != nil {
87
90
return err
88
91
}
89
- configb .SetAttributeRaw (nElectableSpecs , hcl .TokensObject (electableSpec ))
92
+ configb .SetAttributeRaw (nElectableSpecs , hcl .TokensObject (electableSpec . Body () ))
90
93
91
94
repSpecs := hclwrite .NewEmptyFile ()
92
- repSpecs .Body ().SetAttributeRaw (nConfig , hcl .TokensArraySingle (config ))
93
- resourceb .SetAttributeRaw (nRepSpecs , hcl .TokensArraySingle (repSpecs ))
95
+ repSpecs .Body ().SetAttributeRaw (nConfig , hcl .TokensArraySingle (configb ))
96
+ resourceb .SetAttributeRaw (nRepSpecs , hcl .TokensArraySingle (repSpecs . Body () ))
94
97
return nil
95
98
}
96
99
@@ -115,14 +118,31 @@ func fillReplicationSpecs(resourceb *hclwrite.Body) error {
115
118
}
116
119
repSpecs := hclwrite .NewEmptyFile ()
117
120
repSpecs .Body ().SetAttributeRaw (nConfig , configs )
118
-
119
- resourceb .SetAttributeRaw (nRepSpecs , hcl .TokensArraySingle (repSpecs ))
121
+ resourceb .SetAttributeRaw (nRepSpecs , hcl .TokensArraySingle (repSpecs .Body ()))
122
+ tags , errTags := getTagsLabelsOpt (resourceb , nTags )
123
+ if errTags != nil {
124
+ return errTags
125
+ }
126
+ if tags != nil {
127
+ resourceb .SetAttributeRaw (nTags , tags )
128
+ }
129
+ labels , errLabels := getTagsLabelsOpt (resourceb , nLabels )
130
+ if errLabels != nil {
131
+ return errLabels
132
+ }
133
+ if labels != nil {
134
+ resourceb .SetAttributeRaw (nLabels , labels )
135
+ }
136
+ fillBlockOpt (resourceb , nTimeouts )
137
+ fillBlockOpt (resourceb , nAdvConf )
138
+ fillBlockOpt (resourceb , nBiConnector )
139
+ fillBlockOpt (resourceb , nPinnedFCV )
120
140
resourceb .RemoveBlock (repSpecsSrc )
121
141
return nil
122
142
}
123
143
124
144
func getRegionConfigs (repSpecsSrc * hclwrite.Block , root attrVals ) (hclwrite.Tokens , error ) {
125
- var configs []* hclwrite.File
145
+ var configs []* hclwrite.Body
126
146
for {
127
147
configSrc := repSpecsSrc .Body ().FirstMatchingBlock (nConfigSrc , nil )
128
148
if configSrc == nil {
@@ -132,15 +152,15 @@ func getRegionConfigs(repSpecsSrc *hclwrite.Block, root attrVals) (hclwrite.Toke
132
152
if err != nil {
133
153
return nil , err
134
154
}
135
- configs = append (configs , config )
155
+ configs = append (configs , config . Body () )
136
156
repSpecsSrc .Body ().RemoveBlock (configSrc )
137
157
}
138
158
if len (configs ) == 0 {
139
159
return nil , fmt .Errorf ("%s: %s not found" , errRepSpecs , nConfigSrc )
140
160
}
141
161
sort .Slice (configs , func (i , j int ) bool {
142
- pi , _ := hcl .GetAttrInt (configs [i ].Body (). GetAttribute (nPriority ), errPriority )
143
- pj , _ := hcl .GetAttrInt (configs [j ].Body (). GetAttribute (nPriority ), errPriority )
162
+ pi , _ := hcl .GetAttrInt (configs [i ].GetAttribute (nPriority ), errPriority )
163
+ pj , _ := hcl .GetAttrInt (configs [j ].GetAttribute (nPriority ), errPriority )
144
164
return pi > pj
145
165
})
146
166
return hcl .TokensArray (configs ), nil
@@ -156,15 +176,15 @@ func getRegionConfig(configSrc *hclwrite.Block, root attrVals) (*hclwrite.File,
156
176
if err := setPriority (fileb , configSrc .Body ().GetAttribute (nPriority )); err != nil {
157
177
return nil , err
158
178
}
159
- electableSpecs , errElec := getSpecs (nElectableNodes , configSrc , root )
179
+ electableSpecs , errElec := getSpecs (configSrc , nElectableNodes , root )
160
180
if errElec != nil {
161
181
return nil , errElec
162
182
}
163
183
fileb .SetAttributeRaw (nElectableSpecs , electableSpecs )
164
- if readOnly , _ := getSpecs (nReadOnlyNodes , configSrc , root ); readOnly != nil {
184
+ if readOnly , _ := getSpecs (configSrc , nReadOnlyNodes , root ); readOnly != nil {
165
185
fileb .SetAttributeRaw (nReadOnlySpecs , readOnly )
166
186
}
167
- if analytics , _ := getSpecs (nAnalyticsNodes , configSrc , root ); analytics != nil {
187
+ if analytics , _ := getSpecs (configSrc , nAnalyticsNodes , root ); analytics != nil {
168
188
fileb .SetAttributeRaw (nAnalyticsSpecs , analytics )
169
189
}
170
190
if autoScaling := getAutoScalingOpt (root .opt ); autoScaling != nil {
@@ -173,7 +193,7 @@ func getRegionConfig(configSrc *hclwrite.Block, root attrVals) (*hclwrite.File,
173
193
return file , nil
174
194
}
175
195
176
- func getSpecs (countName string , configSrc * hclwrite.Block , root attrVals ) (hclwrite.Tokens , error ) {
196
+ func getSpecs (configSrc * hclwrite.Block , countName string , root attrVals ) (hclwrite.Tokens , error ) {
177
197
var (
178
198
file = hclwrite .NewEmptyFile ()
179
199
fileb = file .Body ()
@@ -196,7 +216,7 @@ func getSpecs(countName string, configSrc *hclwrite.Block, root attrVals) (hclwr
196
216
if root .opt [nDiskIOPSSrc ] != nil {
197
217
fileb .SetAttributeRaw (nDiskIOPS , root .opt [nDiskIOPSSrc ])
198
218
}
199
- return hcl .TokensObject (file ), nil
219
+ return hcl .TokensObject (fileb ), nil
200
220
}
201
221
202
222
func getAutoScalingOpt (opt map [string ]hclwrite.Tokens ) hclwrite.Tokens {
@@ -209,19 +229,55 @@ func getAutoScalingOpt(opt map[string]hclwrite.Tokens) hclwrite.Tokens {
209
229
{nComputeScaleDownEnabledSrc , nComputeScaleDownEnabled },
210
230
}
211
231
file = hclwrite .NewEmptyFile ()
232
+ fileb = file .Body ()
212
233
found = false
213
234
)
214
235
for _ , tuple := range names {
215
236
src , dst := tuple [0 ], tuple [1 ]
216
237
if tokens := opt [src ]; tokens != nil {
217
- file . Body () .SetAttributeRaw (dst , tokens )
238
+ fileb .SetAttributeRaw (dst , tokens )
218
239
found = true
219
240
}
220
241
}
221
242
if ! found {
222
243
return nil
223
244
}
224
- return hcl .TokensObject (file )
245
+ return hcl .TokensObject (fileb )
246
+ }
247
+
248
+ func getTagsLabelsOpt (resourceb * hclwrite.Body , name string ) (hclwrite.Tokens , error ) {
249
+ var (
250
+ file = hclwrite .NewEmptyFile ()
251
+ fileb = file .Body ()
252
+ found = false
253
+ )
254
+ for {
255
+ block := resourceb .FirstMatchingBlock (name , nil )
256
+ if block == nil {
257
+ break
258
+ }
259
+ key := block .Body ().GetAttribute (nKey )
260
+ value := block .Body ().GetAttribute (nValue )
261
+ if key == nil || value == nil {
262
+ return nil , fmt .Errorf ("%s: %s or %s not found" , name , nKey , nValue )
263
+ }
264
+ setKeyValue (fileb , key , value )
265
+ resourceb .RemoveBlock (block )
266
+ found = true
267
+ }
268
+ if ! found {
269
+ return nil , nil
270
+ }
271
+ return hcl .TokensObject (fileb ), nil
272
+ }
273
+
274
+ func fillBlockOpt (resourceb * hclwrite.Body , name string ) {
275
+ block := resourceb .FirstMatchingBlock (name , nil )
276
+ if block == nil {
277
+ return
278
+ }
279
+ resourceb .RemoveBlock (block )
280
+ resourceb .SetAttributeRaw (name , hcl .TokensObject (block .Body ()))
225
281
}
226
282
227
283
func checkDynamicBlock (body * hclwrite.Body ) error {
@@ -233,6 +289,19 @@ func checkDynamicBlock(body *hclwrite.Body) error {
233
289
return nil
234
290
}
235
291
292
+ func setKeyValue (body * hclwrite.Body , key , value * hclwrite.Attribute ) {
293
+ keyStr , err := hcl .GetAttrString (key , "" )
294
+ if err == nil {
295
+ if ! hclsyntax .ValidIdentifier (keyStr ) {
296
+ keyStr = strconv .Quote (keyStr ) // wrap in quotes so invalid identifiers (e.g. with blanks) can be used as attribute names
297
+ }
298
+ } else {
299
+ keyStr = strings .TrimSpace (string (key .Expr ().BuildTokens (nil ).Bytes ()))
300
+ keyStr = "(" + keyStr + ")" // wrap in parentheses so unresolved expressions can be used as attribute names
301
+ }
302
+ body .SetAttributeRaw (keyStr , value .Expr ().BuildTokens (nil ))
303
+ }
304
+
236
305
func setPriority (body * hclwrite.Body , priority * hclwrite.Attribute ) error {
237
306
if priority == nil {
238
307
return fmt .Errorf ("%s: %s not found" , errRepSpecs , nPriority )
0 commit comments