Skip to content
This repository was archived by the owner on Dec 12, 2025. It is now read-only.

Commit 1ae5cee

Browse files
authored
CLOUDP-58413: Deploy any version of MongoDB (#29)
1 parent cc7821b commit 1ae5cee

File tree

5 files changed

+123
-42
lines changed

5 files changed

+123
-42
lines changed

docker/Dockerfile.operator

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,22 @@ RUN go mod vendor && /bin/operator-sdk generate k8s
1919
# TODO: This build takes longer than it needs to and can still be optimized
2020
RUN go build -o build/_output/bin/mongodb-kubernetes-operator -mod=vendor github.com/mongodb/mongodb-kubernetes-operator/cmd/manager
2121

22+
ENV manifest_version=4.2
23+
RUN mkdir -p /content/ \
24+
&& chmod -R +r /content/ \
25+
&& curl --fail --retry 3 -o /content/version_manifest.json "https://opsmanager.mongodb.com/static/version_manifest/${manifest_version}.json"
26+
2227
FROM registry.access.redhat.com/ubi8/ubi-minimal:latest
2328

2429
ENV OPERATOR=/usr/local/bin/mongodb-kubernetes-operator \
2530
USER_UID=1001 \
2631
USER_NAME=mongodb-kubernetes-operator
2732

28-
# copy the operator binary
33+
# copy the operator binary and version manifest
2934
COPY --from=builder /go/build/_output/bin/mongodb-kubernetes-operator ${OPERATOR}
30-
3135
COPY --from=builder /go/build/bin /usr/local/bin
36+
COPY --from=builder /content/version_manifest.json /usr/local/version_manifest.json
37+
3238
RUN /usr/local/bin/user_setup
3339

3440
ENTRYPOINT ["/usr/local/bin/entrypoint"]

pkg/automationconfig/automation_config.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,28 @@ type AutomationConfig struct {
162162
Options Options `json:"options"`
163163
}
164164

165+
type VersionManifest struct {
166+
Updated int `json:"updated"`
167+
Versions []MongoDbVersionConfig `json:"versions"`
168+
}
169+
170+
// BuildsForVersion returns the MongoDbVersionConfig containing all of the version informatioon
171+
// for the given mongodb version provided
172+
func (v VersionManifest) BuildsForVersion(version string) MongoDbVersionConfig {
173+
var builds []BuildConfig
174+
for _, versionConfig := range v.Versions {
175+
if versionConfig.Name != version {
176+
continue
177+
}
178+
builds = versionConfig.Builds
179+
break
180+
}
181+
return MongoDbVersionConfig{
182+
Name: version,
183+
Builds: builds,
184+
}
185+
}
186+
165187
type Options struct {
166188
DownloadBase string `json:"downloadBase"`
167189
}

pkg/automationconfig/automation_config_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,3 +146,29 @@ func TestProcessHasPortSetToDefault(t *testing.T) {
146146
assert.Equal(t, ac.Processes[1].Args26.Net.Port, 27017)
147147
assert.Equal(t, ac.Processes[2].Args26.Net.Port, 27017)
148148
}
149+
150+
func TestVersionManifest_BuildsForVersion(t *testing.T) {
151+
vm := VersionManifest{
152+
Updated: 0,
153+
Versions: []MongoDbVersionConfig{
154+
defaultMongoDbVersion("4.2.0"),
155+
defaultMongoDbVersion("4.2.3"),
156+
defaultMongoDbVersion("4.2.4"),
157+
},
158+
}
159+
160+
version := vm.BuildsForVersion("4.2.0")
161+
assert.Len(t, version.Builds, 1)
162+
assert.Equal(t, defaultMongoDbVersion("4.2.0"), version)
163+
164+
version = vm.BuildsForVersion("4.2.3")
165+
assert.Len(t, version.Builds, 1)
166+
assert.Equal(t, defaultMongoDbVersion("4.2.3"), version)
167+
168+
version = vm.BuildsForVersion("4.2.4")
169+
assert.Len(t, version.Builds, 1)
170+
assert.Equal(t, defaultMongoDbVersion("4.2.4"), version)
171+
172+
version = vm.BuildsForVersion("4.2.1")
173+
assert.Empty(t, version.Builds)
174+
}

pkg/controller/mongodb/mongodb_controller.go

Lines changed: 41 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"encoding/json"
66
"fmt"
7+
"io/ioutil"
78
"os"
89

910
mdbv1 "github.com/mongodb/mongodb-kubernetes-operator/pkg/apis/mongodb/v1"
@@ -31,6 +32,7 @@ const (
3132
agentName = "mongodb-agent"
3233
mongodbName = "mongod"
3334
agentImageEnvVariable = "AGENT_IMAGE"
35+
versionManifestFilePath = "/usr/local/version_manifest.json"
3436
readinessProbePath = "/var/lib/mongodb-mms-automation/probes/readinessprobe"
3537
agentHealthStatusFilePath = "/var/log/mongodb-mms-automation/agent-health-status.json"
3638
clusterFilePath = "/var/lib/automation/config/automation-config"
@@ -39,13 +41,21 @@ const (
3941
// Add creates a new MongoDB Controller and adds it to the Manager. The Manager will set fields on the Controller
4042
// and Start it when the Manager is Started.
4143
func Add(mgr manager.Manager) error {
42-
return add(mgr, newReconciler(mgr))
44+
return add(mgr, newReconciler(mgr, readVersionManifestFromDisk))
4345
}
4446

47+
// ManifestProvider is a function which returns the VersionManifest which
48+
// contains the list of all available MongoDB versions
49+
type ManifestProvider func() (automationconfig.VersionManifest, error)
50+
4551
// newReconciler returns a new reconcile.Reconciler
46-
func newReconciler(mgr manager.Manager) reconcile.Reconciler {
52+
func newReconciler(mgr manager.Manager, manifestProvider ManifestProvider) reconcile.Reconciler {
4753
mgrClient := mgr.GetClient()
48-
return &ReplicaSetReconciler{client: mdbClient.NewClient(mgrClient), scheme: mgr.GetScheme()}
54+
return &ReplicaSetReconciler{
55+
client: mdbClient.NewClient(mgrClient),
56+
scheme: mgr.GetScheme(),
57+
manifestProvider: manifestProvider,
58+
}
4959
}
5060

5161
// add adds a new Controller to mgr with r as the reconcile.Reconciler
@@ -71,8 +81,9 @@ var _ reconcile.Reconciler = &ReplicaSetReconciler{}
7181
type ReplicaSetReconciler struct {
7282
// This client, initialized using mgr.Client() above, is a split client
7383
// that reads objects from the cache and writes to the apiserver
74-
client mdbClient.Client
75-
scheme *runtime.Scheme
84+
client mdbClient.Client
85+
scheme *runtime.Scheme
86+
manifestProvider func() (automationconfig.VersionManifest, error)
7687
}
7788

7889
// Reconcile reads that state of the cluster for a MongoDB object and makes changes based on the state read
@@ -102,7 +113,7 @@ func (r *ReplicaSetReconciler) Reconcile(request reconcile.Request) (reconcile.R
102113

103114
// TODO: Read current automation config version from config map
104115
if err := r.ensureAutomationConfig(mdb); err != nil {
105-
log.Warnf("failed creating config map: %s", err)
116+
log.Warnf("error creating automation config config map: %s", err)
106117
return reconcile.Result{}, err
107118
}
108119

@@ -127,7 +138,7 @@ func (r *ReplicaSetReconciler) Reconcile(request reconcile.Request) (reconcile.R
127138
}
128139

129140
func (r ReplicaSetReconciler) ensureAutomationConfig(mdb mdbv1.MongoDB) error {
130-
cm, err := buildAutomationConfigConfigMap(mdb)
141+
cm, err := r.buildAutomationConfigConfigMap(mdb)
131142
if err != nil {
132143
return err
133144
}
@@ -137,7 +148,7 @@ func (r ReplicaSetReconciler) ensureAutomationConfig(mdb mdbv1.MongoDB) error {
137148
return nil
138149
}
139150

140-
func buildAutomationConfig(mdb mdbv1.MongoDB) automationconfig.AutomationConfig {
151+
func buildAutomationConfig(mdb mdbv1.MongoDB, mdbVersionConfig automationconfig.MongoDbVersionConfig) automationconfig.AutomationConfig {
141152
domain := getDomain(mdb.ServiceName(), mdb.Namespace, "")
142153
return automationconfig.NewBuilder().
143154
SetTopology(automationconfig.ReplicaSetTopology).
@@ -146,10 +157,26 @@ func buildAutomationConfig(mdb mdbv1.MongoDB) automationconfig.AutomationConfig
146157
SetMembers(mdb.Spec.Members).
147158
SetMongoDBVersion(mdb.Spec.Version).
148159
SetAutomationConfigVersion(1). // TODO: Correctly set the version
149-
AddVersion(buildVersion406()).
160+
AddVersion(mdbVersionConfig).
150161
Build()
151162
}
152163

164+
func readVersionManifestFromDisk() (automationconfig.VersionManifest, error) {
165+
bytes, err := ioutil.ReadFile(versionManifestFilePath)
166+
if err != nil {
167+
return automationconfig.VersionManifest{}, err
168+
}
169+
return versionManifestFromBytes(bytes)
170+
}
171+
172+
func versionManifestFromBytes(bytes []byte) (automationconfig.VersionManifest, error) {
173+
versionManifest := automationconfig.VersionManifest{}
174+
if err := json.Unmarshal(bytes, &versionManifest); err != nil {
175+
return automationconfig.VersionManifest{}, err
176+
}
177+
return versionManifest, nil
178+
}
179+
153180
// buildService creates a Service that will be used for the Replica Set StatefulSet
154181
// that allows all the members of the STS to see each other.
155182
// TODO: Make sure this Service is as minimal as posible, to not interfere with
@@ -167,36 +194,12 @@ func buildService(mdb mdbv1.MongoDB) corev1.Service {
167194
Build()
168195
}
169196

170-
// buildVersion406 returns a compatible version.
171-
func buildVersion406() automationconfig.MongoDbVersionConfig {
172-
// TODO: For now we only have 2 versions, that match the versions used for testing.
173-
return automationconfig.MongoDbVersionConfig{
174-
Builds: []automationconfig.BuildConfig{
175-
{
176-
Architecture: "amd64",
177-
GitVersion: "caa42a1f75a56c7643d0b68d3880444375ec42e3",
178-
Platform: "linux",
179-
Url: "/linux/mongodb-linux-x86_64-rhel62-4.0.6.tgz",
180-
Flavor: "rhel",
181-
MaxOsVersion: "8.0",
182-
MinOsVersion: "7.0",
183-
},
184-
{
185-
Architecture: "amd64",
186-
GitVersion: "caa42a1f75a56c7643d0b68d3880444375ec42e3",
187-
Platform: "linux",
188-
Url: "/linux/mongodb-linux-x86_64-ubuntu1604-4.0.6.tgz",
189-
Flavor: "ubuntu",
190-
MaxOsVersion: "17.04",
191-
MinOsVersion: "16.04",
192-
},
193-
},
194-
Name: "4.0.6",
197+
func (r ReplicaSetReconciler) buildAutomationConfigConfigMap(mdb mdbv1.MongoDB) (corev1.ConfigMap, error) {
198+
manifest, err := r.manifestProvider()
199+
if err != nil {
200+
return corev1.ConfigMap{}, fmt.Errorf("error reading version manifest from disk: %+v", err)
195201
}
196-
}
197-
198-
func buildAutomationConfigConfigMap(mdb mdbv1.MongoDB) (corev1.ConfigMap, error) {
199-
ac := buildAutomationConfig(mdb)
202+
ac := buildAutomationConfig(mdb, manifest.BuildsForVersion(mdb.Spec.Version))
200203
acBytes, err := json.Marshal(ac)
201204
if err != nil {
202205
return corev1.ConfigMap{}, err

pkg/controller/mongodb/replicaset_controller_test.go

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import (
66
"reflect"
77
"testing"
88

9+
"github.com/mongodb/mongodb-kubernetes-operator/pkg/automationconfig"
10+
911
mdbv1 "github.com/mongodb/mongodb-kubernetes-operator/pkg/apis/mongodb/v1"
1012
"github.com/mongodb/mongodb-kubernetes-operator/pkg/kube/client"
1113
"github.com/mongodb/mongodb-kubernetes-operator/pkg/kube/resourcerequirements"
@@ -34,12 +36,34 @@ func newTestReplicaSet() mdbv1.MongoDB {
3436
}
3537
}
3638

39+
func mockManifestProvider(version string) func() (automationconfig.VersionManifest, error) {
40+
return func() (automationconfig.VersionManifest, error) {
41+
return automationconfig.VersionManifest{
42+
Updated: 0,
43+
Versions: []automationconfig.MongoDbVersionConfig{
44+
{
45+
Name: version,
46+
Builds: []automationconfig.BuildConfig{{
47+
Platform: "platform",
48+
Url: "url",
49+
GitVersion: "gitVersion",
50+
Architecture: "arch",
51+
Flavor: "flavor",
52+
MinOsVersion: "0",
53+
MaxOsVersion: "10",
54+
Modules: []string{},
55+
}},
56+
}},
57+
}, nil
58+
}
59+
}
60+
3761
func TestKubernetesResources_AreCreated(t *testing.T) {
3862
// TODO: Create builder/yaml fixture of some type to construct MDB objects for unit tests
3963
mdb := newTestReplicaSet()
4064

4165
mgr := client.NewManager(&mdb)
42-
r := newReconciler(mgr)
66+
r := newReconciler(mgr, mockManifestProvider(mdb.Spec.Version))
4367

4468
res, err := r.Reconcile(reconcile.Request{NamespacedName: types.NamespacedName{Namespace: mdb.Namespace, Name: mdb.Name}})
4569
assertReconciliationSuccessful(t, res, err)
@@ -56,7 +80,7 @@ func TestKubernetesResources_AreCreated(t *testing.T) {
5680
func TestStatefulSet_IsCorrectlyConfigured(t *testing.T) {
5781
mdb := newTestReplicaSet()
5882
mgr := client.NewManager(&mdb)
59-
r := newReconciler(mgr)
83+
r := newReconciler(mgr, mockManifestProvider(mdb.Spec.Version))
6084
res, err := r.Reconcile(reconcile.Request{NamespacedName: types.NamespacedName{Namespace: mdb.Namespace, Name: mdb.Name}})
6185
assertReconciliationSuccessful(t, res, err)
6286

0 commit comments

Comments
 (0)