From 0e44410c3458924ae594d531244e90263017eae4 Mon Sep 17 00:00:00 2001 From: prafull01 Date: Tue, 3 Nov 2020 18:12:53 +0530 Subject: [PATCH] :bug: Fix the kubebuilder api creation when resource creation is set to false --- generate_testdata.sh | 2 + pkg/plugin/v2/scaffolds/api.go | 4 +- .../templates/controller/controller.go | 11 +++ .../controller/controller_suitetest.go | 12 ++- .../v2/scaffolds/internal/templates/main.go | 9 ++- pkg/plugin/v3/scaffolds/api.go | 4 +- .../templates/config/controller/controller.go | 11 +++ .../config/controller/controller_suitetest.go | 12 ++- .../v3/scaffolds/internal/templates/main.go | 9 ++- .../config/rbac/role.yaml | 20 +++++ .../controllers/apps/pod_controller.go | 52 +++++++++++++ .../controllers/apps/suite_test.go | 76 +++++++++++++++++++ testdata/project-v2-multigroup/main.go | 9 +++ testdata/project-v2/config/rbac/role.yaml | 20 +++++ .../controllers/laker_controller.go | 52 +++++++++++++ testdata/project-v2/main.go | 8 ++ .../config/rbac/role.yaml | 26 +++++++ .../controllers/apps/pod_controller.go | 63 +++++++++++++++ .../controllers/apps/suite_test.go | 76 +++++++++++++++++++ testdata/project-v3-multigroup/main.go | 9 +++ testdata/project-v3/config/rbac/role.yaml | 26 +++++++ .../controllers/laker_controller.go | 63 +++++++++++++++ testdata/project-v3/main.go | 8 ++ 23 files changed, 570 insertions(+), 12 deletions(-) create mode 100644 testdata/project-v2-multigroup/controllers/apps/pod_controller.go create mode 100644 testdata/project-v2-multigroup/controllers/apps/suite_test.go create mode 100644 testdata/project-v2/controllers/laker_controller.go create mode 100644 testdata/project-v3-multigroup/controllers/apps/pod_controller.go create mode 100644 testdata/project-v3-multigroup/controllers/apps/suite_test.go create mode 100644 testdata/project-v3/controllers/laker_controller.go diff --git a/generate_testdata.sh b/generate_testdata.sh index 542cda6ec96..b2b90495e45 100755 --- a/generate_testdata.sh +++ b/generate_testdata.sh @@ -65,6 +65,7 @@ scaffold_test_project() { $kb create webhook --group crew --version v1 --kind FirstMate --conversion $kb create api --group crew --version v1 --kind Admiral --controller=true --resource=true --namespaced=false --make=false $kb create webhook --group crew --version v1 --kind Admiral --defaulting + $kb create api --group crew --version v1 --kind Laker --controller=true --resource=false --make=false elif [ $project == "project-v2-multigroup" ] || [ $project == "project-v3-multigroup" ]; then header_text 'Switching to multigroup layout ...' $kb edit --multigroup=true @@ -81,6 +82,7 @@ scaffold_test_project() { $kb create api --group sea-creatures --version v1beta1 --kind Kraken --controller=true --resource=true --make=false $kb create api --group sea-creatures --version v1beta2 --kind Leviathan --controller=true --resource=true --make=false $kb create api --group foo.policy --version v1 --kind HealthCheckPolicy --controller=true --resource=true --make=false + $kb create api --group apps --version v1 --kind Pod --controller=true --resource=false --make=false if [ $project == "project-v3-multigroup" ]; then $kb create api --version v1 --kind Lakers --controller=true --resource=true --make=false $kb create webhook --version v1 --kind Lakers --defaulting --programmatic-validation diff --git a/pkg/plugin/v2/scaffolds/api.go b/pkg/plugin/v2/scaffolds/api.go index 6efac7c55df..a9cd80dba7f 100644 --- a/pkg/plugin/v2/scaffolds/api.go +++ b/pkg/plugin/v2/scaffolds/api.go @@ -117,8 +117,8 @@ func (s *apiScaffolder) scaffold() error { if s.doController { if err := machinery.NewScaffold(s.plugins...).Execute( s.newUniverse(), - &controller.SuiteTest{}, - &controller.Controller{}, + &controller.SuiteTest{WireResource: s.doResource}, + &controller.Controller{WireResource: s.doResource}, ); err != nil { return fmt.Errorf("error scaffolding controller: %v", err) } diff --git a/pkg/plugin/v2/scaffolds/internal/templates/controller/controller.go b/pkg/plugin/v2/scaffolds/internal/templates/controller/controller.go index 93c19a904ad..10a79fc0701 100644 --- a/pkg/plugin/v2/scaffolds/internal/templates/controller/controller.go +++ b/pkg/plugin/v2/scaffolds/internal/templates/controller/controller.go @@ -26,11 +26,15 @@ import ( var _ file.Template = &Controller{} // Controller scaffolds a Controller for a Resource +// nolint:maligned type Controller struct { file.TemplateMixin file.MultiGroupMixin file.BoilerplateMixin file.ResourceMixin + + // WireResource defines the api resources are generated or not. + WireResource bool } // SetTemplateDefaults implements input.Template @@ -63,7 +67,9 @@ import ( "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" + {{ if .WireResource -}} {{ .Resource.ImportAlias }} "{{ .Resource.Package }}" + {{- end }} ) // {{ .Resource.Kind }}Reconciler reconciles a {{ .Resource.Kind }} object @@ -87,7 +93,12 @@ func (r *{{ .Resource.Kind }}Reconciler) Reconcile(req ctrl.Request) (ctrl.Resul func (r *{{ .Resource.Kind }}Reconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). + {{ if .WireResource -}} For(&{{ .Resource.ImportAlias }}.{{ .Resource.Kind }}{}). + {{- else -}} + // Uncomment the following line adding a pointer to an instance of the controlled resource as an argument + // For(). + {{- end }} Complete(r) } ` diff --git a/pkg/plugin/v2/scaffolds/internal/templates/controller/controller_suitetest.go b/pkg/plugin/v2/scaffolds/internal/templates/controller/controller_suitetest.go index 80913f122c2..92fcd1c4c13 100644 --- a/pkg/plugin/v2/scaffolds/internal/templates/controller/controller_suitetest.go +++ b/pkg/plugin/v2/scaffolds/internal/templates/controller/controller_suitetest.go @@ -27,6 +27,7 @@ var _ file.Template = &SuiteTest{} var _ file.Inserter = &SuiteTest{} // SuiteTest scaffolds the suite_test.go file to setup the controller test +// nolint:maligned type SuiteTest struct { file.TemplateMixin file.RepositoryMixin @@ -36,6 +37,9 @@ type SuiteTest struct { // CRDDirectoryRelativePath define the Path for the CRD when it is multigroup CRDDirectoryRelativePath string + + // WireResource defines the api resources are generated or not. + WireResource bool } // SetTemplateDefaults implements file.Template @@ -92,11 +96,15 @@ func (f *SuiteTest) GetCodeFragments() file.CodeFragmentsMap { // Generate import code fragments imports := make([]string, 0) - imports = append(imports, fmt.Sprintf(apiImportCodeFragment, f.Resource.ImportAlias, f.Resource.Package)) + if f.WireResource { + imports = append(imports, fmt.Sprintf(apiImportCodeFragment, f.Resource.ImportAlias, f.Resource.Package)) + } // Generate add scheme code fragments addScheme := make([]string, 0) - addScheme = append(addScheme, fmt.Sprintf(addschemeCodeFragment, f.Resource.ImportAlias)) + if f.WireResource { + addScheme = append(addScheme, fmt.Sprintf(addschemeCodeFragment, f.Resource.ImportAlias)) + } // Only store code fragments in the map if the slices are non-empty if len(imports) != 0 { diff --git a/pkg/plugin/v2/scaffolds/internal/templates/main.go b/pkg/plugin/v2/scaffolds/internal/templates/main.go index 8283f838b77..047fd266861 100644 --- a/pkg/plugin/v2/scaffolds/internal/templates/main.go +++ b/pkg/plugin/v2/scaffolds/internal/templates/main.go @@ -156,7 +156,10 @@ func (f *MainUpdater) GetCodeFragments() file.CodeFragmentsMap { // Generate import code fragments imports := make([]string, 0) - imports = append(imports, fmt.Sprintf(apiImportCodeFragment, f.Resource.ImportAlias, f.Resource.Package)) + if f.WireResource { + imports = append(imports, fmt.Sprintf(apiImportCodeFragment, f.Resource.ImportAlias, f.Resource.Package)) + } + if f.WireController { if !f.MultiGroup { imports = append(imports, fmt.Sprintf(controllerImportCodeFragment, f.Repo)) @@ -168,7 +171,9 @@ func (f *MainUpdater) GetCodeFragments() file.CodeFragmentsMap { // Generate add scheme code fragments addScheme := make([]string, 0) - addScheme = append(addScheme, fmt.Sprintf(addschemeCodeFragment, f.Resource.ImportAlias)) + if f.WireResource { + addScheme = append(addScheme, fmt.Sprintf(addschemeCodeFragment, f.Resource.ImportAlias)) + } // Generate setup code fragments setup := make([]string, 0) diff --git a/pkg/plugin/v3/scaffolds/api.go b/pkg/plugin/v3/scaffolds/api.go index 5e0fff0d721..8ee69f1d43c 100644 --- a/pkg/plugin/v3/scaffolds/api.go +++ b/pkg/plugin/v3/scaffolds/api.go @@ -111,8 +111,8 @@ func (s *apiScaffolder) scaffold() error { if s.doController { if err := machinery.NewScaffold(s.plugins...).Execute( s.newUniverse(), - &controller.SuiteTest{}, - &controller.Controller{ControllerRuntimeVersion: ControllerRuntimeVersion}, + &controller.SuiteTest{WireResource: s.doResource}, + &controller.Controller{ControllerRuntimeVersion: ControllerRuntimeVersion, WireResource: s.doResource}, ); err != nil { return fmt.Errorf("error scaffolding controller: %v", err) } diff --git a/pkg/plugin/v3/scaffolds/internal/templates/config/controller/controller.go b/pkg/plugin/v3/scaffolds/internal/templates/config/controller/controller.go index c2dd25bc423..a5898415ec1 100644 --- a/pkg/plugin/v3/scaffolds/internal/templates/config/controller/controller.go +++ b/pkg/plugin/v3/scaffolds/internal/templates/config/controller/controller.go @@ -26,6 +26,7 @@ import ( var _ file.Template = &Controller{} // Controller scaffolds a Controller for a Resource +// nolint:maligned type Controller struct { file.TemplateMixin file.MultiGroupMixin @@ -33,6 +34,9 @@ type Controller struct { file.ResourceMixin ControllerRuntimeVersion string + + // WireResource defines the api resources are generated or not. + WireResource bool } // SetTemplateDefaults implements input.Template @@ -69,7 +73,9 @@ import ( "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" + {{ if .WireResource -}} {{ .Resource.ImportAlias }} "{{ .Resource.Package }}" + {{- end }} ) // {{ .Resource.Kind }}Reconciler reconciles a {{ .Resource.Kind }} object @@ -104,7 +110,12 @@ func (r *{{ .Resource.Kind }}Reconciler) Reconcile(req ctrl.Request) (ctrl.Resul // SetupWithManager sets up the controller with the Manager. func (r *{{ .Resource.Kind }}Reconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). + {{ if .WireResource -}} For(&{{ .Resource.ImportAlias }}.{{ .Resource.Kind }}{}). + {{- else -}} + // Uncomment the following line adding a pointer to an instance of the controlled resource as an argument + // For(). + {{- end }} Complete(r) } ` diff --git a/pkg/plugin/v3/scaffolds/internal/templates/config/controller/controller_suitetest.go b/pkg/plugin/v3/scaffolds/internal/templates/config/controller/controller_suitetest.go index e0979d44eac..3d00988139e 100644 --- a/pkg/plugin/v3/scaffolds/internal/templates/config/controller/controller_suitetest.go +++ b/pkg/plugin/v3/scaffolds/internal/templates/config/controller/controller_suitetest.go @@ -27,6 +27,7 @@ var _ file.Template = &SuiteTest{} var _ file.Inserter = &SuiteTest{} // SuiteTest scaffolds the suite_test.go file to setup the controller test +// nolint:maligned type SuiteTest struct { file.TemplateMixin file.RepositoryMixin @@ -36,6 +37,9 @@ type SuiteTest struct { // CRDDirectoryRelativePath define the Path for the CRD when it is multigroup CRDDirectoryRelativePath string + + // WireResource defines the api resources are generated or not. + WireResource bool } // SetTemplateDefaults implements file.Template @@ -92,11 +96,15 @@ func (f *SuiteTest) GetCodeFragments() file.CodeFragmentsMap { // Generate import code fragments imports := make([]string, 0) - imports = append(imports, fmt.Sprintf(apiImportCodeFragment, f.Resource.ImportAlias, f.Resource.Package)) + if f.WireResource { + imports = append(imports, fmt.Sprintf(apiImportCodeFragment, f.Resource.ImportAlias, f.Resource.Package)) + } // Generate add scheme code fragments addScheme := make([]string, 0) - addScheme = append(addScheme, fmt.Sprintf(addschemeCodeFragment, f.Resource.ImportAlias)) + if f.WireResource { + addScheme = append(addScheme, fmt.Sprintf(addschemeCodeFragment, f.Resource.ImportAlias)) + } // Only store code fragments in the map if the slices are non-empty if len(imports) != 0 { diff --git a/pkg/plugin/v3/scaffolds/internal/templates/main.go b/pkg/plugin/v3/scaffolds/internal/templates/main.go index afd6728b341..f5b2114c668 100644 --- a/pkg/plugin/v3/scaffolds/internal/templates/main.go +++ b/pkg/plugin/v3/scaffolds/internal/templates/main.go @@ -150,7 +150,10 @@ func (f *MainUpdater) GetCodeFragments() file.CodeFragmentsMap { // Generate import code fragments imports := make([]string, 0) - imports = append(imports, fmt.Sprintf(apiImportCodeFragment, f.Resource.ImportAlias, f.Resource.Package)) + if f.WireResource { + imports = append(imports, fmt.Sprintf(apiImportCodeFragment, f.Resource.ImportAlias, f.Resource.Package)) + } + if f.WireController { if !f.MultiGroup || f.Resource.Group == "" { imports = append(imports, fmt.Sprintf(controllerImportCodeFragment, f.Repo)) @@ -162,7 +165,9 @@ func (f *MainUpdater) GetCodeFragments() file.CodeFragmentsMap { // Generate add scheme code fragments addScheme := make([]string, 0) - addScheme = append(addScheme, fmt.Sprintf(addschemeCodeFragment, f.Resource.ImportAlias)) + if f.WireResource { + addScheme = append(addScheme, fmt.Sprintf(addschemeCodeFragment, f.Resource.ImportAlias)) + } // Generate setup code fragments setup := make([]string, 0) diff --git a/testdata/project-v2-multigroup/config/rbac/role.yaml b/testdata/project-v2-multigroup/config/rbac/role.yaml index d1cb5d78124..aef6d389cee 100644 --- a/testdata/project-v2-multigroup/config/rbac/role.yaml +++ b/testdata/project-v2-multigroup/config/rbac/role.yaml @@ -6,6 +6,26 @@ metadata: creationTimestamp: null name: manager-role rules: +- apiGroups: + - apps + resources: + - pods + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - apps + resources: + - pods/status + verbs: + - get + - patch + - update - apiGroups: - crew.testproject.org resources: diff --git a/testdata/project-v2-multigroup/controllers/apps/pod_controller.go b/testdata/project-v2-multigroup/controllers/apps/pod_controller.go new file mode 100644 index 00000000000..0d854d7d32a --- /dev/null +++ b/testdata/project-v2-multigroup/controllers/apps/pod_controller.go @@ -0,0 +1,52 @@ +/* +Copyright 2020 The Kubernetes 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 controllers + +import ( + "context" + + "github.com/go-logr/logr" + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +// PodReconciler reconciles a Pod object +type PodReconciler struct { + client.Client + Log logr.Logger + Scheme *runtime.Scheme +} + +// +kubebuilder:rbac:groups=apps,resources=pods,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=apps,resources=pods/status,verbs=get;update;patch + +func (r *PodReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { + _ = context.Background() + _ = r.Log.WithValues("pod", req.NamespacedName) + + // your logic here + + return ctrl.Result{}, nil +} + +func (r *PodReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + // Uncomment the following line adding a pointer to an instance of the controlled resource as an argument + // For(). + Complete(r) +} diff --git a/testdata/project-v2-multigroup/controllers/apps/suite_test.go b/testdata/project-v2-multigroup/controllers/apps/suite_test.go new file mode 100644 index 00000000000..4026de841b5 --- /dev/null +++ b/testdata/project-v2-multigroup/controllers/apps/suite_test.go @@ -0,0 +1,76 @@ +/* +Copyright 2020 The Kubernetes 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 controllers + +import ( + "path/filepath" + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/envtest" + "sigs.k8s.io/controller-runtime/pkg/envtest/printer" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + // +kubebuilder:scaffold:imports +) + +// These tests use Ginkgo (BDD-style Go testing framework). Refer to +// http://onsi.github.io/ginkgo/ to learn more about Ginkgo. + +var cfg *rest.Config +var k8sClient client.Client +var testEnv *envtest.Environment + +func TestAPIs(t *testing.T) { + RegisterFailHandler(Fail) + + RunSpecsWithDefaultAndCustomReporters(t, + "Controller Suite", + []Reporter{printer.NewlineReporter{}}) +} + +var _ = BeforeSuite(func(done Done) { + logf.SetLogger(zap.LoggerTo(GinkgoWriter, true)) + + By("bootstrapping test environment") + testEnv = &envtest.Environment{ + CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, + } + + var err error + cfg, err = testEnv.Start() + Expect(err).ToNot(HaveOccurred()) + Expect(cfg).ToNot(BeNil()) + + // +kubebuilder:scaffold:scheme + + k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) + Expect(err).ToNot(HaveOccurred()) + Expect(k8sClient).ToNot(BeNil()) + + close(done) +}, 60) + +var _ = AfterSuite(func() { + By("tearing down the test environment") + err := testEnv.Stop() + Expect(err).ToNot(HaveOccurred()) +}) diff --git a/testdata/project-v2-multigroup/main.go b/testdata/project-v2-multigroup/main.go index c4572f3ffc0..3c7fb25a655 100644 --- a/testdata/project-v2-multigroup/main.go +++ b/testdata/project-v2-multigroup/main.go @@ -34,6 +34,7 @@ import ( shipv1 "sigs.k8s.io/kubebuilder/testdata/project-v2-multigroup/apis/ship/v1" shipv1beta1 "sigs.k8s.io/kubebuilder/testdata/project-v2-multigroup/apis/ship/v1beta1" shipv2alpha1 "sigs.k8s.io/kubebuilder/testdata/project-v2-multigroup/apis/ship/v2alpha1" + appscontroller "sigs.k8s.io/kubebuilder/testdata/project-v2-multigroup/controllers/apps" crewcontroller "sigs.k8s.io/kubebuilder/testdata/project-v2-multigroup/controllers/crew" foopolicycontroller "sigs.k8s.io/kubebuilder/testdata/project-v2-multigroup/controllers/foo.policy" seacreaturescontroller "sigs.k8s.io/kubebuilder/testdata/project-v2-multigroup/controllers/sea-creatures" @@ -154,6 +155,14 @@ func main() { setupLog.Error(err, "unable to create controller", "controller", "HealthCheckPolicy") os.Exit(1) } + if err = (&appscontroller.PodReconciler{ + Client: mgr.GetClient(), + Log: ctrl.Log.WithName("controllers").WithName("Pod"), + Scheme: mgr.GetScheme(), + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "Pod") + os.Exit(1) + } // +kubebuilder:scaffold:builder setupLog.Info("starting manager") diff --git a/testdata/project-v2/config/rbac/role.yaml b/testdata/project-v2/config/rbac/role.yaml index a1cd43c89d2..5048ab84fee 100644 --- a/testdata/project-v2/config/rbac/role.yaml +++ b/testdata/project-v2/config/rbac/role.yaml @@ -66,3 +66,23 @@ rules: - get - patch - update +- apiGroups: + - crew.testproject.org + resources: + - lakers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - crew.testproject.org + resources: + - lakers/status + verbs: + - get + - patch + - update diff --git a/testdata/project-v2/controllers/laker_controller.go b/testdata/project-v2/controllers/laker_controller.go new file mode 100644 index 00000000000..b445c35fec3 --- /dev/null +++ b/testdata/project-v2/controllers/laker_controller.go @@ -0,0 +1,52 @@ +/* +Copyright 2020 The Kubernetes 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 controllers + +import ( + "context" + + "github.com/go-logr/logr" + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +// LakerReconciler reconciles a Laker object +type LakerReconciler struct { + client.Client + Log logr.Logger + Scheme *runtime.Scheme +} + +// +kubebuilder:rbac:groups=crew.testproject.org,resources=lakers,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=crew.testproject.org,resources=lakers/status,verbs=get;update;patch + +func (r *LakerReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { + _ = context.Background() + _ = r.Log.WithValues("laker", req.NamespacedName) + + // your logic here + + return ctrl.Result{}, nil +} + +func (r *LakerReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + // Uncomment the following line adding a pointer to an instance of the controlled resource as an argument + // For(). + Complete(r) +} diff --git a/testdata/project-v2/main.go b/testdata/project-v2/main.go index 9f3a99aa5ce..221471f570d 100644 --- a/testdata/project-v2/main.go +++ b/testdata/project-v2/main.go @@ -103,6 +103,14 @@ func main() { setupLog.Error(err, "unable to create webhook", "webhook", "Admiral") os.Exit(1) } + if err = (&controllers.LakerReconciler{ + Client: mgr.GetClient(), + Log: ctrl.Log.WithName("controllers").WithName("Laker"), + Scheme: mgr.GetScheme(), + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "Laker") + os.Exit(1) + } // +kubebuilder:scaffold:builder setupLog.Info("starting manager") diff --git a/testdata/project-v3-multigroup/config/rbac/role.yaml b/testdata/project-v3-multigroup/config/rbac/role.yaml index c326e6efc24..cd19ad8560a 100644 --- a/testdata/project-v3-multigroup/config/rbac/role.yaml +++ b/testdata/project-v3-multigroup/config/rbac/role.yaml @@ -6,6 +6,32 @@ metadata: creationTimestamp: null name: manager-role rules: +- apiGroups: + - apps + resources: + - pods + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - apps + resources: + - pods/finalizers + verbs: + - update +- apiGroups: + - apps + resources: + - pods/status + verbs: + - get + - patch + - update - apiGroups: - crew.testproject.org resources: diff --git a/testdata/project-v3-multigroup/controllers/apps/pod_controller.go b/testdata/project-v3-multigroup/controllers/apps/pod_controller.go new file mode 100644 index 00000000000..66e6bd34812 --- /dev/null +++ b/testdata/project-v3-multigroup/controllers/apps/pod_controller.go @@ -0,0 +1,63 @@ +/* +Copyright 2020 The Kubernetes 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 apps + +import ( + "context" + + "github.com/go-logr/logr" + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +// PodReconciler reconciles a Pod object +type PodReconciler struct { + client.Client + Log logr.Logger + Scheme *runtime.Scheme +} + +// +kubebuilder:rbac:groups=apps,resources=pods,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=apps,resources=pods/status,verbs=get;update;patch +// +kubebuilder:rbac:groups=apps,resources=pods/finalizers,verbs=update + +// Reconcile is part of the main kubernetes reconciliation loop which aims to +// move the current state of the cluster closer to the desired state. +// TODO(user): Modify the Reconcile function to compare the state specified by +// the Pod object against the actual cluster state, and then +// perform operations to make the cluster state reflect the state specified by +// the user. +// +// For more details, check Reconcile and its Result here: +// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.6.3/pkg/reconcile +func (r *PodReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { + _ = context.Background() + _ = r.Log.WithValues("pod", req.NamespacedName) + + // your logic here + + return ctrl.Result{}, nil +} + +// SetupWithManager sets up the controller with the Manager. +func (r *PodReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + // Uncomment the following line adding a pointer to an instance of the controlled resource as an argument + // For(). + Complete(r) +} diff --git a/testdata/project-v3-multigroup/controllers/apps/suite_test.go b/testdata/project-v3-multigroup/controllers/apps/suite_test.go new file mode 100644 index 00000000000..2b7e6562d94 --- /dev/null +++ b/testdata/project-v3-multigroup/controllers/apps/suite_test.go @@ -0,0 +1,76 @@ +/* +Copyright 2020 The Kubernetes 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 apps + +import ( + "path/filepath" + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/envtest" + "sigs.k8s.io/controller-runtime/pkg/envtest/printer" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + // +kubebuilder:scaffold:imports +) + +// These tests use Ginkgo (BDD-style Go testing framework). Refer to +// http://onsi.github.io/ginkgo/ to learn more about Ginkgo. + +var cfg *rest.Config +var k8sClient client.Client +var testEnv *envtest.Environment + +func TestAPIs(t *testing.T) { + RegisterFailHandler(Fail) + + RunSpecsWithDefaultAndCustomReporters(t, + "Controller Suite", + []Reporter{printer.NewlineReporter{}}) +} + +var _ = BeforeSuite(func(done Done) { + logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) + + By("bootstrapping test environment") + testEnv = &envtest.Environment{ + CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, + } + + var err error + cfg, err = testEnv.Start() + Expect(err).ToNot(HaveOccurred()) + Expect(cfg).ToNot(BeNil()) + + // +kubebuilder:scaffold:scheme + + k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) + Expect(err).ToNot(HaveOccurred()) + Expect(k8sClient).ToNot(BeNil()) + + close(done) +}, 60) + +var _ = AfterSuite(func() { + By("tearing down the test environment") + err := testEnv.Stop() + Expect(err).ToNot(HaveOccurred()) +}) diff --git a/testdata/project-v3-multigroup/main.go b/testdata/project-v3-multigroup/main.go index 0e8f542e4cf..bb5f5ef3abb 100644 --- a/testdata/project-v3-multigroup/main.go +++ b/testdata/project-v3-multigroup/main.go @@ -39,6 +39,7 @@ import ( shipv2alpha1 "sigs.k8s.io/kubebuilder/testdata/project-v3-multigroup/apis/ship/v2alpha1" testprojectorgv1 "sigs.k8s.io/kubebuilder/testdata/project-v3-multigroup/apis/v1" "sigs.k8s.io/kubebuilder/testdata/project-v3-multigroup/controllers" + appscontrollers "sigs.k8s.io/kubebuilder/testdata/project-v3-multigroup/controllers/apps" crewcontrollers "sigs.k8s.io/kubebuilder/testdata/project-v3-multigroup/controllers/crew" foopolicycontrollers "sigs.k8s.io/kubebuilder/testdata/project-v3-multigroup/controllers/foo.policy" seacreaturescontrollers "sigs.k8s.io/kubebuilder/testdata/project-v3-multigroup/controllers/sea-creatures" @@ -165,6 +166,14 @@ func main() { setupLog.Error(err, "unable to create controller", "controller", "HealthCheckPolicy") os.Exit(1) } + if err = (&appscontrollers.PodReconciler{ + Client: mgr.GetClient(), + Log: ctrl.Log.WithName("controllers").WithName("apps").WithName("Pod"), + Scheme: mgr.GetScheme(), + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "Pod") + os.Exit(1) + } if err = (&controllers.LakersReconciler{ Client: mgr.GetClient(), Log: ctrl.Log.WithName("controllers").WithName("Lakers"), diff --git a/testdata/project-v3/config/rbac/role.yaml b/testdata/project-v3/config/rbac/role.yaml index 7afe06fb451..1d105256811 100644 --- a/testdata/project-v3/config/rbac/role.yaml +++ b/testdata/project-v3/config/rbac/role.yaml @@ -84,3 +84,29 @@ rules: - get - patch - update +- apiGroups: + - crew.testproject.org + resources: + - lakers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - crew.testproject.org + resources: + - lakers/finalizers + verbs: + - update +- apiGroups: + - crew.testproject.org + resources: + - lakers/status + verbs: + - get + - patch + - update diff --git a/testdata/project-v3/controllers/laker_controller.go b/testdata/project-v3/controllers/laker_controller.go new file mode 100644 index 00000000000..e70d28245ea --- /dev/null +++ b/testdata/project-v3/controllers/laker_controller.go @@ -0,0 +1,63 @@ +/* +Copyright 2020 The Kubernetes 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 controllers + +import ( + "context" + + "github.com/go-logr/logr" + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +// LakerReconciler reconciles a Laker object +type LakerReconciler struct { + client.Client + Log logr.Logger + Scheme *runtime.Scheme +} + +// +kubebuilder:rbac:groups=crew.testproject.org,resources=lakers,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=crew.testproject.org,resources=lakers/status,verbs=get;update;patch +// +kubebuilder:rbac:groups=crew.testproject.org,resources=lakers/finalizers,verbs=update + +// Reconcile is part of the main kubernetes reconciliation loop which aims to +// move the current state of the cluster closer to the desired state. +// TODO(user): Modify the Reconcile function to compare the state specified by +// the Laker object against the actual cluster state, and then +// perform operations to make the cluster state reflect the state specified by +// the user. +// +// For more details, check Reconcile and its Result here: +// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.6.3/pkg/reconcile +func (r *LakerReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { + _ = context.Background() + _ = r.Log.WithValues("laker", req.NamespacedName) + + // your logic here + + return ctrl.Result{}, nil +} + +// SetupWithManager sets up the controller with the Manager. +func (r *LakerReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + // Uncomment the following line adding a pointer to an instance of the controlled resource as an argument + // For(). + Complete(r) +} diff --git a/testdata/project-v3/main.go b/testdata/project-v3/main.go index 99e4bfa9d41..4488ab146e8 100644 --- a/testdata/project-v3/main.go +++ b/testdata/project-v3/main.go @@ -111,6 +111,14 @@ func main() { setupLog.Error(err, "unable to create webhook", "webhook", "Admiral") os.Exit(1) } + if err = (&controllers.LakerReconciler{ + Client: mgr.GetClient(), + Log: ctrl.Log.WithName("controllers").WithName("Laker"), + Scheme: mgr.GetScheme(), + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "Laker") + os.Exit(1) + } // +kubebuilder:scaffold:builder setupLog.Info("starting manager")