Skip to content

Commit 09ab34c

Browse files
CLOUDP-193669: Make overriden tolerations take precedence (#1346)
1 parent fcd99fa commit 09ab34c

File tree

9 files changed

+205
-132
lines changed

9 files changed

+205
-132
lines changed

api/v1/zz_generated.deepcopy.go

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/RELEASE_NOTES.md

+5-13
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,13 @@
1-
# MongoDB Kubernetes Operator 0.8.1
1+
# MongoDB Kubernetes Operator 0.8.2
2+
3+
## Kubernetes Operator
24

3-
## MongoDBCommunity Resource
45
- Changes
5-
- Connection string options
6-
- The MongoDBCommunity Resource now contains a new field ```additionalConnectionStringConfig``` where connection string options can be set, and they will apply to the connection string of every user.
7-
- Each user in the resource contains the same field ```additionalConnectionStringConfig``` and these options apply only for this user and will override any existing options in the resource.
8-
- The following options will be ignored `replicaSet`, `tls`, `ssl`, as they are set through other means.
9-
- [Sample](../config/samples/mongodb.com_v1_mongodbcommunity_additional_connection_string_options.yaml)
10-
- Support for Label and Annotations Wrapper
11-
- Additionally to the `specWrapper` for `statefulsets` we now support overriding `metadata.Labels` and `metadata.Annotations` via the `MetadataWrapper`.
12-
- [Sample](../config/samples/arbitrary_statefulset_configuration/mongodb.com_v1_metadata.yaml)
6+
- Fix a bug when overriding tolerations causing an endless reconciliation loop ([1344](https://github.com/mongodb/mongodb-kubernetes-operator/issues/1344)).
137

148
## Updated Image Tags
159

16-
- mongodb-kubernetes-operator:0.8.1
17-
- mongodb-agent:12.0.24.7719-1
18-
- mongodb-kubernetes-readinessprobe:1.0.15
10+
- mongodb-kubernetes-operator:0.8.2
1911

2012
_All the images can be found in:_
2113

pkg/kube/podtemplatespec/podspec_template_test.go

+134
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,140 @@ func TestMergeEnvironmentVariables(t *testing.T) {
247247
assert.Equal(t, mergedContainer.Env[1].Value, "val2")
248248
}
249249

250+
func TestMergeTolerations(t *testing.T) {
251+
tests := []struct {
252+
name string
253+
defaultTolerations []corev1.Toleration
254+
overrideTolerations []corev1.Toleration
255+
expectedTolerations []corev1.Toleration
256+
}{
257+
{
258+
// In case the calling code specifies default tolerations,
259+
// they should be kept when there are no overrides.
260+
name: "Overriding with nil tolerations",
261+
defaultTolerations: []corev1.Toleration{
262+
{
263+
Key: "key1",
264+
Value: "value1",
265+
Operator: corev1.TolerationOpEqual,
266+
},
267+
{
268+
Key: "key1",
269+
Value: "value2",
270+
Operator: corev1.TolerationOpExists,
271+
},
272+
},
273+
overrideTolerations: nil,
274+
expectedTolerations: []corev1.Toleration{
275+
{
276+
Key: "key1",
277+
Value: "value1",
278+
Operator: corev1.TolerationOpEqual,
279+
},
280+
{
281+
Key: "key1",
282+
Value: "value2",
283+
Operator: corev1.TolerationOpExists,
284+
},
285+
},
286+
},
287+
{
288+
// If the override is specifying an empty list of tolerations,
289+
// they should replace default tolerations.
290+
name: "Overriding with empty tolerations",
291+
defaultTolerations: []corev1.Toleration{
292+
{
293+
Key: "key1",
294+
Value: "value1",
295+
Operator: corev1.TolerationOpEqual,
296+
},
297+
},
298+
overrideTolerations: []corev1.Toleration{},
299+
expectedTolerations: []corev1.Toleration{},
300+
},
301+
{
302+
// Overriding toleration should replace a nil original toleration.
303+
name: "Overriding when default toleration is nil",
304+
defaultTolerations: nil,
305+
overrideTolerations: []corev1.Toleration{
306+
{
307+
Key: "key1",
308+
Value: "value1",
309+
Operator: corev1.TolerationOpEqual,
310+
},
311+
{
312+
Key: "key1",
313+
Value: "value2",
314+
Operator: corev1.TolerationOpExists,
315+
},
316+
},
317+
expectedTolerations: []corev1.Toleration{
318+
{
319+
Key: "key1",
320+
Value: "value1",
321+
Operator: corev1.TolerationOpEqual,
322+
},
323+
{
324+
Key: "key1",
325+
Value: "value2",
326+
Operator: corev1.TolerationOpExists,
327+
},
328+
},
329+
},
330+
{
331+
// Overriding toleration should replace any original toleration.
332+
name: "Overriding when original toleration is not nil",
333+
defaultTolerations: []corev1.Toleration{
334+
{
335+
Key: "key1",
336+
Value: "value3",
337+
Operator: corev1.TolerationOpEqual,
338+
},
339+
{
340+
Key: "key1",
341+
Value: "value4",
342+
Operator: corev1.TolerationOpExists,
343+
},
344+
},
345+
overrideTolerations: []corev1.Toleration{
346+
{
347+
Key: "key1",
348+
Value: "value1",
349+
Operator: corev1.TolerationOpEqual,
350+
},
351+
{
352+
Key: "key1",
353+
Value: "value2",
354+
Operator: corev1.TolerationOpExists,
355+
},
356+
},
357+
expectedTolerations: []corev1.Toleration{
358+
{
359+
Key: "key1",
360+
Value: "value1",
361+
Operator: corev1.TolerationOpEqual,
362+
},
363+
{
364+
Key: "key1",
365+
Value: "value2",
366+
Operator: corev1.TolerationOpExists,
367+
},
368+
},
369+
},
370+
}
371+
for _, tt := range tests {
372+
t.Run(tt.name, func(t *testing.T) {
373+
defaultSpec := getDefaultPodSpec()
374+
defaultSpec.Spec.Tolerations = tt.defaultTolerations
375+
overrideSpec := getDefaultPodSpec()
376+
overrideSpec.Spec.Tolerations = tt.overrideTolerations
377+
378+
mergedSpec := merge.PodTemplateSpecs(defaultSpec, overrideSpec)
379+
assert.Equal(t, tt.expectedTolerations, mergedSpec.Spec.Tolerations)
380+
})
381+
}
382+
}
383+
250384
func TestMergeContainer(t *testing.T) {
251385
vol0 := corev1.VolumeMount{Name: "container-0.volume-mount-0"}
252386
sideCarVol := corev1.VolumeMount{Name: "container-1.volume-mount-0"}

pkg/util/merge/merge.go

-38
Original file line numberDiff line numberDiff line change
@@ -503,44 +503,6 @@ func VolumeMount(original, override corev1.VolumeMount) corev1.VolumeMount {
503503
return merged
504504
}
505505

506-
func Tolerations(defaultTolerations, overrideTolerations []corev1.Toleration) []corev1.Toleration {
507-
mergedTolerations := make([]corev1.Toleration, 0)
508-
defaultMap := createTolerationsMap(defaultTolerations)
509-
for _, v := range overrideTolerations {
510-
if _, ok := defaultMap[v.Key]; ok {
511-
defaultMap[v.Key] = append(defaultMap[v.Key], v)
512-
} else {
513-
defaultMap[v.Key] = []corev1.Toleration{v}
514-
}
515-
}
516-
517-
for _, v := range defaultMap {
518-
mergedTolerations = append(mergedTolerations, v...)
519-
}
520-
521-
if len(mergedTolerations) == 0 {
522-
return nil
523-
}
524-
525-
sort.SliceStable(mergedTolerations, func(i, j int) bool {
526-
return mergedTolerations[i].Key < mergedTolerations[j].Key
527-
})
528-
529-
return mergedTolerations
530-
}
531-
532-
func createTolerationsMap(tolerations []corev1.Toleration) map[string][]corev1.Toleration {
533-
tolerationsMap := make(map[string][]corev1.Toleration)
534-
for _, t := range tolerations {
535-
if _, ok := tolerationsMap[t.Key]; ok {
536-
tolerationsMap[t.Key] = append(tolerationsMap[t.Key], t)
537-
} else {
538-
tolerationsMap[t.Key] = []corev1.Toleration{t}
539-
}
540-
}
541-
return tolerationsMap
542-
}
543-
544506
func Volumes(defaultVolumes []corev1.Volume, overrideVolumes []corev1.Volume) []corev1.Volume {
545507
defaultVolumesMap := createVolumesMap(defaultVolumes)
546508
overrideVolumesMap := createVolumesMap(overrideVolumes)

pkg/util/merge/merge_podtemplate_spec.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,9 @@ func PodTemplateSpecs(original, override corev1.PodTemplateSpec) corev1.PodTempl
9191
merged.Spec.SchedulerName = override.Spec.SchedulerName
9292
}
9393

94-
merged.Spec.Tolerations = Tolerations(original.Spec.Tolerations, override.Spec.Tolerations)
94+
if override.Spec.Tolerations != nil {
95+
merged.Spec.Tolerations = override.Spec.Tolerations
96+
}
9597

9698
merged.Spec.HostAliases = HostAliases(original.Spec.HostAliases, override.Spec.HostAliases)
9799

pkg/util/merge/merge_test.go

-79
Original file line numberDiff line numberDiff line change
@@ -670,82 +670,3 @@ func TestMergeHostAliases(t *testing.T) {
670670
assert.Equal(t, "1.2.3.5", merged[1].IP)
671671
assert.Equal(t, []string{"abc"}, merged[1].Hostnames)
672672
}
673-
674-
func TestTolerations(t *testing.T) {
675-
type args struct {
676-
defaultTolerations []corev1.Toleration
677-
overrideTolerations []corev1.Toleration
678-
}
679-
tests := []struct {
680-
name string
681-
args args
682-
want []corev1.Toleration
683-
}{
684-
{
685-
name: "override tolerations is nil",
686-
args: args{
687-
defaultTolerations: []corev1.Toleration{
688-
{
689-
Key: "key1",
690-
Value: "value1",
691-
Operator: corev1.TolerationOpEqual,
692-
},
693-
{
694-
Key: "key1",
695-
Value: "value2",
696-
Operator: corev1.TolerationOpExists,
697-
},
698-
},
699-
overrideTolerations: nil,
700-
},
701-
want: []corev1.Toleration{
702-
{
703-
Key: "key1",
704-
Value: "value1",
705-
Operator: corev1.TolerationOpEqual,
706-
},
707-
{
708-
Key: "key1",
709-
Value: "value2",
710-
Operator: corev1.TolerationOpExists,
711-
},
712-
},
713-
},
714-
715-
{
716-
name: "default tolerations is nil",
717-
args: args{
718-
defaultTolerations: nil,
719-
overrideTolerations: []corev1.Toleration{
720-
{
721-
Key: "key1",
722-
Value: "value1",
723-
Operator: corev1.TolerationOpEqual,
724-
},
725-
{
726-
Key: "key1",
727-
Value: "value2",
728-
Operator: corev1.TolerationOpExists,
729-
},
730-
},
731-
},
732-
want: []corev1.Toleration{
733-
{
734-
Key: "key1",
735-
Value: "value1",
736-
Operator: corev1.TolerationOpEqual,
737-
},
738-
{
739-
Key: "key1",
740-
Value: "value2",
741-
Operator: corev1.TolerationOpExists,
742-
},
743-
},
744-
},
745-
}
746-
for _, tt := range tests {
747-
t.Run(tt.name, func(t *testing.T) {
748-
assert.Equalf(t, tt.want, Tolerations(tt.args.defaultTolerations, tt.args.overrideTolerations), "Tolerations(%v, %v)", tt.args.defaultTolerations, tt.args.overrideTolerations)
749-
})
750-
}
751-
}

test/e2e/mongodbtests/mongodbtests.go

+16-1
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ import (
44
"context"
55
"encoding/json"
66
"fmt"
7-
"sigs.k8s.io/controller-runtime/pkg/client"
87
"strings"
98
"testing"
109
"time"
1110

11+
"sigs.k8s.io/controller-runtime/pkg/client"
12+
1213
"github.com/mongodb/mongodb-kubernetes-operator/pkg/kube/container"
1314
"github.com/mongodb/mongodb-kubernetes-operator/test/e2e/util/wait"
1415

@@ -643,6 +644,20 @@ func StatefulSetContainerConditionIsTrue(mdb *mdbv1.MongoDBCommunity, containerN
643644
}
644645
}
645646

647+
func StatefulSetConditionIsTrue(mdb *mdbv1.MongoDBCommunity, condition func(s appsv1.StatefulSet) bool) func(*testing.T) {
648+
return func(t *testing.T) {
649+
sts := appsv1.StatefulSet{}
650+
err := e2eutil.TestClient.Get(context.TODO(), types.NamespacedName{Name: mdb.Name, Namespace: mdb.Namespace}, &sts)
651+
if err != nil {
652+
t.Fatal(err)
653+
}
654+
655+
if !condition(sts) {
656+
t.Fatalf(`StatefulSet "%s" does not satisfy condition`, mdb.Name)
657+
}
658+
}
659+
}
660+
646661
// PodContainerBecomesNotReady waits until the container with 'containerName' in the pod #podNum becomes not ready.
647662
func PodContainerBecomesNotReady(mdb *mdbv1.MongoDBCommunity, podNum int, containerName string) func(*testing.T) {
648663
return func(t *testing.T) {

0 commit comments

Comments
 (0)