func SetMutableButUnreadableFields()

in pkg/dcl/livestate/fetchlivestate.go [93:205]


func SetMutableButUnreadableFields(kccLite *unstructured.Unstructured, mutableButUnreadableSpec map[string]interface{}, path []string, schema *openapi.Schema, secretVersions map[string]string, namespace string, kubeClient client.Client) (*unstructured.Unstructured, error) {
	if len(mutableButUnreadableSpec) == 0 {
		return kccLite, nil
	}

	if schema.Type != "object" {
		return nil, fmt.Errorf("wrong type for provided schema: %s, expect to have object", schema.Type)
	}

	for k, v := range mutableButUnreadableSpec {
		path := append(path, k)

		subSchema, ok := schema.Properties[k]
		if !ok {
			return nil, fmt.Errorf("unknown mutable-but-unreadable path '%v'", pathslice.ToString(path))
		}
		switch subSchema.Type {
		case "integer":
			v, err := dcl.CanonicalizeIntegerValue(v)
			if err != nil {
				return nil, fmt.Errorf("error canonicalizing the integer value for path '%v': %w", pathslice.ToString(path), err)
			}

			if err := unstructured.SetNestedField(kccLite.Object, v, path...); err != nil {
				return nil, fmt.Errorf("error setting mutable-but-unreadable path '%v': %w", pathslice.ToString(path), err)
			}
		case "number":
			v, err := dcl.CanonicalizeNumberValue(v)
			if err != nil {
				return nil, fmt.Errorf("error canonicalizing the number value for path '%v': %w", pathslice.ToString(path), err)
			}

			if err := unstructured.SetNestedField(kccLite.Object, v, path...); err != nil {
				return nil, fmt.Errorf("error setting mutable-but-unreadable path '%v': %w", pathslice.ToString(path), err)
			}

		case "string":
			isSensitive, err := extension.IsSensitiveField(subSchema)
			if err != nil {
				return nil, fmt.Errorf("error checking sensitivity for mutable-but-unreadable path '%v': %w", pathslice.ToString(path), err)
			}

			if !isSensitive {
				if err := unstructured.SetNestedField(kccLite.Object, v, path...); err != nil {
					return nil, fmt.Errorf("error setting mutable-but-unreadable path '%v': %w", pathslice.ToString(path), err)
				}
				continue
			}

			val, err := resolveSensitiveValueForLiveState(v, secretVersions, namespace, kubeClient)
			if err != nil {
				return nil, fmt.Errorf("error parsing the secret for mutable-but-unreadable path '%v': %w", pathslice.ToString(path), err)
			}
			valMap := make(map[string]interface{})
			valMap["value"] = val
			if err := unstructured.SetNestedField(kccLite.Object, valMap, path...); err != nil {
				return nil, fmt.Errorf("error setting mutable-but-unreadable path '%v': %w", pathslice.ToString(path), err)
			}
		case "boolean":
			if err := unstructured.SetNestedField(kccLite.Object, v, path...); err != nil {
				return nil, fmt.Errorf("error setting mutable-but-unreadable path '%v': %w", pathslice.ToString(path), err)
			}
		case "array":
			v, ok := v.([]interface{})
			if !ok {
				return nil, fmt.Errorf("wrong type for path '%v': %T, expect to have []interface{}", pathslice.ToString(path), v)
			}

			itemSchema := subSchema.Items
			switch itemSchema.Type {
			case "string", "boolean", "number", "integer":
				// List/set of primitives
				path := strings.Split(pathslice.ToString(path), ".")
				if err := unstructured.SetNestedField(kccLite.Object, deepcopy.DeepCopy(v), path...); err != nil {
					return nil, fmt.Errorf("error setting mutable-but-unreadable path '%v': %w", pathslice.ToString(path), err)
				}
			case "array", "object":
				// List/set of non-primitives
				return nil, fmt.Errorf("error setting mutable-but-unreadable path '%v': mutable-but-unreadable list/set of non-primitive types is not yet supported", pathslice.ToString(path))
			default:
				// List of unknown types
				return nil, fmt.Errorf("unknown list/set type %T for mutable-but-unreadable path '%v'", itemSchema, pathslice.ToString(path))
			}
		case "object":
			v, ok := v.(map[string]interface{})
			if !ok {
				return nil, fmt.Errorf("wrong type for path '%v': %T, expect to have map[string]interface{}", pathslice.ToString(path), v)
			}

			if subSchema.AdditionalProperties != nil {
				// Map
				// Currently KCC doesn't support the nested path in the value
				// of the map to be mutable-but-unreadable, so the map is copied
				// as a whole.
				if err := unstructured.SetNestedField(kccLite.Object, deepcopy.DeepCopy(v), path...); err != nil {
					return nil, fmt.Errorf("error setting mutable-but-unreadable path '%v': %w", pathslice.ToString(path), err)
				}
			} else {
				// Object
				var err error
				kccLite, err = SetMutableButUnreadableFields(kccLite, v, path, subSchema, secretVersions, namespace, kubeClient)
				if err != nil {
					return nil, fmt.Errorf("error setting nested mutable-but-unreadable path: %w", err)
				}
			}
		default:
			// Unknown types
			return nil, fmt.Errorf("unknown type %T for mutable-but-unreadable path '%v'", subSchema, pathslice.ToString(path))
		}
	}

	return kccLite, nil
}