Skip to content

KCL schema initialisation merges array fields with a default value instead of overriding themΒ #275

@karolszmndy

Description

@karolszmndy

What happened?

KCL schema initialisation merges array fields with a default value instead of overriding them.
This issue was already reported and closed here, but the solution does not fit the kcl-function use case.

I'm using kcl import to generate schemas for my composite resource definition (from its CRDs) and bring type safety to my kcl-function code in composition.

My xrd api spec contains fields that are arrays with default values.

  versions:
    - name: v1alpha1
      served: true
      referenceable: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                sizes:
                  type: array
                  items:
                    type: string
                    enum: ["Small", "Medium", "Large"]
                  default: ["Small", "Medium"]

The generated xrd schema reflects the default:

schema xMyCompositeResource:
  sizes?: [str] = ["Small", "Medium"]

Then in kcl-function source I use that schema for oxr:

oxr: xMyCompositeResource =  option("params")?.oxr
print(yaml.encode(oxr))

or

oxr = xMyCompositeResource{ **option("params")?.oxr }
print(yaml.encode(oxr))

If I provide value for the array field in XR, it's being merged with the default values:

xr.yaml

apiVersion: ...
kind: xMyCompositeResource
spec:
  sizes:
  - Large

function output

apiVersion: ...
kind: xMyCompositeResource
spec:
  sizes:
  - Large
  - Small
  - Medium

I can manually assign this array field after initialisation as a workaround, but it's very fragile and unintuitive:

oxr:xMyCompositeResource = {
    **option("params")?.oxr
    spec.sizes = option("params")?.oxr.spec.sizes
}

How can we reproduce it?

example.k

schema MyXRD:
   type: str = "MyXRD"
   name: str = "Unknown"
   sizes?: [str] = ["Small", "Medium"]

input = {
    name: "test-oxr"
    sizes: ["Large"]

}

oxr = MyXRD{**input}

oxr2: MyXRD = input

assert oxr.name == "test-oxr", "oxr.name should be 'test-oxr'"
assert oxr.sizes == ["Large"], "oxr.sizes should be ['Large']"

assert oxr2.name == "test-oxr", "oxr2.name should be 'test-oxr'"
assert oxr2.sizes == ["Large"], "oxr2.sizes should be ['Large']"

Output of kcl example.k:

 input:
   name: test-oxr
   sizes:
   - Large
 oxr:
   type: MyXRD
   name: test-oxr
   sizes:
   - Large
   - Medium
 oxr2:
   type: MyXRD
   name: test-oxr
   sizes:
   - Large
   - Medium

What environment did it happen in?

Function version: xpkg.upbound.io/crossplane-contrib/function-kcl:v0.11.4

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions