colossal
colossal

Reputation: 559

Dynamic key/value input properties to CRD in Kubernetes

While defining a K8 CRD, I need a flexibility to pass any key/value pairs as input while submitting a resource object. https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/

schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                cronSpec:
                  type: string
                image:
                  type: string
                replicas:
                  type: integer

From the link above, if you see properties can only hold cronSpec, image and/or replicas. Can it be free-form? Meaning I can pass any key/value pairs and in my code I get a collection (may be a map) that can contain key/value pairs.

https://stackoverflow.com/users/14044/mike-bryant I tried with this CRD:

schema:
    openAPIV3Schema:
      type: object
      properties:
        apiVersion:
          type: string
        spec:
          type: object
          properties:
            appProperties:
              type: object
              properties:
                messages:
                  type: array
                  items:
                    type: object
                    properties:
                      key:
                        type: string
                      value:
                        type: string

with custom object having input like this:

messages:
      - key: "server1"
        value: "ping failed"
      - key: "server2"
        value: "abort"
      - key: "server3"
        value: "succes"

but when I patch the crd with some update status, k8 fails with below error:

kind=Status, message=the server rejected our request due to an error in our request, metadata=ListMeta(_continue=null, remainingItemCount=null, resourceVersion=null, selfLink=null, additionalProperties={}), reason=Invalid, status=Failure, additionalProperties={}).:

Upvotes: 4

Views: 3891

Answers (3)

systemBuilder
systemBuilder

Reputation: 47

I wanted to have arbitrarily nested json in my k8s custom resource definition. Unfortunately, while "addtionalProperties: true" seems to work, it only works for ONE LEVEL of specification (i.e. arbitrarily nested json is still not allowed). This DOES NOT agree with the OpenAPI v3 spec which Kubernetes is supposed to be following! I finally settled on the following solution:

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: exampleconfigs.mycompany.com
spec:
  group: mycompany.com
  names:
    kind: ExampleConfig
    listKind: ExampleConfigList
    plural: exampleconfigs
    singular: exampleconfig
  scope: Namespaced
  versions:
    - name: v1
      served: true
      storage: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              x-kubernetes-preserve-unknown-fields: true

This solves, the problem completely, i.e., it allows json nested to an arbitrary degree, and is subtle, because you must put the x-kubernetes-preserve-unknown-fields in the 2nd level "object:" field for the tag to work properly, clarifying some of the previous suggestions.

Upvotes: 0

nakamume
nakamume

Reputation: 800

We can use additionalProperties with type: string for this.

additionalProperties:
    type: string

For example, I'm adding customSelector property to the spec. customSelector is of type object (a map) with strings for key/values.

spec:
    properties:
      customSelector:
        additionalProperties:
          type: string
        description: Free form key value pairs
        type: object
    type: object

Upvotes: 2

Mike Bryant
Mike Bryant

Reputation: 1112

I think you can use additionalProperties for this.

x-kubernetes-preserve-unknown-fields might also be useful: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#controlling-pruning

Upvotes: 0

Related Questions