-
Notifications
You must be signed in to change notification settings - Fork 38
Closed
Description
If a CRD uses an enum, k8s.contrib.crd will fail, and with a rather unhelpful error message to the user:
–– Pkl Error ––
No member of union type matched value 'new Mapping { ["apiVersion"] = "apiextensions.k8s.io/v1"; ["kind"] = "CustomResourceDefinition"; ["metadata"] { ["annotations"] { ["controller-gen.kubebuilder.io/version"] = "v0.11.3"; ["helm.sh/resource-policy"] = "keep" }; ["name"] = "cephbucketnotifications.ceph.rook.io" }; ["spec"] { ["group"] = "ceph.rook.io"; ["names"] { ["kind"] = "CephBucketNotification"; ["listKind"] = "CephBucketNotificationList"; ["plural"] = "cephbucketnotifications"; ["singular"] = "cephbucketnotification" }; ["scope"] = "Namespaced"; ["versions"] { new Mapping { ["name"] = "v1"; ["schema"] { ["openAPIV3Schema"] { ["description"] = "CephBucketNotification represents a Bucket Notifications"; ["properties"] { ["apiVersion"] { ["description"] = "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources"; ["type"] = "string" }; ["kind"] { ["description"] = "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds"; ["type"] = "string" }; ["metadata"] { ["type"] = "object" }; ["spec"] { ["description"] = "BucketNotificationSpec represent the spec of a Bucket Notification"; ["properties"] { ["events"] { ["description"] = "List of events that should trigger the notification"; ["items"] { ["description"] = "BucketNotificationSpec represent the event type of the bucket notification"; ["enum"] { "s3:ObjectCreated:*"; "s3:ObjectCreated:Put"; "s3:ObjectCreated:Post"; "s3:ObjectCreated:Copy"; "s3:ObjectCreated:CompleteMultipartUpload"; "s3:ObjectRemoved:*"; "s3:ObjectRemoved:Delete"; "s3:ObjectRemoved:DeleteMarkerCreated" }; ["type"] = "string" }; ["type"] = "array" }; ["filter"] { ["description"] = "Spec of notification filter"; ["properties"] { ["keyFilters"] { ["description"] = "Filters based on the object's key"; ["items"] { ["description"] = "NotificationKeyFilterRule represent a single key rule in the Notification Filter spec"; ["properties"] { ["name"] { ["description"] = "Name of the filter - prefix/suffix/regex"; ["enum"] { "prefix"; "suffix"; "regex" }; ["type"] = "string" }; ["value"] { ["description"] = "Value to filter on"; ["type"] = "string" } }; ["required"] { "name"; "value" }; ["type"] = "object" }; ["type"] = "array" }; ["metadataFilters"] { ["description"] = "Filters based on the object's metadata"; ["items"] { ["description"] = "NotificationFilterRule represent a single rule in the Notification Filter spec"; ["properties"] { ["name"] { ["description"] = "Name of the metadata or tag"; ["minLength"] = 1; ["type"] = "string" }; ["value"] { ["description"] = "Value to filter on"; ["type"] = "string" } }; ["required"] { "name"; "value" }; ["type"] = "object" }; ["type"] = "array" }; ["tagFilters"] { ["description"] = "Filters based on the object's tags"; ["items"] { ["description"] = "NotificationFilterRule represent a single rule in the Notification Filter spec"; ["properties"] { ["name"] { ["description"] = "Name of the metadata or tag"; ["minLength"] = 1; ["type"] = "string" }; ["value"] { ["description"] = "Value to filter on"; ["type"] = "string" } }; ["required"] { "name"; "value" }; ["type"] = "object" }; ["type"] = "array" } }; ["type"] = "object" }; ["topic"] { ["description"] = "The name of the topic associated with this notification"; ["minLength"] = 1; ["type"] = "string" } }; ["required"] { "topic" }; ["type"] = "object" }; ["status"] { ["description"] = "Status represents the status of an object"; ["properties"] { ["conditions"] { ["items"] { ["description"] = "Condition represents a status condition on any Rook-Ceph Custom Resource."; ["properties"] { ["lastHeartbeatTime"] { ["format"] = "date-time"; ["type"] = "string" }; ["lastTransitionTime"] { ["format"] = "date-time"; ["type"] = "string" }; ["message"] { ["type"] = "string" }; ["reason"] { ["description"] = "ConditionReason is a reason for a condition"; ["type"] = "string" }; ["status"] { ["type"] = "string" }; ["type"] { ["description"] = "ConditionType represent a resource's status"; ["type"] = "string" } }; ["type"] = "object" }; ["type"] = "array" }; ["observedGeneration"] { ["description"] = "ObservedGeneration is the latest generation observed by the controller."; ["format"] = "int64"; ["type"] = "integer" }; ["phase"] { ["type"] = "string" } }; ["type"] = "object"; ["x-kubernetes-preserve-unknown-fields"] = true } }; ["required"] { "metadata"; "spec" }; ["type"] = "object" } }; ["served"] = true; ["storage"] = true; ["subresources"] { ["status"] {} } } } } }'
36 | if (result is ConversionFailure) throw(result.message) else result
^^^^^^^^^^^^^^^^^^^^^
at pkl.experimental.deepToTyped.deepToTyped#apply.<function#1> (https://github.com/apple/pkl-pantry/blob/[email protected]/packages/pkl.experimental.deepToTyped/deepToTyped.pkl#L36-36)
30 | let (result =
^^^^^^^^^^^^^
at pkl.experimental.deepToTyped.deepToTyped#apply (https://github.com/apple/pkl-pantry/blob/[email protected]/packages/pkl.experimental.deepToTyped/deepToTyped.pkl#L30-36)
105 | deepToTyped.apply(ModuleGenerator.CRD, crd) as ModuleGenerator.CRD
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
at k8s.contrib.crd.generate#crds.<function#1>[#1] (https://github.com/apple/pkl-pantry/blob/[email protected]/packages/k8s.contrib.crd/generate.pkl#L105-105)
101 | let (parser = new yaml.Parser { useMapping = true })
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
at k8s.contrib.crd.generate#crds (https://github.com/apple/pkl-pantry/blob/[email protected]/packages/k8s.contrib.crd/generate.pkl#L101-108)
128 | for (_crd in crds) {
^^^^
at k8s.contrib.crd.generate#modules (https://github.com/apple/pkl-pantry/blob/[email protected]/packages/k8s.contrib.crd/generate.pkl#L128-128)
142 | for (mod in modules) {
^^^^^^^
at k8s.contrib.crd.generate#output.files (https://github.com/apple/pkl-pantry/blob/[email protected]/packages/k8s.contrib.crd/generate.pkl#L142-142)
Manually parsing and then calling deep to typed on the offending CRD (but without the type union used by k8s.contrib.crd) lead to a slightly better error message:
–– Pkl Error ––
Unsupported type for conversion: Any
36 | if (result is ConversionFailure) throw(result.message) else result
^^^^^^^^^^^^^^^^^^^^^
at pkl.experimental.deepToTyped.deepToTyped#apply.<function#1> (projectpackage://pkg.pkl-lang.org/pkl-pantry/[email protected]#/deepToTyped.pkl)
30 | let (result =
^^^^^^^^^^^^^
at pkl.experimental.deepToTyped.deepToTyped#apply (projectpackage://pkg.pkl-lang.org/pkl-pantry/[email protected]#/deepToTyped.pkl)
11 | crd: CustomResourceDefinition = deepToTyped.apply(CRD, parsed)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
at test#crd (file:///home/joseph/dev/nix-pkl/test.pkl, line 11)
106 | text = renderer.renderDocument(value)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
at pkl.base#Module.output.text (https://github.com/apple/pkl/blob/0.25.2/stdlib/base.pkl#L106)
Which eventually lead me to the offending property, which is enum as defined here https://github.com/apple/pkl-k8s/blob/main/generated-package/apiextensions-apiserver/pkg/apis/apiextensions/v1/CustomResourceDefinition.pkl#L272 (there's also two other properties in there that use the type Any: default and example)
An example minimal CRD which reproduces the issue:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
spec:
group: foo.example.com
names:
kind: Foo
plural: foos
scope: Namespaced
versions:
- name: v1
schema:
openAPIV3Schema:
properties:
doesntwork:
enum:
- foo
type: string
type: object
served: true
storage: true
Metadata
Metadata
Assignees
Labels
No labels