crossplane-contrib / function-cue-archived

Cuelang Integration for Crossplane's Composition Function
Apache License 2.0
10 stars 1 forks source link

How can I inject several fields at once from the observed resource into the managed resource? #79

Open ma-ble opened 9 months ago

ma-ble commented 9 months ago

How can I inject several fields at once from the observed resource into the managed resource?

In my example, I would like to transfer everything under spec.test to the managed resource.

apiVersion: nopexample.org/v1
kind: XSubnetwork
metadata:
  name: test-xrender
spec:
  test: 
    key1: "hello"
    key2: "dummy string"
    karray:
      - v1 
      - v2 
    key3: 5

---
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: xnopresources.nop.example.org
spec:
  compositeTypeRef:
    apiVersion: nop.example.org/v1alpha1
    kind: XNopResource
  mode: Pipeline
  pipeline:
  - step: conditional
    functionRef:
      name: function-cue
    input:
      apiVersion: cue.fn.crossplane.io/v1beta1
      kind: CUEInput
      metadata:
        name: patch-xr
      export:
        options:
          inject:
          - name: test
            path: spec.test
        target: XR
        value: |
          #env: string @tag("test")

          name: "XRPatching"
          resource: {
            spec: test: #env
          }
crossplane beta render xr.yaml composition.yaml function.yaml

When executing - using the function-cue - I get the following resource.

---
apiVersion: nopexample.org/v1
kind: XSubnetwork
metadata:
  name: test-xrender
spec:
  test: map[karray:[v1 v2] key1:hello key2:dummy string key3:%!s(float64=5)]

How can I iterate over the string "test" in Cuelang so that I get the desired output?

---
apiVersion: nopexample.org/v1
kind: XSubnetwork
metadata:
  name: test-xrender
spec:
  test: 
    key1: "hello"
    key2: "dummy string"
    karray:
      - v1 
      - v2 
    key3: 5
Mitsuwa commented 9 months ago

This looks like a bug, thank you for reporting this @ma-ble. I will work out a fix for this

e:

upon looking at this again i think this is mostly a bug around formatting the multiple keys that are pulled from fieldpath into the tag injection, ill need to ask the cue community about this more

Mitsuwa commented 9 months ago

A workaround would be specifying multiple tags to inject each individual key

Mitsuwa commented 9 months ago

You should also not be specifying that this spec.test would be converting to a string within cue, i believe there is a way to have it convert into a cue object thats defined like

#input: {
    key1: string
    key2: string
    karray: [...String]
    key3: int
}

#env: #input @tag("test")

Im not certain if that works copy pasta'd

ma-ble commented 9 months ago

Thank you very much for the quick reply.

In my specific use case, I would like to copy all fields under spec.test into the managed resource. The number of fields is very large and I did not want to have any dependencies on individual fields in the composition in this case. This would only make it unnecessarily bloated and confusing.

Otherwise, you are of course right that you can simply list each individual field in the composition (CUEInport value) as a workaround.

Mitsuwa commented 9 months ago

I have created a new issue #82 that I think is a better solution to this problem. It seems problematic to have to try to convert nested fields into appropriate tag injections and the solution proposed in #82 I feel is a more crossplane native solution to this problem.

do you think this will work for you @ma-ble ?

ma-ble commented 9 months ago

In my opinion, the problems are slightly different, but essentially identical. In my case, I cannot outsource the data to an EnviornmentConfig, as this relates directly to a claim - but in both cases the processing of several fields via the cue functions is required.

Mitsuwa commented 7 months ago

I spoke with paul jolly at the cue project and we have figured out a way that we can do this with a single tag.

Since cue only allows for primitives to be injected, what we could do is take the field that is being injected, if it is an object (has nested fields), we can convert that object into a json strong. From there it will come in as json blob within cue, which the user can then from there the user can use cue's json.Marshal. It is a bit cumbersome but it will give a single line entry for injecting + 1 more line for Marshaling

ma-ble commented 6 months ago

Great, do you have an example?

Mitsuwa commented 6 months ago

Unfortunately this repository is being deprecated and it is going to be merged with https://github.com/elastic/crossplane-function-cue, it is suggested that you move to this repository at your convenience. I have mentioned this functionality to paul before and perhaps we can bring this implementation over to the new repository as well