Skip to content

Commit 2a09f9c

Browse files
authored
Merge pull request #437 from oracle/pv-fix
Fix StatefulSet controller to never attempt to patch VolumeClaimTemplates
2 parents c7f4815 + 490f6e4 commit 2a09f9c

File tree

5 files changed

+38
-41
lines changed

5 files changed

+38
-41
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ PRE_RELEASE ?= true
7373
# Extra arguments to pass to the go test command for the various test steps.
7474
# For example, when running make e2e-test we can run just a single test such
7575
# as the zone test using the go test -run=regex argument like this
76-
# make e2e-test GO_TEST_FLAGS='-run=^TestZone$$'
76+
# make e2e-test GO_TEST_FLAGS_E2E='-run=^TestZone$$'
7777
GO_TEST_FLAGS ?= -timeout=20m
7878
GO_TEST_FLAGS_E2E := -timeout=100m
7979

pkg/apis/coherence/v1/coherence_types.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2332,6 +2332,24 @@ func (in *Resource) IsDelete() bool {
23322332
return in.Spec == nil
23332333
}
23342334

2335+
// Convert the Spec to the specified value.
2336+
// This is done by serializing the Spec to json and deserializing into the specified object.
2337+
func (in *Resource) As(o runtime.Object) error {
2338+
if in == nil {
2339+
return fmt.Errorf("cannot convert to runtime.Object - resource is nil")
2340+
}
2341+
if in.Spec == nil {
2342+
return fmt.Errorf("cannot convert resource - spec is nil")
2343+
}
2344+
2345+
data, err := json.Marshal(in.Spec)
2346+
if err != nil {
2347+
return errors.Wrap(err, "marshalling spec to json")
2348+
}
2349+
2350+
return json.Unmarshal(data, o)
2351+
}
2352+
23352353
// Set the the controller/owner of the resource
23362354
func (in *Resource) SetController(object runtime.Object, scheme *runtime.Scheme) error {
23372355
if in == nil || in.Spec == nil {

pkg/controller/reconciler/base_controller.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ func (in *CommonReconciler) ThreeWayPatchWithCallback(name string, current, orig
328328

329329
// Create a three-way patch between the original state, the current state and the desired state of a k8s resource.
330330
func (in *CommonReconciler) CreateThreeWayPatch(name string, original, desired, current runtime.Object, ignore ...string) (client.Patch, error) {
331-
data, err := in.CreateThreeWayPatchData(name, original, desired, current, ignore...)
331+
data, err := in.CreateThreeWayPatchData(original, desired, current, ignore...)
332332
if err != nil {
333333
return nil, errors.Wrap(err, "creating three-way patch")
334334
}
@@ -350,7 +350,7 @@ func (in *CommonReconciler) CreateThreeWayPatch(name string, original, desired,
350350
}
351351

352352
// Create a three-way patch between the original state, the current state and the desired state of a k8s resource.
353-
func (in *CommonReconciler) CreateThreeWayPatchData(name string, original, desired, current runtime.Object, ignore ...string) ([]byte, error) {
353+
func (in *CommonReconciler) CreateThreeWayPatchData(original, desired, current runtime.Object, ignore ...string) ([]byte, error) {
354354
originalData, err := json.Marshal(original)
355355
if err != nil {
356356
return nil, errors.Wrap(err, "serializing original configuration")

pkg/controller/servicemonitor/servicemonitor_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ func (in *ReconcileServiceMonitor) UpdateServiceMonitor(namespace, name string,
186186
// fix the CreationTimestamp so that it is not in the patch
187187
desired.Spec.(metav1.Object).SetCreationTimestamp(current.(metav1.Object).GetCreationTimestamp())
188188
// create the patch
189-
data, err := in.CreateThreeWayPatchData(name, original.Spec, desired.Spec, current)
189+
data, err := in.CreateThreeWayPatchData(original.Spec, desired.Spec, current)
190190
if err != nil {
191191
return errors.Wrapf(err, "failed to create patch for ServiceMonitor %s/%s", namespace, name)
192192
}

pkg/controller/statefulset/statefulset_controller.go

Lines changed: 16 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -285,16 +285,26 @@ func (in *ReconcileStatefulSet) updateStatefulSet(deployment *coh.Coherence, cur
285285
// Patch the StatefulSet if required, returning a bool to indicate whether a patch was applied.
286286
func (in *ReconcileStatefulSet) patchStatefulSet(deployment *coh.Coherence, current, desired *appsv1.StatefulSet, storage utils.Storage) (bool, error) {
287287
logger := in.GetLog().WithValues("Namespace", deployment.Namespace, "Name", deployment.Name)
288-
name := current.GetName()
289-
original, _ := storage.GetPrevious().GetResource(coh.ResourceTypeStatefulSet, name)
288+
resource, _ := storage.GetPrevious().GetResource(coh.ResourceTypeStatefulSet, current.GetName())
289+
original := &appsv1.StatefulSet{}
290+
err := resource.As(original)
291+
if err != nil {
292+
return false, err
293+
}
290294

291295
// We NEVER change the replicas or Status in an update.
292296
// Replicas is handled by scaling so we always set the desired replicas to match the current replicas
293297
desired.Spec.Replicas = current.Spec.Replicas
298+
original.Spec.Replicas = current.Spec.Replicas
294299
// We need to ensure we do not create a patch due to differences in StatefulSet Status
295-
desired.Status = current.Status
296-
// If the StatefulSet has PVs we need to ensure we do not create a patch due to ignorable differences in PV
297-
in.mergeVolumeClaims(desired, current)
300+
desired.Status = appsv1.StatefulSetStatus{}
301+
current.Status = appsv1.StatefulSetStatus{}
302+
original.Status = appsv1.StatefulSetStatus{}
303+
304+
// The VolumeClaimTemplates of a StetfulSet cannot be changed so blank them out for the patch
305+
desired.Spec.VolumeClaimTemplates = []corev1.PersistentVolumeClaim{}
306+
current.Spec.VolumeClaimTemplates = []corev1.PersistentVolumeClaim{}
307+
original.Spec.VolumeClaimTemplates = []corev1.PersistentVolumeClaim{}
298308

299309
// a callback function that the 3-way patch method will call just before it applies a patch
300310
callback := func() {
@@ -304,7 +314,7 @@ func (in *ReconcileStatefulSet) patchStatefulSet(deployment *coh.Coherence, curr
304314
}
305315
}
306316

307-
patched, err := in.ThreeWayPatchWithCallback(name, current, original.Spec, desired, callback)
317+
patched, err := in.ThreeWayPatchWithCallback(current.GetName(), current, original, desired, callback)
308318
// log the result of patching
309319
switch {
310320
case err != nil:
@@ -318,37 +328,6 @@ func (in *ReconcileStatefulSet) patchStatefulSet(deployment *coh.Coherence, curr
318328
return patched, err
319329
}
320330

321-
// If the desired StatefulSet has PVs update the desired PV to avid needless merges
322-
func (in *ReconcileStatefulSet) mergeVolumeClaims(desired, current *appsv1.StatefulSet) {
323-
if len(desired.Spec.VolumeClaimTemplates) == 0 {
324-
return
325-
}
326-
327-
// Make a map of current PVs by name
328-
m := make(map[string]corev1.PersistentVolumeClaim)
329-
for _, pv := range current.Spec.VolumeClaimTemplates {
330-
m[pv.Name] = pv
331-
}
332-
333-
dfltVolumeMode := corev1.PersistentVolumeFilesystem
334-
335-
for i, pv := range desired.Spec.VolumeClaimTemplates {
336-
currentPV, found := m[pv.Name]
337-
if found {
338-
// Update the desired PV statuses
339-
pv.Status = currentPV.Status
340-
341-
// Set the desired volume mode to the default if it is not set
342-
if pv.Spec.VolumeMode == nil {
343-
pv.Spec.VolumeMode = &dfltVolumeMode
344-
}
345-
346-
// set the updated PV back into the desired array
347-
desired.Spec.VolumeClaimTemplates[i] = pv
348-
}
349-
}
350-
}
351-
352331
// Scale will scale a StatefulSet up or down
353332
func (in *ReconcileStatefulSet) scale(deployment *coh.Coherence, sts *appsv1.StatefulSet, current, desired int32) (reconcile.Result, error) {
354333
// if the StatefulSet is not stable we cannot scale (e.g. it might already be in the middle of a rolling upgrade)

0 commit comments

Comments
 (0)