Skip to content

Commit aba89c5

Browse files
authored
Merge pull request #2817 from NikhilSharmaWe/envImage
✨deploy-image/v1alpha: add env var for storing the image name
2 parents 0a60a3a + bcd38ee commit aba89c5

File tree

9 files changed

+148
-17
lines changed

9 files changed

+148
-17
lines changed

pkg/machinery/funcmap.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ func DefaultFuncMap() template.FuncMap {
3030
return template.FuncMap{
3131
"title": cases.Title,
3232
"lower": strings.ToLower,
33+
"upper": strings.ToUpper,
3334
"isEmptyStr": isEmptyString,
3435
"hashFNV": hashFNV,
3536
}

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

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,14 @@ func (s *apiScaffolder) Scaffold() error {
109109
return fmt.Errorf("error updating main.go: %v", err)
110110
}
111111

112+
if err := s.updateManagerWithNewEnvKey(); err != nil {
113+
return fmt.Errorf("error updating config/manager/manager.yaml with env key: %v", err)
114+
}
115+
116+
if err := s.updateManagerWithNewEnvVar(); err != nil {
117+
return fmt.Errorf("error updating config/manager/manager.yaml with env var: %v", err)
118+
}
119+
112120
if err := scaffold.Execute(
113121
&samples.CRDSample{Port: s.port},
114122
); err != nil {
@@ -124,6 +132,30 @@ func (s *apiScaffolder) Scaffold() error {
124132
return nil
125133
}
126134

135+
func (s *apiScaffolder) updateManagerWithNewEnvKey() error {
136+
managerPath := filepath.Join("config", "manager", "manager.yaml")
137+
err := util.ReplaceInFile(managerPath, `env:`, `env:`)
138+
if err != nil {
139+
err := util.InsertCode(managerPath, `name: manager`, `
140+
env:`)
141+
if err != nil {
142+
return fmt.Errorf("error scaffolding env key in config/manager/manager.yaml")
143+
}
144+
}
145+
146+
return nil
147+
}
148+
149+
func (s *apiScaffolder) updateManagerWithNewEnvVar() error {
150+
managerPath := filepath.Join("config", "manager", "manager.yaml")
151+
err := util.InsertCode(managerPath, `env:`,
152+
fmt.Sprintf(envVarTemplate, strings.ToUpper(s.resource.Kind), s.image))
153+
if err != nil {
154+
return fmt.Errorf("error scaffolding env key in config/manager/manager.yaml")
155+
}
156+
return nil
157+
}
158+
127159
// TODO: replace this implementation by creating its own MainUpdater
128160
// which will have its own controller template which set the recorder
129161
func (s *apiScaffolder) updateMainEventRecorder() error {
@@ -148,8 +180,7 @@ func (s *apiScaffolder) scafffoldControllerWithImage(scaffold *machinery.Scaffol
148180

149181
controllerPath := controller.Path
150182
if err := util.ReplaceInFile(controllerPath, "//TODO: scaffold container",
151-
fmt.Sprintf(containerTemplate,
152-
s.image, // value for the image
183+
fmt.Sprintf(containerTemplate, // value for the image
153184
strings.ToLower(s.resource.Kind), // value for the name of the container
154185
),
155186
); err != nil {
@@ -234,7 +265,7 @@ func (s *apiScaffolder) scaffoldCreateAPIFromGolang() error {
234265
}
235266

236267
const containerTemplate = `Containers: []corev1.Container{{
237-
Image: "%s",
268+
Image: image,
238269
Name: "%s",
239270
ImagePullPolicy: corev1.PullIfNotPresent,
240271
// Ensure restrictive context for the container
@@ -265,3 +296,7 @@ const portTemplate = `
265296
const recorderTemplate = `
266297
Recorder: mgr.GetEventRecorderFor("%s-controller"),
267298
`
299+
300+
const envVarTemplate = `
301+
- name: %s_IMAGE
302+
value: %s`

pkg/plugins/golang/deploy-image/v1alpha1/scaffolds/internal/templates/controllers/controller.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ import (
7373
"context"
7474
"time"
7575
"fmt"
76+
"os"
7677
7778
"k8s.io/apimachinery/pkg/runtime"
7879
"k8s.io/client-go/tools/record"
@@ -185,7 +186,7 @@ func (r *{{ .Resource.Kind }}Reconciler) Reconcile(ctx context.Context, req ctrl
185186
err = r.Get(ctx, types.NamespacedName{Name: {{ lower .Resource.Kind }}.Name, Namespace: {{ lower .Resource.Kind }}.Namespace}, found)
186187
if err != nil && apierrors.IsNotFound(err) {
187188
// Define a new deployment
188-
dep := r.deploymentFor{{ .Resource.Kind }}({{ lower .Resource.Kind }})
189+
dep := r.deploymentFor{{ .Resource.Kind }}(ctx, {{ lower .Resource.Kind }})
189190
log.Info("Creating a new Deployment", "Deployment.Namespace", dep.Namespace, "Deployment.Name", dep.Name)
190191
err = r.Create(ctx, dep)
191192
if err != nil {
@@ -235,9 +236,14 @@ func (r *{{ .Resource.Kind }}Reconciler) doFinalizerOperationsFor{{ .Resource.Ki
235236
}
236237
237238
// deploymentFor{{ .Resource.Kind }} returns a {{ .Resource.Kind }} Deployment object
238-
func (r *{{ .Resource.Kind }}Reconciler) deploymentFor{{ .Resource.Kind }}({{ lower .Resource.Kind }} *{{ .Resource.ImportAlias }}.{{ .Resource.Kind }}) *appsv1.Deployment {
239+
func (r *{{ .Resource.Kind }}Reconciler) deploymentFor{{ .Resource.Kind }}(ctx context.Context, {{ lower .Resource.Kind }} *{{ .Resource.ImportAlias }}.{{ .Resource.Kind }}) *appsv1.Deployment {
239240
ls := labelsFor{{ .Resource.Kind }}({{ lower .Resource.Kind }}.Name)
240241
replicas := {{ lower .Resource.Kind }}.Spec.Size
242+
log := log.FromContext(ctx)
243+
image, err := imageFor{{ .Resource.Kind }}()
244+
if err != nil {
245+
log.Error(err, "unable to get image for {{ .Resource.Kind }}")
246+
}
241247
242248
dep := &appsv1.Deployment{
243249
ObjectMeta: metav1.ObjectMeta{
@@ -283,6 +289,17 @@ func labelsFor{{ .Resource.Kind }}(name string) map[string]string {
283289
return map[string]string{"type": "{{ lower .Resource.Kind }}", "{{ lower .Resource.Kind }}_cr": name}
284290
}
285291
292+
// imageFor{{ .Resource.Kind }} gets the image for the resources belonging to the given {{ .Resource.Kind }} CR,
293+
// from the {{ upper .Resource.Kind }}_IMAGE ENV VAR defined in the config/manager/manager.yaml
294+
func imageFor{{ .Resource.Kind }}() (string, error) {
295+
var imageEnvVar = "{{ upper .Resource.Kind }}_IMAGE"
296+
image, found := os.LookupEnv(imageEnvVar)
297+
if !found {
298+
return "", fmt.Errorf("%s must be set", imageEnvVar)
299+
}
300+
return image, nil
301+
}
302+
286303
// SetupWithManager sets up the controller with the Manager.
287304
// The following code specifies how the controller is built to watch a CR
288305
// and other resources that are owned and managed by that controller.

testdata/project-v3-with-deploy-image/config/manager/manager.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ spec:
4040
- --leader-elect
4141
image: controller:latest
4242
name: manager
43+
env:
44+
- name: BUSYBOX_IMAGE
45+
value: busybox:1.28
46+
- name: MEMCACHED_IMAGE
47+
value: memcached:1.4.36-alpine
4348
securityContext:
4449
allowPrivilegeEscalation: false
4550
capabilities:

testdata/project-v3-with-deploy-image/controllers/busybox_controller.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525

2626
"context"
2727
"fmt"
28+
"os"
2829
"time"
2930

3031
"k8s.io/apimachinery/pkg/runtime"
@@ -137,7 +138,7 @@ func (r *BusyboxReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
137138
err = r.Get(ctx, types.NamespacedName{Name: busybox.Name, Namespace: busybox.Namespace}, found)
138139
if err != nil && apierrors.IsNotFound(err) {
139140
// Define a new deployment
140-
dep := r.deploymentForBusybox(busybox)
141+
dep := r.deploymentForBusybox(ctx, busybox)
141142
log.Info("Creating a new Deployment", "Deployment.Namespace", dep.Namespace, "Deployment.Name", dep.Name)
142143
err = r.Create(ctx, dep)
143144
if err != nil {
@@ -187,9 +188,14 @@ func (r *BusyboxReconciler) doFinalizerOperationsForBusybox(cr *examplecomv1alph
187188
}
188189

189190
// deploymentForBusybox returns a Busybox Deployment object
190-
func (r *BusyboxReconciler) deploymentForBusybox(busybox *examplecomv1alpha1.Busybox) *appsv1.Deployment {
191+
func (r *BusyboxReconciler) deploymentForBusybox(ctx context.Context, busybox *examplecomv1alpha1.Busybox) *appsv1.Deployment {
191192
ls := labelsForBusybox(busybox.Name)
192193
replicas := busybox.Spec.Size
194+
log := log.FromContext(ctx)
195+
image, err := imageForBusybox()
196+
if err != nil {
197+
log.Error(err, "unable to get image for Busybox")
198+
}
193199

194200
dep := &appsv1.Deployment{
195201
ObjectMeta: metav1.ObjectMeta{
@@ -216,7 +222,7 @@ func (r *BusyboxReconciler) deploymentForBusybox(busybox *examplecomv1alpha1.Bus
216222
},
217223
},
218224
Containers: []corev1.Container{{
219-
Image: "busybox:1.28",
225+
Image: image,
220226
Name: "busybox",
221227
ImagePullPolicy: corev1.PullIfNotPresent,
222228
// Ensure restrictive context for the container
@@ -250,6 +256,17 @@ func labelsForBusybox(name string) map[string]string {
250256
return map[string]string{"type": "busybox", "busybox_cr": name}
251257
}
252258

259+
// imageForBusybox gets the image for the resources belonging to the given Busybox CR,
260+
// from the BUSYBOX_IMAGE ENV VAR defined in the config/manager/manager.yaml
261+
func imageForBusybox() (string, error) {
262+
var imageEnvVar = "BUSYBOX_IMAGE"
263+
image, found := os.LookupEnv(imageEnvVar)
264+
if !found {
265+
return "", fmt.Errorf("%s must be set", imageEnvVar)
266+
}
267+
return image, nil
268+
}
269+
253270
// SetupWithManager sets up the controller with the Manager.
254271
// The following code specifies how the controller is built to watch a CR
255272
// and other resources that are owned and managed by that controller.

testdata/project-v3-with-deploy-image/controllers/memcached_controller.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525

2626
"context"
2727
"fmt"
28+
"os"
2829
"time"
2930

3031
"k8s.io/apimachinery/pkg/runtime"
@@ -137,7 +138,7 @@ func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
137138
err = r.Get(ctx, types.NamespacedName{Name: memcached.Name, Namespace: memcached.Namespace}, found)
138139
if err != nil && apierrors.IsNotFound(err) {
139140
// Define a new deployment
140-
dep := r.deploymentForMemcached(memcached)
141+
dep := r.deploymentForMemcached(ctx, memcached)
141142
log.Info("Creating a new Deployment", "Deployment.Namespace", dep.Namespace, "Deployment.Name", dep.Name)
142143
err = r.Create(ctx, dep)
143144
if err != nil {
@@ -187,9 +188,14 @@ func (r *MemcachedReconciler) doFinalizerOperationsForMemcached(cr *examplecomv1
187188
}
188189

189190
// deploymentForMemcached returns a Memcached Deployment object
190-
func (r *MemcachedReconciler) deploymentForMemcached(memcached *examplecomv1alpha1.Memcached) *appsv1.Deployment {
191+
func (r *MemcachedReconciler) deploymentForMemcached(ctx context.Context, memcached *examplecomv1alpha1.Memcached) *appsv1.Deployment {
191192
ls := labelsForMemcached(memcached.Name)
192193
replicas := memcached.Spec.Size
194+
log := log.FromContext(ctx)
195+
image, err := imageForMemcached()
196+
if err != nil {
197+
log.Error(err, "unable to get image for Memcached")
198+
}
193199

194200
dep := &appsv1.Deployment{
195201
ObjectMeta: metav1.ObjectMeta{
@@ -216,7 +222,7 @@ func (r *MemcachedReconciler) deploymentForMemcached(memcached *examplecomv1alph
216222
},
217223
},
218224
Containers: []corev1.Container{{
219-
Image: "memcached:1.4.36-alpine",
225+
Image: image,
220226
Name: "memcached",
221227
ImagePullPolicy: corev1.PullIfNotPresent,
222228
// Ensure restrictive context for the container
@@ -256,6 +262,17 @@ func labelsForMemcached(name string) map[string]string {
256262
return map[string]string{"type": "memcached", "memcached_cr": name}
257263
}
258264

265+
// imageForMemcached gets the image for the resources belonging to the given Memcached CR,
266+
// from the MEMCACHED_IMAGE ENV VAR defined in the config/manager/manager.yaml
267+
func imageForMemcached() (string, error) {
268+
var imageEnvVar = "MEMCACHED_IMAGE"
269+
image, found := os.LookupEnv(imageEnvVar)
270+
if !found {
271+
return "", fmt.Errorf("%s must be set", imageEnvVar)
272+
}
273+
return image, nil
274+
}
275+
259276
// SetupWithManager sets up the controller with the Manager.
260277
// The following code specifies how the controller is built to watch a CR
261278
// and other resources that are owned and managed by that controller.

testdata/project-v4-with-deploy-image/config/manager/manager.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ spec:
4040
- --leader-elect
4141
image: controller:latest
4242
name: manager
43+
env:
44+
- name: BUSYBOX_IMAGE
45+
value: busybox:1.28
46+
- name: MEMCACHED_IMAGE
47+
value: memcached:1.4.36-alpine
4348
securityContext:
4449
allowPrivilegeEscalation: false
4550
capabilities:

testdata/project-v4-with-deploy-image/controllers/busybox_controller.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525

2626
"context"
2727
"fmt"
28+
"os"
2829
"time"
2930

3031
"k8s.io/apimachinery/pkg/runtime"
@@ -137,7 +138,7 @@ func (r *BusyboxReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
137138
err = r.Get(ctx, types.NamespacedName{Name: busybox.Name, Namespace: busybox.Namespace}, found)
138139
if err != nil && apierrors.IsNotFound(err) {
139140
// Define a new deployment
140-
dep := r.deploymentForBusybox(busybox)
141+
dep := r.deploymentForBusybox(ctx, busybox)
141142
log.Info("Creating a new Deployment", "Deployment.Namespace", dep.Namespace, "Deployment.Name", dep.Name)
142143
err = r.Create(ctx, dep)
143144
if err != nil {
@@ -187,9 +188,14 @@ func (r *BusyboxReconciler) doFinalizerOperationsForBusybox(cr *examplecomv1alph
187188
}
188189

189190
// deploymentForBusybox returns a Busybox Deployment object
190-
func (r *BusyboxReconciler) deploymentForBusybox(busybox *examplecomv1alpha1.Busybox) *appsv1.Deployment {
191+
func (r *BusyboxReconciler) deploymentForBusybox(ctx context.Context, busybox *examplecomv1alpha1.Busybox) *appsv1.Deployment {
191192
ls := labelsForBusybox(busybox.Name)
192193
replicas := busybox.Spec.Size
194+
log := log.FromContext(ctx)
195+
image, err := imageForBusybox()
196+
if err != nil {
197+
log.Error(err, "unable to get image for Busybox")
198+
}
193199

194200
dep := &appsv1.Deployment{
195201
ObjectMeta: metav1.ObjectMeta{
@@ -216,7 +222,7 @@ func (r *BusyboxReconciler) deploymentForBusybox(busybox *examplecomv1alpha1.Bus
216222
},
217223
},
218224
Containers: []corev1.Container{{
219-
Image: "busybox:1.28",
225+
Image: image,
220226
Name: "busybox",
221227
ImagePullPolicy: corev1.PullIfNotPresent,
222228
// Ensure restrictive context for the container
@@ -250,6 +256,17 @@ func labelsForBusybox(name string) map[string]string {
250256
return map[string]string{"type": "busybox", "busybox_cr": name}
251257
}
252258

259+
// imageForBusybox gets the image for the resources belonging to the given Busybox CR,
260+
// from the BUSYBOX_IMAGE ENV VAR defined in the config/manager/manager.yaml
261+
func imageForBusybox() (string, error) {
262+
var imageEnvVar = "BUSYBOX_IMAGE"
263+
image, found := os.LookupEnv(imageEnvVar)
264+
if !found {
265+
return "", fmt.Errorf("%s must be set", imageEnvVar)
266+
}
267+
return image, nil
268+
}
269+
253270
// SetupWithManager sets up the controller with the Manager.
254271
// The following code specifies how the controller is built to watch a CR
255272
// and other resources that are owned and managed by that controller.

testdata/project-v4-with-deploy-image/controllers/memcached_controller.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525

2626
"context"
2727
"fmt"
28+
"os"
2829
"time"
2930

3031
"k8s.io/apimachinery/pkg/runtime"
@@ -137,7 +138,7 @@ func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
137138
err = r.Get(ctx, types.NamespacedName{Name: memcached.Name, Namespace: memcached.Namespace}, found)
138139
if err != nil && apierrors.IsNotFound(err) {
139140
// Define a new deployment
140-
dep := r.deploymentForMemcached(memcached)
141+
dep := r.deploymentForMemcached(ctx, memcached)
141142
log.Info("Creating a new Deployment", "Deployment.Namespace", dep.Namespace, "Deployment.Name", dep.Name)
142143
err = r.Create(ctx, dep)
143144
if err != nil {
@@ -187,9 +188,14 @@ func (r *MemcachedReconciler) doFinalizerOperationsForMemcached(cr *examplecomv1
187188
}
188189

189190
// deploymentForMemcached returns a Memcached Deployment object
190-
func (r *MemcachedReconciler) deploymentForMemcached(memcached *examplecomv1alpha1.Memcached) *appsv1.Deployment {
191+
func (r *MemcachedReconciler) deploymentForMemcached(ctx context.Context, memcached *examplecomv1alpha1.Memcached) *appsv1.Deployment {
191192
ls := labelsForMemcached(memcached.Name)
192193
replicas := memcached.Spec.Size
194+
log := log.FromContext(ctx)
195+
image, err := imageForMemcached()
196+
if err != nil {
197+
log.Error(err, "unable to get image for Memcached")
198+
}
193199

194200
dep := &appsv1.Deployment{
195201
ObjectMeta: metav1.ObjectMeta{
@@ -216,7 +222,7 @@ func (r *MemcachedReconciler) deploymentForMemcached(memcached *examplecomv1alph
216222
},
217223
},
218224
Containers: []corev1.Container{{
219-
Image: "memcached:1.4.36-alpine",
225+
Image: image,
220226
Name: "memcached",
221227
ImagePullPolicy: corev1.PullIfNotPresent,
222228
// Ensure restrictive context for the container
@@ -256,6 +262,17 @@ func labelsForMemcached(name string) map[string]string {
256262
return map[string]string{"type": "memcached", "memcached_cr": name}
257263
}
258264

265+
// imageForMemcached gets the image for the resources belonging to the given Memcached CR,
266+
// from the MEMCACHED_IMAGE ENV VAR defined in the config/manager/manager.yaml
267+
func imageForMemcached() (string, error) {
268+
var imageEnvVar = "MEMCACHED_IMAGE"
269+
image, found := os.LookupEnv(imageEnvVar)
270+
if !found {
271+
return "", fmt.Errorf("%s must be set", imageEnvVar)
272+
}
273+
return image, nil
274+
}
275+
259276
// SetupWithManager sets up the controller with the Manager.
260277
// The following code specifies how the controller is built to watch a CR
261278
// and other resources that are owned and managed by that controller.

0 commit comments

Comments
 (0)