Allow composition pipeline steps to reference specific function revisions
What problem are you facing?
We have a large custom composition function that handles the logic.
Because the logic is in the function itself, we cannot do a staggered rollout. Once the new function is deployed all the composites will use it straight away, circumventing the composition revision.
The actual composition only contains a few parameters for the functions, and they are mostly static. So composition revisions as they are today are not helpful for this, as they don't have any reference to the function revisions to be used.
How could Crossplane help solve your problem?
If Crossplane could track the version or revision of any given composition and match it to each function in the pipeline, it would be possible to expand the functionality of the composition revisions to also include functions.
Let's assume we have a composition with version 1 and a function version 1. We deploy some claims or composites with the compositionUpdatePolicy set to Manual. Now version 2 of the composition and the function are released. Version 2 contains some changes that will cause an interruption and should be deployed at a specific time, and the time varies for each claim/composite.
However, because the composition doesn't track which version of the function to use, the compositionUpdatePolicy is useless here. As soon as the function is deployed all resources will be reconciled against this. Even worse, because compositionUpdatePolicy is set to Manual the inputs will still be from version 1 of the composition. This could also lead to issues with function version 2 (breaking changes with inputs, etc...).
Right now to ensure that a specific version of a function matches to a specific composition is by adding the version to the name of the function itself. So instead of calling it myfunc the name would be myfunc-v1.2.3.
@Kidswiss This is possible if you implement the function to look at the .observed.composite.resource.spec.compositionRevisionRef.name parameter and execute the appropriate logic. It's not very pretty, as the compositionRevisionRef.name is a generated value based on the hash of the composition content, but it might serve your purpose for the short term.
Another solution is to add an input parameter to the function that changes with the composition, so that when the composition increments from 1 to 2, the input parameter to the function also increments from 1 to 2 and the function knows to execute the new logic instead of the old logic. This is probably a cleaner solution and also allows you to execute different "versions" of the function decoupled from the specific version of the composition. For example you may want composition version 2.5 to still call function 2.
Hi @bobh66
Thanks for the suggestions.
However both are not very feasible for us, because our comp function logic is pretty huge and adding cases for each new revision will be challenging. It also leaves a lot more room for errors during development.
My current idea is like this:
We build each new function and add the version as a suffix to it:
myfunc-v1.0.0:l(atest or also v1.0.0) myfunc-v1.0.1:latest
Then in the composition:
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
pipeline:
- functionRef:
name: myfunc-v1.0.1
So each composition revision will point at a distinct version of the function. We then ensure that we keep the most current and a few old ones around.
It's also ugly, but it's what come closest to native support for composition revisions with functions.
That's probably the best solution - I don't know that Crossplane could do much more than that natively. It really is in the developer's hands to determine which version of a function is supposed to be called, and if we're not going to mandate backward-compatibility in functions I think this is probably the cleanest solution.
I don't know that Crossplane could do much more than that natively.
That's basically what I'd like to see in Crossplane compositions, a native way to specify which version (or revision) of a function should be used with my composition.
Also it's not necessarily about backward compatibility but rather rolling out changes gracefully. It's very possible that a change in our function could result in restarts of production workloads, which should only happen during specific times and for each composite individually.
That would also require the ability to deploy and execute multiple revisions of a Function, which is currently not possible other than the way you are doing it with separate deployments for each version. I think that would get complicated very quickly.
Given that this is the only reasonable way to get actual composition revisions when using custom functions (and that this mode is what is pushed through upbound's tooling with embedded functions), I'd be in favor of crossplane having a native way to handle this, otherwise we lose a big part of the safety of crossplane when using custom functions.
The Function kind already posesses a notion of FunctionRevision and revision history limit, maybe all we need is the ability to keep "inactive" revisions running, and add a revision selector in the functionRef of the composition's pipeline?
I did some more testing with my approach, however, I quickly stumbled upon #5564 and then #3423.
It's currently not possible to have the same function installed in different versions. The lock will stumble and the functions never reach a good state. So it seems right now there's no good way to emulate the composition revisions for functions...
Update: Okay I randomly found that dependency management can be disabled by setting skipDependencyResolution: true in a function, which will circumvent the bugs and deploy all the functions as expected.
Crossplane does not currently have enough maintainers to address every issue and pull request. This issue has been automatically marked as stale because it has had no activity in the last 90 days. It will be closed in 14 days if no further activity occurs. Leaving a comment starting with /fresh will mark this issue as not stale.
/fresh
Crossplane does not currently have enough maintainers to address every issue and pull request. This issue has been automatically marked as stale because it has had no activity in the last 90 days. It will be closed in 14 days if no further activity occurs. Leaving a comment starting with /fresh will mark this issue as not stale.