Skip to content

Commit 41ce2a6

Browse files
🐛 (deployimage/v1-beta1): fix scaffold with multigroup and add optional plugins to multigroup sample to validate changes
1 parent be40047 commit 41ce2a6

35 files changed

+3512
-23
lines changed

pkg/plugins/golang/deploy-image/v1alpha1/scaffolds/api.go

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ func (s *apiScaffolder) Scaffold() error {
134134
if isGoV3 {
135135
defaultMainPath = "main.go"
136136
}
137-
if err := s.updateMainByAddingEventRecorder(isGoV3, defaultMainPath); err != nil {
137+
if err := s.updateMainByAddingEventRecorder(defaultMainPath); err != nil {
138138
return fmt.Errorf("error updating main.go: %v", err)
139139
}
140140

@@ -188,29 +188,16 @@ func (s *apiScaffolder) scaffoldCreateAPIFromPlugins(isLegacyLayout bool) error
188188
// TODO: replace this implementation by creating its own MainUpdater
189189
// which will have its own controller template which set the recorder so that we can use it
190190
// in the reconciliation to create an event inside for the finalizer
191-
func (s *apiScaffolder) updateMainByAddingEventRecorder(isGoV3 bool, defaultMainPath string) error {
192-
if isGoV3 {
193-
if err := util.InsertCode(
194-
defaultMainPath,
195-
fmt.Sprintf(
196-
`if err = (&controllers.%sReconciler{
191+
func (s *apiScaffolder) updateMainByAddingEventRecorder(defaultMainPath string) error {
192+
if err := util.InsertCode(
193+
defaultMainPath,
194+
fmt.Sprintf(
195+
`%sReconciler{
197196
Client: mgr.GetClient(),
198197
Scheme: mgr.GetScheme(),`, s.resource.Kind),
199-
fmt.Sprintf(recorderTemplate, strings.ToLower(s.resource.Kind)),
200-
); err != nil {
201-
return fmt.Errorf("error scaffolding event recorder in %s: %v", defaultMainPath, err)
202-
}
203-
} else {
204-
if err := util.InsertCode(
205-
defaultMainPath,
206-
fmt.Sprintf(
207-
`if err = (&controller.%sReconciler{
208-
Client: mgr.GetClient(),
209-
Scheme: mgr.GetScheme(),`, s.resource.Kind),
210-
fmt.Sprintf(recorderTemplate, strings.ToLower(s.resource.Kind)),
211-
); err != nil {
212-
return fmt.Errorf("error scaffolding event recorder in %s: %v", defaultMainPath, err)
213-
}
198+
fmt.Sprintf(recorderTemplate, strings.ToLower(s.resource.Kind)),
199+
); err != nil {
200+
return fmt.Errorf("error scaffolding event recorder in %s: %v", defaultMainPath, err)
214201
}
215202

216203
return nil

test/testdata/generate.sh

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,16 @@ function scaffold_test_project {
102102
$kb create api --version v1 --kind Lakers --controller=true --resource=true --make=false
103103
$kb create webhook --version v1 --kind Lakers --defaulting --programmatic-validation
104104
fi
105+
106+
# Call ALL optional plugins within multigroup layout to ensure that they can work within
107+
header_text 'Creating Memcached API with deploy-image plugin ...'
108+
$kb create api --group example.com --version v1alpha1 --kind Memcached --image=memcached:1.4.36-alpine --image-container-command="memcached,-m=64,-o,modern,-v" --image-container-port="11211" --run-as-user="1001" --plugins="deploy-image/v1-alpha" --make=false
109+
$kb create api --group example.com --version v1alpha1 --kind Busybox --image=busybox:1.28 --plugins="deploy-image/v1-alpha" --make=false
110+
header_text 'Creating Memcached webhook ...'
111+
$kb create webhook --group example.com --version v1alpha1 --kind Memcached --programmatic-validation
112+
113+
header_text 'Editing project with Grafana plugin ...'
114+
$kb edit --plugins=grafana.kubebuilder.io/v1-alpha
105115
elif [[ $project =~ declarative ]]; then
106116
header_text 'Creating APIs ...'
107117
$kb create api --group crew --version v1 --kind Captain --controller=true --resource=true --make=false
@@ -114,7 +124,7 @@ function scaffold_test_project {
114124
header_text 'Creating Memcached webhook ...'
115125
$kb create webhook --group example.com --version v1alpha1 --kind Memcached --programmatic-validation
116126
elif [[ $project =~ "with-grafana" ]]; then
117-
header_text 'Editing project with Grafana plugin ...'
127+
header_text 'Editing project with Grafana plugin ...'
118128
$kb edit --plugins=grafana.kubebuilder.io/v1-alpha
119129
fi
120130

testdata/project-v4-multigroup/PROJECT

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,25 @@ domain: testproject.org
66
layout:
77
- go.kubebuilder.io/v4
88
multigroup: true
9+
plugins:
10+
deploy-image.go.kubebuilder.io/v1-alpha:
11+
resources:
12+
- domain: testproject.org
13+
group: example.com
14+
kind: Memcached
15+
options:
16+
containerCommand: memcached,-m=64,-o,modern,-v
17+
containerPort: "11211"
18+
image: memcached:1.4.36-alpine
19+
runAsUser: "1001"
20+
version: v1alpha1
21+
- domain: testproject.org
22+
group: example.com
23+
kind: Busybox
24+
options:
25+
image: busybox:1.28
26+
version: v1alpha1
27+
grafana.kubebuilder.io/v1-alpha: {}
928
projectName: project-v4-multigroup
1029
repo: sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup
1130
resources:
@@ -118,4 +137,25 @@ resources:
118137
defaulting: true
119138
validation: true
120139
webhookVersion: v1
140+
- api:
141+
crdVersion: v1
142+
namespaced: true
143+
controller: true
144+
domain: testproject.org
145+
group: example.com
146+
kind: Memcached
147+
path: sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup/api/example.com/v1alpha1
148+
version: v1alpha1
149+
webhooks:
150+
validation: true
151+
webhookVersion: v1
152+
- api:
153+
crdVersion: v1
154+
namespaced: true
155+
controller: true
156+
domain: testproject.org
157+
group: example.com
158+
kind: Busybox
159+
path: sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup/api/example.com/v1alpha1
160+
version: v1alpha1
121161
version: "3"
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
Copyright 2023 The Kubernetes authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v1alpha1
18+
19+
import (
20+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
21+
)
22+
23+
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
24+
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
25+
26+
// BusyboxSpec defines the desired state of Busybox
27+
type BusyboxSpec struct {
28+
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
29+
// Important: Run "make" to regenerate code after modifying this file
30+
31+
// Size defines the number of Busybox instances
32+
// The following markers will use OpenAPI v3 schema to validate the value
33+
// More info: https://book.kubebuilder.io/reference/markers/crd-validation.html
34+
// +kubebuilder:validation:Minimum=1
35+
// +kubebuilder:validation:Maximum=3
36+
// +kubebuilder:validation:ExclusiveMaximum=false
37+
Size int32 `json:"size,omitempty"`
38+
}
39+
40+
// BusyboxStatus defines the observed state of Busybox
41+
type BusyboxStatus struct {
42+
// Represents the observations of a Busybox's current state.
43+
// Busybox.status.conditions.type are: "Available", "Progressing", and "Degraded"
44+
// Busybox.status.conditions.status are one of True, False, Unknown.
45+
// Busybox.status.conditions.reason the value should be a CamelCase string and producers of specific
46+
// condition types may define expected values and meanings for this field, and whether the values
47+
// are considered a guaranteed API.
48+
// Busybox.status.conditions.Message is a human readable message indicating details about the transition.
49+
// For further information see: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties
50+
51+
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"`
52+
}
53+
54+
//+kubebuilder:object:root=true
55+
//+kubebuilder:subresource:status
56+
57+
// Busybox is the Schema for the busyboxes API
58+
type Busybox struct {
59+
metav1.TypeMeta `json:",inline"`
60+
metav1.ObjectMeta `json:"metadata,omitempty"`
61+
62+
Spec BusyboxSpec `json:"spec,omitempty"`
63+
Status BusyboxStatus `json:"status,omitempty"`
64+
}
65+
66+
//+kubebuilder:object:root=true
67+
68+
// BusyboxList contains a list of Busybox
69+
type BusyboxList struct {
70+
metav1.TypeMeta `json:",inline"`
71+
metav1.ListMeta `json:"metadata,omitempty"`
72+
Items []Busybox `json:"items"`
73+
}
74+
75+
func init() {
76+
SchemeBuilder.Register(&Busybox{}, &BusyboxList{})
77+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
Copyright 2023 The Kubernetes authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
// Package v1alpha1 contains API Schema definitions for the example.com v1alpha1 API group
18+
// +kubebuilder:object:generate=true
19+
// +groupName=example.com.testproject.org
20+
package v1alpha1
21+
22+
import (
23+
"k8s.io/apimachinery/pkg/runtime/schema"
24+
"sigs.k8s.io/controller-runtime/pkg/scheme"
25+
)
26+
27+
var (
28+
// GroupVersion is group version used to register these objects
29+
GroupVersion = schema.GroupVersion{Group: "example.com.testproject.org", Version: "v1alpha1"}
30+
31+
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
32+
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
33+
34+
// AddToScheme adds the types in this group-version to the given scheme.
35+
AddToScheme = SchemeBuilder.AddToScheme
36+
)
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
Copyright 2023 The Kubernetes authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v1alpha1
18+
19+
import (
20+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
21+
)
22+
23+
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
24+
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
25+
26+
// MemcachedSpec defines the desired state of Memcached
27+
type MemcachedSpec struct {
28+
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
29+
// Important: Run "make" to regenerate code after modifying this file
30+
31+
// Size defines the number of Memcached instances
32+
// The following markers will use OpenAPI v3 schema to validate the value
33+
// More info: https://book.kubebuilder.io/reference/markers/crd-validation.html
34+
// +kubebuilder:validation:Minimum=1
35+
// +kubebuilder:validation:Maximum=3
36+
// +kubebuilder:validation:ExclusiveMaximum=false
37+
Size int32 `json:"size,omitempty"`
38+
39+
// Port defines the port that will be used to init the container with the image
40+
ContainerPort int32 `json:"containerPort,omitempty"`
41+
}
42+
43+
// MemcachedStatus defines the observed state of Memcached
44+
type MemcachedStatus struct {
45+
// Represents the observations of a Memcached's current state.
46+
// Memcached.status.conditions.type are: "Available", "Progressing", and "Degraded"
47+
// Memcached.status.conditions.status are one of True, False, Unknown.
48+
// Memcached.status.conditions.reason the value should be a CamelCase string and producers of specific
49+
// condition types may define expected values and meanings for this field, and whether the values
50+
// are considered a guaranteed API.
51+
// Memcached.status.conditions.Message is a human readable message indicating details about the transition.
52+
// For further information see: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties
53+
54+
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"`
55+
}
56+
57+
//+kubebuilder:object:root=true
58+
//+kubebuilder:subresource:status
59+
60+
// Memcached is the Schema for the memcacheds API
61+
type Memcached struct {
62+
metav1.TypeMeta `json:",inline"`
63+
metav1.ObjectMeta `json:"metadata,omitempty"`
64+
65+
Spec MemcachedSpec `json:"spec,omitempty"`
66+
Status MemcachedStatus `json:"status,omitempty"`
67+
}
68+
69+
//+kubebuilder:object:root=true
70+
71+
// MemcachedList contains a list of Memcached
72+
type MemcachedList struct {
73+
metav1.TypeMeta `json:",inline"`
74+
metav1.ListMeta `json:"metadata,omitempty"`
75+
Items []Memcached `json:"items"`
76+
}
77+
78+
func init() {
79+
SchemeBuilder.Register(&Memcached{}, &MemcachedList{})
80+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
Copyright 2023 The Kubernetes authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v1alpha1
18+
19+
import (
20+
"k8s.io/apimachinery/pkg/runtime"
21+
ctrl "sigs.k8s.io/controller-runtime"
22+
logf "sigs.k8s.io/controller-runtime/pkg/log"
23+
"sigs.k8s.io/controller-runtime/pkg/webhook"
24+
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
25+
)
26+
27+
// log is for logging in this package.
28+
var memcachedlog = logf.Log.WithName("memcached-resource")
29+
30+
func (r *Memcached) SetupWebhookWithManager(mgr ctrl.Manager) error {
31+
return ctrl.NewWebhookManagedBy(mgr).
32+
For(r).
33+
Complete()
34+
}
35+
36+
// TODO(user): EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
37+
38+
// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation.
39+
//+kubebuilder:webhook:path=/validate-example-com-testproject-org-v1alpha1-memcached,mutating=false,failurePolicy=fail,sideEffects=None,groups=example.com.testproject.org,resources=memcacheds,verbs=create;update,versions=v1alpha1,name=vmemcached.kb.io,admissionReviewVersions=v1
40+
41+
var _ webhook.Validator = &Memcached{}
42+
43+
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
44+
func (r *Memcached) ValidateCreate() (admission.Warnings, error) {
45+
memcachedlog.Info("validate create", "name", r.Name)
46+
47+
// TODO(user): fill in your validation logic upon object creation.
48+
return nil, nil
49+
}
50+
51+
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
52+
func (r *Memcached) ValidateUpdate(old runtime.Object) (admission.Warnings, error) {
53+
memcachedlog.Info("validate update", "name", r.Name)
54+
55+
// TODO(user): fill in your validation logic upon object update.
56+
return nil, nil
57+
}
58+
59+
// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
60+
func (r *Memcached) ValidateDelete() (admission.Warnings, error) {
61+
memcachedlog.Info("validate delete", "name", r.Name)
62+
63+
// TODO(user): fill in your validation logic upon object deletion.
64+
return nil, nil
65+
}

0 commit comments

Comments
 (0)