Skip to content

Commit cf33b1c

Browse files
josvazghelderjs
andauthored
CLOUDP-190400: Merge deletion protection bits (#1026)
* Add deletion protection flags to manager and support in database_user controller (#1003) * CLOUDP-175080: Support deletion protection for Atlas projects (#1028) * Disable and hide deletion protection (#1052) Signed-off-by: Jose Vazquez <[email protected]> --------- Signed-off-by: Jose Vazquez <[email protected]> Co-authored-by: Helder Santana <[email protected]>
1 parent 1768b4b commit cf33b1c

25 files changed

+1971
-1110
lines changed

Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ ENV TARGET_OS=${TARGETOS}
2727

2828
RUN make manager
2929

30-
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.8
30+
FROM registry.access.redhat.com/ubi9/ubi-minimal:9.2
3131

32-
RUN microdnf install yum &&\
32+
RUN microdnf install -y yum &&\
3333
yum -y update &&\
3434
yum -y upgrade &&\
3535
yum clean all &&\

cmd/manager/main.go

Lines changed: 76 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ import (
2525
"strings"
2626
"time"
2727

28-
"github.com/mongodb/mongodb-atlas-kubernetes/pkg/version"
29-
3028
"go.uber.org/zap/zapcore"
3129
ctrzap "sigs.k8s.io/controller-runtime/pkg/log/zap"
3230

@@ -52,7 +50,17 @@ import (
5250
"github.com/mongodb/mongodb-atlas-kubernetes/pkg/controller/connectionsecret"
5351
"github.com/mongodb/mongodb-atlas-kubernetes/pkg/controller/watch"
5452
"github.com/mongodb/mongodb-atlas-kubernetes/pkg/util/kube"
55-
// +kubebuilder:scaffold:imports
53+
"github.com/mongodb/mongodb-atlas-kubernetes/pkg/version"
54+
)
55+
56+
const (
57+
objectDeletionProtectionFlag = "object-deletion-protection"
58+
subobjectDeletionProtectionFlag = "subobject-deletion-protection"
59+
objectDeletionProtectionDefault = false
60+
subobjectDeletionProtectionDefault = false
61+
62+
objectDeletionProtectionEnvVar = "UNSUPPORTED_OBJECT_DELETION_PROTECTION"
63+
subobjectDeletionProtectionEnvVar = "UNSUPPORTED_SUBOBJECT_DELETION_PROTECTION"
5664
)
5765

5866
var (
@@ -62,9 +70,7 @@ var (
6270

6371
func init() {
6472
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
65-
6673
utilruntime.Must(mdbv1.AddToScheme(scheme))
67-
// +kubebuilder:scaffold:scheme
6874
}
6975

7076
func main() {
@@ -144,28 +150,32 @@ func main() {
144150
}
145151

146152
if err = (&atlasproject.AtlasProjectReconciler{
147-
Client: mgr.GetClient(),
148-
Log: logger.Named("controllers").Named("AtlasProject").Sugar(),
149-
Scheme: mgr.GetScheme(),
150-
AtlasDomain: config.AtlasDomain,
151-
ResourceWatcher: watch.NewResourceWatcher(),
152-
GlobalAPISecret: config.GlobalAPISecret,
153-
GlobalPredicates: globalPredicates,
154-
EventRecorder: mgr.GetEventRecorderFor("AtlasProject"),
153+
Client: mgr.GetClient(),
154+
Log: logger.Named("controllers").Named("AtlasProject").Sugar(),
155+
Scheme: mgr.GetScheme(),
156+
AtlasDomain: config.AtlasDomain,
157+
ResourceWatcher: watch.NewResourceWatcher(),
158+
GlobalAPISecret: config.GlobalAPISecret,
159+
GlobalPredicates: globalPredicates,
160+
EventRecorder: mgr.GetEventRecorderFor("AtlasProject"),
161+
ObjectDeletionProtection: config.ObjectDeletionProtection,
162+
SubObjectDeletionProtection: config.SubObjectDeletionProtection,
155163
}).SetupWithManager(mgr); err != nil {
156164
setupLog.Error(err, "unable to create controller", "controller", "AtlasProject")
157165
os.Exit(1)
158166
}
159167

160168
if err = (&atlasdatabaseuser.AtlasDatabaseUserReconciler{
161-
Client: mgr.GetClient(),
162-
Log: logger.Named("controllers").Named("AtlasDatabaseUser").Sugar(),
163-
Scheme: mgr.GetScheme(),
164-
AtlasDomain: config.AtlasDomain,
165-
ResourceWatcher: watch.NewResourceWatcher(),
166-
GlobalAPISecret: config.GlobalAPISecret,
167-
GlobalPredicates: globalPredicates,
168-
EventRecorder: mgr.GetEventRecorderFor("AtlasDatabaseUser"),
169+
ResourceWatcher: watch.NewResourceWatcher(),
170+
Client: mgr.GetClient(),
171+
Log: logger.Named("controllers").Named("AtlasDatabaseUser").Sugar(),
172+
Scheme: mgr.GetScheme(),
173+
AtlasDomain: config.AtlasDomain,
174+
GlobalAPISecret: config.GlobalAPISecret,
175+
EventRecorder: mgr.GetEventRecorderFor("AtlasDatabaseUser"),
176+
GlobalPredicates: globalPredicates,
177+
ObjectDeletionProtection: config.ObjectDeletionProtection,
178+
SubObjectDeletionProtection: config.SubObjectDeletionProtection,
169179
}).SetupWithManager(mgr); err != nil {
170180
setupLog.Error(err, "unable to create controller", "controller", "AtlasDatabaseUser")
171181
os.Exit(1)
@@ -203,15 +213,17 @@ func main() {
203213
}
204214

205215
type Config struct {
206-
AtlasDomain string
207-
EnableLeaderElection bool
208-
MetricsAddr string
209-
Namespace string
210-
WatchedNamespaces map[string]bool
211-
ProbeAddr string
212-
GlobalAPISecret client.ObjectKey
213-
LogLevel string
214-
LogEncoder string
216+
AtlasDomain string
217+
EnableLeaderElection bool
218+
MetricsAddr string
219+
Namespace string
220+
WatchedNamespaces map[string]bool
221+
ProbeAddr string
222+
GlobalAPISecret client.ObjectKey
223+
LogLevel string
224+
LogEncoder string
225+
ObjectDeletionProtection bool
226+
SubObjectDeletionProtection bool
215227
}
216228

217229
// ParseConfiguration fills the 'OperatorConfig' from the flags passed to the program
@@ -251,6 +263,8 @@ func parseConfiguration() Config {
251263
config.Namespace = watchedNamespace
252264
}
253265

266+
configureDeletionProtection(&config)
267+
254268
return config
255269
}
256270

@@ -303,3 +317,35 @@ func initCustomZapLogger(level, encoding string) (*zap.Logger, error) {
303317
}
304318
return cfg.Build()
305319
}
320+
321+
func configureDeletionProtection(config *Config) {
322+
if config == nil {
323+
return
324+
}
325+
config.ObjectDeletionProtection = objectDeletionProtectionDefault
326+
config.SubObjectDeletionProtection = subobjectDeletionProtectionDefault
327+
328+
// TODO: replace with the CLI flags at feature completion
329+
enableDeletionProtectionFromEnvVars(config, version.Version)
330+
}
331+
332+
func enableDeletionProtectionFromEnvVars(config *Config, v string) {
333+
if version.IsRelease(v) {
334+
if isOn(os.Getenv(objectDeletionProtectionEnvVar)) ||
335+
isOn(os.Getenv(subobjectDeletionProtectionEnvVar)) {
336+
log.Printf("Deletion Protection feature is not available yet in production releases")
337+
}
338+
return
339+
}
340+
341+
if isOn(os.Getenv(objectDeletionProtectionEnvVar)) {
342+
config.ObjectDeletionProtection = true
343+
}
344+
if isOn(os.Getenv(subobjectDeletionProtectionEnvVar)) {
345+
config.SubObjectDeletionProtection = true
346+
}
347+
}
348+
349+
func isOn(value string) bool {
350+
return strings.ToLower(value) == "on"
351+
}

cmd/manager/main_test.go

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package main
2+
3+
import (
4+
"os"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
9+
"github.com/mongodb/mongodb-atlas-kubernetes/pkg/version"
10+
)
11+
12+
const (
13+
nonReleaseVersion = "1.8.0-30-g81233c6-dirty"
14+
releaseVersion = "1.9.0-certified"
15+
)
16+
17+
func TestDeletionProtectionDisabledByDefault(t *testing.T) {
18+
os.Unsetenv(objectDeletionProtectionEnvVar)
19+
os.Unsetenv(subobjectDeletionProtectionEnvVar)
20+
21+
cfg := Config{
22+
ObjectDeletionProtection: objectDeletionProtectionDefault,
23+
SubObjectDeletionProtection: subobjectDeletionProtectionDefault,
24+
}
25+
enableDeletionProtectionFromEnvVars(&cfg, version.DefaultVersion)
26+
27+
assert.Equal(t, false, cfg.ObjectDeletionProtection)
28+
assert.Equal(t, false, cfg.SubObjectDeletionProtection)
29+
}
30+
31+
func TestDeletionProtectionIgnoredOnReleases(t *testing.T) {
32+
version.Version = releaseVersion
33+
os.Setenv(objectDeletionProtectionEnvVar, "On")
34+
os.Setenv(subobjectDeletionProtectionEnvVar, "On")
35+
36+
cfg := Config{
37+
ObjectDeletionProtection: objectDeletionProtectionDefault,
38+
SubObjectDeletionProtection: subobjectDeletionProtectionDefault,
39+
}
40+
enableDeletionProtectionFromEnvVars(&cfg, releaseVersion)
41+
42+
assert.Equal(t, false, cfg.ObjectDeletionProtection)
43+
assert.Equal(t, false, cfg.SubObjectDeletionProtection)
44+
}
45+
46+
func TestDeletionProtectionEnabledAsEnvVars(t *testing.T) {
47+
testCases := []struct {
48+
title string
49+
objDelProtect bool
50+
subObjDelProtect bool
51+
}{
52+
{
53+
"both env vars set on non release version enables both protections",
54+
true,
55+
true,
56+
},
57+
{
58+
"obj env var set on non release version enables obj protection only",
59+
true,
60+
false,
61+
},
62+
{
63+
"subobj env var set on non release version enables subobj protection only",
64+
false,
65+
true,
66+
},
67+
}
68+
for _, tc := range testCases {
69+
t.Run(tc.title, func(t *testing.T) {
70+
os.Unsetenv(objectDeletionProtectionEnvVar)
71+
os.Unsetenv(subobjectDeletionProtectionEnvVar)
72+
if tc.objDelProtect {
73+
os.Setenv(objectDeletionProtectionEnvVar, "On")
74+
}
75+
if tc.subObjDelProtect {
76+
os.Setenv(subobjectDeletionProtectionEnvVar, "On")
77+
}
78+
79+
cfg := Config{
80+
ObjectDeletionProtection: objectDeletionProtectionDefault,
81+
SubObjectDeletionProtection: subobjectDeletionProtectionDefault,
82+
}
83+
enableDeletionProtectionFromEnvVars(&cfg, nonReleaseVersion)
84+
85+
assert.Equal(t, tc.objDelProtect, cfg.ObjectDeletionProtection)
86+
assert.Equal(t, tc.subObjDelProtect, cfg.SubObjectDeletionProtection)
87+
})
88+
}
89+
}

pkg/api/v1/atlascustomresource.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ type AtlasCustomResource interface {
1818
}
1919

2020
var _ AtlasCustomResource = &AtlasProject{}
21-
2221
var _ AtlasCustomResource = &AtlasDeployment{}
23-
22+
var _ AtlasCustomResource = &AtlasDatabaseUser{}
2423
var _ AtlasCustomResource = &AtlasDataFederation{}

pkg/api/v1/atlasproject_types.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,8 +226,8 @@ func (p *AtlasProject) WithLabels(labels map[string]string) *AtlasProject {
226226
return p
227227
}
228228

229-
func (p *AtlasProject) WithAnnotations(labels map[string]string) *AtlasProject {
230-
p.Labels = labels
229+
func (p *AtlasProject) WithAnnotations(annotations map[string]string) *AtlasProject {
230+
p.Annotations = annotations
231231
return p
232232
}
233233

pkg/api/v1/zz_generated.deepcopy.go

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)