1
+ // Copyright 2018 The Operator-SDK Authors
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
1
15
package memcached
2
16
3
17
import (
@@ -6,6 +20,7 @@ import (
6
20
7
21
cachev1alpha1 "github.com/example-inc/memcached-operator/pkg/apis/cache/v1alpha1"
8
22
23
+ "github.com/operator-framework/operator-sdk/pkg/status"
9
24
appsv1 "k8s.io/api/apps/v1"
10
25
corev1 "k8s.io/api/core/v1"
11
26
"k8s.io/apimachinery/pkg/api/errors"
@@ -108,31 +123,48 @@ func (r *ReconcileMemcached) Reconcile(request reconcile.Request) (reconcile.Res
108
123
109
124
// Check if the deployment already exists, if not create a new one
110
125
found := &appsv1.Deployment{}
111
- err = r.client.Get(context.TODO(), types.NamespacedName{Name: memcached.Name, Namespace: memcached.Namespace}, found)
112
- if err != nil && errors.IsNotFound(err ) {
126
+ getErr : = r.client.Get(context.TODO(), types.NamespacedName{Name: memcached.Name, Namespace: memcached.Namespace}, found)
127
+ if getErr != nil && errors.IsNotFound(getErr ) {
113
128
// Define a new deployment
114
129
dep := r.deploymentForMemcached(memcached)
115
130
reqLogger.Info("Creating a new Deployment", "Deployment.Namespace", dep.Namespace, "Deployment.Name", dep.Name)
116
- err = r.client.Create(context.TODO(), dep)
117
- if err != nil {
118
- reqLogger.Error(err, "Failed to create new Deployment", "Deployment.Namespace", dep.Namespace, "Deployment.Name", dep.Name)
119
- return reconcile.Result{}, err
131
+ if createErr := r.client.Create(context.TODO(), dep); createErr != nil {
132
+ reqLogger.Error(createErr, "Failed to create new Deployment", "Deployment.Namespace", dep.Namespace, "Deployment.Name", dep.Name)
133
+
134
+ // Update status not ready
135
+ if setStatusErr := r.setStatusNotReady(memcached, createErr); setStatusErr != nil {
136
+ return reconcile.Result{}, setStatusErr
137
+ }
138
+ return reconcile.Result{}, createErr
139
+ }
140
+ // Update status not ready
141
+ if setStatusErr := r.setStatusNotReady(memcached, getErr); setStatusErr != nil {
142
+ return reconcile.Result{}, setStatusErr
120
143
}
121
144
// Deployment created successfully - return and requeue
122
145
return reconcile.Result{Requeue: true}, nil
123
- } else if err != nil {
124
- reqLogger.Error(err, "Failed to get Deployment")
146
+ } else if getErr != nil {
147
+ reqLogger.Error(getErr, "Failed to get Deployment")
148
+
149
+ // Update status not ready
150
+ if setStatusErr := r.setStatusNotReady(memcached, getErr); setStatusErr != nil {
151
+ return reconcile.Result{}, setStatusErr
152
+ }
125
153
return reconcile.Result{}, err
126
154
}
127
155
128
156
// Ensure the deployment size is the same as the spec
129
157
size := memcached.Spec.Size
130
158
if *found.Spec.Replicas != size {
131
159
found.Spec.Replicas = &size
132
- err = r.client.Update(context.TODO(), found)
133
- if err != nil {
134
- reqLogger.Error(err, "Failed to update Deployment", "Deployment.Namespace", found.Namespace, "Deployment.Name", found.Name)
135
- return reconcile.Result{}, err
160
+ if updateErr := r.client.Update(context.TODO(), found); updateErr != nil {
161
+ reqLogger.Error(updateErr, "Failed to update Deployment", "Deployment.Namespace", found.Namespace, "Deployment.Name", found.Name)
162
+
163
+ // Update status not ready
164
+ if setStatusErr := r.setStatusNotReady(memcached, updateErr); setStatusErr != nil {
165
+ return reconcile.Result{}, setStatusErr
166
+ }
167
+ return reconcile.Result{}, updateErr
136
168
}
137
169
// Spec updated - return and requeue
138
170
return reconcile.Result{Requeue: true}, nil
@@ -153,13 +185,18 @@ func (r *ReconcileMemcached) Reconcile(request reconcile.Request) (reconcile.Res
153
185
// Update status.Nodes if needed
154
186
if !reflect.DeepEqual(podNames, memcached.Status.Nodes) {
155
187
memcached.Status.Nodes = podNames
156
- err := r.client.Status().Update(context.TODO(), memcached)
188
+ err := r.updateStatus( memcached)
157
189
if err != nil {
158
190
reqLogger.Error(err, "Failed to update Memcached status")
159
191
return reconcile.Result{}, err
160
192
}
161
193
}
162
194
195
+ // Set the Memcached status Ready condition to True, if necessary
196
+ if setStatusErr := r.setStatusReady(memcached); setStatusErr != nil {
197
+ return reconcile.Result{}, setStatusErr
198
+ }
199
+
163
200
return reconcile.Result{}, nil
164
201
}
165
202
@@ -219,3 +256,44 @@ func getPodNames(pods []corev1.Pod) []string {
219
256
}
220
257
return podNames
221
258
}
259
+
260
+ func (r *ReconcileMemcached) updateStatus(m *cachev1alpha1.Memcached) error {
261
+ if m.Status.Nodes == nil {
262
+ m.Status.Nodes = []string{}
263
+ }
264
+ if m.Status.Conditions == nil {
265
+ m.Status.Conditions = status.Conditions{}
266
+ }
267
+ return r.client.Status().Update(context.TODO(), m)
268
+ }
269
+
270
+ func (r *ReconcileMemcached) setStatusReady(m *cachev1alpha1.Memcached) error {
271
+ if !m.Status.Conditions.IsTrue(status.ConditionType("Ready")) {
272
+ if setErr := m.Status.Conditions.SetCondition(&status.BasicCondition{
273
+ Type: status.ConditionType("Ready"),
274
+ Status: corev1.ConditionTrue,
275
+ }); setErr != nil {
276
+ return setErr
277
+ }
278
+ if updateErr := r.updateStatus(m); updateErr != nil {
279
+ return updateErr
280
+ }
281
+ }
282
+ return nil
283
+ }
284
+
285
+ func (r *ReconcileMemcached) setStatusNotReady(m *cachev1alpha1.Memcached, origErr error) error {
286
+ if !m.Status.Conditions.IsFalse(status.ConditionType("Ready")) {
287
+ if setErr := m.Status.Conditions.SetCondition(&status.BasicCondition{
288
+ Type: status.ConditionType("Ready"),
289
+ Status: corev1.ConditionFalse,
290
+ Message: origErr.Error(),
291
+ }); setErr != nil {
292
+ return setErr
293
+ }
294
+ if updateErr := r.updateStatus(m); updateErr != nil {
295
+ return updateErr
296
+ }
297
+ }
298
+ return nil
299
+ }
0 commit comments