Skip to content

Commit

Permalink
new suggested solution - management policy
Browse files Browse the repository at this point in the history
Signed-off-by: lsviben <sviben.lovro@gmail.com>
  • Loading branch information
lsviben committed Mar 31, 2023
1 parent 2a43e9c commit d944b43
Showing 1 changed file with 102 additions and 3 deletions.
105 changes: 102 additions & 3 deletions design/one-pager-ignore-changes.md
Expand Up @@ -34,6 +34,10 @@ Some examples of this case:
have external systems that add tags to resources for billing, tracking
or similar purposes. This can conflict with the tags set in
`spec.forProvider.tags`.
- There is an use case with [AzureAD Group] where initially the group is
created certain with `members` and `owners` but is then managed externally
over time as members need to be added or removed. For now the
workaround is to use terraform provider with [ignore_changes].

In these cases, it would make sense to make Crossplane ignore select
parameters during updates. Terraform addresses this use case with its
Expand All @@ -44,18 +48,107 @@ possible to have different Crossplane Compositions managing a single
external resource. This could open up some interesting new possibilities
for Crossplane.

The obvious way would be to just not set the field in the `spec.forProvider`.
However, due to [Late Initialization], some fields are being set in
`spec.forProvider` without any user input. Plus there are some cases
where the field is required/wanted upon creation, but not on updates.

So in this document, the aim will be to introduce a solution in Crossplane
for ignoring some managed resource parameters during updates.

## Goals

* Design a functionality that allows for ignoring some fields during
* Design a functionality that allows for ignoring select fields during
resource updates.

## Solution
## Proposal

Proposed solution is to use the new [managementPolicy] field which came with
the [ObserveOnly] feature and add a new management policy that will
skip late initialization. The loss the information that the
late initialization was providing would be offset by the `status.atProvider`
which contains the resource state on the provider side and is being
added alongside [ObserveOnly].

In addition to the new management policy, we will also add a new field
`spec.initProviders` which would contain parameters that should only be
used at the creation time. This would allow users to specify fields that
should be ignored on updates, but still be used during creation. This can
be added as a separate feature.

## Implementation

### Management policy

Proposed name for the new management policy is `PartialControl`, which
would fit with the current `FullControl` and insinuate that the resource
is not fully managed by Crossplane. Some other proposals for the naming
are: `ExplicitControl`, `SelectiveControl`, `IgnoreLateInit`.

The new management policy would be implemented in the `crossplane-runtime`
and would just ignore the [ResourceLateInitialized] condition and
skip the managed resource update [here][Late Initialization Update] if
the management policy is set to `PartialControl`.

When it comes to the deletion policy, the `PartialControl` policy would
orphan the external resource if the managed resource is deleted. This is
because the resource is not fully managed by Crossplane.

### initProviders

The idea here was to do something similar to K8s `initContainers` and add a
field `initProvider` to the managed resources. The parameters under
`initProvider` would be used only during creation. The `initProvider` would
have the same schema as `forProvider`.

```yaml
apiVersion: eks.aws.crossplane.io/v1alpha1
kind: NodeGroup
metadata:
name: my-group
spec:
initProvider:
scalingConfig:
desiredSize: 1
forProvider:
region: us-east-1
clusterNameRef:
name: sample-cluster
subnetRefs:
- name: sample-subnet1
nodeRoleRef:
name: somenoderole
scalingConfig:
maxSize: 5
minSize: 1
updateConfig:
maxUnavailablePercentage: 50
force: true
providerConfigRef:
name: example
```

This would allow users to specify fields that would only be used on creation,
but not on updates.

When it comes to the implementation, from Crossplane side we would need to
change the API. But the handling would all need to be done on the
provider level. The `initProvider` fields should only be used in the `Create`
step of the managed resource reconciliation loop.

Support for `initProvider` would need to be a manual change in each provider.
From our side we could provide a helper function to merge the `initProvider`
and `forProvider` fields which would be used in the `Create` step.

### Feature Gating

The new management policy would use the same feature gate as ObserveOnly. So
it would be an alpha feature that will be off by default and will be
controlled by `--enable-alpha-management-policies` flag in Providers.

### Implementation
The `initProvider` field would require a separate feature gate. So it would
also be disabled by default and be controlled by `--enable-alpha-init-provider`
flag in the Provider.

## Solution alternative considered

Expand Down Expand Up @@ -235,6 +328,12 @@ if this issue is not that widespread, we could have an easy fix.
[Target]: https://doc.crds.dev/github.com/upbound/provider-aws/appautoscaling.aws.upbound.io/Target/v1beta1@v0.24.0
[NodeGroup]: https://doc.crds.dev/github.com/upbound/provider-aws/eks.aws.upbound.io/NodeGroup/v1beta1@v0.24.0
[Node Pool]: https://doc.crds.dev/github.com/upbound/provider-gcp/container.gcp.upbound.io/NodePool/v1beta1@v0.28.0
[AzureAD Group]: https://marketplace.upbound.io/providers/upbound/provider-azuread/v0.5.0/resources/groups.azuread.upbound.io/Group/v1beta1
[Late Initialization]: https://docs.crossplane.io/v1.11/concepts/managed-resources/#late-initialization
[managementPolicy]: https://github.com/crossplane/crossplane-runtime/blob/master/apis/common/v1/policies.go#L22
[ObserveOnly]: https://github.com/crossplane/crossplane/blob/master/design/design-doc-observe-only-resources.md
[ResourceLateInitialize]: https://github.com/crossplane/crossplane-runtime/blob/00239648258e9731c274fb1f879f8255b948c79a/pkg/reconciler/managed/reconciler.go#L1033
[Late Initialization Update]: https://github.com/crossplane/crossplane-runtime/blob/00239648258e9731c274fb1f879f8255b948c79a/pkg/reconciler/managed/reconciler.go#L1033
[ignore_changes]: https://developer.hashicorp.com/terraform/language/meta-arguments/lifecycle#ignore_changes
[crossplane-runtime]: https://github.com/crossplane/crossplane-runtime/
[crossplane-runtime/fieldpath]: https://github.com/crossplane/crossplane-runtime/tree/master/pkg/fieldpath

0 comments on commit d944b43

Please sign in to comment.