Skip to content

Commit 740fc83

Browse files
authored
Merge pull request #301 from vmware/feat/converter/custom-separator-support
Feat/Converter -- Added support for custom separator, changed default separator & added utils functions
2 parents afdf5ce + dae511d commit 740fc83

12 files changed

+174
-108
lines changed

internal/helper/converter/construct_model.go

+31-29
Original file line numberDiff line numberDiff line change
@@ -10,68 +10,68 @@ import (
1010
"strings"
1111
)
1212

13-
func buildModelField(modelJSON *BlockToStruct, schemaData interface{}, mapValue interface{}, arrIndexer *ArrIndexer) {
13+
func (converter *TFSchemaModelConverter[T]) buildModelField(modelJSON *BlockToStruct, schemaData interface{}, mapValue interface{}, arrIndexer *ArrIndexer) {
1414
if schemaData == nil || mapValue == nil {
1515
return
1616
}
1717

1818
switch mapValue := mapValue.(type) {
1919
case *BlockToStruct:
20-
modelHandleBlockStruct(modelJSON, schemaData, mapValue, arrIndexer)
20+
converter.modelHandleBlockStruct(modelJSON, schemaData, mapValue, arrIndexer)
2121
case *Map:
22-
modelHandleBlockMap(modelJSON, schemaData, mapValue, arrIndexer)
22+
converter.modelHandleBlockMap(modelJSON, schemaData, mapValue, arrIndexer)
2323
case *BlockToStructSlice:
24-
modelHandleBlockStructSlice(modelJSON, schemaData, mapValue, arrIndexer)
24+
converter.modelHandleBlockStructSlice(modelJSON, schemaData, mapValue, arrIndexer)
2525
case *BlockSliceToStructSlice:
26-
modelHandleBlockSliceStructSlice(modelJSON, schemaData, mapValue, arrIndexer)
26+
converter.modelHandleBlockSliceStructSlice(modelJSON, schemaData, mapValue, arrIndexer)
2727
case *ListToStruct:
28-
modelHandleListStruct(modelJSON, schemaData, mapValue, arrIndexer)
28+
converter.modelHandleListStruct(modelJSON, schemaData, mapValue, arrIndexer)
2929
case *EvaluatedField:
3030
modelField := mapValue.Field
3131
modelValue := mapValue.EvalFunc(ConstructModel, schemaData)
32-
setModelValue(modelJSON, modelField, modelValue, arrIndexer)
32+
converter.setModelValue(modelJSON, modelField, modelValue, arrIndexer)
3333
case string:
3434
modelField := mapValue
3535
modelValue := schemaData
36-
setModelValue(modelJSON, modelField, modelValue, arrIndexer)
36+
converter.setModelValue(modelJSON, modelField, modelValue, arrIndexer)
3737
}
3838
}
3939

40-
func modelHandleBlockStruct(modelJSON *BlockToStruct, schemaData interface{}, mapValue *BlockToStruct, arrIndexer *ArrIndexer) {
40+
func (converter *TFSchemaModelConverter[T]) modelHandleBlockStruct(modelJSON *BlockToStruct, schemaData interface{}, mapValue *BlockToStruct, arrIndexer *ArrIndexer) {
4141
if schemaDataSlice, ok := schemaData.([]interface{}); ok && len(schemaDataSlice) > 0 {
4242
rootSchemaDict, _ := schemaDataSlice[0].(map[string]interface{})
4343

4444
for key, value := range *mapValue {
45-
buildModelField(modelJSON, rootSchemaDict[key], value, arrIndexer)
45+
converter.buildModelField(modelJSON, rootSchemaDict[key], value, arrIndexer)
4646
}
4747
}
4848
}
4949

50-
func modelHandleBlockMap(modelJSON *BlockToStruct, schemaData interface{}, mapValue *Map, arrIndexer *ArrIndexer) {
50+
func (converter *TFSchemaModelConverter[T]) modelHandleBlockMap(modelJSON *BlockToStruct, schemaData interface{}, mapValue *Map, arrIndexer *ArrIndexer) {
5151
if rootSchemaDict, ok := schemaData.(map[string]interface{}); ok {
52-
definedKeysMapValue := mapValue.Copy([]string{"*"})
52+
definedKeysMapValue := mapValue.Copy([]string{AllMapKeysFieldMarker})
5353

54-
if allKeysFlagMapValue, exists := (*mapValue)["*"]; exists {
54+
if allKeysFlagMapValue, exists := (*mapValue)[AllMapKeysFieldMarker]; exists {
5555
for key, value := range rootSchemaDict {
5656
var dynamicMapValue interface{}
5757

5858
if allKeysFlagMapStr, ok := allKeysFlagMapValue.(string); ok {
59-
dynamicMapValue = strings.ReplaceAll(allKeysFlagMapStr, "*", key)
59+
dynamicMapValue = strings.ReplaceAll(allKeysFlagMapStr, AllMapKeysFieldMarker, key)
6060
} else {
6161
dynamicMapValue = allKeysFlagMapValue
6262
}
6363

64-
buildModelField(modelJSON, value, dynamicMapValue, arrIndexer)
64+
converter.buildModelField(modelJSON, value, dynamicMapValue, arrIndexer)
6565
}
6666
}
6767

6868
for key, value := range definedKeysMapValue {
69-
buildModelField(modelJSON, rootSchemaDict[key], value, arrIndexer)
69+
converter.buildModelField(modelJSON, rootSchemaDict[key], value, arrIndexer)
7070
}
7171
}
7272
}
7373

74-
func modelHandleBlockStructSlice(modelJSON *BlockToStruct, schemaData interface{}, mapValue *BlockToStructSlice, arrIndexer *ArrIndexer) {
74+
func (converter *TFSchemaModelConverter[T]) modelHandleBlockStructSlice(modelJSON *BlockToStruct, schemaData interface{}, mapValue *BlockToStructSlice, arrIndexer *ArrIndexer) {
7575
if len(schemaData.([]interface{})) > 0 {
7676
arrIndexer.New()
7777

@@ -81,10 +81,10 @@ func modelHandleBlockStructSlice(modelJSON *BlockToStruct, schemaData interface{
8181

8282
if schemaValue != nil {
8383
if _, ok := elemMapValue.(*ListToStruct); ok {
84-
buildModelField(modelJSON, schemaValue, elemMapValue, arrIndexer)
84+
converter.buildModelField(modelJSON, schemaValue, elemMapValue, arrIndexer)
8585
} else {
8686
for _, item := range schemaValue.([]interface{}) {
87-
buildModelField(modelJSON, []interface{}{item}, elemMapValue, arrIndexer)
87+
converter.buildModelField(modelJSON, []interface{}{item}, elemMapValue, arrIndexer)
8888
arrIndexer.IncrementLastIndex()
8989
}
9090
}
@@ -96,7 +96,7 @@ func modelHandleBlockStructSlice(modelJSON *BlockToStruct, schemaData interface{
9696
}
9797
}
9898

99-
func modelHandleBlockSliceStructSlice(modelJSON *BlockToStruct, schemaData interface{}, mapValue *BlockSliceToStructSlice, arrIndexer *ArrIndexer) {
99+
func (converter *TFSchemaModelConverter[T]) modelHandleBlockSliceStructSlice(modelJSON *BlockToStruct, schemaData interface{}, mapValue *BlockSliceToStructSlice, arrIndexer *ArrIndexer) {
100100
if len(schemaData.([]interface{})) > 0 {
101101
for _, elemTypeMap := range *mapValue {
102102
arrIndexer.New()
@@ -105,7 +105,7 @@ func modelHandleBlockSliceStructSlice(modelJSON *BlockToStruct, schemaData inter
105105
var _, ok = item.(map[string]interface{})
106106

107107
if ok {
108-
buildModelField(modelJSON, []interface{}{item}, elemTypeMap, arrIndexer)
108+
converter.buildModelField(modelJSON, []interface{}{item}, elemTypeMap, arrIndexer)
109109
arrIndexer.IncrementLastIndex()
110110
}
111111
}
@@ -115,32 +115,34 @@ func modelHandleBlockSliceStructSlice(modelJSON *BlockToStruct, schemaData inter
115115
}
116116
}
117117

118-
func modelHandleListStruct(modelJSON *BlockToStruct, schemaData interface{}, mapValue *ListToStruct, arrIndexer *ArrIndexer) {
118+
func (converter *TFSchemaModelConverter[T]) modelHandleListStruct(modelJSON *BlockToStruct, schemaData interface{}, mapValue *ListToStruct, arrIndexer *ArrIndexer) {
119119
if reflect.TypeOf(schemaData).Kind() == reflect.Slice {
120120
sliceValue := reflect.ValueOf(schemaData)
121121

122122
for i := 0; i < sliceValue.Len(); i++ {
123123
val := sliceValue.Index(i).Interface()
124-
setModelValue(modelJSON, (*mapValue)[0], val, arrIndexer)
124+
converter.setModelValue(modelJSON, (*mapValue)[0], val, arrIndexer)
125125
arrIndexer.IncrementLastIndex()
126126
}
127127
}
128128
}
129129

130-
func setModelValue(model *BlockToStruct, field string, value interface{}, arrIndexer *ArrIndexer) {
131-
if !strings.Contains(field, ".") {
130+
func (converter *TFSchemaModelConverter[T]) setModelValue(model *BlockToStruct, field string, value interface{}, arrIndexer *ArrIndexer) {
131+
modelPathSeparator := converter.getModelPathSeparator()
132+
133+
if !strings.Contains(field, modelPathSeparator) {
132134
(*model)[field] = value
133135
} else {
134-
fieldPaths := strings.Split(field, ".")
136+
fieldPaths := strings.Split(field, modelPathSeparator)
135137
arrIndices := arrIndexer.GetAllIndexes()
136-
leafField := strings.ReplaceAll(fieldPaths[len(fieldPaths)-1], "[]", "")
138+
leafField := strings.ReplaceAll(fieldPaths[len(fieldPaths)-1], ArrayFieldMarker, "")
137139
arrayFields := 0
138140
parentField := *model
139141

140142
for i := 0; i < len(fieldPaths)-1; i++ {
141143
fieldName := fieldPaths[i]
142144

143-
if !strings.Contains(fieldName, "[]") {
145+
if !strings.Contains(fieldName, ArrayFieldMarker) {
144146
if _, ok := parentField[fieldName]; !ok {
145147
parentField[fieldName] = make(map[string]interface{})
146148
}
@@ -149,7 +151,7 @@ func setModelValue(model *BlockToStruct, field string, value interface{}, arrInd
149151
} else {
150152
var object map[string]interface{}
151153

152-
fieldName = strings.ReplaceAll(fieldName, "[]", "")
154+
fieldName = strings.ReplaceAll(fieldName, ArrayFieldMarker, "")
153155
arrayIndex := arrIndices[arrayFields]
154156

155157
arrayFields++

internal/helper/converter/construct_tf_schema.go

+25-23
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const (
1818
arrayCannotBeReachedMsg = "arrays can't be reached"
1919
)
2020

21-
func buildTFValue(modelJSONData *map[string]interface{}, mapValue interface{}, arrIndexer *ArrIndexer) (interface{}, error) {
21+
func (converter *TFSchemaModelConverter[T]) buildTFValue(modelJSONData *map[string]interface{}, mapValue interface{}, arrIndexer *ArrIndexer) (interface{}, error) {
2222
if modelJSONData == nil || mapValue == nil {
2323
return nil, nil
2424
}
@@ -30,35 +30,37 @@ func buildTFValue(modelJSONData *map[string]interface{}, mapValue interface{}, a
3030

3131
switch mapValue := mapValue.(type) {
3232
case *BlockToStruct, *Map:
33-
return tfHandleBlockMap(modelJSONData, mapValue, arrIndexer)
33+
return converter.tfHandleBlockMap(modelJSONData, mapValue, arrIndexer)
3434
case *BlockToStructSlice:
35-
return tfHandleBlockStructSlice(modelJSONData, mapValue, arrIndexer)
35+
return converter.tfHandleBlockStructSlice(modelJSONData, mapValue, arrIndexer)
3636
case *BlockSliceToStructSlice:
37-
return tfHandleBlockSliceStructSlice(modelJSONData, mapValue, arrIndexer)
37+
return converter.tfHandleBlockSliceStructSlice(modelJSONData, mapValue, arrIndexer)
3838
case *ListToStruct:
39-
return tfHandleListStruct(modelJSONData, mapValue, arrIndexer)
39+
return converter.tfHandleListStruct(modelJSONData, mapValue, arrIndexer)
4040
case *EvaluatedField:
4141
var modelValue interface{}
4242

4343
modelField := mapValue.Field
44-
modelValue, err = getModelValue(modelJSONData, modelField, arrIndexer)
44+
modelValue, err = converter.getModelValue(modelJSONData, modelField, arrIndexer)
4545

4646
if err == nil {
4747
tfSchemaValue = mapValue.EvalFunc(ConstructTFSchema, modelValue)
48+
} else if strings.Contains(err.Error(), arrayCannotBeReachedMsg) && strings.HasSuffix(modelField, ArrayFieldMarker) {
49+
err = nil
4850
}
4951
case string:
50-
tfSchemaValue, err = getModelValue(modelJSONData, mapValue, arrIndexer)
52+
tfSchemaValue, err = converter.getModelValue(modelJSONData, mapValue, arrIndexer)
5153
}
5254

5355
return tfSchemaValue, err
5456
}
5557

56-
func tfHandleBlockMap(modelJSONData *map[string]interface{}, mapValue interface{}, arrIndexer *ArrIndexer) (tfSchemaValue interface{}, err error) {
58+
func (converter *TFSchemaModelConverter[T]) tfHandleBlockMap(modelJSONData *map[string]interface{}, mapValue interface{}, arrIndexer *ArrIndexer) (tfSchemaValue interface{}, err error) {
5759
_, isMap := mapValue.(*Map)
5860

5961
if isMap {
60-
if allFlagsKeyValue, exists := (*mapValue.(*Map))["*"]; exists {
61-
modelValue, _ := buildTFValue(modelJSONData, allFlagsKeyValue, arrIndexer)
62+
if allFlagsKeyValue, exists := (*mapValue.(*Map))[AllMapKeysFieldMarker]; exists {
63+
modelValue, _ := converter.buildTFValue(modelJSONData, allFlagsKeyValue, arrIndexer)
6264

6365
if modelValue != nil {
6466
if tfSchemaValue == nil {
@@ -71,12 +73,12 @@ func tfHandleBlockMap(modelJSONData *map[string]interface{}, mapValue interface{
7173
}
7274
}
7375

74-
newBlock := BlockToStruct(mapValue.(*Map).Copy([]string{"*"}))
76+
newBlock := BlockToStruct(mapValue.(*Map).Copy([]string{AllMapKeysFieldMarker}))
7577
mapValue = &newBlock
7678
}
7779

7880
for elemKey, elemValue := range *mapValue.(*BlockToStruct) {
79-
modelValue, err := buildTFValue(modelJSONData, elemValue, arrIndexer)
81+
modelValue, err := converter.buildTFValue(modelJSONData, elemValue, arrIndexer)
8082

8183
if modelValue != nil {
8284
if tfSchemaValue == nil {
@@ -96,7 +98,7 @@ func tfHandleBlockMap(modelJSONData *map[string]interface{}, mapValue interface{
9698
return tfSchemaValue, err
9799
}
98100

99-
func tfHandleBlockStructSlice(modelJSONData *map[string]interface{}, mapValue *BlockToStructSlice, arrIndexer *ArrIndexer) (tfSchemaValue interface{}, err error) {
101+
func (converter *TFSchemaModelConverter[T]) tfHandleBlockStructSlice(modelJSONData *map[string]interface{}, mapValue *BlockToStructSlice, arrIndexer *ArrIndexer) (tfSchemaValue interface{}, err error) {
100102
var (
101103
modelValue interface{}
102104
tfElemValue map[string]interface{}
@@ -106,7 +108,7 @@ func tfHandleBlockStructSlice(modelJSONData *map[string]interface{}, mapValue *B
106108
arrIndexer.New()
107109

108110
for err == nil {
109-
modelValue, err = buildTFValue(modelJSONData, elemMap, arrIndexer)
111+
modelValue, err = converter.buildTFValue(modelJSONData, elemMap, arrIndexer)
110112

111113
if modelValue != nil {
112114
if tfElemValue == nil {
@@ -178,14 +180,14 @@ func tfHandleBlockStructSlice(modelJSONData *map[string]interface{}, mapValue *B
178180
return tfSchemaValue, err
179181
}
180182

181-
func tfHandleBlockSliceStructSlice(modelJSONData *map[string]interface{}, mapValue *BlockSliceToStructSlice, arrIndexer *ArrIndexer) (tfSchemaValue interface{}, err error) {
183+
func (converter *TFSchemaModelConverter[T]) tfHandleBlockSliceStructSlice(modelJSONData *map[string]interface{}, mapValue *BlockSliceToStructSlice, arrIndexer *ArrIndexer) (tfSchemaValue interface{}, err error) {
182184
var modelValue interface{}
183185

184186
for i, elemMap := range *mapValue {
185187
arrIndexer.New()
186188

187189
for err == nil {
188-
modelValue, err = buildTFValue(modelJSONData, elemMap, arrIndexer)
190+
modelValue, err = converter.buildTFValue(modelJSONData, elemMap, arrIndexer)
189191

190192
if modelValue != nil {
191193
if tfSchemaValue == nil {
@@ -230,14 +232,14 @@ func tfHandleBlockSliceStructSlice(modelJSONData *map[string]interface{}, mapVal
230232
return tfSchemaValue, err
231233
}
232234

233-
func tfHandleListStruct(modelJSONData *map[string]interface{}, mapValue *ListToStruct, arrIndexer *ArrIndexer) (tfSchemaValue interface{}, err error) {
235+
func (converter *TFSchemaModelConverter[T]) tfHandleListStruct(modelJSONData *map[string]interface{}, mapValue *ListToStruct, arrIndexer *ArrIndexer) (tfSchemaValue interface{}, err error) {
234236
var (
235237
arr []interface{}
236238
modelValue interface{}
237239
)
238240

239241
for err == nil {
240-
modelValue, err = getModelValue(modelJSONData, (*mapValue)[0], arrIndexer)
242+
modelValue, err = converter.getModelValue(modelJSONData, (*mapValue)[0], arrIndexer)
241243
arrIndexer.IncrementLastIndex()
242244

243245
if modelValue != nil {
@@ -252,20 +254,20 @@ func tfHandleListStruct(modelJSONData *map[string]interface{}, mapValue *ListToS
252254
return tfSchemaValue, err
253255
}
254256

255-
func getModelValue(modelJSONData *map[string]interface{}, mapValue string, arrIndexer *ArrIndexer) (interface{}, error) {
257+
func (converter *TFSchemaModelConverter[T]) getModelValue(modelJSONData *map[string]interface{}, mapValue string, arrIndexer *ArrIndexer) (interface{}, error) {
256258
var (
257259
err error
258260
lastIndex int
259261
arrIndexerPosition int
260262

261263
modelRootValue interface{} = *modelJSONData
262-
modelValuePaths = strings.Split(mapValue, ".")
264+
modelValuePaths = strings.Split(mapValue, converter.getModelPathSeparator())
263265
)
264266

265267
for i := 0; i < len(modelValuePaths); i++ {
266-
nextModelPath := strings.ReplaceAll(modelValuePaths[i], "[]", "")
268+
nextModelPath := strings.ReplaceAll(modelValuePaths[i], ArrayFieldMarker, "")
267269

268-
if nextModelPath == "*" {
270+
if nextModelPath == AllMapKeysFieldMarker {
269271
newMap := make(map[string]interface{})
270272

271273
for k, v := range modelRootValue.(map[string]interface{}) {
@@ -303,7 +305,7 @@ func getModelValue(modelJSONData *map[string]interface{}, mapValue string, arrIn
303305
}
304306

305307
if modelRootValue == nil {
306-
arraysCount := strings.Count(mapValue, "[]")
308+
arraysCount := strings.Count(mapValue, ArrayFieldMarker)
307309

308310
switch {
309311
case err != nil:

0 commit comments

Comments
 (0)