diff --git a/changelog/fragments/fix-csv-role-names.yaml b/changelog/fragments/fix-csv-role-names.yaml new file mode 100644 index 00000000000..7f03f2874de --- /dev/null +++ b/changelog/fragments/fix-csv-role-names.yaml @@ -0,0 +1,19 @@ +entries: + - description: > + `generate ` will write RBAC objects (Roles, RoleBindings, their Cluster equivalents, + and ServiceAccounts) not bound to CSV deployment service accounts + to the resulting manifests directory. + kind: addition + - description: > + The `--update-crds` flag has been renamed to `--update-objects` for the `generate packagemanifests` subcommand. + kind: change + breaking: true + migration: + header: Rename `--update-crds` flag to `--update-objects` in `generate packagemanifests` invocations + body: > + This flag has been renamed to account for all objects that can be written to the package directory, + ex. Roles. + - description: > + Fixed incorrect (cluster) role name assignments in generated CSVs + [#3600](https://github.com/operator-framework/operator-sdk/issues/3600). + kind: bugfix diff --git a/internal/cmd/operator-sdk/generate/bundle/bundle.go b/internal/cmd/operator-sdk/generate/bundle/bundle.go index 488cce7d031..a0326cee391 100644 --- a/internal/cmd/operator-sdk/generate/bundle/bundle.go +++ b/internal/cmd/operator-sdk/generate/bundle/bundle.go @@ -197,13 +197,7 @@ func (c bundleCmd) runManifests(cfg *config.Config) (err error) { return fmt.Errorf("error generating ClusterServiceVersion: %v", err) } - var objs []interface{} - for _, crd := range col.V1CustomResourceDefinitions { - objs = append(objs, crd) - } - for _, crd := range col.V1beta1CustomResourceDefinitions { - objs = append(objs, crd) - } + objs := genutil.GetManifestObjects(col) if c.stdout { if err := genutil.WriteObjects(stdout, objs...); err != nil { return err diff --git a/internal/cmd/operator-sdk/generate/internal/genutil.go b/internal/cmd/operator-sdk/generate/internal/genutil.go index 8e5554f64ab..3a6dfcf9dd5 100644 --- a/internal/cmd/operator-sdk/generate/internal/genutil.go +++ b/internal/cmd/operator-sdk/generate/internal/genutil.go @@ -23,11 +23,11 @@ import ( "path/filepath" "strings" - "k8s.io/apimachinery/pkg/util/validation" - "github.com/blang/semver" apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + "k8s.io/apimachinery/pkg/util/validation" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/kubebuilder/pkg/model/config" "sigs.k8s.io/yaml" ) @@ -57,7 +57,7 @@ func IsPipeReader() bool { } // WriteObjects writes each object in objs to w. -func WriteObjects(w io.Writer, objs ...interface{}) error { +func WriteObjects(w io.Writer, objs ...controllerutil.Object) error { for _, obj := range objs { if err := writeObject(w, obj); err != nil { return err @@ -67,7 +67,7 @@ func WriteObjects(w io.Writer, objs ...interface{}) error { } // WriteObjectsToFiles creates dir then writes each object in objs to a file in dir. -func WriteObjectsToFiles(dir string, objs ...interface{}) error { +func WriteObjectsToFiles(dir string, objs ...controllerutil.Object) error { if err := os.MkdirAll(dir, 0755); err != nil { return err } @@ -76,12 +76,12 @@ func WriteObjectsToFiles(dir string, objs ...interface{}) error { for _, obj := range objs { var fileName string switch t := obj.(type) { - case apiextv1.CustomResourceDefinition: + case *apiextv1.CustomResourceDefinition: fileName = makeCRDFileName(t.Spec.Group, t.Spec.Names.Plural) - case apiextv1beta1.CustomResourceDefinition: + case *apiextv1beta1.CustomResourceDefinition: fileName = makeCRDFileName(t.Spec.Group, t.Spec.Names.Plural) default: - return fmt.Errorf("unknown object type: %T", t) + fileName = makeObjectFileName(t) } if _, hasFile := seenFiles[fileName]; hasFile { @@ -99,6 +99,14 @@ func makeCRDFileName(group, resource string) string { return fmt.Sprintf("%s_%s.yaml", group, resource) } +func makeObjectFileName(obj controllerutil.Object) string { + gvk := obj.GetObjectKind().GroupVersionKind() + if gvk.Group == "" { + return fmt.Sprintf("%s_%s_%s.yaml", obj.GetName(), gvk.Version, strings.ToLower(gvk.Kind)) + } + return fmt.Sprintf("%s_%s_%s_%s.yaml", obj.GetName(), gvk.Group, gvk.Version, strings.ToLower(gvk.Kind)) +} + // writeObjectToFile marshals crd to bytes and writes them to dir in file. func writeObjectToFile(dir string, obj interface{}, fileName string) error { f, err := os.Create(filepath.Join(dir, fileName)) diff --git a/internal/cmd/operator-sdk/generate/internal/manifests.go b/internal/cmd/operator-sdk/generate/internal/manifests.go new file mode 100644 index 00000000000..8a875506cc9 --- /dev/null +++ b/internal/cmd/operator-sdk/generate/internal/manifests.go @@ -0,0 +1,45 @@ +// Copyright 2020 The Operator-SDK Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package genutil + +import ( + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + + "github.com/operator-framework/operator-sdk/internal/generate/collector" +) + +// GetManifestObjects returns all objects to be written to a manifests directory from collector.Manifests. +func GetManifestObjects(c *collector.Manifests) (objs []controllerutil.Object) { + // All CRDs passed in should be written. + for i := range c.V1CustomResourceDefinitions { + objs = append(objs, &c.V1CustomResourceDefinitions[i]) + } + for i := range c.V1beta1CustomResourceDefinitions { + objs = append(objs, &c.V1beta1CustomResourceDefinitions[i]) + } + + // All ServiceAccounts passed in should be written. + for i := range c.ServiceAccounts { + objs = append(objs, &c.ServiceAccounts[i]) + } + + // RBAC objects that are not a part of the CSV should be written. + _, roleObjs := c.SplitCSVPermissionsObjects() + objs = append(objs, roleObjs...) + _, clusterRoleObjs := c.SplitCSVClusterPermissionsObjects() + objs = append(objs, clusterRoleObjs...) + + return objs +} diff --git a/internal/cmd/operator-sdk/generate/packagemanifests/cmd.go b/internal/cmd/operator-sdk/generate/packagemanifests/cmd.go index 515991e7bd3..fc5d7e0ff8b 100644 --- a/internal/cmd/operator-sdk/generate/packagemanifests/cmd.go +++ b/internal/cmd/operator-sdk/generate/packagemanifests/cmd.go @@ -28,17 +28,17 @@ import ( //nolint:maligned type packagemanifestsCmd struct { // Common options. - projectName string - version string - fromVersion string - inputDir string - outputDir string - kustomizeDir string - deployDir string - crdsDir string - updateCRDs bool - stdout bool - quiet bool + projectName string + version string + fromVersion string + inputDir string + outputDir string + kustomizeDir string + deployDir string + crdsDir string + updateObjects bool + stdout bool + quiet bool // Package manifest options. channelName string @@ -97,7 +97,8 @@ func (c *packagemanifestsCmd) addFlagsTo(fs *pflag.FlagSet) { fs.StringVar(&c.channelName, "channel", "", "Channel name for the generated package") fs.BoolVar(&c.isDefaultChannel, "default-channel", false, "Use the channel passed to --channel "+ "as the package manifest file's default channel") - fs.BoolVar(&c.updateCRDs, "update-crds", true, "Update CustomResoureDefinition manifests in this package") + fs.BoolVar(&c.updateObjects, "update-objects", true, "Update non-CSV objects in this package, "+ + "ex. CustomResoureDefinitions, Roles") fs.BoolVarP(&c.quiet, "quiet", "q", false, "Run in quiet mode") fs.BoolVar(&c.stdout, "stdout", false, "Write package to stdout") } diff --git a/internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests.go b/internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests.go index 523baf65ce6..365355867dc 100644 --- a/internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests.go +++ b/internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests.go @@ -188,14 +188,8 @@ func (c packagemanifestsCmd) run(cfg *config.Config) error { return fmt.Errorf("error generating ClusterServiceVersion: %v", err) } - if c.updateCRDs { - var objs []interface{} - for _, crd := range col.V1CustomResourceDefinitions { - objs = append(objs, crd) - } - for _, crd := range col.V1beta1CustomResourceDefinitions { - objs = append(objs, crd) - } + if c.updateObjects { + objs := genutil.GetManifestObjects(col) if c.stdout { if err := genutil.WriteObjects(stdout, objs...); err != nil { return err diff --git a/internal/generate/clusterserviceversion/clusterserviceversion_test.go b/internal/generate/clusterserviceversion/clusterserviceversion_test.go index 5f7744d19f0..f9d47a52761 100644 --- a/internal/generate/clusterserviceversion/clusterserviceversion_test.go +++ b/internal/generate/clusterserviceversion/clusterserviceversion_test.go @@ -16,7 +16,6 @@ package clusterserviceversion import ( "bytes" - "encoding/json" "fmt" "io/ioutil" "os" @@ -31,7 +30,6 @@ import ( "github.com/operator-framework/api/pkg/operators/v1alpha1" "github.com/operator-framework/operator-registry/pkg/lib/bundle" appsv1 "k8s.io/api/apps/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "sigs.k8s.io/kubebuilder/pkg/model/config" "sigs.k8s.io/yaml" @@ -45,16 +43,12 @@ var ( testDataDir = filepath.Join("..", "testdata") csvDir = filepath.Join(testDataDir, "clusterserviceversions") csvBasesDir = filepath.Join(csvDir, "bases") - csvNewLayoutBundleDir = filepath.Join(csvDir, "newlayout", "manifests") - - // TODO: create a new testdata dir (top level?) that has both a "config" - // dir and a "deploy" dir that contains `kustomize build config/default` - // output to simulate actual manifest collection behavior. Using "config" - // directly is not standard behavior. - goTestDataDir = filepath.Join(testDataDir, "non-standard-layout") - goAPIsDir = filepath.Join(goTestDataDir, "api") - goConfigDir = filepath.Join(goTestDataDir, "config") - goCRDsDir = filepath.Join(goConfigDir, "crds") + csvNewLayoutBundleDir = filepath.Join(csvDir, "output") + + goTestDataDir = filepath.Join(testDataDir, "go") + goAPIsDir = filepath.Join(goTestDataDir, "api") + goStaticDir = filepath.Join(goTestDataDir, "static") + goBasicOperatorPath = filepath.Join(goStaticDir, "basic.operator.yaml") ) var ( @@ -74,7 +68,7 @@ var ( var _ = BeforeSuite(func() { col = &collector.Manifests{} - Expect(col.UpdateFromDirs(goConfigDir, goCRDsDir)).ToNot(HaveOccurred()) + collectManifestsFromFileHelper(col, goBasicOperatorPath) cfg = readConfigHelper(goTestDataDir) @@ -97,7 +91,7 @@ var _ = Describe("Generating a ClusterServiceVersion", func() { buf = &bytes.Buffer{} }) - Describe("for the new Go project layout", func() { + Describe("for a Go project", func() { Context("with correct Options", func() { @@ -281,7 +275,7 @@ var _ = Describe("Generating a ClusterServiceVersion", func() { getBase: makeBaseGetter(newCSV), } // Update the input's and expected CSV's Deployment image. - Expect(g.Collector.UpdateFromDirs(goConfigDir, goCRDsDir)).ToNot(HaveOccurred()) + collectManifestsFromFileHelper(g.Collector, goBasicOperatorPath) Expect(len(g.Collector.Deployments)).To(BeNumerically(">=", 1)) imageTag := "controller:v" + g.Version modifyDepImageHelper(&g.Collector.Deployments[0].Spec, imageTag) @@ -311,42 +305,6 @@ var _ = Describe("Generating a ClusterServiceVersion", func() { Expect(csv).To(Equal(upgradeCSV(newCSV, g.OperatorName, g.Version))) }) }) - - Context("generate ClusterServiceVersion", func() { - It("should handle CRDs with core type name", func() { - g = Generator{ - OperatorName: operatorName, - OperatorType: operatorType, - Version: version, - Collector: &collector.Manifests{}, - config: cfg, - getBase: makeBaseGetter(newCSV), - } - err := filepath.Walk(goConfigDir, func(path string, info os.FileInfo, err error) error { - if err != nil || info.IsDir() { - return err - } - file, err := os.OpenFile(path, os.O_RDONLY, 0) - if err != nil { - return err - } - defer file.Close() - return g.Collector.UpdateFromReader(file) - }) - Expect(err).ShouldNot(HaveOccurred(), "failed to read manifests") - Expect(len(g.Collector.V1beta1CustomResourceDefinitions)).Should(BeEquivalentTo(2)) - Expect(len(g.Collector.CustomResources)).Should(BeEquivalentTo(2)) - - csv, err := g.generate() - Expect(err).ToNot(HaveOccurred()) - Expect(csv.Annotations["alm-examples"]).ShouldNot(BeEquivalentTo("[]")) - - crs := []unstructured.Unstructured{} - err = json.Unmarshal([]byte(csv.Annotations["alm-examples"]), &crs) - Expect(err).ShouldNot(HaveOccurred(), "failed to parse 'alm-examples' annotations") - Expect(crs).Should(ConsistOf(g.Collector.CustomResources), "custom resources shall match with CSV annotations") - }) - }) }) }) @@ -388,6 +346,13 @@ var _ = Describe("Generation requires interaction", func() { }) }) +func collectManifestsFromFileHelper(col *collector.Manifests, path string) { + f, err := os.Open(path) + ExpectWithOffset(1, err).ToNot(HaveOccurred()) + ExpectWithOffset(1, col.UpdateFromReader(f)).ToNot(HaveOccurred()) + ExpectWithOffset(1, f.Close()).Should(Succeed()) +} + func readConfigHelper(dir string) *config.Config { wd, err := os.Getwd() ExpectWithOffset(1, err).ToNot(HaveOccurred()) diff --git a/internal/generate/clusterserviceversion/clusterserviceversion_updaters.go b/internal/generate/clusterserviceversion/clusterserviceversion_updaters.go index 73bd0a65beb..c9dcfaf5c4c 100644 --- a/internal/generate/clusterserviceversion/clusterserviceversion_updaters.go +++ b/internal/generate/clusterserviceversion/clusterserviceversion_updaters.go @@ -28,6 +28,7 @@ import ( admissionregv1 "k8s.io/api/admissionregistration/v1" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/version" "github.com/operator-framework/operator-sdk/internal/generate/collector" @@ -39,11 +40,10 @@ import ( func ApplyTo(c *collector.Manifests, csv *operatorsv1alpha1.ClusterServiceVersion) error { // Apply manifests to the CSV object. if err := apply(c, csv); err != nil { - return fmt.Errorf("error updating ClusterServiceVersion: %v", err) + return err } - // Set fields required by namespaced operators. This is a no-op for cluster- - // scoped operators. + // Set fields required by namespaced operators. This is a no-op for cluster-scoped operators. setNamespacedFields(csv) // Sort all updated fields. @@ -65,7 +65,7 @@ func apply(c *collector.Manifests, csv *operatorsv1alpha1.ClusterServiceVersion) applyCustomResourceDefinitions(c, csv) if err := applyCustomResources(c, csv); err != nil { - return fmt.Errorf("error applying Custom Resource: %v", err) + return fmt.Errorf("error applying Custom Resource examples to CSV %s: %v", csv.GetName(), err) } applyWebhooks(c, csv) return nil @@ -80,27 +80,89 @@ func getCSVInstallStrategy(csv *operatorsv1alpha1.ClusterServiceVersion) operato return csv.Spec.InstallStrategy } -// applyRoles updates strategy's permissions with the Roles in the collector. -func applyRoles(c *collector.Manifests, strategy *operatorsv1alpha1.StrategyDetailsDeployment) { +// This service account exists in every namespace as the default. +const defaultServiceAccountName = "default" + +// applyRoles applies Roles to strategy's permissions field by combining Roles bound to ServiceAccounts +// into one set of permissions. +func applyRoles(c *collector.Manifests, strategy *operatorsv1alpha1.StrategyDetailsDeployment) { //nolint:dupl + objs, _ := c.SplitCSVPermissionsObjects() + roleSet := make(map[string]*rbacv1.Role) + for i := range objs { + switch t := objs[i].(type) { + case *rbacv1.Role: + roleSet[t.GetName()] = t + } + } + + saToPermissions := make(map[string]operatorsv1alpha1.StrategyDeploymentPermissions) + for _, dep := range c.Deployments { + saName := dep.Spec.Template.Spec.ServiceAccountName + if saName == "" { + saName = defaultServiceAccountName + } + saToPermissions[saName] = operatorsv1alpha1.StrategyDeploymentPermissions{ServiceAccountName: saName} + } + + // Collect all role names by their corresponding service accounts via bindings. This lets us + // look up all service accounts a role is bound to and create one set of permissions per service account. + for _, binding := range c.RoleBindings { + if role, hasRole := roleSet[binding.RoleRef.Name]; hasRole { + for _, subject := range binding.Subjects { + if perm, hasSA := saToPermissions[subject.Name]; hasSA && subject.Kind == "ServiceAccount" { + perm.Rules = append(perm.Rules, role.Rules...) + saToPermissions[subject.Name] = perm + } + } + } + } + + // Apply relevant roles to each service account. perms := []operatorsv1alpha1.StrategyDeploymentPermissions{} - for _, role := range c.Roles { - perms = append(perms, operatorsv1alpha1.StrategyDeploymentPermissions{ - ServiceAccountName: role.GetName(), - Rules: role.Rules, - }) + for _, perm := range saToPermissions { + perms = append(perms, perm) } strategy.Permissions = perms } -// applyClusterRoles updates strategy's cluserPermissions with the ClusterRoles -// in the collector. -func applyClusterRoles(c *collector.Manifests, strategy *operatorsv1alpha1.StrategyDetailsDeployment) { +// applyClusterRoles applies ClusterRoles to strategy's clusterPermissions field by combining ClusterRoles +// bound to ServiceAccounts into one set of clusterPermissions. +func applyClusterRoles(c *collector.Manifests, strategy *operatorsv1alpha1.StrategyDetailsDeployment) { //nolint:dupl + objs, _ := c.SplitCSVClusterPermissionsObjects() + roleSet := make(map[string]*rbacv1.ClusterRole) + for i := range objs { + switch t := objs[i].(type) { + case *rbacv1.ClusterRole: + roleSet[t.GetName()] = t + } + } + + saToPermissions := make(map[string]operatorsv1alpha1.StrategyDeploymentPermissions) + for _, dep := range c.Deployments { + saName := dep.Spec.Template.Spec.ServiceAccountName + if saName == "" { + saName = defaultServiceAccountName + } + saToPermissions[saName] = operatorsv1alpha1.StrategyDeploymentPermissions{ServiceAccountName: saName} + } + + // Collect all role names by their corresponding service accounts via bindings. This lets us + // look up all service accounts a role is bound to and create one set of permissions per service account. + for _, binding := range c.ClusterRoleBindings { + if role, hasRole := roleSet[binding.RoleRef.Name]; hasRole { + for _, subject := range binding.Subjects { + if perm, hasSA := saToPermissions[subject.Name]; hasSA && subject.Kind == "ServiceAccount" { + perm.Rules = append(perm.Rules, role.Rules...) + saToPermissions[subject.Name] = perm + } + } + } + } + + // Apply relevant roles to each service account. perms := []operatorsv1alpha1.StrategyDeploymentPermissions{} - for _, role := range c.ClusterRoles { - perms = append(perms, operatorsv1alpha1.StrategyDeploymentPermissions{ - ServiceAccountName: role.GetName(), - Rules: role.Rules, - }) + for _, perm := range saToPermissions { + perms = append(perms, perm) } strategy.ClusterPermissions = perms } diff --git a/internal/generate/collector/clusterserviceversion.go b/internal/generate/collector/clusterserviceversion.go new file mode 100644 index 00000000000..f8bdd67365a --- /dev/null +++ b/internal/generate/collector/clusterserviceversion.go @@ -0,0 +1,222 @@ +// Copyright 2020 The Operator-SDK Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package collector + +import ( + rbacv1 "k8s.io/api/rbac/v1" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" +) + +// TODO(estroz): there's a significant amount of code dupliation here, a byproduct of Go's type system. +// However at least a few bits can be refactored so each method is smaller. + +const ( + // This service account exists in every namespace as the default. + defaultServiceAccountName = "default" + + serviceAccountKind = "ServiceAccount" +) + +// SplitCSVPermissionsObjects splits roles that should be written to a CSV as permissions (in) +// from roles and role bindings that should be written directly to the bundle (out). +func (c *Manifests) SplitCSVPermissionsObjects() (in, out []controllerutil.Object) { //nolint:dupl + roleMap := make(map[string]*rbacv1.Role) + for i := range c.Roles { + roleMap[c.Roles[i].GetName()] = &c.Roles[i] + } + roleBindingMap := make(map[string]*rbacv1.RoleBinding) + for i := range c.RoleBindings { + roleBindingMap[c.RoleBindings[i].GetName()] = &c.RoleBindings[i] + } + + // Check for unbound roles. + for roleName, role := range roleMap { + hasRef := false + for _, roleBinding := range roleBindingMap { + roleRef := roleBinding.RoleRef + if roleRef.Kind == "Role" && (roleRef.APIGroup == "" || roleRef.APIGroup == rbacv1.SchemeGroupVersion.Group) { + if roleRef.Name == roleName { + hasRef = true + break + } + } + } + if !hasRef { + out = append(out, role) + delete(roleMap, roleName) + } + } + + // If a role is bound and: + // 1. the binding only has one subject and it is a service account that maps to a deployment service account, + // add the role to in. + // 2. the binding only has one subject and it does not map to a deployment service account or is not a service account, + // add both role and binding to out. + // 3. the binding has more than one subject and: + // a. one of those subjects is a deployment's service account, add both role and binding to out and role to in. + // b. none of those subjects is a service account or maps to a deployment's service account, add both role and binding to out. + deploymentSANames := make(map[string]struct{}) + for _, dep := range c.Deployments { + saName := dep.Spec.Template.Spec.ServiceAccountName + if saName == "" { + saName = defaultServiceAccountName + } + deploymentSANames[saName] = struct{}{} + } + + inRoleNames := make(map[string]struct{}) + outRoleNames := make(map[string]struct{}) + outRoleBindingNames := make(map[string]struct{}) + for _, binding := range c.RoleBindings { + roleRef := binding.RoleRef + if roleRef.Kind == "Role" && (roleRef.APIGroup == "" || roleRef.APIGroup == rbacv1.SchemeGroupVersion.Group) { + numSubjects := len(binding.Subjects) + if numSubjects == 1 { + // cases (1) and (2). + if _, hasSA := deploymentSANames[binding.Subjects[0].Name]; hasSA && binding.Subjects[0].Kind == serviceAccountKind { + inRoleNames[roleRef.Name] = struct{}{} + } else { + outRoleNames[roleRef.Name] = struct{}{} + outRoleBindingNames[binding.GetName()] = struct{}{} + } + } else { + // case (3). + for _, subject := range binding.Subjects { + if _, hasSA := deploymentSANames[subject.Name]; hasSA && subject.Kind == serviceAccountKind { + // case (3a). + inRoleNames[roleRef.Name] = struct{}{} + } + } + // case (3b). + outRoleNames[roleRef.Name] = struct{}{} + outRoleBindingNames[binding.GetName()] = struct{}{} + } + } + } + + for roleName := range inRoleNames { + if role, hasRoleName := roleMap[roleName]; hasRoleName { + in = append(in, role) + } + } + for roleName := range outRoleNames { + if role, hasRoleName := roleMap[roleName]; hasRoleName { + out = append(out, role) + } + } + for roleBindingName := range outRoleBindingNames { + if roleBinding, hasRoleBindingName := roleBindingMap[roleBindingName]; hasRoleBindingName { + out = append(out, roleBinding) + } + } + + return in, out +} + +// SplitCSVClusterPermissionsObjects splits cluster roles that should be written to a CSV as clusterPermissions (in) +// from cluster roles and cluster role bindings that should be written directly to the bundle (out). +func (c *Manifests) SplitCSVClusterPermissionsObjects() (in, out []controllerutil.Object) { //nolint:dupl + roleMap := make(map[string]*rbacv1.ClusterRole) + for i := range c.ClusterRoles { + roleMap[c.ClusterRoles[i].GetName()] = &c.ClusterRoles[i] + } + roleBindingMap := make(map[string]*rbacv1.ClusterRoleBinding) + for i := range c.ClusterRoleBindings { + roleBindingMap[c.ClusterRoleBindings[i].GetName()] = &c.ClusterRoleBindings[i] + } + + // Check for unbound roles. + for roleName, role := range roleMap { + hasRef := false + for _, roleBinding := range roleBindingMap { + roleRef := roleBinding.RoleRef + if roleRef.Kind == "ClusterRole" && (roleRef.APIGroup == "" || roleRef.APIGroup == rbacv1.SchemeGroupVersion.Group) { + if roleRef.Name == roleName { + hasRef = true + break + } + } + } + if !hasRef { + out = append(out, role) + delete(roleMap, roleName) + } + } + + // If a role is bound and: + // 1. the binding only has one subject and it is a service account that maps to a deployment service account, + // add the role to in. + // 2. the binding only has one subject and it does not map to a deployment service account or is not a service account, + // add both role and binding to out. + // 3. the binding has more than one subject and: + // a. one of those subjects is a deployment's service account, add both role and binding to out and role to in. + // b. none of those subjects is a service account or maps to a deployment's service account, add both role and binding to out. + deploymentSANames := make(map[string]struct{}) + for _, dep := range c.Deployments { + saName := dep.Spec.Template.Spec.ServiceAccountName + if saName == "" { + saName = defaultServiceAccountName + } + deploymentSANames[saName] = struct{}{} + } + + inRoleNames := make(map[string]struct{}) + outRoleNames := make(map[string]struct{}) + outRoleBindingNames := make(map[string]struct{}) + for _, binding := range c.ClusterRoleBindings { + roleRef := binding.RoleRef + if roleRef.Kind == "ClusterRole" && (roleRef.APIGroup == "" || roleRef.APIGroup == rbacv1.SchemeGroupVersion.Group) { + numSubjects := len(binding.Subjects) + if numSubjects == 1 { + // cases (1) and (2). + if _, hasSA := deploymentSANames[binding.Subjects[0].Name]; hasSA && binding.Subjects[0].Kind == serviceAccountKind { + inRoleNames[roleRef.Name] = struct{}{} + } else { + outRoleNames[roleRef.Name] = struct{}{} + outRoleBindingNames[binding.GetName()] = struct{}{} + } + } else { + // case (3). + for _, subject := range binding.Subjects { + if _, hasSA := deploymentSANames[subject.Name]; hasSA && subject.Kind == serviceAccountKind { + // case (3a). + inRoleNames[roleRef.Name] = struct{}{} + } + } + // case (3b). + outRoleNames[roleRef.Name] = struct{}{} + outRoleBindingNames[binding.GetName()] = struct{}{} + } + } + } + + for roleName := range inRoleNames { + if role, hasRoleName := roleMap[roleName]; hasRoleName { + in = append(in, role) + } + } + for roleName := range outRoleNames { + if role, hasRoleName := roleMap[roleName]; hasRoleName { + out = append(out, role) + } + } + for roleBindingName := range outRoleBindingNames { + if roleBinding, hasRoleBindingName := roleBindingMap[roleBindingName]; hasRoleBindingName { + out = append(out, roleBinding) + } + } + + return in, out +} diff --git a/internal/generate/collector/clusterserviceversion_test.go b/internal/generate/collector/clusterserviceversion_test.go new file mode 100644 index 00000000000..01fde88ecc7 --- /dev/null +++ b/internal/generate/collector/clusterserviceversion_test.go @@ -0,0 +1,328 @@ +// Copyright 2020 The Operator-SDK Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//nolint:dupl +package collector + +import ( + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + appsv1 "k8s.io/api/apps/v1" + rbacv1 "k8s.io/api/rbac/v1" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" +) + +var _ = Describe("ClusterServiceVersion", func() { + var ( + c *Manifests + in, out []controllerutil.Object + ) + + BeforeEach(func() { + c = &Manifests{} + }) + + Describe("SplitCSVPermissionsObjects", func() { + + It("should return empty lists for an empty Manifests", func() { + c.Roles = []rbacv1.Role{} + in, out = c.SplitCSVPermissionsObjects() + Expect(in).To(HaveLen(0)) + Expect(out).To(HaveLen(0)) + }) + It("should return non-empty lists", func() { + By("splitting 1 Role no RoleBinding") + c.Roles = []rbacv1.Role{newRole("my-role")} + in, out = c.SplitCSVPermissionsObjects() + Expect(in).To(HaveLen(0)) + Expect(out).To(HaveLen(1)) + Expect(getRoleNames(out)).To(ContainElement("my-role")) + + By("splitting 1 Role 1 RoleBinding with 1 Subject not containing Deployment serviceAccountName") + c.Deployments = []appsv1.Deployment{newDeploymentWithServiceAccount("my-dep-account")} + c.Roles = []rbacv1.Role{newRole("my-role")} + c.RoleBindings = []rbacv1.RoleBinding{ + newRoleBinding("my-role-binding", newRoleRef("my-role"), newServiceAccountSubject("my-other-account")), + } + in, out = c.SplitCSVPermissionsObjects() + Expect(in).To(HaveLen(0)) + Expect(out).To(HaveLen(2)) + Expect(getRoleNames(out)).To(ContainElement("my-role")) + Expect(getRoleBindingNames(out)).To(ContainElement("my-role-binding")) + + By("splitting 1 Role 1 RoleBinding with 1 Subject containing Deployment serviceAccountName") + c.Deployments = []appsv1.Deployment{newDeploymentWithServiceAccount("my-dep-account")} + c.Roles = []rbacv1.Role{newRole("my-role")} + c.RoleBindings = []rbacv1.RoleBinding{ + newRoleBinding("my-role-binding", newRoleRef("my-role"), newServiceAccountSubject("my-dep-account")), + } + in, out = c.SplitCSVPermissionsObjects() + Expect(in).To(HaveLen(1)) + Expect(getRoleNames(in)).To(ContainElement("my-role")) + Expect(out).To(HaveLen(0)) + + By("splitting 1 Role 1 RoleBinding with 2 Subjects containing a Deployment serviceAccountName") + c.Deployments = []appsv1.Deployment{newDeploymentWithServiceAccount("my-dep-account")} + c.Roles = []rbacv1.Role{newRole("my-role")} + c.RoleBindings = []rbacv1.RoleBinding{ + newRoleBinding("my-role-binding", + newRoleRef("my-role"), + newServiceAccountSubject("my-dep-account"), newServiceAccountSubject("my-other-account")), + } + in, out = c.SplitCSVPermissionsObjects() + Expect(in).To(HaveLen(1)) + Expect(getRoleNames(in)).To(ContainElement("my-role")) + Expect(out).To(HaveLen(2)) + Expect(getRoleNames(out)).To(ContainElement("my-role")) + Expect(getRoleBindingNames(out)).To(ContainElement("my-role-binding")) + + By("splitting 2 Roles 2 RoleBinding, one with 1 Subject not containing and the other with 2 Subjects containing a Deployment serviceAccountName") + c.Deployments = []appsv1.Deployment{newDeploymentWithServiceAccount("my-dep-account")} + c.Roles = []rbacv1.Role{newRole("my-role-1"), newRole("my-role-2")} + c.RoleBindings = []rbacv1.RoleBinding{ + newRoleBinding("my-role-binding-1", + newRoleRef("my-role-1"), + newServiceAccountSubject("my-dep-account"), newServiceAccountSubject("my-other-account")), + newRoleBinding("my-role-binding-2", + newRoleRef("my-role-2"), + newServiceAccountSubject("my-other-account")), + } + in, out = c.SplitCSVPermissionsObjects() + Expect(in).To(HaveLen(1)) + Expect(getRoleNames(in)).To(ContainElement("my-role-1")) + Expect(out).To(HaveLen(4)) + Expect(getRoleNames(out)).To(ContainElement("my-role-1")) + Expect(getRoleNames(out)).To(ContainElement("my-role-2")) + Expect(getRoleBindingNames(out)).To(ContainElement("my-role-binding-1")) + Expect(getRoleBindingNames(out)).To(ContainElement("my-role-binding-2")) + + By("splitting on 2 different Deployments") + c.Deployments = []appsv1.Deployment{ + newDeploymentWithServiceAccount("my-dep-account-1"), + newDeploymentWithServiceAccount("my-dep-account-2"), + } + c.Roles = []rbacv1.Role{newRole("my-role-1"), newRole("my-role-2"), newRole("my-role-3")} + c.RoleBindings = []rbacv1.RoleBinding{ + newRoleBinding("my-role-binding-1", + newRoleRef("my-role-1"), + newServiceAccountSubject("my-dep-account-1"), newServiceAccountSubject("my-other-account")), + newRoleBinding("my-role-binding-2", + newRoleRef("my-role-2"), + newServiceAccountSubject("my-other-account")), + newRoleBinding("my-role-binding-3", + newRoleRef("my-role-3"), + newServiceAccountSubject("my-dep-account-2")), + } + in, out = c.SplitCSVPermissionsObjects() + Expect(in).To(HaveLen(2)) + Expect(getRoleNames(in)).To(ContainElement("my-role-1")) + Expect(getRoleNames(in)).To(ContainElement("my-role-3")) + Expect(out).To(HaveLen(4)) + Expect(getRoleNames(out)).To(ContainElement("my-role-1")) + Expect(getRoleNames(out)).To(ContainElement("my-role-2")) + Expect(getRoleBindingNames(out)).To(ContainElement("my-role-binding-1")) + Expect(getRoleBindingNames(out)).To(ContainElement("my-role-binding-2")) + }) + }) + + Describe("SplitCSVClusterPermissionsObjects", func() { + It("should return empty lists for an empty Manifests", func() { + c.ClusterRoles = []rbacv1.ClusterRole{} + in, out = c.SplitCSVClusterPermissionsObjects() + Expect(in).To(HaveLen(0)) + Expect(out).To(HaveLen(0)) + }) + It("should return non-empty lists", func() { + By("splitting 1 ClusterRole no ClusterRoleBinding") + c.ClusterRoles = []rbacv1.ClusterRole{newClusterRole("my-role")} + in, out = c.SplitCSVClusterPermissionsObjects() + Expect(in).To(HaveLen(0)) + Expect(out).To(HaveLen(1)) + Expect(getClusterRoleNames(out)).To(ContainElement("my-role")) + + By("splitting 1 ClusterRole 1 ClusterRoleBinding with 1 Subject not containing Deployment serviceAccountName") + c.Deployments = []appsv1.Deployment{newDeploymentWithServiceAccount("my-dep-account")} + c.ClusterRoles = []rbacv1.ClusterRole{newClusterRole("my-role")} + c.ClusterRoleBindings = []rbacv1.ClusterRoleBinding{ + newClusterRoleBinding("my-role-binding", newClusterRoleRef("my-role"), newServiceAccountSubject("my-other-account")), + } + in, out = c.SplitCSVClusterPermissionsObjects() + Expect(in).To(HaveLen(0)) + Expect(out).To(HaveLen(2)) + Expect(getClusterRoleNames(out)).To(ContainElement("my-role")) + Expect(getClusterRoleBindingNames(out)).To(ContainElement("my-role-binding")) + + By("splitting 1 ClusterRole 1 ClusterRoleBinding with 1 Subject containing Deployment serviceAccountName") + c.Deployments = []appsv1.Deployment{newDeploymentWithServiceAccount("my-dep-account")} + c.ClusterRoles = []rbacv1.ClusterRole{newClusterRole("my-role")} + c.ClusterRoleBindings = []rbacv1.ClusterRoleBinding{ + newClusterRoleBinding("my-role-binding", newClusterRoleRef("my-role"), newServiceAccountSubject("my-dep-account")), + } + in, out = c.SplitCSVClusterPermissionsObjects() + Expect(in).To(HaveLen(1)) + Expect(getClusterRoleNames(in)).To(ContainElement("my-role")) + Expect(out).To(HaveLen(0)) + + By("splitting 1 ClusterRole 1 ClusterRoleBinding with 2 Subjects containing a Deployment serviceAccountName") + c.Deployments = []appsv1.Deployment{newDeploymentWithServiceAccount("my-dep-account")} + c.ClusterRoles = []rbacv1.ClusterRole{newClusterRole("my-role")} + c.ClusterRoleBindings = []rbacv1.ClusterRoleBinding{ + newClusterRoleBinding("my-role-binding", + newClusterRoleRef("my-role"), + newServiceAccountSubject("my-dep-account"), newServiceAccountSubject("my-other-account")), + } + in, out = c.SplitCSVClusterPermissionsObjects() + Expect(in).To(HaveLen(1)) + Expect(getClusterRoleNames(in)).To(ContainElement("my-role")) + Expect(out).To(HaveLen(2)) + Expect(getClusterRoleNames(out)).To(ContainElement("my-role")) + Expect(getClusterRoleBindingNames(out)).To(ContainElement("my-role-binding")) + + By("splitting 2 ClusterRoles 2 ClusterRoleBindings, one with 1 Subject not containing and the other with 2 Subjects containing a Deployment serviceAccountName") + c.Deployments = []appsv1.Deployment{newDeploymentWithServiceAccount("my-dep-account")} + c.ClusterRoles = []rbacv1.ClusterRole{newClusterRole("my-role-1"), newClusterRole("my-role-2")} + c.ClusterRoleBindings = []rbacv1.ClusterRoleBinding{ + newClusterRoleBinding("my-role-binding-1", + newClusterRoleRef("my-role-1"), + newServiceAccountSubject("my-dep-account"), newServiceAccountSubject("my-other-account")), + newClusterRoleBinding("my-role-binding-2", + newClusterRoleRef("my-role-2"), + newServiceAccountSubject("my-other-account")), + } + in, out = c.SplitCSVClusterPermissionsObjects() + Expect(in).To(HaveLen(1)) + Expect(getClusterRoleNames(in)).To(ContainElement("my-role-1")) + Expect(out).To(HaveLen(4)) + Expect(getClusterRoleNames(out)).To(ContainElement("my-role-1")) + Expect(getClusterRoleNames(out)).To(ContainElement("my-role-2")) + Expect(getClusterRoleBindingNames(out)).To(ContainElement("my-role-binding-1")) + Expect(getClusterRoleBindingNames(out)).To(ContainElement("my-role-binding-2")) + + By("splitting on 2 different Deployments") + c.Deployments = []appsv1.Deployment{ + newDeploymentWithServiceAccount("my-dep-account-1"), + newDeploymentWithServiceAccount("my-dep-account-2"), + } + c.ClusterRoles = []rbacv1.ClusterRole{ + newClusterRole("my-role-1"), + newClusterRole("my-role-2"), + newClusterRole("my-role-3"), + } + c.ClusterRoleBindings = []rbacv1.ClusterRoleBinding{ + newClusterRoleBinding("my-role-binding-1", + newClusterRoleRef("my-role-1"), + newServiceAccountSubject("my-dep-account-1"), newServiceAccountSubject("my-other-account")), + newClusterRoleBinding("my-role-binding-2", + newClusterRoleRef("my-role-2"), + newServiceAccountSubject("my-other-account")), + newClusterRoleBinding("my-role-binding-3", + newClusterRoleRef("my-role-3"), + newServiceAccountSubject("my-dep-account-2")), + } + in, out = c.SplitCSVClusterPermissionsObjects() + Expect(in).To(HaveLen(2)) + Expect(getClusterRoleNames(in)).To(ContainElement("my-role-1")) + Expect(getClusterRoleNames(in)).To(ContainElement("my-role-3")) + Expect(out).To(HaveLen(4)) + Expect(getClusterRoleNames(out)).To(ContainElement("my-role-1")) + Expect(getClusterRoleNames(out)).To(ContainElement("my-role-2")) + Expect(getClusterRoleBindingNames(out)).To(ContainElement("my-role-binding-1")) + Expect(getClusterRoleBindingNames(out)).To(ContainElement("my-role-binding-2")) + }) + }) + +}) + +func getRoleNames(objs []controllerutil.Object) []string { + return getNamesForKind("Role", objs) +} + +func getRoleBindingNames(objs []controllerutil.Object) []string { + return getNamesForKind("RoleBinding", objs) +} + +func getClusterRoleNames(objs []controllerutil.Object) []string { + return getNamesForKind("ClusterRole", objs) +} + +func getClusterRoleBindingNames(objs []controllerutil.Object) []string { + return getNamesForKind("ClusterRoleBinding", objs) +} + +func getNamesForKind(kind string, objs []controllerutil.Object) (names []string) { + for _, obj := range objs { + if obj.GetObjectKind().GroupVersionKind().Kind == kind { + names = append(names, obj.GetName()) + } + } + return +} + +func newDeploymentWithServiceAccount(name string) (d appsv1.Deployment) { + d.Spec.Template.Spec.ServiceAccountName = name + return d +} + +func newRole(name string) (r rbacv1.Role) { + r.SetGroupVersionKind(rbacv1.SchemeGroupVersion.WithKind("Role")) + r.SetName(name) + return r +} + +func newClusterRole(name string) (r rbacv1.ClusterRole) { + r.SetGroupVersionKind(rbacv1.SchemeGroupVersion.WithKind("ClusterRole")) + r.SetName(name) + return r +} + +func newRoleBinding(name string, ref rbacv1.RoleRef, subjects ...rbacv1.Subject) (r rbacv1.RoleBinding) { + r.SetGroupVersionKind(rbacv1.SchemeGroupVersion.WithKind("RoleBinding")) + r.SetName(name) + r.RoleRef = ref + r.Subjects = subjects + return r +} + +func newClusterRoleBinding(name string, ref rbacv1.RoleRef, subjects ...rbacv1.Subject) (r rbacv1.ClusterRoleBinding) { + r.SetGroupVersionKind(rbacv1.SchemeGroupVersion.WithKind("ClusterRoleBinding")) + r.SetName(name) + r.RoleRef = ref + r.Subjects = subjects + return r +} + +func newRef(name, kind, apiGroup string) (s rbacv1.RoleRef) { + s.Name = name + s.Kind = kind + s.APIGroup = apiGroup + return s +} + +func newRoleRef(name string) (s rbacv1.RoleRef) { + return newRef(name, "Role", rbacv1.SchemeGroupVersion.Group) +} + +func newClusterRoleRef(name string) (s rbacv1.RoleRef) { + return newRef(name, "ClusterRole", rbacv1.SchemeGroupVersion.Group) +} + +func newSubject(name, kind string) (s rbacv1.Subject) { + s.Name = name + s.Kind = kind + return s +} + +func newServiceAccountSubject(name string) (s rbacv1.Subject) { + return newSubject(name, "ServiceAccount") +} diff --git a/internal/generate/collector/collect_test.go b/internal/generate/collector/collect_test.go deleted file mode 100644 index 0010cba259b..00000000000 --- a/internal/generate/collector/collect_test.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2018 The Operator-SDK Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package collector - -import ( - "os" - "path/filepath" - "testing" - - "github.com/stretchr/testify/assert" -) - -var ( - testDataDir = filepath.Join("..", "testdata") - goTestDataDir = filepath.Join(testDataDir, "non-standard-layout") - goConfigDir = filepath.Join(goTestDataDir, "config") -) - -func TestUpdateFromReader(t *testing.T) { - c := &Manifests{} - - err := filepath.Walk(goConfigDir, func(path string, info os.FileInfo, err error) error { - if err != nil || info.IsDir() { - return err - } - file, err := os.OpenFile(path, os.O_RDONLY, 0) - if err != nil { - return err - } - defer file.Close() - return c.UpdateFromReader(file) - }) - - assert.Nil(t, err, "failed to read manifests") - assert.Equal(t, len(c.Roles), 1, "failed to read Role(s)") - assert.Equal(t, len(c.Deployments), 1, "failed to read Deployment(s)") - // 2 CR/CRDs: - // - memcached.cache.examples.com - // - deployment.foo.example.com - assert.Equal(t, len(c.V1beta1CustomResourceDefinitions), 2, "failed to read v1beta1 CRDs") - assert.Equal(t, len(c.CustomResources), 2, "failed to read CRs") -} diff --git a/internal/generate/testdata/non-standard-layout/api/cache/v1alpha1/doc.go b/internal/generate/collector/collector_suite_test.go similarity index 75% rename from internal/generate/testdata/non-standard-layout/api/cache/v1alpha1/doc.go rename to internal/generate/collector/collector_suite_test.go index d5094b45a66..6066452f6d9 100644 --- a/internal/generate/testdata/non-standard-layout/api/cache/v1alpha1/doc.go +++ b/internal/generate/collector/collector_suite_test.go @@ -12,7 +12,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package v1alpha1 contains API Schema definitions for the cache v1alpha1 API group -// +k8s:deepcopy-gen=package,register -// +groupName=cache.example.com -package v1alpha1 +package collector + +import ( + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +func TestCollector(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Collector Suite") +} diff --git a/internal/generate/collector/collect.go b/internal/generate/collector/manifests.go similarity index 82% rename from internal/generate/collector/collect.go rename to internal/generate/collector/manifests.go index 097de8aeb96..71604d5da13 100644 --- a/internal/generate/collector/collect.go +++ b/internal/generate/collector/manifests.go @@ -27,6 +27,7 @@ import ( log "github.com/sirupsen/logrus" admissionregv1 "k8s.io/api/admissionregistration/v1" appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" @@ -40,7 +41,10 @@ import ( type Manifests struct { Roles []rbacv1.Role ClusterRoles []rbacv1.ClusterRole + RoleBindings []rbacv1.RoleBinding + ClusterRoleBindings []rbacv1.ClusterRoleBinding Deployments []appsv1.Deployment + ServiceAccounts []corev1.ServiceAccount V1CustomResourceDefinitions []apiextv1.CustomResourceDefinition V1beta1CustomResourceDefinitions []apiextv1beta1.CustomResourceDefinition ValidatingWebhooks []admissionregv1.ValidatingWebhook @@ -54,9 +58,11 @@ type Manifests struct { var ( roleGK = rbacv1.SchemeGroupVersion.WithKind("Role").GroupKind() clusterRoleGK = rbacv1.SchemeGroupVersion.WithKind("ClusterRole").GroupKind() + roleBindingGK = rbacv1.SchemeGroupVersion.WithKind("RoleBinding").GroupKind() + clusterRoleBindingGK = rbacv1.SchemeGroupVersion.WithKind("ClusterRoleBinding").GroupKind() + serviceAccountGK = corev1.SchemeGroupVersion.WithKind("ServiceAccount").GroupKind() deploymentGK = appsv1.SchemeGroupVersion.WithKind("Deployment").GroupKind() - v1crdGK = apiextv1.SchemeGroupVersion.WithKind("CustomResourceDefinition").GroupKind() - v1beta1crdGK = apiextv1beta1.SchemeGroupVersion.WithKind("CustomResourceDefinition").GroupKind() + crdGK = apiextv1.SchemeGroupVersion.WithKind("CustomResourceDefinition").GroupKind() validatingWebhookCfgGK = admissionregv1.SchemeGroupVersion.WithKind("ValidatingWebhookConfiguration").GroupKind() mutatingWebhookCfgGK = admissionregv1.SchemeGroupVersion.WithKind("MutatingWebhookConfiguration").GroupKind() v1alpha3ScorecardCfgGK = scorecardv1alpha3.GroupVersion.WithKind("Configuration").GroupKind() @@ -92,9 +98,15 @@ func (c *Manifests) UpdateFromDirs(deployDir, crdsDir string) error { err = c.addRoles(manifest) case clusterRoleGK: err = c.addClusterRoles(manifest) + case roleBindingGK: + err = c.addRoleBindings(manifest) + case clusterRoleBindingGK: + err = c.addClusterRoleBindings(manifest) + case serviceAccountGK: + err = c.addServiceAccounts(manifest) case deploymentGK: err = c.addDeployments(manifest) - case v1crdGK, v1beta1crdGK: + case crdGK: // Skip for now and add explicitly from CRDsDir input. case validatingWebhookCfgGK: err = c.addValidatingWebhookConfigurations(manifest) @@ -154,9 +166,15 @@ func (c *Manifests) UpdateFromReader(r io.Reader) error { err = c.addRoles(manifest) case clusterRoleGK: err = c.addClusterRoles(manifest) + case roleBindingGK: + err = c.addRoleBindings(manifest) + case clusterRoleBindingGK: + err = c.addClusterRoleBindings(manifest) + case serviceAccountGK: + err = c.addServiceAccounts(manifest) case deploymentGK: err = c.addDeployments(manifest) - case v1crdGK, v1beta1crdGK: + case crdGK: err = c.addCustomResourceDefinitions(gvk.Version, manifest) case validatingWebhookCfgGK: err = c.addValidatingWebhookConfigurations(manifest) @@ -212,6 +230,42 @@ func (c *Manifests) addClusterRoles(rawManifests ...[]byte) error { return nil } +// addRoleBindings assumes all manifest data in rawManifests are RoleBindings and adds them to the collector. +func (c *Manifests) addRoleBindings(rawManifests ...[]byte) error { + for _, rawManifest := range rawManifests { + binding := rbacv1.RoleBinding{} + if err := yaml.Unmarshal(rawManifest, &binding); err != nil { + return err + } + c.RoleBindings = append(c.RoleBindings, binding) + } + return nil +} + +// addClusterRoleBindings assumes all manifest data in rawManifests are ClusterRoleBindings and adds them to the collector. +func (c *Manifests) addClusterRoleBindings(rawManifests ...[]byte) error { + for _, rawManifest := range rawManifests { + binding := rbacv1.ClusterRoleBinding{} + if err := yaml.Unmarshal(rawManifest, &binding); err != nil { + return err + } + c.ClusterRoleBindings = append(c.ClusterRoleBindings, binding) + } + return nil +} + +// addServiceAccounts assumes all manifest data in rawManifests are ServiceAccounts and adds them to the collector. +func (c *Manifests) addServiceAccounts(rawManifests ...[]byte) error { + for _, rawManifest := range rawManifests { + sa := corev1.ServiceAccount{} + if err := yaml.Unmarshal(rawManifest, &sa); err != nil { + return err + } + c.ServiceAccounts = append(c.ServiceAccounts, sa) + } + return nil +} + // addDeployments assumes all manifest data in rawManifests are Deployments // and adds them to the collector. func (c *Manifests) addDeployments(rawManifests ...[]byte) error { diff --git a/internal/generate/testdata/clusterserviceversions/newlayout/manifests/memcached-operator.clusterserviceversion.yaml b/internal/generate/testdata/clusterserviceversions/output/memcached-operator.clusterserviceversion.yaml similarity index 58% rename from internal/generate/testdata/clusterserviceversions/newlayout/manifests/memcached-operator.clusterserviceversion.yaml rename to internal/generate/testdata/clusterserviceversions/output/memcached-operator.clusterserviceversion.yaml index 6c5a0b6a972..af7b345e646 100644 --- a/internal/generate/testdata/clusterserviceversions/newlayout/manifests/memcached-operator.clusterserviceversion.yaml +++ b/internal/generate/testdata/clusterserviceversions/output/memcached-operator.clusterserviceversion.yaml @@ -8,10 +8,10 @@ metadata: "apiVersion": "cache.example.com/v1alpha1", "kind": "Memcached", "metadata": { - "name": "example-memcached" + "name": "memcached-sample" }, "spec": { - "size": 3 + "foo": "bar" } } ] @@ -42,97 +42,111 @@ spec: mediatype: "" install: spec: + clusterPermissions: + - rules: + - apiGroups: + - cache.example.com + resources: + - memcacheds + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - cache.example.com + resources: + - memcacheds/status + verbs: + - get + - patch + - update + - apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create + - apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create + serviceAccountName: default deployments: - - name: memcached-operator + - name: memcached-operator-controller-manager spec: replicas: 1 selector: matchLabels: - name: memcached-operator + control-plane: controller-manager strategy: {} template: metadata: labels: - name: memcached-operator + control-plane: controller-manager spec: containers: - - command: - - memcached-operator - env: - - name: WATCH_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.annotations['olm.targetNamespaces'] - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: OPERATOR_NAME - value: memcached-operator - image: quay.io/example/memcached-operator:v0.0.3 - imagePullPolicy: Never - name: memcached-operator + - args: + - --secure-listen-address=0.0.0.0:8443 + - --upstream=http://127.0.0.1:8080/ + - --logtostderr=true + - --v=10 + image: gcr.io/kubebuilder/kube-rbac-proxy:v0.5.0 + name: kube-rbac-proxy + ports: + - containerPort: 8443 + name: https resources: {} - serviceAccountName: memcached-operator + - args: + - --metrics-addr=127.0.0.1:8080 + - --enable-leader-election + command: + - /manager + image: controller:latest + name: manager + resources: + limits: + cpu: 100m + memory: 30Mi + requests: + cpu: 100m + memory: 20Mi + terminationGracePeriodSeconds: 10 permissions: - rules: - apiGroups: - "" resources: - - pods - - services - - services/finalizers - - endpoints - - persistentvolumeclaims - - events - configmaps - - secrets - verbs: - - '*' - - apiGroups: - - apps - resources: - - deployments - - daemonsets - - replicasets - - statefulsets - verbs: - - '*' - - apiGroups: - - monitoring.coreos.com - resources: - - servicemonitors verbs: - get + - list + - watch - create - - apiGroups: - - apps - resourceNames: - - memcached-operator - resources: - - deployments/finalizers - verbs: - update + - patch + - delete - apiGroups: - "" resources: - - pods - verbs: - - get - - apiGroups: - - apps - resources: - - replicasets - - deployments + - configmaps/status verbs: - get + - update + - patch - apiGroups: - - cache.example.com + - "" resources: - - '*' + - events verbs: - - '*' - serviceAccountName: memcached-operator + - create + - patch + serviceAccountName: default strategy: deployment installModes: - supported: true diff --git a/internal/generate/testdata/non-standard-layout/PROJECT b/internal/generate/testdata/go/PROJECT similarity index 87% rename from internal/generate/testdata/non-standard-layout/PROJECT rename to internal/generate/testdata/go/PROJECT index ccdb9332a17..29a8478d6fd 100644 --- a/internal/generate/testdata/non-standard-layout/PROJECT +++ b/internal/generate/testdata/go/PROJECT @@ -1,5 +1,6 @@ domain: example.com layout: go.kubebuilder.io/v2 +projectName: memcached-operator repo: github.com/example/memcached-operator resources: - group: cache diff --git a/internal/generate/testdata/go/pkg/apis/cache/v1alpha1/doc.go b/internal/generate/testdata/go/api/v1alpha1/doc.go similarity index 100% rename from internal/generate/testdata/go/pkg/apis/cache/v1alpha1/doc.go rename to internal/generate/testdata/go/api/v1alpha1/doc.go diff --git a/internal/generate/testdata/go/api/v1alpha1/memcached_types.go b/internal/generate/testdata/go/api/v1alpha1/memcached_types.go index 985292f393e..99b77521bf4 100644 --- a/internal/generate/testdata/go/api/v1alpha1/memcached_types.go +++ b/internal/generate/testdata/go/api/v1alpha1/memcached_types.go @@ -21,14 +21,14 @@ import ( // MemcachedSpec defines the desired state of Memcached type MemcachedSpec struct { // Size is the size of the memcached deployment - // +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors=true + // +operator-sdk:csv:customresourcedefinitions:type=spec Size int32 `json:"size"` } // MemcachedStatus defines the observed state of Memcached type MemcachedStatus struct { // Nodes are the names of the memcached pods - // +operator-sdk:gen-csv:customresourcedefinitions.statusDescriptors=true + // +operator-sdk:csv:customresourcedefinitions:type=status Nodes []string `json:"nodes"` } @@ -38,7 +38,7 @@ type MemcachedStatus struct { // +kubebuilder:subresource:status // +kubebuilder:resource:path=memcacheds,scope=Namespaced // +kubebuilder:storageversion -// +operator-sdk:gen-csv:customresourcedefinitions.displayName="Memcached App" +// +operator-sdk:csv:customresourcedefinitions:displayName="Memcached App Display Name" type Memcached struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` diff --git a/internal/generate/testdata/go/api/v1alpha2/doc.go b/internal/generate/testdata/go/api/v1alpha2/doc.go index 09ac980c8c3..5686f852db6 100644 --- a/internal/generate/testdata/go/api/v1alpha2/doc.go +++ b/internal/generate/testdata/go/api/v1alpha2/doc.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package v1alpha1 contains API Schema definitions for the cache v1alpha1 API group +// Package v1alpha2 contains API Schema definitions for the cache v1alpha2 API group // +k8s:deepcopy-gen=package,register // +groupName=cache.example.com package v1alpha2 diff --git a/internal/generate/testdata/go/cmd/manager/main.go b/internal/generate/testdata/go/cmd/manager/main.go deleted file mode 100644 index 38dd16da61a..00000000000 --- a/internal/generate/testdata/go/cmd/manager/main.go +++ /dev/null @@ -1,3 +0,0 @@ -package main - -func main() {} diff --git a/internal/generate/testdata/go/deploy/crds_v1/cache.example.com_memcachedrs_crd.yaml b/internal/generate/testdata/go/deploy/crds_v1/cache.example.com_memcachedrs_crd.yaml deleted file mode 100644 index be7b00dfc12..00000000000 --- a/internal/generate/testdata/go/deploy/crds_v1/cache.example.com_memcachedrs_crd.yaml +++ /dev/null @@ -1,57 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: memcachedrs.cache.example.com -spec: - group: cache.example.com - names: - kind: MemcachedRS - listKind: MemcachedRSList - plural: memcachedrs - singular: memcachedrs - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: MemcachedRS is the Schema for the memcachedrs API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: MemcachedRSSpec defines the desired state of MemcachedRS - properties: - numNodes: - format: int32 - type: integer - required: - - numNodes - type: object - status: - description: MemcachedRSStatus defines the observed state of MemcachedRS - properties: - nodeList: - items: - type: string - type: array - test: - type: boolean - required: - - nodeList - - test - type: object - type: object - served: true - storage: true - subresources: - status: {} diff --git a/internal/generate/testdata/go/deploy/crds_v1/cache.example.com_memcacheds_crd.yaml b/internal/generate/testdata/go/deploy/crds_v1/cache.example.com_memcacheds_crd.yaml deleted file mode 100644 index 800a156069e..00000000000 --- a/internal/generate/testdata/go/deploy/crds_v1/cache.example.com_memcacheds_crd.yaml +++ /dev/null @@ -1,56 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: memcacheds.cache.example.com -spec: - group: cache.example.com - names: - kind: Memcached - listKind: MemcachedList - plural: memcacheds - singular: memcached - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: Memcached is the Schema for the memcacheds API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: MemcachedSpec defines the desired state of Memcached - properties: - size: - description: Size is the size of the memcached deployment - format: int32 - type: integer - required: - - size - type: object - status: - description: MemcachedStatus defines the observed state of Memcached - properties: - nodes: - description: Nodes are the names of the memcached pods - items: - type: string - type: array - required: - - nodes - type: object - type: object - served: true - storage: true - subresources: - status: {} diff --git a/internal/generate/testdata/go/deploy/crds_v1/cache.example.com_v1alpha1_memcached_cr.yaml b/internal/generate/testdata/go/deploy/crds_v1/cache.example.com_v1alpha1_memcached_cr.yaml deleted file mode 100644 index 2b8f17c3998..00000000000 --- a/internal/generate/testdata/go/deploy/crds_v1/cache.example.com_v1alpha1_memcached_cr.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: cache.example.com/v1alpha1 -kind: Memcached -metadata: - name: example-memcached -spec: - # Add fields here - size: 3 diff --git a/internal/generate/testdata/go/deploy/crds_v1/cache.example.com_v1alpha1_memcachedrs_cr.yaml b/internal/generate/testdata/go/deploy/crds_v1/cache.example.com_v1alpha1_memcachedrs_cr.yaml deleted file mode 100644 index 92861ed5fe5..00000000000 --- a/internal/generate/testdata/go/deploy/crds_v1/cache.example.com_v1alpha1_memcachedrs_cr.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: cache.example.com/v1alpha1 -kind: MemcachedRS -metadata: - name: example-memcachedrs -spec: - numNodes: 4 diff --git a/internal/generate/testdata/go/deploy/crds_v1beta1/cache.example.com_memcachedrs_crd.yaml b/internal/generate/testdata/go/deploy/crds_v1beta1/cache.example.com_memcachedrs_crd.yaml deleted file mode 100644 index 9ffb3fab46d..00000000000 --- a/internal/generate/testdata/go/deploy/crds_v1beta1/cache.example.com_memcachedrs_crd.yaml +++ /dev/null @@ -1,58 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: memcachedrs.cache.example.com -spec: - group: cache.example.com - names: - kind: MemcachedRS - listKind: MemcachedRSList - plural: memcachedrs - singular: memcachedrs - scope: Namespaced - subresources: - status: {} - validation: - openAPIV3Schema: - description: MemcachedRS is the Schema for the memcachedrs API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: MemcachedRSSpec defines the desired state of MemcachedRS - properties: - numNodes: - format: int32 - type: integer - required: - - numNodes - type: object - status: - description: MemcachedRSStatus defines the observed state of MemcachedRS - properties: - nodeList: - items: - type: string - type: array - test: - type: boolean - required: - - nodeList - - test - type: object - type: object - version: v1alpha1 - versions: - - name: v1alpha1 - served: true - storage: true diff --git a/internal/generate/testdata/go/deploy/crds_v1beta1/cache.example.com_memcacheds_crd.yaml b/internal/generate/testdata/go/deploy/crds_v1beta1/cache.example.com_memcacheds_crd.yaml deleted file mode 100644 index 0109edbab9a..00000000000 --- a/internal/generate/testdata/go/deploy/crds_v1beta1/cache.example.com_memcacheds_crd.yaml +++ /dev/null @@ -1,57 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: memcacheds.cache.example.com -spec: - group: cache.example.com - names: - kind: Memcached - listKind: MemcachedList - plural: memcacheds - singular: memcached - scope: Namespaced - subresources: - status: {} - validation: - openAPIV3Schema: - description: Memcached is the Schema for the memcacheds API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: MemcachedSpec defines the desired state of Memcached - properties: - size: - description: Size is the size of the memcached deployment - format: int32 - type: integer - required: - - size - type: object - status: - description: MemcachedStatus defines the observed state of Memcached - properties: - nodes: - description: Nodes are the names of the memcached pods - items: - type: string - type: array - required: - - nodes - type: object - type: object - version: v1alpha1 - versions: - - name: v1alpha1 - served: true - storage: true diff --git a/internal/generate/testdata/go/deploy/crds_v1beta1/cache.example.com_v1alpha1_memcached_cr.yaml b/internal/generate/testdata/go/deploy/crds_v1beta1/cache.example.com_v1alpha1_memcached_cr.yaml deleted file mode 100644 index 2b8f17c3998..00000000000 --- a/internal/generate/testdata/go/deploy/crds_v1beta1/cache.example.com_v1alpha1_memcached_cr.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: cache.example.com/v1alpha1 -kind: Memcached -metadata: - name: example-memcached -spec: - # Add fields here - size: 3 diff --git a/internal/generate/testdata/go/deploy/crds_v1beta1/cache.example.com_v1alpha1_memcachedrs_cr.yaml b/internal/generate/testdata/go/deploy/crds_v1beta1/cache.example.com_v1alpha1_memcachedrs_cr.yaml deleted file mode 100644 index 92861ed5fe5..00000000000 --- a/internal/generate/testdata/go/deploy/crds_v1beta1/cache.example.com_v1alpha1_memcachedrs_cr.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: cache.example.com/v1alpha1 -kind: MemcachedRS -metadata: - name: example-memcachedrs -spec: - numNodes: 4 diff --git a/internal/generate/testdata/go/deploy/olm-catalog/memcached-operator/0.0.2/memcached-operator.v0.0.2.clusterserviceversion.yaml b/internal/generate/testdata/go/deploy/olm-catalog/memcached-operator/0.0.2/memcached-operator.v0.0.2.clusterserviceversion.yaml deleted file mode 100644 index bdbdf724572..00000000000 --- a/internal/generate/testdata/go/deploy/olm-catalog/memcached-operator/0.0.2/memcached-operator.v0.0.2.clusterserviceversion.yaml +++ /dev/null @@ -1,212 +0,0 @@ -apiVersion: operators.coreos.com/v1alpha1 -kind: ClusterServiceVersion -metadata: - annotations: - alm-examples: |- - [ - { - "apiVersion": "cache.example.com/v1alpha1", - "kind": "Memcached", - "metadata": { - "name": "example-memcached" - }, - "spec": { - "size": 3 - } - }, - { - "apiVersion": "cache.example.com/v1alpha1", - "kind": "MemcachedRS", - "metadata": { - "name": "example-memcachedrs" - }, - "spec": { - "numNodes": 4 - } - } - ] - capabilities: Basic Install - name: memcached-operator.v0.0.2 - namespace: placeholder -spec: - apiservicedefinitions: {} - customresourcedefinitions: - owned: - - description: MemcachedRS is the Schema for the memcachedrs API - displayName: MemcachedRS App - kind: MemcachedRS - name: memcachedrs.cache.example.com - specDescriptors: - - displayName: Num Nodes - path: numNodes - statusDescriptors: - - displayName: Node List - path: nodeList - version: v1alpha1 - - description: Memcached is the Schema for the memcacheds API - displayName: Memcached App - kind: Memcached - name: memcacheds.cache.example.com - specDescriptors: - - description: Size is the size of the memcached deployment - displayName: Size - path: size - x-descriptors: - - urn:alm:descriptor:com.tectonic.ui:podCount - statusDescriptors: - - description: Nodes are the names of the memcached pods - displayName: Nodes - path: nodes - version: v1alpha1 - description: Main enterprise application providing business critical features with - high availability and no manual intervention. - displayName: Memcached Application - install: - spec: - deployments: - - name: memcached-operator - spec: - replicas: 1 - selector: - matchLabels: - name: memcached-operator - strategy: {} - template: - metadata: - labels: - name: memcached-operator - spec: - containers: - - command: - - memcached-operator - env: - - name: WATCH_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.annotations['olm.targetNamespaces'] - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: OPERATOR_NAME - value: memcached-operator - image: quay.io/example/memcached-operator:v0.0.2 - imagePullPolicy: Never - name: memcached-operator - resources: {} - serviceAccountName: memcached-operator - permissions: - - rules: - - apiGroups: - - "" - resources: - - pods - - services - - services/finalizers - - endpoints - - persistentvolumeclaims - - events - - configmaps - - secrets - verbs: - - '*' - - apiGroups: - - apps - resources: - - deployments - - daemonsets - - replicasets - - statefulsets - verbs: - - '*' - - apiGroups: - - monitoring.coreos.com - resources: - - servicemonitors - verbs: - - get - - create - - apiGroups: - - apps - resourceNames: - - memcached-operator - resources: - - deployments/finalizers - verbs: - - update - - apiGroups: - - "" - resources: - - pods - verbs: - - get - - apiGroups: - - apps - resources: - - replicasets - - deployments - verbs: - - get - - apiGroups: - - cache.example.com - resources: - - '*' - verbs: - - '*' - serviceAccountName: memcached-operator - strategy: deployment - installModes: - - supported: true - type: OwnNamespace - - supported: true - type: SingleNamespace - - supported: false - type: MultiNamespace - - supported: true - type: AllNamespaces - keywords: - - memcached - - app - maintainers: - - email: corp@example.com - name: Some Corp - maturity: alpha - provider: - name: Example - url: www.example.com - version: 0.0.2 - webhookdefinitions: - - admissionReviewVersions: null - deploymentName: memcached-operator-webhook - failurePolicy: Fail - generateName: vmemcached.kb.io - rules: - - apiGroups: - - cache.example.com - apiVersions: - - v1alpha1 - operations: - - CREATE - - UPDATE - resources: - - memcacheds - sideEffects: null - type: ValidatingAdmissionWebhook - webhookPath: /validate-cache-example-com-v1alpha1-memcached - - admissionReviewVersions: null - deploymentName: memcached-operator-webhook - failurePolicy: Fail - generateName: mmemcached.kb.io - rules: - - apiGroups: - - cache.example.com - apiVersions: - - v1alpha1 - operations: - - CREATE - - UPDATE - resources: - - memcacheds - sideEffects: null - type: MutatingAdmissionWebhook - webhookPath: /mutate-cache-example-com-v1alpha1-memcached diff --git a/internal/generate/testdata/go/deploy/olm-catalog/memcached-operator/0.0.3/memcached-operator.v0.0.3.clusterserviceversion.yaml b/internal/generate/testdata/go/deploy/olm-catalog/memcached-operator/0.0.3/memcached-operator.v0.0.3.clusterserviceversion.yaml deleted file mode 100644 index 4204b668f2e..00000000000 --- a/internal/generate/testdata/go/deploy/olm-catalog/memcached-operator/0.0.3/memcached-operator.v0.0.3.clusterserviceversion.yaml +++ /dev/null @@ -1,213 +0,0 @@ -apiVersion: operators.coreos.com/v1alpha1 -kind: ClusterServiceVersion -metadata: - annotations: - alm-examples: |- - [ - { - "apiVersion": "cache.example.com/v1alpha1", - "kind": "Memcached", - "metadata": { - "name": "example-memcached" - }, - "spec": { - "size": 3 - } - }, - { - "apiVersion": "cache.example.com/v1alpha1", - "kind": "MemcachedRS", - "metadata": { - "name": "example-memcachedrs" - }, - "spec": { - "numNodes": 4 - } - } - ] - capabilities: Basic Install - name: memcached-operator.v0.0.3 - namespace: placeholder -spec: - apiservicedefinitions: {} - customresourcedefinitions: - owned: - - description: MemcachedRS is the Schema for the memcachedrs API - displayName: MemcachedRS App - kind: MemcachedRS - name: memcachedrs.cache.example.com - specDescriptors: - - displayName: Num Nodes - path: numNodes - statusDescriptors: - - displayName: Node List - path: nodeList - version: v1alpha1 - - description: Memcached is the Schema for the memcacheds API - displayName: Memcached App - kind: Memcached - name: memcacheds.cache.example.com - specDescriptors: - - description: Size is the size of the memcached deployment - displayName: Size - path: size - x-descriptors: - - urn:alm:descriptor:com.tectonic.ui:podCount - statusDescriptors: - - description: Nodes are the names of the memcached pods - displayName: Nodes - path: nodes - version: v1alpha1 - description: Main enterprise application providing business critical features with - high availability and no manual intervention. - displayName: Memcached Application - install: - spec: - deployments: - - name: memcached-operator - spec: - replicas: 1 - selector: - matchLabels: - name: memcached-operator - strategy: {} - template: - metadata: - labels: - name: memcached-operator - spec: - containers: - - command: - - memcached-operator - env: - - name: WATCH_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.annotations['olm.targetNamespaces'] - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: OPERATOR_NAME - value: memcached-operator - image: quay.io/example/memcached-operator:v0.0.3 - imagePullPolicy: Never - name: memcached-operator - resources: {} - serviceAccountName: memcached-operator - permissions: - - rules: - - apiGroups: - - "" - resources: - - pods - - services - - services/finalizers - - endpoints - - persistentvolumeclaims - - events - - configmaps - - secrets - verbs: - - '*' - - apiGroups: - - apps - resources: - - deployments - - daemonsets - - replicasets - - statefulsets - verbs: - - '*' - - apiGroups: - - monitoring.coreos.com - resources: - - servicemonitors - verbs: - - get - - create - - apiGroups: - - apps - resourceNames: - - memcached-operator - resources: - - deployments/finalizers - verbs: - - update - - apiGroups: - - "" - resources: - - pods - verbs: - - get - - apiGroups: - - apps - resources: - - replicasets - - deployments - verbs: - - get - - apiGroups: - - cache.example.com - resources: - - '*' - verbs: - - '*' - serviceAccountName: memcached-operator - strategy: deployment - installModes: - - supported: true - type: OwnNamespace - - supported: true - type: SingleNamespace - - supported: false - type: MultiNamespace - - supported: true - type: AllNamespaces - keywords: - - memcached - - app - maintainers: - - email: corp@example.com - name: Some Corp - maturity: alpha - provider: - name: Example - url: www.example.com - replaces: memcached-operator.v0.0.2 - version: 0.0.3 - webhookdefinitions: - - admissionReviewVersions: null - deploymentName: memcached-operator-webhook - failurePolicy: Fail - generateName: vmemcached.kb.io - rules: - - apiGroups: - - cache.example.com - apiVersions: - - v1alpha1 - operations: - - CREATE - - UPDATE - resources: - - memcacheds - sideEffects: null - type: ValidatingAdmissionWebhook - webhookPath: /validate-cache-example-com-v1alpha1-memcached - - admissionReviewVersions: null - deploymentName: memcached-operator-webhook - failurePolicy: Fail - generateName: mmemcached.kb.io - rules: - - apiGroups: - - cache.example.com - apiVersions: - - v1alpha1 - operations: - - CREATE - - UPDATE - resources: - - memcacheds - sideEffects: null - type: MutatingAdmissionWebhook - webhookPath: /mutate-cache-example-com-v1alpha1-memcached diff --git a/internal/generate/testdata/go/deploy/olm-catalog/memcached-operator/manifests/memcached-operator.clusterserviceversion.yaml b/internal/generate/testdata/go/deploy/olm-catalog/memcached-operator/manifests/memcached-operator.clusterserviceversion.yaml deleted file mode 100644 index ce132cdbf53..00000000000 --- a/internal/generate/testdata/go/deploy/olm-catalog/memcached-operator/manifests/memcached-operator.clusterserviceversion.yaml +++ /dev/null @@ -1,212 +0,0 @@ -apiVersion: operators.coreos.com/v1alpha1 -kind: ClusterServiceVersion -metadata: - annotations: - alm-examples: |- - [ - { - "apiVersion": "cache.example.com/v1alpha1", - "kind": "Memcached", - "metadata": { - "name": "example-memcached" - }, - "spec": { - "size": 3 - } - }, - { - "apiVersion": "cache.example.com/v1alpha1", - "kind": "MemcachedRS", - "metadata": { - "name": "example-memcachedrs" - }, - "spec": { - "numNodes": 4 - } - } - ] - capabilities: Basic Install - name: memcached-operator.v0.0.2 - namespace: placeholder -spec: - apiservicedefinitions: {} - customresourcedefinitions: - owned: - - description: MemcachedRS is the Schema for the memcachedrs API - displayName: MemcachedRS App - kind: MemcachedRS - name: memcachedrs.cache.example.com - specDescriptors: - - displayName: Num Nodes - path: numNodes - statusDescriptors: - - displayName: Node List - path: nodeList - version: v1alpha1 - - description: Memcached is the Schema for the memcacheds API - displayName: Memcached App - kind: Memcached - name: memcacheds.cache.example.com - specDescriptors: - - description: Size is the size of the memcached deployment - displayName: Size - path: size - x-descriptors: - - urn:alm:descriptor:com.tectonic.ui:podCount - statusDescriptors: - - description: Nodes are the names of the memcached pods - displayName: Nodes - path: nodes - version: v1alpha1 - description: Main enterprise application providing business critical features with - high availability and no manual intervention. - displayName: Memcached Application - install: - spec: - deployments: - - name: memcached-operator - spec: - replicas: 1 - selector: - matchLabels: - name: memcached-operator - strategy: {} - template: - metadata: - labels: - name: memcached-operator - spec: - containers: - - command: - - memcached-operator - env: - - name: WATCH_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.annotations['olm.targetNamespaces'] - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: OPERATOR_NAME - value: memcached-operator - image: quay.io/example/memcached-operator:v0.0.3 - imagePullPolicy: Never - name: memcached-operator - resources: {} - serviceAccountName: memcached-operator - permissions: - - rules: - - apiGroups: - - "" - resources: - - pods - - services - - services/finalizers - - endpoints - - persistentvolumeclaims - - events - - configmaps - - secrets - verbs: - - '*' - - apiGroups: - - apps - resources: - - deployments - - daemonsets - - replicasets - - statefulsets - verbs: - - '*' - - apiGroups: - - monitoring.coreos.com - resources: - - servicemonitors - verbs: - - get - - create - - apiGroups: - - apps - resourceNames: - - memcached-operator - resources: - - deployments/finalizers - verbs: - - update - - apiGroups: - - "" - resources: - - pods - verbs: - - get - - apiGroups: - - apps - resources: - - replicasets - - deployments - verbs: - - get - - apiGroups: - - cache.example.com - resources: - - '*' - verbs: - - '*' - serviceAccountName: memcached-operator - strategy: deployment - installModes: - - supported: true - type: OwnNamespace - - supported: true - type: SingleNamespace - - supported: false - type: MultiNamespace - - supported: true - type: AllNamespaces - keywords: - - memcached - - app - maintainers: - - email: corp@example.com - name: Some Corp - maturity: alpha - provider: - name: Example - url: www.example.com - version: 0.0.2 - webhookdefinitions: - - admissionReviewVersions: null - deploymentName: memcached-operator-webhook - failurePolicy: Fail - generateName: vmemcached.kb.io - rules: - - apiGroups: - - cache.example.com - apiVersions: - - v1alpha1 - operations: - - CREATE - - UPDATE - resources: - - memcacheds - sideEffects: null - type: ValidatingAdmissionWebhook - webhookPath: /validate-cache-example-com-v1alpha1-memcached - - admissionReviewVersions: null - deploymentName: memcached-operator-webhook - failurePolicy: Fail - generateName: mmemcached.kb.io - rules: - - apiGroups: - - cache.example.com - apiVersions: - - v1alpha1 - operations: - - CREATE - - UPDATE - resources: - - memcacheds - sideEffects: null - type: MutatingAdmissionWebhook - webhookPath: /mutate-cache-example-com-v1alpha1-memcached diff --git a/internal/generate/testdata/go/deploy/olm-catalog/memcached-operator/memcached-operator.package.yaml b/internal/generate/testdata/go/deploy/olm-catalog/memcached-operator/memcached-operator.package.yaml deleted file mode 100644 index 63b19654795..00000000000 --- a/internal/generate/testdata/go/deploy/olm-catalog/memcached-operator/memcached-operator.package.yaml +++ /dev/null @@ -1,7 +0,0 @@ -channels: -- currentCSV: memcached-operator.v0.0.2 - name: alpha -- currentCSV: memcached-operator.v0.0.3 - name: stable -defaultChannel: stable -packageName: memcached-operator diff --git a/internal/generate/testdata/go/deploy/olm-catalog/memcached-operator/noupdate/memcached-operator.v0.0.3.clusterserviceversion.yaml b/internal/generate/testdata/go/deploy/olm-catalog/memcached-operator/noupdate/memcached-operator.v0.0.3.clusterserviceversion.yaml deleted file mode 100644 index 31afb9a1d1c..00000000000 --- a/internal/generate/testdata/go/deploy/olm-catalog/memcached-operator/noupdate/memcached-operator.v0.0.3.clusterserviceversion.yaml +++ /dev/null @@ -1,216 +0,0 @@ -apiVersion: operators.coreos.com/v1alpha1 -kind: ClusterServiceVersion -metadata: - annotations: - alm-examples: |- - [ - { - "apiVersion": "cache.example.com/v1alpha1", - "kind": "Memcached", - "metadata": { - "name": "example-memcached" - }, - "spec": { - "size": 3 - } - }, - { - "apiVersion": "cache.example.com/v1alpha1", - "kind": "MemcachedRS", - "metadata": { - "name": "example-memcachedrs" - }, - "spec": { - "numNodes": 4 - } - } - ] - capabilities: Basic Install - name: memcached-operator.v0.0.3 - namespace: placeholder -spec: - apiservicedefinitions: {} - customresourcedefinitions: - owned: - - description: MemcachedRS is the Schema for the memcachedrs API - displayName: MemcachedRS App - kind: MemcachedRS - name: memcachedrs.cache.example.com - specDescriptors: - - displayName: Num Nodes - path: numNodes - statusDescriptors: - - displayName: Node List - path: nodeList - version: v1alpha1 - - description: Memcached is the Schema for the memcacheds API - displayName: Memcached App - kind: Memcached - name: memcacheds.cache.example.com - specDescriptors: - - description: Size is the size of the memcached deployment - displayName: Size - path: size - x-descriptors: - - urn:alm:descriptor:com.tectonic.ui:podCount - statusDescriptors: - - description: Nodes are the names of the memcached pods - displayName: Nodes - path: nodes - version: v1alpha1 - description: Memcached Operator description. TODO. - displayName: Memcached Operator - icon: - - base64data: "" - mediatype: "" - install: - spec: - deployments: - - name: memcached-operator - spec: - replicas: 1 - selector: - matchLabels: - name: memcached-operator - strategy: {} - template: - metadata: - labels: - name: memcached-operator - spec: - containers: - - command: - - memcached-operator - env: - - name: WATCH_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.annotations['olm.targetNamespaces'] - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: OPERATOR_NAME - value: memcached-operator - image: quay.io/example/memcached-operator:v0.0.3 - imagePullPolicy: Never - name: memcached-operator - resources: {} - serviceAccountName: memcached-operator - permissions: - - rules: - - apiGroups: - - "" - resources: - - pods - - services - - services/finalizers - - endpoints - - persistentvolumeclaims - - events - - configmaps - - secrets - verbs: - - '*' - - apiGroups: - - apps - resources: - - deployments - - daemonsets - - replicasets - - statefulsets - verbs: - - '*' - - apiGroups: - - monitoring.coreos.com - resources: - - servicemonitors - verbs: - - get - - create - - apiGroups: - - apps - resourceNames: - - memcached-operator - resources: - - deployments/finalizers - verbs: - - update - - apiGroups: - - "" - resources: - - pods - verbs: - - get - - apiGroups: - - apps - resources: - - replicasets - - deployments - verbs: - - get - - apiGroups: - - cache.example.com - resources: - - '*' - verbs: - - '*' - serviceAccountName: memcached-operator - strategy: deployment - installModes: - - supported: true - type: OwnNamespace - - supported: true - type: SingleNamespace - - supported: false - type: MultiNamespace - - supported: true - type: AllNamespaces - keywords: - - memcached-operator - links: - - name: Memcached Operator - url: https://memcached-operator.domain - maintainers: - - email: your@email.com - name: Maintainer Name - maturity: alpha - provider: - name: Provider Name - url: https://your.domain - version: 0.0.3 - webhookdefinitions: - - admissionReviewVersions: null - deploymentName: memcached-operator-webhook - failurePolicy: Fail - generateName: vmemcached.kb.io - rules: - - apiGroups: - - cache.example.com - apiVersions: - - v1alpha1 - operations: - - CREATE - - UPDATE - resources: - - memcacheds - sideEffects: null - type: ValidatingAdmissionWebhook - webhookPath: /validate-cache-example-com-v1alpha1-memcached - - admissionReviewVersions: null - deploymentName: memcached-operator-webhook - failurePolicy: Fail - generateName: mmemcached.kb.io - rules: - - apiGroups: - - cache.example.com - apiVersions: - - v1alpha1 - operations: - - CREATE - - UPDATE - resources: - - memcacheds - sideEffects: null - type: MutatingAdmissionWebhook - webhookPath: /mutate-cache-example-com-v1alpha1-memcached diff --git a/internal/generate/testdata/go/deploy/operator.yaml b/internal/generate/testdata/go/deploy/operator.yaml deleted file mode 100644 index 8a00f16ad68..00000000000 --- a/internal/generate/testdata/go/deploy/operator.yaml +++ /dev/null @@ -1,32 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: memcached-operator -spec: - replicas: 1 - selector: - matchLabels: - name: memcached-operator - template: - metadata: - labels: - name: memcached-operator - spec: - serviceAccountName: memcached-operator - containers: - - name: memcached-operator - image: quay.io/example/memcached-operator:v0.0.3 - command: - - memcached-operator - imagePullPolicy: Never - env: - - name: WATCH_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: OPERATOR_NAME - value: memcached-operator diff --git a/internal/generate/testdata/go/deploy/role.yaml b/internal/generate/testdata/go/deploy/role.yaml deleted file mode 100644 index d1a2a04d0d0..00000000000 --- a/internal/generate/testdata/go/deploy/role.yaml +++ /dev/null @@ -1,61 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: memcached-operator -rules: -- apiGroups: - - "" - resources: - - pods - - services - - services/finalizers - - endpoints - - persistentvolumeclaims - - events - - configmaps - - secrets - verbs: - - '*' -- apiGroups: - - apps - resources: - - deployments - - daemonsets - - replicasets - - statefulsets - verbs: - - '*' -- apiGroups: - - monitoring.coreos.com - resources: - - servicemonitors - verbs: - - get - - create -- apiGroups: - - apps - resourceNames: - - memcached-operator - resources: - - deployments/finalizers - verbs: - - update -- apiGroups: - - "" - resources: - - pods - verbs: - - get -- apiGroups: - - apps - resources: - - replicasets - - deployments - verbs: - - get -- apiGroups: - - cache.example.com - resources: - - '*' - verbs: - - '*' diff --git a/internal/generate/testdata/go/deploy/role_binding.yaml b/internal/generate/testdata/go/deploy/role_binding.yaml deleted file mode 100644 index 322ecc9e6ac..00000000000 --- a/internal/generate/testdata/go/deploy/role_binding.yaml +++ /dev/null @@ -1,11 +0,0 @@ -kind: RoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: memcached-operator -subjects: -- kind: ServiceAccount - name: memcached-operator -roleRef: - kind: Role - name: memcached-operator - apiGroup: rbac.authorization.k8s.io diff --git a/internal/generate/testdata/go/deploy/service_account.yaml b/internal/generate/testdata/go/deploy/service_account.yaml deleted file mode 100644 index 8d58bc78322..00000000000 --- a/internal/generate/testdata/go/deploy/service_account.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - name: memcached-operator diff --git a/internal/generate/testdata/go/deploy/webhooks/cache-example-com-v1alpha1-memcached.webhook.yaml b/internal/generate/testdata/go/deploy/webhooks/cache-example-com-v1alpha1-memcached.webhook.yaml deleted file mode 100644 index 063f60f2f91..00000000000 --- a/internal/generate/testdata/go/deploy/webhooks/cache-example-com-v1alpha1-memcached.webhook.yaml +++ /dev/null @@ -1,50 +0,0 @@ ---- -apiVersion: admissionregistration.k8s.io/v1beta1 -kind: MutatingWebhookConfiguration -metadata: - creationTimestamp: null - name: memcached-operator-mutating-webhook-configuration -webhooks: -- clientConfig: - caBundle: Cg== - service: - name: memcached-operator-webhook-service - namespace: memcached-operator-system - path: /mutate-cache-example-com-v1alpha1-memcached - failurePolicy: Fail - name: mmemcached.kb.io - rules: - - apiGroups: - - cache.example.com - apiVersions: - - v1alpha1 - operations: - - CREATE - - UPDATE - resources: - - memcacheds ---- -apiVersion: admissionregistration.k8s.io/v1beta1 -kind: ValidatingWebhookConfiguration -metadata: - creationTimestamp: null - name: memcached-operator-validating-webhook-configuration -webhooks: -- clientConfig: - caBundle: Cg== - service: - name: memcached-operator-webhook-service - namespace: memcached-operator-system - path: /validate-cache-example-com-v1alpha1-memcached - failurePolicy: Fail - name: vmemcached.kb.io - rules: - - apiGroups: - - cache.example.com - apiVersions: - - v1alpha1 - operations: - - CREATE - - UPDATE - resources: - - memcacheds diff --git a/internal/generate/testdata/go/emptydir/.keep b/internal/generate/testdata/go/emptydir/.keep deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/internal/generate/testdata/go/pkg/apis/cache/v1alpha1/dummy_types.go b/internal/generate/testdata/go/pkg/apis/cache/v1alpha1/dummy_types.go deleted file mode 100644 index e6ee1101a7c..00000000000 --- a/internal/generate/testdata/go/pkg/apis/cache/v1alpha1/dummy_types.go +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright 2020 The Operator-SDK Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v1alpha1 - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// +k8s:deepcopy-gen=false -// +k8s:openapi-gen=false -type NoKindSpec struct { - // Not included in anything, no kind type - // +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors=true - // +operator-sdk:gen-csv:customresourcedefinitions.statusDescriptors=true - Size int32 `json:"size"` - // Not included in anything, no kind type - Boss Hog `json:"hog"` -} - -// +k8s:deepcopy-gen=false -// +k8s:openapi-gen=false -type NoKindStatus struct { - // Not included in anything, no kind type - // +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors=true - // +operator-sdk:gen-csv:customresourcedefinitions.statusDescriptors=true - Nodes []string `json:"nodes"` -} - -// +k8s:deepcopy-gen=false -// +k8s:openapi-gen=false -type DummySpec struct { - // Should be in spec - // +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors=true - // +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors.displayName="dummy-pods" - // +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors.x-descriptors="urn:alm:descriptor:com.tectonic.ui:podCount" - Size int32 `json:"size"` - // Should be in spec, but should not have array index in path - // +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors=true - // +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors.displayName="Wheels" - // +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors.x-descriptors="urn:alm:descriptor:com.tectonic.ui:text" - Wheels []Wheel `json:"wheels"` -} - -// +k8s:deepcopy-gen=false -// +k8s:openapi-gen=false -type DummyStatus struct { - // Should be in status but not spec, since DummyStatus isn't in DummySpec - // +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors=true - // +operator-sdk:gen-csv:customresourcedefinitions.statusDescriptors=true - Nodes []string `json:"nodes"` - // Not included in status but children should be - Boss Hog `json:"hog"` -} - -// +k8s:deepcopy-gen=false -// +k8s:openapi-gen=false -type Hog struct { - // Should be in status but not spec, since Hog isn't in DummySpec - // +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors=true - // +operator-sdk:gen-csv:customresourcedefinitions.statusDescriptors=true - // +operator-sdk:gen-csv:customresourcedefinitions.statusDescriptors.displayName="boss-hog-engine" - Engine Engine `json:"engine"` - // Not in spec or status, no boolean annotation - // +operator-sdk:gen-csv:customresourcedefinitions.statusDescriptors.displayName="doesnt-matter" - Brand string `json:"brand"` - // Not in spec or status - Helmet string `json:"helmet"` - // Fields should be inlined - // +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors=true - // +operator-sdk:gen-csv:customresourcedefinitions.statusDescriptors=true - Inlined InlinedComponent `json:",inline"` - // Fields should be inlined - InlinedComponent `json:",inline"` - // Should be ignored - // +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors=true - // +operator-sdk:gen-csv:customresourcedefinitions.statusDescriptors=true - Ignored IgnoredComponent `json:"-"` - // Should be ignored, but exported children should not be - notExported `json:",inline"` -} - -type notExported struct { - // +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors=true - // +operator-sdk:gen-csv:customresourcedefinitions.statusDescriptors=true - Public string `json:"foo"` - // +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors=true - // +operator-sdk:gen-csv:customresourcedefinitions.statusDescriptors=true - private string `json:"-"` -} - -// +k8s:deepcopy-gen=false -// +k8s:openapi-gen=false -type Engine struct { - // Should not be included, no annotations. - Pistons []string `json:"pistons"` -} - -// +k8s:deepcopy-gen=false -// +k8s:openapi-gen=false -type Wheel struct { - // Type should be in spec with path equal to wheels[0].type - // +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors=true - // +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors.displayName="Wheel Type" - // +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors.x-descriptors="urn:alm:descriptor:com.tectonic.ui:arrayFieldGroup:wheels,urn:alm:descriptor:com.tectonic.ui:text" - Type string `json:"type"` -} - -// +k8s:deepcopy-gen=false -// +k8s:openapi-gen=false -type InlinedComponent struct { - // +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors=true - // +operator-sdk:gen-csv:customresourcedefinitions.statusDescriptors=true - SeatMaterial string `json:"seatMaterial"` -} - -// +k8s:deepcopy-gen=false -// +k8s:openapi-gen=false -type IgnoredComponent struct { - // +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors=true - // +operator-sdk:gen-csv:customresourcedefinitions.statusDescriptors=true - TrunkSpace string `json:"trunkSpace"` -} - -// +k8s:deepcopy-gen=false -// +k8s:openapi-gen=false -type OtherDummyStatus struct { - // Should be in status but not spec, since this isn't a spec type - // +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors=true - // +operator-sdk:gen-csv:customresourcedefinitions.statusDescriptors=true - Nothing string `json:"nothing"` -} - -// Dummy is the Schema for the dummy API -// +k8s:deepcopy-gen=false -// +k8s:openapi-gen=false -// +kubebuilder:subresource:status -// +kubebuilder:resource:path=dummys,scope=Namespaced -// +operator-sdk:gen-csv:customresourcedefinitions.displayName="Dummy App" -// +operator-sdk:gen-csv:customresourcedefinitions.resources="Deployment,v1,\"dummy-deployment\"" -// +operator-sdk:gen-csv:customresourcedefinitions.resources="ReplicaSet,v1beta2,\"dummy-replicaset\"" -// +operator-sdk:gen-csv:customresourcedefinitions.resources="Pod,v1,\"dummy-pod\"" -type Dummy struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec DummySpec `json:"spec,omitempty"` - Status DummyStatus `json:"status,omitempty"` -} - -// OtherDummy is the Schema for the other dummy API -// +k8s:deepcopy-gen=false -// +k8s:openapi-gen=false -// +operator-sdk:gen-csv:customresourcedefinitions.displayName="Other Dummy App" -// +operator-sdk:gen-csv:customresourcedefinitions.resources="Service,v1,\"other-dummy-service\"" -// +operator-sdk:gen-csv:customresourcedefinitions.resources="Pod,v1,\"other-dummy-pod\"" -type OtherDummy struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec Hog `json:"spec,omitempty"` - Status OtherDummyStatus `json:"status,omitempty"` -} - -// DummyList contains a list of Dummy -// +k8s:deepcopy-gen=false -// +k8s:openapi-gen=false -type DummyList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []Dummy `json:"items"` -} diff --git a/internal/generate/testdata/go/pkg/apis/cache/v1alpha1/memcached_types.go b/internal/generate/testdata/go/pkg/apis/cache/v1alpha1/memcached_types.go deleted file mode 100644 index 985292f393e..00000000000 --- a/internal/generate/testdata/go/pkg/apis/cache/v1alpha1/memcached_types.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2020 The Operator-SDK Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v1alpha1 - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// MemcachedSpec defines the desired state of Memcached -type MemcachedSpec struct { - // Size is the size of the memcached deployment - // +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors=true - Size int32 `json:"size"` -} - -// MemcachedStatus defines the observed state of Memcached -type MemcachedStatus struct { - // Nodes are the names of the memcached pods - // +operator-sdk:gen-csv:customresourcedefinitions.statusDescriptors=true - Nodes []string `json:"nodes"` -} - -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -// Memcached is the Schema for the memcacheds API -// +kubebuilder:subresource:status -// +kubebuilder:resource:path=memcacheds,scope=Namespaced -// +kubebuilder:storageversion -// +operator-sdk:gen-csv:customresourcedefinitions.displayName="Memcached App" -type Memcached struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec MemcachedSpec `json:"spec,omitempty"` - Status MemcachedStatus `json:"status,omitempty"` -} - -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -// MemcachedList contains a list of Memcached -type MemcachedList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []Memcached `json:"items"` -} diff --git a/internal/generate/testdata/go/pkg/apis/cache/v1alpha1/memcachedrs_types.go b/internal/generate/testdata/go/pkg/apis/cache/v1alpha1/memcachedrs_types.go deleted file mode 100644 index ec8dde33bfc..00000000000 --- a/internal/generate/testdata/go/pkg/apis/cache/v1alpha1/memcachedrs_types.go +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2020 The Operator-SDK Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v1alpha1 - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// MemcachedRSSpec defines the desired state of MemcachedRS -type MemcachedRSSpec struct { - // +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors=true - NumNodes int32 `json:"numNodes"` -} - -// MemcachedRSStatus defines the observed state of MemcachedRS -type MemcachedRSStatus struct { - // +operator-sdk:gen-csv:customresourcedefinitions.statusDescriptors=true - NodeList []string `json:"nodeList"` -} - -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -// MemcachedRS is the Schema for the memcachedrs API -// +kubebuilder:subresource:status -// +kubebuilder:resource:path=memcachedrs,scope=Namespaced -// +kubebuilder:storageversion -// +operator-sdk:gen-csv:customresourcedefinitions.displayName="MemcachedRS App" -type MemcachedRS struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec MemcachedRSSpec `json:"spec,omitempty"` - Status MemcachedRSStatus `json:"status,omitempty"` -} - -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -// MemcachedRSList contains a list of MemcachedRS -type MemcachedRSList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []MemcachedRS `json:"items"` -} diff --git a/internal/generate/testdata/go/static/basic.operator.yaml b/internal/generate/testdata/go/static/basic.operator.yaml new file mode 100644 index 00000000000..2d97140d3c0 --- /dev/null +++ b/internal/generate/testdata/go/static/basic.operator.yaml @@ -0,0 +1,258 @@ +apiVersion: v1 +kind: Namespace +metadata: + labels: + control-plane: controller-manager + name: memcached-operator-system +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.3.0 + creationTimestamp: null + name: memcacheds.cache.example.com +spec: + group: cache.example.com + names: + kind: Memcached + listKind: MemcachedList + plural: memcacheds + singular: memcached + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + description: Memcached is the Schema for the memcacheds API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: MemcachedSpec defines the desired state of Memcached + properties: + foo: + description: Foo is an example field of Memcached. Edit Memcached_types.go + to remove/update + type: string + type: object + status: + description: MemcachedStatus defines the observed state of Memcached + type: object + type: object + version: v1alpha1 + versions: + - name: v1alpha1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: memcached-operator-leader-election-role + namespace: memcached-operator-system +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - configmaps/status + verbs: + - get + - update + - patch +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + creationTimestamp: null + name: memcached-operator-manager-role +rules: +- apiGroups: + - cache.example.com + resources: + - memcacheds + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - cache.example.com + resources: + - memcacheds/status + verbs: + - get + - patch + - update +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: memcached-operator-proxy-role +rules: +- apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create +- apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: memcached-operator-metrics-reader +rules: +- nonResourceURLs: + - /metrics + verbs: + - get +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: memcached-operator-leader-election-rolebinding + namespace: memcached-operator-system +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: memcached-operator-leader-election-role +subjects: +- kind: ServiceAccount + name: default + namespace: memcached-operator-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: memcached-operator-manager-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: memcached-operator-manager-role +subjects: +- kind: ServiceAccount + name: default + namespace: memcached-operator-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: memcached-operator-proxy-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: memcached-operator-proxy-role +subjects: +- kind: ServiceAccount + name: default + namespace: memcached-operator-system +--- +apiVersion: v1 +kind: Service +metadata: + labels: + control-plane: controller-manager + name: memcached-operator-controller-manager-metrics-service + namespace: memcached-operator-system +spec: + ports: + - name: https + port: 8443 + targetPort: https + selector: + control-plane: controller-manager +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + control-plane: controller-manager + name: memcached-operator-controller-manager + namespace: memcached-operator-system +spec: + replicas: 1 + selector: + matchLabels: + control-plane: controller-manager + template: + metadata: + labels: + control-plane: controller-manager + spec: + containers: + - args: + - --secure-listen-address=0.0.0.0:8443 + - --upstream=http://127.0.0.1:8080/ + - --logtostderr=true + - --v=10 + image: gcr.io/kubebuilder/kube-rbac-proxy:v0.5.0 + name: kube-rbac-proxy + ports: + - containerPort: 8443 + name: https + - args: + - --metrics-addr=127.0.0.1:8080 + - --enable-leader-election + command: + - /manager + image: controller:latest + name: manager + resources: + limits: + cpu: 100m + memory: 30Mi + requests: + cpu: 100m + memory: 20Mi + terminationGracePeriodSeconds: 10 +--- +apiVersion: cache.example.com/v1alpha1 +kind: Memcached +metadata: + name: memcached-sample +spec: + foo: bar diff --git a/internal/generate/testdata/non-standard-layout/api/cache/v1alpha1/memcached_types.go b/internal/generate/testdata/non-standard-layout/api/cache/v1alpha1/memcached_types.go deleted file mode 100644 index 99b77521bf4..00000000000 --- a/internal/generate/testdata/non-standard-layout/api/cache/v1alpha1/memcached_types.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2020 The Operator-SDK Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v1alpha1 - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// MemcachedSpec defines the desired state of Memcached -type MemcachedSpec struct { - // Size is the size of the memcached deployment - // +operator-sdk:csv:customresourcedefinitions:type=spec - Size int32 `json:"size"` -} - -// MemcachedStatus defines the observed state of Memcached -type MemcachedStatus struct { - // Nodes are the names of the memcached pods - // +operator-sdk:csv:customresourcedefinitions:type=status - Nodes []string `json:"nodes"` -} - -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -// Memcached is the Schema for the memcacheds API -// +kubebuilder:subresource:status -// +kubebuilder:resource:path=memcacheds,scope=Namespaced -// +kubebuilder:storageversion -// +operator-sdk:csv:customresourcedefinitions:displayName="Memcached App Display Name" -type Memcached struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec MemcachedSpec `json:"spec,omitempty"` - Status MemcachedStatus `json:"status,omitempty"` -} - -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -// MemcachedList contains a list of Memcached -type MemcachedList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []Memcached `json:"items"` -} diff --git a/internal/generate/testdata/non-standard-layout/config/crds-with-core-types/foo.example.com_deployment_crd.yaml b/internal/generate/testdata/non-standard-layout/config/crds-with-core-types/foo.example.com_deployment_crd.yaml deleted file mode 100644 index 44f4065c8c5..00000000000 --- a/internal/generate/testdata/non-standard-layout/config/crds-with-core-types/foo.example.com_deployment_crd.yaml +++ /dev/null @@ -1,57 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: deployment.foo.example.com -spec: - group: foo.example.com - names: - kind: Deployment - listKind: DeploymentList - plural: deployments - singular: deployment - scope: Namespaced - subresources: - status: {} - validation: - openAPIV3Schema: - description: Schema for the deployments API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: DeploymentSpec defines the desired state of the Foo Deployment - properties: - size: - description: Size is the size of the Foo deployment nodes - format: int32 - type: integer - required: - - size - type: object - status: - description: DeploymentStatus defines the observed state of the Foo Deployment - properties: - nodes: - description: Nodes are the names of the Foo pods - items: - type: string - type: array - required: - - nodes - type: object - type: object - version: v1alpha1 - versions: - - name: v1alpha1 - served: true - storage: true diff --git a/internal/generate/testdata/non-standard-layout/config/crds-with-core-types/foo.example.com_v1alpha1_deployment_cr.yaml b/internal/generate/testdata/non-standard-layout/config/crds-with-core-types/foo.example.com_v1alpha1_deployment_cr.yaml deleted file mode 100644 index 1e7da7daf47..00000000000 --- a/internal/generate/testdata/non-standard-layout/config/crds-with-core-types/foo.example.com_v1alpha1_deployment_cr.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: foo.example.com/v1alpha1 -kind: Deployment -metadata: - name: example-foo-deployment -spec: - # Add fields here - size: 3 diff --git a/internal/generate/testdata/non-standard-layout/config/crds/cache.example.com_memcacheds_crd.yaml b/internal/generate/testdata/non-standard-layout/config/crds/cache.example.com_memcacheds_crd.yaml deleted file mode 100644 index 0109edbab9a..00000000000 --- a/internal/generate/testdata/non-standard-layout/config/crds/cache.example.com_memcacheds_crd.yaml +++ /dev/null @@ -1,57 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: memcacheds.cache.example.com -spec: - group: cache.example.com - names: - kind: Memcached - listKind: MemcachedList - plural: memcacheds - singular: memcached - scope: Namespaced - subresources: - status: {} - validation: - openAPIV3Schema: - description: Memcached is the Schema for the memcacheds API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: MemcachedSpec defines the desired state of Memcached - properties: - size: - description: Size is the size of the memcached deployment - format: int32 - type: integer - required: - - size - type: object - status: - description: MemcachedStatus defines the observed state of Memcached - properties: - nodes: - description: Nodes are the names of the memcached pods - items: - type: string - type: array - required: - - nodes - type: object - type: object - version: v1alpha1 - versions: - - name: v1alpha1 - served: true - storage: true diff --git a/internal/generate/testdata/non-standard-layout/config/crds/cache.example.com_v1alpha1_memcached_cr.yaml b/internal/generate/testdata/non-standard-layout/config/crds/cache.example.com_v1alpha1_memcached_cr.yaml deleted file mode 100644 index 2b8f17c3998..00000000000 --- a/internal/generate/testdata/non-standard-layout/config/crds/cache.example.com_v1alpha1_memcached_cr.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: cache.example.com/v1alpha1 -kind: Memcached -metadata: - name: example-memcached -spec: - # Add fields here - size: 3 diff --git a/internal/generate/testdata/non-standard-layout/config/operator.yaml b/internal/generate/testdata/non-standard-layout/config/operator.yaml deleted file mode 100644 index 8a00f16ad68..00000000000 --- a/internal/generate/testdata/non-standard-layout/config/operator.yaml +++ /dev/null @@ -1,32 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: memcached-operator -spec: - replicas: 1 - selector: - matchLabels: - name: memcached-operator - template: - metadata: - labels: - name: memcached-operator - spec: - serviceAccountName: memcached-operator - containers: - - name: memcached-operator - image: quay.io/example/memcached-operator:v0.0.3 - command: - - memcached-operator - imagePullPolicy: Never - env: - - name: WATCH_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: OPERATOR_NAME - value: memcached-operator diff --git a/internal/generate/testdata/non-standard-layout/config/role.yaml b/internal/generate/testdata/non-standard-layout/config/role.yaml deleted file mode 100644 index d1a2a04d0d0..00000000000 --- a/internal/generate/testdata/non-standard-layout/config/role.yaml +++ /dev/null @@ -1,61 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: memcached-operator -rules: -- apiGroups: - - "" - resources: - - pods - - services - - services/finalizers - - endpoints - - persistentvolumeclaims - - events - - configmaps - - secrets - verbs: - - '*' -- apiGroups: - - apps - resources: - - deployments - - daemonsets - - replicasets - - statefulsets - verbs: - - '*' -- apiGroups: - - monitoring.coreos.com - resources: - - servicemonitors - verbs: - - get - - create -- apiGroups: - - apps - resourceNames: - - memcached-operator - resources: - - deployments/finalizers - verbs: - - update -- apiGroups: - - "" - resources: - - pods - verbs: - - get -- apiGroups: - - apps - resources: - - replicasets - - deployments - verbs: - - get -- apiGroups: - - cache.example.com - resources: - - '*' - verbs: - - '*' diff --git a/internal/generate/testdata/non-standard-layout/config/role_binding.yaml b/internal/generate/testdata/non-standard-layout/config/role_binding.yaml deleted file mode 100644 index 322ecc9e6ac..00000000000 --- a/internal/generate/testdata/non-standard-layout/config/role_binding.yaml +++ /dev/null @@ -1,11 +0,0 @@ -kind: RoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: memcached-operator -subjects: -- kind: ServiceAccount - name: memcached-operator -roleRef: - kind: Role - name: memcached-operator - apiGroup: rbac.authorization.k8s.io diff --git a/internal/generate/testdata/non-standard-layout/config/service_account.yaml b/internal/generate/testdata/non-standard-layout/config/service_account.yaml deleted file mode 100644 index 8d58bc78322..00000000000 --- a/internal/generate/testdata/non-standard-layout/config/service_account.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - name: memcached-operator diff --git a/internal/generate/testdata/non-standard-layout/expected-catalog/olm-catalog/memcached-operator/0.0.1/memcached-operator.v0.0.1.clusterserviceversion.yaml b/internal/generate/testdata/non-standard-layout/expected-catalog/olm-catalog/memcached-operator/0.0.1/memcached-operator.v0.0.1.clusterserviceversion.yaml deleted file mode 100644 index 6c5a0b6a972..00000000000 --- a/internal/generate/testdata/non-standard-layout/expected-catalog/olm-catalog/memcached-operator/0.0.1/memcached-operator.v0.0.1.clusterserviceversion.yaml +++ /dev/null @@ -1,158 +0,0 @@ -apiVersion: operators.coreos.com/v1alpha1 -kind: ClusterServiceVersion -metadata: - annotations: - alm-examples: |- - [ - { - "apiVersion": "cache.example.com/v1alpha1", - "kind": "Memcached", - "metadata": { - "name": "example-memcached" - }, - "spec": { - "size": 3 - } - } - ] - capabilities: Basic Install - name: memcached-operator.v0.0.1 - namespace: placeholder -spec: - apiservicedefinitions: {} - customresourcedefinitions: - owned: - - description: Memcached is the Schema for the memcacheds API - displayName: Memcached App Display Name - kind: Memcached - name: memcacheds.cache.example.com - specDescriptors: - - description: Size is the size of the memcached deployment - displayName: Size - path: size - statusDescriptors: - - description: Nodes are the names of the memcached pods - displayName: Nodes - path: nodes - version: v1alpha1 - description: Memcached Operator description. TODO. - displayName: Memcached Operator - icon: - - base64data: "" - mediatype: "" - install: - spec: - deployments: - - name: memcached-operator - spec: - replicas: 1 - selector: - matchLabels: - name: memcached-operator - strategy: {} - template: - metadata: - labels: - name: memcached-operator - spec: - containers: - - command: - - memcached-operator - env: - - name: WATCH_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.annotations['olm.targetNamespaces'] - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: OPERATOR_NAME - value: memcached-operator - image: quay.io/example/memcached-operator:v0.0.3 - imagePullPolicy: Never - name: memcached-operator - resources: {} - serviceAccountName: memcached-operator - permissions: - - rules: - - apiGroups: - - "" - resources: - - pods - - services - - services/finalizers - - endpoints - - persistentvolumeclaims - - events - - configmaps - - secrets - verbs: - - '*' - - apiGroups: - - apps - resources: - - deployments - - daemonsets - - replicasets - - statefulsets - verbs: - - '*' - - apiGroups: - - monitoring.coreos.com - resources: - - servicemonitors - verbs: - - get - - create - - apiGroups: - - apps - resourceNames: - - memcached-operator - resources: - - deployments/finalizers - verbs: - - update - - apiGroups: - - "" - resources: - - pods - verbs: - - get - - apiGroups: - - apps - resources: - - replicasets - - deployments - verbs: - - get - - apiGroups: - - cache.example.com - resources: - - '*' - verbs: - - '*' - serviceAccountName: memcached-operator - strategy: deployment - installModes: - - supported: true - type: OwnNamespace - - supported: true - type: SingleNamespace - - supported: false - type: MultiNamespace - - supported: true - type: AllNamespaces - keywords: - - memcached-operator - links: - - name: Memcached Operator - url: https://memcached-operator.domain - maintainers: - - email: your@email.com - name: Maintainer Name - maturity: alpha - provider: - name: Provider Name - url: https://your.domain - version: 0.0.1 diff --git a/internal/generate/testdata/non-standard-layout/expected-catalog/olm-catalog/memcached-operator/0.0.3/memcached-operator.v0.0.3.clusterserviceversion.yaml b/internal/generate/testdata/non-standard-layout/expected-catalog/olm-catalog/memcached-operator/0.0.3/memcached-operator.v0.0.3.clusterserviceversion.yaml deleted file mode 100644 index 8d9dcde805d..00000000000 --- a/internal/generate/testdata/non-standard-layout/expected-catalog/olm-catalog/memcached-operator/0.0.3/memcached-operator.v0.0.3.clusterserviceversion.yaml +++ /dev/null @@ -1,159 +0,0 @@ -apiVersion: operators.coreos.com/v1alpha1 -kind: ClusterServiceVersion -metadata: - annotations: - alm-examples: |- - [ - { - "apiVersion": "cache.example.com/v1alpha1", - "kind": "Memcached", - "metadata": { - "name": "example-memcached" - }, - "spec": { - "size": 3 - } - } - ] - capabilities: Basic Install - name: memcached-operator.v0.0.3 - namespace: placeholder -spec: - apiservicedefinitions: {} - customresourcedefinitions: - owned: - - description: Memcached is the Schema for the memcacheds API - displayName: Memcached App Display Name - kind: Memcached - name: memcacheds.cache.example.com - specDescriptors: - - description: Size is the size of the memcached deployment - displayName: Size - path: size - statusDescriptors: - - description: Nodes are the names of the memcached pods - displayName: Nodes - path: nodes - version: v1alpha1 - description: Memcached Operator description. TODO. - displayName: Memcached Operator - icon: - - base64data: "" - mediatype: "" - install: - spec: - deployments: - - name: memcached-operator - spec: - replicas: 1 - selector: - matchLabels: - name: memcached-operator - strategy: {} - template: - metadata: - labels: - name: memcached-operator - spec: - containers: - - command: - - memcached-operator - env: - - name: WATCH_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.annotations['olm.targetNamespaces'] - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: OPERATOR_NAME - value: memcached-operator - image: quay.io/example/memcached-operator:v0.0.3 - imagePullPolicy: Never - name: memcached-operator - resources: {} - serviceAccountName: memcached-operator - permissions: - - rules: - - apiGroups: - - "" - resources: - - pods - - services - - services/finalizers - - endpoints - - persistentvolumeclaims - - events - - configmaps - - secrets - verbs: - - '*' - - apiGroups: - - apps - resources: - - deployments - - daemonsets - - replicasets - - statefulsets - verbs: - - '*' - - apiGroups: - - monitoring.coreos.com - resources: - - servicemonitors - verbs: - - get - - create - - apiGroups: - - apps - resourceNames: - - memcached-operator - resources: - - deployments/finalizers - verbs: - - update - - apiGroups: - - "" - resources: - - pods - verbs: - - get - - apiGroups: - - apps - resources: - - replicasets - - deployments - verbs: - - get - - apiGroups: - - cache.example.com - resources: - - '*' - verbs: - - '*' - serviceAccountName: memcached-operator - strategy: deployment - installModes: - - supported: true - type: OwnNamespace - - supported: true - type: SingleNamespace - - supported: false - type: MultiNamespace - - supported: true - type: AllNamespaces - keywords: - - FooBar - - These keywords must be preserved in the CSV update tests from 0.0.3 to 0.0.4 - links: - - name: Memcached Operator - url: https://memcached-operator.domain - maintainers: - - email: your@email.com - name: Maintainer Name - maturity: alpha - provider: - name: Provider Name - url: https://your.domain - version: 0.0.3 diff --git a/internal/generate/testdata/non-standard-layout/expected-catalog/olm-catalog/memcached-operator/0.0.4/memcached-operator.v0.0.4.clusterserviceversion.yaml b/internal/generate/testdata/non-standard-layout/expected-catalog/olm-catalog/memcached-operator/0.0.4/memcached-operator.v0.0.4.clusterserviceversion.yaml deleted file mode 100644 index 63f288cdb16..00000000000 --- a/internal/generate/testdata/non-standard-layout/expected-catalog/olm-catalog/memcached-operator/0.0.4/memcached-operator.v0.0.4.clusterserviceversion.yaml +++ /dev/null @@ -1,160 +0,0 @@ -apiVersion: operators.coreos.com/v1alpha1 -kind: ClusterServiceVersion -metadata: - annotations: - alm-examples: |- - [ - { - "apiVersion": "cache.example.com/v1alpha1", - "kind": "Memcached", - "metadata": { - "name": "example-memcached" - }, - "spec": { - "size": 3 - } - } - ] - capabilities: Basic Install - name: memcached-operator.v0.0.4 - namespace: placeholder -spec: - apiservicedefinitions: {} - customresourcedefinitions: - owned: - - description: Memcached is the Schema for the memcacheds API - displayName: Memcached App Display Name - kind: Memcached - name: memcacheds.cache.example.com - specDescriptors: - - description: Size is the size of the memcached deployment - displayName: Size - path: size - statusDescriptors: - - description: Nodes are the names of the memcached pods - displayName: Nodes - path: nodes - version: v1alpha1 - description: Memcached Operator description. TODO. - displayName: Memcached Operator - icon: - - base64data: "" - mediatype: "" - install: - spec: - deployments: - - name: memcached-operator - spec: - replicas: 1 - selector: - matchLabels: - name: memcached-operator - strategy: {} - template: - metadata: - labels: - name: memcached-operator - spec: - containers: - - command: - - memcached-operator - env: - - name: WATCH_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.annotations['olm.targetNamespaces'] - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: OPERATOR_NAME - value: memcached-operator - image: quay.io/example/memcached-operator:v0.0.3 - imagePullPolicy: Never - name: memcached-operator - resources: {} - serviceAccountName: memcached-operator - permissions: - - rules: - - apiGroups: - - "" - resources: - - pods - - services - - services/finalizers - - endpoints - - persistentvolumeclaims - - events - - configmaps - - secrets - verbs: - - '*' - - apiGroups: - - apps - resources: - - deployments - - daemonsets - - replicasets - - statefulsets - verbs: - - '*' - - apiGroups: - - monitoring.coreos.com - resources: - - servicemonitors - verbs: - - get - - create - - apiGroups: - - apps - resourceNames: - - memcached-operator - resources: - - deployments/finalizers - verbs: - - update - - apiGroups: - - "" - resources: - - pods - verbs: - - get - - apiGroups: - - apps - resources: - - replicasets - - deployments - verbs: - - get - - apiGroups: - - cache.example.com - resources: - - '*' - verbs: - - '*' - serviceAccountName: memcached-operator - strategy: deployment - installModes: - - supported: true - type: OwnNamespace - - supported: true - type: SingleNamespace - - supported: false - type: MultiNamespace - - supported: true - type: AllNamespaces - keywords: - - FooBar - - These keywords must be preserved in the CSV update tests from 0.0.3 to 0.0.4 - links: - - name: Memcached Operator - url: https://memcached-operator.domain - maintainers: - - email: your@email.com - name: Maintainer Name - maturity: alpha - provider: - name: Provider Name - url: https://your.domain - replaces: memcached-operator.v0.0.3 - version: 0.0.4 diff --git a/internal/generate/testdata/non-standard-layout/expected-catalog/olm-catalog/memcached-operator/memcached-operator.package.yaml b/internal/generate/testdata/non-standard-layout/expected-catalog/olm-catalog/memcached-operator/memcached-operator.package.yaml deleted file mode 100644 index 64d34201345..00000000000 --- a/internal/generate/testdata/non-standard-layout/expected-catalog/olm-catalog/memcached-operator/memcached-operator.package.yaml +++ /dev/null @@ -1,5 +0,0 @@ -channels: -- currentCSV: memcached-operator.v0.0.3 - name: stable -defaultChannel: stable -packageName: memcached-operator diff --git a/internal/generate/testdata/non-standard-layout/main.go b/internal/generate/testdata/non-standard-layout/main.go deleted file mode 100644 index 38dd16da61a..00000000000 --- a/internal/generate/testdata/non-standard-layout/main.go +++ /dev/null @@ -1,3 +0,0 @@ -package main - -func main() {} diff --git a/website/content/en/docs/cli/operator-sdk_generate_packagemanifests.md b/website/content/en/docs/cli/operator-sdk_generate_packagemanifests.md index 72600ab3b39..3ae2e037d6b 100644 --- a/website/content/en/docs/cli/operator-sdk_generate_packagemanifests.md +++ b/website/content/en/docs/cli/operator-sdk_generate_packagemanifests.md @@ -73,7 +73,7 @@ operator-sdk generate packagemanifests [flags] --output-dir string Directory in which to write package manifests -q, --quiet Run in quiet mode --stdout Write package to stdout - --update-crds Update CustomResoureDefinition manifests in this package (default true) + --update-objects Update non-CSV objects in this package, ex. CustomResoureDefinitions, Roles (default true) -v, --version string Semantic version of the packaged operator ```