crossplane-contrib / function-kcl

Crossplane Composition Functions using KCL Programming Language
Apache License 2.0
36 stars 16 forks source link

How to modify composite resource connection details from kcl function? #59

Closed markphillips100 closed 5 months ago

markphillips100 commented 6 months ago

I am developing a composite using KCL function code to create resources needed for an Azure workload identity, namely a UserAssignedIdentity, a FederatedIdentityCredential and a K8 Object for a service account. The PrincipalId of the UserAssignedIdentity is needed by other composites to facilitate the creation of RoleAssignment resources for their own access needs. So I need to surface the PrincipalId property from the composite somehow. NOTE: RoleAssignment only accepts a PrincipalId and has no selector option.

The problem is UserAssignedIdentity does not surface any information in connection details so writeConnectionSecretToRef produces a secret with no data, and of course this then provides no data to propagate up to the composite itself.

The status.atProvider data surfaced by the UserAssignedIdentity in the observed ocds dictionary does contain all the data needed of course but I'm not sure how to surface this to the composite. Theoretically I could write my own secret with the required data but was wondering if there was a way of still using a composite's connectiondetails so the secret is written by crossplane. Any ideas?

markphillips100 commented 6 months ago

If I have to go down the road of creating my own secret, does KCL support transforming some KCL data object to json/yaml and base64 encoding it?

Peefy commented 6 months ago

Could the system modules help? https://www.kcl-lang.io/docs/reference/model/json

markphillips100 commented 6 months ago

For format conversion yes it would. Still need to base64 encode too. Is there a module with that support available?

markphillips100 commented 6 months ago

Got it https://www.kcl-lang.io/docs/reference/model/base64

markphillips100 commented 6 months ago

@Peefy Whilst I can create a secret from the composition I'm not sure it is the right approach for compositions.

Have you seen how the go templating function supports CompositeConnectionDetails? The readme explains how to render out a resource to convey composite key/values and also how to indicate if a resource is ready or not (another feature I think is quite important).

That function adds the connection details as defined by their custom resource as shown here. Ready state detection is by annotation as shown here. Are both these features something KCL function could implement?

Peefy commented 6 months ago

Make sense. This feature can be implemented.

markphillips100 commented 6 months ago

Ready state detection is by annotation as shown here

Hi @Peefy . Just wanted to be sure we don't forget about ready state annotation enhancement. Maybe a separate PR?

An example of why it is needed: If I am copying data from resource A's status.atProvider property into resource B's forProvider property and the resource A is not ready so no data available, I want to still create resource B's MR but make it NotReady (by applying the annotation conditionally). This assumes resource B can exist synced with the property not yet having a real value.

Only option at the moment is to conditionally not include resource B in the items list. On the other hand, always including it even though it is not ready runs the risk of it not getting resolved with the correct values.

Peefy commented 6 months ago

Just wanted to be sure we don't forget about ready state annotation enhancement. Maybe a separate PR?

I did it in this PR https://github.com/crossplane-contrib/function-kcl/pull/61 and the example:https://github.com/crossplane-contrib/function-kcl/pull/61/files#diff-5d9851a7828526bc8ae1407fef1440e7cdf703f59da4f3ef6a6af59e95ac44d5 because they are related features

markphillips100 commented 6 months ago

I see the annotation code in the recent commit Thank you.👍

Did you say you had an example of applying the annotation in your linked example?

Peefy commented 6 months ago

Yes, do you mean this example with the ready annotation? image

markphillips100 commented 6 months ago

I must be blind. Sorry for not seeing that.

markphillips100 commented 6 months ago

Hey just thinking, is the resource defaulted to ready: True if no annotation is provided?

Peefy commented 6 months ago

I see the default ready status is Unspecified. For convenience, it may be possible to set the default value of ready to True from the configuration of kcl-funding itself. For example

      apiVersion: krm.kcl.dev/v1alpha1
      kind: KCLRun
      metadata:
        annotations:
          "krm.kcl.dev/default_ready": "True"
        name: basic
      spec:

image

markphillips100 commented 6 months ago

Yeah whatever the default behaviour was before the code change might be wise. I don't know if that means unspecified or true to be honest.

markphillips100 commented 6 months ago

Unspecified would make sense as a default I guess. I'd assume the resource provider itself would then set ready status as and when it needs to. Setting the annotation to False basically prevents the provider from making a change.

I shall be able to confirm such behaviour very early on with all the compositions I'm creating.

Peefy commented 6 months ago

I think too.

markphillips100 commented 6 months ago

You've been very busy and I greatly appreciate all your efforts. Thank you.

Peefy commented 6 months ago

It's okay, I'm willing to communicate anytime. I believe there will be more community participants in the future. ❤️

markphillips100 commented 6 months ago

I've tried connection details and works perfect. I get my resource data propagating up to the secret specified by my claim.

Also tested setting status property on dxr and that works great too. Haven't tested the ready state yet.

markphillips100 commented 6 months ago

@Peefy I'm in the process of using the ready state to try and prevent a k8 secret from appearing ready until an atProvider data value is available on another resource in the same composition. The intention is to set ready state to False until data available and then set to True.

I use the Object.kubernetes.crossplane.io/v1alpha1 Kind from xpkg.upbound.io/crossplane-contrib/provider-kubernetes:v0.12.1 to create the secret.

To just test things without the noise of other resources, I just apply the annotation "krm.kcl.dev/ready": "False" to the provider's Object Kind. What I'm finding though is the MR is immediately in the ready state and has no such annotation on it. What I don't know at this point is if it's the kubernetes provider or function-kcl that is not writing out the annotation.

Let me know if you want to open this as a separate issue.

markphillips100 commented 6 months ago

I'm pretty sure the annotation is removed by the meta.RemoveAnnotations call which is fine. Can't explain why the ready state is not False though.

markphillips100 commented 6 months ago

I think my problem has more to do with the Object in kubernetes-provider and how its ready state is not determined based on the secret manifest state. I'll try and few things and report back over the weekend.

markphillips100 commented 6 months ago

@Peefy I've learnt a little more on ready state and it's become clear to me that setting it from the function is a use case only necessary for when a resource in a composition has no ready state property that is managed by itself, e.g. a ProviderConfig kind from provider-sql or provider-kubernetes.

For these apis we need to force the ready state else the composition will never become ready, hence need to use the annotation.

I've a real-world use case using the config from provider-sql and it works perfectly fine there.

Peefy commented 6 months ago

Hello @markphillips100 Sorry for the late reply. We just had a short vacation.

Are you saying that you need to force the ready state to be set to False in the KCL function? I tried a use case locally and it can indeed be set to False through the annotations

markphillips100 commented 6 months ago

Sorry to interrupt the hols.

I was thinking I could set to False in an attempt to allow me to decide the ready state of a resource. I was trying it with provider-kubernetes Object api to manage the creation of a secret, i.e. make it not ready until the data of the secret had a proper value (one provided by another resources atProvider data).

Seems the Object's ready state is controlled by the provider/crossplane and is made ready by itself when the resource is created, thereby ignoring any value the function may have set. You can attempt to use the Object's readiness policy DeriveFromObject but I believe in this case it makes no difference.

I tried a use case locally and it can indeed be set to False through comments.

Curious what you mean by "through comments"?

Peefy commented 6 months ago

Make sense. I'll give a try.

Peefy commented 5 months ago

Closed by #61