Skip to content

Commit 2957f6a

Browse files
authored
Fix merging volume claim templates (#150)
1 parent 79f9a5a commit 2957f6a

12 files changed

+316
-19
lines changed

deploy/crds/arbitrary_statefulset_configuration/mongodb.com_v1_custom_volume_cr.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,19 @@ spec:
66
members: 3
77
type: ReplicaSet
88
version: "4.2.6"
9+
security:
10+
authentication:
11+
modes: ["SCRAM"]
12+
users:
13+
- name: my-user
14+
db: admin
15+
passwordSecretRef:
16+
name: my-user-password
17+
roles:
18+
- name: clusterAdmin
19+
db: admin
20+
- name: userAdminAnyDatabase
21+
db: admin
922
statefulSet:
1023
spec:
1124
template:

deploy/crds/mongodb.com_v1_mongodb_cr.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,16 @@ spec:
66
members: 3
77
type: ReplicaSet
88
version: "4.2.6"
9+
security:
10+
authentication:
11+
modes: ["SCRAM"]
12+
users:
13+
- name: my-user
14+
db: admin
15+
passwordSecretRef:
16+
name: my-user-password
17+
roles:
18+
- name: clusterAdmin
19+
db: admin
20+
- name: userAdminAnyDatabase
21+
db: admin

deploy/crds/mongodb.com_v1_mongodb_openshift_cr.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,19 @@ spec:
66
members: 3
77
type: ReplicaSet
88
version: "4.2.6"
9+
security:
10+
authentication:
11+
modes: ["SCRAM"]
12+
users:
13+
- name: my-user
14+
db: admin
15+
passwordSecretRef:
16+
name: my-user-password
17+
roles:
18+
- name: clusterAdmin
19+
db: admin
20+
- name: userAdminAnyDatabase
21+
db: admin
922
statefulSet:
1023
spec:
1124
template:

deploy/crds/mongodb.com_v1_mongodb_tls_cr.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,21 @@ spec:
77
type: ReplicaSet
88
version: "4.2.7"
99
security:
10+
authentication:
11+
modes: ["SCRAM"]
1012
tls:
1113
enabled: true
1214
certificateKeySecretRef:
1315
name: tls-secret-name
1416
caConfigMapRef:
1517
name: tls-ca-configmap-name
18+
users:
19+
- name: my-user
20+
db: admin
21+
passwordSecretRef:
22+
name: my-user-password
23+
roles:
24+
- name: clusterAdmin
25+
db: admin
26+
- name: userAdminAnyDatabase
27+
db: admin

pkg/controller/mongodb/replica_set_controller.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,11 @@ func (r *ReplicaSetReconciler) Reconcile(request reconcile.Request) (reconcile.R
183183

184184
isTLSValid, err := r.validateTLSConfig(mdb)
185185
if err != nil {
186+
r.log.Warnf("Error validating TLS config: %s", err)
186187
return reconcile.Result{}, err
187188
}
188189
if !isTLSValid {
190+
r.log.Infof("TLS config is not yet valid, retrying in 10 seconds")
189191
return reconcile.Result{RequeueAfter: 10 * time.Second}, nil
190192
}
191193

@@ -197,7 +199,9 @@ func (r *ReplicaSetReconciler) Reconcile(request reconcile.Request) (reconcile.R
197199

198200
currentSts := appsv1.StatefulSet{}
199201
if err := r.client.Get(context.TODO(), mdb.NamespacedName(), &currentSts); err != nil {
200-
r.log.Warnf("Error getting StatefulSet: %s", err)
202+
if !apiErrors.IsNotFound(err) {
203+
r.log.Warnf("Error getting StatefulSet: %s", err)
204+
}
201205
return reconcile.Result{}, err
202206
}
203207

@@ -401,11 +405,11 @@ func dummyToolsVersionConfig() automationconfig.ToolsVersion {
401405
}
402406

403407
func readVersionManifestFromDisk() (automationconfig.VersionManifest, error) {
404-
bytes, err := ioutil.ReadFile(versionManifestFilePath)
408+
versionManifestBytes, err := ioutil.ReadFile(versionManifestFilePath)
405409
if err != nil {
406410
return automationconfig.VersionManifest{}, err
407411
}
408-
return versionManifestFromBytes(bytes)
412+
return versionManifestFromBytes(versionManifestBytes)
409413
}
410414

411415
func versionManifestFromBytes(bytes []byte) (automationconfig.VersionManifest, error) {

pkg/controller/mongodb/replicaset_controller_test.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,17 @@ package mongodb
22

33
import (
44
"context"
5+
"encoding/json"
6+
"fmt"
7+
"io/ioutil"
58
"os"
69
"reflect"
710
"testing"
811
"time"
912

13+
"k8s.io/apimachinery/pkg/runtime"
14+
"sigs.k8s.io/yaml"
15+
1016
"github.com/pkg/errors"
1117

1218
"github.com/stretchr/objx"
@@ -414,6 +420,76 @@ func AssertReplicaSetIsConfiguredWithScram(t *testing.T, mdb mdbv1.MongoDB) {
414420
})
415421
}
416422

423+
func TestOpenshift_Configuration(t *testing.T) {
424+
sts := performReconciliationAndGetStatefulSet(t, "openshift_mdb.yaml")
425+
assert.Equal(t, "MANAGED_SECURITY_CONTEXT", sts.Spec.Template.Spec.Containers[0].Env[1].Name)
426+
assert.Equal(t, "MANAGED_SECURITY_CONTEXT", sts.Spec.Template.Spec.Containers[1].Env[1].Name)
427+
}
428+
429+
func TestVolumeClaimTemplates_Configuration(t *testing.T) {
430+
sts := performReconciliationAndGetStatefulSet(t, "volume_claim_templates_mdb.yaml")
431+
432+
assert.Len(t, sts.Spec.VolumeClaimTemplates, 2)
433+
434+
pvcSpec := sts.Spec.VolumeClaimTemplates[1].Spec
435+
436+
storage := pvcSpec.Resources.Requests[corev1.ResourceStorage]
437+
storageRef := &storage
438+
439+
assert.Equal(t, "1Gi", storageRef.String())
440+
assert.Len(t, pvcSpec.AccessModes, 1)
441+
assert.Contains(t, pvcSpec.AccessModes, corev1.ReadWriteOnce)
442+
}
443+
444+
func TestChangeDataVolume_Configuration(t *testing.T) {
445+
sts := performReconciliationAndGetStatefulSet(t, "change_data_volume.yaml")
446+
assert.Len(t, sts.Spec.VolumeClaimTemplates, 1)
447+
448+
dataVolume := sts.Spec.VolumeClaimTemplates[0]
449+
450+
storage := dataVolume.Spec.Resources.Requests[corev1.ResourceStorage]
451+
storageRef := &storage
452+
453+
assert.Equal(t, "data-volume", dataVolume.Name)
454+
assert.Equal(t, "50Gi", storageRef.String())
455+
}
456+
457+
func performReconciliationAndGetStatefulSet(t *testing.T, filePath string) appsv1.StatefulSet {
458+
mdb, err := loadTestFixture(filePath)
459+
assert.NoError(t, err)
460+
mgr := client.NewManager(&mdb)
461+
assert.NoError(t, generatePasswordsForAllUsers(mdb, mgr.Client))
462+
r := newReconciler(mgr, mockManifestProvider(mdb.Spec.Version))
463+
res, err := r.Reconcile(reconcile.Request{NamespacedName: mdb.NamespacedName()})
464+
assertReconciliationSuccessful(t, res, err)
465+
466+
sts, err := mgr.Client.GetStatefulSet(mdb.NamespacedName())
467+
assert.NoError(t, err)
468+
return sts
469+
}
470+
471+
func generatePasswordsForAllUsers(mdb mdbv1.MongoDB, c client.Client) error {
472+
for _, user := range mdb.Spec.Users {
473+
474+
key := "password"
475+
if user.PasswordSecretRef.Key != "" {
476+
key = user.PasswordSecretRef.Key
477+
}
478+
479+
passwordSecret := secret.Builder().
480+
SetName(user.PasswordSecretRef.Name).
481+
SetNamespace(mdb.Namespace).
482+
SetField(key, "GAGTQK2ccRRaxJFudI5y").
483+
Build()
484+
485+
if err := c.CreateSecret(passwordSecret); err != nil {
486+
return err
487+
}
488+
}
489+
490+
return nil
491+
}
492+
417493
func assertReconciliationSuccessful(t *testing.T, result reconcile.Result, err error) {
418494
assert.NoError(t, err)
419495
assert.Equal(t, false, result.Requeue)
@@ -431,3 +507,29 @@ func makeStatefulSetReady(t *testing.T, c k8sClient.Client, mdb mdbv1.MongoDB) {
431507
err = c.Update(context.TODO(), &sts)
432508
assert.NoError(t, err)
433509
}
510+
511+
// loadTestFixture will create a MongoDB resource from a given fixture
512+
func loadTestFixture(yamlFileName string) (mdbv1.MongoDB, error) {
513+
testPath := fmt.Sprintf("testdata/%s", yamlFileName)
514+
mdb := mdbv1.MongoDB{}
515+
data, err := ioutil.ReadFile(testPath)
516+
if err != nil {
517+
return mdb, errors.Errorf("error reading file: %s", err)
518+
}
519+
520+
if err := marshalRuntimeObjectFromYAMLBytes(data, &mdb); err != nil {
521+
return mdb, errors.Errorf("error converting yaml bytes to service account: %s", err)
522+
}
523+
524+
return mdb, nil
525+
}
526+
527+
// marshalRuntimeObjectFromYAMLBytes accepts the bytes of a yaml resource
528+
// and unmarshals them into the provided runtime Object
529+
func marshalRuntimeObjectFromYAMLBytes(bytes []byte, obj runtime.Object) error {
530+
jsonBytes, err := yaml.YAMLToJSON(bytes)
531+
if err != nil {
532+
return err
533+
}
534+
return json.Unmarshal(jsonBytes, &obj)
535+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
apiVersion: mongodb.com/v1
2+
kind: MongoDB
3+
metadata:
4+
name: change-data-volume-mdb
5+
spec:
6+
members: 3
7+
type: ReplicaSet
8+
version: "4.2.6"
9+
persistent: true
10+
security:
11+
authentication:
12+
modes: ["SCRAM"]
13+
users:
14+
- name: my-user
15+
db: admin
16+
passwordSecretRef:
17+
name: my-user-password
18+
roles:
19+
- name: clusterAdmin
20+
db: admin
21+
- name: userAdminAnyDatabase
22+
db: admin
23+
statefulSet:
24+
spec:
25+
volumeClaimTemplates:
26+
- metadata:
27+
name: data-volume
28+
spec:
29+
accessModes: [ "ReadWriteOnce", "ReadWriteMany" ]
30+
resources:
31+
requests:
32+
storage: 50Gi
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
apiVersion: mongodb.com/v1
2+
kind: MongoDB
3+
metadata:
4+
name: example-openshift-mongodb
5+
spec:
6+
members: 3
7+
type: ReplicaSet
8+
version: "4.2.6"
9+
security:
10+
authentication:
11+
modes: ["SCRAM"]
12+
users:
13+
- name: my-user
14+
db: admin
15+
passwordSecretRef:
16+
name: my-user-password
17+
roles:
18+
- name: clusterAdmin
19+
db: admin
20+
- name: userAdminAnyDatabase
21+
db: admin
22+
statefulSet:
23+
spec:
24+
template:
25+
spec:
26+
containers:
27+
- name: "mongodb-agent"
28+
env:
29+
- name: MANAGED_SECURITY_CONTEXT
30+
value: "true"
31+
- name: "mongod"
32+
env:
33+
- name: MANAGED_SECURITY_CONTEXT
34+
value: "true"
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
apiVersion: mongodb.com/v1
2+
kind: MongoDB
3+
metadata:
4+
name: volume-claim-templates-mdb
5+
spec:
6+
members: 3
7+
type: ReplicaSet
8+
version: "4.2.6"
9+
persistent: true
10+
statefulSet:
11+
spec:
12+
volumeClaimTemplates:
13+
- metadata:
14+
name: volume-claim-templates
15+
spec:
16+
accessModes: [ "ReadWriteOnce" ]
17+
resources:
18+
requests:
19+
storage: 1Gi

pkg/kube/client/mocked_client.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,16 @@ func (m *mockedClient) ensureMapFor(obj runtime.Object) map[k8sClient.ObjectKey]
4040
func (m *mockedClient) Get(_ context.Context, key k8sClient.ObjectKey, obj runtime.Object) error {
4141
relevantMap := m.ensureMapFor(obj)
4242
if val, ok := relevantMap[key]; ok {
43-
v := reflect.ValueOf(obj).Elem()
44-
v.Set(reflect.ValueOf(val).Elem())
43+
if currSts, ok := val.(*appsv1.StatefulSet); ok {
44+
// TODO: this currently doesn't work with additional mongodb config
45+
// just doing it for StatefulSets for now
46+
objCopy := currSts.DeepCopyObject()
47+
v := reflect.ValueOf(obj).Elem()
48+
v.Set(reflect.ValueOf(objCopy).Elem())
49+
} else {
50+
v := reflect.ValueOf(obj).Elem()
51+
v.Set(reflect.ValueOf(val).Elem())
52+
}
4553
return nil
4654
}
4755
return notFoundError()

0 commit comments

Comments
 (0)