diff --git a/README.md b/README.md index 8a41aa7..399cafe 100644 --- a/README.md +++ b/README.md @@ -130,10 +130,14 @@ These fields are now required. This makes P&T configuration less ambiguous: Also, the `resources[i].patches[i].policy.mergeOptions` field is no longer supported. The same capability can be achieved by setting `resources[i].patches[i].policy.toFieldPath` to: -- `MergeObject` - equivalent to +- `MergeObjects` - equivalent to `resources[i].patches[i].policy.mergeOptions.keepMapValues: true` -- `AppendArray` - equivalent to - `resources[i].patches[i].policy.mergeOptions.appendSlice: false` +- `MergeObjectsAppendArrays` - equivalent to + `resources[i].patches[i].policy.mergeOptions{keepMapValues: true, appendSlice: true}` +- `ForceMergeObjects` - equivalent to + `resources[i].patches[i].policy.mergeOptions.keepMapValues: false` +- `ForceMergeObjectsAppendArrays` - equivalent to + `resources[i].patches[i].policy.mergeOptions.appendSlice: true` ## Developing this function @@ -163,4 +167,4 @@ $ crossplane xpkg build -f package --embed-runtime-image=runtime [#4746]: https://github.com/crossplane/crossplane/issues/4746 [go]: https://go.dev [docker]: https://www.docker.com -[cli]: https://docs.crossplane.io/latest/cli \ No newline at end of file +[cli]: https://docs.crossplane.io/latest/cli diff --git a/fn_test.go b/fn_test.go index 29ddbf5..d27840f 100644 --- a/fn_test.go +++ b/fn_test.go @@ -482,7 +482,7 @@ func TestRunFunction(t *testing.T) { FromFieldPath: ptr.To[string]("spec.sourceObject"), ToFieldPath: ptr.To[string]("spec.targetObject"), Policy: &v1beta1.PatchPolicy{ - ToFieldPath: ptr.To(v1beta1.ToFieldPathPolicyMergeObject), + ToFieldPath: ptr.To(v1beta1.ToFieldPathPolicyMergeObjects), }, }, }, diff --git a/input/v1beta1/resources_patches.go b/input/v1beta1/resources_patches.go index eefb40d..2dc2959 100644 --- a/input/v1beta1/resources_patches.go +++ b/input/v1beta1/resources_patches.go @@ -37,8 +37,15 @@ type ToFieldPathPolicy string // ToFieldPath patch policies. const ( - ToFieldPathPolicyReplace ToFieldPathPolicy = "Replace" + ToFieldPathPolicyReplace ToFieldPathPolicy = "Replace" + ToFieldPathPolicyMergeObjects ToFieldPathPolicy = "MergeObjects" + ToFieldPathPolicyMergeObjectsAppendArrays ToFieldPathPolicy = "MergeObjectsAppendArrays" + ToFieldPathPolicyForceMergeObjects ToFieldPathPolicy = "ForceMergeObjects" + ToFieldPathPolicyForceMergeObjectsAppendArrays ToFieldPathPolicy = "ForceMergeObjectsAppendArrays" + + // Deprecated: Use MergeObjects, which is functionally identical. ToFieldPathPolicyMergeObject ToFieldPathPolicy = "MergeObject" + // Deprecated: Use ForceMergeObjectsAppendArrays, which is functionally identical. ToFieldPathPolicyAppendArray ToFieldPathPolicy = "AppendArray" ) @@ -54,10 +61,17 @@ type PatchPolicy struct { // ToFieldPath specifies how to patch to a field path. The default is // 'Replace', which means the patch will completely replace the target field, - // or create it if it does not exist. Use 'MergeObject' to merge the patch - // object with the target object, or 'AppendArray' to append the patch array - // to the target array. - // +kubebuilder:validation:Enum=Replace;MergeObject;AppendArray + // or create it if it does not exist. Use 'MergeObjects' to recursively merge the patch + // object with the target object, while keeping target object keys, but overwriting any array values, or use + // 'MergeObjectsAppendArrays' to recursively merge the patch object with the target object, while keeping + // target object keys and appending any array values to target array values, or use + // 'ForceMergeObjects' to recursively merge the patch object with the target object, overwriting + // any target object keys, including array values, or use + // 'ForceMergeObjectsAppendArrays' to recursively merge the patch object with the target object, + // overwriting target object keys, and appending any array values to target array values. + // 'MergeObject' is deprecated, use 'MergeObjects' instead, which is functionally identical. + // 'AppendArray' is deprecated, use 'ForceMergeObjectsAppendArrays' instead, which is functionally identical. + // +kubebuilder:validation:Enum=Replace;MergeObjects;MergeObjectsAppendArrays;ForceMergeObjects;ForceMergeObjectsAppendArrays;MergeObject;AppendArray // +optional ToFieldPath *ToFieldPathPolicy `json:"toFieldPath,omitempty"` } diff --git a/package/input/pt.fn.crossplane.io_resources.yaml b/package/input/pt.fn.crossplane.io_resources.yaml index 9734fdd..d58d4a8 100644 --- a/package/input/pt.fn.crossplane.io_resources.yaml +++ b/package/input/pt.fn.crossplane.io_resources.yaml @@ -121,11 +121,22 @@ spec: description: |- ToFieldPath specifies how to patch to a field path. The default is 'Replace', which means the patch will completely replace the target field, - or create it if it does not exist. Use 'MergeObject' to merge the patch - object with the target object, or 'AppendArray' to append the patch array - to the target array. + or create it if it does not exist. Use 'MergeObjects' to recursively merge the patch + object with the target object, while keeping target object keys, but overwriting any array values, or use + 'MergeObjectsAppendArrays' to recursively merge the patch object with the target object, while keeping + target object keys and appending any array values to target array values, or use + 'ForceMergeObjects' to recursively merge the patch object with the target object, overwriting + any target object keys, including array values, or use + 'ForceMergeObjectsAppendArrays' to recursively merge the patch object with the target object, + overwriting target object keys, and appending any array values to target array values. + 'MergeObject' is deprecated, use 'MergeObjects' instead, which is functionally identical. + 'AppendArray' is deprecated, use 'ForceMergeObjectsAppendArrays' instead, which is functionally identical. enum: - Replace + - MergeObjects + - MergeObjectsAppendArrays + - ForceMergeObjects + - ForceMergeObjectsAppendArrays - MergeObject - AppendArray type: string @@ -464,11 +475,22 @@ spec: description: |- ToFieldPath specifies how to patch to a field path. The default is 'Replace', which means the patch will completely replace the target field, - or create it if it does not exist. Use 'MergeObject' to merge the patch - object with the target object, or 'AppendArray' to append the patch array - to the target array. + or create it if it does not exist. Use 'MergeObjects' to recursively merge the patch + object with the target object, while keeping target object keys, but overwriting any array values, or use + 'MergeObjectsAppendArrays' to recursively merge the patch object with the target object, while keeping + target object keys and appending any array values to target array values, or use + 'ForceMergeObjects' to recursively merge the patch object with the target object, overwriting + any target object keys, including array values, or use + 'ForceMergeObjectsAppendArrays' to recursively merge the patch object with the target object, + overwriting target object keys, and appending any array values to target array values. + 'MergeObject' is deprecated, use 'MergeObjects' instead, which is functionally identical. + 'AppendArray' is deprecated, use 'ForceMergeObjectsAppendArrays' instead, which is functionally identical. enum: - Replace + - MergeObjects + - MergeObjectsAppendArrays + - ForceMergeObjects + - ForceMergeObjectsAppendArrays - MergeObject - AppendArray type: string @@ -871,11 +893,22 @@ spec: description: |- ToFieldPath specifies how to patch to a field path. The default is 'Replace', which means the patch will completely replace the target field, - or create it if it does not exist. Use 'MergeObject' to merge the patch - object with the target object, or 'AppendArray' to append the patch array - to the target array. + or create it if it does not exist. Use 'MergeObjects' to recursively merge the patch + object with the target object, while keeping target object keys, but overwriting any array values, or use + 'MergeObjectsAppendArrays' to recursively merge the patch object with the target object, while keeping + target object keys and appending any array values to target array values, or use + 'ForceMergeObjects' to recursively merge the patch object with the target object, overwriting + any target object keys, including array values, or use + 'ForceMergeObjectsAppendArrays' to recursively merge the patch object with the target object, + overwriting target object keys, and appending any array values to target array values. + 'MergeObject' is deprecated, use 'MergeObjects' instead, which is functionally identical. + 'AppendArray' is deprecated, use 'ForceMergeObjectsAppendArrays' instead, which is functionally identical. enum: - Replace + - MergeObjects + - MergeObjectsAppendArrays + - ForceMergeObjects + - ForceMergeObjectsAppendArrays - MergeObject - AppendArray type: string diff --git a/patches.go b/patches.go index 5e06603..7391263 100644 --- a/patches.go +++ b/patches.go @@ -102,10 +102,14 @@ func toMergeOption(p PatchInterface) (mo *xpv1.MergeOptions, err error) { switch pp.GetToFieldPathPolicy() { case v1beta1.ToFieldPathPolicyReplace: // nothing to do, this is the default - case v1beta1.ToFieldPathPolicyAppendArray: - mo = &xpv1.MergeOptions{AppendSlice: ptr.To(true)} - case v1beta1.ToFieldPathPolicyMergeObject: + case v1beta1.ToFieldPathPolicyMergeObjects, v1beta1.ToFieldPathPolicyMergeObject: //nolint:staticcheck // MergeObject is deprecated but we must still support it. mo = &xpv1.MergeOptions{KeepMapValues: ptr.To(true)} + case v1beta1.ToFieldPathPolicyMergeObjectsAppendArrays: + mo = &xpv1.MergeOptions{KeepMapValues: ptr.To(true), AppendSlice: ptr.To(true)} + case v1beta1.ToFieldPathPolicyForceMergeObjects: + mo = &xpv1.MergeOptions{KeepMapValues: ptr.To(false)} + case v1beta1.ToFieldPathPolicyForceMergeObjectsAppendArrays, v1beta1.ToFieldPathPolicyAppendArray: //nolint:staticcheck // AppendArray is deprecated but we must still support it. + mo = &xpv1.MergeOptions{AppendSlice: ptr.To(true)} default: // should never happen return nil, errors.Errorf(errFmtInvalidPatchPolicy, pp.GetToFieldPathPolicy()) diff --git a/validate.go b/validate.go index c815a5c..a1f44fc 100644 --- a/validate.go +++ b/validate.go @@ -202,8 +202,12 @@ func ValidatePatch(p PatchInterface) *field.Error { //nolint: gocyclo // This is if pp := p.GetPolicy(); pp != nil { switch pp.GetToFieldPathPolicy() { case v1beta1.ToFieldPathPolicyReplace, - v1beta1.ToFieldPathPolicyAppendArray, - v1beta1.ToFieldPathPolicyMergeObject: + v1beta1.ToFieldPathPolicyMergeObjects, + v1beta1.ToFieldPathPolicyMergeObjectsAppendArrays, + v1beta1.ToFieldPathPolicyForceMergeObjects, + v1beta1.ToFieldPathPolicyForceMergeObjectsAppendArrays, + v1beta1.ToFieldPathPolicyMergeObject, //nolint:staticcheck // MergeObject is deprecated but we must still support it. + v1beta1.ToFieldPathPolicyAppendArray: //nolint:staticcheck // AppendArray is deprecated but we must still support it. // ok default: return field.Invalid(field.NewPath("policy", "toFieldPathPolicy"), pp.GetToFieldPathPolicy(), "unknown toFieldPathPolicy")