Add config.Resource. ServerSideApplyMergeStrategies to configure the SSA Merge Strategies #308
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description of your changes
This is a follow-up PR for #301.
We would like to have the API server properly track the field owners of the objects in the lists of the upjet-generated APIs when the server-side apply (SSA) patch operations are used. We would like it to also be able to properly merge objects in these lists with SSA patches. This will help us in addressing issues similar to crossplane-contrib/provider-upjet-aws#975 when we specify a non-atomic SSA merge strategy for a list. Please see this comment for more context.
This PR extends upjet's resource configuration framework so that it's now possible to configure a map's or object list's SSA merge strategy and to specify the list map keys for object lists with the
map
merge strategy. Please note that themap
merge strategy is not the best merge strategy for all object lists. For certain object lists, it's more desirable to replace the whole object instead of merging values specified by different clients, when merging the lists. This PR allows the configuration of the SSA merge strategy as one of the allowed values ofmap
,set
oratomic
for object lists, orgranular
oratomic
for maps.This PR allows injection of a naming (index) field into the object schemas of a list being configured with a merge strategy of
map
. This injected field will be available in the generated CRDs and thus visible to the API server (so that it can properly track field ownership for the list's objects and merge the lists and the objects as intended) but it's removed when the objects are being passed down to the Terraform layer (as these injected fields are not known to the underlying Terraform provider).The list map keys specified in the OpenAPI SSA extensions for an associative list are not nullable, they must either be required or defaulted. While configuring an injected field for the SSA merge strategy configuration, one can also specify a default value for an injected field, which will result in a
+kubebuilder:default
marker to be added to the generated Go struct field. This is useful when configuring the SSA merge strategy for object lists with a max size constraint of 1. However, object lists with a size greater than 1 will not be able to utilize this configuration option and will need to delegate the defaulting or the specification of a value for the injected field to some other entity such as:{"host": "a.b.c", interfaces: ["x", "y"], injected:"0"}
and{"host": "a.b.c", interfaces: ["x", "y"], injected:"1"}
, semantically these two objects are equal because they are the samehost
and they designate the same set of network interfaces to be attached to this host. In order to implement SSA field manager tracking and list merging properly, the injected index fields (injected
in the example JSON objects) for these two objects should be the same. Please note that these examples deliberately have the non-scalar fieldinterfaces
that are used to uniquely identify the list objects, so that we cannot designate the SSA list map keys to be{host, interfaces}
. For another object schema like{"host": "a.b.c", "port": 443}
, where all the identifying fields are scalars, we may not need to inject any new indexing fields as the already existing scalar fields could constitute the index set if they are all not nullable (required or defaulted).An example configuration looks like as follows:
Because the
spec.forProvider.vpcConfig
field of theCluster.eks
resource is an object list of max length 1 (actually an embedded object), this configuration injects an indexing field and defaults its value to"0"
. Please note thatvpcConfig
list item schema does not have an existing index set available to it and this is the reason we configure field injection to support SSA patch operations on this list.Upjet checks the supplied SSA merge strategy configuration and if interrupts the code generation pipelines of the supplied configuration is not compatible with the underlying resource schema, for example, when a map strategy configuration is supplied for an object list.
This PR moves the merge strategy related types from the
markers
package to theconfig
package to prevent the import cyclemarkers
->config
->markers
as themarkers
package already uses theconfig.Reference
. Making the merge strategies configurable via upjet's configuration framework, it makes more sense to move the merge strategy related types to theconfig
package.We may also consider automatically injecting SSA merge strategy markers on top of the configuration framework being introduced with this PR. This would allow us to override/remove any merge strategy configuration that's done by upjet on the provider side.
I have:
make reviewable
to ensure this PR is ready for review.backport release-x.y
labels to auto-backport this PR if necessary.How has this code been tested
This PR has been tested with custom builds of
upbound/provider-aws
and the configurationsupbound/configuration-aws-eks
andupbound/configuration-aws-network
in the context of crossplane-contrib/provider-upjet-aws#975. The AWS family provider packages used in these tests areindex.docker.io/ulucinar/provider-aws-{ec2, iam, eks}:v0.45.0-c914fe18a92011992e32630ca4d0dba4a8f36242
and the configuration packages areindex.docker.io/ulucinar/configuration-aws-{network, eks}:v0.45.0-c914fe18a92011992e32630ca4d0dba4a8f36242
. We also need changes in the crossplane-runtime (subject of a separate PR) so that the MR reconciler uses SSA patch operations while setting the resolved references (in the context of these tests, thespec.forProvider.vpcConfig[0].subnetIds
field) and changes in the XR reconciler so that the XR reconciler uses SSA patch operations while applying the composed resources from the compositions of the configuration packageupbound/configuration-aws-eks
.