Skip to content

Commit

Permalink
deployment independent resource
Browse files Browse the repository at this point in the history
  • Loading branch information
josvazg authored and helderjs committed Oct 4, 2024
1 parent 1c2ccb8 commit f229dbc
Show file tree
Hide file tree
Showing 13 changed files with 717 additions and 119 deletions.
33 changes: 31 additions & 2 deletions config/crd/bases/atlas.mongodb.com_atlasdeployments.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,18 @@ spec:
required:
- name
type: object
connectionSecret:
description: LocalObjectReference is a reference to an object in the
same namespace as the referent
properties:
name:
description: |-
Name of the resource being referred to
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
required:
- name
type: object
deploymentSpec:
description: Configuration for the advanced (v1.5) deployment API
https://www.mongodb.com/docs/atlas/reference/api/clusters/
Expand Down Expand Up @@ -605,6 +617,16 @@ spec:
required:
- name
type: object
externalProjectRef:
description: ExternalProjectRef holds the Atlas project ID the user
belongs to
properties:
id:
description: ID is the Atlas project ID
type: string
required:
- id
type: object
processArgs:
description: ProcessArgs allows to modify Advanced Configuration Options
properties:
Expand Down Expand Up @@ -822,9 +844,16 @@ spec:
- name
- providerSettings
type: object
required:
- projectRef
type: object
x-kubernetes-validations:
- message: must define only one project reference through externalProjectRef
or projectRef
rule: (has(self.externalProjectRef) && !has(self.projectRef)) || (!has(self.externalProjectRef)
&& has(self.projectRef))
- message: must define a local connection secret when referencing an external
project
rule: (has(self.externalProjectRef) && has(self.connectionSecret)) ||
!has(self.externalProjectRef)
status:
description: AtlasDeploymentStatus defines the observed state of AtlasDeployment.
properties:
Expand Down
69 changes: 13 additions & 56 deletions pkg/api/v1/atlasdatabaseuser_types_test.go
Original file line number Diff line number Diff line change
@@ -1,33 +1,22 @@
package v1
package v1 // nolint: dupl

import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"k8s.io/apimachinery/pkg/runtime"

"github.com/mongodb/mongodb-atlas-kubernetes/v2/pkg/api"
"github.com/mongodb/mongodb-atlas-kubernetes/v2/pkg/api/v1/common"
"github.com/mongodb/mongodb-atlas-kubernetes/v2/test/helper/cel"
)

func TestProjectReference(t *testing.T) {
validator, err := cel.VersionValidatorFromFile(t, "../../../config/crd/bases/atlas.mongodb.com_atlasdatabaseusers.yaml", "v1")
require.NoError(t, err)

tests := map[string]struct {
dbUser *AtlasDatabaseUser
expectedErrors []string
}{
tests := projectReferenceTestCase{
"no project reference is set": {
dbUser: &AtlasDatabaseUser{
object: &AtlasDatabaseUser{
Spec: AtlasDatabaseUserSpec{},
},
expectedErrors: []string{"spec: Invalid value: \"object\": must define only one project reference through externalProjectRef or projectRef"},
},
"both project references are set": {
dbUser: &AtlasDatabaseUser{
object: &AtlasDatabaseUser{
Spec: AtlasDatabaseUserSpec{
Project: &common.ResourceRefNamespaced{
Name: "my-project",
Expand All @@ -43,7 +32,7 @@ func TestProjectReference(t *testing.T) {
},
},
"external project references is set": {
dbUser: &AtlasDatabaseUser{
object: &AtlasDatabaseUser{
Spec: AtlasDatabaseUserSpec{
ExternalProjectRef: &ExternalProjectReference{
ID: "my-project-id",
Expand All @@ -55,7 +44,7 @@ func TestProjectReference(t *testing.T) {
},
},
"kubernetes project references is set": {
dbUser: &AtlasDatabaseUser{
object: &AtlasDatabaseUser{
Spec: AtlasDatabaseUserSpec{
Project: &common.ResourceRefNamespaced{
Name: "my-project",
Expand All @@ -65,32 +54,13 @@ func TestProjectReference(t *testing.T) {
},
}

for name, tt := range tests {
t.Run(name, func(t *testing.T) {
unstructuredDBUser, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&tt.dbUser)
require.NoError(t, err)

errs := validator(unstructuredDBUser, nil)

require.Equal(t, len(tt.expectedErrors), len(errs))

for i, err := range errs {
assert.Equal(t, tt.expectedErrors[i], err.Error())
}
})
}
assertProjectReference(t, "../../../config/crd/bases/atlas.mongodb.com_atlasdatabaseusers.yaml", tests)
}

func TestExternalProjectReferenceConnectionSecret(t *testing.T) {
validator, err := cel.VersionValidatorFromFile(t, "../../../config/crd/bases/atlas.mongodb.com_atlasdatabaseusers.yaml", "v1")
require.NoError(t, err)

tests := map[string]struct {
dbUser *AtlasDatabaseUser
expectedErrors []string
}{
tests := projectReferenceTestCase{
"external project references is set without connection secret": {
dbUser: &AtlasDatabaseUser{
object: &AtlasDatabaseUser{
Spec: AtlasDatabaseUserSpec{
ExternalProjectRef: &ExternalProjectReference{
ID: "my-project-id",
Expand All @@ -102,7 +72,7 @@ func TestExternalProjectReferenceConnectionSecret(t *testing.T) {
},
},
"external project references is set with connection secret": {
dbUser: &AtlasDatabaseUser{
object: &AtlasDatabaseUser{
Spec: AtlasDatabaseUserSpec{
ExternalProjectRef: &ExternalProjectReference{
ID: "my-project-id",
Expand All @@ -116,7 +86,7 @@ func TestExternalProjectReferenceConnectionSecret(t *testing.T) {
},
},
"kubernetes project references is set without connection secret": {
dbUser: &AtlasDatabaseUser{
object: &AtlasDatabaseUser{
Spec: AtlasDatabaseUserSpec{
Project: &common.ResourceRefNamespaced{
Name: "my-project",
Expand All @@ -125,7 +95,7 @@ func TestExternalProjectReferenceConnectionSecret(t *testing.T) {
},
},
"kubernetes project references is set with connection secret": {
dbUser: &AtlasDatabaseUser{
object: &AtlasDatabaseUser{
Spec: AtlasDatabaseUserSpec{
Project: &common.ResourceRefNamespaced{
Name: "my-project",
Expand All @@ -140,18 +110,5 @@ func TestExternalProjectReferenceConnectionSecret(t *testing.T) {
},
}

for name, tt := range tests {
t.Run(name, func(t *testing.T) {
unstructuredDBUser, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&tt.dbUser)
require.NoError(t, err)

errs := validator(unstructuredDBUser, nil)

require.Equal(t, len(tt.expectedErrors), len(errs))

for i, err := range errs {
assert.Equal(t, tt.expectedErrors[i], err.Error())
}
})
}
assertExternalProjectReferenceConnectionSecret(t, "../../../config/crd/bases/atlas.mongodb.com_atlasdatabaseusers.yaml", tests)
}
14 changes: 12 additions & 2 deletions pkg/api/v1/atlasdeployment_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,15 @@ const (

// AtlasDeploymentSpec defines the desired state of AtlasDeployment
// Only one of DeploymentSpec, AdvancedDeploymentSpec and ServerlessSpec should be defined
// +kubebuilder:validation:XValidation:rule="(has(self.externalProjectRef) && !has(self.projectRef)) || (!has(self.externalProjectRef) && has(self.projectRef))",message="must define only one project reference through externalProjectRef or projectRef"
// +kubebuilder:validation:XValidation:rule="(has(self.externalProjectRef) && has(self.connectionSecret)) || !has(self.externalProjectRef)",message="must define a local connection secret when referencing an external project"
type AtlasDeploymentSpec struct {
api.LocalCredentialHolder `json:",inline"`

// Project is a reference to AtlasProject resource the deployment belongs to
Project common.ResourceRefNamespaced `json:"projectRef"`
Project *common.ResourceRefNamespaced `json:"projectRef,omitempty"`
// ExternalProjectRef holds the Atlas project ID the user belongs to
ExternalProjectRef *ExternalProjectReference `json:"externalProjectRef,omitempty"`

// Configuration for the advanced (v1.5) deployment API https://www.mongodb.com/docs/atlas/reference/api/clusters/
// +optional
Expand Down Expand Up @@ -520,6 +526,10 @@ func (c *AtlasDeployment) UpdateStatus(conditions []api.Condition, options ...ap
}
}

func (c *AtlasDeployment) Credentials() *api.LocalObjectReference {
return c.Spec.Credentials()
}

// ************************************ Builder methods *************************************************

func NewDeployment(namespace, name, nameInAtlas string) *AtlasDeployment {
Expand Down Expand Up @@ -619,7 +629,7 @@ func (c *AtlasDeployment) WithAtlasName(name string) *AtlasDeployment {
}

func (c *AtlasDeployment) WithProjectName(projectName string) *AtlasDeployment {
c.Spec.Project = common.ResourceRefNamespaced{Name: projectName}
c.Spec.Project = &common.ResourceRefNamespaced{Name: projectName}
return c
}

Expand Down
114 changes: 114 additions & 0 deletions pkg/api/v1/atlasdeployment_types_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package v1 // nolint: dupl

import (
"testing"

"github.com/mongodb/mongodb-atlas-kubernetes/v2/pkg/api"
"github.com/mongodb/mongodb-atlas-kubernetes/v2/pkg/api/v1/common"
)

func TestDeploymentProjectReference(t *testing.T) {
tests := projectReferenceTestCase{
"no project reference is set": {
object: &AtlasDeployment{
Spec: AtlasDeploymentSpec{},
},
expectedErrors: []string{"spec: Invalid value: \"object\": must define only one project reference through externalProjectRef or projectRef"},
},
"both project references are set": {
object: &AtlasDeployment{
Spec: AtlasDeploymentSpec{
Project: &common.ResourceRefNamespaced{
Name: "my-project",
},
ExternalProjectRef: &ExternalProjectReference{
ID: "my-project-id",
},
},
},
expectedErrors: []string{
"spec: Invalid value: \"object\": must define only one project reference through externalProjectRef or projectRef",
"spec: Invalid value: \"object\": must define a local connection secret when referencing an external project",
},
},
"external project references is set": {
object: &AtlasDeployment{
Spec: AtlasDeploymentSpec{
ExternalProjectRef: &ExternalProjectReference{
ID: "my-project-id",
},
},
},
expectedErrors: []string{
"spec: Invalid value: \"object\": must define a local connection secret when referencing an external project",
},
},
"kubernetes project references is set": {
object: &AtlasDeployment{
Spec: AtlasDeploymentSpec{
Project: &common.ResourceRefNamespaced{
Name: "my-project",
},
},
},
},
}

assertProjectReference(t, "../../../config/crd/bases/atlas.mongodb.com_atlasdeployments.yaml", tests)
}

func TestDeploymentExternalProjectReferenceConnectionSecret(t *testing.T) {
tests := projectReferenceTestCase{
"external project references is set without connection secret": {
object: &AtlasDeployment{
Spec: AtlasDeploymentSpec{
ExternalProjectRef: &ExternalProjectReference{
ID: "my-project-id",
},
},
},
expectedErrors: []string{
"spec: Invalid value: \"object\": must define a local connection secret when referencing an external project",
},
},
"external project references is set with connection secret": {
object: &AtlasDeployment{
Spec: AtlasDeploymentSpec{
ExternalProjectRef: &ExternalProjectReference{
ID: "my-project-id",
},
LocalCredentialHolder: api.LocalCredentialHolder{
ConnectionSecret: &api.LocalObjectReference{
Name: "my-dbuser-connection-secret",
},
},
},
},
},
"kubernetes project references is set without connection secret": {
object: &AtlasDeployment{
Spec: AtlasDeploymentSpec{
Project: &common.ResourceRefNamespaced{
Name: "my-project",
},
},
},
},
"kubernetes project references is set with connection secret": {
object: &AtlasDeployment{
Spec: AtlasDeploymentSpec{
Project: &common.ResourceRefNamespaced{
Name: "my-project",
},
LocalCredentialHolder: api.LocalCredentialHolder{
ConnectionSecret: &api.LocalObjectReference{
Name: "my-dbuser-connection-secret",
},
},
},
},
},
}

assertExternalProjectReferenceConnectionSecret(t, "../../../config/crd/bases/atlas.mongodb.com_atlasdeployments.yaml", tests)
}
Loading

0 comments on commit f229dbc

Please sign in to comment.