Skip to content

Commit

Permalink
Merge pull request #5912 from crossplane/backport-5908-to-release-1.17
Browse files Browse the repository at this point in the history
[Backport release-1.17] fix: ensure x-kubernetes-preserve-unknown-fields is copied from xrd to crd spec
  • Loading branch information
phisco authored Aug 28, 2024
2 parents c22d0d8 + 6106784 commit 0e973c9
Show file tree
Hide file tree
Showing 2 changed files with 304 additions and 0 deletions.
1 change: 1 addition & 0 deletions internal/xcrd/crd.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ func genCrdVersion(vr v1.CompositeResourceDefinitionVersion, maxNameLength int64
xSpec := s.Properties["spec"]
cSpec := crdv.Schema.OpenAPIV3Schema.Properties["spec"]
cSpec.Required = append(cSpec.Required, xSpec.Required...)
cSpec.XPreserveUnknownFields = xSpec.XPreserveUnknownFields
cSpec.XValidations = append(cSpec.XValidations, xSpec.XValidations...)
cSpec.OneOf = append(cSpec.OneOf, xSpec.OneOf...)
cSpec.Description = xSpec.Description
Expand Down
303 changes: 303 additions & 0 deletions internal/xcrd/crd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1707,6 +1707,309 @@ func TestForCompositeResource(t *testing.T) {
c: nil,
},
},
"PreserveUnknownFieldsInSpec": {
reason: "A CRD should set PreserveUnknownFields based on the XRD PreserveUnknownFields.",
args: args{
v: &v1.CompositeResourceValidation{
OpenAPIV3Schema: runtime.RawExtension{Raw: []byte(strings.Replace(schema, `"spec": {`, `"spec": { "x-kubernetes-preserve-unknown-fields": true,`, 1))},
},
},
want: want{
c: &extv1.CustomResourceDefinition{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Labels: labels,
OwnerReferences: []metav1.OwnerReference{
meta.AsController(meta.TypedReferenceTo(d, v1.CompositeResourceDefinitionGroupVersionKind)),
},
},
Spec: extv1.CustomResourceDefinitionSpec{
Group: group,
Names: extv1.CustomResourceDefinitionNames{
Plural: plural,
Singular: singular,
Kind: kind,
ListKind: listKind,
Categories: []string{CategoryComposite},
},
Scope: extv1.ClusterScoped,
Versions: []extv1.CustomResourceDefinitionVersion{{
Name: version,
Served: true,
Storage: true,
Subresources: &extv1.CustomResourceSubresources{
Status: &extv1.CustomResourceSubresourceStatus{},
},
AdditionalPrinterColumns: []extv1.CustomResourceColumnDefinition{
{
Name: "SYNCED",
Type: "string",
JSONPath: ".status.conditions[?(@.type=='Synced')].status",
},
{
Name: "READY",
Type: "string",
JSONPath: ".status.conditions[?(@.type=='Ready')].status",
},
{
Name: "COMPOSITION",
Type: "string",
JSONPath: ".spec.compositionRef.name",
},
{
Name: "AGE",
Type: "date",
JSONPath: ".metadata.creationTimestamp",
},
},
Schema: &extv1.CustomResourceValidation{
OpenAPIV3Schema: &extv1.JSONSchemaProps{
Type: "object",
Description: "What the resource is for.",
Required: []string{"spec"},
Properties: map[string]extv1.JSONSchemaProps{
"apiVersion": {
Type: "string",
},
"kind": {
Type: "string",
},
"metadata": {
// NOTE(muvaf): api-server takes care of validating
// metadata.
Type: "object",
Properties: map[string]extv1.JSONSchemaProps{
"name": {
Type: "string",
MaxLength: ptr.To[int64](63),
},
},
},
"spec": {
Type: "object",
Required: []string{"storageGB", "engineVersion"},
Description: "Specification of the resource.",
XPreserveUnknownFields: ptr.To(true),
Properties: map[string]extv1.JSONSchemaProps{
// From CRDSpecTemplate.Validation
"storageGB": {Type: "integer", Description: "Pretend this is useful."},
"engineVersion": {
Type: "string",
Enum: []extv1.JSON{
{Raw: []byte(`"5.6"`)},
{Raw: []byte(`"5.7"`)},
},
},
"someField": {Type: "string", Description: "Pretend this is useful."},
"someOtherField": {Type: "string", Description: "Pretend this is useful."},

// From CompositeResourceSpecProps()
"compositionRef": {
Type: "object",
Required: []string{"name"},
Properties: map[string]extv1.JSONSchemaProps{
"name": {Type: "string"},
},
},
"compositionSelector": {
Type: "object",
Required: []string{"matchLabels"},
Properties: map[string]extv1.JSONSchemaProps{
"matchLabels": {
Type: "object",
AdditionalProperties: &extv1.JSONSchemaPropsOrBool{
Allows: true,
Schema: &extv1.JSONSchemaProps{Type: "string"},
},
},
},
},
"compositionRevisionRef": {
Type: "object",
Required: []string{"name"},
Properties: map[string]extv1.JSONSchemaProps{
"name": {Type: "string"},
},
},
"compositionRevisionSelector": {
Type: "object",
Required: []string{"matchLabels"},
Properties: map[string]extv1.JSONSchemaProps{
"matchLabels": {
Type: "object",
AdditionalProperties: &extv1.JSONSchemaPropsOrBool{
Allows: true,
Schema: &extv1.JSONSchemaProps{Type: "string"},
},
},
},
},
"compositionUpdatePolicy": {
Type: "string",
Enum: []extv1.JSON{
{Raw: []byte(`"Automatic"`)},
{Raw: []byte(`"Manual"`)},
},
},
"claimRef": {
Type: "object",
Required: []string{"apiVersion", "kind", "namespace", "name"},
Properties: map[string]extv1.JSONSchemaProps{
"apiVersion": {Type: "string"},
"kind": {Type: "string"},
"namespace": {Type: "string"},
"name": {Type: "string"},
},
},
"environmentConfigRefs": {
Type: "array",
Items: &extv1.JSONSchemaPropsOrArray{
Schema: &extv1.JSONSchemaProps{
Type: "object",
Properties: map[string]extv1.JSONSchemaProps{
"apiVersion": {Type: "string"},
"name": {Type: "string"},
"kind": {Type: "string"},
},
Required: []string{"apiVersion", "kind"},
},
},
},
"resourceRefs": {
Type: "array",
Items: &extv1.JSONSchemaPropsOrArray{
Schema: &extv1.JSONSchemaProps{
Type: "object",
Properties: map[string]extv1.JSONSchemaProps{
"apiVersion": {Type: "string"},
"name": {Type: "string"},
"kind": {Type: "string"},
},
Required: []string{"apiVersion", "kind"},
},
},
XListType: ptr.To("atomic"),
},
"publishConnectionDetailsTo": {
Type: "object",
Required: []string{"name"},
Properties: map[string]extv1.JSONSchemaProps{
"name": {Type: "string"},
"configRef": {
Type: "object",
Default: &extv1.JSON{Raw: []byte(`{"name": "default"}`)},
Properties: map[string]extv1.JSONSchemaProps{
"name": {
Type: "string",
},
},
},
"metadata": {
Type: "object",
Properties: map[string]extv1.JSONSchemaProps{
"labels": {
Type: "object",
AdditionalProperties: &extv1.JSONSchemaPropsOrBool{
Allows: true,
Schema: &extv1.JSONSchemaProps{Type: "string"},
},
},
"annotations": {
Type: "object",
AdditionalProperties: &extv1.JSONSchemaPropsOrBool{
Allows: true,
Schema: &extv1.JSONSchemaProps{Type: "string"},
},
},
"type": {
Type: "string",
},
},
},
},
},
"writeConnectionSecretToRef": {
Type: "object",
Required: []string{"name", "namespace"},
Properties: map[string]extv1.JSONSchemaProps{
"name": {Type: "string"},
"namespace": {Type: "string"},
},
},
},
XValidations: extv1.ValidationRules{
{
Message: "Cannot change engine version",
Rule: "self.engineVersion == oldSelf.engineVersion",
},
},
OneOf: []extv1.JSONSchemaProps{
{Required: []string{"someField"}},
{Required: []string{"someOtherField"}},
},
},
"status": {
Type: "object",
Description: "Status of the resource.",
Properties: map[string]extv1.JSONSchemaProps{
"phase": {Type: "string"},
"something": {Type: "string"},

// From CompositeResourceStatusProps()
"conditions": {
Description: "Conditions of the resource.",
Type: "array",
XListType: ptr.To("map"),
XListMapKeys: []string{"type"},
Items: &extv1.JSONSchemaPropsOrArray{
Schema: &extv1.JSONSchemaProps{
Type: "object",
Required: []string{"lastTransitionTime", "reason", "status", "type"},
Properties: map[string]extv1.JSONSchemaProps{
"lastTransitionTime": {Type: "string", Format: "date-time"},
"message": {Type: "string"},
"reason": {Type: "string"},
"status": {Type: "string"},
"type": {Type: "string"},
},
},
},
},
"claimConditionTypes": {
Type: "array",
XListType: ptr.To("set"),
Items: &extv1.JSONSchemaPropsOrArray{
Schema: &extv1.JSONSchemaProps{
Type: "string",
},
},
},
"connectionDetails": {
Type: "object",
Properties: map[string]extv1.JSONSchemaProps{
"lastPublishedTime": {Type: "string", Format: "date-time"},
},
},
},
XValidations: extv1.ValidationRules{
{
Message: "Phase is required once set",
Rule: "!has(oldSelf.phase) || has(self.phase)",
},
},
OneOf: []extv1.JSONSchemaProps{
{Required: []string{"phase"}},
{Required: []string{"something"}},
},
},
},
},
},
}},
},
},
},
},
}

for name, tc := range cases {
Expand Down

0 comments on commit 0e973c9

Please sign in to comment.