kubectl icon indicating copy to clipboard operation
kubectl copied to clipboard

kubectl explain template fails when array includes boolean value

Open ardaguclu opened this issue 10 months ago • 7 comments

What happened:

apply the example CRD and running kubectl explain fails with;

CRD
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: mock-resources.test.tectonic.com
spec:
  group: test.tectonic.com
  scope: Namespaced
  names:
    plural: mock-resources
    singular: mock-resource
    kind: MockResource
    listKind: MockResources
  versions:
    - name: v1
      storage: true
      served: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            status:
              type: object
              properties:
                statuses:
                  type: object
                  properties:
                    status1:
                      type: string
                    status2:
                      type: string
                podStatuses:
                  type: object
                  additionalProperties:
                    type: array
                    items:
                      type: string
                otherStatuses:
                  type: object
                  additionalProperties:
                    type: array
                    items:
                      type: string
                customConditions:
                  type: array
                  items:
                    type: object
                    properties:
                      lastTransitionTime:
                        type: string
                      lastUpdateTime:
                        type: string
                      message:
                        type: string
                      reason:
                        type: string
                      status:
                        type: string
                      type:
                        type: string
                otherCustomConditions:
                  type: array
                  items:
                    type: object
                    properties:
                      lastTransitionTime:
                        type: string
                      lastUpdateTime:
                        type: string
                      message:
                        type: string
                      reason:
                        type: string
                      status:
                        type: string
                      type:
                        type: string
              additionalProperties: true
            spec:
              type: object
              required:
                - password
                - select
              properties:
                password:
                  type: string
                  minLength: 1
                  maxLength: 25
                  pattern: "^[a-zA-Z0-9._\\-%]*$"
                number:
                  type: integer
                  minimum: 2
                  maximum: 4
                select:
                  type: string
                fieldGroup:
                  type: object
                  description: "[SCHEMA] field group - Quis cupidatat in sint occaecat quis dolore irure ea minim sint aliquip nisi aliquip."
                  title: "[SCHEMA] Field Group"
                  properties:
                    itemOne:
                      type: string
                    itemTwo:
                      type: integer
                arrayFieldGroup:
                  type: array
                  title: "[SCHEMA] Array Field Group"
                  description: "[SCHEMA] array field group - Quis excepteur nostrud qui sunt reprehenderit reprehenderit deserunt eu aute laboris id aliqua."
                  items:
                    type: object
                    properties:
                      itemOne:
                        type: string
                      itemTwo:
                        type: integer
                hiddenFieldGroup:
                  type: object
                  properties:
                    hiddenItem:
                      type: object
                podCount:
                  type: integer
                endpointList:
                  type: array
                  items:
                    type: object
                    additionalProperties: true
                resourceRequirements:
                  type: object
                  additionalProperties: true
                k8sResourcePrefix:
                  type: string
                booleanSwitch:
                  type: boolean
                checkbox:
                  type: boolean
                imagePullPolicy:
                  type: string
                updateStrategy:
                  type: object
                  additionalProperties: true
                text:
                  type: string
                nodeAffinity:
                  type: object
                  additionalProperties: true
                podAffinity:
                  type: object
                  additionalProperties: true
                podAntiAffinity:
                  type: object
                  additionalProperties: true
                advanced:
                  type: string
                fieldDependencyControl:
                  type: boolean
                fieldDependency:
                  type: string
                nestedFieldDependency:
                  type: object
                  properties:
                    enabled:
                      type: boolean
                    settings:
                      type: object
                      properties:
                        enabled:
                          type: boolean
                arrayFieldDependency:
                  type: array
                  items:
                    type: object
                    properties:
                      enabled:
                        type: boolean
                      dependent:
                        type: string
                hidden:
                  type: string
                objectWithArray:
                  type: object
                  properties:
                    name:
                      type: string
                    tags:
                      type: array
                      items:
                        type: string
                    birthday:
                      type: object
                      properties:
                        month:
                          type: number
                        day:
                          type: number
                        year:
                          type: number
                arrayWithObject:
                  type: array
                  items:
                    type: object
                    properties:
                      organization:
                        type: object
                        properties:
                          name:
                            type: string
                          address:
                            type: object
                            properties:
                              street:
                                type: string
                              city:
                                type: string
                              state:
                                type: string
                      current:
                        type: boolean
                      resourceRequirements:
                        type: object
                        properties: {}
                deeplyNested:
                  type: object
                  properties:
                    foo:
                      type: object
                      properties:
                        bar:
                          type: object
                          properties:
                            baz:
                              type: object
                              properties:
                                bat:
                                  type: object
                                  additionalProperties: true
GROUP:      test.tectonic.com
KIND:       MockResource
VERSION:    v1

error: template: plaintext:39:13: executing "plaintext" at <include "schema" (dict "gvk" $gvk "Document" $.Document "FieldPath" $.FieldPath "Recursive" $.Recursive)>: error calling include: template: plaintext:63:21: executing "schema" at <include "output" (set $ "schema" .)>: error calling include: template: plaintext:101:17: executing "output" at <include "fieldList" (dict "schema" $resolved "level" 1 "Document" $.Document "Recursive" $.Recursive)>: error calling include: template: plaintext:257:15: executing "typeGuess" at <.items>: can't evaluate field items in type bool

What you expected to happen:

kubectl explain properly renders the CRD to template

How to reproduce it (as minimally and precisely as possible): Apply CRD and run kubectl explain

Anything else we need to know?:

Environment:

  • Kubernetes client and server versions (use kubectl version): 1.28, 1.29, 1.30
  • Cloud provider or hardware configuration:
  • OS (e.g: cat /etc/os-release):

ardaguclu avatar Apr 24 '24 07:04 ardaguclu

I verified that CRD is successfully applied to API server.

/triage accepted /priority backlog

@alexzielenski @ah8ad3 do you have any insights about how to troubleshoot this?. I spent some time on it but couldn't sort out. Thanks.

ardaguclu avatar Apr 24 '24 07:04 ardaguclu

Thanks for raising this issue Arda. Tested it with some CRD's few months ago and it worked fine, i will take a look at this. I will add my finding and troubleshoot after i can reproduce it.

ah8ad3 avatar Apr 24 '24 07:04 ah8ad3

I haven’t dug too deeply into it my guess would be that the problem is your schema uses ‘additionalProperties: true’ while the template assumes it is always a schema in a few places:

https://github.com/kubernetes/kubectl/blob/d0e936c703558421df2ef367a7c8c1c5972e5c3c/pkg/explain/v2/templates/plaintext.tmpl#L185

the template should be changed to handle/ignore bool case

alexzielenski avatar Apr 24 '24 08:04 alexzielenski

@ardaguclu After some debugging i find out if you remove line 77 of schema. It would work fine.

ah8ad3 avatar Apr 24 '24 08:04 ah8ad3

Thanks @alexzielenski, code wants to iterate over true value of additionalProperties. I can fix that if you want.

ah8ad3 avatar Apr 24 '24 08:04 ah8ad3

That’d be helpful, thanks @ah8ad3 !

/assign @ah8ad3

alexzielenski avatar Apr 24 '24 08:04 alexzielenski

Thanks a lot for taking care of this.

ardaguclu avatar Apr 24 '24 08:04 ardaguclu