Skip to content

Commit 3650515

Browse files
authored
Merge pull request #59347 from xenolinux/memcached_controller-example
OCPBUGS#12826: Update the memcached_controller.go file
2 parents 6c7c978 + dd62485 commit 3650515

File tree

1 file changed

+140
-137
lines changed

1 file changed

+140
-137
lines changed

modules/osdk-golang-implement-controller.adoc

Lines changed: 140 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -36,28 +36,29 @@ limitations under the License.
3636
package controllers
3737

3838
import (
39-
appsv1 "k8s.io/api/apps/v1"
40-
corev1 "k8s.io/api/core/v1"
41-
"k8s.io/apimachinery/pkg/api/errors"
42-
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
43-
"k8s.io/apimachinery/pkg/types"
44-
"reflect"
45-
46-
"context"
47-
48-
"github.com/go-logr/logr"
49-
"k8s.io/apimachinery/pkg/runtime"
50-
ctrl "sigs.k8s.io/controller-runtime"
51-
"sigs.k8s.io/controller-runtime/pkg/client"
52-
53-
cachev1alpha1 "github.com/example/memcached-operator/api/v1alpha1"
39+
appsv1 "k8s.io/api/apps/v1"
40+
corev1 "k8s.io/api/core/v1"
41+
"k8s.io/apimachinery/pkg/api/errors"
42+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
43+
"k8s.io/apimachinery/pkg/types"
44+
"reflect"
45+
46+
"context"
47+
48+
"github.com/go-logr/logr"
49+
"k8s.io/apimachinery/pkg/runtime"
50+
ctrl "sigs.k8s.io/controller-runtime"
51+
"sigs.k8s.io/controller-runtime/pkg/client"
52+
ctrllog "sigs.k8s.io/controller-runtime/pkg/log"
53+
54+
cachev1 "github.com/example-inc/memcached-operator/api/v1"
5455
)
5556

5657
// MemcachedReconciler reconciles a Memcached object
5758
type MemcachedReconciler struct {
58-
client.Client
59-
Log logr.Logger
60-
Scheme *runtime.Scheme
59+
client.Client
60+
Log logr.Logger
61+
Scheme *runtime.Scheme
6162
}
6263

6364
// +kubebuilder:rbac:groups=cache.example.com,resources=memcacheds,verbs=get;list;watch;create;update;patch;delete
@@ -76,142 +77,144 @@ type MemcachedReconciler struct {
7677
// For more details, check Reconcile and its Result here:
7778
// - https://pkg.go.dev/sigs.k8s.io/[email protected]/pkg/reconcile
7879
func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
79-
log := r.Log.WithValues("memcached", req.NamespacedName)
80-
81-
// Fetch the Memcached instance
82-
memcached := &cachev1alpha1.Memcached{}
83-
err := r.Get(ctx, req.NamespacedName, memcached)
84-
if err != nil {
85-
if errors.IsNotFound(err) {
86-
// Request object not found, could have been deleted after reconcile request.
87-
// Owned objects are automatically garbage collected. For additional cleanup logic use finalizers.
88-
// Return and don't requeue
89-
log.Info("Memcached resource not found. Ignoring since object must be deleted")
90-
return ctrl.Result{}, nil
91-
}
92-
// Error reading the object - requeue the request.
93-
log.Error(err, "Failed to get Memcached")
94-
return ctrl.Result{}, err
95-
}
96-
97-
// Check if the deployment already exists, if not create a new one
98-
found := &appsv1.Deployment{}
99-
err = r.Get(ctx, types.NamespacedName{Name: memcached.Name, Namespace: memcached.Namespace}, found)
100-
if err != nil && errors.IsNotFound(err) {
101-
// Define a new deployment
102-
dep := r.deploymentForMemcached(memcached)
103-
log.Info("Creating a new Deployment", "Deployment.Namespace", dep.Namespace, "Deployment.Name", dep.Name)
104-
err = r.Create(ctx, dep)
105-
if err != nil {
106-
log.Error(err, "Failed to create new Deployment", "Deployment.Namespace", dep.Namespace, "Deployment.Name", dep.Name)
107-
return ctrl.Result{}, err
108-
}
109-
// Deployment created successfully - return and requeue
110-
return ctrl.Result{Requeue: true}, nil
111-
} else if err != nil {
112-
log.Error(err, "Failed to get Deployment")
113-
return ctrl.Result{}, err
114-
}
115-
116-
// Ensure the deployment size is the same as the spec
117-
size := memcached.Spec.Size
118-
if *found.Spec.Replicas != size {
119-
found.Spec.Replicas = &size
120-
err = r.Update(ctx, found)
121-
if err != nil {
122-
log.Error(err, "Failed to update Deployment", "Deployment.Namespace", found.Namespace, "Deployment.Name", found.Name)
123-
return ctrl.Result{}, err
124-
}
125-
// Spec updated - return and requeue
126-
return ctrl.Result{Requeue: true}, nil
127-
}
128-
129-
// Update the Memcached status with the pod names
130-
// List the pods for this memcached's deployment
131-
podList := &corev1.PodList{}
132-
listOpts := []client.ListOption{
133-
client.InNamespace(memcached.Namespace),
134-
client.MatchingLabels(labelsForMemcached(memcached.Name)),
135-
}
136-
if err = r.List(ctx, podList, listOpts...); err != nil {
137-
log.Error(err, "Failed to list pods", "Memcached.Namespace", memcached.Namespace, "Memcached.Name", memcached.Name)
138-
return ctrl.Result{}, err
139-
}
140-
podNames := getPodNames(podList.Items)
141-
142-
// Update status.Nodes if needed
143-
if !reflect.DeepEqual(podNames, memcached.Status.Nodes) {
144-
memcached.Status.Nodes = podNames
145-
err := r.Status().Update(ctx, memcached)
146-
if err != nil {
147-
log.Error(err, "Failed to update Memcached status")
148-
return ctrl.Result{}, err
149-
}
150-
}
151-
152-
return ctrl.Result{}, nil
80+
//log := r.Log.WithValues("memcached", req.NamespacedName)
81+
log := ctrllog.FromContext(ctx)
82+
// Fetch the Memcached instance
83+
memcached := &cachev1.Memcached{}
84+
err := r.Get(ctx, req.NamespacedName, memcached)
85+
if err != nil {
86+
if errors.IsNotFound(err) {
87+
// Request object not found, could have been deleted after reconcile request.
88+
// Owned objects are automatically garbage collected. For additional cleanup logic use finalizers.
89+
// Return and don't requeue
90+
log.Info("Memcached resource not found. Ignoring since object must be deleted")
91+
return ctrl.Result{}, nil
92+
}
93+
// Error reading the object - requeue the request.
94+
log.Error(err, "Failed to get Memcached")
95+
return ctrl.Result{}, err
96+
}
97+
98+
// Check if the deployment already exists, if not create a new one
99+
found := &appsv1.Deployment{}
100+
err = r.Get(ctx, types.NamespacedName{Name: memcached.Name, Namespace: memcached.Namespace}, found)
101+
if err != nil && errors.IsNotFound(err) {
102+
// Define a new deployment
103+
dep := r.deploymentForMemcached(memcached)
104+
log.Info("Creating a new Deployment", "Deployment.Namespace", dep.Namespace, "Deployment.Name", dep.Name)
105+
err = r.Create(ctx, dep)
106+
if err != nil {
107+
log.Error(err, "Failed to create new Deployment", "Deployment.Namespace", dep.Namespace, "Deployment.Name", dep.Name)
108+
return ctrl.Result{}, err
109+
}
110+
// Deployment created successfully - return and requeue
111+
return ctrl.Result{Requeue: true}, nil
112+
} else if err != nil {
113+
log.Error(err, "Failed to get Deployment")
114+
return ctrl.Result{}, err
115+
}
116+
117+
// Ensure the deployment size is the same as the spec
118+
size := memcached.Spec.Size
119+
if *found.Spec.Replicas != size {
120+
found.Spec.Replicas = &size
121+
err = r.Update(ctx, found)
122+
if err != nil {
123+
log.Error(err, "Failed to update Deployment", "Deployment.Namespace", found.Namespace, "Deployment.Name", found.Name)
124+
return ctrl.Result{}, err
125+
}
126+
// Spec updated - return and requeue
127+
return ctrl.Result{Requeue: true}, nil
128+
}
129+
130+
// Update the Memcached status with the pod names
131+
// List the pods for this memcached's deployment
132+
podList := &corev1.PodList{}
133+
listOpts := []client.ListOption{
134+
client.InNamespace(memcached.Namespace),
135+
client.MatchingLabels(labelsForMemcached(memcached.Name)),
136+
}
137+
if err = r.List(ctx, podList, listOpts...); err != nil {
138+
log.Error(err, "Failed to list pods", "Memcached.Namespace", memcached.Namespace, "Memcached.Name", memcached.Name)
139+
return ctrl.Result{}, err
140+
}
141+
podNames := getPodNames(podList.Items)
142+
143+
// Update status.Nodes if needed
144+
if !reflect.DeepEqual(podNames, memcached.Status.Nodes) {
145+
memcached.Status.Nodes = podNames
146+
err := r.Status().Update(ctx, memcached)
147+
if err != nil {
148+
log.Error(err, "Failed to update Memcached status")
149+
return ctrl.Result{}, err
150+
}
151+
}
152+
153+
return ctrl.Result{}, nil
153154
}
154155

155156
// deploymentForMemcached returns a memcached Deployment object
156-
func (r *MemcachedReconciler) deploymentForMemcached(m *cachev1alpha1.Memcached) *appsv1.Deployment {
157-
ls := labelsForMemcached(m.Name)
158-
replicas := m.Spec.Size
159-
160-
dep := &appsv1.Deployment{
161-
ObjectMeta: metav1.ObjectMeta{
162-
Name: m.Name,
163-
Namespace: m.Namespace,
164-
},
165-
Spec: appsv1.DeploymentSpec{
166-
Replicas: &replicas,
167-
Selector: &metav1.LabelSelector{
168-
MatchLabels: ls,
169-
},
170-
Template: corev1.PodTemplateSpec{
171-
ObjectMeta: metav1.ObjectMeta{
172-
Labels: ls,
173-
},
174-
Spec: corev1.PodSpec{
175-
Containers: []corev1.Container{{
176-
Image: "memcached:1.4.36-alpine",
177-
Name: "memcached",
178-
Command: []string{"memcached", "-m=64", "-o", "modern", "-v"},
179-
Ports: []corev1.ContainerPort{{
180-
ContainerPort: 11211,
181-
Name: "memcached",
182-
}},
183-
}},
184-
},
185-
},
186-
},
187-
}
188-
// Set Memcached instance as the owner and controller
189-
ctrl.SetControllerReference(m, dep, r.Scheme)
190-
return dep
157+
func (r *MemcachedReconciler) deploymentForMemcached(m *cachev1.Memcached) *appsv1.Deployment {
158+
ls := labelsForMemcached(m.Name)
159+
replicas := m.Spec.Size
160+
161+
dep := &appsv1.Deployment{
162+
ObjectMeta: metav1.ObjectMeta{
163+
Name: m.Name,
164+
Namespace: m.Namespace,
165+
},
166+
Spec: appsv1.DeploymentSpec{
167+
Replicas: &replicas,
168+
Selector: &metav1.LabelSelector{
169+
MatchLabels: ls,
170+
},
171+
Template: corev1.PodTemplateSpec{
172+
ObjectMeta: metav1.ObjectMeta{
173+
Labels: ls,
174+
},
175+
Spec: corev1.PodSpec{
176+
Containers: []corev1.Container{{
177+
Image: "memcached:1.4.36-alpine",
178+
Name: "memcached",
179+
Command: []string{"memcached", "-m=64", "-o", "modern", "-v"},
180+
Ports: []corev1.ContainerPort{{
181+
ContainerPort: 11211,
182+
Name: "memcached",
183+
}},
184+
}},
185+
},
186+
},
187+
},
188+
}
189+
// Set Memcached instance as the owner and controller
190+
ctrl.SetControllerReference(m, dep, r.Scheme)
191+
return dep
191192
}
192193

193194
// labelsForMemcached returns the labels for selecting the resources
194195
// belonging to the given memcached CR name.
195196
func labelsForMemcached(name string) map[string]string {
196-
return map[string]string{"app": "memcached", "memcached_cr": name}
197+
return map[string]string{"app": "memcached", "memcached_cr": name}
197198
}
198199

199200
// getPodNames returns the pod names of the array of pods passed in
200201
func getPodNames(pods []corev1.Pod) []string {
201-
var podNames []string
202-
for _, pod := range pods {
203-
podNames = append(podNames, pod.Name)
204-
}
205-
return podNames
202+
var podNames []string
203+
for _, pod := range pods {
204+
podNames = append(podNames, pod.Name)
205+
}
206+
return podNames
206207
}
207208

208209
// SetupWithManager sets up the controller with the Manager.
209210
func (r *MemcachedReconciler) SetupWithManager(mgr ctrl.Manager) error {
210-
return ctrl.NewControllerManagedBy(mgr).
211-
For(&cachev1alpha1.Memcached{}).
212-
Owns(&appsv1.Deployment{}).
213-
Complete(r)
211+
return ctrl.NewControllerManagedBy(mgr).
212+
For(&cachev1.Memcached{}).
213+
Owns(&appsv1.Deployment{}).
214+
Complete(r)
214215
}
216+
217+
215218
----
216219
====
217220
+

0 commit comments

Comments
 (0)