Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

🐛 Fix the kubebuilder api creation when resource creation is set to false #1770

Merged
merged 1 commit into from
Nov 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions generate_testdata.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions pkg/plugin/v2/scaffolds/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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)
}
`
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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 {
Expand Down
9 changes: 7 additions & 2 deletions pkg/plugin/v2/scaffolds/internal/templates/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions pkg/plugin/v3/scaffolds/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,17 @@ 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

ControllerRuntimeVersion string

// WireResource defines the api resources are generated or not.
WireResource bool
}

// SetTemplateDefaults implements input.Template
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 }}
prafull01 marked this conversation as resolved.
Show resolved Hide resolved
Complete(r)
}
`
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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 {
Expand Down
9 changes: 7 additions & 2 deletions pkg/plugin/v3/scaffolds/internal/templates/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -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)
Expand Down
20 changes: 20 additions & 0 deletions testdata/project-v2-multigroup/config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
52 changes: 52 additions & 0 deletions testdata/project-v2-multigroup/controllers/apps/pod_controller.go
Original file line number Diff line number Diff line change
@@ -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)
}
76 changes: 76 additions & 0 deletions testdata/project-v2-multigroup/controllers/apps/suite_test.go
Original file line number Diff line number Diff line change
@@ -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())
})
Loading