Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Support api-approved annotation for CRD with k8s group #691

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
40 changes: 40 additions & 0 deletions pkg/crd/markers/crd.go
Expand Up @@ -18,6 +18,7 @@ package markers

import (
"fmt"
"strings"

apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"

Expand Down Expand Up @@ -51,6 +52,9 @@ var CRDMarkers = []*definitionWithHelp{

must(markers.MakeDefinition("kubebuilder:deprecatedversion", markers.DescribesType, DeprecatedVersion{})).
WithHelp(DeprecatedVersion{}.Help()),

must(markers.MakeDefinition("kubebuilder:metadata", markers.DescribesType, Metadata{})).
WithHelp(Metadata{}.Help()),
}

// TODO: categories and singular used to be annotations types
Expand Down Expand Up @@ -345,3 +349,39 @@ func (s DeprecatedVersion) ApplyToCRD(crd *apiext.CustomResourceDefinitionSpec,
}
return nil
}

// +controllertools:marker:generateHelp:category=CRD

// Metadata configures the additional annotations or labels for this CRD.
// For example adding annotation "api-approved.kubernetes.io" for a CRD with Kubernetes groups,
// or annotation "cert-manager.io/inject-ca-from-secret" for a CRD that needs CA injection.
type Metadata struct {
// Annotations will be added into the annotations of this CRD.
Annotations []string `marker:",optional"`
// Labels will be added into the labels of this CRD.
Labels []string `marker:",optional"`
}

func (s Metadata) ApplyToCRD(crd *apiext.CustomResourceDefinition, version string) error {
if len(s.Annotations) > 0 {
if crd.Annotations == nil {
crd.Annotations = map[string]string{}
}
for _, str := range s.Annotations {
kv := strings.SplitN(str, "=", 2)
crd.Annotations[kv[0]] = kv[1]
}
}

if len(s.Labels) > 0 {
if crd.Labels == nil {
crd.Labels = map[string]string{}
}
for _, str := range s.Labels {
kv := strings.SplitN(str, "=", 2)
crd.Labels[kv[0]] = kv[1]
}
}

return nil
}
20 changes: 20 additions & 0 deletions pkg/crd/markers/zz_generated.markerhelp.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions pkg/crd/parser_integration_test.go
Expand Up @@ -122,8 +122,11 @@ var _ = Describe("CRD Generation From Parsing to CustomResourceDefinition", func
By(fmt.Sprintf("parsing the desired %s YAML", kind))
var crd apiext.CustomResourceDefinition
ExpectWithOffset(1, yaml.Unmarshal(expectedFile, &crd)).To(Succeed())
// clear the annotations -- we don't care about the attribution annotation
crd.Annotations = nil
// clear the version annotation -- we don't care about the attribution annotation
delete(crd.Annotations, "controller-gen.kubebuilder.io/version")
if len(crd.Annotations) == 0 {
crd.Annotations = nil
}

By(fmt.Sprintf("comparing the two %s CRDs", kind))
ExpectWithOffset(1, parser.CustomResourceDefinitions[groupKind]).To(Equal(crd), "type not as expected, check pkg/crd/testdata/README.md for more details.\n\nDiff:\n\n%s", cmp.Diff(parser.CustomResourceDefinitions[groupKind], crd))
Expand Down
24 changes: 17 additions & 7 deletions pkg/crd/spec.go
Expand Up @@ -30,13 +30,21 @@ import (
)

// SpecMarker is a marker that knows how to apply itself to a particular
// version in a CRD.
// version in a CRD Spec.
type SpecMarker interface {
// ApplyToCRD applies this marker to the given CRD, in the given version
// within that CRD. It's called after everything else in the CRD is populated.
ApplyToCRD(crd *apiext.CustomResourceDefinitionSpec, version string) error
}

// Marker is a marker that knows how to apply itself to a particular
// version in a CRD.
type Marker interface {
// ApplyToCRD applies this marker to the given CRD, in the given version
// within that CRD. It's called after everything else in the CRD is populated.
ApplyToCRD(crd *apiext.CustomResourceDefinition, version string) error
}

// NeedCRDFor requests the full CRD for the given group-kind. It requires
// that the packages containing the Go structs for that CRD have already
// been loaded with NeedPackage.
Expand Down Expand Up @@ -109,12 +117,14 @@ func (p *Parser) NeedCRDFor(groupKind schema.GroupKind, maxDescLen *int) {

for _, markerVals := range typeInfo.Markers {
for _, val := range markerVals {
crdMarker, isCrdMarker := val.(SpecMarker)
if !isCrdMarker {
continue
}
if err := crdMarker.ApplyToCRD(&crd.Spec, ver); err != nil {
pkg.AddError(loader.ErrFromNode(err /* an okay guess */, typeInfo.RawSpec))
if specMarker, isSpecMarker := val.(SpecMarker); isSpecMarker {
if err := specMarker.ApplyToCRD(&crd.Spec, ver); err != nil {
pkg.AddError(loader.ErrFromNode(err /* an okay guess */, typeInfo.RawSpec))
}
} else if crdMarker, isCRDMarker := val.(Marker); isCRDMarker {
if err := crdMarker.ApplyToCRD(&crd, ver); err != nil {
pkg.AddError(loader.ErrFromNode(err /* an okay guess */, typeInfo.RawSpec))
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions pkg/crd/testdata/cronjob_types.go
Expand Up @@ -499,6 +499,7 @@ type CronJobStatus struct {
// +kubebuilder:subresource:status
// +kubebuilder:resource:singular=mycronjob
// +kubebuilder:storageversion
// +kubebuilder:metadata:annotations="api-approved.kubernetes.io=https://github.com/kubernetes-sigs/controller-tools";"cert-manager.io/inject-ca-from-secret=cert-manager/cert-manager-webhook-ca"

// CronJob is the Schema for the cronjobs API
type CronJob struct {
Expand Down
2 changes: 2 additions & 0 deletions pkg/crd/testdata/testdata.kubebuilder.io_cronjobs.yaml
Expand Up @@ -4,6 +4,8 @@ kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: (devel)
api-approved.kubernetes.io: https://github.com/kubernetes-sigs/controller-tools
cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca
creationTimestamp: null
name: cronjobs.testdata.kubebuilder.io
spec:
Expand Down