-
Notifications
You must be signed in to change notification settings - Fork 77
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
CLOUDP-186825: Add deletion protection to deployments
Signed-off-by: Jose Vazquez <jose.vazquez@mongodb.com>
- Loading branch information
Showing
11 changed files
with
719 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
package customresource_test | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
|
||
"sigs.k8s.io/controller-runtime/pkg/client/fake" | ||
|
||
mdbv1 "github.com/mongodb/mongodb-atlas-kubernetes/pkg/api/v1" | ||
"github.com/mongodb/mongodb-atlas-kubernetes/pkg/controller/customresource" | ||
) | ||
|
||
func sampleResource() *mdbv1.AtlasDatabaseUser { | ||
return &mdbv1.AtlasDatabaseUser{ | ||
Spec: mdbv1.AtlasDatabaseUserSpec{}, | ||
} | ||
} | ||
|
||
func taggedResource(tag, value string) *mdbv1.AtlasDatabaseUser { | ||
dbUser := sampleResource() | ||
annot := map[string]string{} | ||
annot[tag] = value | ||
dbUser.SetAnnotations(annot) | ||
return dbUser | ||
} | ||
|
||
func testOpChecker(reply bool) customresource.OperatorChecker { | ||
return func(resource mdbv1.AtlasCustomResource) (bool, error) { | ||
return reply, nil | ||
} | ||
} | ||
|
||
func testAtlasChecker(reply bool) customresource.AtlasChecker { | ||
return func(resource mdbv1.AtlasCustomResource) (bool, error) { | ||
return reply, nil | ||
} | ||
} | ||
|
||
var ErrOpChecker = fmt.Errorf("operator checker failed") | ||
|
||
func failedOpChecker(err error) customresource.OperatorChecker { | ||
return func(resource mdbv1.AtlasCustomResource) (bool, error) { | ||
return false, err | ||
} | ||
} | ||
|
||
var ErrAtlasChecker = fmt.Errorf("atlas checker failed") | ||
|
||
func failedAtlasChecker(err error) customresource.AtlasChecker { | ||
return func(resource mdbv1.AtlasCustomResource) (bool, error) { | ||
return false, err | ||
} | ||
} | ||
|
||
func TestWithoutProtectionIsOwned(t *testing.T) { | ||
owned, err := customresource.IsOwner(sampleResource(), false, nil, nil) | ||
assert.NoError(t, err) | ||
assert.Equal(t, owned, true) | ||
} | ||
|
||
func TestProtected(t *testing.T) { | ||
tests := []struct { | ||
title string | ||
opChecker customresource.OperatorChecker | ||
atlasChecker customresource.AtlasChecker | ||
expectedOwned bool | ||
}{ | ||
{"managed is owned", testOpChecker(true), nil, true}, | ||
{"unmanaged but not in Atlas is owned", testOpChecker(false), testAtlasChecker(false), true}, | ||
{"unmanaged but in Atlas is NOT owned", testOpChecker(false), testAtlasChecker(true), false}, | ||
} | ||
for _, tc := range tests { | ||
t.Run(fmt.Sprintf("Protected and %s", tc.title), func(t *testing.T) { | ||
owned, err := customresource.IsOwner(sampleResource(), true, tc.opChecker, tc.atlasChecker) | ||
assert.NoError(t, err) | ||
assert.Equal(t, tc.expectedOwned, owned) | ||
}) | ||
} | ||
} | ||
|
||
func TestProtectedFailures(t *testing.T) { | ||
tests := []struct { | ||
title string | ||
opChecker customresource.OperatorChecker | ||
atlasChecker customresource.AtlasChecker | ||
expectedFailure error | ||
}{ | ||
{"When all checkers fail, operator checker fails first", failedOpChecker(ErrOpChecker), failedAtlasChecker(ErrAtlasChecker), ErrOpChecker}, | ||
{"When unamanaged and atlas checker fails we get that its failure", testOpChecker(false), failedAtlasChecker(ErrAtlasChecker), ErrAtlasChecker}, | ||
} | ||
for _, tc := range tests { | ||
t.Run(tc.title, func(t *testing.T) { | ||
_, err := customresource.IsOwner(sampleResource(), true, tc.opChecker, tc.atlasChecker) | ||
assert.Equal(t, tc.expectedFailure, err) | ||
}) | ||
} | ||
} | ||
|
||
func TestIsResourceProtected(t *testing.T) { | ||
tests := []struct { | ||
title string | ||
protectionFlag bool | ||
resource mdbv1.AtlasCustomResource | ||
expectedProtected bool | ||
}{ | ||
{"Resource without tags with the flag set is protected", true, sampleResource(), true}, | ||
{"Resource without tags with the flag unset isn't protected", false, sampleResource(), false}, | ||
{ | ||
"Resource with keep tag is protected", | ||
false, | ||
taggedResource(customresource.ResourcePolicyAnnotation, customresource.ResourcePolicyKeep), | ||
true, | ||
}, | ||
{ | ||
"Resource with delete tag and protected flag set is NOT protected", | ||
true, | ||
taggedResource(customresource.ResourcePolicyAnnotation, customresource.ResourcePolicyDelete), | ||
false, | ||
}, | ||
{ | ||
"Resource with delete tag and protected flag unset isn't protected", | ||
false, | ||
taggedResource(customresource.ResourcePolicyAnnotation, customresource.ResourcePolicyDelete), | ||
false, | ||
}, | ||
} | ||
for _, tc := range tests { | ||
t.Run(tc.title, func(t *testing.T) { | ||
assert.Equal(t, tc.expectedProtected, customresource.IsResourceProtected(tc.resource, tc.protectionFlag)) | ||
}) | ||
} | ||
} | ||
|
||
func TestApplyLastConfigApplied(t *testing.T) { | ||
resource := sampleResource() | ||
resource.Spec.Username = "test-user" | ||
|
||
// ignore the error due to not configuring the fake client | ||
// we are not checking that, we are only interested on a new annotation in resource | ||
_ = customresource.ApplyLastConfigApplied(context.Background(), resource, fake.NewClientBuilder().Build()) | ||
|
||
annot := resource.GetAnnotations() | ||
assert.NotEmpty(t, annot) | ||
expectedConfig := `{"projectRef":{"name":"","namespace":""},"roles":null,"username":"test-user"}` | ||
assert.Equal(t, annot[customresource.AnnotationLastAppliedConfiguration], expectedConfig) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.