-
Notifications
You must be signed in to change notification settings - Fork 907
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conditional Resources in Composition #2712
Comments
As @Feggah alluded to, this functionality is something we explicitly avoided building in favor of 'Custom Compositions' per #2524. That said, I don't think we're fundamentally opposed to ever adding this functionality into the existing
Is using different compositions a feasible way to 'branch' here? e.g. One composition with the conditional resource and one without, then use a |
@Feggah thanks for your input. I'm unsure if #2524 might be overkill for our usecase. Basically, we would want a resource to be NOT rendered until a condition is met. Like a no-op resource. It would still be part of the composition and listed in the XR. @negz thanks for your considerations. We actually haven't thought about patches yet but it sounds very interesting. Do you think we need to enforce named resources? (I personally see the |
Just chiming in here. I see Custom Compositions as a great feature down the road, but until its there, the current Compositions framework leaves much to be desired. The basic premise of conditional resources seems very sane to me within a composition. In our case, we want to create a |
I have asked about the conditional resource creation support in Slack, and thought about this a bit more in detail. I find there are a couple of use cases where this conditional resource creation would benefit the community. 1. Environment specific requirementsThe original question I had was about how to disable creating EKS NodeGroup only for staging or development environment. Yes, patching a single NodeGroup resource is definitely possible, but if I were to have multiple separate NodeGroups (e.g. 1 being expensive production-ready node, and another being cheaper spot instance), I don't want to separate Composition definition just for that difference. If I had a control for disabling the creation of NodeGroup with some XR input, I could reuse the same Composition and tune it based on the environment. So, as an example, I can do this today: - base:
apiVersion: eks.aws.crossplane.io/v1alpha1
kind: NodeGroup
spec:
# ...
patches:
- fromFieldPath: spec.parameters.deploymentMode
toFieldPath: spec.forProvider.instanceTypes[0]
transforms:
- type: map
map:
production: m6g.large
staging: t4g.large
dev: t4g.medium But that's "either m6g or t4g", and instead, I want production to have "both m6g and t4g", while staging and dev to have "only t4g". I was hoping to do something like - name: node-group-m6g
base:
apiVersion: eks.aws.crossplane.io/v1alpha1
kind: NodeGroup
# **********
# Patch to disable this resource altogether if env is staging or dev
# **********
# ...
- name: node-group-t4g
base:
apiVersion: eks.aws.crossplane.io/v1alpha1
kind: NodeGroup
# ...
Another example I can think of is Subnet configuration - production could use multiple subnets, but environments such as development may not need the full redundancy. Just like the NodeGroup, it would be great if I can configure all the possible use cases in Composition, mainly aimed for production use cases, and disable any of those that do not need to be deployed in staging or dev env using XR input. 2. Dry run Composition updateI have been iterating on my Composition spec, and when adding an extra resource, there is no way to stop it to actually create the resource. Sometimes I just want to ensure that my Composition spec is correct, and when a Claim or XR is applied, I want to see if my spec was correctly rendered. This is similar to how I would use Terraform Plan to check the expected impact before applying, or use If there was a way to disable the resource creation, that would make it much easier to adjust Composition spec, without worrying about breaking or introducing unnecessary resources. I believe the condition field can support both of the use cases I described above. I personally find An example of that would be: - name: new-node-group
base:
apiVersion: eks.aws.crossplane.io/v1alpha1
kind: NodeGroup
spec:
forProvider:
# ...
creationPolicy: Create # Default, to be patched
deletionPolicy: Delete # Default, to be patched
patches:
- fromFieldPath: spec.parameters.deploymentMode
toFieldPath: spec.forProvider.instanceTypes[0]
transforms:
- type: map
map:
production: m6g.large
staging: t4g.large
dev: t4g.medium
- fromFieldPath: spec.parameters.deploymentMode
toFieldPath: spec.creationPolicy
transforms:
- type: map
map:
production: Disable # Do not create the cloud resource at all
staging: DryRun # Create managed resource, but do not update, only check whether it's sync'ed
dev: Create # Default, simply create the cloud resource
- fromFieldPath: spec.parameters.deploymentMode
toFieldPath: spec.deletionPolicy
transforms:
- type: map
map:
production: Orphan
staging: Delete
dev: Delete With Custom Composition, this sort of handling should certainly be possible. But, IMHO, I feel adding another customisation layer is an overkill for achieving resource creation control. I personally see the |
I also would like this as well. creating an entire composition violates DRY. I understand conditionals can get out of hand... but is there anyway we can limit it to just what was originally proposed here ? This feature I am surprised cross plane does not support. I also understand your arguments for avoiding compositions to devolve into a full fledged DSL. It is so critical for example if a gcp region does not have a particular machine type, we have to be able to conditionally use another one. or to conditionally reference or own a created base resource. |
This feature is absolutely necessary. It would instantly replace helm templates... Please for the love of god let me get rid of the moustaches |
Crossplane does not currently have enough maintainers to address every issue and pull request. This issue has been automatically marked as |
/fresh |
Crossplane does not currently have enough maintainers to address every issue and pull request. This issue has been automatically marked as |
/fresh |
/fresh |
Is there any update on this topic? |
See the Composition Functions alpha feature in 1.11 and later. That is intended to address this need. |
With Crossplane v1.14 about to ship we'll have Composition Functions in beta. Our current longer term thinking is that we'll eventually remove (or at least deprecate and freeze) support for native P&T, per the issue above. At that point whether Crossplane supports conditional resources is really up to what Functions you use to do Composition. If your Function(s) support conditionals, so does Crossplane. For example crossplane-contrib/function-patch-and-transform#14 proposes adding conditionals to the P&T function. So, it's early, but I suspect we probably won't do anything in core Crossplane to enable this other than continue working on making Functions the future of Composition. |
I have a pull request open against function-patch-and-transform that uses the Common Expression Language (CEL) that is used with other parts of the K8s ecosystem (like CRD validation). crossplane-contrib/function-patch-and-transform#26 Since multiple function steps can be run in a pipeline, and they update the partial desired state, these conditions can be use to build conditional logic for rendering resources. |
Building on @stevendborrelli's PR I added conditionals down to the desired resources. We wanted a single patch-and-transform function to be able to apply our global patchsets and the condition enables this by only running when the resource is being included. |
I workaround this "feature miss" with go-templating function: - step: create-pg-chat-db
functionRef:
name: function-go-templating
input:
apiVersion: gotemplating.fn.crossplane.io/v1beta1
kind: GoTemplate
source: Inline
inline:
template: |
{{ $enabled := (hasKey $.observed.composite.resource.spec "chatDBEnabled" | ternary $.observed.composite.resource.spec.chatDBEnabled false) }}
{{ if $enabled }}
{{ $resName := (printf "%s-chat" $.observed.composite.resource.spec.id) }}
apiVersion: postgresql.sql.crossplane.io/v1alpha1
kind: Database
metadata:
name: {{ $resName }}
annotations:
gotemplating.fn.crossplane.io/composition-resource-name: {{ $resName }}
spec:
forProvider:
owner: {{ (printf "%s-pg-user" $.observed.composite.resource.spec.id) }}
template: "{{ $.observed.composite.resource.spec.chatTemplate }}"
encoding: "UTF8"
providerConfigRef:
name: {{ .observed.composite.resource.spec.pgSuperuserProviderConfigName }}
{{ end }}
- step: auto-detect-pg-db
functionRef:
name: function-auto-ready
|
@jcooklin How have you found this to be working out? Any issues? |
@negz is here available https://github.com/stevendborrelli/function-conditional-patch-and-transform and working great |
@haarchri Do you have a sense of how many different people/orgs have tried it? I'm trying to get a sense of whether it's been well exercised enough to merge the feature upstream, into function-patch-and-transform. |
On my side i running this in 2 orgs |
Can we close this issue? With functions we now have multiple ways to embed conditional logic into compositions, including https://github.com/crossplane-contrib/function-cel-filter. |
Yes, I think so. We now have the following options available:
You can also write your own function using the full expressiveness of a general purpose programming language using https://github.com/crossplane/function-template-go or https://github.com/crossplane/function-template-python. Given that we're likely to deprecate native patch and transform compositions once functions are GA, I don't think we'll be making any major improvements (such as adding conditionals) to native P&T. |
What problem are you facing?
Currently, if you create a claim in Crossplane, a composition is selected and all defined resources are rendered using parameters from the claim. In most cases this works fine and without issues.
However, in some cases we only want to create a resource if a condition is met, i.e. a flag is set by the user or another resource is ready and provides specific info needed by the conditional resource, for example an AWS ARN.
How could Crossplane help solve your problem?
It would be great to specify conditions for a resource in a composition to be rendered.
These conditions should be optional and could be defined alongside
patches
andbase
. I'm imagining something like this:The text was updated successfully, but these errors were encountered: