Skip to content

Commit b83c1eb

Browse files
authored
Array enhancement for ODLM templating system (#1136) (#1139)
* support advanced array source value * handle else branch is empty case * add unit test cases for GetValueFromBranch method * add doc for array changes * one more unit test with array containning map values with reference * add required option for each reference and test cases --------- Signed-off-by: YuChen <[email protected]>
1 parent f1c2e47 commit b83c1eb

File tree

4 files changed

+542
-52
lines changed

4 files changed

+542
-52
lines changed

controllers/operator/manager.go

Lines changed: 100 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -721,7 +721,20 @@ func (m *ODLMOperator) processMapObject(ctx context.Context, key string, mapObj
721721
if err != nil {
722722
return err
723723
}
724-
finalObject[key] = valueRef
724+
if valueRef != "" {
725+
// Check if the returned value is a JSON array string and the field should be an array
726+
if strings.HasPrefix(valueRef, "[") && strings.HasSuffix(valueRef, "]") {
727+
var arrayValue []interface{}
728+
if err := json.Unmarshal([]byte(valueRef), &arrayValue); err == nil {
729+
finalObject[key] = arrayValue
730+
continue
731+
}
732+
}
733+
finalObject[key] = valueRef
734+
} else {
735+
klog.V(3).Infof("Empty value reference returned for key %s, deleting key %s from finalObject", key, key)
736+
delete(finalObject, key)
737+
}
725738
} else {
726739
if finalObject[key] == nil {
727740
// Skip if the key doesn't exist in finalObject
@@ -807,57 +820,85 @@ func (m *ODLMOperator) processExpressionCondition(ctx context.Context, templateR
807820
instanceType, instanceNs, instanceName, key, err)
808821
return "", err
809822
}
823+
klog.Infof("010101 key %s and result is %v", key, result)
810824

811825
if result {
812826
// Use 'then' branch when condition is true
813-
return m.getValueFromBranch(ctx, templateRefObj.Conditional.Then, "then", key, instanceType, instanceName, instanceNs)
827+
return m.GetValueFromBranch(ctx, templateRefObj.Conditional.Then, "then", key, instanceType, instanceName, instanceNs)
814828
} else {
815829
// Use 'else' branch when condition is false
816-
return m.getValueFromBranch(ctx, templateRefObj.Conditional.Else, "else", key, instanceType, instanceName, instanceNs)
830+
return m.GetValueFromBranch(ctx, templateRefObj.Conditional.Else, "else", key, instanceType, instanceName, instanceNs)
817831
}
818832
}
819833

820-
// getValueFromBranch retrieves a value from a specific branch (then/else)
821-
func (m *ODLMOperator) getValueFromBranch(ctx context.Context, branch *util.ValueSource, branchName, key string, instanceType, instanceName, instanceNs string) (string, error) {
834+
// GetValueFromBranch retrieves a value from a specific branch (then/else)
835+
func (m *ODLMOperator) GetValueFromBranch(ctx context.Context, branch *util.ValueSource, branchName, key string, instanceType, instanceName, instanceNs string) (string, error) {
822836
if branch == nil {
823837
return "", nil
824838
}
825839

826-
valueRef := ""
827-
828-
if branch.ObjectRef != nil {
829-
ref, err := m.ParseObjectRef(ctx, branch.ObjectRef, instanceType, instanceName, instanceNs)
830-
if err != nil {
831-
klog.Errorf("Failed to get '%s' value from Object for %s %s/%s on field %s: %v",
832-
branchName, instanceType, instanceNs, instanceName, key, err)
833-
return "", err
834-
}
835-
if ref != "" {
836-
valueRef = ref
837-
}
838-
} else if branch.ConfigMapKeyRef != nil {
839-
ref, err := m.ParseConfigMapRef(ctx, branch.ConfigMapKeyRef, instanceType, instanceName, instanceNs)
840-
if err != nil {
841-
klog.Errorf("Failed to get '%s' value from ConfigMap for %s %s/%s on field %s: %v",
842-
branchName, instanceType, instanceNs, instanceName, key, err)
843-
return "", err
844-
}
845-
if ref != "" {
846-
valueRef = ref
840+
// Handle direct literal value first
841+
if branch.Literal != "" {
842+
return branch.Literal, nil
843+
}
844+
845+
// Handle array values
846+
if len(branch.Array) > 0 {
847+
// Create a slice to hold processed values
848+
var processedValues []interface{}
849+
850+
// Iterate over the array items
851+
for _, item := range branch.Array {
852+
if item.Literal != "" {
853+
// For literal values in array, add directly
854+
processedValues = append(processedValues, item.Literal)
855+
} else if len(item.Map) > 0 {
856+
// Handle map items
857+
resultMap := make(map[string]interface{})
858+
859+
for k, v := range item.Map {
860+
if valueSourceMap, ok := v.(map[string]interface{}); ok {
861+
vsBytes, err := json.Marshal(valueSourceMap)
862+
if err != nil {
863+
klog.Errorf("Failed to marshal map value to JSON: %v", err)
864+
return "", err
865+
}
866+
867+
var vs util.ValueSource
868+
if err := json.Unmarshal(vsBytes, &vs); err != nil {
869+
klog.Errorf("Failed to unmarshal to ValueSource: %v", err)
870+
return "", err
871+
}
872+
873+
resolvedVal, err := m.GetValueFromSource(ctx, &vs, instanceType, instanceName, instanceNs)
874+
if err != nil {
875+
return "", err
876+
}
877+
resultMap[k] = resolvedVal
878+
} else {
879+
resultMap[k] = v
880+
}
881+
}
882+
processedValues = append(processedValues, resultMap)
883+
} else {
884+
// Handle direct reference types in array items
885+
val, err := m.GetValueFromSource(ctx, &item, instanceType, instanceName, instanceNs)
886+
if err != nil {
887+
return "", err
888+
}
889+
processedValues = append(processedValues, val)
890+
}
847891
}
848-
} else if branch.SecretKeyRef != nil {
849-
ref, err := m.ParseSecretKeyRef(ctx, branch.SecretKeyRef, instanceType, instanceName, instanceNs)
892+
893+
// Marshal the array to JSON
894+
jsonBytes, err := json.Marshal(processedValues)
850895
if err != nil {
851-
klog.Errorf("Failed to get '%s' value from Secret for %s %s/%s on field %s: %v",
852-
branchName, instanceType, instanceNs, instanceName, key, err)
853896
return "", err
854897
}
855-
if ref != "" {
856-
valueRef = ref
857-
}
898+
return string(jsonBytes), nil
858899
}
859900

860-
return valueRef, nil
901+
return m.GetValueFromSource(ctx, branch, instanceType, instanceName, instanceNs)
861902
}
862903

863904
// processStandardTemplate handles non-conditional templates
@@ -1033,21 +1074,38 @@ func (m *ODLMOperator) GetValueFromSource(ctx context.Context, source *util.Valu
10331074
return source.Literal, nil
10341075
}
10351076

1036-
// Get value from ConfigMap
1037-
if source.ConfigMapKeyRef != nil {
1038-
return m.ParseConfigMapRef(ctx, source.ConfigMapKeyRef, instanceType, instanceName, instanceNs)
1077+
// Get value from Object
1078+
if source.ObjectRef != nil {
1079+
val, err := m.ParseObjectRef(ctx, source.ObjectRef, instanceType, instanceName, instanceNs)
1080+
if err != nil {
1081+
return "", err
1082+
} else if val == "" && source.Required {
1083+
return "", errors.Errorf("Failed to get required value from source %s, retry in few second", source.ObjectRef.Name)
1084+
}
1085+
return val, nil
10391086
}
10401087

10411088
// Get value from Secret
10421089
if source.SecretKeyRef != nil {
1043-
return m.ParseSecretKeyRef(ctx, source.SecretKeyRef, instanceType, instanceName, instanceNs)
1090+
val, err := m.ParseSecretKeyRef(ctx, source.SecretKeyRef, instanceType, instanceName, instanceNs)
1091+
if err != nil {
1092+
return "", err
1093+
} else if val == "" && source.Required {
1094+
return "", errors.Errorf("Failed to get required value from source %s, retry in few second", source.SecretKeyRef.Name)
1095+
}
1096+
return val, nil
10441097
}
10451098

1046-
// Get value from Object
1047-
if source.ObjectRef != nil {
1048-
return m.ParseObjectRef(ctx, source.ObjectRef, instanceType, instanceName, instanceNs)
1099+
// Get value from ConfigMap
1100+
if source.ConfigMapKeyRef != nil {
1101+
val, err := m.ParseConfigMapRef(ctx, source.ConfigMapKeyRef, instanceType, instanceName, instanceNs)
1102+
if err != nil {
1103+
return "", err
1104+
} else if val == "" && source.Required {
1105+
return "", errors.Errorf("Failed to get required value from source %s, retry in few second", source.ConfigMapKeyRef.Name)
1106+
}
1107+
return val, nil
10491108
}
1050-
10511109
return "", nil
10521110
}
10531111

0 commit comments

Comments
 (0)