From 407decd638d928528c007a9334eb3f8562e5b1a8 Mon Sep 17 00:00:00 2001 From: Dmitri Dolguikh Date: Fri, 14 Jul 2023 20:24:12 -0700 Subject: [PATCH 01/27] Support for enabling/disabling of alpha-level CRDs Signed-off-by: Dmitri Dolguikh --- codegen/cmd.go | 48 +++++---- codegen/kuberesource/crd.go | 96 +++++++++-------- codegen/render/manifests_renderer.go | 127 ++++++++++++++++------- codegen/templates/manifests/crd.yamltmpl | 30 ++++++ 4 files changed, 199 insertions(+), 102 deletions(-) create mode 100644 codegen/templates/manifests/crd.yamltmpl diff --git a/codegen/cmd.go b/codegen/cmd.go index e9251af4a..4dcf83970 100644 --- a/codegen/cmd.go +++ b/codegen/cmd.go @@ -146,14 +146,16 @@ func (c Command) Execute() error { group := group // pike groups = append(groups, &group) } - for i, group := range groups { + for _, group := range groups { group := group // pike c.initGroup(group, descriptors) + } - if err := c.generateGroup(*group, protoOpts, c.GroupOptions); err != nil { - return err - } + if err := c.generateGroup(groups, protoOpts, c.GroupOptions); err != nil { + return err + } + for i, group := range groups { // replace group in Groups array with the group including generated fields c.Groups[i] = *group } @@ -240,7 +242,7 @@ func (c Command) renderProtos() ([]*collector.DescriptorWithPath, error) { } func (c Command) generateGroup( - grp model.Group, + grps []*model.Group, protoOpts proto.Options, groupOptions model.GroupOptions, ) error { @@ -250,25 +252,27 @@ func (c Command) generateGroup( Header: c.GeneratedHeader, } - protoTypes, err := render.RenderProtoTypes(grp) - if err != nil { - return err - } + for _, grp := range grps { + protoTypes, err := render.RenderProtoTypes(*grp) + if err != nil { + return err + } - if err := fileWriter.WriteFiles(protoTypes); err != nil { - return err - } + if err := fileWriter.WriteFiles(protoTypes); err != nil { + return err + } - apiTypes, err := render.RenderApiTypes(grp) - if err != nil { - return err - } + apiTypes, err := render.RenderApiTypes(*grp) + if err != nil { + return err + } - if err := fileWriter.WriteFiles(apiTypes); err != nil { - return err + if err := fileWriter.WriteFiles(apiTypes); err != nil { + return err + } } - manifests, err := render.RenderManifests(c.AppName, c.ManifestRoot, c.ProtoDir, protoOpts, groupOptions, grp) + manifests, err := render.RenderManifests(c.AppName, c.ManifestRoot, c.ProtoDir, protoOpts, groupOptions, grps) if err != nil { return err } @@ -277,8 +281,10 @@ func (c Command) generateGroup( return err } - if err := render.KubeCodegen(grp); err != nil { - return err + for _, grp := range grps { + if err := render.KubeCodegen(*grp); err != nil { + return err + } } return nil diff --git a/codegen/kuberesource/crd.go b/codegen/kuberesource/crd.go index 02148c62d..04b9231bb 100644 --- a/codegen/kuberesource/crd.go +++ b/codegen/kuberesource/crd.go @@ -18,21 +18,33 @@ import ( // Create CRDs for a group func CustomResourceDefinitions( - group model.Group, -) (objects []metav1.Object, err error) { - for _, resource := range group.Resources { - - var validationSchema *apiextv1.CustomResourceValidation - validationSchema, err = constructValidationSchema( - group.RenderValidationSchemas, - resource, - group.OpenApiSchemas, - ) - if err != nil { - return nil, err + groups []*model.Group, +) (objects []apiextv1.CustomResourceDefinition, err error) { + resourcesByKind := make(map[string][]model.Resource) + for _, group := range groups { + for _, resource := range group.Resources { + resourcesByKind[resource.Kind] = append(resourcesByKind[resource.Kind], resource) + } + } + + //objects = make([]apiextv1.CustomResourceDefinition, 0, len(resourcesByKind)) + for _, resources := range resourcesByKind { + validationSchemas := make(map[string]*apiextv1.CustomResourceValidation) + for _, resource := range resources { + var validationSchema *apiextv1.CustomResourceValidation + validationSchema, err = constructValidationSchema( + resource.Group.RenderValidationSchemas, + resource, + resource.Group.OpenApiSchemas, + ) + if err != nil { + return nil, err + } + + validationSchemas[resource.Group.String()] = validationSchema } - objects = append(objects, CustomResourceDefinition(resource, validationSchema, group.SkipSpecHash)) + objects = append(objects, *CustomResourceDefinition(resources, validationSchemas, true)) //group.SkipSpecHash)) } return objects, nil } @@ -117,27 +129,40 @@ func validateStructural(s *apiextv1.JSONSchemaProps) error { } func CustomResourceDefinition( - resource model.Resource, - validationSchema *apiextv1.CustomResourceValidation, + resources []model.Resource, + validationSchemas map[string]*apiextv1.CustomResourceValidation, withoutSpecHash bool, ) *apiextv1.CustomResourceDefinition { - group := resource.Group.Group - version := resource.Group.Version - kind := resource.Kind + group := resources[0].Group.Group + kind := resources[0].Kind kindLowerPlural := strings.ToLower(stringutils.Pluralize(kind)) kindLower := strings.ToLower(kind) - var status *apiextv1.CustomResourceSubresourceStatus - if resource.Status != nil { - status = &apiextv1.CustomResourceSubresourceStatus{} - } - scope := apiextv1.NamespaceScoped - if resource.ClusterScoped { + if resources[0].ClusterScoped { scope = apiextv1.ClusterScoped } + versions := make([]apiextv1.CustomResourceDefinitionVersion, 0, len(resources)) + for _, resource := range resources { + var status *apiextv1.CustomResourceSubresourceStatus + if resource.Status != nil { + status = &apiextv1.CustomResourceSubresourceStatus{} + } + + v := apiextv1.CustomResourceDefinitionVersion{ + Name: resource.Group.Version, + Served: true, + Storage: true, + AdditionalPrinterColumns: resource.AdditionalPrinterColumns, + Subresources: &apiextv1.CustomResourceSubresources{ + Status: status, + }, + Schema: validationSchemas[resource.Group.String()], + } + versions = append(versions, v) + } crd := &apiextv1.CustomResourceDefinition{ TypeMeta: metav1.TypeMeta{ APIVersion: apiextv1.SchemeGroupVersion.String(), @@ -147,27 +172,16 @@ func CustomResourceDefinition( Name: fmt.Sprintf("%s.%s", kindLowerPlural, group), }, Spec: apiextv1.CustomResourceDefinitionSpec{ - Group: group, - Scope: scope, - Versions: []apiextv1.CustomResourceDefinitionVersion{ - { - Name: version, - Served: true, - Storage: true, - AdditionalPrinterColumns: resource.AdditionalPrinterColumns, - Subresources: &apiextv1.CustomResourceSubresources{ - Status: status, - }, - Schema: validationSchema, - }, - }, + Group: group, + Scope: scope, + Versions: versions, Names: apiextv1.CustomResourceDefinitionNames{ Plural: kindLowerPlural, Singular: kindLower, Kind: kind, - ShortNames: resource.ShortNames, + ShortNames: resources[0].ShortNames, ListKind: kind + "List", - Categories: resource.Categories, + Categories: resources[0].Categories, }, }, } @@ -182,7 +196,7 @@ func CustomResourceDefinition( } } - if validationSchema != nil { + if len(validationSchemas) > 0 { // Setting PreserveUnknownFields to false ensures that objects with unknown fields are rejected. crd.Spec.PreserveUnknownFields = false } diff --git a/codegen/render/manifests_renderer.go b/codegen/render/manifests_renderer.go index 6b1e6a47c..a5092dce2 100644 --- a/codegen/render/manifests_renderer.go +++ b/codegen/render/manifests_renderer.go @@ -26,10 +26,11 @@ import ( // creates a k8s resource for a group // this gets turned into a k8s manifest file -type MakeResourceFunc func(group Group) ([]metav1.Object, error) +type MakeResourceFunc func(groups []*Group) ([]metav1.Object, error) // renders kubernetes from templates type ManifestsRenderer struct { + templateRenderer AppName string // used for labeling ResourceFuncs map[OutFile]MakeResourceFunc ManifestDir string @@ -40,46 +41,57 @@ func RenderManifests( appName, manifestDir, protoDir string, protoOpts protoutil.Options, groupOptions model.GroupOptions, - grp Group, + grps []*Group, ) ([]OutFile, error) { defaultManifestsRenderer := ManifestsRenderer{ AppName: appName, ManifestDir: manifestDir, ProtoDir: protoDir, - ResourceFuncs: map[OutFile]MakeResourceFunc{ - { - Path: manifestDir + "/crds/" + grp.Group + "_" + grp.Version + "_" + "crds.yaml", - }: func(group Group) ([]metav1.Object, error) { - return kuberesource.CustomResourceDefinitions(group) - }, - }, - } - return defaultManifestsRenderer.RenderManifests(grp, protoOpts, groupOptions) + } + return defaultManifestsRenderer.RenderManifests(grps, protoOpts, groupOptions) } -func (r ManifestsRenderer) RenderManifests(grp Group, protoOpts protoutil.Options, groupOptions model.GroupOptions) ([]OutFile, error) { - if !grp.RenderManifests { - return nil, nil +func (r ManifestsRenderer) RenderManifests(grps []*Group, protoOpts protoutil.Options, groupOptions model.GroupOptions) ([]OutFile, error) { + // if !grp.RenderManifests { + // return nil, nil + // } + + for _, grp := range grps { + if grp.RenderValidationSchemas { + var err error + oapiSchemas, err := generateOpenApi(*grp, r.ProtoDir, protoOpts, groupOptions) + if err != nil { + return nil, err + } + grp.OpenApiSchemas = oapiSchemas + } + } + + grpsByG := make(map[string][]*Group) + for _, grp := range grps { + grpsByG[grp.Group] = append(grpsByG[grp.Group], grp) } - if grp.RenderValidationSchemas { - var err error - oapiSchemas, err := generateOpenApi(grp, r.ProtoDir, protoOpts, groupOptions) + var renderedFiles []OutFile + + for _, selectedGrps := range grpsByG { + crds, err := r.createCrds(r.AppName, selectedGrps) if err != nil { return nil, err } - grp.OpenApiSchemas = oapiSchemas - } + out, err := r.renderManifest(r.AppName, selectedGrps[0].Group, crds) + if err != nil { + return nil, err + } + renderedFiles = append(renderedFiles, out) - var renderedFiles []OutFile - for out, mkFunc := range r.ResourceFuncs { - content, err := r.renderManifest(r.AppName, mkFunc, grp) + out, err = r.renderTemplatedManifest(r.AppName, selectedGrps[0].Group, crds) if err != nil { return nil, err } - out.Content = content renderedFiles = append(renderedFiles, out) } + return renderedFiles, nil } @@ -198,7 +210,7 @@ func getUnstructuredFieldsMap(grp model.Group, opts protoutil.Options) (map[stri return unstructuredFields, nil } -func SetVersionForObject(obj metav1.Object, version string) { +func SetVersionForObject(obj *apiextv1.CustomResourceDefinition, version string) { if version == "" { return } @@ -218,41 +230,76 @@ func SetVersionForObject(obj metav1.Object, version string) { } a[crdutils.CRDVersionKey] = strippedVersion.String() + obj.SetAnnotations(a) } } -func (r ManifestsRenderer) renderManifest(appName string, mk MakeResourceFunc, group Group) (string, error) { - objs, err := mk(group) - if err != nil { - return "", err +func (r ManifestsRenderer) renderManifest(appName, groupName string, objs []apiextv1.CustomResourceDefinition) (OutFile, error) { + outFile := OutFile{ + Path: r.ManifestDir + "/crds/" + groupName + "_" + "crds.yaml", } var objManifests []string for _, obj := range objs { - // find the annotation of the manifest, and add to them - SetVersionForObject(obj, group.AddChartVersion) - manifest, err := marshalObjToYaml(appName, obj) + manifest, err := marshalObjToYaml(appName, &obj) if err != nil { - return "", err + return OutFile{}, err } objManifests = append(objManifests, manifest) } - return strings.Join(objManifests, "\n---\n"), nil + outFile.Content = strings.Join(objManifests, "\n---\n") + return outFile, nil } -func marshalObjToYaml(appName string, obj metav1.Object) (string, error) { - labels := obj.GetLabels() - if labels == nil { - labels = map[string]string{} +func (r ManifestsRenderer) renderTemplatedManifest(appName, groupName string, objs []apiextv1.CustomResourceDefinition) (OutFile, error) { + renderer := DefaultTemplateRenderer + + // when rendering helm charts, we need + // to use a custom delimiter + renderer.left = "[[" + renderer.right = "]]" + + defaultManifestRenderer := ChartRenderer{ + templateRenderer: renderer, + } + + outFile := OutFile{Path: r.ManifestDir + "/templates/" + groupName + "_" + "crds.yaml"} + templatesToRender := inputTemplates{ + "manifests/crd.yamltmpl": outFile, + } + files, err := defaultManifestRenderer.renderCoreTemplates(templatesToRender, objs) + if err != nil { + return OutFile{}, err + } + return files[0], nil +} + +func (r ManifestsRenderer) createCrds(appName string, groups []*Group) ([]apiextv1.CustomResourceDefinition, error) { + objs, err := kuberesource.CustomResourceDefinitions(groups) + if err != nil { + return nil, err } - labels["app"] = appName - labels["app.kubernetes.io/name"] = appName + for i, obj := range objs { + // find the annotation of the manifest, and add to them + SetVersionForObject(&objs[i], groups[0].AddChartVersion) + + labels := obj.GetLabels() + if labels == nil { + labels = map[string]string{} + } - obj.SetLabels(labels) + labels["app"] = appName + labels["app.kubernetes.io/name"] = appName + objs[i].SetLabels(labels) + } + return objs, nil +} + +func marshalObjToYaml(appName string, obj metav1.Object) (string, error) { yam, err := yaml.Marshal(obj) if err != nil { return "", err diff --git a/codegen/templates/manifests/crd.yamltmpl b/codegen/templates/manifests/crd.yamltmpl new file mode 100644 index 000000000..4855791f4 --- /dev/null +++ b/codegen/templates/manifests/crd.yamltmpl @@ -0,0 +1,30 @@ +[[- range $crd := . -]] +[[- if and (lt (len $crd.Spec.Versions) 2) (string_contains (index $crd.Spec.Versions 0).Name "alpha") ]] +{{- if index $.Values.experimental.api "[[ $crd.GetName ]]/[[ (index $crd.Spec.Versions 0).Name ]]" }} +[[- end ]] +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: [[- $crd.GetAnnotations | toYaml | nindent 4 ]] + labels: [[- $crd.GetLabels | toYaml | nindent 4 ]] + name: [[ $crd.GetName ]] +spec: + group: [[ $crd.Spec.Group ]] + names: [[- $crd.Spec.Names | toYaml | nindent 4 ]] + scope: [[ $crd.Spec.Scope ]] + versions: + [[- range $version := $crd.Spec.Versions ]] + [[- if and (gt (len $crd.Spec.Versions) 1) (string_contains $version.Name "alpha") ]] + {{- if index $.Values.experimental.api "[[ $crd.GetName ]]/[[ $version.Name ]]" }} + [[- end ]] + - + [[- $version | toYaml | indent 4 | trimPrefix " " ]] + [[- if and (gt (len $crd.Spec.Versions) 1) (string_contains $version.Name "alpha") ]] + {{- end }} + [[- end ]] + [[- end ]] +[[- if and (lt (len $crd.Spec.Versions) 2) (string_contains (index $crd.Spec.Versions 0).Name "alpha") ]] +{{- end }} +[[- end ]] +--- +[[ end ]] \ No newline at end of file From aba416a78161006f647b40107f2d35750e5c28f3 Mon Sep 17 00:00:00 2001 From: Dmitri Dolguikh Date: Mon, 17 Jul 2023 17:07:17 -0700 Subject: [PATCH 02/27] Fixed crd template Signed-off-by: Dmitri Dolguikh --- codegen/kuberesource/crd.go | 3 ++- codegen/model/resource.go | 4 ++++ codegen/templates/manifests/crd.yamltmpl | 4 ++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/codegen/kuberesource/crd.go b/codegen/kuberesource/crd.go index 04b9231bb..5d1319ebe 100644 --- a/codegen/kuberesource/crd.go +++ b/codegen/kuberesource/crd.go @@ -154,7 +154,8 @@ func CustomResourceDefinition( v := apiextv1.CustomResourceDefinitionVersion{ Name: resource.Group.Version, Served: true, - Storage: true, + Storage: resource.Stored, + Deprecated: resource.Deprecated, AdditionalPrinterColumns: resource.AdditionalPrinterColumns, Subresources: &apiextv1.CustomResourceSubresources{ Status: status, diff --git a/codegen/model/resource.go b/codegen/model/resource.go index f0c03e604..5a5c33061 100644 --- a/codegen/model/resource.go +++ b/codegen/model/resource.go @@ -172,6 +172,10 @@ type Resource struct { // If enabled, the unmarshal will NOT allow unknown fields. StrictUnmarshal bool + + Stored bool + + Deprecated bool } type Field struct { diff --git a/codegen/templates/manifests/crd.yamltmpl b/codegen/templates/manifests/crd.yamltmpl index 4855791f4..1f72c75f5 100644 --- a/codegen/templates/manifests/crd.yamltmpl +++ b/codegen/templates/manifests/crd.yamltmpl @@ -1,6 +1,6 @@ [[- range $crd := . -]] [[- if and (lt (len $crd.Spec.Versions) 2) (string_contains (index $crd.Spec.Versions 0).Name "alpha") ]] -{{- if index $.Values.experimental.api "[[ $crd.GetName ]]/[[ (index $crd.Spec.Versions 0).Name ]]" }} +{{- if has "[[ $crd.GetName ]]/[[ (index $crd.Spec.Versions 0).Name ]]" $.Values.enabledExperimentalApi }} [[- end ]] apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -15,7 +15,7 @@ spec: versions: [[- range $version := $crd.Spec.Versions ]] [[- if and (gt (len $crd.Spec.Versions) 1) (string_contains $version.Name "alpha") ]] - {{- if index $.Values.experimental.api "[[ $crd.GetName ]]/[[ $version.Name ]]" }} + {{- if has "[[ $crd.GetName ]]/[[ $version.Name ]]" $.Values.enabledExperimentalApi }} [[- end ]] - [[- $version | toYaml | indent 4 | trimPrefix " " ]] From ba8158dad5785cee6879938ae764d9409871d32a Mon Sep 17 00:00:00 2001 From: Dmitri Dolguikh Date: Mon, 17 Jul 2023 20:08:11 -0700 Subject: [PATCH 03/27] Groups are matched with correct file descriptors now Signed-off-by: Dmitri Dolguikh --- codegen/cmd.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/codegen/cmd.go b/codegen/cmd.go index 4dcf83970..4616c335b 100644 --- a/codegen/cmd.go +++ b/codegen/cmd.go @@ -6,8 +6,10 @@ import ( "log" "os" "path/filepath" + "strings" "github.com/rotisserie/eris" + "k8s.io/utils/strings/slices" protovendor "github.com/solo-io/anyvendor/pkg/proto" "github.com/solo-io/skv2/codegen/metrics" @@ -341,7 +343,15 @@ func (c Command) initGroup( // default to the resource API Group name matchingProtoPackage = resource.Group.Group } + // TODO (dmitri-d): can we change protobuf package to contain version instead? + // for example, workspace.proto package is "admin.gloo.solo.io"; + // can we change it to "admin.gloo.solo.io.v2"? if fileDescriptor.GetPackage() == matchingProtoPackage { + path := strings.Split(fileDescriptor.GetName(), "/") + if !slices.Contains(path, resource.Group.Version) { + return false + } + if message := fileDescriptor.GetMessage(fieldType.Name); message != nil { fieldType.Message = message fieldType.GoPackage = fileDescriptor.GetOptions().GetGoPackage() From 804ea8835025d90ecc5e32209e4e6dd570752d9f Mon Sep 17 00:00:00 2001 From: Dmitri Dolguikh Date: Wed, 19 Jul 2023 17:18:04 -0700 Subject: [PATCH 04/27] Added 'Grandfathered' field to Group model Signed-off-by: Dmitri Dolguikh --- codegen/model/resource.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/codegen/model/resource.go b/codegen/model/resource.go index 5a5c33061..b18c8a2bb 100644 --- a/codegen/model/resource.go +++ b/codegen/model/resource.go @@ -114,6 +114,10 @@ type Group struct { // Some resources use pointer slices for the Items field. PointerSlices bool `default:"false"` + + // true if this should not be considered "experimental" + // even if the Version string contains "alpha" + Grandfathered bool } type GroupOptions struct { From 16c6794922b33a12332a5e9429f99a6f001e10b7 Mon Sep 17 00:00:00 2001 From: Dmitri Dolguikh Date: Wed, 26 Jul 2023 11:37:53 -0700 Subject: [PATCH 05/27] Fixing test failures Signed-off-by: Dmitri Dolguikh --- codegen/cmd.go | 40 +++++++++-------------- codegen/cmd_test.go | 1 + codegen/kuberesource/crd.go | 12 ++++--- codegen/kuberesource/crd_test.go | 20 +++++++----- codegen/render/manifests_renderer.go | 14 ++++---- codegen/render/manifests_renderer_test.go | 13 +++++--- 6 files changed, 52 insertions(+), 48 deletions(-) diff --git a/codegen/cmd.go b/codegen/cmd.go index 4616c335b..aae6e645a 100644 --- a/codegen/cmd.go +++ b/codegen/cmd.go @@ -6,10 +6,8 @@ import ( "log" "os" "path/filepath" - "strings" "github.com/rotisserie/eris" - "k8s.io/utils/strings/slices" protovendor "github.com/solo-io/anyvendor/pkg/proto" "github.com/solo-io/skv2/codegen/metrics" @@ -143,24 +141,19 @@ func (c Command) Execute() error { return err } - var groups []*model.Group + var groups []model.Group for _, group := range c.Groups { group := group // pike - groups = append(groups, &group) - } - for _, group := range groups { - group := group // pike - c.initGroup(group, descriptors) + c.initGroup(&group, descriptors) + groups = append(groups, group) } if err := c.generateGroup(groups, protoOpts, c.GroupOptions); err != nil { return err } - for i, group := range groups { - // replace group in Groups array with the group including generated fields - c.Groups[i] = *group - } + // replace group in Groups array with the group including generated fields + copy(c.Groups, groups) for _, template := range c.TopLevelTemplates { if err := c.generateTopLevelTemplates(template); err != nil { @@ -244,7 +237,7 @@ func (c Command) renderProtos() ([]*collector.DescriptorWithPath, error) { } func (c Command) generateGroup( - grps []*model.Group, + grps []model.Group, protoOpts proto.Options, groupOptions model.GroupOptions, ) error { @@ -255,7 +248,7 @@ func (c Command) generateGroup( } for _, grp := range grps { - protoTypes, err := render.RenderProtoTypes(*grp) + protoTypes, err := render.RenderProtoTypes(grp) if err != nil { return err } @@ -264,7 +257,7 @@ func (c Command) generateGroup( return err } - apiTypes, err := render.RenderApiTypes(*grp) + apiTypes, err := render.RenderApiTypes(grp) if err != nil { return err } @@ -284,7 +277,7 @@ func (c Command) generateGroup( } for _, grp := range grps { - if err := render.KubeCodegen(*grp); err != nil { + if err := render.KubeCodegen(grp); err != nil { return err } } @@ -343,15 +336,14 @@ func (c Command) initGroup( // default to the resource API Group name matchingProtoPackage = resource.Group.Group } - // TODO (dmitri-d): can we change protobuf package to contain version instead? - // for example, workspace.proto package is "admin.gloo.solo.io"; - // can we change it to "admin.gloo.solo.io.v2"? + // TODO (dmitri-d): This assumes we only ever have a single message with a given name, and breaks when we + // have multiple versions of the same proto message. + // `go_package`` is not a reliable way to determine the package version, as it is not always set. + // protobuf path is not reliable either, as it is not always contains the version (see test/test_api.proto). + // A common approach is to include the version in the proto package name, perhaps we could adopt that? + // For example, workspace.proto package now is "admin.gloo.solo.io", it would change to + // "admin.gloo.solo.io.v2" with such an approach. if fileDescriptor.GetPackage() == matchingProtoPackage { - path := strings.Split(fileDescriptor.GetName(), "/") - if !slices.Contains(path, resource.Group.Version) { - return false - } - if message := fileDescriptor.GetMessage(fieldType.Name); message != nil { fieldType.Message = message fieldType.GoPackage = fileDescriptor.GetOptions().GetGoPackage() diff --git a/codegen/cmd_test.go b/codegen/cmd_test.go index 6eed47bc3..df490830f 100644 --- a/codegen/cmd_test.go +++ b/codegen/cmd_test.go @@ -1514,6 +1514,7 @@ func helmTemplate(path string, values interface{}) []byte { path, "--values", helmValuesFile.Name(), ).CombinedOutput() + ExpectWithOffset(1, err).NotTo(HaveOccurred(), string(out)) return out } diff --git a/codegen/kuberesource/crd.go b/codegen/kuberesource/crd.go index 5d1319ebe..3872b1e8a 100644 --- a/codegen/kuberesource/crd.go +++ b/codegen/kuberesource/crd.go @@ -18,17 +18,18 @@ import ( // Create CRDs for a group func CustomResourceDefinitions( - groups []*model.Group, + groups []model.Group, ) (objects []apiextv1.CustomResourceDefinition, err error) { resourcesByKind := make(map[string][]model.Resource) + skipHashByKind := make(map[string]bool) for _, group := range groups { for _, resource := range group.Resources { resourcesByKind[resource.Kind] = append(resourcesByKind[resource.Kind], resource) + skipHashByKind[resource.Kind] = skipHashByKind[resource.Kind] || resource.Group.SkipSpecHash } } - //objects = make([]apiextv1.CustomResourceDefinition, 0, len(resourcesByKind)) - for _, resources := range resourcesByKind { + for kind, resources := range resourcesByKind { validationSchemas := make(map[string]*apiextv1.CustomResourceValidation) for _, resource := range resources { var validationSchema *apiextv1.CustomResourceValidation @@ -44,7 +45,7 @@ func CustomResourceDefinitions( validationSchemas[resource.Group.String()] = validationSchema } - objects = append(objects, *CustomResourceDefinition(resources, validationSchemas, true)) //group.SkipSpecHash)) + objects = append(objects, *CustomResourceDefinition(resources, validationSchemas, skipHashByKind[kind])) } return objects, nil } @@ -140,6 +141,9 @@ func CustomResourceDefinition( kindLower := strings.ToLower(kind) scope := apiextv1.NamespaceScoped + // TODO (dmitri-d) Should we check if all resources have the same scope + // bail if not? + // Same for ShortNames and Categories below if resources[0].ClusterScoped { scope = apiextv1.ClusterScoped } diff --git a/codegen/kuberesource/crd_test.go b/codegen/kuberesource/crd_test.go index efe9e4989..1ddb087b5 100644 --- a/codegen/kuberesource/crd_test.go +++ b/codegen/kuberesource/crd_test.go @@ -15,11 +15,11 @@ var _ = Describe("Crd", func() { Describe("CRD gen", func() { var ( - grp model.Group + grps []model.Group ) BeforeEach(func() { - grp = model.Group{ + grps = []model.Group{{ Resources: []model.Resource{ { Kind: "kind", @@ -29,15 +29,19 @@ var _ = Describe("Crd", func() { Message: &v1.AcrylicType{}, }, }, + Stored: true, + Deprecated: false, }, - }, + }}, + } + for i := range grps { + grps[i].Init() } - grp.Init() }) It("should generate spec hash", func() { - grp.SkipSpecHash = false - o, err := CustomResourceDefinitions(grp) + grps[0].SkipSpecHash = false + o, err := CustomResourceDefinitions(grps) Expect(err).NotTo(HaveOccurred()) Expect(o).To(HaveLen(1)) // note: we intentionally provide the "b6ec737002f7d02e" hash in the test, as it shouldn't change @@ -46,8 +50,8 @@ var _ = Describe("Crd", func() { }) It("should not generate spec hash", func() { - grp.SkipSpecHash = true - o, err := CustomResourceDefinitions(grp) + grps[0].SkipSpecHash = true + o, err := CustomResourceDefinitions(grps) Expect(err).NotTo(HaveOccurred()) Expect(o).To(HaveLen(1)) // note: we intentionally provide the "d18828e563010e32" hash in the test, as it shouldn't change diff --git a/codegen/render/manifests_renderer.go b/codegen/render/manifests_renderer.go index a5092dce2..af0dee841 100644 --- a/codegen/render/manifests_renderer.go +++ b/codegen/render/manifests_renderer.go @@ -41,7 +41,7 @@ func RenderManifests( appName, manifestDir, protoDir string, protoOpts protoutil.Options, groupOptions model.GroupOptions, - grps []*Group, + grps []Group, ) ([]OutFile, error) { defaultManifestsRenderer := ManifestsRenderer{ AppName: appName, @@ -51,7 +51,7 @@ func RenderManifests( return defaultManifestsRenderer.RenderManifests(grps, protoOpts, groupOptions) } -func (r ManifestsRenderer) RenderManifests(grps []*Group, protoOpts protoutil.Options, groupOptions model.GroupOptions) ([]OutFile, error) { +func (r ManifestsRenderer) RenderManifests(grps []Group, protoOpts protoutil.Options, groupOptions model.GroupOptions) ([]OutFile, error) { // if !grp.RenderManifests { // return nil, nil // } @@ -59,7 +59,7 @@ func (r ManifestsRenderer) RenderManifests(grps []*Group, protoOpts protoutil.Op for _, grp := range grps { if grp.RenderValidationSchemas { var err error - oapiSchemas, err := generateOpenApi(*grp, r.ProtoDir, protoOpts, groupOptions) + oapiSchemas, err := generateOpenApi(grp, r.ProtoDir, protoOpts, groupOptions) if err != nil { return nil, err } @@ -67,7 +67,7 @@ func (r ManifestsRenderer) RenderManifests(grps []*Group, protoOpts protoutil.Op } } - grpsByG := make(map[string][]*Group) + grpsByG := make(map[string][]Group) for _, grp := range grps { grpsByG[grp.Group] = append(grpsByG[grp.Group], grp) } @@ -210,7 +210,7 @@ func getUnstructuredFieldsMap(grp model.Group, opts protoutil.Options) (map[stri return unstructuredFields, nil } -func SetVersionForObject(obj *apiextv1.CustomResourceDefinition, version string) { +func SetVersionForObject(obj metav1.Object, version string) { if version == "" { return } @@ -276,7 +276,7 @@ func (r ManifestsRenderer) renderTemplatedManifest(appName, groupName string, ob return files[0], nil } -func (r ManifestsRenderer) createCrds(appName string, groups []*Group) ([]apiextv1.CustomResourceDefinition, error) { +func (r ManifestsRenderer) createCrds(appName string, groups []Group) ([]apiextv1.CustomResourceDefinition, error) { objs, err := kuberesource.CustomResourceDefinitions(groups) if err != nil { return nil, err @@ -284,7 +284,7 @@ func (r ManifestsRenderer) createCrds(appName string, groups []*Group) ([]apiext for i, obj := range objs { // find the annotation of the manifest, and add to them - SetVersionForObject(&objs[i], groups[0].AddChartVersion) + SetVersionForObject(objs[i].GetObjectMeta(), groups[0].AddChartVersion) labels := obj.GetLabels() if labels == nil { diff --git a/codegen/render/manifests_renderer_test.go b/codegen/render/manifests_renderer_test.go index 5d9ed79c3..0c8846dff 100644 --- a/codegen/render/manifests_renderer_test.go +++ b/codegen/render/manifests_renderer_test.go @@ -53,11 +53,11 @@ var _ = Describe("ManifestsRenderer", func() { Describe("CRD gen", func() { var ( - grp model.Group + grps []model.Group ) BeforeEach(func() { - grp = model.Group{ + grps = []model.Group{{ RenderManifests: true, AddChartVersion: "1.0.0", Resources: []model.Resource{ @@ -69,10 +69,13 @@ var _ = Describe("ManifestsRenderer", func() { Message: &v1.AcrylicType{}, }, }, + Stored: true, }, - }, + }}, + } + for i := range grps { + grps[i].Init() } - grp.Init() }) It("Renderse manifests with chart and spec hash", func() { @@ -81,7 +84,7 @@ var _ = Describe("ManifestsRenderer", func() { "appName", "manifestDir", "protoDir", nil, model.GroupOptions{}, - grp, + grps, ) Expect(err).NotTo(HaveOccurred()) Expect(outFiles).To(HaveLen(1)) From fd01b1511bb199209419888a66de2984a2476eec Mon Sep 17 00:00:00 2001 From: Dmitri Dolguikh Date: Wed, 26 Jul 2023 16:47:06 -0700 Subject: [PATCH 06/27] Tests are passing Signed-off-by: Dmitri Dolguikh --- codegen/cmd.go | 16 +++++++++------- codegen/kuberesource/crd.go | 6 +++--- codegen/kuberesource/crd_test.go | 4 ++-- codegen/render/manifests_renderer.go | 22 ++++++++++++---------- codegen/render/manifests_renderer_test.go | 9 +++++---- 5 files changed, 31 insertions(+), 26 deletions(-) diff --git a/codegen/cmd.go b/codegen/cmd.go index aae6e645a..4c0105454 100644 --- a/codegen/cmd.go +++ b/codegen/cmd.go @@ -141,11 +141,11 @@ func (c Command) Execute() error { return err } - var groups []model.Group + var groups []*model.Group for _, group := range c.Groups { group := group // pike c.initGroup(&group, descriptors) - groups = append(groups, group) + groups = append(groups, &group) } if err := c.generateGroup(groups, protoOpts, c.GroupOptions); err != nil { @@ -153,7 +153,9 @@ func (c Command) Execute() error { } // replace group in Groups array with the group including generated fields - copy(c.Groups, groups) + for i, group := range groups { + c.Groups[i] = *group + } for _, template := range c.TopLevelTemplates { if err := c.generateTopLevelTemplates(template); err != nil { @@ -237,7 +239,7 @@ func (c Command) renderProtos() ([]*collector.DescriptorWithPath, error) { } func (c Command) generateGroup( - grps []model.Group, + grps []*model.Group, protoOpts proto.Options, groupOptions model.GroupOptions, ) error { @@ -248,7 +250,7 @@ func (c Command) generateGroup( } for _, grp := range grps { - protoTypes, err := render.RenderProtoTypes(grp) + protoTypes, err := render.RenderProtoTypes(*grp) if err != nil { return err } @@ -257,7 +259,7 @@ func (c Command) generateGroup( return err } - apiTypes, err := render.RenderApiTypes(grp) + apiTypes, err := render.RenderApiTypes(*grp) if err != nil { return err } @@ -277,7 +279,7 @@ func (c Command) generateGroup( } for _, grp := range grps { - if err := render.KubeCodegen(grp); err != nil { + if err := render.KubeCodegen(*grp); err != nil { return err } } diff --git a/codegen/kuberesource/crd.go b/codegen/kuberesource/crd.go index 3872b1e8a..aec82c36e 100644 --- a/codegen/kuberesource/crd.go +++ b/codegen/kuberesource/crd.go @@ -18,13 +18,13 @@ import ( // Create CRDs for a group func CustomResourceDefinitions( - groups []model.Group, + groups []*model.Group, ) (objects []apiextv1.CustomResourceDefinition, err error) { resourcesByKind := make(map[string][]model.Resource) skipHashByKind := make(map[string]bool) for _, group := range groups { - for _, resource := range group.Resources { - resourcesByKind[resource.Kind] = append(resourcesByKind[resource.Kind], resource) + for i, resource := range group.Resources { + resourcesByKind[resource.Kind] = append(resourcesByKind[resource.Kind], group.Resources[i]) skipHashByKind[resource.Kind] = skipHashByKind[resource.Kind] || resource.Group.SkipSpecHash } } diff --git a/codegen/kuberesource/crd_test.go b/codegen/kuberesource/crd_test.go index 1ddb087b5..f5cd48036 100644 --- a/codegen/kuberesource/crd_test.go +++ b/codegen/kuberesource/crd_test.go @@ -15,11 +15,11 @@ var _ = Describe("Crd", func() { Describe("CRD gen", func() { var ( - grps []model.Group + grps []*model.Group ) BeforeEach(func() { - grps = []model.Group{{ + grps = []*model.Group{{ Resources: []model.Resource{ { Kind: "kind", diff --git a/codegen/render/manifests_renderer.go b/codegen/render/manifests_renderer.go index af0dee841..2baace976 100644 --- a/codegen/render/manifests_renderer.go +++ b/codegen/render/manifests_renderer.go @@ -41,7 +41,7 @@ func RenderManifests( appName, manifestDir, protoDir string, protoOpts protoutil.Options, groupOptions model.GroupOptions, - grps []Group, + grps []*Group, ) ([]OutFile, error) { defaultManifestsRenderer := ManifestsRenderer{ AppName: appName, @@ -51,7 +51,7 @@ func RenderManifests( return defaultManifestsRenderer.RenderManifests(grps, protoOpts, groupOptions) } -func (r ManifestsRenderer) RenderManifests(grps []Group, protoOpts protoutil.Options, groupOptions model.GroupOptions) ([]OutFile, error) { +func (r ManifestsRenderer) RenderManifests(grps []*Group, protoOpts protoutil.Options, groupOptions model.GroupOptions) ([]OutFile, error) { // if !grp.RenderManifests { // return nil, nil // } @@ -59,7 +59,7 @@ func (r ManifestsRenderer) RenderManifests(grps []Group, protoOpts protoutil.Opt for _, grp := range grps { if grp.RenderValidationSchemas { var err error - oapiSchemas, err := generateOpenApi(grp, r.ProtoDir, protoOpts, groupOptions) + oapiSchemas, err := generateOpenApi(*grp, r.ProtoDir, protoOpts, groupOptions) if err != nil { return nil, err } @@ -67,25 +67,26 @@ func (r ManifestsRenderer) RenderManifests(grps []Group, protoOpts protoutil.Opt } } - grpsByG := make(map[string][]Group) + grpsByGroupName := make(map[string][]*Group) for _, grp := range grps { - grpsByG[grp.Group] = append(grpsByG[grp.Group], grp) + grpsByGroupName[grp.Group] = append(grpsByGroupName[grp.Group], grp) } var renderedFiles []OutFile - for _, selectedGrps := range grpsByG { + for groupName, selectedGrps := range grpsByGroupName { crds, err := r.createCrds(r.AppName, selectedGrps) if err != nil { return nil, err } - out, err := r.renderManifest(r.AppName, selectedGrps[0].Group, crds) + // TODO (dmitri-d): this can be removed once we migrate to use platform charts exclusively + out, err := r.renderLegacyManifest(r.AppName, groupName, crds) if err != nil { return nil, err } renderedFiles = append(renderedFiles, out) - out, err = r.renderTemplatedManifest(r.AppName, selectedGrps[0].Group, crds) + out, err = r.renderTemplatedManifest(r.AppName, groupName, crds) if err != nil { return nil, err } @@ -235,7 +236,8 @@ func SetVersionForObject(obj metav1.Object, version string) { } } -func (r ManifestsRenderer) renderManifest(appName, groupName string, objs []apiextv1.CustomResourceDefinition) (OutFile, error) { +// TODO (dmitri-d): this can be removed once we migrate to use platform charts exclusively +func (r ManifestsRenderer) renderLegacyManifest(appName, groupName string, objs []apiextv1.CustomResourceDefinition) (OutFile, error) { outFile := OutFile{ Path: r.ManifestDir + "/crds/" + groupName + "_" + "crds.yaml", } @@ -276,7 +278,7 @@ func (r ManifestsRenderer) renderTemplatedManifest(appName, groupName string, ob return files[0], nil } -func (r ManifestsRenderer) createCrds(appName string, groups []Group) ([]apiextv1.CustomResourceDefinition, error) { +func (r ManifestsRenderer) createCrds(appName string, groups []*Group) ([]apiextv1.CustomResourceDefinition, error) { objs, err := kuberesource.CustomResourceDefinitions(groups) if err != nil { return nil, err diff --git a/codegen/render/manifests_renderer_test.go b/codegen/render/manifests_renderer_test.go index 0c8846dff..4cafa4fba 100644 --- a/codegen/render/manifests_renderer_test.go +++ b/codegen/render/manifests_renderer_test.go @@ -53,11 +53,11 @@ var _ = Describe("ManifestsRenderer", func() { Describe("CRD gen", func() { var ( - grps []model.Group + grps []*model.Group ) BeforeEach(func() { - grps = []model.Group{{ + grps = []*model.Group{{ RenderManifests: true, AddChartVersion: "1.0.0", Resources: []model.Resource{ @@ -87,10 +87,11 @@ var _ = Describe("ManifestsRenderer", func() { grps, ) Expect(err).NotTo(HaveOccurred()) - Expect(outFiles).To(HaveLen(1)) + Expect(outFiles).To(HaveLen(2)) // legacy and templated manifests Expect(outFiles[0].Content).To(ContainSubstring(crdutils.CRDVersionKey + ": 1.0.0")) Expect(outFiles[0].Content).To(ContainSubstring(crdutils.CRDSpecHashKey + ": b6ec737002f7d02e")) - + Expect(outFiles[1].Content).To(ContainSubstring(crdutils.CRDVersionKey + ": 1.0.0")) + Expect(outFiles[1].Content).To(ContainSubstring(crdutils.CRDSpecHashKey + ": b6ec737002f7d02e")) }) }) }) From ff3b4c3a1a55853e55b6562a82f7ea9ed77bde92 Mon Sep 17 00:00:00 2001 From: Dmitri Dolguikh Date: Wed, 26 Jul 2023 18:06:16 -0700 Subject: [PATCH 07/27] Added more tests Signed-off-by: Dmitri Dolguikh --- codegen/kuberesource/crd.go | 6 +- codegen/kuberesource/crd_test.go | 29 +- codegen/render/manifests_renderer_test.go | 121 +++- codegen/test/api/things.test.io/v1/clients.go | 349 +++++----- .../v1/controller/event_handlers.go | 244 +++---- .../v1/controller/multicluster_reconcilers.go | 2 + .../v1/controller/reconcilers.go | 228 +++---- .../test/api/things.test.io/v1/json.gen.go | 17 +- .../api/things.test.io/v1/proto_deepcopy.go | 47 +- .../v1/providers/client_providers.go | 50 +- .../test/api/things.test.io/v1/register.go | 19 +- .../test/api/things.test.io/v1/sets/sets.go | 618 +++++++++--------- .../test/api/things.test.io/v1/test_api.pb.go | 5 +- .../api/things.test.io/v1/type_helpers.go | 3 + codegen/test/api/things.test.io/v1/types.go | 51 +- .../v1/zz_generated.deepcopy.go | 151 ++--- ..._v1_crds.yaml => things.test.io_crds.yaml} | 8 +- .../templates/things.test.io_crds.yaml | 169 +++++ ..._v1_crds.yaml => things.test.io_crds.yaml} | 8 +- .../chart/templates/things.test.io_crds.yaml | 173 +++++ ..._v1_crds.yaml => things.test.io_crds.yaml} | 8 +- .../templates/things.test.io_crds.yaml | 59 ++ 22 files changed, 1463 insertions(+), 902 deletions(-) rename codegen/test/chart-no-desc/crds/{things.test.io_v1_crds.yaml => things.test.io_crds.yaml} (97%) create mode 100644 codegen/test/chart-no-desc/templates/things.test.io_crds.yaml rename codegen/test/chart/crds/{things.test.io_v1_crds.yaml => things.test.io_crds.yaml} (97%) create mode 100644 codegen/test/chart/templates/things.test.io_crds.yaml rename codegen/test/name_override_chart/crds/{things.test.io_v1_crds.yaml => things.test.io_crds.yaml} (89%) create mode 100644 codegen/test/name_override_chart/templates/things.test.io_crds.yaml diff --git a/codegen/kuberesource/crd.go b/codegen/kuberesource/crd.go index aec82c36e..6c3afbbbe 100644 --- a/codegen/kuberesource/crd.go +++ b/codegen/kuberesource/crd.go @@ -2,6 +2,7 @@ package kuberesource import ( "fmt" + "sort" "strings" "github.com/mitchellh/hashstructure" @@ -31,6 +32,9 @@ func CustomResourceDefinitions( for kind, resources := range resourcesByKind { validationSchemas := make(map[string]*apiextv1.CustomResourceValidation) + resources := resources + // make version ordering deterministic + sort.Slice(resources, func(i, j int) bool { return resources[i].Version < resources[j].Version }) for _, resource := range resources { var validationSchema *apiextv1.CustomResourceValidation validationSchema, err = constructValidationSchema( @@ -142,7 +146,7 @@ func CustomResourceDefinition( scope := apiextv1.NamespaceScoped // TODO (dmitri-d) Should we check if all resources have the same scope - // bail if not? + // and bail if not? // Same for ShortNames and Categories below if resources[0].ClusterScoped { scope = apiextv1.ClusterScoped diff --git a/codegen/kuberesource/crd_test.go b/codegen/kuberesource/crd_test.go index f5cd48036..2ca1b5775 100644 --- a/codegen/kuberesource/crd_test.go +++ b/codegen/kuberesource/crd_test.go @@ -32,6 +32,17 @@ var _ = Describe("Crd", func() { Stored: true, Deprecated: false, }, + { + Kind: "kind-1", + Spec: model.Field{ + Type: model.Type{ + Name: "test", + Message: &v1.PaintColor{}, + }, + }, + Stored: false, + Deprecated: true, + }, }}, } for i := range grps { @@ -43,21 +54,33 @@ var _ = Describe("Crd", func() { grps[0].SkipSpecHash = false o, err := CustomResourceDefinitions(grps) Expect(err).NotTo(HaveOccurred()) - Expect(o).To(HaveLen(1)) + Expect(o).To(HaveLen(2)) // note: we intentionally provide the "b6ec737002f7d02e" hash in the test, as it shouldn't change // between runs. Expect(o[0].GetAnnotations()).To(HaveKeyWithValue(crdutils.CRDSpecHashKey, "b6ec737002f7d02e")) - }) It("should not generate spec hash", func() { grps[0].SkipSpecHash = true o, err := CustomResourceDefinitions(grps) Expect(err).NotTo(HaveOccurred()) - Expect(o).To(HaveLen(1)) + Expect(o).To(HaveLen(2)) // note: we intentionally provide the "d18828e563010e32" hash in the test, as it shouldn't change // between runs. Expect(o[0].GetAnnotations()).NotTo(HaveKey(crdutils.CRDSpecHashKey)) }) + It("should set 'Stored' and 'Deprecated' fields", func() { + grps[0].SkipSpecHash = false + o, err := CustomResourceDefinitions(grps) + Expect(err).NotTo(HaveOccurred()) + Expect(o).To(HaveLen(2)) + Expect(o[0].Spec.Versions).To(HaveLen(1)) + Expect(o[0].Spec.Versions[0].Storage).To(BeTrue()) + Expect(o[0].Spec.Versions[0].Deprecated).To(BeFalse()) + Expect(o[1].Spec.Versions).To(HaveLen(1)) + Expect(o[1].Spec.Versions[0].Storage).To(BeFalse()) + Expect(o[1].Spec.Versions[0].Deprecated).To(BeTrue()) + }) + }) }) diff --git a/codegen/render/manifests_renderer_test.go b/codegen/render/manifests_renderer_test.go index 4cafa4fba..dfa8c3323 100644 --- a/codegen/render/manifests_renderer_test.go +++ b/codegen/render/manifests_renderer_test.go @@ -5,6 +5,7 @@ import ( . "github.com/onsi/gomega" v1 "github.com/solo-io/skv2/codegen/test/api/things.test.io/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" "github.com/solo-io/skv2/codegen/model" "github.com/solo-io/skv2/codegen/render" @@ -51,7 +52,7 @@ var _ = Describe("ManifestsRenderer", func() { Expect(obj).To(Equal(expectedObj)) }) - Describe("CRD gen", func() { + Describe("Generate non-alpha versioned CRD", func() { var ( grps []*model.Group ) @@ -90,8 +91,124 @@ var _ = Describe("ManifestsRenderer", func() { Expect(outFiles).To(HaveLen(2)) // legacy and templated manifests Expect(outFiles[0].Content).To(ContainSubstring(crdutils.CRDVersionKey + ": 1.0.0")) Expect(outFiles[0].Content).To(ContainSubstring(crdutils.CRDSpecHashKey + ": b6ec737002f7d02e")) + // only alpha versioned CRDs contain logic to conditionally render templates + Expect(outFiles[0].Content).To(Equal(outFiles[0].Content)) + }) + }) + + Describe("Generate alpha versioned CRD", func() { + var ( + grps []*model.Group + ) + + BeforeEach(func() { + grps = []*model.Group{{ + GroupVersion: schema.GroupVersion{ + Group: "things.test.io", + Version: "v1alpha1", + }, + RenderManifests: true, + AddChartVersion: "1.0.0", + Resources: []model.Resource{ + { + Kind: "kind", + Spec: model.Field{ + Type: model.Type{ + Name: "test", + Message: &v1.AcrylicType{}, + }, + }, + Stored: true, + }, + }}, + } + for i := range grps { + grps[i].Init() + } + }) + It("Renderse manifests with chart and spec hash", func() { + + // get api-level code gen options from descriptors + outFiles, err := render.RenderManifests( + "appName", "manifestDir", "protoDir", + nil, + model.GroupOptions{}, + grps, + ) + Expect(err).NotTo(HaveOccurred()) + Expect(outFiles).To(HaveLen(2)) // legacy and templated manifests + // only alpha versioned CRDs contain logic to conditionally render templates + Expect(outFiles[1].Content).To(HavePrefix("\n{{- if has \"kinds.things.test.io/v1alpha1\" $.Values.enabledExperimentalApi }}")) + Expect(outFiles[1].Content).To(HaveSuffix("{{- end }}\n---\n")) Expect(outFiles[1].Content).To(ContainSubstring(crdutils.CRDVersionKey + ": 1.0.0")) - Expect(outFiles[1].Content).To(ContainSubstring(crdutils.CRDSpecHashKey + ": b6ec737002f7d02e")) + Expect(outFiles[1].Content).To(ContainSubstring(crdutils.CRDSpecHashKey + ": 80c06d3e2484e4c8")) }) }) + + Describe("Generate combined alpha and non-alpha versioned CRD", func() { + var ( + grps []*model.Group + ) + + BeforeEach(func() { + grps = []*model.Group{{ + GroupVersion: schema.GroupVersion{ + Group: "things.test.io", + Version: "v2alpha1", + }, + RenderManifests: true, + AddChartVersion: "1.0.0", + Resources: []model.Resource{ + { + Kind: "kind", + Spec: model.Field{ + Type: model.Type{ + Name: "test", + Message: &v1.AcrylicType{}, + }, + }, + Stored: false, + }, + }}, + { + GroupVersion: schema.GroupVersion{ + Group: "things.test.io", + Version: "v1", + }, + RenderManifests: true, + AddChartVersion: "1.0.0", + Resources: []model.Resource{ + { + Kind: "kind", + Spec: model.Field{ + Type: model.Type{ + Name: "test", + Message: &v1.AcrylicType{}, + }, + }, + Stored: true, + }, + }}, + } + for i := range grps { + grps[i].Init() + } + }) + It("Renderse manifests with chart and spec hash", func() { + + // get api-level code gen options from descriptors + outFiles, err := render.RenderManifests( + "appName", "manifestDir", "protoDir", + nil, + model.GroupOptions{}, + grps, + ) + Expect(err).NotTo(HaveOccurred()) + Expect(outFiles).To(HaveLen(2)) // legacy and templated manifests + // only v2alpha1 version of the CRDs is conditionally rendered, v1 has no conditions surrounding it + Expect(outFiles[1].Content).To(ContainSubstring("subresources: {}\n {{- if has \"kinds.things.test.io/v2alpha1\" $.Values.enabledExperimentalApi }}\n - name: v2alpha1")) + Expect(outFiles[1].Content).To(ContainSubstring("{{- end }}\n---\n")) + }) + }) + }) diff --git a/codegen/test/api/things.test.io/v1/clients.go b/codegen/test/api/things.test.io/v1/clients.go index 9f7c889c8..1f54aadb5 100644 --- a/codegen/test/api/things.test.io/v1/clients.go +++ b/codegen/test/api/things.test.io/v1/clients.go @@ -4,86 +4,89 @@ package v1 + + + import ( - "context" - - "github.com/solo-io/skv2/pkg/controllerutils" - "github.com/solo-io/skv2/pkg/multicluster" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/client-go/kubernetes/scheme" - "k8s.io/client-go/rest" - "sigs.k8s.io/controller-runtime/pkg/client" + "context" + + "github.com/solo-io/skv2/pkg/controllerutils" + "github.com/solo-io/skv2/pkg/multicluster" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/client" ) // MulticlusterClientset for the things.test.io/v1 APIs type MulticlusterClientset interface { - // Cluster returns a Clientset for the given cluster - Cluster(cluster string) (Clientset, error) + // Cluster returns a Clientset for the given cluster + Cluster(cluster string) (Clientset, error) } type multiclusterClientset struct { - client multicluster.Client + client multicluster.Client } func NewMulticlusterClientset(client multicluster.Client) MulticlusterClientset { - return &multiclusterClientset{client: client} + return &multiclusterClientset{client: client} } func (m *multiclusterClientset) Cluster(cluster string) (Clientset, error) { - client, err := m.client.Cluster(cluster) - if err != nil { - return nil, err - } - return NewClientset(client), nil + client, err := m.client.Cluster(cluster) + if err != nil { + return nil, err + } + return NewClientset(client), nil } // clienset for the things.test.io/v1 APIs type Clientset interface { - // clienset for the things.test.io/v1/v1 APIs - Paints() PaintClient - // clienset for the things.test.io/v1/v1 APIs - ClusterResources() ClusterResourceClient + // clienset for the things.test.io/v1/v1 APIs + Paints() PaintClient + // clienset for the things.test.io/v1/v1 APIs + ClusterResources() ClusterResourceClient } type clientSet struct { - client client.Client + client client.Client } func NewClientsetFromConfig(cfg *rest.Config) (Clientset, error) { - scheme := scheme.Scheme - if err := SchemeBuilder.AddToScheme(scheme); err != nil { - return nil, err - } - client, err := client.New(cfg, client.Options{ - Scheme: scheme, - }) - if err != nil { - return nil, err - } - return NewClientset(client), nil + scheme := scheme.Scheme + if err := SchemeBuilder.AddToScheme(scheme); err != nil{ + return nil, err + } + client, err := client.New(cfg, client.Options{ + Scheme: scheme, + }) + if err != nil { + return nil, err + } + return NewClientset(client), nil } func NewClientset(client client.Client) Clientset { - return &clientSet{client: client} + return &clientSet{client: client} } // clienset for the things.test.io/v1/v1 APIs func (c *clientSet) Paints() PaintClient { - return NewPaintClient(c.client) + return NewPaintClient(c.client) } // clienset for the things.test.io/v1/v1 APIs func (c *clientSet) ClusterResources() ClusterResourceClient { - return NewClusterResourceClient(c.client) + return NewClusterResourceClient(c.client) } // Reader knows how to read and list Paints. type PaintReader interface { - // Get retrieves a Paint for the given object key - GetPaint(ctx context.Context, key client.ObjectKey) (*Paint, error) + // Get retrieves a Paint for the given object key + GetPaint(ctx context.Context, key client.ObjectKey) (*Paint, error) - // List retrieves list of Paints for a given namespace and list options. - ListPaint(ctx context.Context, opts ...client.ListOption) (*PaintList, error) + // List retrieves list of Paints for a given namespace and list options. + ListPaint(ctx context.Context, opts ...client.ListOption) (*PaintList, error) } // PaintTransitionFunction instructs the PaintWriter how to transition between an existing @@ -92,140 +95,142 @@ type PaintTransitionFunction func(existing, desired *Paint) error // Writer knows how to create, delete, and update Paints. type PaintWriter interface { - // Create saves the Paint object. - CreatePaint(ctx context.Context, obj *Paint, opts ...client.CreateOption) error + // Create saves the Paint object. + CreatePaint(ctx context.Context, obj *Paint, opts ...client.CreateOption) error - // Delete deletes the Paint object. - DeletePaint(ctx context.Context, key client.ObjectKey, opts ...client.DeleteOption) error + // Delete deletes the Paint object. + DeletePaint(ctx context.Context, key client.ObjectKey, opts ...client.DeleteOption) error - // Update updates the given Paint object. - UpdatePaint(ctx context.Context, obj *Paint, opts ...client.UpdateOption) error + // Update updates the given Paint object. + UpdatePaint(ctx context.Context, obj *Paint, opts ...client.UpdateOption) error - // Patch patches the given Paint object. - PatchPaint(ctx context.Context, obj *Paint, patch client.Patch, opts ...client.PatchOption) error + // Patch patches the given Paint object. + PatchPaint(ctx context.Context, obj *Paint, patch client.Patch, opts ...client.PatchOption) error - // DeleteAllOf deletes all Paint objects matching the given options. - DeleteAllOfPaint(ctx context.Context, opts ...client.DeleteAllOfOption) error + // DeleteAllOf deletes all Paint objects matching the given options. + DeleteAllOfPaint(ctx context.Context, opts ...client.DeleteAllOfOption) error - // Create or Update the Paint object. - UpsertPaint(ctx context.Context, obj *Paint, transitionFuncs ...PaintTransitionFunction) error + // Create or Update the Paint object. + UpsertPaint(ctx context.Context, obj *Paint, transitionFuncs ...PaintTransitionFunction) error } // StatusWriter knows how to update status subresource of a Paint object. type PaintStatusWriter interface { - // Update updates the fields corresponding to the status subresource for the - // given Paint object. - UpdatePaintStatus(ctx context.Context, obj *Paint, opts ...client.SubResourceUpdateOption) error + // Update updates the fields corresponding to the status subresource for the + // given Paint object. + UpdatePaintStatus(ctx context.Context, obj *Paint, opts ...client.SubResourceUpdateOption) error - // Patch patches the given Paint object's subresource. - PatchPaintStatus(ctx context.Context, obj *Paint, patch client.Patch, opts ...client.SubResourcePatchOption) error + // Patch patches the given Paint object's subresource. + PatchPaintStatus(ctx context.Context, obj *Paint, patch client.Patch, opts ...client.SubResourcePatchOption) error } // Client knows how to perform CRUD operations on Paints. type PaintClient interface { - PaintReader - PaintWriter - PaintStatusWriter + PaintReader + PaintWriter + PaintStatusWriter } type paintClient struct { - client client.Client + client client.Client } func NewPaintClient(client client.Client) *paintClient { - return &paintClient{client: client} + return &paintClient{client: client} } + func (c *paintClient) GetPaint(ctx context.Context, key client.ObjectKey) (*Paint, error) { - obj := &Paint{} - if err := c.client.Get(ctx, key, obj); err != nil { - return nil, err - } - return obj, nil + obj := &Paint{} + if err := c.client.Get(ctx, key, obj); err != nil { + return nil, err + } + return obj, nil } func (c *paintClient) ListPaint(ctx context.Context, opts ...client.ListOption) (*PaintList, error) { - list := &PaintList{} - if err := c.client.List(ctx, list, opts...); err != nil { - return nil, err - } - return list, nil + list := &PaintList{} + if err := c.client.List(ctx, list, opts...); err != nil { + return nil, err + } + return list, nil } func (c *paintClient) CreatePaint(ctx context.Context, obj *Paint, opts ...client.CreateOption) error { - return c.client.Create(ctx, obj, opts...) + return c.client.Create(ctx, obj, opts...) } + func (c *paintClient) DeletePaint(ctx context.Context, key client.ObjectKey, opts ...client.DeleteOption) error { - obj := &Paint{} - obj.SetName(key.Name) - obj.SetNamespace(key.Namespace) - return c.client.Delete(ctx, obj, opts...) + obj := &Paint{} + obj.SetName(key.Name) + obj.SetNamespace(key.Namespace) + return c.client.Delete(ctx, obj, opts...) } func (c *paintClient) UpdatePaint(ctx context.Context, obj *Paint, opts ...client.UpdateOption) error { - return c.client.Update(ctx, obj, opts...) + return c.client.Update(ctx, obj, opts...) } func (c *paintClient) PatchPaint(ctx context.Context, obj *Paint, patch client.Patch, opts ...client.PatchOption) error { - return c.client.Patch(ctx, obj, patch, opts...) + return c.client.Patch(ctx, obj, patch, opts...) } func (c *paintClient) DeleteAllOfPaint(ctx context.Context, opts ...client.DeleteAllOfOption) error { - obj := &Paint{} - return c.client.DeleteAllOf(ctx, obj, opts...) + obj := &Paint{} + return c.client.DeleteAllOf(ctx, obj, opts...) } func (c *paintClient) UpsertPaint(ctx context.Context, obj *Paint, transitionFuncs ...PaintTransitionFunction) error { - genericTxFunc := func(existing, desired runtime.Object) error { - for _, txFunc := range transitionFuncs { - if err := txFunc(existing.(*Paint), desired.(*Paint)); err != nil { - return err - } - } - return nil - } - _, err := controllerutils.Upsert(ctx, c.client, obj, genericTxFunc) - return err + genericTxFunc := func(existing, desired runtime.Object) error { + for _, txFunc := range transitionFuncs { + if err := txFunc(existing.(*Paint), desired.(*Paint)); err != nil { + return err + } + } + return nil + } + _, err := controllerutils.Upsert(ctx, c.client, obj, genericTxFunc) + return err } func (c *paintClient) UpdatePaintStatus(ctx context.Context, obj *Paint, opts ...client.SubResourceUpdateOption) error { - return c.client.Status().Update(ctx, obj, opts...) + return c.client.Status().Update(ctx, obj, opts...) } func (c *paintClient) PatchPaintStatus(ctx context.Context, obj *Paint, patch client.Patch, opts ...client.SubResourcePatchOption) error { - return c.client.Status().Patch(ctx, obj, patch, opts...) + return c.client.Status().Patch(ctx, obj, patch, opts...) } // Provides PaintClients for multiple clusters. type MulticlusterPaintClient interface { - // Cluster returns a PaintClient for the given cluster - Cluster(cluster string) (PaintClient, error) + // Cluster returns a PaintClient for the given cluster + Cluster(cluster string) (PaintClient, error) } type multiclusterPaintClient struct { - client multicluster.Client + client multicluster.Client } func NewMulticlusterPaintClient(client multicluster.Client) MulticlusterPaintClient { - return &multiclusterPaintClient{client: client} + return &multiclusterPaintClient{client: client} } func (m *multiclusterPaintClient) Cluster(cluster string) (PaintClient, error) { - client, err := m.client.Cluster(cluster) - if err != nil { - return nil, err - } - return NewPaintClient(client), nil + client, err := m.client.Cluster(cluster) + if err != nil { + return nil, err + } + return NewPaintClient(client), nil } // Reader knows how to read and list ClusterResources. type ClusterResourceReader interface { - // Get retrieves a ClusterResource for the given object key - GetClusterResource(ctx context.Context, name string) (*ClusterResource, error) + // Get retrieves a ClusterResource for the given object key + GetClusterResource(ctx context.Context, name string) (*ClusterResource, error) - // List retrieves list of ClusterResources for a given namespace and list options. - ListClusterResource(ctx context.Context, opts ...client.ListOption) (*ClusterResourceList, error) + // List retrieves list of ClusterResources for a given namespace and list options. + ListClusterResource(ctx context.Context, opts ...client.ListOption) (*ClusterResourceList, error) } // ClusterResourceTransitionFunction instructs the ClusterResourceWriter how to transition between an existing @@ -234,131 +239,133 @@ type ClusterResourceTransitionFunction func(existing, desired *ClusterResource) // Writer knows how to create, delete, and update ClusterResources. type ClusterResourceWriter interface { - // Create saves the ClusterResource object. - CreateClusterResource(ctx context.Context, obj *ClusterResource, opts ...client.CreateOption) error + // Create saves the ClusterResource object. + CreateClusterResource(ctx context.Context, obj *ClusterResource, opts ...client.CreateOption) error - // Delete deletes the ClusterResource object. - DeleteClusterResource(ctx context.Context, name string, opts ...client.DeleteOption) error + // Delete deletes the ClusterResource object. + DeleteClusterResource(ctx context.Context, name string, opts ...client.DeleteOption) error - // Update updates the given ClusterResource object. - UpdateClusterResource(ctx context.Context, obj *ClusterResource, opts ...client.UpdateOption) error + // Update updates the given ClusterResource object. + UpdateClusterResource(ctx context.Context, obj *ClusterResource, opts ...client.UpdateOption) error - // Patch patches the given ClusterResource object. - PatchClusterResource(ctx context.Context, obj *ClusterResource, patch client.Patch, opts ...client.PatchOption) error + // Patch patches the given ClusterResource object. + PatchClusterResource(ctx context.Context, obj *ClusterResource, patch client.Patch, opts ...client.PatchOption) error - // DeleteAllOf deletes all ClusterResource objects matching the given options. - DeleteAllOfClusterResource(ctx context.Context, opts ...client.DeleteAllOfOption) error + // DeleteAllOf deletes all ClusterResource objects matching the given options. + DeleteAllOfClusterResource(ctx context.Context, opts ...client.DeleteAllOfOption) error - // Create or Update the ClusterResource object. - UpsertClusterResource(ctx context.Context, obj *ClusterResource, transitionFuncs ...ClusterResourceTransitionFunction) error + // Create or Update the ClusterResource object. + UpsertClusterResource(ctx context.Context, obj *ClusterResource, transitionFuncs ...ClusterResourceTransitionFunction) error } // StatusWriter knows how to update status subresource of a ClusterResource object. type ClusterResourceStatusWriter interface { - // Update updates the fields corresponding to the status subresource for the - // given ClusterResource object. - UpdateClusterResourceStatus(ctx context.Context, obj *ClusterResource, opts ...client.SubResourceUpdateOption) error + // Update updates the fields corresponding to the status subresource for the + // given ClusterResource object. + UpdateClusterResourceStatus(ctx context.Context, obj *ClusterResource, opts ...client.SubResourceUpdateOption) error - // Patch patches the given ClusterResource object's subresource. - PatchClusterResourceStatus(ctx context.Context, obj *ClusterResource, patch client.Patch, opts ...client.SubResourcePatchOption) error + // Patch patches the given ClusterResource object's subresource. + PatchClusterResourceStatus(ctx context.Context, obj *ClusterResource, patch client.Patch, opts ...client.SubResourcePatchOption) error } // Client knows how to perform CRUD operations on ClusterResources. type ClusterResourceClient interface { - ClusterResourceReader - ClusterResourceWriter - ClusterResourceStatusWriter + ClusterResourceReader + ClusterResourceWriter + ClusterResourceStatusWriter } type clusterResourceClient struct { - client client.Client + client client.Client } func NewClusterResourceClient(client client.Client) *clusterResourceClient { - return &clusterResourceClient{client: client} + return &clusterResourceClient{client: client} } + func (c *clusterResourceClient) GetClusterResource(ctx context.Context, name string) (*ClusterResource, error) { - obj := &ClusterResource{} - key := client.ObjectKey{ - Name: name, - } - if err := c.client.Get(ctx, key, obj); err != nil { - return nil, err - } - return obj, nil + obj := &ClusterResource{} + key := client.ObjectKey{ + Name: name, + } + if err := c.client.Get(ctx, key, obj); err != nil { + return nil, err + } + return obj, nil } func (c *clusterResourceClient) ListClusterResource(ctx context.Context, opts ...client.ListOption) (*ClusterResourceList, error) { - list := &ClusterResourceList{} - if err := c.client.List(ctx, list, opts...); err != nil { - return nil, err - } - return list, nil + list := &ClusterResourceList{} + if err := c.client.List(ctx, list, opts...); err != nil { + return nil, err + } + return list, nil } func (c *clusterResourceClient) CreateClusterResource(ctx context.Context, obj *ClusterResource, opts ...client.CreateOption) error { - return c.client.Create(ctx, obj, opts...) + return c.client.Create(ctx, obj, opts...) } + func (c *clusterResourceClient) DeleteClusterResource(ctx context.Context, name string, opts ...client.DeleteOption) error { - obj := &ClusterResource{} - obj.SetName(name) - return c.client.Delete(ctx, obj, opts...) + obj := &ClusterResource{} + obj.SetName(name) + return c.client.Delete(ctx, obj, opts...) } func (c *clusterResourceClient) UpdateClusterResource(ctx context.Context, obj *ClusterResource, opts ...client.UpdateOption) error { - return c.client.Update(ctx, obj, opts...) + return c.client.Update(ctx, obj, opts...) } func (c *clusterResourceClient) PatchClusterResource(ctx context.Context, obj *ClusterResource, patch client.Patch, opts ...client.PatchOption) error { - return c.client.Patch(ctx, obj, patch, opts...) + return c.client.Patch(ctx, obj, patch, opts...) } func (c *clusterResourceClient) DeleteAllOfClusterResource(ctx context.Context, opts ...client.DeleteAllOfOption) error { - obj := &ClusterResource{} - return c.client.DeleteAllOf(ctx, obj, opts...) + obj := &ClusterResource{} + return c.client.DeleteAllOf(ctx, obj, opts...) } func (c *clusterResourceClient) UpsertClusterResource(ctx context.Context, obj *ClusterResource, transitionFuncs ...ClusterResourceTransitionFunction) error { - genericTxFunc := func(existing, desired runtime.Object) error { - for _, txFunc := range transitionFuncs { - if err := txFunc(existing.(*ClusterResource), desired.(*ClusterResource)); err != nil { - return err - } - } - return nil - } - _, err := controllerutils.Upsert(ctx, c.client, obj, genericTxFunc) - return err + genericTxFunc := func(existing, desired runtime.Object) error { + for _, txFunc := range transitionFuncs { + if err := txFunc(existing.(*ClusterResource), desired.(*ClusterResource)); err != nil { + return err + } + } + return nil + } + _, err := controllerutils.Upsert(ctx, c.client, obj, genericTxFunc) + return err } func (c *clusterResourceClient) UpdateClusterResourceStatus(ctx context.Context, obj *ClusterResource, opts ...client.SubResourceUpdateOption) error { - return c.client.Status().Update(ctx, obj, opts...) + return c.client.Status().Update(ctx, obj, opts...) } func (c *clusterResourceClient) PatchClusterResourceStatus(ctx context.Context, obj *ClusterResource, patch client.Patch, opts ...client.SubResourcePatchOption) error { - return c.client.Status().Patch(ctx, obj, patch, opts...) + return c.client.Status().Patch(ctx, obj, patch, opts...) } // Provides ClusterResourceClients for multiple clusters. type MulticlusterClusterResourceClient interface { - // Cluster returns a ClusterResourceClient for the given cluster - Cluster(cluster string) (ClusterResourceClient, error) + // Cluster returns a ClusterResourceClient for the given cluster + Cluster(cluster string) (ClusterResourceClient, error) } type multiclusterClusterResourceClient struct { - client multicluster.Client + client multicluster.Client } func NewMulticlusterClusterResourceClient(client multicluster.Client) MulticlusterClusterResourceClient { - return &multiclusterClusterResourceClient{client: client} + return &multiclusterClusterResourceClient{client: client} } func (m *multiclusterClusterResourceClient) Cluster(cluster string) (ClusterResourceClient, error) { - client, err := m.client.Cluster(cluster) - if err != nil { - return nil, err - } - return NewClusterResourceClient(client), nil -} + client, err := m.client.Cluster(cluster) + if err != nil { + return nil, err + } + return NewClusterResourceClient(client), nil +} \ No newline at end of file diff --git a/codegen/test/api/things.test.io/v1/controller/event_handlers.go b/codegen/test/api/things.test.io/v1/controller/event_handlers.go index 3c52ed1f6..066691b25 100644 --- a/codegen/test/api/things.test.io/v1/controller/event_handlers.go +++ b/codegen/test/api/things.test.io/v1/controller/event_handlers.go @@ -8,225 +8,225 @@ package controller import ( "context" - things_test_io_v1 "github.com/solo-io/skv2/codegen/test/api/things.test.io/v1" + things_test_io_v1 "github.com/solo-io/skv2/codegen/test/api/things.test.io/v1" - "github.com/pkg/errors" - "github.com/solo-io/skv2/pkg/events" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/manager" - "sigs.k8s.io/controller-runtime/pkg/predicate" + "github.com/pkg/errors" + "github.com/solo-io/skv2/pkg/events" + "sigs.k8s.io/controller-runtime/pkg/manager" + "sigs.k8s.io/controller-runtime/pkg/predicate" + "sigs.k8s.io/controller-runtime/pkg/client" ) // Handle events for the Paint Resource // DEPRECATED: Prefer reconciler pattern. type PaintEventHandler interface { - CreatePaint(obj *things_test_io_v1.Paint) error - UpdatePaint(old, new *things_test_io_v1.Paint) error - DeletePaint(obj *things_test_io_v1.Paint) error - GenericPaint(obj *things_test_io_v1.Paint) error + CreatePaint(obj *things_test_io_v1.Paint) error + UpdatePaint(old, new *things_test_io_v1.Paint) error + DeletePaint(obj *things_test_io_v1.Paint) error + GenericPaint(obj *things_test_io_v1.Paint) error } type PaintEventHandlerFuncs struct { - OnCreate func(obj *things_test_io_v1.Paint) error - OnUpdate func(old, new *things_test_io_v1.Paint) error - OnDelete func(obj *things_test_io_v1.Paint) error - OnGeneric func(obj *things_test_io_v1.Paint) error + OnCreate func(obj *things_test_io_v1.Paint) error + OnUpdate func(old, new *things_test_io_v1.Paint) error + OnDelete func(obj *things_test_io_v1.Paint) error + OnGeneric func(obj *things_test_io_v1.Paint) error } func (f *PaintEventHandlerFuncs) CreatePaint(obj *things_test_io_v1.Paint) error { - if f.OnCreate == nil { - return nil - } - return f.OnCreate(obj) + if f.OnCreate == nil { + return nil + } + return f.OnCreate(obj) } func (f *PaintEventHandlerFuncs) DeletePaint(obj *things_test_io_v1.Paint) error { - if f.OnDelete == nil { - return nil - } - return f.OnDelete(obj) + if f.OnDelete == nil { + return nil + } + return f.OnDelete(obj) } func (f *PaintEventHandlerFuncs) UpdatePaint(objOld, objNew *things_test_io_v1.Paint) error { - if f.OnUpdate == nil { - return nil - } - return f.OnUpdate(objOld, objNew) + if f.OnUpdate == nil { + return nil + } + return f.OnUpdate(objOld, objNew) } func (f *PaintEventHandlerFuncs) GenericPaint(obj *things_test_io_v1.Paint) error { - if f.OnGeneric == nil { - return nil - } - return f.OnGeneric(obj) + if f.OnGeneric == nil { + return nil + } + return f.OnGeneric(obj) } type PaintEventWatcher interface { - AddEventHandler(ctx context.Context, h PaintEventHandler, predicates ...predicate.Predicate) error + AddEventHandler(ctx context.Context, h PaintEventHandler, predicates ...predicate.Predicate) error } type paintEventWatcher struct { - watcher events.EventWatcher + watcher events.EventWatcher } func NewPaintEventWatcher(name string, mgr manager.Manager) PaintEventWatcher { - return &paintEventWatcher{ - watcher: events.NewWatcher(name, mgr, &things_test_io_v1.Paint{}), - } + return &paintEventWatcher{ + watcher: events.NewWatcher(name, mgr, &things_test_io_v1.Paint{}), + } } func (c *paintEventWatcher) AddEventHandler(ctx context.Context, h PaintEventHandler, predicates ...predicate.Predicate) error { handler := genericPaintHandler{handler: h} - if err := c.watcher.Watch(ctx, handler, predicates...); err != nil { - return err - } - return nil + if err := c.watcher.Watch(ctx, handler, predicates...); err != nil{ + return err + } + return nil } // genericPaintHandler implements a generic events.EventHandler type genericPaintHandler struct { - handler PaintEventHandler + handler PaintEventHandler } func (h genericPaintHandler) Create(object client.Object) error { - obj, ok := object.(*things_test_io_v1.Paint) - if !ok { - return errors.Errorf("internal error: Paint handler received event for %T", object) - } - return h.handler.CreatePaint(obj) + obj, ok := object.(*things_test_io_v1.Paint) + if !ok { + return errors.Errorf("internal error: Paint handler received event for %T", object) + } + return h.handler.CreatePaint(obj) } func (h genericPaintHandler) Delete(object client.Object) error { - obj, ok := object.(*things_test_io_v1.Paint) - if !ok { - return errors.Errorf("internal error: Paint handler received event for %T", object) - } - return h.handler.DeletePaint(obj) + obj, ok := object.(*things_test_io_v1.Paint) + if !ok { + return errors.Errorf("internal error: Paint handler received event for %T", object) + } + return h.handler.DeletePaint(obj) } func (h genericPaintHandler) Update(old, new client.Object) error { - objOld, ok := old.(*things_test_io_v1.Paint) - if !ok { - return errors.Errorf("internal error: Paint handler received event for %T", old) - } - objNew, ok := new.(*things_test_io_v1.Paint) - if !ok { - return errors.Errorf("internal error: Paint handler received event for %T", new) - } - return h.handler.UpdatePaint(objOld, objNew) + objOld, ok := old.(*things_test_io_v1.Paint) + if !ok { + return errors.Errorf("internal error: Paint handler received event for %T", old) + } + objNew, ok := new.(*things_test_io_v1.Paint) + if !ok { + return errors.Errorf("internal error: Paint handler received event for %T", new) + } + return h.handler.UpdatePaint(objOld, objNew) } func (h genericPaintHandler) Generic(object client.Object) error { - obj, ok := object.(*things_test_io_v1.Paint) - if !ok { - return errors.Errorf("internal error: Paint handler received event for %T", object) - } - return h.handler.GenericPaint(obj) + obj, ok := object.(*things_test_io_v1.Paint) + if !ok { + return errors.Errorf("internal error: Paint handler received event for %T", object) + } + return h.handler.GenericPaint(obj) } // Handle events for the ClusterResource Resource // DEPRECATED: Prefer reconciler pattern. type ClusterResourceEventHandler interface { - CreateClusterResource(obj *things_test_io_v1.ClusterResource) error - UpdateClusterResource(old, new *things_test_io_v1.ClusterResource) error - DeleteClusterResource(obj *things_test_io_v1.ClusterResource) error - GenericClusterResource(obj *things_test_io_v1.ClusterResource) error + CreateClusterResource(obj *things_test_io_v1.ClusterResource) error + UpdateClusterResource(old, new *things_test_io_v1.ClusterResource) error + DeleteClusterResource(obj *things_test_io_v1.ClusterResource) error + GenericClusterResource(obj *things_test_io_v1.ClusterResource) error } type ClusterResourceEventHandlerFuncs struct { - OnCreate func(obj *things_test_io_v1.ClusterResource) error - OnUpdate func(old, new *things_test_io_v1.ClusterResource) error - OnDelete func(obj *things_test_io_v1.ClusterResource) error - OnGeneric func(obj *things_test_io_v1.ClusterResource) error + OnCreate func(obj *things_test_io_v1.ClusterResource) error + OnUpdate func(old, new *things_test_io_v1.ClusterResource) error + OnDelete func(obj *things_test_io_v1.ClusterResource) error + OnGeneric func(obj *things_test_io_v1.ClusterResource) error } func (f *ClusterResourceEventHandlerFuncs) CreateClusterResource(obj *things_test_io_v1.ClusterResource) error { - if f.OnCreate == nil { - return nil - } - return f.OnCreate(obj) + if f.OnCreate == nil { + return nil + } + return f.OnCreate(obj) } func (f *ClusterResourceEventHandlerFuncs) DeleteClusterResource(obj *things_test_io_v1.ClusterResource) error { - if f.OnDelete == nil { - return nil - } - return f.OnDelete(obj) + if f.OnDelete == nil { + return nil + } + return f.OnDelete(obj) } func (f *ClusterResourceEventHandlerFuncs) UpdateClusterResource(objOld, objNew *things_test_io_v1.ClusterResource) error { - if f.OnUpdate == nil { - return nil - } - return f.OnUpdate(objOld, objNew) + if f.OnUpdate == nil { + return nil + } + return f.OnUpdate(objOld, objNew) } func (f *ClusterResourceEventHandlerFuncs) GenericClusterResource(obj *things_test_io_v1.ClusterResource) error { - if f.OnGeneric == nil { - return nil - } - return f.OnGeneric(obj) + if f.OnGeneric == nil { + return nil + } + return f.OnGeneric(obj) } type ClusterResourceEventWatcher interface { - AddEventHandler(ctx context.Context, h ClusterResourceEventHandler, predicates ...predicate.Predicate) error + AddEventHandler(ctx context.Context, h ClusterResourceEventHandler, predicates ...predicate.Predicate) error } type clusterResourceEventWatcher struct { - watcher events.EventWatcher + watcher events.EventWatcher } func NewClusterResourceEventWatcher(name string, mgr manager.Manager) ClusterResourceEventWatcher { - return &clusterResourceEventWatcher{ - watcher: events.NewWatcher(name, mgr, &things_test_io_v1.ClusterResource{}), - } + return &clusterResourceEventWatcher{ + watcher: events.NewWatcher(name, mgr, &things_test_io_v1.ClusterResource{}), + } } func (c *clusterResourceEventWatcher) AddEventHandler(ctx context.Context, h ClusterResourceEventHandler, predicates ...predicate.Predicate) error { handler := genericClusterResourceHandler{handler: h} - if err := c.watcher.Watch(ctx, handler, predicates...); err != nil { - return err - } - return nil + if err := c.watcher.Watch(ctx, handler, predicates...); err != nil{ + return err + } + return nil } // genericClusterResourceHandler implements a generic events.EventHandler type genericClusterResourceHandler struct { - handler ClusterResourceEventHandler + handler ClusterResourceEventHandler } func (h genericClusterResourceHandler) Create(object client.Object) error { - obj, ok := object.(*things_test_io_v1.ClusterResource) - if !ok { - return errors.Errorf("internal error: ClusterResource handler received event for %T", object) - } - return h.handler.CreateClusterResource(obj) + obj, ok := object.(*things_test_io_v1.ClusterResource) + if !ok { + return errors.Errorf("internal error: ClusterResource handler received event for %T", object) + } + return h.handler.CreateClusterResource(obj) } func (h genericClusterResourceHandler) Delete(object client.Object) error { - obj, ok := object.(*things_test_io_v1.ClusterResource) - if !ok { - return errors.Errorf("internal error: ClusterResource handler received event for %T", object) - } - return h.handler.DeleteClusterResource(obj) + obj, ok := object.(*things_test_io_v1.ClusterResource) + if !ok { + return errors.Errorf("internal error: ClusterResource handler received event for %T", object) + } + return h.handler.DeleteClusterResource(obj) } func (h genericClusterResourceHandler) Update(old, new client.Object) error { - objOld, ok := old.(*things_test_io_v1.ClusterResource) - if !ok { - return errors.Errorf("internal error: ClusterResource handler received event for %T", old) - } - objNew, ok := new.(*things_test_io_v1.ClusterResource) - if !ok { - return errors.Errorf("internal error: ClusterResource handler received event for %T", new) - } - return h.handler.UpdateClusterResource(objOld, objNew) + objOld, ok := old.(*things_test_io_v1.ClusterResource) + if !ok { + return errors.Errorf("internal error: ClusterResource handler received event for %T", old) + } + objNew, ok := new.(*things_test_io_v1.ClusterResource) + if !ok { + return errors.Errorf("internal error: ClusterResource handler received event for %T", new) + } + return h.handler.UpdateClusterResource(objOld, objNew) } func (h genericClusterResourceHandler) Generic(object client.Object) error { - obj, ok := object.(*things_test_io_v1.ClusterResource) - if !ok { - return errors.Errorf("internal error: ClusterResource handler received event for %T", object) - } - return h.handler.GenericClusterResource(obj) + obj, ok := object.(*things_test_io_v1.ClusterResource) + if !ok { + return errors.Errorf("internal error: ClusterResource handler received event for %T", object) + } + return h.handler.GenericClusterResource(obj) } diff --git a/codegen/test/api/things.test.io/v1/controller/multicluster_reconcilers.go b/codegen/test/api/things.test.io/v1/controller/multicluster_reconcilers.go index fbfe2e86e..237ee95a0 100644 --- a/codegen/test/api/things.test.io/v1/controller/multicluster_reconcilers.go +++ b/codegen/test/api/things.test.io/v1/controller/multicluster_reconcilers.go @@ -5,6 +5,8 @@ // Definitions for the multicluster Kubernetes Controllers package controller + + import ( "context" diff --git a/codegen/test/api/things.test.io/v1/controller/reconcilers.go b/codegen/test/api/things.test.io/v1/controller/reconcilers.go index 355e61896..a04151fb4 100644 --- a/codegen/test/api/things.test.io/v1/controller/reconcilers.go +++ b/codegen/test/api/things.test.io/v1/controller/reconcilers.go @@ -5,22 +5,24 @@ // Definitions for the Kubernetes Controllers package controller + + import ( "context" - things_test_io_v1 "github.com/solo-io/skv2/codegen/test/api/things.test.io/v1" + things_test_io_v1 "github.com/solo-io/skv2/codegen/test/api/things.test.io/v1" - "github.com/pkg/errors" - "github.com/solo-io/skv2/pkg/ezkube" - "github.com/solo-io/skv2/pkg/reconcile" - "sigs.k8s.io/controller-runtime/pkg/manager" - "sigs.k8s.io/controller-runtime/pkg/predicate" + "github.com/pkg/errors" + "github.com/solo-io/skv2/pkg/ezkube" + "github.com/solo-io/skv2/pkg/reconcile" + "sigs.k8s.io/controller-runtime/pkg/manager" + "sigs.k8s.io/controller-runtime/pkg/predicate" ) // Reconcile Upsert events for the Paint Resource. // implemented by the user type PaintReconciler interface { - ReconcilePaint(obj *things_test_io_v1.Paint) (reconcile.Result, error) + ReconcilePaint(obj *things_test_io_v1.Paint) (reconcile.Result, error) } // Reconcile deletion events for the Paint Resource. @@ -28,116 +30,117 @@ type PaintReconciler interface { // before being deleted. // implemented by the user type PaintDeletionReconciler interface { - ReconcilePaintDeletion(req reconcile.Request) error + ReconcilePaintDeletion(req reconcile.Request) error } type PaintReconcilerFuncs struct { - OnReconcilePaint func(obj *things_test_io_v1.Paint) (reconcile.Result, error) - OnReconcilePaintDeletion func(req reconcile.Request) error + OnReconcilePaint func(obj *things_test_io_v1.Paint) (reconcile.Result, error) + OnReconcilePaintDeletion func(req reconcile.Request) error } func (f *PaintReconcilerFuncs) ReconcilePaint(obj *things_test_io_v1.Paint) (reconcile.Result, error) { - if f.OnReconcilePaint == nil { - return reconcile.Result{}, nil - } - return f.OnReconcilePaint(obj) + if f.OnReconcilePaint == nil { + return reconcile.Result{}, nil + } + return f.OnReconcilePaint(obj) } func (f *PaintReconcilerFuncs) ReconcilePaintDeletion(req reconcile.Request) error { - if f.OnReconcilePaintDeletion == nil { - return nil - } - return f.OnReconcilePaintDeletion(req) + if f.OnReconcilePaintDeletion == nil { + return nil + } + return f.OnReconcilePaintDeletion(req) } // Reconcile and finalize the Paint Resource // implemented by the user type PaintFinalizer interface { - PaintReconciler + PaintReconciler - // name of the finalizer used by this handler. - // finalizer names should be unique for a single task - PaintFinalizerName() string + // name of the finalizer used by this handler. + // finalizer names should be unique for a single task + PaintFinalizerName() string - // finalize the object before it is deleted. - // Watchers created with a finalizing handler will a - FinalizePaint(obj *things_test_io_v1.Paint) error + // finalize the object before it is deleted. + // Watchers created with a finalizing handler will a + FinalizePaint(obj *things_test_io_v1.Paint) error } type PaintReconcileLoop interface { - RunPaintReconciler(ctx context.Context, rec PaintReconciler, predicates ...predicate.Predicate) error + RunPaintReconciler(ctx context.Context, rec PaintReconciler, predicates ...predicate.Predicate) error } type paintReconcileLoop struct { - loop reconcile.Loop + loop reconcile.Loop } func NewPaintReconcileLoop(name string, mgr manager.Manager, options reconcile.Options) PaintReconcileLoop { - return &paintReconcileLoop{ - // empty cluster indicates this reconciler is built for the local cluster - loop: reconcile.NewLoop(name, "", mgr, &things_test_io_v1.Paint{}, options), - } + return &paintReconcileLoop{ + // empty cluster indicates this reconciler is built for the local cluster + loop: reconcile.NewLoop(name, "", mgr, &things_test_io_v1.Paint{}, options), + } } func (c *paintReconcileLoop) RunPaintReconciler(ctx context.Context, reconciler PaintReconciler, predicates ...predicate.Predicate) error { - genericReconciler := genericPaintReconciler{ - reconciler: reconciler, - } + genericReconciler := genericPaintReconciler{ + reconciler: reconciler, + } var reconcilerWrapper reconcile.Reconciler if finalizingReconciler, ok := reconciler.(PaintFinalizer); ok { - reconcilerWrapper = genericPaintFinalizer{ - genericPaintReconciler: genericReconciler, - finalizingReconciler: finalizingReconciler, - } - } else { - reconcilerWrapper = genericReconciler - } + reconcilerWrapper = genericPaintFinalizer{ + genericPaintReconciler: genericReconciler, + finalizingReconciler: finalizingReconciler, + } + } else { + reconcilerWrapper = genericReconciler + } return c.loop.RunReconciler(ctx, reconcilerWrapper, predicates...) } // genericPaintHandler implements a generic reconcile.Reconciler type genericPaintReconciler struct { - reconciler PaintReconciler + reconciler PaintReconciler } func (r genericPaintReconciler) Reconcile(object ezkube.Object) (reconcile.Result, error) { - obj, ok := object.(*things_test_io_v1.Paint) - if !ok { - return reconcile.Result{}, errors.Errorf("internal error: Paint handler received event for %T", object) - } - return r.reconciler.ReconcilePaint(obj) + obj, ok := object.(*things_test_io_v1.Paint) + if !ok { + return reconcile.Result{}, errors.Errorf("internal error: Paint handler received event for %T", object) + } + return r.reconciler.ReconcilePaint(obj) } func (r genericPaintReconciler) ReconcileDeletion(request reconcile.Request) error { - if deletionReconciler, ok := r.reconciler.(PaintDeletionReconciler); ok { - return deletionReconciler.ReconcilePaintDeletion(request) - } - return nil + if deletionReconciler, ok := r.reconciler.(PaintDeletionReconciler); ok { + return deletionReconciler.ReconcilePaintDeletion(request) + } + return nil } // genericPaintFinalizer implements a generic reconcile.FinalizingReconciler type genericPaintFinalizer struct { - genericPaintReconciler - finalizingReconciler PaintFinalizer + genericPaintReconciler + finalizingReconciler PaintFinalizer } + func (r genericPaintFinalizer) FinalizerName() string { - return r.finalizingReconciler.PaintFinalizerName() + return r.finalizingReconciler.PaintFinalizerName() } func (r genericPaintFinalizer) Finalize(object ezkube.Object) error { - obj, ok := object.(*things_test_io_v1.Paint) - if !ok { - return errors.Errorf("internal error: Paint handler received event for %T", object) - } - return r.finalizingReconciler.FinalizePaint(obj) + obj, ok := object.(*things_test_io_v1.Paint) + if !ok { + return errors.Errorf("internal error: Paint handler received event for %T", object) + } + return r.finalizingReconciler.FinalizePaint(obj) } // Reconcile Upsert events for the ClusterResource Resource. // implemented by the user type ClusterResourceReconciler interface { - ReconcileClusterResource(obj *things_test_io_v1.ClusterResource) (reconcile.Result, error) + ReconcileClusterResource(obj *things_test_io_v1.ClusterResource) (reconcile.Result, error) } // Reconcile deletion events for the ClusterResource Resource. @@ -145,108 +148,109 @@ type ClusterResourceReconciler interface { // before being deleted. // implemented by the user type ClusterResourceDeletionReconciler interface { - ReconcileClusterResourceDeletion(req reconcile.Request) error + ReconcileClusterResourceDeletion(req reconcile.Request) error } type ClusterResourceReconcilerFuncs struct { - OnReconcileClusterResource func(obj *things_test_io_v1.ClusterResource) (reconcile.Result, error) - OnReconcileClusterResourceDeletion func(req reconcile.Request) error + OnReconcileClusterResource func(obj *things_test_io_v1.ClusterResource) (reconcile.Result, error) + OnReconcileClusterResourceDeletion func(req reconcile.Request) error } func (f *ClusterResourceReconcilerFuncs) ReconcileClusterResource(obj *things_test_io_v1.ClusterResource) (reconcile.Result, error) { - if f.OnReconcileClusterResource == nil { - return reconcile.Result{}, nil - } - return f.OnReconcileClusterResource(obj) + if f.OnReconcileClusterResource == nil { + return reconcile.Result{}, nil + } + return f.OnReconcileClusterResource(obj) } func (f *ClusterResourceReconcilerFuncs) ReconcileClusterResourceDeletion(req reconcile.Request) error { - if f.OnReconcileClusterResourceDeletion == nil { - return nil - } - return f.OnReconcileClusterResourceDeletion(req) + if f.OnReconcileClusterResourceDeletion == nil { + return nil + } + return f.OnReconcileClusterResourceDeletion(req) } // Reconcile and finalize the ClusterResource Resource // implemented by the user type ClusterResourceFinalizer interface { - ClusterResourceReconciler + ClusterResourceReconciler - // name of the finalizer used by this handler. - // finalizer names should be unique for a single task - ClusterResourceFinalizerName() string + // name of the finalizer used by this handler. + // finalizer names should be unique for a single task + ClusterResourceFinalizerName() string - // finalize the object before it is deleted. - // Watchers created with a finalizing handler will a - FinalizeClusterResource(obj *things_test_io_v1.ClusterResource) error + // finalize the object before it is deleted. + // Watchers created with a finalizing handler will a + FinalizeClusterResource(obj *things_test_io_v1.ClusterResource) error } type ClusterResourceReconcileLoop interface { - RunClusterResourceReconciler(ctx context.Context, rec ClusterResourceReconciler, predicates ...predicate.Predicate) error + RunClusterResourceReconciler(ctx context.Context, rec ClusterResourceReconciler, predicates ...predicate.Predicate) error } type clusterResourceReconcileLoop struct { - loop reconcile.Loop + loop reconcile.Loop } func NewClusterResourceReconcileLoop(name string, mgr manager.Manager, options reconcile.Options) ClusterResourceReconcileLoop { - return &clusterResourceReconcileLoop{ - // empty cluster indicates this reconciler is built for the local cluster - loop: reconcile.NewLoop(name, "", mgr, &things_test_io_v1.ClusterResource{}, options), - } + return &clusterResourceReconcileLoop{ + // empty cluster indicates this reconciler is built for the local cluster + loop: reconcile.NewLoop(name, "", mgr, &things_test_io_v1.ClusterResource{}, options), + } } func (c *clusterResourceReconcileLoop) RunClusterResourceReconciler(ctx context.Context, reconciler ClusterResourceReconciler, predicates ...predicate.Predicate) error { - genericReconciler := genericClusterResourceReconciler{ - reconciler: reconciler, - } + genericReconciler := genericClusterResourceReconciler{ + reconciler: reconciler, + } var reconcilerWrapper reconcile.Reconciler if finalizingReconciler, ok := reconciler.(ClusterResourceFinalizer); ok { - reconcilerWrapper = genericClusterResourceFinalizer{ - genericClusterResourceReconciler: genericReconciler, - finalizingReconciler: finalizingReconciler, - } - } else { - reconcilerWrapper = genericReconciler - } + reconcilerWrapper = genericClusterResourceFinalizer{ + genericClusterResourceReconciler: genericReconciler, + finalizingReconciler: finalizingReconciler, + } + } else { + reconcilerWrapper = genericReconciler + } return c.loop.RunReconciler(ctx, reconcilerWrapper, predicates...) } // genericClusterResourceHandler implements a generic reconcile.Reconciler type genericClusterResourceReconciler struct { - reconciler ClusterResourceReconciler + reconciler ClusterResourceReconciler } func (r genericClusterResourceReconciler) Reconcile(object ezkube.Object) (reconcile.Result, error) { - obj, ok := object.(*things_test_io_v1.ClusterResource) - if !ok { - return reconcile.Result{}, errors.Errorf("internal error: ClusterResource handler received event for %T", object) - } - return r.reconciler.ReconcileClusterResource(obj) + obj, ok := object.(*things_test_io_v1.ClusterResource) + if !ok { + return reconcile.Result{}, errors.Errorf("internal error: ClusterResource handler received event for %T", object) + } + return r.reconciler.ReconcileClusterResource(obj) } func (r genericClusterResourceReconciler) ReconcileDeletion(request reconcile.Request) error { - if deletionReconciler, ok := r.reconciler.(ClusterResourceDeletionReconciler); ok { - return deletionReconciler.ReconcileClusterResourceDeletion(request) - } - return nil + if deletionReconciler, ok := r.reconciler.(ClusterResourceDeletionReconciler); ok { + return deletionReconciler.ReconcileClusterResourceDeletion(request) + } + return nil } // genericClusterResourceFinalizer implements a generic reconcile.FinalizingReconciler type genericClusterResourceFinalizer struct { - genericClusterResourceReconciler - finalizingReconciler ClusterResourceFinalizer + genericClusterResourceReconciler + finalizingReconciler ClusterResourceFinalizer } + func (r genericClusterResourceFinalizer) FinalizerName() string { - return r.finalizingReconciler.ClusterResourceFinalizerName() + return r.finalizingReconciler.ClusterResourceFinalizerName() } func (r genericClusterResourceFinalizer) Finalize(object ezkube.Object) error { - obj, ok := object.(*things_test_io_v1.ClusterResource) - if !ok { - return errors.Errorf("internal error: ClusterResource handler received event for %T", object) - } - return r.finalizingReconciler.FinalizeClusterResource(obj) + obj, ok := object.(*things_test_io_v1.ClusterResource) + if !ok { + return errors.Errorf("internal error: ClusterResource handler received event for %T", object) + } + return r.finalizingReconciler.FinalizeClusterResource(obj) } diff --git a/codegen/test/api/things.test.io/v1/json.gen.go b/codegen/test/api/things.test.io/v1/json.gen.go index d8b4c1b0b..d7582f228 100644 --- a/codegen/test/api/things.test.io/v1/json.gen.go +++ b/codegen/test/api/things.test.io/v1/json.gen.go @@ -5,13 +5,13 @@ package v1 import ( - bytes "bytes" - fmt "fmt" - math "math" + bytes "bytes" + fmt "fmt" + math "math" - jsonpb "github.com/golang/protobuf/jsonpb" - proto "github.com/golang/protobuf/proto" - skv2jsonpb "github.com/solo-io/skv2/pkg/kube_jsonpb" + skv2jsonpb "github.com/solo-io/skv2/pkg/kube_jsonpb" + jsonpb "github.com/golang/protobuf/jsonpb" + proto "github.com/golang/protobuf/proto" ) // Reference imports to suppress errors if they are not otherwise used. @@ -20,13 +20,12 @@ var _ = fmt.Errorf var _ = math.Inf var ( - marshaller = &skv2jsonpb.Marshaler{} + marshaller = &skv2jsonpb.Marshaler{} unmarshaller = &jsonpb.Unmarshaler{ AllowUnknownFields: true, } strictUnmarshaller = &jsonpb.Unmarshaler{} ) - // MarshalJSON is a custom marshaler for PaintSpec func (this *PaintSpec) MarshalJSON() ([]byte, error) { str, err := marshaller.MarshalToString(this) @@ -37,7 +36,6 @@ func (this *PaintSpec) MarshalJSON() ([]byte, error) { func (this *PaintSpec) UnmarshalJSON(b []byte) error { return unmarshaller.Unmarshal(bytes.NewReader(b), this) } - // MarshalJSON is a custom marshaler for PaintStatus func (this *PaintStatus) MarshalJSON() ([]byte, error) { str, err := marshaller.MarshalToString(this) @@ -48,7 +46,6 @@ func (this *PaintStatus) MarshalJSON() ([]byte, error) { func (this *PaintStatus) UnmarshalJSON(b []byte) error { return unmarshaller.Unmarshal(bytes.NewReader(b), this) } - // MarshalJSON is a custom marshaler for ClusterResourceSpec func (this *ClusterResourceSpec) MarshalJSON() ([]byte, error) { str, err := marshaller.MarshalToString(this) diff --git a/codegen/test/api/things.test.io/v1/proto_deepcopy.go b/codegen/test/api/things.test.io/v1/proto_deepcopy.go index 7fe7a023f..30d4d08c0 100644 --- a/codegen/test/api/things.test.io/v1/proto_deepcopy.go +++ b/codegen/test/api/things.test.io/v1/proto_deepcopy.go @@ -5,39 +5,36 @@ package v1 import ( - proto "github.com/golang/protobuf/proto" + proto "github.com/golang/protobuf/proto" "github.com/solo-io/protoc-gen-ext/pkg/clone" ) - // DeepCopyInto for the Paint.Spec func (in *PaintSpec) DeepCopyInto(out *PaintSpec) { - var p *PaintSpec - if h, ok := interface{}(in).(clone.Cloner); ok { - p = h.Clone().(*PaintSpec) - } else { - p = proto.Clone(in).(*PaintSpec) - } - *out = *p + var p *PaintSpec + if h, ok := interface{}(in).(clone.Cloner); ok { + p = h.Clone().(*PaintSpec) + } else { + p = proto.Clone(in).(*PaintSpec) + } + *out = *p } - // DeepCopyInto for the Paint.Status func (in *PaintStatus) DeepCopyInto(out *PaintStatus) { - var p *PaintStatus - if h, ok := interface{}(in).(clone.Cloner); ok { - p = h.Clone().(*PaintStatus) - } else { - p = proto.Clone(in).(*PaintStatus) - } - *out = *p + var p *PaintStatus + if h, ok := interface{}(in).(clone.Cloner); ok { + p = h.Clone().(*PaintStatus) + } else { + p = proto.Clone(in).(*PaintStatus) + } + *out = *p } - // DeepCopyInto for the ClusterResource.Spec func (in *ClusterResourceSpec) DeepCopyInto(out *ClusterResourceSpec) { - var p *ClusterResourceSpec - if h, ok := interface{}(in).(clone.Cloner); ok { - p = h.Clone().(*ClusterResourceSpec) - } else { - p = proto.Clone(in).(*ClusterResourceSpec) - } - *out = *p + var p *ClusterResourceSpec + if h, ok := interface{}(in).(clone.Cloner); ok { + p = h.Clone().(*ClusterResourceSpec) + } else { + p = proto.Clone(in).(*ClusterResourceSpec) + } + *out = *p } diff --git a/codegen/test/api/things.test.io/v1/providers/client_providers.go b/codegen/test/api/things.test.io/v1/providers/client_providers.go index ea1c91a28..53570c869 100644 --- a/codegen/test/api/things.test.io/v1/providers/client_providers.go +++ b/codegen/test/api/things.test.io/v1/providers/client_providers.go @@ -2,11 +2,13 @@ package v1 + + import ( - things_test_io_v1 "github.com/solo-io/skv2/codegen/test/api/things.test.io/v1" + things_test_io_v1 "github.com/solo-io/skv2/codegen/test/api/things.test.io/v1" - "k8s.io/client-go/rest" - "sigs.k8s.io/controller-runtime/pkg/client" + "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/client" ) /* @@ -19,56 +21,56 @@ import ( // Provider for PaintClient from Clientset func PaintClientFromClientsetProvider(clients things_test_io_v1.Clientset) things_test_io_v1.PaintClient { - return clients.Paints() + return clients.Paints() } // Provider for Paint Client from Client func PaintClientProvider(client client.Client) things_test_io_v1.PaintClient { - return things_test_io_v1.NewPaintClient(client) + return things_test_io_v1.NewPaintClient(client) } type PaintClientFactory func(client client.Client) things_test_io_v1.PaintClient func PaintClientFactoryProvider() PaintClientFactory { - return PaintClientProvider + return PaintClientProvider } type PaintClientFromConfigFactory func(cfg *rest.Config) (things_test_io_v1.PaintClient, error) func PaintClientFromConfigFactoryProvider() PaintClientFromConfigFactory { - return func(cfg *rest.Config) (things_test_io_v1.PaintClient, error) { - clients, err := things_test_io_v1.NewClientsetFromConfig(cfg) - if err != nil { - return nil, err - } - return clients.Paints(), nil - } + return func(cfg *rest.Config) (things_test_io_v1.PaintClient, error) { + clients, err := things_test_io_v1.NewClientsetFromConfig(cfg) + if err != nil { + return nil, err + } + return clients.Paints(), nil + } } // Provider for ClusterResourceClient from Clientset func ClusterResourceClientFromClientsetProvider(clients things_test_io_v1.Clientset) things_test_io_v1.ClusterResourceClient { - return clients.ClusterResources() + return clients.ClusterResources() } // Provider for ClusterResource Client from Client func ClusterResourceClientProvider(client client.Client) things_test_io_v1.ClusterResourceClient { - return things_test_io_v1.NewClusterResourceClient(client) + return things_test_io_v1.NewClusterResourceClient(client) } type ClusterResourceClientFactory func(client client.Client) things_test_io_v1.ClusterResourceClient func ClusterResourceClientFactoryProvider() ClusterResourceClientFactory { - return ClusterResourceClientProvider + return ClusterResourceClientProvider } type ClusterResourceClientFromConfigFactory func(cfg *rest.Config) (things_test_io_v1.ClusterResourceClient, error) func ClusterResourceClientFromConfigFactoryProvider() ClusterResourceClientFromConfigFactory { - return func(cfg *rest.Config) (things_test_io_v1.ClusterResourceClient, error) { - clients, err := things_test_io_v1.NewClientsetFromConfig(cfg) - if err != nil { - return nil, err - } - return clients.ClusterResources(), nil - } -} + return func(cfg *rest.Config) (things_test_io_v1.ClusterResourceClient, error) { + clients, err := things_test_io_v1.NewClientsetFromConfig(cfg) + if err != nil { + return nil, err + } + return clients.ClusterResources(), nil + } +} \ No newline at end of file diff --git a/codegen/test/api/things.test.io/v1/register.go b/codegen/test/api/things.test.io/v1/register.go index 38bbf15c1..99e1def72 100644 --- a/codegen/test/api/things.test.io/v1/register.go +++ b/codegen/test/api/things.test.io/v1/register.go @@ -6,9 +6,9 @@ package v1 import ( - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "sigs.k8s.io/controller-runtime/pkg/scheme" + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" + "k8s.io/apimachinery/pkg/runtime" ) // AddToSchemes may be used to add all resources defined in the project to a Scheme @@ -16,18 +16,19 @@ import ( // AddToScheme adds all Resources to the Scheme var ( - // SchemeGroupVersion is group version used to register these objects - SchemeGroupVersion = schema.GroupVersion{Group: "things.test.io", Version: "v1"} + // SchemeGroupVersion is group version used to register these objects + SchemeGroupVersion = schema.GroupVersion{Group: "things.test.io", Version: "v1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} - // SchemeBuilder is used to add go types to the GroupVersionKind scheme - SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} ) // Resource takes an unqualified resource and returns a Group qualified GroupResource func Resource(resource string) schema.GroupResource { - return SchemeGroupVersion.WithResource(resource).GroupResource() + return SchemeGroupVersion.WithResource(resource).GroupResource() } func AddToScheme(s *runtime.Scheme) error { - return SchemeBuilder.AddToScheme(s) + return SchemeBuilder.AddToScheme(s) } diff --git a/codegen/test/api/things.test.io/v1/sets/sets.go b/codegen/test/api/things.test.io/v1/sets/sets.go index 73703a3cd..8e9cb54fb 100644 --- a/codegen/test/api/things.test.io/v1/sets/sets.go +++ b/codegen/test/api/things.test.io/v1/sets/sets.go @@ -4,229 +4,232 @@ package v1sets + + import ( - things_test_io_v1 "github.com/solo-io/skv2/codegen/test/api/things.test.io/v1" + things_test_io_v1 "github.com/solo-io/skv2/codegen/test/api/things.test.io/v1" - "github.com/rotisserie/eris" - sksets "github.com/solo-io/skv2/contrib/pkg/sets" - "github.com/solo-io/skv2/pkg/ezkube" - "k8s.io/apimachinery/pkg/util/sets" + "github.com/rotisserie/eris" + sksets "github.com/solo-io/skv2/contrib/pkg/sets" + "github.com/solo-io/skv2/pkg/ezkube" + "k8s.io/apimachinery/pkg/util/sets" ) type PaintSet interface { // Get the set stored keys - Keys() sets.String - // List of resources stored in the set. Pass an optional filter function to filter on the list. - // The filter function should return false to keep the resource, true to drop it. - List(filterResource ...func(*things_test_io_v1.Paint) bool) []*things_test_io_v1.Paint - // Unsorted list of resources stored in the set. Pass an optional filter function to filter on the list. - // The filter function should return false to keep the resource, true to drop it. - UnsortedList(filterResource ...func(*things_test_io_v1.Paint) bool) []*things_test_io_v1.Paint - // Return the Set as a map of key to resource. - Map() map[string]*things_test_io_v1.Paint - // Insert a resource into the set. - Insert(paint ...*things_test_io_v1.Paint) - // Compare the equality of the keys in two sets (not the resources themselves) - Equal(paintSet PaintSet) bool - // Check if the set contains a key matching the resource (not the resource itself) - Has(paint ezkube.ResourceId) bool - // Delete the key matching the resource - Delete(paint ezkube.ResourceId) - // Return the union with the provided set - Union(set PaintSet) PaintSet - // Return the difference with the provided set - Difference(set PaintSet) PaintSet - // Return the intersection with the provided set - Intersection(set PaintSet) PaintSet - // Find the resource with the given ID - Find(id ezkube.ResourceId) (*things_test_io_v1.Paint, error) - // Get the length of the set - Length() int - // returns the generic implementation of the set - Generic() sksets.ResourceSet - // returns the delta between this and and another PaintSet - Delta(newSet PaintSet) sksets.ResourceDelta - // Create a deep copy of the current PaintSet - Clone() PaintSet + Keys() sets.String + // List of resources stored in the set. Pass an optional filter function to filter on the list. + // The filter function should return false to keep the resource, true to drop it. + List(filterResource ... func(*things_test_io_v1.Paint) bool) []*things_test_io_v1.Paint + // Unsorted list of resources stored in the set. Pass an optional filter function to filter on the list. + // The filter function should return false to keep the resource, true to drop it. + UnsortedList(filterResource ... func(*things_test_io_v1.Paint) bool) []*things_test_io_v1.Paint + // Return the Set as a map of key to resource. + Map() map[string]*things_test_io_v1.Paint + // Insert a resource into the set. + Insert(paint ...*things_test_io_v1.Paint) + // Compare the equality of the keys in two sets (not the resources themselves) + Equal(paintSet PaintSet) bool + // Check if the set contains a key matching the resource (not the resource itself) + Has(paint ezkube.ResourceId) bool + // Delete the key matching the resource + Delete(paint ezkube.ResourceId) + // Return the union with the provided set + Union(set PaintSet) PaintSet + // Return the difference with the provided set + Difference(set PaintSet) PaintSet + // Return the intersection with the provided set + Intersection(set PaintSet) PaintSet + // Find the resource with the given ID + Find(id ezkube.ResourceId) (*things_test_io_v1.Paint, error) + // Get the length of the set + Length() int + // returns the generic implementation of the set + Generic() sksets.ResourceSet + // returns the delta between this and and another PaintSet + Delta(newSet PaintSet) sksets.ResourceDelta + // Create a deep copy of the current PaintSet + Clone() PaintSet } func makeGenericPaintSet(paintList []*things_test_io_v1.Paint) sksets.ResourceSet { - var genericResources []ezkube.ResourceId - for _, obj := range paintList { - genericResources = append(genericResources, obj) - } - return sksets.NewResourceSet(genericResources...) + var genericResources []ezkube.ResourceId + for _, obj := range paintList { + genericResources = append(genericResources, obj) + } + return sksets.NewResourceSet(genericResources...) } type paintSet struct { - set sksets.ResourceSet + set sksets.ResourceSet } func NewPaintSet(paintList ...*things_test_io_v1.Paint) PaintSet { - return &paintSet{set: makeGenericPaintSet(paintList)} + return &paintSet{set: makeGenericPaintSet(paintList)} } func NewPaintSetFromList(paintList *things_test_io_v1.PaintList) PaintSet { - list := make([]*things_test_io_v1.Paint, 0, len(paintList.Items)) - for idx := range paintList.Items { - list = append(list, &paintList.Items[idx]) - } - return &paintSet{set: makeGenericPaintSet(list)} + list := make([]*things_test_io_v1.Paint, 0, len(paintList.Items)) + for idx := range paintList.Items { + list = append(list, &paintList.Items[idx]) + } + return &paintSet{set: makeGenericPaintSet(list)} } func (s *paintSet) Keys() sets.String { if s == nil { return sets.String{} - } - return s.Generic().Keys() -} - -func (s *paintSet) List(filterResource ...func(*things_test_io_v1.Paint) bool) []*things_test_io_v1.Paint { - if s == nil { - return nil - } - var genericFilters []func(ezkube.ResourceId) bool - for _, filter := range filterResource { - filter := filter - genericFilters = append(genericFilters, func(obj ezkube.ResourceId) bool { - return filter(obj.(*things_test_io_v1.Paint)) - }) - } - - objs := s.Generic().List(genericFilters...) - paintList := make([]*things_test_io_v1.Paint, 0, len(objs)) - for _, obj := range objs { - paintList = append(paintList, obj.(*things_test_io_v1.Paint)) - } - return paintList -} - -func (s *paintSet) UnsortedList(filterResource ...func(*things_test_io_v1.Paint) bool) []*things_test_io_v1.Paint { - if s == nil { - return nil - } - var genericFilters []func(ezkube.ResourceId) bool - for _, filter := range filterResource { - filter := filter - genericFilters = append(genericFilters, func(obj ezkube.ResourceId) bool { - return filter(obj.(*things_test_io_v1.Paint)) - }) - } - - var paintList []*things_test_io_v1.Paint - for _, obj := range s.Generic().UnsortedList(genericFilters...) { - paintList = append(paintList, obj.(*things_test_io_v1.Paint)) - } - return paintList + } + return s.Generic().Keys() +} + +func (s *paintSet) List(filterResource ... func(*things_test_io_v1.Paint) bool) []*things_test_io_v1.Paint { + if s == nil { + return nil + } + var genericFilters []func(ezkube.ResourceId) bool + for _, filter := range filterResource { + filter := filter + genericFilters = append(genericFilters, func(obj ezkube.ResourceId) bool { + return filter(obj.(*things_test_io_v1.Paint)) + }) + } + + objs := s.Generic().List(genericFilters...) + paintList := make([]*things_test_io_v1.Paint, 0, len(objs)) + for _, obj := range objs { + paintList = append(paintList, obj.(*things_test_io_v1.Paint)) + } + return paintList +} + +func (s *paintSet) UnsortedList(filterResource ... func(*things_test_io_v1.Paint) bool) []*things_test_io_v1.Paint { + if s == nil { + return nil + } + var genericFilters []func(ezkube.ResourceId) bool + for _, filter := range filterResource { + filter := filter + genericFilters = append(genericFilters, func(obj ezkube.ResourceId) bool { + return filter(obj.(*things_test_io_v1.Paint)) + }) + } + + var paintList []*things_test_io_v1.Paint + for _, obj := range s.Generic().UnsortedList(genericFilters...) { + paintList = append(paintList, obj.(*things_test_io_v1.Paint)) + } + return paintList } func (s *paintSet) Map() map[string]*things_test_io_v1.Paint { - if s == nil { - return nil - } + if s == nil { + return nil + } - newMap := map[string]*things_test_io_v1.Paint{} - for k, v := range s.Generic().Map() { - newMap[k] = v.(*things_test_io_v1.Paint) - } - return newMap + newMap := map[string]*things_test_io_v1.Paint{} + for k, v := range s.Generic().Map() { + newMap[k] = v.(*things_test_io_v1.Paint) + } + return newMap } func (s *paintSet) Insert( - paintList ...*things_test_io_v1.Paint, + paintList ...*things_test_io_v1.Paint, ) { - if s == nil { - panic("cannot insert into nil set") - } + if s == nil { + panic("cannot insert into nil set") + } - for _, obj := range paintList { - s.Generic().Insert(obj) - } + for _, obj := range paintList { + s.Generic().Insert(obj) + } } func (s *paintSet) Has(paint ezkube.ResourceId) bool { - if s == nil { - return false - } - return s.Generic().Has(paint) + if s == nil { + return false + } + return s.Generic().Has(paint) } func (s *paintSet) Equal( - paintSet PaintSet, + paintSet PaintSet, ) bool { - if s == nil { - return paintSet == nil - } - return s.Generic().Equal(paintSet.Generic()) + if s == nil { + return paintSet == nil + } + return s.Generic().Equal(paintSet.Generic()) } func (s *paintSet) Delete(Paint ezkube.ResourceId) { - if s == nil { - return - } - s.Generic().Delete(Paint) + if s == nil { + return + } + s.Generic().Delete(Paint) } func (s *paintSet) Union(set PaintSet) PaintSet { - if s == nil { - return set - } - return NewPaintSet(append(s.List(), set.List()...)...) + if s == nil { + return set + } + return NewPaintSet(append(s.List(), set.List()...)...) } func (s *paintSet) Difference(set PaintSet) PaintSet { - if s == nil { - return set - } - newSet := s.Generic().Difference(set.Generic()) - return &paintSet{set: newSet} + if s == nil { + return set + } + newSet := s.Generic().Difference(set.Generic()) + return &paintSet{set: newSet} } func (s *paintSet) Intersection(set PaintSet) PaintSet { - if s == nil { - return nil - } - newSet := s.Generic().Intersection(set.Generic()) - var paintList []*things_test_io_v1.Paint - for _, obj := range newSet.List() { - paintList = append(paintList, obj.(*things_test_io_v1.Paint)) - } - return NewPaintSet(paintList...) + if s == nil { + return nil + } + newSet := s.Generic().Intersection(set.Generic()) + var paintList []*things_test_io_v1.Paint + for _, obj := range newSet.List() { + paintList = append(paintList, obj.(*things_test_io_v1.Paint)) + } + return NewPaintSet(paintList...) } + func (s *paintSet) Find(id ezkube.ResourceId) (*things_test_io_v1.Paint, error) { - if s == nil { - return nil, eris.Errorf("empty set, cannot find Paint %v", sksets.Key(id)) - } + if s == nil { + return nil, eris.Errorf("empty set, cannot find Paint %v", sksets.Key(id)) + } obj, err := s.Generic().Find(&things_test_io_v1.Paint{}, id) if err != nil { return nil, err - } + } - return obj.(*things_test_io_v1.Paint), nil + return obj.(*things_test_io_v1.Paint), nil } func (s *paintSet) Length() int { - if s == nil { - return 0 - } - return s.Generic().Length() + if s == nil { + return 0 + } + return s.Generic().Length() } func (s *paintSet) Generic() sksets.ResourceSet { - if s == nil { - return nil - } - return s.set + if s == nil { + return nil + } + return s.set } func (s *paintSet) Delta(newSet PaintSet) sksets.ResourceDelta { - if s == nil { - return sksets.ResourceDelta{ - Inserted: newSet.Generic(), - } - } - return s.Generic().Delta(newSet.Generic()) + if s == nil { + return sksets.ResourceDelta{ + Inserted: newSet.Generic(), + } + } + return s.Generic().Delta(newSet.Generic()) } func (s *paintSet) Clone() PaintSet { @@ -238,218 +241,219 @@ func (s *paintSet) Clone() PaintSet { type ClusterResourceSet interface { // Get the set stored keys - Keys() sets.String - // List of resources stored in the set. Pass an optional filter function to filter on the list. - // The filter function should return false to keep the resource, true to drop it. - List(filterResource ...func(*things_test_io_v1.ClusterResource) bool) []*things_test_io_v1.ClusterResource - // Unsorted list of resources stored in the set. Pass an optional filter function to filter on the list. - // The filter function should return false to keep the resource, true to drop it. - UnsortedList(filterResource ...func(*things_test_io_v1.ClusterResource) bool) []*things_test_io_v1.ClusterResource - // Return the Set as a map of key to resource. - Map() map[string]*things_test_io_v1.ClusterResource - // Insert a resource into the set. - Insert(clusterResource ...*things_test_io_v1.ClusterResource) - // Compare the equality of the keys in two sets (not the resources themselves) - Equal(clusterResourceSet ClusterResourceSet) bool - // Check if the set contains a key matching the resource (not the resource itself) - Has(clusterResource ezkube.ResourceId) bool - // Delete the key matching the resource - Delete(clusterResource ezkube.ResourceId) - // Return the union with the provided set - Union(set ClusterResourceSet) ClusterResourceSet - // Return the difference with the provided set - Difference(set ClusterResourceSet) ClusterResourceSet - // Return the intersection with the provided set - Intersection(set ClusterResourceSet) ClusterResourceSet - // Find the resource with the given ID - Find(id ezkube.ResourceId) (*things_test_io_v1.ClusterResource, error) - // Get the length of the set - Length() int - // returns the generic implementation of the set - Generic() sksets.ResourceSet - // returns the delta between this and and another ClusterResourceSet - Delta(newSet ClusterResourceSet) sksets.ResourceDelta - // Create a deep copy of the current ClusterResourceSet - Clone() ClusterResourceSet + Keys() sets.String + // List of resources stored in the set. Pass an optional filter function to filter on the list. + // The filter function should return false to keep the resource, true to drop it. + List(filterResource ... func(*things_test_io_v1.ClusterResource) bool) []*things_test_io_v1.ClusterResource + // Unsorted list of resources stored in the set. Pass an optional filter function to filter on the list. + // The filter function should return false to keep the resource, true to drop it. + UnsortedList(filterResource ... func(*things_test_io_v1.ClusterResource) bool) []*things_test_io_v1.ClusterResource + // Return the Set as a map of key to resource. + Map() map[string]*things_test_io_v1.ClusterResource + // Insert a resource into the set. + Insert(clusterResource ...*things_test_io_v1.ClusterResource) + // Compare the equality of the keys in two sets (not the resources themselves) + Equal(clusterResourceSet ClusterResourceSet) bool + // Check if the set contains a key matching the resource (not the resource itself) + Has(clusterResource ezkube.ResourceId) bool + // Delete the key matching the resource + Delete(clusterResource ezkube.ResourceId) + // Return the union with the provided set + Union(set ClusterResourceSet) ClusterResourceSet + // Return the difference with the provided set + Difference(set ClusterResourceSet) ClusterResourceSet + // Return the intersection with the provided set + Intersection(set ClusterResourceSet) ClusterResourceSet + // Find the resource with the given ID + Find(id ezkube.ResourceId) (*things_test_io_v1.ClusterResource, error) + // Get the length of the set + Length() int + // returns the generic implementation of the set + Generic() sksets.ResourceSet + // returns the delta between this and and another ClusterResourceSet + Delta(newSet ClusterResourceSet) sksets.ResourceDelta + // Create a deep copy of the current ClusterResourceSet + Clone() ClusterResourceSet } func makeGenericClusterResourceSet(clusterResourceList []*things_test_io_v1.ClusterResource) sksets.ResourceSet { - var genericResources []ezkube.ResourceId - for _, obj := range clusterResourceList { - genericResources = append(genericResources, obj) - } - return sksets.NewResourceSet(genericResources...) + var genericResources []ezkube.ResourceId + for _, obj := range clusterResourceList { + genericResources = append(genericResources, obj) + } + return sksets.NewResourceSet(genericResources...) } type clusterResourceSet struct { - set sksets.ResourceSet + set sksets.ResourceSet } func NewClusterResourceSet(clusterResourceList ...*things_test_io_v1.ClusterResource) ClusterResourceSet { - return &clusterResourceSet{set: makeGenericClusterResourceSet(clusterResourceList)} + return &clusterResourceSet{set: makeGenericClusterResourceSet(clusterResourceList)} } func NewClusterResourceSetFromList(clusterResourceList *things_test_io_v1.ClusterResourceList) ClusterResourceSet { - list := make([]*things_test_io_v1.ClusterResource, 0, len(clusterResourceList.Items)) - for idx := range clusterResourceList.Items { - list = append(list, &clusterResourceList.Items[idx]) - } - return &clusterResourceSet{set: makeGenericClusterResourceSet(list)} + list := make([]*things_test_io_v1.ClusterResource, 0, len(clusterResourceList.Items)) + for idx := range clusterResourceList.Items { + list = append(list, &clusterResourceList.Items[idx]) + } + return &clusterResourceSet{set: makeGenericClusterResourceSet(list)} } func (s *clusterResourceSet) Keys() sets.String { if s == nil { return sets.String{} - } - return s.Generic().Keys() -} - -func (s *clusterResourceSet) List(filterResource ...func(*things_test_io_v1.ClusterResource) bool) []*things_test_io_v1.ClusterResource { - if s == nil { - return nil - } - var genericFilters []func(ezkube.ResourceId) bool - for _, filter := range filterResource { - filter := filter - genericFilters = append(genericFilters, func(obj ezkube.ResourceId) bool { - return filter(obj.(*things_test_io_v1.ClusterResource)) - }) - } - - objs := s.Generic().List(genericFilters...) - clusterResourceList := make([]*things_test_io_v1.ClusterResource, 0, len(objs)) - for _, obj := range objs { - clusterResourceList = append(clusterResourceList, obj.(*things_test_io_v1.ClusterResource)) - } - return clusterResourceList -} - -func (s *clusterResourceSet) UnsortedList(filterResource ...func(*things_test_io_v1.ClusterResource) bool) []*things_test_io_v1.ClusterResource { - if s == nil { - return nil - } - var genericFilters []func(ezkube.ResourceId) bool - for _, filter := range filterResource { - filter := filter - genericFilters = append(genericFilters, func(obj ezkube.ResourceId) bool { - return filter(obj.(*things_test_io_v1.ClusterResource)) - }) - } - - var clusterResourceList []*things_test_io_v1.ClusterResource - for _, obj := range s.Generic().UnsortedList(genericFilters...) { - clusterResourceList = append(clusterResourceList, obj.(*things_test_io_v1.ClusterResource)) - } - return clusterResourceList + } + return s.Generic().Keys() +} + +func (s *clusterResourceSet) List(filterResource ... func(*things_test_io_v1.ClusterResource) bool) []*things_test_io_v1.ClusterResource { + if s == nil { + return nil + } + var genericFilters []func(ezkube.ResourceId) bool + for _, filter := range filterResource { + filter := filter + genericFilters = append(genericFilters, func(obj ezkube.ResourceId) bool { + return filter(obj.(*things_test_io_v1.ClusterResource)) + }) + } + + objs := s.Generic().List(genericFilters...) + clusterResourceList := make([]*things_test_io_v1.ClusterResource, 0, len(objs)) + for _, obj := range objs { + clusterResourceList = append(clusterResourceList, obj.(*things_test_io_v1.ClusterResource)) + } + return clusterResourceList +} + +func (s *clusterResourceSet) UnsortedList(filterResource ... func(*things_test_io_v1.ClusterResource) bool) []*things_test_io_v1.ClusterResource { + if s == nil { + return nil + } + var genericFilters []func(ezkube.ResourceId) bool + for _, filter := range filterResource { + filter := filter + genericFilters = append(genericFilters, func(obj ezkube.ResourceId) bool { + return filter(obj.(*things_test_io_v1.ClusterResource)) + }) + } + + var clusterResourceList []*things_test_io_v1.ClusterResource + for _, obj := range s.Generic().UnsortedList(genericFilters...) { + clusterResourceList = append(clusterResourceList, obj.(*things_test_io_v1.ClusterResource)) + } + return clusterResourceList } func (s *clusterResourceSet) Map() map[string]*things_test_io_v1.ClusterResource { - if s == nil { - return nil - } + if s == nil { + return nil + } - newMap := map[string]*things_test_io_v1.ClusterResource{} - for k, v := range s.Generic().Map() { - newMap[k] = v.(*things_test_io_v1.ClusterResource) - } - return newMap + newMap := map[string]*things_test_io_v1.ClusterResource{} + for k, v := range s.Generic().Map() { + newMap[k] = v.(*things_test_io_v1.ClusterResource) + } + return newMap } func (s *clusterResourceSet) Insert( - clusterResourceList ...*things_test_io_v1.ClusterResource, + clusterResourceList ...*things_test_io_v1.ClusterResource, ) { - if s == nil { - panic("cannot insert into nil set") - } + if s == nil { + panic("cannot insert into nil set") + } - for _, obj := range clusterResourceList { - s.Generic().Insert(obj) - } + for _, obj := range clusterResourceList { + s.Generic().Insert(obj) + } } func (s *clusterResourceSet) Has(clusterResource ezkube.ResourceId) bool { - if s == nil { - return false - } - return s.Generic().Has(clusterResource) + if s == nil { + return false + } + return s.Generic().Has(clusterResource) } func (s *clusterResourceSet) Equal( - clusterResourceSet ClusterResourceSet, + clusterResourceSet ClusterResourceSet, ) bool { - if s == nil { - return clusterResourceSet == nil - } - return s.Generic().Equal(clusterResourceSet.Generic()) + if s == nil { + return clusterResourceSet == nil + } + return s.Generic().Equal(clusterResourceSet.Generic()) } func (s *clusterResourceSet) Delete(ClusterResource ezkube.ResourceId) { - if s == nil { - return - } - s.Generic().Delete(ClusterResource) + if s == nil { + return + } + s.Generic().Delete(ClusterResource) } func (s *clusterResourceSet) Union(set ClusterResourceSet) ClusterResourceSet { - if s == nil { - return set - } - return NewClusterResourceSet(append(s.List(), set.List()...)...) + if s == nil { + return set + } + return NewClusterResourceSet(append(s.List(), set.List()...)...) } func (s *clusterResourceSet) Difference(set ClusterResourceSet) ClusterResourceSet { - if s == nil { - return set - } - newSet := s.Generic().Difference(set.Generic()) - return &clusterResourceSet{set: newSet} + if s == nil { + return set + } + newSet := s.Generic().Difference(set.Generic()) + return &clusterResourceSet{set: newSet} } func (s *clusterResourceSet) Intersection(set ClusterResourceSet) ClusterResourceSet { - if s == nil { - return nil - } - newSet := s.Generic().Intersection(set.Generic()) - var clusterResourceList []*things_test_io_v1.ClusterResource - for _, obj := range newSet.List() { - clusterResourceList = append(clusterResourceList, obj.(*things_test_io_v1.ClusterResource)) - } - return NewClusterResourceSet(clusterResourceList...) + if s == nil { + return nil + } + newSet := s.Generic().Intersection(set.Generic()) + var clusterResourceList []*things_test_io_v1.ClusterResource + for _, obj := range newSet.List() { + clusterResourceList = append(clusterResourceList, obj.(*things_test_io_v1.ClusterResource)) + } + return NewClusterResourceSet(clusterResourceList...) } + func (s *clusterResourceSet) Find(id ezkube.ResourceId) (*things_test_io_v1.ClusterResource, error) { - if s == nil { - return nil, eris.Errorf("empty set, cannot find ClusterResource %v", sksets.Key(id)) - } + if s == nil { + return nil, eris.Errorf("empty set, cannot find ClusterResource %v", sksets.Key(id)) + } obj, err := s.Generic().Find(&things_test_io_v1.ClusterResource{}, id) if err != nil { return nil, err - } + } - return obj.(*things_test_io_v1.ClusterResource), nil + return obj.(*things_test_io_v1.ClusterResource), nil } func (s *clusterResourceSet) Length() int { - if s == nil { - return 0 - } - return s.Generic().Length() + if s == nil { + return 0 + } + return s.Generic().Length() } func (s *clusterResourceSet) Generic() sksets.ResourceSet { - if s == nil { - return nil - } - return s.set + if s == nil { + return nil + } + return s.set } func (s *clusterResourceSet) Delta(newSet ClusterResourceSet) sksets.ResourceDelta { - if s == nil { - return sksets.ResourceDelta{ - Inserted: newSet.Generic(), - } - } - return s.Generic().Delta(newSet.Generic()) + if s == nil { + return sksets.ResourceDelta{ + Inserted: newSet.Generic(), + } + } + return s.Generic().Delta(newSet.Generic()) } func (s *clusterResourceSet) Clone() ClusterResourceSet { diff --git a/codegen/test/api/things.test.io/v1/test_api.pb.go b/codegen/test/api/things.test.io/v1/test_api.pb.go index 53e16624d..fa79410fd 100644 --- a/codegen/test/api/things.test.io/v1/test_api.pb.go +++ b/codegen/test/api/things.test.io/v1/test_api.pb.go @@ -7,15 +7,14 @@ package v1 import ( - reflect "reflect" - sync "sync" - any1 "github.com/golang/protobuf/ptypes/any" _struct "github.com/golang/protobuf/ptypes/struct" wrappers "github.com/golang/protobuf/ptypes/wrappers" _ "github.com/solo-io/cue/encoding/protobuf/cue" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/codegen/test/api/things.test.io/v1/type_helpers.go b/codegen/test/api/things.test.io/v1/type_helpers.go index 4133a8e21..2d04a4fd1 100644 --- a/codegen/test/api/things.test.io/v1/type_helpers.go +++ b/codegen/test/api/things.test.io/v1/type_helpers.go @@ -3,6 +3,9 @@ // Definitions for the Kubernetes types package v1 +import ( +) + // PaintSlice represents a slice of *Paint type PaintSlice []*Paint diff --git a/codegen/test/api/things.test.io/v1/types.go b/codegen/test/api/things.test.io/v1/types.go index f153a3983..3f3fc59e2 100644 --- a/codegen/test/api/things.test.io/v1/types.go +++ b/codegen/test/api/things.test.io/v1/types.go @@ -4,9 +4,8 @@ package v1 import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema" -) + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema") // +genclient // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object @@ -15,22 +14,22 @@ import ( // GroupVersionKind for Paint var PaintGVK = schema.GroupVersionKind{ - Group: "things.test.io", - Version: "v1", - Kind: "Paint", + Group: "things.test.io", + Version: "v1", + Kind: "Paint", } // Paint is the Schema for the paint API type Paint struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` - Spec PaintSpec `json:"spec,omitempty"` - Status PaintStatus `json:"status,omitempty"` + Spec PaintSpec `json:"spec,omitempty"` + Status PaintStatus `json:"status,omitempty"` } // GVK returns the GroupVersionKind associated with the resource type. -func (Paint) GVK() schema.GroupVersionKind { +func (Paint) GVK() schema.GroupVersionKind { return PaintGVK } @@ -38,9 +37,9 @@ func (Paint) GVK() schema.GroupVersionKind { // PaintList contains a list of Paint type PaintList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []Paint `json:"items"` + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Paint `json:"items"` } // +genclient @@ -50,21 +49,21 @@ type PaintList struct { // GroupVersionKind for ClusterResource var ClusterResourceGVK = schema.GroupVersionKind{ - Group: "things.test.io", - Version: "v1", - Kind: "ClusterResource", + Group: "things.test.io", + Version: "v1", + Kind: "ClusterResource", } // ClusterResource is the Schema for the clusterResource API type ClusterResource struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` - Spec ClusterResourceSpec `json:"spec,omitempty"` + Spec ClusterResourceSpec `json:"spec,omitempty"` } // GVK returns the GroupVersionKind associated with the resource type. -func (ClusterResource) GVK() schema.GroupVersionKind { +func (ClusterResource) GVK() schema.GroupVersionKind { return ClusterResourceGVK } @@ -72,12 +71,12 @@ func (ClusterResource) GVK() schema.GroupVersionKind { // ClusterResourceList contains a list of ClusterResource type ClusterResourceList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []ClusterResource `json:"items"` + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ClusterResource `json:"items"` } func init() { - SchemeBuilder.Register(&Paint{}, &PaintList{}) - SchemeBuilder.Register(&ClusterResource{}, &ClusterResourceList{}) + SchemeBuilder.Register(&Paint{}, &PaintList{}) + SchemeBuilder.Register(&ClusterResource{}, &ClusterResourceList{}) } diff --git a/codegen/test/api/things.test.io/v1/zz_generated.deepcopy.go b/codegen/test/api/things.test.io/v1/zz_generated.deepcopy.go index 4203de9bf..8939012a9 100644 --- a/codegen/test/api/things.test.io/v1/zz_generated.deepcopy.go +++ b/codegen/test/api/things.test.io/v1/zz_generated.deepcopy.go @@ -5,123 +5,124 @@ package v1 import ( - runtime "k8s.io/apimachinery/pkg/runtime" + runtime "k8s.io/apimachinery/pkg/runtime" ) // Generated Deepcopy methods for Paint func (in *Paint) DeepCopyInto(out *Paint) { - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - // deepcopy spec - in.Spec.DeepCopyInto(&out.Spec) - // deepcopy status - in.Status.DeepCopyInto(&out.Status) + // deepcopy spec + in.Spec.DeepCopyInto(&out.Spec) + // deepcopy status + in.Status.DeepCopyInto(&out.Status) - return + return } func (in *Paint) DeepCopy() *Paint { - if in == nil { - return nil - } - out := new(Paint) - in.DeepCopyInto(out) - return out + if in == nil { + return nil + } + out := new(Paint) + in.DeepCopyInto(out) + return out } func (in *Paint) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil + if c := in.DeepCopy(); c != nil { + return c + } + return nil } func (in *PaintList) DeepCopyInto(out *PaintList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]Paint, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Paint, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return } func (in *PaintList) DeepCopy() *PaintList { - if in == nil { - return nil - } - out := new(PaintList) - in.DeepCopyInto(out) - return out + if in == nil { + return nil + } + out := new(PaintList) + in.DeepCopyInto(out) + return out } func (in *PaintList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil + if c := in.DeepCopy(); c != nil { + return c + } + return nil } // Generated Deepcopy methods for ClusterResource func (in *ClusterResource) DeepCopyInto(out *ClusterResource) { - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - // deepcopy spec - in.Spec.DeepCopyInto(&out.Spec) + // deepcopy spec + in.Spec.DeepCopyInto(&out.Spec) - return + return } func (in *ClusterResource) DeepCopy() *ClusterResource { - if in == nil { - return nil - } - out := new(ClusterResource) - in.DeepCopyInto(out) - return out + if in == nil { + return nil + } + out := new(ClusterResource) + in.DeepCopyInto(out) + return out } func (in *ClusterResource) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil + if c := in.DeepCopy(); c != nil { + return c + } + return nil } func (in *ClusterResourceList) DeepCopyInto(out *ClusterResourceList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]ClusterResource, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ClusterResource, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return } func (in *ClusterResourceList) DeepCopy() *ClusterResourceList { - if in == nil { - return nil - } - out := new(ClusterResourceList) - in.DeepCopyInto(out) - return out + if in == nil { + return nil + } + out := new(ClusterResourceList) + in.DeepCopyInto(out) + return out } func (in *ClusterResourceList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil + if c := in.DeepCopy(); c != nil { + return c + } + return nil } + diff --git a/codegen/test/chart-no-desc/crds/things.test.io_v1_crds.yaml b/codegen/test/chart-no-desc/crds/things.test.io_crds.yaml similarity index 97% rename from codegen/test/chart-no-desc/crds/things.test.io_v1_crds.yaml rename to codegen/test/chart-no-desc/crds/things.test.io_crds.yaml index b44f06926..7751afc54 100644 --- a/codegen/test/chart-no-desc/crds/things.test.io_v1_crds.yaml +++ b/codegen/test/chart-no-desc/crds/things.test.io_crds.yaml @@ -4,7 +4,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - crd.solo.io/specHash: 52f9159d46759d37 + crd.solo.io/specHash: d4c655613b9cf09a labels: app: "" app.kubernetes.io/name: "" @@ -129,7 +129,7 @@ spec: type: object type: object served: true - storage: true + storage: false subresources: status: {} @@ -138,7 +138,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - crd.solo.io/specHash: a7f6c51daca2a86e + crd.solo.io/specHash: 4e5d137cbc4ab67f labels: app: "" app.kubernetes.io/name: "" @@ -163,5 +163,5 @@ spec: type: object type: object served: true - storage: true + storage: false subresources: {} diff --git a/codegen/test/chart-no-desc/templates/things.test.io_crds.yaml b/codegen/test/chart-no-desc/templates/things.test.io_crds.yaml new file mode 100644 index 000000000..c3ec4e31e --- /dev/null +++ b/codegen/test/chart-no-desc/templates/things.test.io_crds.yaml @@ -0,0 +1,169 @@ +# Code generated by skv2. DO NOT EDIT. + + +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + crd.solo.io/specHash: d4c655613b9cf09a + labels: + app: "" + app.kubernetes.io/name: "" + name: paints.things.test.io +spec: + group: things.test.io + names: + kind: Paint + listKind: PaintList + plural: paints + singular: paint + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + spec: + oneOf: + - not: + anyOf: + - required: + - acrylic + - properties: + oil: + oneOf: + - not: + anyOf: + - required: + - powder + - required: + - fluid + - required: + - powder + - required: + - fluid + required: + - oil + - required: + - acrylic + - properties: + oil: + oneOf: + - not: + anyOf: + - required: + - powder + - required: + - fluid + - required: + - powder + - required: + - fluid + required: + - oil + properties: + acrylic: + properties: + body: + enum: + - Light + - Medium + - Heavy + type: string + type: object + color: + properties: + hue: + type: string + value: + format: float + type: number + type: object + myFavorite: + type: object + x-kubernetes-preserve-unknown-fields: true + oil: + properties: + fluid: + type: string + powder: + type: string + waterMixable: + type: boolean + type: object + recursiveType: + properties: + protobufValue: + x-kubernetes-preserve-unknown-fields: true + recursiveField: + type: object + x-kubernetes-preserve-unknown-fields: true + recursiveFieldOutermostScope: + type: object + x-kubernetes-preserve-unknown-fields: true + repeatedRecursiveField: + items: + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + type: object + type: object + status: + properties: + nearbyPaints: + additionalProperties: + properties: + x: + type: object + x-kubernetes-preserve-unknown-fields: true + "y": + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + observedGeneration: + format: int64 + type: integer + percentRemaining: + format: int64 + type: integer + type: object + type: object + served: true + storage: false + subresources: + status: {} +--- + +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + crd.solo.io/specHash: 4e5d137cbc4ab67f + labels: + app: "" + app.kubernetes.io/name: "" + name: clusterresources.things.test.io +spec: + group: things.test.io + names: + kind: ClusterResource + listKind: ClusterResourceList + plural: clusterresources + singular: clusterresource + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + spec: + properties: + imported: + type: string + type: object + type: object + served: true + storage: false + subresources: {} +--- diff --git a/codegen/test/chart/crds/things.test.io_v1_crds.yaml b/codegen/test/chart/crds/things.test.io_crds.yaml similarity index 97% rename from codegen/test/chart/crds/things.test.io_v1_crds.yaml rename to codegen/test/chart/crds/things.test.io_crds.yaml index 0a333a174..1ff72cc78 100644 --- a/codegen/test/chart/crds/things.test.io_v1_crds.yaml +++ b/codegen/test/chart/crds/things.test.io_crds.yaml @@ -4,7 +4,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - crd.solo.io/specHash: 888c42601b3e10b6 + crd.solo.io/specHash: 6d9fb6fb4e2b4cf1 labels: app: "" app.kubernetes.io/name: "" @@ -133,7 +133,7 @@ spec: type: object type: object served: true - storage: true + storage: false subresources: status: {} @@ -142,7 +142,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - crd.solo.io/specHash: a7f6c51daca2a86e + crd.solo.io/specHash: 4e5d137cbc4ab67f labels: app: "" app.kubernetes.io/name: "" @@ -167,5 +167,5 @@ spec: type: object type: object served: true - storage: true + storage: false subresources: {} diff --git a/codegen/test/chart/templates/things.test.io_crds.yaml b/codegen/test/chart/templates/things.test.io_crds.yaml new file mode 100644 index 000000000..01440611a --- /dev/null +++ b/codegen/test/chart/templates/things.test.io_crds.yaml @@ -0,0 +1,173 @@ +# Code generated by skv2. DO NOT EDIT. + + +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + crd.solo.io/specHash: 6d9fb6fb4e2b4cf1 + labels: + app: "" + app.kubernetes.io/name: "" + name: paints.things.test.io +spec: + group: things.test.io + names: + kind: Paint + listKind: PaintList + plural: paints + singular: paint + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + spec: + oneOf: + - not: + anyOf: + - required: + - acrylic + - properties: + oil: + oneOf: + - not: + anyOf: + - required: + - powder + - required: + - fluid + - required: + - powder + - required: + - fluid + required: + - oil + - required: + - acrylic + - properties: + oil: + oneOf: + - not: + anyOf: + - required: + - powder + - required: + - fluid + - required: + - powder + - required: + - fluid + required: + - oil + properties: + acrylic: + properties: + body: + enum: + - Light + - Medium + - Heavy + type: string + type: object + color: + properties: + hue: + type: string + value: + format: float + type: number + type: object + myFavorite: + type: object + x-kubernetes-preserve-unknown-fields: true + oil: + properties: + fluid: + type: string + powder: + type: string + waterMixable: + type: boolean + type: object + recursiveType: + description: OpenAPI gen test for recursive fields + properties: + protobufValue: + x-kubernetes-preserve-unknown-fields: true + recursiveField: + type: object + x-kubernetes-preserve-unknown-fields: true + recursiveFieldOutermostScope: + description: |- + Ensure that FieldOptions can be defined using package name resolution that starts from the + outermost scope: https://developers.google.com/protocol-buffers/docs/proto3#packages_and_name_resolution + type: object + x-kubernetes-preserve-unknown-fields: true + repeatedRecursiveField: + items: + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + type: object + type: object + status: + properties: + nearbyPaints: + additionalProperties: + properties: + x: + type: object + x-kubernetes-preserve-unknown-fields: true + "y": + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + observedGeneration: + format: int64 + type: integer + percentRemaining: + format: int64 + type: integer + type: object + type: object + served: true + storage: false + subresources: + status: {} +--- + +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + crd.solo.io/specHash: 4e5d137cbc4ab67f + labels: + app: "" + app.kubernetes.io/name: "" + name: clusterresources.things.test.io +spec: + group: things.test.io + names: + kind: ClusterResource + listKind: ClusterResourceList + plural: clusterresources + singular: clusterresource + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + spec: + properties: + imported: + type: string + type: object + type: object + served: true + storage: false + subresources: {} +--- diff --git a/codegen/test/name_override_chart/crds/things.test.io_v1_crds.yaml b/codegen/test/name_override_chart/crds/things.test.io_crds.yaml similarity index 89% rename from codegen/test/name_override_chart/crds/things.test.io_v1_crds.yaml rename to codegen/test/name_override_chart/crds/things.test.io_crds.yaml index 69f3cbb1c..1ef134fa7 100644 --- a/codegen/test/name_override_chart/crds/things.test.io_v1_crds.yaml +++ b/codegen/test/name_override_chart/crds/things.test.io_crds.yaml @@ -4,7 +4,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - crd.solo.io/specHash: 80e7931efac2214e + crd.solo.io/specHash: 7e527d75eb594ad1 labels: app: "" app.kubernetes.io/name: "" @@ -24,7 +24,7 @@ spec: type: object x-kubernetes-preserve-unknown-fields: true served: true - storage: true + storage: false subresources: status: {} @@ -33,7 +33,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - crd.solo.io/specHash: 2c0000aa4677e683 + crd.solo.io/specHash: 807308fa48da5845 labels: app: "" app.kubernetes.io/name: "" @@ -53,5 +53,5 @@ spec: type: object x-kubernetes-preserve-unknown-fields: true served: true - storage: true + storage: false subresources: {} diff --git a/codegen/test/name_override_chart/templates/things.test.io_crds.yaml b/codegen/test/name_override_chart/templates/things.test.io_crds.yaml new file mode 100644 index 000000000..d71680d66 --- /dev/null +++ b/codegen/test/name_override_chart/templates/things.test.io_crds.yaml @@ -0,0 +1,59 @@ +# Code generated by skv2. DO NOT EDIT. + + +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + crd.solo.io/specHash: 7e527d75eb594ad1 + labels: + app: "" + app.kubernetes.io/name: "" + name: paints.things.test.io +spec: + group: things.test.io + names: + kind: Paint + listKind: PaintList + plural: paints + singular: paint + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + type: object + x-kubernetes-preserve-unknown-fields: true + served: true + storage: false + subresources: + status: {} +--- + +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + crd.solo.io/specHash: 807308fa48da5845 + labels: + app: "" + app.kubernetes.io/name: "" + name: clusterresources.things.test.io +spec: + group: things.test.io + names: + kind: ClusterResource + listKind: ClusterResourceList + plural: clusterresources + singular: clusterresource + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + type: object + x-kubernetes-preserve-unknown-fields: true + served: true + storage: false + subresources: {} +--- From 2ad44afe8a28d742ab1f53e095d04a458898411c Mon Sep 17 00:00:00 2001 From: Dmitri Dolguikh Date: Wed, 26 Jul 2023 20:48:26 -0700 Subject: [PATCH 08/27] Test fixes Signed-off-by: Dmitri Dolguikh --- codegen/cmd_test.go | 23 ++++-- codegen/render/kube_crud_test.go | 5 +- codegen/render/kube_multicluster_test.go | 3 +- .../crds/things.test.io_crds.yaml | 70 +++++++++---------- .../templates/things.test.io_crds.yaml | 70 +++++++++---------- .../test/chart/crds/things.test.io_crds.yaml | 8 +-- .../chart/templates/things.test.io_crds.yaml | 8 +-- .../crds/things.test.io_crds.yaml | 8 +-- .../templates/things.test.io_crds.yaml | 8 +-- 9 files changed, 111 insertions(+), 92 deletions(-) diff --git a/codegen/cmd_test.go b/codegen/cmd_test.go index df490830f..0f21d1ee5 100644 --- a/codegen/cmd_test.go +++ b/codegen/cmd_test.go @@ -54,11 +54,13 @@ var _ = Describe("Cmd", func() { Kind: "Paint", Spec: Field{Type: Type{Name: "PaintSpec"}}, Status: &Field{Type: Type{Name: "PaintStatus"}}, + Stored: true, }, { Kind: "ClusterResource", Spec: Field{Type: Type{Name: "ClusterResourceSpec"}}, ClusterScoped: true, + Stored: true, }, }, RenderManifests: true, @@ -133,6 +135,7 @@ var _ = Describe("Cmd", func() { Name: "KubernetesCluster", GoPackage: "github.com/solo-io/skv2/pkg/api/multicluster.solo.io/v1alpha1", }}, + Stored: true, }, }, RenderManifests: true, @@ -171,11 +174,13 @@ var _ = Describe("Cmd", func() { Kind: "Paint", Spec: Field{Type: Type{Name: "PaintSpec"}}, Status: &Field{Type: Type{Name: "PaintStatus"}}, + Stored: true, }, { Kind: "ClusterResource", Spec: Field{Type: Type{Name: "ClusterResourceSpec"}}, ClusterScoped: true, + Stored: true, }, }, RenderManifests: true, @@ -256,11 +261,13 @@ var _ = Describe("Cmd", func() { Kind: "Paint", Spec: Field{Type: Type{Name: "PaintSpec"}}, Status: &Field{Type: Type{Name: "PaintStatus"}}, + Stored: true, }, { Kind: "ClusterResource", Spec: Field{Type: Type{Name: "ClusterResourceSpec"}}, ClusterScoped: true, + Stored: true, }, }, RenderManifests: true, @@ -375,11 +382,13 @@ var _ = Describe("Cmd", func() { Kind: "Paint", Spec: Field{Type: Type{Name: "PaintSpec"}}, Status: &Field{Type: Type{Name: "PaintStatus"}}, + Stored: true, }, { Kind: "ClusterResource", Spec: Field{Type: Type{Name: "ClusterResourceSpec"}}, ClusterScoped: true, + Stored: true, }, }, RenderManifests: true, @@ -1195,11 +1204,13 @@ var _ = Describe("Cmd", func() { Kind: "Paint", Spec: Field{Type: Type{Name: "PaintSpec"}}, Status: &Field{Type: Type{Name: "PaintStatus"}}, + Stored: true, }, { Kind: "ClusterResource", Spec: Field{Type: Type{Name: "ClusterResourceSpec"}}, ClusterScoped: true, + Stored: true, }, }, RenderManifests: true, @@ -1315,7 +1326,7 @@ var _ = Describe("Cmd", func() { }) It("can include field descriptions", func() { - crdFilePath := filepath.Join(util.GetModuleRoot(), cmd.ManifestRoot, "/crds/things.test.io_v1_crds.yaml") + crdFilePath := filepath.Join(util.GetModuleRoot(), cmd.ManifestRoot, "/crds/things.test.io_crds.yaml") err := cmd.Execute() Expect(err).NotTo(HaveOccurred()) @@ -1325,8 +1336,12 @@ var _ = Describe("Cmd", func() { Expect(string(bytes)).To(ContainSubstring("description: OpenAPI gen test for recursive fields")) }) + // TODO (dmitri-d): this is flaky, as the ordering of generated CustomResourceDefinitions is unstable + // when the "Paint" CRD isn't the first in the list, the test fails. + // Can't remove "ClusterResource" either, as kube_crud_test and kube_multicluster_test depend on crds + // this suite. It("generates google.protobuf.Value with no type", func() { - crdFilePath := filepath.Join(util.GetModuleRoot(), cmd.ManifestRoot, "/crds/things.test.io_v1_crds.yaml") + crdFilePath := filepath.Join(util.GetModuleRoot(), cmd.ManifestRoot, "/crds/things.test.io_crds.yaml") err := cmd.Execute() Expect(err).NotTo(HaveOccurred()) @@ -1334,7 +1349,7 @@ var _ = Describe("Cmd", func() { bytes, err := ioutil.ReadFile(crdFilePath) Expect(err).NotTo(HaveOccurred()) generatedCrd := &v12.CustomResourceDefinition{} - Expect(yaml.Unmarshal(bytes, generatedCrd)).NotTo(HaveOccurred()) + Expect(yaml.Unmarshal(bytes, &generatedCrd)).NotTo(HaveOccurred()) protobufValueField := generatedCrd.Spec.Versions[0].Schema.OpenAPIV3Schema.Properties["spec"].Properties["recursiveType"].Properties["protobufValue"] // access the field to make sure it's not nil Expect(protobufValueField.XPreserveUnknownFields).ToNot(BeNil()) @@ -1346,7 +1361,7 @@ var _ = Describe("Cmd", func() { // write this manifest to a different dir to avoid modifying the crd file from the // above test, which other tests seem to depend on cmd.ManifestRoot = "codegen/test/chart-no-desc" - crdFilePath := filepath.Join(util.GetModuleRoot(), cmd.ManifestRoot, "/crds/things.test.io_v1_crds.yaml") + crdFilePath := filepath.Join(util.GetModuleRoot(), cmd.ManifestRoot, "/crds/things.test.io_crds.yaml") cmd.Groups[0].SkipSchemaDescriptions = true diff --git a/codegen/render/kube_crud_test.go b/codegen/render/kube_crud_test.go index d30e18cc7..5c9116cef 100644 --- a/codegen/render/kube_crud_test.go +++ b/codegen/render/kube_crud_test.go @@ -31,12 +31,14 @@ import ( "sigs.k8s.io/controller-runtime/pkg/manager" ) +// TODO (dmitri-d): Remove dependency of these tests on crds generated in cmd_test func applyFile(file string, extraArgs ...string) error { path := filepath.Join(util.GetModuleRoot(), "codegen/test/chart/crds", file) b, err := ioutil.ReadFile(path) if err != nil { return err } + return util.KubectlApply(b, extraArgs...) } @@ -117,7 +119,8 @@ var _ = Describe("Generated Code", func() { log.SetLogger(zaputil.New( zaputil.Level(&logLevel), )) - err := applyFile("things.test.io_v1_crds.yaml") + err := applyFile("things.test.io_crds.yaml") + Expect(err).NotTo(HaveOccurred()) ns = randutils.RandString(4) kube = kubehelp.MustKubeClient() diff --git a/codegen/render/kube_multicluster_test.go b/codegen/render/kube_multicluster_test.go index 67fbb4a6b..d8046b913 100644 --- a/codegen/render/kube_multicluster_test.go +++ b/codegen/render/kube_multicluster_test.go @@ -40,6 +40,7 @@ func WithRemoteClusterContextDescribe(text string, body func()) bool { return Describe(text, body) } +// TODO (dmitri-d): Remove dependency of these tests on crds generated in cmd_test var _ = WithRemoteClusterContextDescribe("Multicluster", func() { var ( ctx context.Context @@ -66,7 +67,7 @@ var _ = WithRemoteClusterContextDescribe("Multicluster", func() { Expect(err).NotTo(HaveOccurred()) for _, kubeContext := range []string{"", remoteContext} { - err = applyFile("things.test.io_v1_crds.yaml", "--context", kubeContext) + err = applyFile("things.test.io_crds.yaml", "--context", kubeContext) Expect(err).NotTo(HaveOccurred()) cfg := test.MustConfig(kubeContext) diff --git a/codegen/test/chart-no-desc/crds/things.test.io_crds.yaml b/codegen/test/chart-no-desc/crds/things.test.io_crds.yaml index 7751afc54..b83d9e1b8 100644 --- a/codegen/test/chart-no-desc/crds/things.test.io_crds.yaml +++ b/codegen/test/chart-no-desc/crds/things.test.io_crds.yaml @@ -4,7 +4,40 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - crd.solo.io/specHash: d4c655613b9cf09a + crd.solo.io/specHash: a7f6c51daca2a86e + labels: + app: "" + app.kubernetes.io/name: "" + name: clusterresources.things.test.io +spec: + group: things.test.io + names: + kind: ClusterResource + listKind: ClusterResourceList + plural: clusterresources + singular: clusterresource + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + spec: + properties: + imported: + type: string + type: object + type: object + served: true + storage: true + subresources: {} + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + crd.solo.io/specHash: 52f9159d46759d37 labels: app: "" app.kubernetes.io/name: "" @@ -129,39 +162,6 @@ spec: type: object type: object served: true - storage: false + storage: true subresources: status: {} - ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - crd.solo.io/specHash: 4e5d137cbc4ab67f - labels: - app: "" - app.kubernetes.io/name: "" - name: clusterresources.things.test.io -spec: - group: things.test.io - names: - kind: ClusterResource - listKind: ClusterResourceList - plural: clusterresources - singular: clusterresource - scope: Cluster - versions: - - name: v1 - schema: - openAPIV3Schema: - properties: - spec: - properties: - imported: - type: string - type: object - type: object - served: true - storage: false - subresources: {} diff --git a/codegen/test/chart-no-desc/templates/things.test.io_crds.yaml b/codegen/test/chart-no-desc/templates/things.test.io_crds.yaml index c3ec4e31e..f5cc1031a 100644 --- a/codegen/test/chart-no-desc/templates/things.test.io_crds.yaml +++ b/codegen/test/chart-no-desc/templates/things.test.io_crds.yaml @@ -5,7 +5,40 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - crd.solo.io/specHash: d4c655613b9cf09a + crd.solo.io/specHash: a7f6c51daca2a86e + labels: + app: "" + app.kubernetes.io/name: "" + name: clusterresources.things.test.io +spec: + group: things.test.io + names: + kind: ClusterResource + listKind: ClusterResourceList + plural: clusterresources + singular: clusterresource + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + spec: + properties: + imported: + type: string + type: object + type: object + served: true + storage: true + subresources: {} +--- + +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + crd.solo.io/specHash: 52f9159d46759d37 labels: app: "" app.kubernetes.io/name: "" @@ -130,40 +163,7 @@ spec: type: object type: object served: true - storage: false + storage: true subresources: status: {} --- - -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - crd.solo.io/specHash: 4e5d137cbc4ab67f - labels: - app: "" - app.kubernetes.io/name: "" - name: clusterresources.things.test.io -spec: - group: things.test.io - names: - kind: ClusterResource - listKind: ClusterResourceList - plural: clusterresources - singular: clusterresource - scope: Cluster - versions: - - name: v1 - schema: - openAPIV3Schema: - properties: - spec: - properties: - imported: - type: string - type: object - type: object - served: true - storage: false - subresources: {} ---- diff --git a/codegen/test/chart/crds/things.test.io_crds.yaml b/codegen/test/chart/crds/things.test.io_crds.yaml index 1ff72cc78..0a333a174 100644 --- a/codegen/test/chart/crds/things.test.io_crds.yaml +++ b/codegen/test/chart/crds/things.test.io_crds.yaml @@ -4,7 +4,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - crd.solo.io/specHash: 6d9fb6fb4e2b4cf1 + crd.solo.io/specHash: 888c42601b3e10b6 labels: app: "" app.kubernetes.io/name: "" @@ -133,7 +133,7 @@ spec: type: object type: object served: true - storage: false + storage: true subresources: status: {} @@ -142,7 +142,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - crd.solo.io/specHash: 4e5d137cbc4ab67f + crd.solo.io/specHash: a7f6c51daca2a86e labels: app: "" app.kubernetes.io/name: "" @@ -167,5 +167,5 @@ spec: type: object type: object served: true - storage: false + storage: true subresources: {} diff --git a/codegen/test/chart/templates/things.test.io_crds.yaml b/codegen/test/chart/templates/things.test.io_crds.yaml index 01440611a..b634b9e21 100644 --- a/codegen/test/chart/templates/things.test.io_crds.yaml +++ b/codegen/test/chart/templates/things.test.io_crds.yaml @@ -5,7 +5,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - crd.solo.io/specHash: 6d9fb6fb4e2b4cf1 + crd.solo.io/specHash: 888c42601b3e10b6 labels: app: "" app.kubernetes.io/name: "" @@ -134,7 +134,7 @@ spec: type: object type: object served: true - storage: false + storage: true subresources: status: {} --- @@ -143,7 +143,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - crd.solo.io/specHash: 4e5d137cbc4ab67f + crd.solo.io/specHash: a7f6c51daca2a86e labels: app: "" app.kubernetes.io/name: "" @@ -168,6 +168,6 @@ spec: type: object type: object served: true - storage: false + storage: true subresources: {} --- diff --git a/codegen/test/name_override_chart/crds/things.test.io_crds.yaml b/codegen/test/name_override_chart/crds/things.test.io_crds.yaml index 1ef134fa7..69f3cbb1c 100644 --- a/codegen/test/name_override_chart/crds/things.test.io_crds.yaml +++ b/codegen/test/name_override_chart/crds/things.test.io_crds.yaml @@ -4,7 +4,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - crd.solo.io/specHash: 7e527d75eb594ad1 + crd.solo.io/specHash: 80e7931efac2214e labels: app: "" app.kubernetes.io/name: "" @@ -24,7 +24,7 @@ spec: type: object x-kubernetes-preserve-unknown-fields: true served: true - storage: false + storage: true subresources: status: {} @@ -33,7 +33,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - crd.solo.io/specHash: 807308fa48da5845 + crd.solo.io/specHash: 2c0000aa4677e683 labels: app: "" app.kubernetes.io/name: "" @@ -53,5 +53,5 @@ spec: type: object x-kubernetes-preserve-unknown-fields: true served: true - storage: false + storage: true subresources: {} diff --git a/codegen/test/name_override_chart/templates/things.test.io_crds.yaml b/codegen/test/name_override_chart/templates/things.test.io_crds.yaml index d71680d66..f8e0072e0 100644 --- a/codegen/test/name_override_chart/templates/things.test.io_crds.yaml +++ b/codegen/test/name_override_chart/templates/things.test.io_crds.yaml @@ -5,7 +5,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - crd.solo.io/specHash: 7e527d75eb594ad1 + crd.solo.io/specHash: 80e7931efac2214e labels: app: "" app.kubernetes.io/name: "" @@ -25,7 +25,7 @@ spec: type: object x-kubernetes-preserve-unknown-fields: true served: true - storage: false + storage: true subresources: status: {} --- @@ -34,7 +34,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - crd.solo.io/specHash: 807308fa48da5845 + crd.solo.io/specHash: 2c0000aa4677e683 labels: app: "" app.kubernetes.io/name: "" @@ -54,6 +54,6 @@ spec: type: object x-kubernetes-preserve-unknown-fields: true served: true - storage: false + storage: true subresources: {} --- From b947347a4c27dba9bdae9dc66a53b766b544fd78 Mon Sep 17 00:00:00 2001 From: Dmitri Dolguikh Date: Wed, 26 Jul 2023 20:53:27 -0700 Subject: [PATCH 09/27] Added a changelog entry Signed-off-by: Dmitri Dolguikh --- changelog/v0.31.2/conditional_crd_rendering.yaml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 changelog/v0.31.2/conditional_crd_rendering.yaml diff --git a/changelog/v0.31.2/conditional_crd_rendering.yaml b/changelog/v0.31.2/conditional_crd_rendering.yaml new file mode 100644 index 000000000..9be5a7354 --- /dev/null +++ b/changelog/v0.31.2/conditional_crd_rendering.yaml @@ -0,0 +1,5 @@ +changelog: + - type: NON_USER_FACING + issueLink: https://github.com/solo-io/gloo-mesh-enterprise/issues/9019 + description: > + Add support for conditional rendering of CRDs. From 08dfd42befdfa649cf01526b4892c41102118f39 Mon Sep 17 00:00:00 2001 From: Dmitri Dolguikh Date: Wed, 26 Jul 2023 21:05:39 -0700 Subject: [PATCH 10/27] Respect 'RenderManifests' Group field --- codegen/render/manifests_renderer.go | 20 +++--- .../crds/things.test.io_crds.yaml | 66 +++++++++---------- .../templates/things.test.io_crds.yaml | 66 +++++++++---------- 3 files changed, 77 insertions(+), 75 deletions(-) diff --git a/codegen/render/manifests_renderer.go b/codegen/render/manifests_renderer.go index 2baace976..b395af9dd 100644 --- a/codegen/render/manifests_renderer.go +++ b/codegen/render/manifests_renderer.go @@ -52,12 +52,15 @@ func RenderManifests( } func (r ManifestsRenderer) RenderManifests(grps []*Group, protoOpts protoutil.Options, groupOptions model.GroupOptions) ([]OutFile, error) { - // if !grp.RenderManifests { - // return nil, nil - // } + grpsByGroupName := make(map[string][]*Group) + shouldRenderGroups := make(map[string]bool) + for _, grp := range grps { + grpsByGroupName[grp.Group] = append(grpsByGroupName[grp.Group], grp) + shouldRenderGroups[grp.Group] = shouldRenderGroups[grp.Group] || grp.RenderManifests + } for _, grp := range grps { - if grp.RenderValidationSchemas { + if grp.RenderValidationSchemas && shouldRenderGroups[grp.Group] { var err error oapiSchemas, err := generateOpenApi(*grp, r.ProtoDir, protoOpts, groupOptions) if err != nil { @@ -67,14 +70,13 @@ func (r ManifestsRenderer) RenderManifests(grps []*Group, protoOpts protoutil.Op } } - grpsByGroupName := make(map[string][]*Group) - for _, grp := range grps { - grpsByGroupName[grp.Group] = append(grpsByGroupName[grp.Group], grp) - } - var renderedFiles []OutFile for groupName, selectedGrps := range grpsByGroupName { + if !shouldRenderGroups[groupName] { + continue + } + crds, err := r.createCrds(r.AppName, selectedGrps) if err != nil { return nil, err diff --git a/codegen/test/chart-no-desc/crds/things.test.io_crds.yaml b/codegen/test/chart-no-desc/crds/things.test.io_crds.yaml index b83d9e1b8..b44f06926 100644 --- a/codegen/test/chart-no-desc/crds/things.test.io_crds.yaml +++ b/codegen/test/chart-no-desc/crds/things.test.io_crds.yaml @@ -1,38 +1,5 @@ # Code generated by skv2. DO NOT EDIT. -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - crd.solo.io/specHash: a7f6c51daca2a86e - labels: - app: "" - app.kubernetes.io/name: "" - name: clusterresources.things.test.io -spec: - group: things.test.io - names: - kind: ClusterResource - listKind: ClusterResourceList - plural: clusterresources - singular: clusterresource - scope: Cluster - versions: - - name: v1 - schema: - openAPIV3Schema: - properties: - spec: - properties: - imported: - type: string - type: object - type: object - served: true - storage: true - subresources: {} - ---- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: @@ -165,3 +132,36 @@ spec: storage: true subresources: status: {} + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + crd.solo.io/specHash: a7f6c51daca2a86e + labels: + app: "" + app.kubernetes.io/name: "" + name: clusterresources.things.test.io +spec: + group: things.test.io + names: + kind: ClusterResource + listKind: ClusterResourceList + plural: clusterresources + singular: clusterresource + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + spec: + properties: + imported: + type: string + type: object + type: object + served: true + storage: true + subresources: {} diff --git a/codegen/test/chart-no-desc/templates/things.test.io_crds.yaml b/codegen/test/chart-no-desc/templates/things.test.io_crds.yaml index f5cc1031a..38e88c562 100644 --- a/codegen/test/chart-no-desc/templates/things.test.io_crds.yaml +++ b/codegen/test/chart-no-desc/templates/things.test.io_crds.yaml @@ -1,39 +1,6 @@ # Code generated by skv2. DO NOT EDIT. -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - crd.solo.io/specHash: a7f6c51daca2a86e - labels: - app: "" - app.kubernetes.io/name: "" - name: clusterresources.things.test.io -spec: - group: things.test.io - names: - kind: ClusterResource - listKind: ClusterResourceList - plural: clusterresources - singular: clusterresource - scope: Cluster - versions: - - name: v1 - schema: - openAPIV3Schema: - properties: - spec: - properties: - imported: - type: string - type: object - type: object - served: true - storage: true - subresources: {} ---- - apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: @@ -167,3 +134,36 @@ spec: subresources: status: {} --- + +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + crd.solo.io/specHash: a7f6c51daca2a86e + labels: + app: "" + app.kubernetes.io/name: "" + name: clusterresources.things.test.io +spec: + group: things.test.io + names: + kind: ClusterResource + listKind: ClusterResourceList + plural: clusterresources + singular: clusterresource + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + spec: + properties: + imported: + type: string + type: object + type: object + served: true + storage: true + subresources: {} +--- From e6a958cc5ae84856524cde692501526c58c2374a Mon Sep 17 00:00:00 2001 From: Dmitri Dolguikh Date: Wed, 26 Jul 2023 21:08:49 -0700 Subject: [PATCH 11/27] Moved changelog to v0.31.3 --- changelog/{v0.31.2 => v0.31.3}/conditional_crd_rendering.yaml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename changelog/{v0.31.2 => v0.31.3}/conditional_crd_rendering.yaml (100%) diff --git a/changelog/v0.31.2/conditional_crd_rendering.yaml b/changelog/v0.31.3/conditional_crd_rendering.yaml similarity index 100% rename from changelog/v0.31.2/conditional_crd_rendering.yaml rename to changelog/v0.31.3/conditional_crd_rendering.yaml From 77ee7d2df97e5f0f1e99f16572e8ebbabc07843f Mon Sep 17 00:00:00 2001 From: Dmitri Dolguikh Date: Wed, 26 Jul 2023 21:35:18 -0700 Subject: [PATCH 12/27] Regenerated code Signed-off-by: Dmitri Dolguikh --- api/multicluster/v1alpha1/group.go | 1 + codegen/test/api/things.test.io/v1/clients.go | 349 +++++----- .../v1/controller/event_handlers.go | 244 +++---- .../v1/controller/multicluster_reconcilers.go | 2 - .../v1/controller/reconcilers.go | 228 ++++--- .../test/api/things.test.io/v1/json.gen.go | 17 +- .../api/things.test.io/v1/proto_deepcopy.go | 47 +- .../v1/providers/client_providers.go | 50 +- .../test/api/things.test.io/v1/register.go | 19 +- .../test/api/things.test.io/v1/sets/sets.go | 618 +++++++++--------- .../test/api/things.test.io/v1/test_api.pb.go | 5 +- .../api/things.test.io/v1/type_helpers.go | 3 - codegen/test/api/things.test.io/v1/types.go | 51 +- .../v1/zz_generated.deepcopy.go | 151 +++-- ...ds.yaml => multicluster.solo.io_crds.yaml} | 0 templates/multicluster.solo.io_crds.yaml | 163 +++++ 16 files changed, 1048 insertions(+), 900 deletions(-) rename crds/{multicluster.solo.io_v1alpha1_crds.yaml => multicluster.solo.io_crds.yaml} (100%) create mode 100644 templates/multicluster.solo.io_crds.yaml diff --git a/api/multicluster/v1alpha1/group.go b/api/multicluster/v1alpha1/group.go index 9291ebf47..5782dba2a 100644 --- a/api/multicluster/v1alpha1/group.go +++ b/api/multicluster/v1alpha1/group.go @@ -26,6 +26,7 @@ var Group = model.Group{ Name: "KubernetesClusterStatus", }, }, + Stored: true, }, }, RenderManifests: true, diff --git a/codegen/test/api/things.test.io/v1/clients.go b/codegen/test/api/things.test.io/v1/clients.go index 1f54aadb5..9f7c889c8 100644 --- a/codegen/test/api/things.test.io/v1/clients.go +++ b/codegen/test/api/things.test.io/v1/clients.go @@ -4,89 +4,86 @@ package v1 - - - import ( - "context" - - "github.com/solo-io/skv2/pkg/controllerutils" - "github.com/solo-io/skv2/pkg/multicluster" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/client-go/kubernetes/scheme" - "k8s.io/client-go/rest" - "sigs.k8s.io/controller-runtime/pkg/client" + "context" + + "github.com/solo-io/skv2/pkg/controllerutils" + "github.com/solo-io/skv2/pkg/multicluster" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/client" ) // MulticlusterClientset for the things.test.io/v1 APIs type MulticlusterClientset interface { - // Cluster returns a Clientset for the given cluster - Cluster(cluster string) (Clientset, error) + // Cluster returns a Clientset for the given cluster + Cluster(cluster string) (Clientset, error) } type multiclusterClientset struct { - client multicluster.Client + client multicluster.Client } func NewMulticlusterClientset(client multicluster.Client) MulticlusterClientset { - return &multiclusterClientset{client: client} + return &multiclusterClientset{client: client} } func (m *multiclusterClientset) Cluster(cluster string) (Clientset, error) { - client, err := m.client.Cluster(cluster) - if err != nil { - return nil, err - } - return NewClientset(client), nil + client, err := m.client.Cluster(cluster) + if err != nil { + return nil, err + } + return NewClientset(client), nil } // clienset for the things.test.io/v1 APIs type Clientset interface { - // clienset for the things.test.io/v1/v1 APIs - Paints() PaintClient - // clienset for the things.test.io/v1/v1 APIs - ClusterResources() ClusterResourceClient + // clienset for the things.test.io/v1/v1 APIs + Paints() PaintClient + // clienset for the things.test.io/v1/v1 APIs + ClusterResources() ClusterResourceClient } type clientSet struct { - client client.Client + client client.Client } func NewClientsetFromConfig(cfg *rest.Config) (Clientset, error) { - scheme := scheme.Scheme - if err := SchemeBuilder.AddToScheme(scheme); err != nil{ - return nil, err - } - client, err := client.New(cfg, client.Options{ - Scheme: scheme, - }) - if err != nil { - return nil, err - } - return NewClientset(client), nil + scheme := scheme.Scheme + if err := SchemeBuilder.AddToScheme(scheme); err != nil { + return nil, err + } + client, err := client.New(cfg, client.Options{ + Scheme: scheme, + }) + if err != nil { + return nil, err + } + return NewClientset(client), nil } func NewClientset(client client.Client) Clientset { - return &clientSet{client: client} + return &clientSet{client: client} } // clienset for the things.test.io/v1/v1 APIs func (c *clientSet) Paints() PaintClient { - return NewPaintClient(c.client) + return NewPaintClient(c.client) } // clienset for the things.test.io/v1/v1 APIs func (c *clientSet) ClusterResources() ClusterResourceClient { - return NewClusterResourceClient(c.client) + return NewClusterResourceClient(c.client) } // Reader knows how to read and list Paints. type PaintReader interface { - // Get retrieves a Paint for the given object key - GetPaint(ctx context.Context, key client.ObjectKey) (*Paint, error) + // Get retrieves a Paint for the given object key + GetPaint(ctx context.Context, key client.ObjectKey) (*Paint, error) - // List retrieves list of Paints for a given namespace and list options. - ListPaint(ctx context.Context, opts ...client.ListOption) (*PaintList, error) + // List retrieves list of Paints for a given namespace and list options. + ListPaint(ctx context.Context, opts ...client.ListOption) (*PaintList, error) } // PaintTransitionFunction instructs the PaintWriter how to transition between an existing @@ -95,142 +92,140 @@ type PaintTransitionFunction func(existing, desired *Paint) error // Writer knows how to create, delete, and update Paints. type PaintWriter interface { - // Create saves the Paint object. - CreatePaint(ctx context.Context, obj *Paint, opts ...client.CreateOption) error + // Create saves the Paint object. + CreatePaint(ctx context.Context, obj *Paint, opts ...client.CreateOption) error - // Delete deletes the Paint object. - DeletePaint(ctx context.Context, key client.ObjectKey, opts ...client.DeleteOption) error + // Delete deletes the Paint object. + DeletePaint(ctx context.Context, key client.ObjectKey, opts ...client.DeleteOption) error - // Update updates the given Paint object. - UpdatePaint(ctx context.Context, obj *Paint, opts ...client.UpdateOption) error + // Update updates the given Paint object. + UpdatePaint(ctx context.Context, obj *Paint, opts ...client.UpdateOption) error - // Patch patches the given Paint object. - PatchPaint(ctx context.Context, obj *Paint, patch client.Patch, opts ...client.PatchOption) error + // Patch patches the given Paint object. + PatchPaint(ctx context.Context, obj *Paint, patch client.Patch, opts ...client.PatchOption) error - // DeleteAllOf deletes all Paint objects matching the given options. - DeleteAllOfPaint(ctx context.Context, opts ...client.DeleteAllOfOption) error + // DeleteAllOf deletes all Paint objects matching the given options. + DeleteAllOfPaint(ctx context.Context, opts ...client.DeleteAllOfOption) error - // Create or Update the Paint object. - UpsertPaint(ctx context.Context, obj *Paint, transitionFuncs ...PaintTransitionFunction) error + // Create or Update the Paint object. + UpsertPaint(ctx context.Context, obj *Paint, transitionFuncs ...PaintTransitionFunction) error } // StatusWriter knows how to update status subresource of a Paint object. type PaintStatusWriter interface { - // Update updates the fields corresponding to the status subresource for the - // given Paint object. - UpdatePaintStatus(ctx context.Context, obj *Paint, opts ...client.SubResourceUpdateOption) error + // Update updates the fields corresponding to the status subresource for the + // given Paint object. + UpdatePaintStatus(ctx context.Context, obj *Paint, opts ...client.SubResourceUpdateOption) error - // Patch patches the given Paint object's subresource. - PatchPaintStatus(ctx context.Context, obj *Paint, patch client.Patch, opts ...client.SubResourcePatchOption) error + // Patch patches the given Paint object's subresource. + PatchPaintStatus(ctx context.Context, obj *Paint, patch client.Patch, opts ...client.SubResourcePatchOption) error } // Client knows how to perform CRUD operations on Paints. type PaintClient interface { - PaintReader - PaintWriter - PaintStatusWriter + PaintReader + PaintWriter + PaintStatusWriter } type paintClient struct { - client client.Client + client client.Client } func NewPaintClient(client client.Client) *paintClient { - return &paintClient{client: client} + return &paintClient{client: client} } - func (c *paintClient) GetPaint(ctx context.Context, key client.ObjectKey) (*Paint, error) { - obj := &Paint{} - if err := c.client.Get(ctx, key, obj); err != nil { - return nil, err - } - return obj, nil + obj := &Paint{} + if err := c.client.Get(ctx, key, obj); err != nil { + return nil, err + } + return obj, nil } func (c *paintClient) ListPaint(ctx context.Context, opts ...client.ListOption) (*PaintList, error) { - list := &PaintList{} - if err := c.client.List(ctx, list, opts...); err != nil { - return nil, err - } - return list, nil + list := &PaintList{} + if err := c.client.List(ctx, list, opts...); err != nil { + return nil, err + } + return list, nil } func (c *paintClient) CreatePaint(ctx context.Context, obj *Paint, opts ...client.CreateOption) error { - return c.client.Create(ctx, obj, opts...) + return c.client.Create(ctx, obj, opts...) } - func (c *paintClient) DeletePaint(ctx context.Context, key client.ObjectKey, opts ...client.DeleteOption) error { - obj := &Paint{} - obj.SetName(key.Name) - obj.SetNamespace(key.Namespace) - return c.client.Delete(ctx, obj, opts...) + obj := &Paint{} + obj.SetName(key.Name) + obj.SetNamespace(key.Namespace) + return c.client.Delete(ctx, obj, opts...) } func (c *paintClient) UpdatePaint(ctx context.Context, obj *Paint, opts ...client.UpdateOption) error { - return c.client.Update(ctx, obj, opts...) + return c.client.Update(ctx, obj, opts...) } func (c *paintClient) PatchPaint(ctx context.Context, obj *Paint, patch client.Patch, opts ...client.PatchOption) error { - return c.client.Patch(ctx, obj, patch, opts...) + return c.client.Patch(ctx, obj, patch, opts...) } func (c *paintClient) DeleteAllOfPaint(ctx context.Context, opts ...client.DeleteAllOfOption) error { - obj := &Paint{} - return c.client.DeleteAllOf(ctx, obj, opts...) + obj := &Paint{} + return c.client.DeleteAllOf(ctx, obj, opts...) } func (c *paintClient) UpsertPaint(ctx context.Context, obj *Paint, transitionFuncs ...PaintTransitionFunction) error { - genericTxFunc := func(existing, desired runtime.Object) error { - for _, txFunc := range transitionFuncs { - if err := txFunc(existing.(*Paint), desired.(*Paint)); err != nil { - return err - } - } - return nil - } - _, err := controllerutils.Upsert(ctx, c.client, obj, genericTxFunc) - return err + genericTxFunc := func(existing, desired runtime.Object) error { + for _, txFunc := range transitionFuncs { + if err := txFunc(existing.(*Paint), desired.(*Paint)); err != nil { + return err + } + } + return nil + } + _, err := controllerutils.Upsert(ctx, c.client, obj, genericTxFunc) + return err } func (c *paintClient) UpdatePaintStatus(ctx context.Context, obj *Paint, opts ...client.SubResourceUpdateOption) error { - return c.client.Status().Update(ctx, obj, opts...) + return c.client.Status().Update(ctx, obj, opts...) } func (c *paintClient) PatchPaintStatus(ctx context.Context, obj *Paint, patch client.Patch, opts ...client.SubResourcePatchOption) error { - return c.client.Status().Patch(ctx, obj, patch, opts...) + return c.client.Status().Patch(ctx, obj, patch, opts...) } // Provides PaintClients for multiple clusters. type MulticlusterPaintClient interface { - // Cluster returns a PaintClient for the given cluster - Cluster(cluster string) (PaintClient, error) + // Cluster returns a PaintClient for the given cluster + Cluster(cluster string) (PaintClient, error) } type multiclusterPaintClient struct { - client multicluster.Client + client multicluster.Client } func NewMulticlusterPaintClient(client multicluster.Client) MulticlusterPaintClient { - return &multiclusterPaintClient{client: client} + return &multiclusterPaintClient{client: client} } func (m *multiclusterPaintClient) Cluster(cluster string) (PaintClient, error) { - client, err := m.client.Cluster(cluster) - if err != nil { - return nil, err - } - return NewPaintClient(client), nil + client, err := m.client.Cluster(cluster) + if err != nil { + return nil, err + } + return NewPaintClient(client), nil } // Reader knows how to read and list ClusterResources. type ClusterResourceReader interface { - // Get retrieves a ClusterResource for the given object key - GetClusterResource(ctx context.Context, name string) (*ClusterResource, error) + // Get retrieves a ClusterResource for the given object key + GetClusterResource(ctx context.Context, name string) (*ClusterResource, error) - // List retrieves list of ClusterResources for a given namespace and list options. - ListClusterResource(ctx context.Context, opts ...client.ListOption) (*ClusterResourceList, error) + // List retrieves list of ClusterResources for a given namespace and list options. + ListClusterResource(ctx context.Context, opts ...client.ListOption) (*ClusterResourceList, error) } // ClusterResourceTransitionFunction instructs the ClusterResourceWriter how to transition between an existing @@ -239,133 +234,131 @@ type ClusterResourceTransitionFunction func(existing, desired *ClusterResource) // Writer knows how to create, delete, and update ClusterResources. type ClusterResourceWriter interface { - // Create saves the ClusterResource object. - CreateClusterResource(ctx context.Context, obj *ClusterResource, opts ...client.CreateOption) error + // Create saves the ClusterResource object. + CreateClusterResource(ctx context.Context, obj *ClusterResource, opts ...client.CreateOption) error - // Delete deletes the ClusterResource object. - DeleteClusterResource(ctx context.Context, name string, opts ...client.DeleteOption) error + // Delete deletes the ClusterResource object. + DeleteClusterResource(ctx context.Context, name string, opts ...client.DeleteOption) error - // Update updates the given ClusterResource object. - UpdateClusterResource(ctx context.Context, obj *ClusterResource, opts ...client.UpdateOption) error + // Update updates the given ClusterResource object. + UpdateClusterResource(ctx context.Context, obj *ClusterResource, opts ...client.UpdateOption) error - // Patch patches the given ClusterResource object. - PatchClusterResource(ctx context.Context, obj *ClusterResource, patch client.Patch, opts ...client.PatchOption) error + // Patch patches the given ClusterResource object. + PatchClusterResource(ctx context.Context, obj *ClusterResource, patch client.Patch, opts ...client.PatchOption) error - // DeleteAllOf deletes all ClusterResource objects matching the given options. - DeleteAllOfClusterResource(ctx context.Context, opts ...client.DeleteAllOfOption) error + // DeleteAllOf deletes all ClusterResource objects matching the given options. + DeleteAllOfClusterResource(ctx context.Context, opts ...client.DeleteAllOfOption) error - // Create or Update the ClusterResource object. - UpsertClusterResource(ctx context.Context, obj *ClusterResource, transitionFuncs ...ClusterResourceTransitionFunction) error + // Create or Update the ClusterResource object. + UpsertClusterResource(ctx context.Context, obj *ClusterResource, transitionFuncs ...ClusterResourceTransitionFunction) error } // StatusWriter knows how to update status subresource of a ClusterResource object. type ClusterResourceStatusWriter interface { - // Update updates the fields corresponding to the status subresource for the - // given ClusterResource object. - UpdateClusterResourceStatus(ctx context.Context, obj *ClusterResource, opts ...client.SubResourceUpdateOption) error + // Update updates the fields corresponding to the status subresource for the + // given ClusterResource object. + UpdateClusterResourceStatus(ctx context.Context, obj *ClusterResource, opts ...client.SubResourceUpdateOption) error - // Patch patches the given ClusterResource object's subresource. - PatchClusterResourceStatus(ctx context.Context, obj *ClusterResource, patch client.Patch, opts ...client.SubResourcePatchOption) error + // Patch patches the given ClusterResource object's subresource. + PatchClusterResourceStatus(ctx context.Context, obj *ClusterResource, patch client.Patch, opts ...client.SubResourcePatchOption) error } // Client knows how to perform CRUD operations on ClusterResources. type ClusterResourceClient interface { - ClusterResourceReader - ClusterResourceWriter - ClusterResourceStatusWriter + ClusterResourceReader + ClusterResourceWriter + ClusterResourceStatusWriter } type clusterResourceClient struct { - client client.Client + client client.Client } func NewClusterResourceClient(client client.Client) *clusterResourceClient { - return &clusterResourceClient{client: client} + return &clusterResourceClient{client: client} } - func (c *clusterResourceClient) GetClusterResource(ctx context.Context, name string) (*ClusterResource, error) { - obj := &ClusterResource{} - key := client.ObjectKey{ - Name: name, - } - if err := c.client.Get(ctx, key, obj); err != nil { - return nil, err - } - return obj, nil + obj := &ClusterResource{} + key := client.ObjectKey{ + Name: name, + } + if err := c.client.Get(ctx, key, obj); err != nil { + return nil, err + } + return obj, nil } func (c *clusterResourceClient) ListClusterResource(ctx context.Context, opts ...client.ListOption) (*ClusterResourceList, error) { - list := &ClusterResourceList{} - if err := c.client.List(ctx, list, opts...); err != nil { - return nil, err - } - return list, nil + list := &ClusterResourceList{} + if err := c.client.List(ctx, list, opts...); err != nil { + return nil, err + } + return list, nil } func (c *clusterResourceClient) CreateClusterResource(ctx context.Context, obj *ClusterResource, opts ...client.CreateOption) error { - return c.client.Create(ctx, obj, opts...) + return c.client.Create(ctx, obj, opts...) } - func (c *clusterResourceClient) DeleteClusterResource(ctx context.Context, name string, opts ...client.DeleteOption) error { - obj := &ClusterResource{} - obj.SetName(name) - return c.client.Delete(ctx, obj, opts...) + obj := &ClusterResource{} + obj.SetName(name) + return c.client.Delete(ctx, obj, opts...) } func (c *clusterResourceClient) UpdateClusterResource(ctx context.Context, obj *ClusterResource, opts ...client.UpdateOption) error { - return c.client.Update(ctx, obj, opts...) + return c.client.Update(ctx, obj, opts...) } func (c *clusterResourceClient) PatchClusterResource(ctx context.Context, obj *ClusterResource, patch client.Patch, opts ...client.PatchOption) error { - return c.client.Patch(ctx, obj, patch, opts...) + return c.client.Patch(ctx, obj, patch, opts...) } func (c *clusterResourceClient) DeleteAllOfClusterResource(ctx context.Context, opts ...client.DeleteAllOfOption) error { - obj := &ClusterResource{} - return c.client.DeleteAllOf(ctx, obj, opts...) + obj := &ClusterResource{} + return c.client.DeleteAllOf(ctx, obj, opts...) } func (c *clusterResourceClient) UpsertClusterResource(ctx context.Context, obj *ClusterResource, transitionFuncs ...ClusterResourceTransitionFunction) error { - genericTxFunc := func(existing, desired runtime.Object) error { - for _, txFunc := range transitionFuncs { - if err := txFunc(existing.(*ClusterResource), desired.(*ClusterResource)); err != nil { - return err - } - } - return nil - } - _, err := controllerutils.Upsert(ctx, c.client, obj, genericTxFunc) - return err + genericTxFunc := func(existing, desired runtime.Object) error { + for _, txFunc := range transitionFuncs { + if err := txFunc(existing.(*ClusterResource), desired.(*ClusterResource)); err != nil { + return err + } + } + return nil + } + _, err := controllerutils.Upsert(ctx, c.client, obj, genericTxFunc) + return err } func (c *clusterResourceClient) UpdateClusterResourceStatus(ctx context.Context, obj *ClusterResource, opts ...client.SubResourceUpdateOption) error { - return c.client.Status().Update(ctx, obj, opts...) + return c.client.Status().Update(ctx, obj, opts...) } func (c *clusterResourceClient) PatchClusterResourceStatus(ctx context.Context, obj *ClusterResource, patch client.Patch, opts ...client.SubResourcePatchOption) error { - return c.client.Status().Patch(ctx, obj, patch, opts...) + return c.client.Status().Patch(ctx, obj, patch, opts...) } // Provides ClusterResourceClients for multiple clusters. type MulticlusterClusterResourceClient interface { - // Cluster returns a ClusterResourceClient for the given cluster - Cluster(cluster string) (ClusterResourceClient, error) + // Cluster returns a ClusterResourceClient for the given cluster + Cluster(cluster string) (ClusterResourceClient, error) } type multiclusterClusterResourceClient struct { - client multicluster.Client + client multicluster.Client } func NewMulticlusterClusterResourceClient(client multicluster.Client) MulticlusterClusterResourceClient { - return &multiclusterClusterResourceClient{client: client} + return &multiclusterClusterResourceClient{client: client} } func (m *multiclusterClusterResourceClient) Cluster(cluster string) (ClusterResourceClient, error) { - client, err := m.client.Cluster(cluster) - if err != nil { - return nil, err - } - return NewClusterResourceClient(client), nil -} \ No newline at end of file + client, err := m.client.Cluster(cluster) + if err != nil { + return nil, err + } + return NewClusterResourceClient(client), nil +} diff --git a/codegen/test/api/things.test.io/v1/controller/event_handlers.go b/codegen/test/api/things.test.io/v1/controller/event_handlers.go index 066691b25..3c52ed1f6 100644 --- a/codegen/test/api/things.test.io/v1/controller/event_handlers.go +++ b/codegen/test/api/things.test.io/v1/controller/event_handlers.go @@ -8,225 +8,225 @@ package controller import ( "context" - things_test_io_v1 "github.com/solo-io/skv2/codegen/test/api/things.test.io/v1" + things_test_io_v1 "github.com/solo-io/skv2/codegen/test/api/things.test.io/v1" - "github.com/pkg/errors" - "github.com/solo-io/skv2/pkg/events" - "sigs.k8s.io/controller-runtime/pkg/manager" - "sigs.k8s.io/controller-runtime/pkg/predicate" - "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/pkg/errors" + "github.com/solo-io/skv2/pkg/events" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/manager" + "sigs.k8s.io/controller-runtime/pkg/predicate" ) // Handle events for the Paint Resource // DEPRECATED: Prefer reconciler pattern. type PaintEventHandler interface { - CreatePaint(obj *things_test_io_v1.Paint) error - UpdatePaint(old, new *things_test_io_v1.Paint) error - DeletePaint(obj *things_test_io_v1.Paint) error - GenericPaint(obj *things_test_io_v1.Paint) error + CreatePaint(obj *things_test_io_v1.Paint) error + UpdatePaint(old, new *things_test_io_v1.Paint) error + DeletePaint(obj *things_test_io_v1.Paint) error + GenericPaint(obj *things_test_io_v1.Paint) error } type PaintEventHandlerFuncs struct { - OnCreate func(obj *things_test_io_v1.Paint) error - OnUpdate func(old, new *things_test_io_v1.Paint) error - OnDelete func(obj *things_test_io_v1.Paint) error - OnGeneric func(obj *things_test_io_v1.Paint) error + OnCreate func(obj *things_test_io_v1.Paint) error + OnUpdate func(old, new *things_test_io_v1.Paint) error + OnDelete func(obj *things_test_io_v1.Paint) error + OnGeneric func(obj *things_test_io_v1.Paint) error } func (f *PaintEventHandlerFuncs) CreatePaint(obj *things_test_io_v1.Paint) error { - if f.OnCreate == nil { - return nil - } - return f.OnCreate(obj) + if f.OnCreate == nil { + return nil + } + return f.OnCreate(obj) } func (f *PaintEventHandlerFuncs) DeletePaint(obj *things_test_io_v1.Paint) error { - if f.OnDelete == nil { - return nil - } - return f.OnDelete(obj) + if f.OnDelete == nil { + return nil + } + return f.OnDelete(obj) } func (f *PaintEventHandlerFuncs) UpdatePaint(objOld, objNew *things_test_io_v1.Paint) error { - if f.OnUpdate == nil { - return nil - } - return f.OnUpdate(objOld, objNew) + if f.OnUpdate == nil { + return nil + } + return f.OnUpdate(objOld, objNew) } func (f *PaintEventHandlerFuncs) GenericPaint(obj *things_test_io_v1.Paint) error { - if f.OnGeneric == nil { - return nil - } - return f.OnGeneric(obj) + if f.OnGeneric == nil { + return nil + } + return f.OnGeneric(obj) } type PaintEventWatcher interface { - AddEventHandler(ctx context.Context, h PaintEventHandler, predicates ...predicate.Predicate) error + AddEventHandler(ctx context.Context, h PaintEventHandler, predicates ...predicate.Predicate) error } type paintEventWatcher struct { - watcher events.EventWatcher + watcher events.EventWatcher } func NewPaintEventWatcher(name string, mgr manager.Manager) PaintEventWatcher { - return &paintEventWatcher{ - watcher: events.NewWatcher(name, mgr, &things_test_io_v1.Paint{}), - } + return &paintEventWatcher{ + watcher: events.NewWatcher(name, mgr, &things_test_io_v1.Paint{}), + } } func (c *paintEventWatcher) AddEventHandler(ctx context.Context, h PaintEventHandler, predicates ...predicate.Predicate) error { handler := genericPaintHandler{handler: h} - if err := c.watcher.Watch(ctx, handler, predicates...); err != nil{ - return err - } - return nil + if err := c.watcher.Watch(ctx, handler, predicates...); err != nil { + return err + } + return nil } // genericPaintHandler implements a generic events.EventHandler type genericPaintHandler struct { - handler PaintEventHandler + handler PaintEventHandler } func (h genericPaintHandler) Create(object client.Object) error { - obj, ok := object.(*things_test_io_v1.Paint) - if !ok { - return errors.Errorf("internal error: Paint handler received event for %T", object) - } - return h.handler.CreatePaint(obj) + obj, ok := object.(*things_test_io_v1.Paint) + if !ok { + return errors.Errorf("internal error: Paint handler received event for %T", object) + } + return h.handler.CreatePaint(obj) } func (h genericPaintHandler) Delete(object client.Object) error { - obj, ok := object.(*things_test_io_v1.Paint) - if !ok { - return errors.Errorf("internal error: Paint handler received event for %T", object) - } - return h.handler.DeletePaint(obj) + obj, ok := object.(*things_test_io_v1.Paint) + if !ok { + return errors.Errorf("internal error: Paint handler received event for %T", object) + } + return h.handler.DeletePaint(obj) } func (h genericPaintHandler) Update(old, new client.Object) error { - objOld, ok := old.(*things_test_io_v1.Paint) - if !ok { - return errors.Errorf("internal error: Paint handler received event for %T", old) - } - objNew, ok := new.(*things_test_io_v1.Paint) - if !ok { - return errors.Errorf("internal error: Paint handler received event for %T", new) - } - return h.handler.UpdatePaint(objOld, objNew) + objOld, ok := old.(*things_test_io_v1.Paint) + if !ok { + return errors.Errorf("internal error: Paint handler received event for %T", old) + } + objNew, ok := new.(*things_test_io_v1.Paint) + if !ok { + return errors.Errorf("internal error: Paint handler received event for %T", new) + } + return h.handler.UpdatePaint(objOld, objNew) } func (h genericPaintHandler) Generic(object client.Object) error { - obj, ok := object.(*things_test_io_v1.Paint) - if !ok { - return errors.Errorf("internal error: Paint handler received event for %T", object) - } - return h.handler.GenericPaint(obj) + obj, ok := object.(*things_test_io_v1.Paint) + if !ok { + return errors.Errorf("internal error: Paint handler received event for %T", object) + } + return h.handler.GenericPaint(obj) } // Handle events for the ClusterResource Resource // DEPRECATED: Prefer reconciler pattern. type ClusterResourceEventHandler interface { - CreateClusterResource(obj *things_test_io_v1.ClusterResource) error - UpdateClusterResource(old, new *things_test_io_v1.ClusterResource) error - DeleteClusterResource(obj *things_test_io_v1.ClusterResource) error - GenericClusterResource(obj *things_test_io_v1.ClusterResource) error + CreateClusterResource(obj *things_test_io_v1.ClusterResource) error + UpdateClusterResource(old, new *things_test_io_v1.ClusterResource) error + DeleteClusterResource(obj *things_test_io_v1.ClusterResource) error + GenericClusterResource(obj *things_test_io_v1.ClusterResource) error } type ClusterResourceEventHandlerFuncs struct { - OnCreate func(obj *things_test_io_v1.ClusterResource) error - OnUpdate func(old, new *things_test_io_v1.ClusterResource) error - OnDelete func(obj *things_test_io_v1.ClusterResource) error - OnGeneric func(obj *things_test_io_v1.ClusterResource) error + OnCreate func(obj *things_test_io_v1.ClusterResource) error + OnUpdate func(old, new *things_test_io_v1.ClusterResource) error + OnDelete func(obj *things_test_io_v1.ClusterResource) error + OnGeneric func(obj *things_test_io_v1.ClusterResource) error } func (f *ClusterResourceEventHandlerFuncs) CreateClusterResource(obj *things_test_io_v1.ClusterResource) error { - if f.OnCreate == nil { - return nil - } - return f.OnCreate(obj) + if f.OnCreate == nil { + return nil + } + return f.OnCreate(obj) } func (f *ClusterResourceEventHandlerFuncs) DeleteClusterResource(obj *things_test_io_v1.ClusterResource) error { - if f.OnDelete == nil { - return nil - } - return f.OnDelete(obj) + if f.OnDelete == nil { + return nil + } + return f.OnDelete(obj) } func (f *ClusterResourceEventHandlerFuncs) UpdateClusterResource(objOld, objNew *things_test_io_v1.ClusterResource) error { - if f.OnUpdate == nil { - return nil - } - return f.OnUpdate(objOld, objNew) + if f.OnUpdate == nil { + return nil + } + return f.OnUpdate(objOld, objNew) } func (f *ClusterResourceEventHandlerFuncs) GenericClusterResource(obj *things_test_io_v1.ClusterResource) error { - if f.OnGeneric == nil { - return nil - } - return f.OnGeneric(obj) + if f.OnGeneric == nil { + return nil + } + return f.OnGeneric(obj) } type ClusterResourceEventWatcher interface { - AddEventHandler(ctx context.Context, h ClusterResourceEventHandler, predicates ...predicate.Predicate) error + AddEventHandler(ctx context.Context, h ClusterResourceEventHandler, predicates ...predicate.Predicate) error } type clusterResourceEventWatcher struct { - watcher events.EventWatcher + watcher events.EventWatcher } func NewClusterResourceEventWatcher(name string, mgr manager.Manager) ClusterResourceEventWatcher { - return &clusterResourceEventWatcher{ - watcher: events.NewWatcher(name, mgr, &things_test_io_v1.ClusterResource{}), - } + return &clusterResourceEventWatcher{ + watcher: events.NewWatcher(name, mgr, &things_test_io_v1.ClusterResource{}), + } } func (c *clusterResourceEventWatcher) AddEventHandler(ctx context.Context, h ClusterResourceEventHandler, predicates ...predicate.Predicate) error { handler := genericClusterResourceHandler{handler: h} - if err := c.watcher.Watch(ctx, handler, predicates...); err != nil{ - return err - } - return nil + if err := c.watcher.Watch(ctx, handler, predicates...); err != nil { + return err + } + return nil } // genericClusterResourceHandler implements a generic events.EventHandler type genericClusterResourceHandler struct { - handler ClusterResourceEventHandler + handler ClusterResourceEventHandler } func (h genericClusterResourceHandler) Create(object client.Object) error { - obj, ok := object.(*things_test_io_v1.ClusterResource) - if !ok { - return errors.Errorf("internal error: ClusterResource handler received event for %T", object) - } - return h.handler.CreateClusterResource(obj) + obj, ok := object.(*things_test_io_v1.ClusterResource) + if !ok { + return errors.Errorf("internal error: ClusterResource handler received event for %T", object) + } + return h.handler.CreateClusterResource(obj) } func (h genericClusterResourceHandler) Delete(object client.Object) error { - obj, ok := object.(*things_test_io_v1.ClusterResource) - if !ok { - return errors.Errorf("internal error: ClusterResource handler received event for %T", object) - } - return h.handler.DeleteClusterResource(obj) + obj, ok := object.(*things_test_io_v1.ClusterResource) + if !ok { + return errors.Errorf("internal error: ClusterResource handler received event for %T", object) + } + return h.handler.DeleteClusterResource(obj) } func (h genericClusterResourceHandler) Update(old, new client.Object) error { - objOld, ok := old.(*things_test_io_v1.ClusterResource) - if !ok { - return errors.Errorf("internal error: ClusterResource handler received event for %T", old) - } - objNew, ok := new.(*things_test_io_v1.ClusterResource) - if !ok { - return errors.Errorf("internal error: ClusterResource handler received event for %T", new) - } - return h.handler.UpdateClusterResource(objOld, objNew) + objOld, ok := old.(*things_test_io_v1.ClusterResource) + if !ok { + return errors.Errorf("internal error: ClusterResource handler received event for %T", old) + } + objNew, ok := new.(*things_test_io_v1.ClusterResource) + if !ok { + return errors.Errorf("internal error: ClusterResource handler received event for %T", new) + } + return h.handler.UpdateClusterResource(objOld, objNew) } func (h genericClusterResourceHandler) Generic(object client.Object) error { - obj, ok := object.(*things_test_io_v1.ClusterResource) - if !ok { - return errors.Errorf("internal error: ClusterResource handler received event for %T", object) - } - return h.handler.GenericClusterResource(obj) + obj, ok := object.(*things_test_io_v1.ClusterResource) + if !ok { + return errors.Errorf("internal error: ClusterResource handler received event for %T", object) + } + return h.handler.GenericClusterResource(obj) } diff --git a/codegen/test/api/things.test.io/v1/controller/multicluster_reconcilers.go b/codegen/test/api/things.test.io/v1/controller/multicluster_reconcilers.go index 237ee95a0..fbfe2e86e 100644 --- a/codegen/test/api/things.test.io/v1/controller/multicluster_reconcilers.go +++ b/codegen/test/api/things.test.io/v1/controller/multicluster_reconcilers.go @@ -5,8 +5,6 @@ // Definitions for the multicluster Kubernetes Controllers package controller - - import ( "context" diff --git a/codegen/test/api/things.test.io/v1/controller/reconcilers.go b/codegen/test/api/things.test.io/v1/controller/reconcilers.go index a04151fb4..355e61896 100644 --- a/codegen/test/api/things.test.io/v1/controller/reconcilers.go +++ b/codegen/test/api/things.test.io/v1/controller/reconcilers.go @@ -5,24 +5,22 @@ // Definitions for the Kubernetes Controllers package controller - - import ( "context" - things_test_io_v1 "github.com/solo-io/skv2/codegen/test/api/things.test.io/v1" + things_test_io_v1 "github.com/solo-io/skv2/codegen/test/api/things.test.io/v1" - "github.com/pkg/errors" - "github.com/solo-io/skv2/pkg/ezkube" - "github.com/solo-io/skv2/pkg/reconcile" - "sigs.k8s.io/controller-runtime/pkg/manager" - "sigs.k8s.io/controller-runtime/pkg/predicate" + "github.com/pkg/errors" + "github.com/solo-io/skv2/pkg/ezkube" + "github.com/solo-io/skv2/pkg/reconcile" + "sigs.k8s.io/controller-runtime/pkg/manager" + "sigs.k8s.io/controller-runtime/pkg/predicate" ) // Reconcile Upsert events for the Paint Resource. // implemented by the user type PaintReconciler interface { - ReconcilePaint(obj *things_test_io_v1.Paint) (reconcile.Result, error) + ReconcilePaint(obj *things_test_io_v1.Paint) (reconcile.Result, error) } // Reconcile deletion events for the Paint Resource. @@ -30,117 +28,116 @@ type PaintReconciler interface { // before being deleted. // implemented by the user type PaintDeletionReconciler interface { - ReconcilePaintDeletion(req reconcile.Request) error + ReconcilePaintDeletion(req reconcile.Request) error } type PaintReconcilerFuncs struct { - OnReconcilePaint func(obj *things_test_io_v1.Paint) (reconcile.Result, error) - OnReconcilePaintDeletion func(req reconcile.Request) error + OnReconcilePaint func(obj *things_test_io_v1.Paint) (reconcile.Result, error) + OnReconcilePaintDeletion func(req reconcile.Request) error } func (f *PaintReconcilerFuncs) ReconcilePaint(obj *things_test_io_v1.Paint) (reconcile.Result, error) { - if f.OnReconcilePaint == nil { - return reconcile.Result{}, nil - } - return f.OnReconcilePaint(obj) + if f.OnReconcilePaint == nil { + return reconcile.Result{}, nil + } + return f.OnReconcilePaint(obj) } func (f *PaintReconcilerFuncs) ReconcilePaintDeletion(req reconcile.Request) error { - if f.OnReconcilePaintDeletion == nil { - return nil - } - return f.OnReconcilePaintDeletion(req) + if f.OnReconcilePaintDeletion == nil { + return nil + } + return f.OnReconcilePaintDeletion(req) } // Reconcile and finalize the Paint Resource // implemented by the user type PaintFinalizer interface { - PaintReconciler + PaintReconciler - // name of the finalizer used by this handler. - // finalizer names should be unique for a single task - PaintFinalizerName() string + // name of the finalizer used by this handler. + // finalizer names should be unique for a single task + PaintFinalizerName() string - // finalize the object before it is deleted. - // Watchers created with a finalizing handler will a - FinalizePaint(obj *things_test_io_v1.Paint) error + // finalize the object before it is deleted. + // Watchers created with a finalizing handler will a + FinalizePaint(obj *things_test_io_v1.Paint) error } type PaintReconcileLoop interface { - RunPaintReconciler(ctx context.Context, rec PaintReconciler, predicates ...predicate.Predicate) error + RunPaintReconciler(ctx context.Context, rec PaintReconciler, predicates ...predicate.Predicate) error } type paintReconcileLoop struct { - loop reconcile.Loop + loop reconcile.Loop } func NewPaintReconcileLoop(name string, mgr manager.Manager, options reconcile.Options) PaintReconcileLoop { - return &paintReconcileLoop{ - // empty cluster indicates this reconciler is built for the local cluster - loop: reconcile.NewLoop(name, "", mgr, &things_test_io_v1.Paint{}, options), - } + return &paintReconcileLoop{ + // empty cluster indicates this reconciler is built for the local cluster + loop: reconcile.NewLoop(name, "", mgr, &things_test_io_v1.Paint{}, options), + } } func (c *paintReconcileLoop) RunPaintReconciler(ctx context.Context, reconciler PaintReconciler, predicates ...predicate.Predicate) error { - genericReconciler := genericPaintReconciler{ - reconciler: reconciler, - } + genericReconciler := genericPaintReconciler{ + reconciler: reconciler, + } var reconcilerWrapper reconcile.Reconciler if finalizingReconciler, ok := reconciler.(PaintFinalizer); ok { - reconcilerWrapper = genericPaintFinalizer{ - genericPaintReconciler: genericReconciler, - finalizingReconciler: finalizingReconciler, - } - } else { - reconcilerWrapper = genericReconciler - } + reconcilerWrapper = genericPaintFinalizer{ + genericPaintReconciler: genericReconciler, + finalizingReconciler: finalizingReconciler, + } + } else { + reconcilerWrapper = genericReconciler + } return c.loop.RunReconciler(ctx, reconcilerWrapper, predicates...) } // genericPaintHandler implements a generic reconcile.Reconciler type genericPaintReconciler struct { - reconciler PaintReconciler + reconciler PaintReconciler } func (r genericPaintReconciler) Reconcile(object ezkube.Object) (reconcile.Result, error) { - obj, ok := object.(*things_test_io_v1.Paint) - if !ok { - return reconcile.Result{}, errors.Errorf("internal error: Paint handler received event for %T", object) - } - return r.reconciler.ReconcilePaint(obj) + obj, ok := object.(*things_test_io_v1.Paint) + if !ok { + return reconcile.Result{}, errors.Errorf("internal error: Paint handler received event for %T", object) + } + return r.reconciler.ReconcilePaint(obj) } func (r genericPaintReconciler) ReconcileDeletion(request reconcile.Request) error { - if deletionReconciler, ok := r.reconciler.(PaintDeletionReconciler); ok { - return deletionReconciler.ReconcilePaintDeletion(request) - } - return nil + if deletionReconciler, ok := r.reconciler.(PaintDeletionReconciler); ok { + return deletionReconciler.ReconcilePaintDeletion(request) + } + return nil } // genericPaintFinalizer implements a generic reconcile.FinalizingReconciler type genericPaintFinalizer struct { - genericPaintReconciler - finalizingReconciler PaintFinalizer + genericPaintReconciler + finalizingReconciler PaintFinalizer } - func (r genericPaintFinalizer) FinalizerName() string { - return r.finalizingReconciler.PaintFinalizerName() + return r.finalizingReconciler.PaintFinalizerName() } func (r genericPaintFinalizer) Finalize(object ezkube.Object) error { - obj, ok := object.(*things_test_io_v1.Paint) - if !ok { - return errors.Errorf("internal error: Paint handler received event for %T", object) - } - return r.finalizingReconciler.FinalizePaint(obj) + obj, ok := object.(*things_test_io_v1.Paint) + if !ok { + return errors.Errorf("internal error: Paint handler received event for %T", object) + } + return r.finalizingReconciler.FinalizePaint(obj) } // Reconcile Upsert events for the ClusterResource Resource. // implemented by the user type ClusterResourceReconciler interface { - ReconcileClusterResource(obj *things_test_io_v1.ClusterResource) (reconcile.Result, error) + ReconcileClusterResource(obj *things_test_io_v1.ClusterResource) (reconcile.Result, error) } // Reconcile deletion events for the ClusterResource Resource. @@ -148,109 +145,108 @@ type ClusterResourceReconciler interface { // before being deleted. // implemented by the user type ClusterResourceDeletionReconciler interface { - ReconcileClusterResourceDeletion(req reconcile.Request) error + ReconcileClusterResourceDeletion(req reconcile.Request) error } type ClusterResourceReconcilerFuncs struct { - OnReconcileClusterResource func(obj *things_test_io_v1.ClusterResource) (reconcile.Result, error) - OnReconcileClusterResourceDeletion func(req reconcile.Request) error + OnReconcileClusterResource func(obj *things_test_io_v1.ClusterResource) (reconcile.Result, error) + OnReconcileClusterResourceDeletion func(req reconcile.Request) error } func (f *ClusterResourceReconcilerFuncs) ReconcileClusterResource(obj *things_test_io_v1.ClusterResource) (reconcile.Result, error) { - if f.OnReconcileClusterResource == nil { - return reconcile.Result{}, nil - } - return f.OnReconcileClusterResource(obj) + if f.OnReconcileClusterResource == nil { + return reconcile.Result{}, nil + } + return f.OnReconcileClusterResource(obj) } func (f *ClusterResourceReconcilerFuncs) ReconcileClusterResourceDeletion(req reconcile.Request) error { - if f.OnReconcileClusterResourceDeletion == nil { - return nil - } - return f.OnReconcileClusterResourceDeletion(req) + if f.OnReconcileClusterResourceDeletion == nil { + return nil + } + return f.OnReconcileClusterResourceDeletion(req) } // Reconcile and finalize the ClusterResource Resource // implemented by the user type ClusterResourceFinalizer interface { - ClusterResourceReconciler + ClusterResourceReconciler - // name of the finalizer used by this handler. - // finalizer names should be unique for a single task - ClusterResourceFinalizerName() string + // name of the finalizer used by this handler. + // finalizer names should be unique for a single task + ClusterResourceFinalizerName() string - // finalize the object before it is deleted. - // Watchers created with a finalizing handler will a - FinalizeClusterResource(obj *things_test_io_v1.ClusterResource) error + // finalize the object before it is deleted. + // Watchers created with a finalizing handler will a + FinalizeClusterResource(obj *things_test_io_v1.ClusterResource) error } type ClusterResourceReconcileLoop interface { - RunClusterResourceReconciler(ctx context.Context, rec ClusterResourceReconciler, predicates ...predicate.Predicate) error + RunClusterResourceReconciler(ctx context.Context, rec ClusterResourceReconciler, predicates ...predicate.Predicate) error } type clusterResourceReconcileLoop struct { - loop reconcile.Loop + loop reconcile.Loop } func NewClusterResourceReconcileLoop(name string, mgr manager.Manager, options reconcile.Options) ClusterResourceReconcileLoop { - return &clusterResourceReconcileLoop{ - // empty cluster indicates this reconciler is built for the local cluster - loop: reconcile.NewLoop(name, "", mgr, &things_test_io_v1.ClusterResource{}, options), - } + return &clusterResourceReconcileLoop{ + // empty cluster indicates this reconciler is built for the local cluster + loop: reconcile.NewLoop(name, "", mgr, &things_test_io_v1.ClusterResource{}, options), + } } func (c *clusterResourceReconcileLoop) RunClusterResourceReconciler(ctx context.Context, reconciler ClusterResourceReconciler, predicates ...predicate.Predicate) error { - genericReconciler := genericClusterResourceReconciler{ - reconciler: reconciler, - } + genericReconciler := genericClusterResourceReconciler{ + reconciler: reconciler, + } var reconcilerWrapper reconcile.Reconciler if finalizingReconciler, ok := reconciler.(ClusterResourceFinalizer); ok { - reconcilerWrapper = genericClusterResourceFinalizer{ - genericClusterResourceReconciler: genericReconciler, - finalizingReconciler: finalizingReconciler, - } - } else { - reconcilerWrapper = genericReconciler - } + reconcilerWrapper = genericClusterResourceFinalizer{ + genericClusterResourceReconciler: genericReconciler, + finalizingReconciler: finalizingReconciler, + } + } else { + reconcilerWrapper = genericReconciler + } return c.loop.RunReconciler(ctx, reconcilerWrapper, predicates...) } // genericClusterResourceHandler implements a generic reconcile.Reconciler type genericClusterResourceReconciler struct { - reconciler ClusterResourceReconciler + reconciler ClusterResourceReconciler } func (r genericClusterResourceReconciler) Reconcile(object ezkube.Object) (reconcile.Result, error) { - obj, ok := object.(*things_test_io_v1.ClusterResource) - if !ok { - return reconcile.Result{}, errors.Errorf("internal error: ClusterResource handler received event for %T", object) - } - return r.reconciler.ReconcileClusterResource(obj) + obj, ok := object.(*things_test_io_v1.ClusterResource) + if !ok { + return reconcile.Result{}, errors.Errorf("internal error: ClusterResource handler received event for %T", object) + } + return r.reconciler.ReconcileClusterResource(obj) } func (r genericClusterResourceReconciler) ReconcileDeletion(request reconcile.Request) error { - if deletionReconciler, ok := r.reconciler.(ClusterResourceDeletionReconciler); ok { - return deletionReconciler.ReconcileClusterResourceDeletion(request) - } - return nil + if deletionReconciler, ok := r.reconciler.(ClusterResourceDeletionReconciler); ok { + return deletionReconciler.ReconcileClusterResourceDeletion(request) + } + return nil } // genericClusterResourceFinalizer implements a generic reconcile.FinalizingReconciler type genericClusterResourceFinalizer struct { - genericClusterResourceReconciler - finalizingReconciler ClusterResourceFinalizer + genericClusterResourceReconciler + finalizingReconciler ClusterResourceFinalizer } - func (r genericClusterResourceFinalizer) FinalizerName() string { - return r.finalizingReconciler.ClusterResourceFinalizerName() + return r.finalizingReconciler.ClusterResourceFinalizerName() } func (r genericClusterResourceFinalizer) Finalize(object ezkube.Object) error { - obj, ok := object.(*things_test_io_v1.ClusterResource) - if !ok { - return errors.Errorf("internal error: ClusterResource handler received event for %T", object) - } - return r.finalizingReconciler.FinalizeClusterResource(obj) + obj, ok := object.(*things_test_io_v1.ClusterResource) + if !ok { + return errors.Errorf("internal error: ClusterResource handler received event for %T", object) + } + return r.finalizingReconciler.FinalizeClusterResource(obj) } diff --git a/codegen/test/api/things.test.io/v1/json.gen.go b/codegen/test/api/things.test.io/v1/json.gen.go index d7582f228..d8b4c1b0b 100644 --- a/codegen/test/api/things.test.io/v1/json.gen.go +++ b/codegen/test/api/things.test.io/v1/json.gen.go @@ -5,13 +5,13 @@ package v1 import ( - bytes "bytes" - fmt "fmt" - math "math" + bytes "bytes" + fmt "fmt" + math "math" - skv2jsonpb "github.com/solo-io/skv2/pkg/kube_jsonpb" - jsonpb "github.com/golang/protobuf/jsonpb" - proto "github.com/golang/protobuf/proto" + jsonpb "github.com/golang/protobuf/jsonpb" + proto "github.com/golang/protobuf/proto" + skv2jsonpb "github.com/solo-io/skv2/pkg/kube_jsonpb" ) // Reference imports to suppress errors if they are not otherwise used. @@ -20,12 +20,13 @@ var _ = fmt.Errorf var _ = math.Inf var ( - marshaller = &skv2jsonpb.Marshaler{} + marshaller = &skv2jsonpb.Marshaler{} unmarshaller = &jsonpb.Unmarshaler{ AllowUnknownFields: true, } strictUnmarshaller = &jsonpb.Unmarshaler{} ) + // MarshalJSON is a custom marshaler for PaintSpec func (this *PaintSpec) MarshalJSON() ([]byte, error) { str, err := marshaller.MarshalToString(this) @@ -36,6 +37,7 @@ func (this *PaintSpec) MarshalJSON() ([]byte, error) { func (this *PaintSpec) UnmarshalJSON(b []byte) error { return unmarshaller.Unmarshal(bytes.NewReader(b), this) } + // MarshalJSON is a custom marshaler for PaintStatus func (this *PaintStatus) MarshalJSON() ([]byte, error) { str, err := marshaller.MarshalToString(this) @@ -46,6 +48,7 @@ func (this *PaintStatus) MarshalJSON() ([]byte, error) { func (this *PaintStatus) UnmarshalJSON(b []byte) error { return unmarshaller.Unmarshal(bytes.NewReader(b), this) } + // MarshalJSON is a custom marshaler for ClusterResourceSpec func (this *ClusterResourceSpec) MarshalJSON() ([]byte, error) { str, err := marshaller.MarshalToString(this) diff --git a/codegen/test/api/things.test.io/v1/proto_deepcopy.go b/codegen/test/api/things.test.io/v1/proto_deepcopy.go index 30d4d08c0..7fe7a023f 100644 --- a/codegen/test/api/things.test.io/v1/proto_deepcopy.go +++ b/codegen/test/api/things.test.io/v1/proto_deepcopy.go @@ -5,36 +5,39 @@ package v1 import ( - proto "github.com/golang/protobuf/proto" + proto "github.com/golang/protobuf/proto" "github.com/solo-io/protoc-gen-ext/pkg/clone" ) + // DeepCopyInto for the Paint.Spec func (in *PaintSpec) DeepCopyInto(out *PaintSpec) { - var p *PaintSpec - if h, ok := interface{}(in).(clone.Cloner); ok { - p = h.Clone().(*PaintSpec) - } else { - p = proto.Clone(in).(*PaintSpec) - } - *out = *p + var p *PaintSpec + if h, ok := interface{}(in).(clone.Cloner); ok { + p = h.Clone().(*PaintSpec) + } else { + p = proto.Clone(in).(*PaintSpec) + } + *out = *p } + // DeepCopyInto for the Paint.Status func (in *PaintStatus) DeepCopyInto(out *PaintStatus) { - var p *PaintStatus - if h, ok := interface{}(in).(clone.Cloner); ok { - p = h.Clone().(*PaintStatus) - } else { - p = proto.Clone(in).(*PaintStatus) - } - *out = *p + var p *PaintStatus + if h, ok := interface{}(in).(clone.Cloner); ok { + p = h.Clone().(*PaintStatus) + } else { + p = proto.Clone(in).(*PaintStatus) + } + *out = *p } + // DeepCopyInto for the ClusterResource.Spec func (in *ClusterResourceSpec) DeepCopyInto(out *ClusterResourceSpec) { - var p *ClusterResourceSpec - if h, ok := interface{}(in).(clone.Cloner); ok { - p = h.Clone().(*ClusterResourceSpec) - } else { - p = proto.Clone(in).(*ClusterResourceSpec) - } - *out = *p + var p *ClusterResourceSpec + if h, ok := interface{}(in).(clone.Cloner); ok { + p = h.Clone().(*ClusterResourceSpec) + } else { + p = proto.Clone(in).(*ClusterResourceSpec) + } + *out = *p } diff --git a/codegen/test/api/things.test.io/v1/providers/client_providers.go b/codegen/test/api/things.test.io/v1/providers/client_providers.go index 53570c869..ea1c91a28 100644 --- a/codegen/test/api/things.test.io/v1/providers/client_providers.go +++ b/codegen/test/api/things.test.io/v1/providers/client_providers.go @@ -2,13 +2,11 @@ package v1 - - import ( - things_test_io_v1 "github.com/solo-io/skv2/codegen/test/api/things.test.io/v1" + things_test_io_v1 "github.com/solo-io/skv2/codegen/test/api/things.test.io/v1" - "k8s.io/client-go/rest" - "sigs.k8s.io/controller-runtime/pkg/client" + "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/client" ) /* @@ -21,56 +19,56 @@ import ( // Provider for PaintClient from Clientset func PaintClientFromClientsetProvider(clients things_test_io_v1.Clientset) things_test_io_v1.PaintClient { - return clients.Paints() + return clients.Paints() } // Provider for Paint Client from Client func PaintClientProvider(client client.Client) things_test_io_v1.PaintClient { - return things_test_io_v1.NewPaintClient(client) + return things_test_io_v1.NewPaintClient(client) } type PaintClientFactory func(client client.Client) things_test_io_v1.PaintClient func PaintClientFactoryProvider() PaintClientFactory { - return PaintClientProvider + return PaintClientProvider } type PaintClientFromConfigFactory func(cfg *rest.Config) (things_test_io_v1.PaintClient, error) func PaintClientFromConfigFactoryProvider() PaintClientFromConfigFactory { - return func(cfg *rest.Config) (things_test_io_v1.PaintClient, error) { - clients, err := things_test_io_v1.NewClientsetFromConfig(cfg) - if err != nil { - return nil, err - } - return clients.Paints(), nil - } + return func(cfg *rest.Config) (things_test_io_v1.PaintClient, error) { + clients, err := things_test_io_v1.NewClientsetFromConfig(cfg) + if err != nil { + return nil, err + } + return clients.Paints(), nil + } } // Provider for ClusterResourceClient from Clientset func ClusterResourceClientFromClientsetProvider(clients things_test_io_v1.Clientset) things_test_io_v1.ClusterResourceClient { - return clients.ClusterResources() + return clients.ClusterResources() } // Provider for ClusterResource Client from Client func ClusterResourceClientProvider(client client.Client) things_test_io_v1.ClusterResourceClient { - return things_test_io_v1.NewClusterResourceClient(client) + return things_test_io_v1.NewClusterResourceClient(client) } type ClusterResourceClientFactory func(client client.Client) things_test_io_v1.ClusterResourceClient func ClusterResourceClientFactoryProvider() ClusterResourceClientFactory { - return ClusterResourceClientProvider + return ClusterResourceClientProvider } type ClusterResourceClientFromConfigFactory func(cfg *rest.Config) (things_test_io_v1.ClusterResourceClient, error) func ClusterResourceClientFromConfigFactoryProvider() ClusterResourceClientFromConfigFactory { - return func(cfg *rest.Config) (things_test_io_v1.ClusterResourceClient, error) { - clients, err := things_test_io_v1.NewClientsetFromConfig(cfg) - if err != nil { - return nil, err - } - return clients.ClusterResources(), nil - } -} \ No newline at end of file + return func(cfg *rest.Config) (things_test_io_v1.ClusterResourceClient, error) { + clients, err := things_test_io_v1.NewClientsetFromConfig(cfg) + if err != nil { + return nil, err + } + return clients.ClusterResources(), nil + } +} diff --git a/codegen/test/api/things.test.io/v1/register.go b/codegen/test/api/things.test.io/v1/register.go index 99e1def72..38bbf15c1 100644 --- a/codegen/test/api/things.test.io/v1/register.go +++ b/codegen/test/api/things.test.io/v1/register.go @@ -6,9 +6,9 @@ package v1 import ( - "k8s.io/apimachinery/pkg/runtime/schema" - "sigs.k8s.io/controller-runtime/pkg/scheme" - "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" ) // AddToSchemes may be used to add all resources defined in the project to a Scheme @@ -16,19 +16,18 @@ import ( // AddToScheme adds all Resources to the Scheme var ( - // SchemeGroupVersion is group version used to register these objects - SchemeGroupVersion = schema.GroupVersion{Group: "things.test.io", Version: "v1"} - - // SchemeBuilder is used to add go types to the GroupVersionKind scheme - SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} + // SchemeGroupVersion is group version used to register these objects + SchemeGroupVersion = schema.GroupVersion{Group: "things.test.io", Version: "v1"} + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} ) // Resource takes an unqualified resource and returns a Group qualified GroupResource func Resource(resource string) schema.GroupResource { - return SchemeGroupVersion.WithResource(resource).GroupResource() + return SchemeGroupVersion.WithResource(resource).GroupResource() } func AddToScheme(s *runtime.Scheme) error { - return SchemeBuilder.AddToScheme(s) + return SchemeBuilder.AddToScheme(s) } diff --git a/codegen/test/api/things.test.io/v1/sets/sets.go b/codegen/test/api/things.test.io/v1/sets/sets.go index 8e9cb54fb..73703a3cd 100644 --- a/codegen/test/api/things.test.io/v1/sets/sets.go +++ b/codegen/test/api/things.test.io/v1/sets/sets.go @@ -4,232 +4,229 @@ package v1sets - - import ( - things_test_io_v1 "github.com/solo-io/skv2/codegen/test/api/things.test.io/v1" + things_test_io_v1 "github.com/solo-io/skv2/codegen/test/api/things.test.io/v1" - "github.com/rotisserie/eris" - sksets "github.com/solo-io/skv2/contrib/pkg/sets" - "github.com/solo-io/skv2/pkg/ezkube" - "k8s.io/apimachinery/pkg/util/sets" + "github.com/rotisserie/eris" + sksets "github.com/solo-io/skv2/contrib/pkg/sets" + "github.com/solo-io/skv2/pkg/ezkube" + "k8s.io/apimachinery/pkg/util/sets" ) type PaintSet interface { // Get the set stored keys - Keys() sets.String - // List of resources stored in the set. Pass an optional filter function to filter on the list. - // The filter function should return false to keep the resource, true to drop it. - List(filterResource ... func(*things_test_io_v1.Paint) bool) []*things_test_io_v1.Paint - // Unsorted list of resources stored in the set. Pass an optional filter function to filter on the list. - // The filter function should return false to keep the resource, true to drop it. - UnsortedList(filterResource ... func(*things_test_io_v1.Paint) bool) []*things_test_io_v1.Paint - // Return the Set as a map of key to resource. - Map() map[string]*things_test_io_v1.Paint - // Insert a resource into the set. - Insert(paint ...*things_test_io_v1.Paint) - // Compare the equality of the keys in two sets (not the resources themselves) - Equal(paintSet PaintSet) bool - // Check if the set contains a key matching the resource (not the resource itself) - Has(paint ezkube.ResourceId) bool - // Delete the key matching the resource - Delete(paint ezkube.ResourceId) - // Return the union with the provided set - Union(set PaintSet) PaintSet - // Return the difference with the provided set - Difference(set PaintSet) PaintSet - // Return the intersection with the provided set - Intersection(set PaintSet) PaintSet - // Find the resource with the given ID - Find(id ezkube.ResourceId) (*things_test_io_v1.Paint, error) - // Get the length of the set - Length() int - // returns the generic implementation of the set - Generic() sksets.ResourceSet - // returns the delta between this and and another PaintSet - Delta(newSet PaintSet) sksets.ResourceDelta - // Create a deep copy of the current PaintSet - Clone() PaintSet + Keys() sets.String + // List of resources stored in the set. Pass an optional filter function to filter on the list. + // The filter function should return false to keep the resource, true to drop it. + List(filterResource ...func(*things_test_io_v1.Paint) bool) []*things_test_io_v1.Paint + // Unsorted list of resources stored in the set. Pass an optional filter function to filter on the list. + // The filter function should return false to keep the resource, true to drop it. + UnsortedList(filterResource ...func(*things_test_io_v1.Paint) bool) []*things_test_io_v1.Paint + // Return the Set as a map of key to resource. + Map() map[string]*things_test_io_v1.Paint + // Insert a resource into the set. + Insert(paint ...*things_test_io_v1.Paint) + // Compare the equality of the keys in two sets (not the resources themselves) + Equal(paintSet PaintSet) bool + // Check if the set contains a key matching the resource (not the resource itself) + Has(paint ezkube.ResourceId) bool + // Delete the key matching the resource + Delete(paint ezkube.ResourceId) + // Return the union with the provided set + Union(set PaintSet) PaintSet + // Return the difference with the provided set + Difference(set PaintSet) PaintSet + // Return the intersection with the provided set + Intersection(set PaintSet) PaintSet + // Find the resource with the given ID + Find(id ezkube.ResourceId) (*things_test_io_v1.Paint, error) + // Get the length of the set + Length() int + // returns the generic implementation of the set + Generic() sksets.ResourceSet + // returns the delta between this and and another PaintSet + Delta(newSet PaintSet) sksets.ResourceDelta + // Create a deep copy of the current PaintSet + Clone() PaintSet } func makeGenericPaintSet(paintList []*things_test_io_v1.Paint) sksets.ResourceSet { - var genericResources []ezkube.ResourceId - for _, obj := range paintList { - genericResources = append(genericResources, obj) - } - return sksets.NewResourceSet(genericResources...) + var genericResources []ezkube.ResourceId + for _, obj := range paintList { + genericResources = append(genericResources, obj) + } + return sksets.NewResourceSet(genericResources...) } type paintSet struct { - set sksets.ResourceSet + set sksets.ResourceSet } func NewPaintSet(paintList ...*things_test_io_v1.Paint) PaintSet { - return &paintSet{set: makeGenericPaintSet(paintList)} + return &paintSet{set: makeGenericPaintSet(paintList)} } func NewPaintSetFromList(paintList *things_test_io_v1.PaintList) PaintSet { - list := make([]*things_test_io_v1.Paint, 0, len(paintList.Items)) - for idx := range paintList.Items { - list = append(list, &paintList.Items[idx]) - } - return &paintSet{set: makeGenericPaintSet(list)} + list := make([]*things_test_io_v1.Paint, 0, len(paintList.Items)) + for idx := range paintList.Items { + list = append(list, &paintList.Items[idx]) + } + return &paintSet{set: makeGenericPaintSet(list)} } func (s *paintSet) Keys() sets.String { if s == nil { return sets.String{} - } - return s.Generic().Keys() -} - -func (s *paintSet) List(filterResource ... func(*things_test_io_v1.Paint) bool) []*things_test_io_v1.Paint { - if s == nil { - return nil - } - var genericFilters []func(ezkube.ResourceId) bool - for _, filter := range filterResource { - filter := filter - genericFilters = append(genericFilters, func(obj ezkube.ResourceId) bool { - return filter(obj.(*things_test_io_v1.Paint)) - }) - } - - objs := s.Generic().List(genericFilters...) - paintList := make([]*things_test_io_v1.Paint, 0, len(objs)) - for _, obj := range objs { - paintList = append(paintList, obj.(*things_test_io_v1.Paint)) - } - return paintList -} - -func (s *paintSet) UnsortedList(filterResource ... func(*things_test_io_v1.Paint) bool) []*things_test_io_v1.Paint { - if s == nil { - return nil - } - var genericFilters []func(ezkube.ResourceId) bool - for _, filter := range filterResource { - filter := filter - genericFilters = append(genericFilters, func(obj ezkube.ResourceId) bool { - return filter(obj.(*things_test_io_v1.Paint)) - }) - } - - var paintList []*things_test_io_v1.Paint - for _, obj := range s.Generic().UnsortedList(genericFilters...) { - paintList = append(paintList, obj.(*things_test_io_v1.Paint)) - } - return paintList + } + return s.Generic().Keys() +} + +func (s *paintSet) List(filterResource ...func(*things_test_io_v1.Paint) bool) []*things_test_io_v1.Paint { + if s == nil { + return nil + } + var genericFilters []func(ezkube.ResourceId) bool + for _, filter := range filterResource { + filter := filter + genericFilters = append(genericFilters, func(obj ezkube.ResourceId) bool { + return filter(obj.(*things_test_io_v1.Paint)) + }) + } + + objs := s.Generic().List(genericFilters...) + paintList := make([]*things_test_io_v1.Paint, 0, len(objs)) + for _, obj := range objs { + paintList = append(paintList, obj.(*things_test_io_v1.Paint)) + } + return paintList +} + +func (s *paintSet) UnsortedList(filterResource ...func(*things_test_io_v1.Paint) bool) []*things_test_io_v1.Paint { + if s == nil { + return nil + } + var genericFilters []func(ezkube.ResourceId) bool + for _, filter := range filterResource { + filter := filter + genericFilters = append(genericFilters, func(obj ezkube.ResourceId) bool { + return filter(obj.(*things_test_io_v1.Paint)) + }) + } + + var paintList []*things_test_io_v1.Paint + for _, obj := range s.Generic().UnsortedList(genericFilters...) { + paintList = append(paintList, obj.(*things_test_io_v1.Paint)) + } + return paintList } func (s *paintSet) Map() map[string]*things_test_io_v1.Paint { - if s == nil { - return nil - } + if s == nil { + return nil + } - newMap := map[string]*things_test_io_v1.Paint{} - for k, v := range s.Generic().Map() { - newMap[k] = v.(*things_test_io_v1.Paint) - } - return newMap + newMap := map[string]*things_test_io_v1.Paint{} + for k, v := range s.Generic().Map() { + newMap[k] = v.(*things_test_io_v1.Paint) + } + return newMap } func (s *paintSet) Insert( - paintList ...*things_test_io_v1.Paint, + paintList ...*things_test_io_v1.Paint, ) { - if s == nil { - panic("cannot insert into nil set") - } + if s == nil { + panic("cannot insert into nil set") + } - for _, obj := range paintList { - s.Generic().Insert(obj) - } + for _, obj := range paintList { + s.Generic().Insert(obj) + } } func (s *paintSet) Has(paint ezkube.ResourceId) bool { - if s == nil { - return false - } - return s.Generic().Has(paint) + if s == nil { + return false + } + return s.Generic().Has(paint) } func (s *paintSet) Equal( - paintSet PaintSet, + paintSet PaintSet, ) bool { - if s == nil { - return paintSet == nil - } - return s.Generic().Equal(paintSet.Generic()) + if s == nil { + return paintSet == nil + } + return s.Generic().Equal(paintSet.Generic()) } func (s *paintSet) Delete(Paint ezkube.ResourceId) { - if s == nil { - return - } - s.Generic().Delete(Paint) + if s == nil { + return + } + s.Generic().Delete(Paint) } func (s *paintSet) Union(set PaintSet) PaintSet { - if s == nil { - return set - } - return NewPaintSet(append(s.List(), set.List()...)...) + if s == nil { + return set + } + return NewPaintSet(append(s.List(), set.List()...)...) } func (s *paintSet) Difference(set PaintSet) PaintSet { - if s == nil { - return set - } - newSet := s.Generic().Difference(set.Generic()) - return &paintSet{set: newSet} + if s == nil { + return set + } + newSet := s.Generic().Difference(set.Generic()) + return &paintSet{set: newSet} } func (s *paintSet) Intersection(set PaintSet) PaintSet { - if s == nil { - return nil - } - newSet := s.Generic().Intersection(set.Generic()) - var paintList []*things_test_io_v1.Paint - for _, obj := range newSet.List() { - paintList = append(paintList, obj.(*things_test_io_v1.Paint)) - } - return NewPaintSet(paintList...) + if s == nil { + return nil + } + newSet := s.Generic().Intersection(set.Generic()) + var paintList []*things_test_io_v1.Paint + for _, obj := range newSet.List() { + paintList = append(paintList, obj.(*things_test_io_v1.Paint)) + } + return NewPaintSet(paintList...) } - func (s *paintSet) Find(id ezkube.ResourceId) (*things_test_io_v1.Paint, error) { - if s == nil { - return nil, eris.Errorf("empty set, cannot find Paint %v", sksets.Key(id)) - } + if s == nil { + return nil, eris.Errorf("empty set, cannot find Paint %v", sksets.Key(id)) + } obj, err := s.Generic().Find(&things_test_io_v1.Paint{}, id) if err != nil { return nil, err - } + } - return obj.(*things_test_io_v1.Paint), nil + return obj.(*things_test_io_v1.Paint), nil } func (s *paintSet) Length() int { - if s == nil { - return 0 - } - return s.Generic().Length() + if s == nil { + return 0 + } + return s.Generic().Length() } func (s *paintSet) Generic() sksets.ResourceSet { - if s == nil { - return nil - } - return s.set + if s == nil { + return nil + } + return s.set } func (s *paintSet) Delta(newSet PaintSet) sksets.ResourceDelta { - if s == nil { - return sksets.ResourceDelta{ - Inserted: newSet.Generic(), - } - } - return s.Generic().Delta(newSet.Generic()) + if s == nil { + return sksets.ResourceDelta{ + Inserted: newSet.Generic(), + } + } + return s.Generic().Delta(newSet.Generic()) } func (s *paintSet) Clone() PaintSet { @@ -241,219 +238,218 @@ func (s *paintSet) Clone() PaintSet { type ClusterResourceSet interface { // Get the set stored keys - Keys() sets.String - // List of resources stored in the set. Pass an optional filter function to filter on the list. - // The filter function should return false to keep the resource, true to drop it. - List(filterResource ... func(*things_test_io_v1.ClusterResource) bool) []*things_test_io_v1.ClusterResource - // Unsorted list of resources stored in the set. Pass an optional filter function to filter on the list. - // The filter function should return false to keep the resource, true to drop it. - UnsortedList(filterResource ... func(*things_test_io_v1.ClusterResource) bool) []*things_test_io_v1.ClusterResource - // Return the Set as a map of key to resource. - Map() map[string]*things_test_io_v1.ClusterResource - // Insert a resource into the set. - Insert(clusterResource ...*things_test_io_v1.ClusterResource) - // Compare the equality of the keys in two sets (not the resources themselves) - Equal(clusterResourceSet ClusterResourceSet) bool - // Check if the set contains a key matching the resource (not the resource itself) - Has(clusterResource ezkube.ResourceId) bool - // Delete the key matching the resource - Delete(clusterResource ezkube.ResourceId) - // Return the union with the provided set - Union(set ClusterResourceSet) ClusterResourceSet - // Return the difference with the provided set - Difference(set ClusterResourceSet) ClusterResourceSet - // Return the intersection with the provided set - Intersection(set ClusterResourceSet) ClusterResourceSet - // Find the resource with the given ID - Find(id ezkube.ResourceId) (*things_test_io_v1.ClusterResource, error) - // Get the length of the set - Length() int - // returns the generic implementation of the set - Generic() sksets.ResourceSet - // returns the delta between this and and another ClusterResourceSet - Delta(newSet ClusterResourceSet) sksets.ResourceDelta - // Create a deep copy of the current ClusterResourceSet - Clone() ClusterResourceSet + Keys() sets.String + // List of resources stored in the set. Pass an optional filter function to filter on the list. + // The filter function should return false to keep the resource, true to drop it. + List(filterResource ...func(*things_test_io_v1.ClusterResource) bool) []*things_test_io_v1.ClusterResource + // Unsorted list of resources stored in the set. Pass an optional filter function to filter on the list. + // The filter function should return false to keep the resource, true to drop it. + UnsortedList(filterResource ...func(*things_test_io_v1.ClusterResource) bool) []*things_test_io_v1.ClusterResource + // Return the Set as a map of key to resource. + Map() map[string]*things_test_io_v1.ClusterResource + // Insert a resource into the set. + Insert(clusterResource ...*things_test_io_v1.ClusterResource) + // Compare the equality of the keys in two sets (not the resources themselves) + Equal(clusterResourceSet ClusterResourceSet) bool + // Check if the set contains a key matching the resource (not the resource itself) + Has(clusterResource ezkube.ResourceId) bool + // Delete the key matching the resource + Delete(clusterResource ezkube.ResourceId) + // Return the union with the provided set + Union(set ClusterResourceSet) ClusterResourceSet + // Return the difference with the provided set + Difference(set ClusterResourceSet) ClusterResourceSet + // Return the intersection with the provided set + Intersection(set ClusterResourceSet) ClusterResourceSet + // Find the resource with the given ID + Find(id ezkube.ResourceId) (*things_test_io_v1.ClusterResource, error) + // Get the length of the set + Length() int + // returns the generic implementation of the set + Generic() sksets.ResourceSet + // returns the delta between this and and another ClusterResourceSet + Delta(newSet ClusterResourceSet) sksets.ResourceDelta + // Create a deep copy of the current ClusterResourceSet + Clone() ClusterResourceSet } func makeGenericClusterResourceSet(clusterResourceList []*things_test_io_v1.ClusterResource) sksets.ResourceSet { - var genericResources []ezkube.ResourceId - for _, obj := range clusterResourceList { - genericResources = append(genericResources, obj) - } - return sksets.NewResourceSet(genericResources...) + var genericResources []ezkube.ResourceId + for _, obj := range clusterResourceList { + genericResources = append(genericResources, obj) + } + return sksets.NewResourceSet(genericResources...) } type clusterResourceSet struct { - set sksets.ResourceSet + set sksets.ResourceSet } func NewClusterResourceSet(clusterResourceList ...*things_test_io_v1.ClusterResource) ClusterResourceSet { - return &clusterResourceSet{set: makeGenericClusterResourceSet(clusterResourceList)} + return &clusterResourceSet{set: makeGenericClusterResourceSet(clusterResourceList)} } func NewClusterResourceSetFromList(clusterResourceList *things_test_io_v1.ClusterResourceList) ClusterResourceSet { - list := make([]*things_test_io_v1.ClusterResource, 0, len(clusterResourceList.Items)) - for idx := range clusterResourceList.Items { - list = append(list, &clusterResourceList.Items[idx]) - } - return &clusterResourceSet{set: makeGenericClusterResourceSet(list)} + list := make([]*things_test_io_v1.ClusterResource, 0, len(clusterResourceList.Items)) + for idx := range clusterResourceList.Items { + list = append(list, &clusterResourceList.Items[idx]) + } + return &clusterResourceSet{set: makeGenericClusterResourceSet(list)} } func (s *clusterResourceSet) Keys() sets.String { if s == nil { return sets.String{} - } - return s.Generic().Keys() -} - -func (s *clusterResourceSet) List(filterResource ... func(*things_test_io_v1.ClusterResource) bool) []*things_test_io_v1.ClusterResource { - if s == nil { - return nil - } - var genericFilters []func(ezkube.ResourceId) bool - for _, filter := range filterResource { - filter := filter - genericFilters = append(genericFilters, func(obj ezkube.ResourceId) bool { - return filter(obj.(*things_test_io_v1.ClusterResource)) - }) - } - - objs := s.Generic().List(genericFilters...) - clusterResourceList := make([]*things_test_io_v1.ClusterResource, 0, len(objs)) - for _, obj := range objs { - clusterResourceList = append(clusterResourceList, obj.(*things_test_io_v1.ClusterResource)) - } - return clusterResourceList -} - -func (s *clusterResourceSet) UnsortedList(filterResource ... func(*things_test_io_v1.ClusterResource) bool) []*things_test_io_v1.ClusterResource { - if s == nil { - return nil - } - var genericFilters []func(ezkube.ResourceId) bool - for _, filter := range filterResource { - filter := filter - genericFilters = append(genericFilters, func(obj ezkube.ResourceId) bool { - return filter(obj.(*things_test_io_v1.ClusterResource)) - }) - } - - var clusterResourceList []*things_test_io_v1.ClusterResource - for _, obj := range s.Generic().UnsortedList(genericFilters...) { - clusterResourceList = append(clusterResourceList, obj.(*things_test_io_v1.ClusterResource)) - } - return clusterResourceList + } + return s.Generic().Keys() +} + +func (s *clusterResourceSet) List(filterResource ...func(*things_test_io_v1.ClusterResource) bool) []*things_test_io_v1.ClusterResource { + if s == nil { + return nil + } + var genericFilters []func(ezkube.ResourceId) bool + for _, filter := range filterResource { + filter := filter + genericFilters = append(genericFilters, func(obj ezkube.ResourceId) bool { + return filter(obj.(*things_test_io_v1.ClusterResource)) + }) + } + + objs := s.Generic().List(genericFilters...) + clusterResourceList := make([]*things_test_io_v1.ClusterResource, 0, len(objs)) + for _, obj := range objs { + clusterResourceList = append(clusterResourceList, obj.(*things_test_io_v1.ClusterResource)) + } + return clusterResourceList +} + +func (s *clusterResourceSet) UnsortedList(filterResource ...func(*things_test_io_v1.ClusterResource) bool) []*things_test_io_v1.ClusterResource { + if s == nil { + return nil + } + var genericFilters []func(ezkube.ResourceId) bool + for _, filter := range filterResource { + filter := filter + genericFilters = append(genericFilters, func(obj ezkube.ResourceId) bool { + return filter(obj.(*things_test_io_v1.ClusterResource)) + }) + } + + var clusterResourceList []*things_test_io_v1.ClusterResource + for _, obj := range s.Generic().UnsortedList(genericFilters...) { + clusterResourceList = append(clusterResourceList, obj.(*things_test_io_v1.ClusterResource)) + } + return clusterResourceList } func (s *clusterResourceSet) Map() map[string]*things_test_io_v1.ClusterResource { - if s == nil { - return nil - } + if s == nil { + return nil + } - newMap := map[string]*things_test_io_v1.ClusterResource{} - for k, v := range s.Generic().Map() { - newMap[k] = v.(*things_test_io_v1.ClusterResource) - } - return newMap + newMap := map[string]*things_test_io_v1.ClusterResource{} + for k, v := range s.Generic().Map() { + newMap[k] = v.(*things_test_io_v1.ClusterResource) + } + return newMap } func (s *clusterResourceSet) Insert( - clusterResourceList ...*things_test_io_v1.ClusterResource, + clusterResourceList ...*things_test_io_v1.ClusterResource, ) { - if s == nil { - panic("cannot insert into nil set") - } + if s == nil { + panic("cannot insert into nil set") + } - for _, obj := range clusterResourceList { - s.Generic().Insert(obj) - } + for _, obj := range clusterResourceList { + s.Generic().Insert(obj) + } } func (s *clusterResourceSet) Has(clusterResource ezkube.ResourceId) bool { - if s == nil { - return false - } - return s.Generic().Has(clusterResource) + if s == nil { + return false + } + return s.Generic().Has(clusterResource) } func (s *clusterResourceSet) Equal( - clusterResourceSet ClusterResourceSet, + clusterResourceSet ClusterResourceSet, ) bool { - if s == nil { - return clusterResourceSet == nil - } - return s.Generic().Equal(clusterResourceSet.Generic()) + if s == nil { + return clusterResourceSet == nil + } + return s.Generic().Equal(clusterResourceSet.Generic()) } func (s *clusterResourceSet) Delete(ClusterResource ezkube.ResourceId) { - if s == nil { - return - } - s.Generic().Delete(ClusterResource) + if s == nil { + return + } + s.Generic().Delete(ClusterResource) } func (s *clusterResourceSet) Union(set ClusterResourceSet) ClusterResourceSet { - if s == nil { - return set - } - return NewClusterResourceSet(append(s.List(), set.List()...)...) + if s == nil { + return set + } + return NewClusterResourceSet(append(s.List(), set.List()...)...) } func (s *clusterResourceSet) Difference(set ClusterResourceSet) ClusterResourceSet { - if s == nil { - return set - } - newSet := s.Generic().Difference(set.Generic()) - return &clusterResourceSet{set: newSet} + if s == nil { + return set + } + newSet := s.Generic().Difference(set.Generic()) + return &clusterResourceSet{set: newSet} } func (s *clusterResourceSet) Intersection(set ClusterResourceSet) ClusterResourceSet { - if s == nil { - return nil - } - newSet := s.Generic().Intersection(set.Generic()) - var clusterResourceList []*things_test_io_v1.ClusterResource - for _, obj := range newSet.List() { - clusterResourceList = append(clusterResourceList, obj.(*things_test_io_v1.ClusterResource)) - } - return NewClusterResourceSet(clusterResourceList...) + if s == nil { + return nil + } + newSet := s.Generic().Intersection(set.Generic()) + var clusterResourceList []*things_test_io_v1.ClusterResource + for _, obj := range newSet.List() { + clusterResourceList = append(clusterResourceList, obj.(*things_test_io_v1.ClusterResource)) + } + return NewClusterResourceSet(clusterResourceList...) } - func (s *clusterResourceSet) Find(id ezkube.ResourceId) (*things_test_io_v1.ClusterResource, error) { - if s == nil { - return nil, eris.Errorf("empty set, cannot find ClusterResource %v", sksets.Key(id)) - } + if s == nil { + return nil, eris.Errorf("empty set, cannot find ClusterResource %v", sksets.Key(id)) + } obj, err := s.Generic().Find(&things_test_io_v1.ClusterResource{}, id) if err != nil { return nil, err - } + } - return obj.(*things_test_io_v1.ClusterResource), nil + return obj.(*things_test_io_v1.ClusterResource), nil } func (s *clusterResourceSet) Length() int { - if s == nil { - return 0 - } - return s.Generic().Length() + if s == nil { + return 0 + } + return s.Generic().Length() } func (s *clusterResourceSet) Generic() sksets.ResourceSet { - if s == nil { - return nil - } - return s.set + if s == nil { + return nil + } + return s.set } func (s *clusterResourceSet) Delta(newSet ClusterResourceSet) sksets.ResourceDelta { - if s == nil { - return sksets.ResourceDelta{ - Inserted: newSet.Generic(), - } - } - return s.Generic().Delta(newSet.Generic()) + if s == nil { + return sksets.ResourceDelta{ + Inserted: newSet.Generic(), + } + } + return s.Generic().Delta(newSet.Generic()) } func (s *clusterResourceSet) Clone() ClusterResourceSet { diff --git a/codegen/test/api/things.test.io/v1/test_api.pb.go b/codegen/test/api/things.test.io/v1/test_api.pb.go index fa79410fd..53e16624d 100644 --- a/codegen/test/api/things.test.io/v1/test_api.pb.go +++ b/codegen/test/api/things.test.io/v1/test_api.pb.go @@ -7,14 +7,15 @@ package v1 import ( + reflect "reflect" + sync "sync" + any1 "github.com/golang/protobuf/ptypes/any" _struct "github.com/golang/protobuf/ptypes/struct" wrappers "github.com/golang/protobuf/ptypes/wrappers" _ "github.com/solo-io/cue/encoding/protobuf/cue" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" ) const ( diff --git a/codegen/test/api/things.test.io/v1/type_helpers.go b/codegen/test/api/things.test.io/v1/type_helpers.go index 2d04a4fd1..4133a8e21 100644 --- a/codegen/test/api/things.test.io/v1/type_helpers.go +++ b/codegen/test/api/things.test.io/v1/type_helpers.go @@ -3,9 +3,6 @@ // Definitions for the Kubernetes types package v1 -import ( -) - // PaintSlice represents a slice of *Paint type PaintSlice []*Paint diff --git a/codegen/test/api/things.test.io/v1/types.go b/codegen/test/api/things.test.io/v1/types.go index 3f3fc59e2..f153a3983 100644 --- a/codegen/test/api/things.test.io/v1/types.go +++ b/codegen/test/api/things.test.io/v1/types.go @@ -4,8 +4,9 @@ package v1 import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema") + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" +) // +genclient // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object @@ -14,22 +15,22 @@ import ( // GroupVersionKind for Paint var PaintGVK = schema.GroupVersionKind{ - Group: "things.test.io", - Version: "v1", - Kind: "Paint", + Group: "things.test.io", + Version: "v1", + Kind: "Paint", } // Paint is the Schema for the paint API type Paint struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` - Spec PaintSpec `json:"spec,omitempty"` - Status PaintStatus `json:"status,omitempty"` + Spec PaintSpec `json:"spec,omitempty"` + Status PaintStatus `json:"status,omitempty"` } // GVK returns the GroupVersionKind associated with the resource type. -func (Paint) GVK() schema.GroupVersionKind { +func (Paint) GVK() schema.GroupVersionKind { return PaintGVK } @@ -37,9 +38,9 @@ func (Paint) GVK() schema.GroupVersionKind { // PaintList contains a list of Paint type PaintList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []Paint `json:"items"` + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Paint `json:"items"` } // +genclient @@ -49,21 +50,21 @@ type PaintList struct { // GroupVersionKind for ClusterResource var ClusterResourceGVK = schema.GroupVersionKind{ - Group: "things.test.io", - Version: "v1", - Kind: "ClusterResource", + Group: "things.test.io", + Version: "v1", + Kind: "ClusterResource", } // ClusterResource is the Schema for the clusterResource API type ClusterResource struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` - Spec ClusterResourceSpec `json:"spec,omitempty"` + Spec ClusterResourceSpec `json:"spec,omitempty"` } // GVK returns the GroupVersionKind associated with the resource type. -func (ClusterResource) GVK() schema.GroupVersionKind { +func (ClusterResource) GVK() schema.GroupVersionKind { return ClusterResourceGVK } @@ -71,12 +72,12 @@ func (ClusterResource) GVK() schema.GroupVersionKind { // ClusterResourceList contains a list of ClusterResource type ClusterResourceList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []ClusterResource `json:"items"` + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ClusterResource `json:"items"` } func init() { - SchemeBuilder.Register(&Paint{}, &PaintList{}) - SchemeBuilder.Register(&ClusterResource{}, &ClusterResourceList{}) + SchemeBuilder.Register(&Paint{}, &PaintList{}) + SchemeBuilder.Register(&ClusterResource{}, &ClusterResourceList{}) } diff --git a/codegen/test/api/things.test.io/v1/zz_generated.deepcopy.go b/codegen/test/api/things.test.io/v1/zz_generated.deepcopy.go index 8939012a9..4203de9bf 100644 --- a/codegen/test/api/things.test.io/v1/zz_generated.deepcopy.go +++ b/codegen/test/api/things.test.io/v1/zz_generated.deepcopy.go @@ -5,124 +5,123 @@ package v1 import ( - runtime "k8s.io/apimachinery/pkg/runtime" + runtime "k8s.io/apimachinery/pkg/runtime" ) // Generated Deepcopy methods for Paint func (in *Paint) DeepCopyInto(out *Paint) { - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - // deepcopy spec - in.Spec.DeepCopyInto(&out.Spec) - // deepcopy status - in.Status.DeepCopyInto(&out.Status) + // deepcopy spec + in.Spec.DeepCopyInto(&out.Spec) + // deepcopy status + in.Status.DeepCopyInto(&out.Status) - return + return } func (in *Paint) DeepCopy() *Paint { - if in == nil { - return nil - } - out := new(Paint) - in.DeepCopyInto(out) - return out + if in == nil { + return nil + } + out := new(Paint) + in.DeepCopyInto(out) + return out } func (in *Paint) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil + if c := in.DeepCopy(); c != nil { + return c + } + return nil } func (in *PaintList) DeepCopyInto(out *PaintList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]Paint, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Paint, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return } func (in *PaintList) DeepCopy() *PaintList { - if in == nil { - return nil - } - out := new(PaintList) - in.DeepCopyInto(out) - return out + if in == nil { + return nil + } + out := new(PaintList) + in.DeepCopyInto(out) + return out } func (in *PaintList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil + if c := in.DeepCopy(); c != nil { + return c + } + return nil } // Generated Deepcopy methods for ClusterResource func (in *ClusterResource) DeepCopyInto(out *ClusterResource) { - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - // deepcopy spec - in.Spec.DeepCopyInto(&out.Spec) + // deepcopy spec + in.Spec.DeepCopyInto(&out.Spec) - return + return } func (in *ClusterResource) DeepCopy() *ClusterResource { - if in == nil { - return nil - } - out := new(ClusterResource) - in.DeepCopyInto(out) - return out + if in == nil { + return nil + } + out := new(ClusterResource) + in.DeepCopyInto(out) + return out } func (in *ClusterResource) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil + if c := in.DeepCopy(); c != nil { + return c + } + return nil } func (in *ClusterResourceList) DeepCopyInto(out *ClusterResourceList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]ClusterResource, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ClusterResource, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return } func (in *ClusterResourceList) DeepCopy() *ClusterResourceList { - if in == nil { - return nil - } - out := new(ClusterResourceList) - in.DeepCopyInto(out) - return out + if in == nil { + return nil + } + out := new(ClusterResourceList) + in.DeepCopyInto(out) + return out } func (in *ClusterResourceList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil + if c := in.DeepCopy(); c != nil { + return c + } + return nil } - diff --git a/crds/multicluster.solo.io_v1alpha1_crds.yaml b/crds/multicluster.solo.io_crds.yaml similarity index 100% rename from crds/multicluster.solo.io_v1alpha1_crds.yaml rename to crds/multicluster.solo.io_crds.yaml diff --git a/templates/multicluster.solo.io_crds.yaml b/templates/multicluster.solo.io_crds.yaml new file mode 100644 index 000000000..ee6e8f2d5 --- /dev/null +++ b/templates/multicluster.solo.io_crds.yaml @@ -0,0 +1,163 @@ +# Code generated by skv2. DO NOT EDIT. + + +{{- if has "kubernetesclusters.multicluster.solo.io/v1alpha1" $.Values.enabledExperimentalApi }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + crd.solo.io/specHash: 396fd84315636ecb + labels: + app: skv2 + app.kubernetes.io/name: skv2 + name: kubernetesclusters.multicluster.solo.io +spec: + group: multicluster.solo.io + names: + kind: KubernetesCluster + listKind: KubernetesClusterList + plural: kubernetesclusters + singular: kubernetescluster + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + properties: + spec: + description: Representation of a Kubernetes cluster that has been registered. + properties: + clusterDomain: + description: |- + name local DNS suffix used by the cluster. + used for building FQDNs for in-cluster services + defaults to 'cluster.local' + type: string + providerInfo: + description: Metadata for clusters provisioned from cloud providers. + oneOf: + - not: + anyOf: + - required: + - eks + - required: + - eks + properties: + eks: + description: Provider info for an AWS EKS provisioned cluster. + properties: + accountId: + description: AWS 12 digit account ID. + type: string + arn: + description: AWS ARN. + type: string + name: + description: EKS resource name. + type: string + region: + description: AWS region. + type: string + type: object + type: object + secretName: + description: name of the secret which contains the kubeconfig with information + to connect to the remote cluster. + type: string + type: object + status: + properties: + namespace: + description: The namespace in which cluster registration resources were + created. + type: string + policyRules: + description: The set of PolicyRules attached to ClusterRoles when this + cluster was registered. + items: + properties: + apiGroups: + description: |- + APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of + the enumerated resources in any API group will be allowed. + +optional + items: + type: string + type: array + nonResourceUrls: + description: |- + NonResourceURLs is a set of partial urls that a user should have access to. *s are allowed, but only as the full, final step in the path + Since non-resource URLs are not namespaced, this field is only applicable for ClusterRoles referenced from a ClusterRoleBinding. + Rules can either apply to API resources (such as "pods" or "secrets") or non-resource URL paths (such as "/api"), but not both. + +optional + items: + type: string + type: array + resourceNames: + description: |- + ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed. + +optional + items: + type: string + type: array + resources: + description: |- + Resources is a list of resources this rule applies to. ResourceAll represents all resources. + +optional + items: + type: string + type: array + verbs: + description: Verbs is a list of Verbs that apply to ALL the ResourceKinds + and AttributeRestrictions contained in this rule. VerbAll represents + all kinds. + items: + type: string + type: array + type: object + type: array + status: + description: |- + List of statuses about the kubernetes cluster. + This list allows for multiple applications/pods to record their connection status. + items: + properties: + message: + description: A human readable message about the current state of + the object + type: string + observedGeneration: + description: |- + The most recently observed generation of the resource. This value corresponds to the `metadata.generation` of + a kubernetes resource + format: int64 + type: integer + owner: + description: |- + (optional) The owner of the status, this value can be used to identify the entity which wrote this status. + This is useful in situations where a given resource may have multiple owners. + nullable: true + type: string + processingTime: + description: The time at which this status was recorded + format: date-time + type: string + state: + description: The current state of the resource + enum: + - PENDING + - PROCESSING + - INVALID + - FAILED + - ACCEPTED + type: string + type: object + type: array + type: object + type: object + served: true + storage: true + subresources: + status: {} +{{- end }} +--- From 13d41d935c862f2867d5f4a0531fd1c7fbfe97e4 Mon Sep 17 00:00:00 2001 From: Dmitri Dolguikh Date: Wed, 26 Jul 2023 22:11:02 -0700 Subject: [PATCH 13/27] De-flaked a test Signed-off-by: Dmitri Dolguikh --- codegen/cmd_test.go | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/codegen/cmd_test.go b/codegen/cmd_test.go index 0f21d1ee5..52d19caee 100644 --- a/codegen/cmd_test.go +++ b/codegen/cmd_test.go @@ -8,6 +8,7 @@ import ( "os/exec" "path/filepath" "reflect" + "strings" goyaml "gopkg.in/yaml.v3" rbacv1 "k8s.io/api/rbac/v1" @@ -1336,10 +1337,7 @@ var _ = Describe("Cmd", func() { Expect(string(bytes)).To(ContainSubstring("description: OpenAPI gen test for recursive fields")) }) - // TODO (dmitri-d): this is flaky, as the ordering of generated CustomResourceDefinitions is unstable - // when the "Paint" CRD isn't the first in the list, the test fails. - // Can't remove "ClusterResource" either, as kube_crud_test and kube_multicluster_test depend on crds - // this suite. + // TODO (dmitri-d): kube_crud_test and kube_multicluster_test depend on crds in this suite. It("generates google.protobuf.Value with no type", func() { crdFilePath := filepath.Join(util.GetModuleRoot(), cmd.ManifestRoot, "/crds/things.test.io_crds.yaml") @@ -1348,8 +1346,16 @@ var _ = Describe("Cmd", func() { bytes, err := ioutil.ReadFile(crdFilePath) Expect(err).NotTo(HaveOccurred()) + paintCrdYaml := "" + for _, crd := range strings.Split(string(bytes), "---") { + if strings.Contains(crd, "kind: Paint") { + paintCrdYaml = crd + } + } + Expect(paintCrdYaml).ToNot(BeEmpty()) + generatedCrd := &v12.CustomResourceDefinition{} - Expect(yaml.Unmarshal(bytes, &generatedCrd)).NotTo(HaveOccurred()) + Expect(yaml.Unmarshal([]byte(paintCrdYaml), &generatedCrd)).NotTo(HaveOccurred()) protobufValueField := generatedCrd.Spec.Versions[0].Schema.OpenAPIV3Schema.Properties["spec"].Properties["recursiveType"].Properties["protobufValue"] // access the field to make sure it's not nil Expect(protobufValueField.XPreserveUnknownFields).ToNot(BeNil()) From ce5b6e4f75b1e6f29440777e40beb0a8ee50da13 Mon Sep 17 00:00:00 2001 From: Dmitri Dolguikh Date: Thu, 27 Jul 2023 19:08:31 -0700 Subject: [PATCH 14/27] Added support for skipping conditional rendering of CRDs for grandfathered groups Signed-off-by: Dmitri Dolguikh --- codegen/render/funcs.go | 5 ++ codegen/render/manifests_renderer.go | 20 +++++- codegen/render/manifests_renderer_test.go | 83 +++++++++++++++++++++-- codegen/templates/manifests/crd.yamltmpl | 10 +-- 4 files changed, 104 insertions(+), 14 deletions(-) diff --git a/codegen/render/funcs.go b/codegen/render/funcs.go index e875cc9e9..b1e90f7a0 100644 --- a/codegen/render/funcs.go +++ b/codegen/render/funcs.go @@ -131,6 +131,11 @@ func makeTemplateFuncs(customFuncs template.FuncMap) template.FuncMap { "containerConfigs": containerConfigs, "opVar": opVar, + + "should_not_skip": func(group, version string, skips map[string]bool) bool { + _, ok := skips[group+"/"+version] + return !ok + }, } for k, v := range skv2Funcs { diff --git a/codegen/render/manifests_renderer.go b/codegen/render/manifests_renderer.go index b395af9dd..9fe84e6ee 100644 --- a/codegen/render/manifests_renderer.go +++ b/codegen/render/manifests_renderer.go @@ -37,6 +37,11 @@ type ManifestsRenderer struct { ProtoDir string } +type templateArgs struct { + Crds []apiextv1.CustomResourceDefinition + ShouldSkip map[string]bool +} + func RenderManifests( appName, manifestDir, protoDir string, protoOpts protoutil.Options, @@ -54,9 +59,13 @@ func RenderManifests( func (r ManifestsRenderer) RenderManifests(grps []*Group, protoOpts protoutil.Options, groupOptions model.GroupOptions) ([]OutFile, error) { grpsByGroupName := make(map[string][]*Group) shouldRenderGroups := make(map[string]bool) + grandfatheredGroups := make(map[string]bool) for _, grp := range grps { grpsByGroupName[grp.Group] = append(grpsByGroupName[grp.Group], grp) shouldRenderGroups[grp.Group] = shouldRenderGroups[grp.Group] || grp.RenderManifests + if grp.Grandfathered { + grandfatheredGroups[grp.GroupVersion.String()] = true + } } for _, grp := range grps { @@ -88,7 +97,7 @@ func (r ManifestsRenderer) RenderManifests(grps []*Group, protoOpts protoutil.Op } renderedFiles = append(renderedFiles, out) - out, err = r.renderTemplatedManifest(r.AppName, groupName, crds) + out, err = r.renderTemplatedManifest(r.AppName, groupName, crds, grandfatheredGroups) if err != nil { return nil, err } @@ -257,7 +266,10 @@ func (r ManifestsRenderer) renderLegacyManifest(appName, groupName string, objs return outFile, nil } -func (r ManifestsRenderer) renderTemplatedManifest(appName, groupName string, objs []apiextv1.CustomResourceDefinition) (OutFile, error) { +func (r ManifestsRenderer) renderTemplatedManifest(appName, groupName string, + objs []apiextv1.CustomResourceDefinition, + grandfatheredGroups map[string]bool) (OutFile, error) { + renderer := DefaultTemplateRenderer // when rendering helm charts, we need @@ -273,7 +285,9 @@ func (r ManifestsRenderer) renderTemplatedManifest(appName, groupName string, ob templatesToRender := inputTemplates{ "manifests/crd.yamltmpl": outFile, } - files, err := defaultManifestRenderer.renderCoreTemplates(templatesToRender, objs) + files, err := defaultManifestRenderer.renderCoreTemplates( + templatesToRender, + templateArgs{Crds: objs, ShouldSkip: grandfatheredGroups}) if err != nil { return OutFile{}, err } diff --git a/codegen/render/manifests_renderer_test.go b/codegen/render/manifests_renderer_test.go index dfa8c3323..f3a8646ae 100644 --- a/codegen/render/manifests_renderer_test.go +++ b/codegen/render/manifests_renderer_test.go @@ -1,6 +1,8 @@ package render_test import ( + "strings" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" v1 "github.com/solo-io/skv2/codegen/test/api/things.test.io/v1" @@ -126,7 +128,7 @@ var _ = Describe("ManifestsRenderer", func() { grps[i].Init() } }) - It("Renderse manifests with chart and spec hash", func() { + It("Renders manifests with template and spec hash", func() { // get api-level code gen options from descriptors outFiles, err := render.RenderManifests( @@ -145,7 +147,54 @@ var _ = Describe("ManifestsRenderer", func() { }) }) - Describe("Generate combined alpha and non-alpha versioned CRD", func() { + Describe("Skip template for grandfathered alpha versioned CRD", func() { + var ( + grps []*model.Group + ) + + BeforeEach(func() { + grps = []*model.Group{{ + GroupVersion: schema.GroupVersion{ + Group: "things.test.io", + Version: "v1alpha1", + }, + RenderManifests: true, + AddChartVersion: "1.0.0", + Grandfathered: true, + Resources: []model.Resource{ + { + Kind: "kind", + Spec: model.Field{ + Type: model.Type{ + Name: "test", + Message: &v1.AcrylicType{}, + }, + }, + Stored: true, + }, + }}, + } + for i := range grps { + grps[i].Init() + } + }) + It("Renders manifests without template", func() { + // get api-level code gen options from descriptors + outFiles, err := render.RenderManifests( + "appName", "manifestDir", "protoDir", + nil, + model.GroupOptions{}, + grps, + ) + Expect(err).NotTo(HaveOccurred()) + Expect(outFiles).To(HaveLen(2)) // legacy and templated manifests + // only alpha versioned CRDs contain logic to conditionally render templates + Expect(outFiles[1].Content).ToNot(ContainSubstring("{{- if has \"kinds.things.test.io/v1alpha1\" $.Values.enabledExperimentalApi }}")) + Expect(outFiles[1].Content).ToNot(ContainSubstring("{{- end }}")) + }) + }) + + Describe("Generate combined alpha, grandfathered alpha, and non-alpha versioned CRD", func() { var ( grps []*model.Group ) @@ -154,7 +203,7 @@ var _ = Describe("ManifestsRenderer", func() { grps = []*model.Group{{ GroupVersion: schema.GroupVersion{ Group: "things.test.io", - Version: "v2alpha1", + Version: "v3alpha1", }, RenderManifests: true, AddChartVersion: "1.0.0", @@ -173,10 +222,30 @@ var _ = Describe("ManifestsRenderer", func() { { GroupVersion: schema.GroupVersion{ Group: "things.test.io", - Version: "v1", + Version: "v2", + }, + RenderManifests: true, + AddChartVersion: "1.0.0", + Resources: []model.Resource{ + { + Kind: "kind", + Spec: model.Field{ + Type: model.Type{ + Name: "test", + Message: &v1.AcrylicType{}, + }, + }, + Stored: true, + }, + }}, + { + GroupVersion: schema.GroupVersion{ + Group: "things.test.io", + Version: "v1alpha1", }, RenderManifests: true, AddChartVersion: "1.0.0", + Grandfathered: true, Resources: []model.Resource{ { Kind: "kind", @@ -205,9 +274,11 @@ var _ = Describe("ManifestsRenderer", func() { ) Expect(err).NotTo(HaveOccurred()) Expect(outFiles).To(HaveLen(2)) // legacy and templated manifests - // only v2alpha1 version of the CRDs is conditionally rendered, v1 has no conditions surrounding it - Expect(outFiles[1].Content).To(ContainSubstring("subresources: {}\n {{- if has \"kinds.things.test.io/v2alpha1\" $.Values.enabledExperimentalApi }}\n - name: v2alpha1")) + // only v3alpha1 version of the CRDs is conditionally rendered, v2 and v1alpha1 have no conditions surrounding them + Expect(outFiles[1].Content).To(ContainSubstring("subresources: {}\n {{- if has \"kinds.things.test.io/v3alpha1\" $.Values.enabledExperimentalApi }}")) + Expect(outFiles[1].Content).ToNot(ContainSubstring("{{- if has \"kinds.things.test.io/v1alpha1\" $.Values.enabledExperimentalApi }}\n - name: v2alpha1")) Expect(outFiles[1].Content).To(ContainSubstring("{{- end }}\n---\n")) + Expect(strings.Count(outFiles[1].Content, "{{- end }}")).To(Equal(1)) }) }) diff --git a/codegen/templates/manifests/crd.yamltmpl b/codegen/templates/manifests/crd.yamltmpl index 1f72c75f5..58b02d3d2 100644 --- a/codegen/templates/manifests/crd.yamltmpl +++ b/codegen/templates/manifests/crd.yamltmpl @@ -1,5 +1,5 @@ -[[- range $crd := . -]] -[[- if and (lt (len $crd.Spec.Versions) 2) (string_contains (index $crd.Spec.Versions 0).Name "alpha") ]] +[[- range $crd := .Crds -]] +[[- if and (and (lt (len $crd.Spec.Versions) 2) (string_contains (index $crd.Spec.Versions 0).Name "alpha")) (should_not_skip $crd.Spec.Group (index $crd.Spec.Versions 0).Name $.ShouldSkip) ]] {{- if has "[[ $crd.GetName ]]/[[ (index $crd.Spec.Versions 0).Name ]]" $.Values.enabledExperimentalApi }} [[- end ]] apiVersion: apiextensions.k8s.io/v1 @@ -14,16 +14,16 @@ spec: scope: [[ $crd.Spec.Scope ]] versions: [[- range $version := $crd.Spec.Versions ]] - [[- if and (gt (len $crd.Spec.Versions) 1) (string_contains $version.Name "alpha") ]] + [[- if and (and (gt (len $crd.Spec.Versions) 1) (string_contains $version.Name "alpha")) (should_not_skip $crd.Spec.Group $version.Name $.ShouldSkip) ]] {{- if has "[[ $crd.GetName ]]/[[ $version.Name ]]" $.Values.enabledExperimentalApi }} [[- end ]] - [[- $version | toYaml | indent 4 | trimPrefix " " ]] - [[- if and (gt (len $crd.Spec.Versions) 1) (string_contains $version.Name "alpha") ]] + [[- if and (and (gt (len $crd.Spec.Versions) 1) (string_contains $version.Name "alpha")) (should_not_skip $crd.Spec.Group $version.Name $.ShouldSkip) ]] {{- end }} [[- end ]] [[- end ]] -[[- if and (lt (len $crd.Spec.Versions) 2) (string_contains (index $crd.Spec.Versions 0).Name "alpha") ]] +[[- if and (and (lt (len $crd.Spec.Versions) 2) (string_contains (index $crd.Spec.Versions 0).Name "alpha")) (should_not_skip $crd.Spec.Group (index $crd.Spec.Versions 0).Name $.ShouldSkip) ]] {{- end }} [[- end ]] --- From 8ff87add47f1ea16c59fb71f278805b286648035 Mon Sep 17 00:00:00 2001 From: Dmitri Dolguikh Date: Thu, 27 Jul 2023 19:38:48 -0700 Subject: [PATCH 15/27] De-flaked a test Signed-off-by: Dmitri Dolguikh --- codegen/kuberesource/crd_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/codegen/kuberesource/crd_test.go b/codegen/kuberesource/crd_test.go index 2ca1b5775..fd09594ee 100644 --- a/codegen/kuberesource/crd_test.go +++ b/codegen/kuberesource/crd_test.go @@ -57,7 +57,9 @@ var _ = Describe("Crd", func() { Expect(o).To(HaveLen(2)) // note: we intentionally provide the "b6ec737002f7d02e" hash in the test, as it shouldn't change // between runs. - Expect(o[0].GetAnnotations()).To(HaveKeyWithValue(crdutils.CRDSpecHashKey, "b6ec737002f7d02e")) + hash0 := o[0].GetAnnotations()[crdutils.CRDSpecHashKey] == "b6ec737002f7d02e" + hash1 := o[1].GetAnnotations()[crdutils.CRDSpecHashKey] == "b6ec737002f7d02e" + Expect(hash0 || hash1).To(BeTrue()) }) It("should not generate spec hash", func() { grps[0].SkipSpecHash = true From acf693e11fd37032d1e9813a85d5e6888a1c0a4d Mon Sep 17 00:00:00 2001 From: Dmitri Dolguikh Date: Thu, 27 Jul 2023 21:13:08 -0700 Subject: [PATCH 16/27] Made ordering of crds in a group deterministic Signed-off-by: Dmitri Dolguikh --- codegen/kuberesource/crd.go | 8 ++- codegen/kuberesource/crd_test.go | 4 +- .../crds/things.test.io_crds.yaml | 66 +++++++++---------- .../templates/things.test.io_crds.yaml | 66 +++++++++---------- .../test/chart/crds/things.test.io_crds.yaml | 66 +++++++++---------- .../chart/templates/things.test.io_crds.yaml | 66 +++++++++---------- .../crds/things.test.io_crds.yaml | 34 +++++----- .../templates/things.test.io_crds.yaml | 34 +++++----- 8 files changed, 173 insertions(+), 171 deletions(-) diff --git a/codegen/kuberesource/crd.go b/codegen/kuberesource/crd.go index 6c3afbbbe..75d9e8a33 100644 --- a/codegen/kuberesource/crd.go +++ b/codegen/kuberesource/crd.go @@ -8,6 +8,7 @@ import ( "github.com/mitchellh/hashstructure" "github.com/solo-io/skv2/codegen/util/stringutils" "github.com/solo-io/skv2/pkg/crdutils" + "golang.org/x/exp/maps" "github.com/rotisserie/eris" "github.com/solo-io/skv2/codegen/model" @@ -30,9 +31,12 @@ func CustomResourceDefinitions( } } - for kind, resources := range resourcesByKind { + // Make ordering of crds in a group deterministic + kinds := maps.Keys(resourcesByKind) + sort.Strings(kinds) + for _, kind := range kinds { validationSchemas := make(map[string]*apiextv1.CustomResourceValidation) - resources := resources + resources := resourcesByKind[kind] // make version ordering deterministic sort.Slice(resources, func(i, j int) bool { return resources[i].Version < resources[j].Version }) for _, resource := range resources { diff --git a/codegen/kuberesource/crd_test.go b/codegen/kuberesource/crd_test.go index fd09594ee..2ca1b5775 100644 --- a/codegen/kuberesource/crd_test.go +++ b/codegen/kuberesource/crd_test.go @@ -57,9 +57,7 @@ var _ = Describe("Crd", func() { Expect(o).To(HaveLen(2)) // note: we intentionally provide the "b6ec737002f7d02e" hash in the test, as it shouldn't change // between runs. - hash0 := o[0].GetAnnotations()[crdutils.CRDSpecHashKey] == "b6ec737002f7d02e" - hash1 := o[1].GetAnnotations()[crdutils.CRDSpecHashKey] == "b6ec737002f7d02e" - Expect(hash0 || hash1).To(BeTrue()) + Expect(o[0].GetAnnotations()).To(HaveKeyWithValue(crdutils.CRDSpecHashKey, "b6ec737002f7d02e")) }) It("should not generate spec hash", func() { grps[0].SkipSpecHash = true diff --git a/codegen/test/chart-no-desc/crds/things.test.io_crds.yaml b/codegen/test/chart-no-desc/crds/things.test.io_crds.yaml index b44f06926..b83d9e1b8 100644 --- a/codegen/test/chart-no-desc/crds/things.test.io_crds.yaml +++ b/codegen/test/chart-no-desc/crds/things.test.io_crds.yaml @@ -1,5 +1,38 @@ # Code generated by skv2. DO NOT EDIT. +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + crd.solo.io/specHash: a7f6c51daca2a86e + labels: + app: "" + app.kubernetes.io/name: "" + name: clusterresources.things.test.io +spec: + group: things.test.io + names: + kind: ClusterResource + listKind: ClusterResourceList + plural: clusterresources + singular: clusterresource + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + spec: + properties: + imported: + type: string + type: object + type: object + served: true + storage: true + subresources: {} + +--- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: @@ -132,36 +165,3 @@ spec: storage: true subresources: status: {} - ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - crd.solo.io/specHash: a7f6c51daca2a86e - labels: - app: "" - app.kubernetes.io/name: "" - name: clusterresources.things.test.io -spec: - group: things.test.io - names: - kind: ClusterResource - listKind: ClusterResourceList - plural: clusterresources - singular: clusterresource - scope: Cluster - versions: - - name: v1 - schema: - openAPIV3Schema: - properties: - spec: - properties: - imported: - type: string - type: object - type: object - served: true - storage: true - subresources: {} diff --git a/codegen/test/chart-no-desc/templates/things.test.io_crds.yaml b/codegen/test/chart-no-desc/templates/things.test.io_crds.yaml index 38e88c562..f5cc1031a 100644 --- a/codegen/test/chart-no-desc/templates/things.test.io_crds.yaml +++ b/codegen/test/chart-no-desc/templates/things.test.io_crds.yaml @@ -1,6 +1,39 @@ # Code generated by skv2. DO NOT EDIT. +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + crd.solo.io/specHash: a7f6c51daca2a86e + labels: + app: "" + app.kubernetes.io/name: "" + name: clusterresources.things.test.io +spec: + group: things.test.io + names: + kind: ClusterResource + listKind: ClusterResourceList + plural: clusterresources + singular: clusterresource + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + spec: + properties: + imported: + type: string + type: object + type: object + served: true + storage: true + subresources: {} +--- + apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: @@ -134,36 +167,3 @@ spec: subresources: status: {} --- - -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - crd.solo.io/specHash: a7f6c51daca2a86e - labels: - app: "" - app.kubernetes.io/name: "" - name: clusterresources.things.test.io -spec: - group: things.test.io - names: - kind: ClusterResource - listKind: ClusterResourceList - plural: clusterresources - singular: clusterresource - scope: Cluster - versions: - - name: v1 - schema: - openAPIV3Schema: - properties: - spec: - properties: - imported: - type: string - type: object - type: object - served: true - storage: true - subresources: {} ---- diff --git a/codegen/test/chart/crds/things.test.io_crds.yaml b/codegen/test/chart/crds/things.test.io_crds.yaml index 0a333a174..3aa575da9 100644 --- a/codegen/test/chart/crds/things.test.io_crds.yaml +++ b/codegen/test/chart/crds/things.test.io_crds.yaml @@ -1,5 +1,38 @@ # Code generated by skv2. DO NOT EDIT. +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + crd.solo.io/specHash: a7f6c51daca2a86e + labels: + app: "" + app.kubernetes.io/name: "" + name: clusterresources.things.test.io +spec: + group: things.test.io + names: + kind: ClusterResource + listKind: ClusterResourceList + plural: clusterresources + singular: clusterresource + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + spec: + properties: + imported: + type: string + type: object + type: object + served: true + storage: true + subresources: {} + +--- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: @@ -136,36 +169,3 @@ spec: storage: true subresources: status: {} - ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - crd.solo.io/specHash: a7f6c51daca2a86e - labels: - app: "" - app.kubernetes.io/name: "" - name: clusterresources.things.test.io -spec: - group: things.test.io - names: - kind: ClusterResource - listKind: ClusterResourceList - plural: clusterresources - singular: clusterresource - scope: Cluster - versions: - - name: v1 - schema: - openAPIV3Schema: - properties: - spec: - properties: - imported: - type: string - type: object - type: object - served: true - storage: true - subresources: {} diff --git a/codegen/test/chart/templates/things.test.io_crds.yaml b/codegen/test/chart/templates/things.test.io_crds.yaml index b634b9e21..50170ee18 100644 --- a/codegen/test/chart/templates/things.test.io_crds.yaml +++ b/codegen/test/chart/templates/things.test.io_crds.yaml @@ -1,6 +1,39 @@ # Code generated by skv2. DO NOT EDIT. +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + crd.solo.io/specHash: a7f6c51daca2a86e + labels: + app: "" + app.kubernetes.io/name: "" + name: clusterresources.things.test.io +spec: + group: things.test.io + names: + kind: ClusterResource + listKind: ClusterResourceList + plural: clusterresources + singular: clusterresource + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + spec: + properties: + imported: + type: string + type: object + type: object + served: true + storage: true + subresources: {} +--- + apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: @@ -138,36 +171,3 @@ spec: subresources: status: {} --- - -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - crd.solo.io/specHash: a7f6c51daca2a86e - labels: - app: "" - app.kubernetes.io/name: "" - name: clusterresources.things.test.io -spec: - group: things.test.io - names: - kind: ClusterResource - listKind: ClusterResourceList - plural: clusterresources - singular: clusterresource - scope: Cluster - versions: - - name: v1 - schema: - openAPIV3Schema: - properties: - spec: - properties: - imported: - type: string - type: object - type: object - served: true - storage: true - subresources: {} ---- diff --git a/codegen/test/name_override_chart/crds/things.test.io_crds.yaml b/codegen/test/name_override_chart/crds/things.test.io_crds.yaml index 69f3cbb1c..649673502 100644 --- a/codegen/test/name_override_chart/crds/things.test.io_crds.yaml +++ b/codegen/test/name_override_chart/crds/things.test.io_crds.yaml @@ -4,19 +4,19 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - crd.solo.io/specHash: 80e7931efac2214e + crd.solo.io/specHash: 2c0000aa4677e683 labels: app: "" app.kubernetes.io/name: "" - name: paints.things.test.io + name: clusterresources.things.test.io spec: group: things.test.io names: - kind: Paint - listKind: PaintList - plural: paints - singular: paint - scope: Namespaced + kind: ClusterResource + listKind: ClusterResourceList + plural: clusterresources + singular: clusterresource + scope: Cluster versions: - name: v1 schema: @@ -25,27 +25,26 @@ spec: x-kubernetes-preserve-unknown-fields: true served: true storage: true - subresources: - status: {} + subresources: {} --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - crd.solo.io/specHash: 2c0000aa4677e683 + crd.solo.io/specHash: 80e7931efac2214e labels: app: "" app.kubernetes.io/name: "" - name: clusterresources.things.test.io + name: paints.things.test.io spec: group: things.test.io names: - kind: ClusterResource - listKind: ClusterResourceList - plural: clusterresources - singular: clusterresource - scope: Cluster + kind: Paint + listKind: PaintList + plural: paints + singular: paint + scope: Namespaced versions: - name: v1 schema: @@ -54,4 +53,5 @@ spec: x-kubernetes-preserve-unknown-fields: true served: true storage: true - subresources: {} + subresources: + status: {} diff --git a/codegen/test/name_override_chart/templates/things.test.io_crds.yaml b/codegen/test/name_override_chart/templates/things.test.io_crds.yaml index f8e0072e0..d23e63f00 100644 --- a/codegen/test/name_override_chart/templates/things.test.io_crds.yaml +++ b/codegen/test/name_override_chart/templates/things.test.io_crds.yaml @@ -5,19 +5,19 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - crd.solo.io/specHash: 80e7931efac2214e + crd.solo.io/specHash: 2c0000aa4677e683 labels: app: "" app.kubernetes.io/name: "" - name: paints.things.test.io + name: clusterresources.things.test.io spec: group: things.test.io names: - kind: Paint - listKind: PaintList - plural: paints - singular: paint - scope: Namespaced + kind: ClusterResource + listKind: ClusterResourceList + plural: clusterresources + singular: clusterresource + scope: Cluster versions: - name: v1 schema: @@ -26,27 +26,26 @@ spec: x-kubernetes-preserve-unknown-fields: true served: true storage: true - subresources: - status: {} + subresources: {} --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - crd.solo.io/specHash: 2c0000aa4677e683 + crd.solo.io/specHash: 80e7931efac2214e labels: app: "" app.kubernetes.io/name: "" - name: clusterresources.things.test.io + name: paints.things.test.io spec: group: things.test.io names: - kind: ClusterResource - listKind: ClusterResourceList - plural: clusterresources - singular: clusterresource - scope: Cluster + kind: Paint + listKind: PaintList + plural: paints + singular: paint + scope: Namespaced versions: - name: v1 schema: @@ -55,5 +54,6 @@ spec: x-kubernetes-preserve-unknown-fields: true served: true storage: true - subresources: {} + subresources: + status: {} --- From 697c2afd673a1e50c0dfff32913b21a4071ca28d Mon Sep 17 00:00:00 2001 From: Dmitri Dolguikh Date: Fri, 28 Jul 2023 09:06:34 -0700 Subject: [PATCH 17/27] Responded to feedback Signed-off-by: Dmitri Dolguikh --- codegen/kuberesource/crd.go | 47 +++++++++++++-- codegen/kuberesource/crd_test.go | 86 ++++++++++++++++++++++++++++ codegen/model/resource.go | 6 ++ codegen/render/manifests_renderer.go | 19 +++--- 4 files changed, 144 insertions(+), 14 deletions(-) diff --git a/codegen/kuberesource/crd.go b/codegen/kuberesource/crd.go index 75d9e8a33..ac345a4b0 100644 --- a/codegen/kuberesource/crd.go +++ b/codegen/kuberesource/crd.go @@ -5,6 +5,7 @@ import ( "sort" "strings" + "github.com/google/go-cmp/cmp" "github.com/mitchellh/hashstructure" "github.com/solo-io/skv2/codegen/util/stringutils" "github.com/solo-io/skv2/pkg/crdutils" @@ -53,7 +54,11 @@ func CustomResourceDefinitions( validationSchemas[resource.Group.String()] = validationSchema } - objects = append(objects, *CustomResourceDefinition(resources, validationSchemas, skipHashByKind[kind])) + crd, err := CustomResourceDefinition(resources, validationSchemas, skipHashByKind[kind]) + if err != nil { + return nil, err + } + objects = append(objects, *crd) } return objects, nil } @@ -137,11 +142,44 @@ func validateStructural(s *apiextv1.JSONSchemaProps) error { return nil } +func validateCRDResources(resources []model.Resource) error { + if len(resources) < 2 { + return nil + } + + previousScope := resources[0].ClusterScoped + previousShortName := resources[0].ShortNames + previousCategories := resources[0].Categories + + for i := 1; i < len(resources); i++ { + if resources[i].ClusterScoped != previousScope { + return fmt.Errorf("mismatched 'currentScope' in versions of CRD for resource kind %s", resources[i].Kind) + } + if !cmp.Equal(resources[i].ShortNames, previousShortName) { + return fmt.Errorf("mismatched 'ShortNames' in versions of CRD for resource kind %s", resources[i].Kind) + } + if !cmp.Equal(resources[i].Categories, previousCategories) { + return fmt.Errorf("mismatched 'Categories' in versions of CRD for resource kind %s", resources[i].Kind) + } + + previousScope = resources[i].ClusterScoped + previousShortName = resources[i].ShortNames + previousCategories = resources[i].Categories + } + + return nil +} + func CustomResourceDefinition( resources []model.Resource, validationSchemas map[string]*apiextv1.CustomResourceValidation, withoutSpecHash bool, -) *apiextv1.CustomResourceDefinition { +) (*apiextv1.CustomResourceDefinition, error) { + + err := validateCRDResources(resources) + if err != nil { + return nil, err + } group := resources[0].Group.Group kind := resources[0].Kind @@ -149,9 +187,6 @@ func CustomResourceDefinition( kindLower := strings.ToLower(kind) scope := apiextv1.NamespaceScoped - // TODO (dmitri-d) Should we check if all resources have the same scope - // and bail if not? - // Same for ShortNames and Categories below if resources[0].ClusterScoped { scope = apiextv1.ClusterScoped } @@ -213,5 +248,5 @@ func CustomResourceDefinition( // Setting PreserveUnknownFields to false ensures that objects with unknown fields are rejected. crd.Spec.PreserveUnknownFields = false } - return crd + return crd, nil } diff --git a/codegen/kuberesource/crd_test.go b/codegen/kuberesource/crd_test.go index 2ca1b5775..316d1ed52 100644 --- a/codegen/kuberesource/crd_test.go +++ b/codegen/kuberesource/crd_test.go @@ -1,8 +1,11 @@ package kuberesource_test import ( + "fmt" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" v1 "github.com/solo-io/skv2/codegen/test/api/things.test.io/v1" @@ -83,4 +86,87 @@ var _ = Describe("Crd", func() { }) + Describe("CRD gen with errors", func() { + It("should return an error when scopes are mismatched", func() { + resources := []model.Resource{ + { + Kind: "kind", + Spec: model.Field{ + Type: model.Type{ + Name: "test", + Message: &v1.AcrylicType{}, + }, + }, + ClusterScoped: true, + }, + { + Kind: "kind", + Spec: model.Field{ + Type: model.Type{ + Name: "test", + Message: &v1.PaintColor{}, + }, + }, + ClusterScoped: false, + }, + } + + _, err := CustomResourceDefinition(resources, map[string]*apiextv1.CustomResourceValidation{}, false) + Expect(err).To(Equal(fmt.Errorf("mismatched 'currentScope' in versions of CRD for resource kind kind"))) + }) + It("should return an error when ShortNames are mismatched", func() { + resources := []model.Resource{ + { + Kind: "kind", + Spec: model.Field{ + Type: model.Type{ + Name: "test", + Message: &v1.AcrylicType{}, + }, + }, + ShortNames: []string{"name1", "name2"}, + }, + { + Kind: "kind", + Spec: model.Field{ + Type: model.Type{ + Name: "test", + Message: &v1.PaintColor{}, + }, + }, + ShortNames: []string{"name2", "name3"}, + }, + } + + _, err := CustomResourceDefinition(resources, map[string]*apiextv1.CustomResourceValidation{}, false) + Expect(err).To(Equal(fmt.Errorf("mismatched 'ShortNames' in versions of CRD for resource kind kind"))) + }) + It("should return an error when Categories are mismatched", func() { + resources := []model.Resource{ + { + Kind: "kind", + Spec: model.Field{ + Type: model.Type{ + Name: "test", + Message: &v1.AcrylicType{}, + }, + }, + Categories: []string{"cat1", "cat2"}, + }, + { + Kind: "kind", + Spec: model.Field{ + Type: model.Type{ + Name: "test", + Message: &v1.PaintColor{}, + }, + }, + Categories: []string{"cat2", "cat3"}, + }, + } + + _, err := CustomResourceDefinition(resources, map[string]*apiextv1.CustomResourceValidation{}, false) + Expect(err).To(Equal(fmt.Errorf("mismatched 'Categories' in versions of CRD for resource kind kind"))) + }) + }) }) diff --git a/codegen/model/resource.go b/codegen/model/resource.go index b18c8a2bb..de14cccb3 100644 --- a/codegen/model/resource.go +++ b/codegen/model/resource.go @@ -118,6 +118,12 @@ type Group struct { // true if this should not be considered "experimental" // even if the Version string contains "alpha" Grandfathered bool + + // Skip generation of crd manifests that live in crd/ directory of a chart + SkipCRDManifest bool + + // Skip generation of templated crd manifests that live in templates/ dir of a chart + SkipTemplatedCRDManifest bool } type GroupOptions struct { diff --git a/codegen/render/manifests_renderer.go b/codegen/render/manifests_renderer.go index 9fe84e6ee..97a5ea1a5 100644 --- a/codegen/render/manifests_renderer.go +++ b/codegen/render/manifests_renderer.go @@ -59,13 +59,17 @@ func RenderManifests( func (r ManifestsRenderer) RenderManifests(grps []*Group, protoOpts protoutil.Options, groupOptions model.GroupOptions) ([]OutFile, error) { grpsByGroupName := make(map[string][]*Group) shouldRenderGroups := make(map[string]bool) + shouldSkipCRDManifest := make(map[string]bool) + shouldSkipTemplatedCRDManifest := make(map[string]bool) grandfatheredGroups := make(map[string]bool) for _, grp := range grps { grpsByGroupName[grp.Group] = append(grpsByGroupName[grp.Group], grp) shouldRenderGroups[grp.Group] = shouldRenderGroups[grp.Group] || grp.RenderManifests - if grp.Grandfathered { - grandfatheredGroups[grp.GroupVersion.String()] = true - } + grandfatheredGroups[grp.GroupVersion.String()] = grandfatheredGroups[grp.GroupVersion.String()] || grp.Grandfathered + shouldSkipCRDManifest[grp.Group] = + shouldSkipCRDManifest[grp.Group] || grp.SkipCRDManifest + shouldSkipTemplatedCRDManifest[grp.Group] = + shouldSkipTemplatedCRDManifest[grp.Group] || grp.SkipTemplatedCRDManifest } for _, grp := range grps { @@ -90,14 +94,13 @@ func (r ManifestsRenderer) RenderManifests(grps []*Group, protoOpts protoutil.Op if err != nil { return nil, err } - // TODO (dmitri-d): this can be removed once we migrate to use platform charts exclusively - out, err := r.renderLegacyManifest(r.AppName, groupName, crds) + out, err := r.renderCRDManifest(r.AppName, groupName, crds) if err != nil { return nil, err } renderedFiles = append(renderedFiles, out) - out, err = r.renderTemplatedManifest(r.AppName, groupName, crds, grandfatheredGroups) + out, err = r.renderTemplatedCRDManifest(r.AppName, groupName, crds, grandfatheredGroups) if err != nil { return nil, err } @@ -248,7 +251,7 @@ func SetVersionForObject(obj metav1.Object, version string) { } // TODO (dmitri-d): this can be removed once we migrate to use platform charts exclusively -func (r ManifestsRenderer) renderLegacyManifest(appName, groupName string, objs []apiextv1.CustomResourceDefinition) (OutFile, error) { +func (r ManifestsRenderer) renderCRDManifest(appName, groupName string, objs []apiextv1.CustomResourceDefinition) (OutFile, error) { outFile := OutFile{ Path: r.ManifestDir + "/crds/" + groupName + "_" + "crds.yaml", } @@ -266,7 +269,7 @@ func (r ManifestsRenderer) renderLegacyManifest(appName, groupName string, objs return outFile, nil } -func (r ManifestsRenderer) renderTemplatedManifest(appName, groupName string, +func (r ManifestsRenderer) renderTemplatedCRDManifest(appName, groupName string, objs []apiextv1.CustomResourceDefinition, grandfatheredGroups map[string]bool) (OutFile, error) { From 49c4f850b1e982224d4797ce793c03a2b61a805d Mon Sep 17 00:00:00 2001 From: Dmitri Dolguikh Date: Fri, 28 Jul 2023 09:25:20 -0700 Subject: [PATCH 18/27] Fixed an issue in template rendering Signed-off-by: Dmitri Dolguikh --- api/multicluster/v1alpha1/group.go | 1 + codegen/render/funcs.go | 3 +-- go.mod | 2 +- templates/multicluster.solo.io_crds.yaml | 2 -- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/api/multicluster/v1alpha1/group.go b/api/multicluster/v1alpha1/group.go index 5782dba2a..d827cabe6 100644 --- a/api/multicluster/v1alpha1/group.go +++ b/api/multicluster/v1alpha1/group.go @@ -37,4 +37,5 @@ var Group = model.Group{ MockgenDirective: true, ApiRoot: "pkg/api", CustomTemplates: contrib.AllGroupCustomTemplates, + Grandfathered: true, } diff --git a/codegen/render/funcs.go b/codegen/render/funcs.go index b1e90f7a0..859dc76d0 100644 --- a/codegen/render/funcs.go +++ b/codegen/render/funcs.go @@ -133,8 +133,7 @@ func makeTemplateFuncs(customFuncs template.FuncMap) template.FuncMap { "opVar": opVar, "should_not_skip": func(group, version string, skips map[string]bool) bool { - _, ok := skips[group+"/"+version] - return !ok + return !skips[group+"/"+version] }, } diff --git a/go.mod b/go.mod index 221e17926..53405253b 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,7 @@ require ( github.com/golang/mock v1.6.0 github.com/golang/protobuf v1.5.2 github.com/google/gnostic v0.5.7-v3refs + github.com/google/go-cmp v0.5.9 github.com/hashicorp/go-multierror v1.1.0 github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 github.com/iancoleman/strcase v0.1.3 @@ -79,7 +80,6 @@ require ( github.com/gobuffalo/packd v0.3.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/google/go-cmp v0.5.9 // indirect github.com/google/gofuzz v1.1.0 // indirect github.com/google/uuid v1.2.0 // indirect github.com/hashicorp/errwrap v1.0.0 // indirect diff --git a/templates/multicluster.solo.io_crds.yaml b/templates/multicluster.solo.io_crds.yaml index ee6e8f2d5..f430e3c30 100644 --- a/templates/multicluster.solo.io_crds.yaml +++ b/templates/multicluster.solo.io_crds.yaml @@ -1,7 +1,6 @@ # Code generated by skv2. DO NOT EDIT. -{{- if has "kubernetesclusters.multicluster.solo.io/v1alpha1" $.Values.enabledExperimentalApi }} apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: @@ -159,5 +158,4 @@ spec: storage: true subresources: status: {} -{{- end }} --- From bf1770905c85243fe0631678d1caa581bc6950f4 Mon Sep 17 00:00:00 2001 From: Dmitri Dolguikh Date: Fri, 28 Jul 2023 13:02:31 -0700 Subject: [PATCH 19/27] Responded to feedback Signed-off-by: Dmitri Dolguikh --- .../conditional_crd_rendering.yaml | 0 codegen/cmd.go | 4 ++-- codegen/kuberesource/crd.go | 16 ++++++---------- codegen/model/resource.go | 7 +++++++ codegen/render/manifests_renderer.go | 2 ++ 5 files changed, 17 insertions(+), 12 deletions(-) rename changelog/{v0.31.3 => v0.32.0}/conditional_crd_rendering.yaml (100%) diff --git a/changelog/v0.31.3/conditional_crd_rendering.yaml b/changelog/v0.32.0/conditional_crd_rendering.yaml similarity index 100% rename from changelog/v0.31.3/conditional_crd_rendering.yaml rename to changelog/v0.32.0/conditional_crd_rendering.yaml diff --git a/codegen/cmd.go b/codegen/cmd.go index 4c0105454..95afd896c 100644 --- a/codegen/cmd.go +++ b/codegen/cmd.go @@ -148,7 +148,7 @@ func (c Command) Execute() error { groups = append(groups, &group) } - if err := c.generateGroup(groups, protoOpts, c.GroupOptions); err != nil { + if err := c.generateGroups(groups, protoOpts, c.GroupOptions); err != nil { return err } @@ -238,7 +238,7 @@ func (c Command) renderProtos() ([]*collector.DescriptorWithPath, error) { return descriptors, nil } -func (c Command) generateGroup( +func (c Command) generateGroups( grps []*model.Group, protoOpts proto.Options, groupOptions model.GroupOptions, diff --git a/codegen/kuberesource/crd.go b/codegen/kuberesource/crd.go index ac345a4b0..8ff95a557 100644 --- a/codegen/kuberesource/crd.go +++ b/codegen/kuberesource/crd.go @@ -147,24 +147,20 @@ func validateCRDResources(resources []model.Resource) error { return nil } - previousScope := resources[0].ClusterScoped - previousShortName := resources[0].ShortNames - previousCategories := resources[0].Categories + scope := resources[0].ClusterScoped + shortNames := resources[0].ShortNames + categories := resources[0].Categories for i := 1; i < len(resources); i++ { - if resources[i].ClusterScoped != previousScope { + if resources[i].ClusterScoped != scope { return fmt.Errorf("mismatched 'currentScope' in versions of CRD for resource kind %s", resources[i].Kind) } - if !cmp.Equal(resources[i].ShortNames, previousShortName) { + if !cmp.Equal(resources[i].ShortNames, shortNames) { return fmt.Errorf("mismatched 'ShortNames' in versions of CRD for resource kind %s", resources[i].Kind) } - if !cmp.Equal(resources[i].Categories, previousCategories) { + if !cmp.Equal(resources[i].Categories, categories) { return fmt.Errorf("mismatched 'Categories' in versions of CRD for resource kind %s", resources[i].Kind) } - - previousScope = resources[i].ClusterScoped - previousShortName = resources[i].ShortNames - previousCategories = resources[i].Categories } return nil diff --git a/codegen/model/resource.go b/codegen/model/resource.go index de14cccb3..5ddfc68da 100644 --- a/codegen/model/resource.go +++ b/codegen/model/resource.go @@ -183,8 +183,15 @@ type Resource struct { // If enabled, the unmarshal will NOT allow unknown fields. StrictUnmarshal bool + // Corresponds to CRD's versions.storage field + // Only one version of a resource can be marked as "stored" + // Set to false by default + // See https://kubernetes.io/docs/reference/kubernetes-api/extend-resources/custom-resource-definition-v1/#CustomResourceDefinitionSpec Stored bool + // Corresponds to CRD's versions.deprecated field + // Set to false by default + // See https://kubernetes.io/docs/reference/kubernetes-api/extend-resources/custom-resource-definition-v1/#CustomResourceDefinitionSpec Deprecated bool } diff --git a/codegen/render/manifests_renderer.go b/codegen/render/manifests_renderer.go index 97a5ea1a5..2414b64d7 100644 --- a/codegen/render/manifests_renderer.go +++ b/codegen/render/manifests_renderer.go @@ -294,6 +294,8 @@ func (r ManifestsRenderer) renderTemplatedCRDManifest(appName, groupName string, if err != nil { return OutFile{}, err } + // if we got here there's one item in []files, + // as we only rendered one template and there were no errors return files[0], nil } From 7c8768635b69b11a10efc7794df24a75c661fa54 Mon Sep 17 00:00:00 2001 From: Dmitri Dolguikh Date: Fri, 28 Jul 2023 13:19:17 -0700 Subject: [PATCH 20/27] changed changelog entry to 'BREAKING_CHANGE' Signed-off-by: Dmitri Dolguikh --- changelog/v0.32.0/conditional_crd_rendering.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog/v0.32.0/conditional_crd_rendering.yaml b/changelog/v0.32.0/conditional_crd_rendering.yaml index 9be5a7354..0ad14deed 100644 --- a/changelog/v0.32.0/conditional_crd_rendering.yaml +++ b/changelog/v0.32.0/conditional_crd_rendering.yaml @@ -1,5 +1,5 @@ changelog: - - type: NON_USER_FACING + - type: BREAKING_CHANGE issueLink: https://github.com/solo-io/gloo-mesh-enterprise/issues/9019 description: > Add support for conditional rendering of CRDs. From 774e479cbb1477b281fc50d773c426118ef26b3b Mon Sep 17 00:00:00 2001 From: Dmitri Dolguikh Date: Fri, 28 Jul 2023 13:29:12 -0700 Subject: [PATCH 21/27] cleaned up crd.CustomResourceDefinitions Signed-off-by: Dmitri Dolguikh --- codegen/kuberesource/crd.go | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/codegen/kuberesource/crd.go b/codegen/kuberesource/crd.go index 8ff95a557..ef655204e 100644 --- a/codegen/kuberesource/crd.go +++ b/codegen/kuberesource/crd.go @@ -36,22 +36,12 @@ func CustomResourceDefinitions( kinds := maps.Keys(resourcesByKind) sort.Strings(kinds) for _, kind := range kinds { - validationSchemas := make(map[string]*apiextv1.CustomResourceValidation) resources := resourcesByKind[kind] // make version ordering deterministic sort.Slice(resources, func(i, j int) bool { return resources[i].Version < resources[j].Version }) - for _, resource := range resources { - var validationSchema *apiextv1.CustomResourceValidation - validationSchema, err = constructValidationSchema( - resource.Group.RenderValidationSchemas, - resource, - resource.Group.OpenApiSchemas, - ) - if err != nil { - return nil, err - } - - validationSchemas[resource.Group.String()] = validationSchema + validationSchemas, err := constructValidationSchemas(resources) + if err != nil { + return nil, err } crd, err := CustomResourceDefinition(resources, validationSchemas, skipHashByKind[kind]) @@ -63,6 +53,24 @@ func CustomResourceDefinitions( return objects, nil } +func constructValidationSchemas(resources []model.Resource) (map[string]*apiextv1.CustomResourceValidation, error) { + validationSchemas := make(map[string]*apiextv1.CustomResourceValidation) + for _, resource := range resources { + var validationSchema *apiextv1.CustomResourceValidation + validationSchema, err := constructValidationSchema( + resource.Group.RenderValidationSchemas, + resource, + resource.Group.OpenApiSchemas, + ) + if err != nil { + return nil, err + } + + validationSchemas[resource.Group.String()] = validationSchema + } + return validationSchemas, nil +} + func constructValidationSchema( renderValidationSchema bool, resource model.Resource, From 458d999d7abae3e2e1cc3f6d7f30baac68906875 Mon Sep 17 00:00:00 2001 From: Dmitri Dolguikh Date: Fri, 28 Jul 2023 16:46:59 -0700 Subject: [PATCH 22/27] Made configurable the name for the flag that contains the list of enabled alpha API Signed-off-by: Dmitri Dolguikh --- api/multicluster/v1alpha1/group.go | 18 +++++++++--------- codegen/cmd.go | 6 +++++- codegen/model/resource.go | 7 ++++--- codegen/render/funcs.go | 7 +++++-- codegen/render/manifests_renderer.go | 22 ++++++++++++++-------- codegen/render/manifests_renderer_test.go | 20 ++++++++++---------- codegen/templates/manifests/crd.yamltmpl | 12 ++++++------ 7 files changed, 53 insertions(+), 39 deletions(-) diff --git a/api/multicluster/v1alpha1/group.go b/api/multicluster/v1alpha1/group.go index d827cabe6..a63cf9fa7 100644 --- a/api/multicluster/v1alpha1/group.go +++ b/api/multicluster/v1alpha1/group.go @@ -29,13 +29,13 @@ var Group = model.Group{ Stored: true, }, }, - RenderManifests: true, - RenderValidationSchemas: true, - RenderController: true, - RenderClients: true, - RenderTypes: true, - MockgenDirective: true, - ApiRoot: "pkg/api", - CustomTemplates: contrib.AllGroupCustomTemplates, - Grandfathered: true, + RenderManifests: true, + RenderValidationSchemas: true, + RenderController: true, + RenderClients: true, + RenderTypes: true, + MockgenDirective: true, + ApiRoot: "pkg/api", + CustomTemplates: contrib.AllGroupCustomTemplates, + SkipConditionalCRDLoading: true, } diff --git a/codegen/cmd.go b/codegen/cmd.go index 95afd896c..41c90cd65 100644 --- a/codegen/cmd.go +++ b/codegen/cmd.go @@ -106,6 +106,10 @@ type Command struct { // context of the command ctx context.Context + + // the name of the flag to pass the list of enabled alpha-level crds + // used in codegen/templates/manifests/crd.yamltmpl + EnabledAlphaApiFlagName string } // function to execute skv2 code gen from another repository @@ -269,7 +273,7 @@ func (c Command) generateGroups( } } - manifests, err := render.RenderManifests(c.AppName, c.ManifestRoot, c.ProtoDir, protoOpts, groupOptions, grps) + manifests, err := render.RenderManifests(c.AppName, c.ManifestRoot, c.ProtoDir, c.EnabledAlphaApiFlagName, protoOpts, groupOptions, grps) if err != nil { return err } diff --git a/codegen/model/resource.go b/codegen/model/resource.go index 5ddfc68da..e508a6008 100644 --- a/codegen/model/resource.go +++ b/codegen/model/resource.go @@ -115,9 +115,10 @@ type Group struct { // Some resources use pointer slices for the Items field. PointerSlices bool `default:"false"` - // true if this should not be considered "experimental" - // even if the Version string contains "alpha" - Grandfathered bool + // Set to true to skip rendering of conditional loading logic + // for CRDs containing alpha-versioned resources. + // Used by codegen/templates/manifests/crd.yamltmpl + SkipConditionalCRDLoading bool // Skip generation of crd manifests that live in crd/ directory of a chart SkipCRDManifest bool diff --git a/codegen/render/funcs.go b/codegen/render/funcs.go index 859dc76d0..c27130f43 100644 --- a/codegen/render/funcs.go +++ b/codegen/render/funcs.go @@ -15,6 +15,7 @@ import ( "github.com/solo-io/skv2/codegen/util/stringutils" "google.golang.org/protobuf/types/known/structpb" v1 "k8s.io/api/core/v1" + apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" @@ -132,8 +133,10 @@ func makeTemplateFuncs(customFuncs template.FuncMap) template.FuncMap { "opVar": opVar, - "should_not_skip": func(group, version string, skips map[string]bool) bool { - return !skips[group+"/"+version] + "render_conditional_crd_template": func(crd apiextv1.CustomResourceDefinition, currentVersion string, skips map[string]bool) bool { + wrapWholeCrd := len(crd.Spec.Versions) < 2 && strings.Contains(currentVersion, "alpha") && !skips[crd.Spec.Group+"/"+currentVersion] + wrapSingleVersion := len(crd.Spec.Versions) > 1 && strings.Contains(currentVersion, "alpha") && !skips[crd.Spec.Group+"/"+currentVersion] + return wrapWholeCrd || wrapSingleVersion }, } diff --git a/codegen/render/manifests_renderer.go b/codegen/render/manifests_renderer.go index 2414b64d7..8cb838116 100644 --- a/codegen/render/manifests_renderer.go +++ b/codegen/render/manifests_renderer.go @@ -35,23 +35,28 @@ type ManifestsRenderer struct { ResourceFuncs map[OutFile]MakeResourceFunc ManifestDir string ProtoDir string + // the name of the flag to pass the list of enabled alpha-level crds + // used in codegen/templates/manifests/crd.yamltmpl + EnabledAlphaApiFlagName string } type templateArgs struct { - Crds []apiextv1.CustomResourceDefinition - ShouldSkip map[string]bool + Crds []apiextv1.CustomResourceDefinition + ShouldSkip map[string]bool + EnabledAlphaApiFlagName string } func RenderManifests( - appName, manifestDir, protoDir string, + appName, manifestDir, protoDir, enabledAlphaApiFlagName string, protoOpts protoutil.Options, groupOptions model.GroupOptions, grps []*Group, ) ([]OutFile, error) { defaultManifestsRenderer := ManifestsRenderer{ - AppName: appName, - ManifestDir: manifestDir, - ProtoDir: protoDir, + AppName: appName, + ManifestDir: manifestDir, + ProtoDir: protoDir, + EnabledAlphaApiFlagName: enabledAlphaApiFlagName, } return defaultManifestsRenderer.RenderManifests(grps, protoOpts, groupOptions) } @@ -65,7 +70,7 @@ func (r ManifestsRenderer) RenderManifests(grps []*Group, protoOpts protoutil.Op for _, grp := range grps { grpsByGroupName[grp.Group] = append(grpsByGroupName[grp.Group], grp) shouldRenderGroups[grp.Group] = shouldRenderGroups[grp.Group] || grp.RenderManifests - grandfatheredGroups[grp.GroupVersion.String()] = grandfatheredGroups[grp.GroupVersion.String()] || grp.Grandfathered + grandfatheredGroups[grp.GroupVersion.String()] = grandfatheredGroups[grp.GroupVersion.String()] || grp.SkipConditionalCRDLoading shouldSkipCRDManifest[grp.Group] = shouldSkipCRDManifest[grp.Group] || grp.SkipCRDManifest shouldSkipTemplatedCRDManifest[grp.Group] = @@ -288,9 +293,10 @@ func (r ManifestsRenderer) renderTemplatedCRDManifest(appName, groupName string, templatesToRender := inputTemplates{ "manifests/crd.yamltmpl": outFile, } + // validate that templates will render ok files, err := defaultManifestRenderer.renderCoreTemplates( templatesToRender, - templateArgs{Crds: objs, ShouldSkip: grandfatheredGroups}) + templateArgs{Crds: objs, ShouldSkip: grandfatheredGroups, EnabledAlphaApiFlagName: r.EnabledAlphaApiFlagName}) if err != nil { return OutFile{}, err } diff --git a/codegen/render/manifests_renderer_test.go b/codegen/render/manifests_renderer_test.go index f3a8646ae..e3e859d5f 100644 --- a/codegen/render/manifests_renderer_test.go +++ b/codegen/render/manifests_renderer_test.go @@ -84,7 +84,7 @@ var _ = Describe("ManifestsRenderer", func() { // get api-level code gen options from descriptors outFiles, err := render.RenderManifests( - "appName", "manifestDir", "protoDir", + "appName", "manifestDir", "protoDir", "enabledExperimentalApi", nil, model.GroupOptions{}, grps, @@ -132,7 +132,7 @@ var _ = Describe("ManifestsRenderer", func() { // get api-level code gen options from descriptors outFiles, err := render.RenderManifests( - "appName", "manifestDir", "protoDir", + "appName", "manifestDir", "protoDir", "enabledExperimentalApi", nil, model.GroupOptions{}, grps, @@ -158,9 +158,9 @@ var _ = Describe("ManifestsRenderer", func() { Group: "things.test.io", Version: "v1alpha1", }, - RenderManifests: true, - AddChartVersion: "1.0.0", - Grandfathered: true, + RenderManifests: true, + AddChartVersion: "1.0.0", + SkipConditionalCRDLoading: true, Resources: []model.Resource{ { Kind: "kind", @@ -181,7 +181,7 @@ var _ = Describe("ManifestsRenderer", func() { It("Renders manifests without template", func() { // get api-level code gen options from descriptors outFiles, err := render.RenderManifests( - "appName", "manifestDir", "protoDir", + "appName", "manifestDir", "protoDir", "enabledExperimentalApi", nil, model.GroupOptions{}, grps, @@ -243,9 +243,9 @@ var _ = Describe("ManifestsRenderer", func() { Group: "things.test.io", Version: "v1alpha1", }, - RenderManifests: true, - AddChartVersion: "1.0.0", - Grandfathered: true, + RenderManifests: true, + AddChartVersion: "1.0.0", + SkipConditionalCRDLoading: true, Resources: []model.Resource{ { Kind: "kind", @@ -267,7 +267,7 @@ var _ = Describe("ManifestsRenderer", func() { // get api-level code gen options from descriptors outFiles, err := render.RenderManifests( - "appName", "manifestDir", "protoDir", + "appName", "manifestDir", "protoDir", "enabledExperimentalApi", nil, model.GroupOptions{}, grps, diff --git a/codegen/templates/manifests/crd.yamltmpl b/codegen/templates/manifests/crd.yamltmpl index 58b02d3d2..4778ee997 100644 --- a/codegen/templates/manifests/crd.yamltmpl +++ b/codegen/templates/manifests/crd.yamltmpl @@ -1,6 +1,6 @@ [[- range $crd := .Crds -]] -[[- if and (and (lt (len $crd.Spec.Versions) 2) (string_contains (index $crd.Spec.Versions 0).Name "alpha")) (should_not_skip $crd.Spec.Group (index $crd.Spec.Versions 0).Name $.ShouldSkip) ]] -{{- if has "[[ $crd.GetName ]]/[[ (index $crd.Spec.Versions 0).Name ]]" $.Values.enabledExperimentalApi }} +[[- if render_conditional_crd_template $crd (index $crd.Spec.Versions 0).Name $.ShouldSkip ]] +{{- if has "[[ $crd.GetName ]]/[[ (index $crd.Spec.Versions 0).Name ]]" $.Values.[[ $.EnabledAlphaApiFlagName ]] }} [[- end ]] apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -14,16 +14,16 @@ spec: scope: [[ $crd.Spec.Scope ]] versions: [[- range $version := $crd.Spec.Versions ]] - [[- if and (and (gt (len $crd.Spec.Versions) 1) (string_contains $version.Name "alpha")) (should_not_skip $crd.Spec.Group $version.Name $.ShouldSkip) ]] - {{- if has "[[ $crd.GetName ]]/[[ $version.Name ]]" $.Values.enabledExperimentalApi }} + [[- if render_conditional_crd_template $crd $version.Name $.ShouldSkip ]] + {{- if has "[[ $crd.GetName ]]/[[ $version.Name ]]" $.Values.[[ $.EnabledAlphaApiFlagName ]] }} [[- end ]] - [[- $version | toYaml | indent 4 | trimPrefix " " ]] - [[- if and (and (gt (len $crd.Spec.Versions) 1) (string_contains $version.Name "alpha")) (should_not_skip $crd.Spec.Group $version.Name $.ShouldSkip) ]] + [[- if render_conditional_crd_template $crd $version.Name $.ShouldSkip ]] {{- end }} [[- end ]] [[- end ]] -[[- if and (and (lt (len $crd.Spec.Versions) 2) (string_contains (index $crd.Spec.Versions 0).Name "alpha")) (should_not_skip $crd.Spec.Group (index $crd.Spec.Versions 0).Name $.ShouldSkip) ]] +[[- if render_conditional_crd_template $crd (index $crd.Spec.Versions 0).Name $.ShouldSkip ]] {{- end }} [[- end ]] --- From 9892a1a6b380d9535cc9d00593c10e580886ee24 Mon Sep 17 00:00:00 2001 From: Dmitri Dolguikh Date: Fri, 28 Jul 2023 20:41:59 -0700 Subject: [PATCH 23/27] Added validation that CRD templates can be rendered Signed-off-by: Dmitri Dolguikh --- codegen/render/manifests_renderer.go | 18 ++- codegen/render/manifests_renderer_test.go | 159 ++++++++++++++++++++++ 2 files changed, 176 insertions(+), 1 deletion(-) diff --git a/codegen/render/manifests_renderer.go b/codegen/render/manifests_renderer.go index 8cb838116..3f05fff9a 100644 --- a/codegen/render/manifests_renderer.go +++ b/codegen/render/manifests_renderer.go @@ -2,6 +2,7 @@ package render import ( "encoding/json" + "fmt" "regexp" "strings" @@ -293,7 +294,11 @@ func (r ManifestsRenderer) renderTemplatedCRDManifest(appName, groupName string, templatesToRender := inputTemplates{ "manifests/crd.yamltmpl": outFile, } - // validate that templates will render ok + + if err := r.canRenderCRDTemplate(objs, grandfatheredGroups); err != nil { + return OutFile{}, err + } + files, err := defaultManifestRenderer.renderCoreTemplates( templatesToRender, templateArgs{Crds: objs, ShouldSkip: grandfatheredGroups, EnabledAlphaApiFlagName: r.EnabledAlphaApiFlagName}) @@ -305,6 +310,17 @@ func (r ManifestsRenderer) renderTemplatedCRDManifest(appName, groupName string, return files[0], nil } +func (r ManifestsRenderer) canRenderCRDTemplate(objs []apiextv1.CustomResourceDefinition, grandfatheredGroups map[string]bool) error { + for _, obj := range objs { + for _, v := range obj.Spec.Versions { + if strings.Contains(v.Name, "alpha") && !grandfatheredGroups[obj.Spec.Group+"/"+v.Name] && r.EnabledAlphaApiFlagName == "" { + return fmt.Errorf("error rendering CRD template for kind %s: 'EnabledAlphaApiFlagName' is not defined", obj.Spec.Names.Kind) + } + } + } + return nil +} + func (r ManifestsRenderer) createCrds(appName string, groups []*Group) ([]apiextv1.CustomResourceDefinition, error) { objs, err := kuberesource.CustomResourceDefinitions(groups) if err != nil { diff --git a/codegen/render/manifests_renderer_test.go b/codegen/render/manifests_renderer_test.go index e3e859d5f..a493438cf 100644 --- a/codegen/render/manifests_renderer_test.go +++ b/codegen/render/manifests_renderer_test.go @@ -1,6 +1,7 @@ package render_test import ( + "fmt" "strings" . "github.com/onsi/ginkgo/v2" @@ -282,4 +283,162 @@ var _ = Describe("ManifestsRenderer", func() { }) }) + Describe("Generate combined alpha, grandfathered alpha, and non-alpha versioned CRD", func() { + var ( + grps []*model.Group + ) + + BeforeEach(func() { + grps = []*model.Group{{ + GroupVersion: schema.GroupVersion{ + Group: "things.test.io", + Version: "v3alpha1", + }, + RenderManifests: true, + AddChartVersion: "1.0.0", + Resources: []model.Resource{ + { + Kind: "kind", + Spec: model.Field{ + Type: model.Type{ + Name: "test", + Message: &v1.AcrylicType{}, + }, + }, + Stored: false, + }, + }}, + { + GroupVersion: schema.GroupVersion{ + Group: "things.test.io", + Version: "v2", + }, + RenderManifests: true, + AddChartVersion: "1.0.0", + Resources: []model.Resource{ + { + Kind: "kind", + Spec: model.Field{ + Type: model.Type{ + Name: "test", + Message: &v1.AcrylicType{}, + }, + }, + Stored: true, + }, + }}, + { + GroupVersion: schema.GroupVersion{ + Group: "things.test.io", + Version: "v1alpha1", + }, + RenderManifests: true, + AddChartVersion: "1.0.0", + SkipConditionalCRDLoading: true, + Resources: []model.Resource{ + { + Kind: "kind", + Spec: model.Field{ + Type: model.Type{ + Name: "test", + Message: &v1.AcrylicType{}, + }, + }, + Stored: true, + }, + }}, + } + for i := range grps { + grps[i].Init() + } + }) + It("Renderse manifests with chart and spec hash", func() { + + // get api-level code gen options from descriptors + outFiles, err := render.RenderManifests( + "appName", "manifestDir", "protoDir", "enabledExperimentalApi", + nil, + model.GroupOptions{}, + grps, + ) + Expect(err).NotTo(HaveOccurred()) + Expect(outFiles).To(HaveLen(2)) // legacy and templated manifests + // only v3alpha1 version of the CRDs is conditionally rendered, v2 and v1alpha1 have no conditions surrounding them + Expect(outFiles[1].Content).To(ContainSubstring("subresources: {}\n {{- if has \"kinds.things.test.io/v3alpha1\" $.Values.enabledExperimentalApi }}")) + Expect(outFiles[1].Content).ToNot(ContainSubstring("{{- if has \"kinds.things.test.io/v1alpha1\" $.Values.enabledExperimentalApi }}\n - name: v2alpha1")) + Expect(outFiles[1].Content).To(ContainSubstring("{{- end }}\n---\n")) + Expect(strings.Count(outFiles[1].Content, "{{- end }}")).To(Equal(1)) + }) + }) + + Describe("Render CRD template when 'EnabledAlphaApiFlagName' isn't set", func() { + It("and resource contains an alpha version that should not be skipped", func() { + grps := []*model.Group{{ + GroupVersion: schema.GroupVersion{ + Group: "things.test.io", + Version: "v3alpha1", + }, + RenderManifests: true, + AddChartVersion: "1.0.0", + Resources: []model.Resource{ + { + Kind: "kind", + Spec: model.Field{ + Type: model.Type{ + Name: "test", + Message: &v1.AcrylicType{}, + }, + }, + Stored: false, + }, + }}, + } + for i := range grps { + grps[i].Init() + } + + _, err := render.RenderManifests( + "appName", "manifestDir", "protoDir", "", + nil, + model.GroupOptions{}, + grps, + ) + Expect(err).ToNot(BeNil()) + Expect(err).To(Equal(fmt.Errorf("error rendering CRD template for kind kind: 'EnabledAlphaApiFlagName' is not defined"))) + }) + It("and resource contains an alpha version that should be skipped", func() { + grps := []*model.Group{{ + GroupVersion: schema.GroupVersion{ + Group: "things.test.io", + Version: "v3alpha1", + }, + RenderManifests: true, + AddChartVersion: "1.0.0", + SkipConditionalCRDLoading: true, + Resources: []model.Resource{ + { + Kind: "kind", + Spec: model.Field{ + Type: model.Type{ + Name: "test", + Message: &v1.AcrylicType{}, + }, + }, + Stored: false, + }, + }}, + } + for i := range grps { + grps[i].Init() + } + + _, err := render.RenderManifests( + "appName", "manifestDir", "protoDir", "", + nil, + model.GroupOptions{}, + grps, + ) + Expect(err).To(BeNil()) + }) + }) }) From 628ec34d7dba46636db509ee117f20a85f964430 Mon Sep 17 00:00:00 2001 From: Dmitri Dolguikh Date: Sat, 29 Jul 2023 18:58:37 -0700 Subject: [PATCH 24/27] Fixed an issue with crd template rendering Signed-off-by: Dmitri Dolguikh --- codegen/render/funcs.go | 10 ++++++---- codegen/render/manifests_renderer_test.go | 5 ++++- codegen/templates/manifests/crd.yamltmpl | 8 ++++---- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/codegen/render/funcs.go b/codegen/render/funcs.go index c27130f43..3a9135116 100644 --- a/codegen/render/funcs.go +++ b/codegen/render/funcs.go @@ -133,10 +133,12 @@ func makeTemplateFuncs(customFuncs template.FuncMap) template.FuncMap { "opVar": opVar, - "render_conditional_crd_template": func(crd apiextv1.CustomResourceDefinition, currentVersion string, skips map[string]bool) bool { - wrapWholeCrd := len(crd.Spec.Versions) < 2 && strings.Contains(currentVersion, "alpha") && !skips[crd.Spec.Group+"/"+currentVersion] - wrapSingleVersion := len(crd.Spec.Versions) > 1 && strings.Contains(currentVersion, "alpha") && !skips[crd.Spec.Group+"/"+currentVersion] - return wrapWholeCrd || wrapSingleVersion + "render_outer_conditional_crd_template": func(crd apiextv1.CustomResourceDefinition, currentVersion string, skips map[string]bool) bool { + return len(crd.Spec.Versions) < 2 && strings.Contains(currentVersion, "alpha") && !skips[crd.Spec.Group+"/"+currentVersion] + }, + + "render_inner_conditional_crd_template": func(crd apiextv1.CustomResourceDefinition, currentVersion string, skips map[string]bool) bool { + return len(crd.Spec.Versions) > 1 && strings.Contains(currentVersion, "alpha") && !skips[crd.Spec.Group+"/"+currentVersion] }, } diff --git a/codegen/render/manifests_renderer_test.go b/codegen/render/manifests_renderer_test.go index a493438cf..ae9ef1d3b 100644 --- a/codegen/render/manifests_renderer_test.go +++ b/codegen/render/manifests_renderer_test.go @@ -364,9 +364,12 @@ var _ = Describe("ManifestsRenderer", func() { Expect(err).NotTo(HaveOccurred()) Expect(outFiles).To(HaveLen(2)) // legacy and templated manifests // only v3alpha1 version of the CRDs is conditionally rendered, v2 and v1alpha1 have no conditions surrounding them - Expect(outFiles[1].Content).To(ContainSubstring("subresources: {}\n {{- if has \"kinds.things.test.io/v3alpha1\" $.Values.enabledExperimentalApi }}")) + expectedTemplateString := "subresources: {}\n {{- if has \"kinds.things.test.io/v3alpha1\" $.Values.enabledExperimentalApi }}" + Expect(outFiles[1].Content).To(ContainSubstring(expectedTemplateString)) + Expect(strings.Count(outFiles[1].Content, expectedTemplateString)).To(Equal(1)) Expect(outFiles[1].Content).ToNot(ContainSubstring("{{- if has \"kinds.things.test.io/v1alpha1\" $.Values.enabledExperimentalApi }}\n - name: v2alpha1")) Expect(outFiles[1].Content).To(ContainSubstring("{{- end }}\n---\n")) + Expect(strings.Count(outFiles[1].Content, "{{- end }}\n---\n")).To(Equal(1)) Expect(strings.Count(outFiles[1].Content, "{{- end }}")).To(Equal(1)) }) }) diff --git a/codegen/templates/manifests/crd.yamltmpl b/codegen/templates/manifests/crd.yamltmpl index 4778ee997..db66b723f 100644 --- a/codegen/templates/manifests/crd.yamltmpl +++ b/codegen/templates/manifests/crd.yamltmpl @@ -1,5 +1,5 @@ [[- range $crd := .Crds -]] -[[- if render_conditional_crd_template $crd (index $crd.Spec.Versions 0).Name $.ShouldSkip ]] +[[- if render_outer_conditional_crd_template $crd (index $crd.Spec.Versions 0).Name $.ShouldSkip ]] {{- if has "[[ $crd.GetName ]]/[[ (index $crd.Spec.Versions 0).Name ]]" $.Values.[[ $.EnabledAlphaApiFlagName ]] }} [[- end ]] apiVersion: apiextensions.k8s.io/v1 @@ -14,16 +14,16 @@ spec: scope: [[ $crd.Spec.Scope ]] versions: [[- range $version := $crd.Spec.Versions ]] - [[- if render_conditional_crd_template $crd $version.Name $.ShouldSkip ]] + [[- if render_inner_conditional_crd_template $crd $version.Name $.ShouldSkip ]] {{- if has "[[ $crd.GetName ]]/[[ $version.Name ]]" $.Values.[[ $.EnabledAlphaApiFlagName ]] }} [[- end ]] - [[- $version | toYaml | indent 4 | trimPrefix " " ]] - [[- if render_conditional_crd_template $crd $version.Name $.ShouldSkip ]] + [[- if render_inner_conditional_crd_template $crd $version.Name $.ShouldSkip ]] {{- end }} [[- end ]] [[- end ]] -[[- if render_conditional_crd_template $crd (index $crd.Spec.Versions 0).Name $.ShouldSkip ]] +[[- if render_outer_conditional_crd_template $crd (index $crd.Spec.Versions 0).Name $.ShouldSkip ]] {{- end }} [[- end ]] --- From 32b91d0d3e170c33a28661c9daa71004125f109a Mon Sep 17 00:00:00 2001 From: changelog-bot Date: Mon, 31 Jul 2023 18:33:17 +0000 Subject: [PATCH 25/27] Adding changelog file to new location --- changelog/v0.33.0/conditional_crd_rendering.yaml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 changelog/v0.33.0/conditional_crd_rendering.yaml diff --git a/changelog/v0.33.0/conditional_crd_rendering.yaml b/changelog/v0.33.0/conditional_crd_rendering.yaml new file mode 100644 index 000000000..0ad14deed --- /dev/null +++ b/changelog/v0.33.0/conditional_crd_rendering.yaml @@ -0,0 +1,5 @@ +changelog: + - type: BREAKING_CHANGE + issueLink: https://github.com/solo-io/gloo-mesh-enterprise/issues/9019 + description: > + Add support for conditional rendering of CRDs. From 9bc78c70b18f9169ae74540f184abf9b8aab11e2 Mon Sep 17 00:00:00 2001 From: changelog-bot Date: Mon, 31 Jul 2023 18:33:18 +0000 Subject: [PATCH 26/27] Deleting changelog file from old location --- changelog/v0.32.0/conditional_crd_rendering.yaml | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 changelog/v0.32.0/conditional_crd_rendering.yaml diff --git a/changelog/v0.32.0/conditional_crd_rendering.yaml b/changelog/v0.32.0/conditional_crd_rendering.yaml deleted file mode 100644 index 0ad14deed..000000000 --- a/changelog/v0.32.0/conditional_crd_rendering.yaml +++ /dev/null @@ -1,5 +0,0 @@ -changelog: - - type: BREAKING_CHANGE - issueLink: https://github.com/solo-io/gloo-mesh-enterprise/issues/9019 - description: > - Add support for conditional rendering of CRDs. From c5ad04be43eb83ff988e403b3c555aa05f25b642 Mon Sep 17 00:00:00 2001 From: Dmitri Dolguikh Date: Mon, 31 Jul 2023 13:39:39 -0700 Subject: [PATCH 27/27] Updated version to v0.33.0 Signed-off-by: Dmitri Dolguikh --- changelog/{v0.32.0 => v0.33.0}/conditional_crd_rendering.yaml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename changelog/{v0.32.0 => v0.33.0}/conditional_crd_rendering.yaml (100%) diff --git a/changelog/v0.32.0/conditional_crd_rendering.yaml b/changelog/v0.33.0/conditional_crd_rendering.yaml similarity index 100% rename from changelog/v0.32.0/conditional_crd_rendering.yaml rename to changelog/v0.33.0/conditional_crd_rendering.yaml