Skip to content

Commit

Permalink
fix: Pass description fields in XRDs into CRDs
Browse files Browse the repository at this point in the history
Signed-off-by: Matt Bush <mbbush@gmail.com>
  • Loading branch information
mbbush committed Jul 28, 2023
1 parent 9f5384a commit 4344780
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 134 deletions.
147 changes: 60 additions & 87 deletions internal/xcrd/crd.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const (
)

const (
errFmtGetProps = "cannot get %q properties from validation schema"
errFmtGenCrd = "cannot generate CRD for %q %q"
errParseValidation = "cannot parse validation schema"
errInvalidClaimNames = "invalid resource claim names"
errMissingClaimNames = "missing names"
Expand Down Expand Up @@ -71,48 +71,15 @@ func ForCompositeResource(xrd *v1.CompositeResourceDefinition) (*extv1.CustomRes
crd.Spec.Names.Categories = append(crd.Spec.Names.Categories, CategoryComposite)

for i, vr := range xrd.Spec.Versions {
crd.Spec.Versions[i] = extv1.CustomResourceDefinitionVersion{
Name: vr.Name,
Served: vr.Served,
Storage: vr.Referenceable,
Deprecated: pointer.BoolDeref(vr.Deprecated, false),
DeprecationWarning: vr.DeprecationWarning,
AdditionalPrinterColumns: append(vr.AdditionalPrinterColumns, CompositeResourcePrinterColumns()...),
Schema: &extv1.CustomResourceValidation{
OpenAPIV3Schema: BaseProps(),
},
Subresources: &extv1.CustomResourceSubresources{
Status: &extv1.CustomResourceSubresourceStatus{},
},
}

p, required, err := getProps("spec", vr.Schema)
crdv, err := genCrdVersion(vr)
if err != nil {
return nil, errors.Wrapf(err, errFmtGetProps, "spec")
}
specProps := crd.Spec.Versions[i].Schema.OpenAPIV3Schema.Properties["spec"]
specProps.Required = append(specProps.Required, required...)
for k, v := range p {
specProps.Properties[k] = v
return nil, errors.Wrapf(err, errFmtGenCrd, "Composite Resource", xrd.Name)
}
crdv.AdditionalPrinterColumns = append(crdv.AdditionalPrinterColumns, CompositeResourcePrinterColumns()...)
for k, v := range CompositeResourceSpecProps() {
specProps.Properties[k] = v
}
crd.Spec.Versions[i].Schema.OpenAPIV3Schema.Properties["spec"] = specProps

statusP, statusRequired, err := getProps("status", vr.Schema)
if err != nil {
return nil, errors.Wrapf(err, errFmtGetProps, "status")
}
statusProps := crd.Spec.Versions[i].Schema.OpenAPIV3Schema.Properties["status"]
statusProps.Required = statusRequired
for k, v := range statusP {
statusProps.Properties[k] = v
}
for k, v := range CompositeResourceStatusProps() {
statusProps.Properties[k] = v
crdv.Schema.OpenAPIV3Schema.Properties["spec"].Properties[k] = v
}
crd.Spec.Versions[i].Schema.OpenAPIV3Schema.Properties["status"] = statusProps
crd.Spec.Versions[i] = *crdv
}

return crd, nil
Expand Down Expand Up @@ -144,53 +111,65 @@ func ForCompositeResourceClaim(xrd *v1.CompositeResourceDefinition) (*extv1.Cust
crd.Spec.Names.Categories = append(crd.Spec.Names.Categories, CategoryClaim)

for i, vr := range xrd.Spec.Versions {
crd.Spec.Versions[i] = extv1.CustomResourceDefinitionVersion{
Name: vr.Name,
Served: vr.Served,
Storage: vr.Referenceable,
Deprecated: pointer.BoolDeref(vr.Deprecated, false),
DeprecationWarning: vr.DeprecationWarning,
AdditionalPrinterColumns: append(vr.AdditionalPrinterColumns, CompositeResourceClaimPrinterColumns()...),
Schema: &extv1.CustomResourceValidation{
OpenAPIV3Schema: BaseProps(),
},
Subresources: &extv1.CustomResourceSubresources{
Status: &extv1.CustomResourceSubresourceStatus{},
},
}

p, required, err := getProps("spec", vr.Schema)
crdv, err := genCrdVersion(vr)
if err != nil {
return nil, errors.Wrapf(err, errFmtGetProps, "spec")
}
specProps := crd.Spec.Versions[i].Schema.OpenAPIV3Schema.Properties["spec"]
specProps.Required = append(specProps.Required, required...)
for k, v := range p {
specProps.Properties[k] = v
return nil, errors.Wrapf(err, errFmtGenCrd, "Composite Resource Claim", xrd.Name)
}
crdv.AdditionalPrinterColumns = append(crdv.AdditionalPrinterColumns, CompositeResourceClaimPrinterColumns()...)
for k, v := range CompositeResourceClaimSpecProps() {
specProps.Properties[k] = v
}
crd.Spec.Versions[i].Schema.OpenAPIV3Schema.Properties["spec"] = specProps

statusP, statusRequired, err := getProps("status", vr.Schema)
if err != nil {
return nil, errors.Wrapf(err, errFmtGetProps, "status")
}
statusProps := crd.Spec.Versions[i].Schema.OpenAPIV3Schema.Properties["status"]
statusProps.Required = statusRequired
for k, v := range statusP {
statusProps.Properties[k] = v
crdv.Schema.OpenAPIV3Schema.Properties["spec"].Properties[k] = v
}
for k, v := range CompositeResourceStatusProps() {
statusProps.Properties[k] = v
}
crd.Spec.Versions[i].Schema.OpenAPIV3Schema.Properties["status"] = statusProps
crd.Spec.Versions[i] = *crdv
}

return crd, nil
}

func genCrdVersion(vr v1.CompositeResourceDefinitionVersion) (*extv1.CustomResourceDefinitionVersion, error) {
crdv := extv1.CustomResourceDefinitionVersion{
Name: vr.Name,
Served: vr.Served,
Storage: vr.Referenceable,
Deprecated: pointer.BoolDeref(vr.Deprecated, false),
DeprecationWarning: vr.DeprecationWarning,
AdditionalPrinterColumns: vr.AdditionalPrinterColumns,
Schema: &extv1.CustomResourceValidation{
OpenAPIV3Schema: BaseProps(),
},
Subresources: &extv1.CustomResourceSubresources{
Status: &extv1.CustomResourceSubresourceStatus{},
},
}
s, err := parseSchema(vr.Schema)
if err != nil {
return nil, errors.Wrapf(err, errParseValidation)
}
crdv.Schema.OpenAPIV3Schema.Description = s.Description

xSpec := s.Properties["spec"]
cSpec := crdv.Schema.OpenAPIV3Schema.Properties["spec"]
cSpec.Required = append(cSpec.Required, xSpec.Required...)

cSpec.Description = xSpec.Description
for k, v := range xSpec.Properties {
cSpec.Properties[k] = v
}
crdv.Schema.OpenAPIV3Schema.Properties["spec"] = cSpec

xStatus := s.Properties["status"]
cStatus := crdv.Schema.OpenAPIV3Schema.Properties["status"]
cStatus.Required = xStatus.Required
cStatus.Description = xStatus.Description
for k, v := range xStatus.Properties {
cStatus.Properties[k] = v
}
for k, v := range CompositeResourceStatusProps() {
cStatus.Properties[k] = v
}
crdv.Schema.OpenAPIV3Schema.Properties["status"] = cStatus
return &crdv, nil
}

func validateClaimNames(d *v1.CompositeResourceDefinition) error {
if d.Spec.ClaimNames == nil {
return errors.New(errMissingClaimNames)
Expand All @@ -215,22 +194,16 @@ func validateClaimNames(d *v1.CompositeResourceDefinition) error {
return nil
}

func getProps(field string, v *v1.CompositeResourceValidation) (map[string]extv1.JSONSchemaProps, []string, error) {
func parseSchema(v *v1.CompositeResourceValidation) (*extv1.JSONSchemaProps, error) {
if v == nil {
return nil, nil, nil
return nil, nil
}

s := &extv1.JSONSchemaProps{}
if err := json.Unmarshal(v.OpenAPIV3Schema.Raw, s); err != nil {
return nil, nil, errors.Wrap(err, errParseValidation)
return nil, errors.Wrap(err, errParseValidation)
}

spec, ok := s.Properties[field]
if !ok {
return nil, nil, nil
}

return spec.Properties, spec.Required, nil
return s, nil
}

// setCrdMetadata sets the labels and annotations on the CRD.
Expand Down
94 changes: 47 additions & 47 deletions internal/xcrd/crd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,43 +82,43 @@ func TestForCompositeResource(t *testing.T) {

schema := `
{
"required": [
"spec"
],
"properties": {
"spec": {
"description": "Specification of the resource.",
"required": [
"storageGB",
"engineVersion"
],
"properties": {
"engineVersion": {
"enum": [
"5.6",
"5.7"
],
"type": "string"
},
"storageGB": {
"type": "integer",
"description": "Pretend this is useful."
}
},
"type": "object"
},
"status": {
"properties": {
"phase": {
"type": "string"
}
},
"type": "object",
"description": "Status of the resource."
}
},
"type": "object",
"description": "What the resource is for."
"required": [
"spec"
],
"properties": {
"spec": {
"description": "Specification of the resource.",
"required": [
"storageGB",
"engineVersion"
],
"properties": {
"engineVersion": {
"enum": [
"5.6",
"5.7"
],
"type": "string"
},
"storageGB": {
"type": "integer",
"description": "Pretend this is useful."
}
},
"type": "object"
},
"status": {
"properties": {
"phase": {
"type": "string"
}
},
"type": "object",
"description": "Status of the resource."
}
},
"type": "object",
"description": "What the resource is for."
}`

d := &v1.CompositeResourceDefinition{
Expand Down Expand Up @@ -196,9 +196,9 @@ func TestForCompositeResource(t *testing.T) {
},
Schema: &extv1.CustomResourceValidation{
OpenAPIV3Schema: &extv1.JSONSchemaProps{
Type: "object",
Type: "object",
Description: "What the resource is for.",
Required: []string{"spec"},
Required: []string{"spec"},
Properties: map[string]extv1.JSONSchemaProps{
"apiVersion": {
Type: "string",
Expand All @@ -212,8 +212,8 @@ func TestForCompositeResource(t *testing.T) {
Type: "object",
},
"spec": {
Type: "object",
Required: []string{"storageGB", "engineVersion"},
Type: "object",
Required: []string{"storageGB", "engineVersion"},
Description: "Specification of the resource.",
Properties: map[string]extv1.JSONSchemaProps{
// From CRDSpecTemplate.Validation
Expand Down Expand Up @@ -361,7 +361,7 @@ func TestForCompositeResource(t *testing.T) {
},
},
"status": {
Type: "object",
Type: "object",
Description: "Status of the resource.",
Properties: map[string]extv1.JSONSchemaProps{
"phase": {Type: "string"},
Expand Down Expand Up @@ -935,8 +935,8 @@ func TestForCompositeResourceClaim(t *testing.T) {
},
Schema: &extv1.CustomResourceValidation{
OpenAPIV3Schema: &extv1.JSONSchemaProps{
Type: "object",
Required: []string{"spec"},
Type: "object",
Required: []string{"spec"},
Description: "Description of the resource.",
Properties: map[string]extv1.JSONSchemaProps{
"apiVersion": {
Expand All @@ -951,8 +951,8 @@ func TestForCompositeResourceClaim(t *testing.T) {
Type: "object",
},
"spec": {
Type: "object",
Required: []string{"storageGB", "engineVersion"},
Type: "object",
Required: []string{"storageGB", "engineVersion"},
Description: "Specification of the resource.",
Properties: map[string]extv1.JSONSchemaProps{
// From CRDSpecTemplate.Validation
Expand Down Expand Up @@ -1074,7 +1074,7 @@ func TestForCompositeResourceClaim(t *testing.T) {
},
},
"status": {
Type: "object",
Type: "object",
Description: "Status of the resource.",
Properties: map[string]extv1.JSONSchemaProps{
"phase": {Type: "string"},
Expand Down

0 comments on commit 4344780

Please sign in to comment.