Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CLOUDP-280230: Refactor adds Project Dual Reference #1971

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .licenses-gomod.sha256
Original file line number Diff line number Diff line change
@@ -1 +1 @@
100644 a979d1bdefc865411988e3f2d3cd96b356a75eef go.mod
100644 b69877498f1fa3e2d18a80d212dea38329f5951c go.mod
19 changes: 5 additions & 14 deletions api/credentials.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package api

import "sigs.k8s.io/controller-runtime/pkg/client"

type LocalRef string

// +k8s:deepcopy-gen=false
Expand All @@ -11,19 +13,8 @@ type CredentialsProvider interface {

// +k8s:deepcopy-gen=false

// ResourceWithCredentials is to be implemented by all CRDs using custom local credentials
type ResourceWithCredentials interface {
// ObjectWithCredentials is a Kubernetes Object interface with credentials
type ObjectWithCredentials interface {
client.Object
CredentialsProvider
GetName() string
GetNamespace() string
}

// LocalCredentialHolder is to be embedded by Specs of CRDs using custom local credentials
type LocalCredentialHolder struct {
// Name of the secret containing Atlas API private and public keys
ConnectionSecret *LocalObjectReference `json:"connectionSecret,omitempty"`
}

func (ch *LocalCredentialHolder) Credentials() *LocalObjectReference {
return ch.ConnectionSecret
}
18 changes: 8 additions & 10 deletions api/v1/atlascustomrole_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

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

Expand All @@ -30,7 +29,11 @@ type AtlasCustomRole struct {
}

func (in *AtlasCustomRole) Credentials() *api.LocalObjectReference {
return in.Spec.Credentials()
return in.Spec.ConnectionSecret
}

func (in *AtlasCustomRole) ProjectDualRef() *ProjectDualReference {
return &in.Spec.ProjectDualReference
}

func (in *AtlasCustomRole) UpdateStatus(conditions []api.Condition, options ...api.Option) {
Expand All @@ -54,12 +57,7 @@ type AtlasCustomRoleList struct {
// +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 AtlasCustomRoleSpec struct {
api.LocalCredentialHolder `json:",inline"`
Role CustomRole `json:"role"`
// Optional ID of the Atlas Project this role is attached to. Mutually exclusive with "projectRef" field
// +optional
ExternalProjectIDRef *ExternalProjectReference `json:"externalProjectRef"`
// Optional reference to an AtlasProject custom resource. Mutually exclusive with "externalProjectRef" field
// +optional
ProjectRef *common.ResourceRefNamespaced `json:"projectRef,omitempty"`
// ProjectReference is the dual external or kubernetes reference with access credentials
ProjectDualReference `json:",inline"`
Role CustomRole `json:"role"`
}
41 changes: 20 additions & 21 deletions api/v1/atlasdatabaseuser_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,8 @@ const (
// +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 AtlasDatabaseUserSpec struct {
api.LocalCredentialHolder `json:",inline"`

// Project is a reference to AtlasProject resource the user belongs to
Project *common.ResourceRefNamespaced `json:"projectRef,omitempty"`
// ExternalProjectRef holds the Atlas project ID the user belongs to
ExternalProjectRef *ExternalProjectReference `json:"externalProjectRef,omitempty"`
// ProjectReference is the dual external or kubernetes reference with access credentials
ProjectDualReference `json:",inline"`

// DatabaseName is a Database against which Atlas authenticates the user.
// If the user authenticates with AWS IAM, x.509, LDAP, or OIDC Workload this value should be '$external'.
Expand Down Expand Up @@ -172,10 +168,10 @@ type ScopeSpec struct {

func (p AtlasDatabaseUser) AtlasProjectObjectKey() client.ObjectKey {
ns := p.Namespace
if p.Spec.Project.Namespace != "" {
ns = p.Spec.Project.Namespace
if p.Spec.ProjectRef.Namespace != "" {
ns = p.Spec.ProjectRef.Namespace
}
return kube.ObjectKey(ns, p.Spec.Project.Name)
return kube.ObjectKey(ns, p.Spec.ProjectRef.Name)
}

func (p AtlasDatabaseUser) PasswordSecretObjectKey() *client.ObjectKey {
Expand All @@ -190,6 +186,14 @@ func (p *AtlasDatabaseUser) GetStatus() api.Status {
return p.Status
}

func (p *AtlasDatabaseUser) Credentials() *api.LocalObjectReference {
return p.Spec.ConnectionSecret
}

func (p *AtlasDatabaseUser) ProjectDualRef() *ProjectDualReference {
return &p.Spec.ProjectDualReference
}

func (p *AtlasDatabaseUser) UpdateStatus(conditions []api.Condition, options ...api.Option) {
p.Status.Conditions = conditions
p.Status.ObservedGeneration = p.ObjectMeta.Generation
Expand Down Expand Up @@ -257,8 +261,10 @@ func NewDBUser(namespace, name, dbUserName, projectName string) *AtlasDatabaseUs
Namespace: namespace,
},
Spec: AtlasDatabaseUserSpec{
Username: dbUserName,
Project: &common.ResourceRefNamespaced{Name: projectName},
Username: dbUserName,
ProjectDualReference: ProjectDualReference{
ProjectRef: &common.ResourceRefNamespaced{Name: projectName},
},
PasswordSecret: &common.ResourceRef{},
Roles: []RoleSpec{},
Scopes: []ScopeSpec{},
Expand Down Expand Up @@ -302,23 +308,16 @@ func (p *AtlasDatabaseUser) WithDeleteAfterDate(date string) *AtlasDatabaseUser
}

func (p *AtlasDatabaseUser) WithExternaLProject(projectID, credentialsName string) *AtlasDatabaseUser {
p.Spec.Project = nil
p.Spec.ProjectRef = nil
p.Spec.ExternalProjectRef = &ExternalProjectReference{
ID: projectID,
}
p.Spec.LocalCredentialHolder = api.LocalCredentialHolder{
ConnectionSecret: &api.LocalObjectReference{
Name: credentialsName,
},
p.Spec.ConnectionSecret = &api.LocalObjectReference{
Name: credentialsName,
}

return p
}

func (p AtlasDatabaseUser) Credentials() *api.LocalObjectReference {
return p.Spec.Credentials()
}

func DefaultDBUser(namespace, username, projectName string) *AtlasDatabaseUser {
return NewDBUser(namespace, username, username, projectName).WithRole("clusterMonitor", "admin", "")
}
52 changes: 31 additions & 21 deletions api/v1/atlasdatabaseuser_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ func TestProjectReference(t *testing.T) {
"both project references are set": {
object: &AtlasDatabaseUser{
Spec: AtlasDatabaseUserSpec{
Project: &common.ResourceRefNamespaced{
Name: "my-project",
},
ExternalProjectRef: &ExternalProjectReference{
ID: "my-project-id",
ProjectDualReference: ProjectDualReference{
ProjectRef: &common.ResourceRefNamespaced{
Name: "my-project",
},
ExternalProjectRef: &ExternalProjectReference{
ID: "my-project-id",
},
},
},
},
Expand All @@ -34,8 +36,10 @@ func TestProjectReference(t *testing.T) {
"external project references is set": {
object: &AtlasDatabaseUser{
Spec: AtlasDatabaseUserSpec{
ExternalProjectRef: &ExternalProjectReference{
ID: "my-project-id",
ProjectDualReference: ProjectDualReference{
ExternalProjectRef: &ExternalProjectReference{
ID: "my-project-id",
},
},
},
},
Expand All @@ -46,8 +50,10 @@ func TestProjectReference(t *testing.T) {
"kubernetes project references is set": {
object: &AtlasDatabaseUser{
Spec: AtlasDatabaseUserSpec{
Project: &common.ResourceRefNamespaced{
Name: "my-project",
ProjectDualReference: ProjectDualReference{
ProjectRef: &common.ResourceRefNamespaced{
Name: "my-project",
},
},
},
},
Expand All @@ -62,8 +68,10 @@ func TestExternalProjectReferenceConnectionSecret(t *testing.T) {
"external project references is set without connection secret": {
object: &AtlasDatabaseUser{
Spec: AtlasDatabaseUserSpec{
ExternalProjectRef: &ExternalProjectReference{
ID: "my-project-id",
ProjectDualReference: ProjectDualReference{
ExternalProjectRef: &ExternalProjectReference{
ID: "my-project-id",
},
},
},
},
Expand All @@ -74,10 +82,10 @@ func TestExternalProjectReferenceConnectionSecret(t *testing.T) {
"external project references is set with connection secret": {
object: &AtlasDatabaseUser{
Spec: AtlasDatabaseUserSpec{
ExternalProjectRef: &ExternalProjectReference{
ID: "my-project-id",
},
LocalCredentialHolder: api.LocalCredentialHolder{
ProjectDualReference: ProjectDualReference{
ExternalProjectRef: &ExternalProjectReference{
ID: "my-project-id",
},
ConnectionSecret: &api.LocalObjectReference{
Name: "my-dbuser-connection-secret",
},
Expand All @@ -88,19 +96,21 @@ func TestExternalProjectReferenceConnectionSecret(t *testing.T) {
"kubernetes project references is set without connection secret": {
object: &AtlasDatabaseUser{
Spec: AtlasDatabaseUserSpec{
Project: &common.ResourceRefNamespaced{
Name: "my-project",
ProjectDualReference: ProjectDualReference{
ProjectRef: &common.ResourceRefNamespaced{
Name: "my-project",
},
},
},
},
},
"kubernetes project references is set with connection secret": {
object: &AtlasDatabaseUser{
Spec: AtlasDatabaseUserSpec{
Project: &common.ResourceRefNamespaced{
Name: "my-project",
},
LocalCredentialHolder: api.LocalCredentialHolder{
ProjectDualReference: ProjectDualReference{
ProjectRef: &common.ResourceRefNamespaced{
Name: "my-project",
},
ConnectionSecret: &api.LocalObjectReference{
Name: "my-dbuser-connection-secret",
},
Expand Down
30 changes: 14 additions & 16 deletions api/v1/atlasdeployment_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,8 @@ const (
// +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,omitempty"`
// ExternalProjectRef holds the Atlas project ID the user belongs to
ExternalProjectRef *ExternalProjectReference `json:"externalProjectRef,omitempty"`
// ProjectReference is the dual external or kubernetes reference with access credentials
ProjectDualReference `json:",inline"`

// Configuration for the advanced (v1.5) deployment API https://www.mongodb.com/docs/atlas/reference/api/clusters/
// +optional
Expand Down Expand Up @@ -505,10 +501,10 @@ type AtlasDeploymentList struct {

func (c AtlasDeployment) AtlasProjectObjectKey() client.ObjectKey {
ns := c.Namespace
if c.Spec.Project.Namespace != "" {
ns = c.Spec.Project.Namespace
if c.Spec.ProjectRef.Namespace != "" {
ns = c.Spec.ProjectRef.Namespace
}
return kube.ObjectKey(ns, c.Spec.Project.Name)
return kube.ObjectKey(ns, c.Spec.ProjectRef.Name)
}

func (c *AtlasDeployment) GetStatus() api.Status {
Expand All @@ -527,7 +523,11 @@ func (c *AtlasDeployment) UpdateStatus(conditions []api.Condition, options ...ap
}

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

func (c *AtlasDeployment) ProjectDualRef() *ProjectDualReference {
return &c.Spec.ProjectDualReference
}

// ************************************ Builder methods *************************************************
Expand Down Expand Up @@ -633,7 +633,7 @@ func (c *AtlasDeployment) WithAtlasName(name string) *AtlasDeployment {
}

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

Expand Down Expand Up @@ -689,14 +689,12 @@ func (c *AtlasDeployment) WithSearchNodes(instanceSize string, count uint8) *Atl
}

func (c *AtlasDeployment) WithExternaLProject(projectID, credentialsName string) *AtlasDeployment {
c.Spec.Project = nil
c.Spec.ProjectRef = nil
c.Spec.ExternalProjectRef = &ExternalProjectReference{
ID: projectID,
}
c.Spec.LocalCredentialHolder = api.LocalCredentialHolder{
ConnectionSecret: &api.LocalObjectReference{
Name: credentialsName,
},
c.Spec.ConnectionSecret = &api.LocalObjectReference{
Name: credentialsName,
}

return c
Expand Down
Loading
Loading