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-292365: Support Flex Clusters #2030

Open
wants to merge 33 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
44934a5
Add initial Flex types
roothorp Jan 2, 2025
285b047
Add Flex to translation layer
roothorp Jan 6, 2025
41c5378
Add Flex to Deployment controller
roothorp Jan 6, 2025
c67934d
Generate mocks
roothorp Jan 6, 2025
1b63909
Correctly propogate Flex API to controllers
roothorp Jan 9, 2025
cd636a0
fix tests
roothorp Jan 9, 2025
cb52847
Add SDK Client Set to Contract tests
roothorp Jan 9, 2025
fcfa362
fix int tests
roothorp Jan 13, 2025
a3e1c00
check for flex before normal cluster
roothorp Jan 13, 2025
f72fb2f
Add flex helper funcs
roothorp Jan 13, 2025
4084f7e
Update deployment validation to account for flex
roothorp Jan 13, 2025
9729e19
small fixes after rebase
roothorp Jan 13, 2025
935f65d
Fix remaining broken tests
roothorp Jan 13, 2025
91f259b
add e2e test
roothorp Jan 16, 2025
bdabc78
changes per reviews
roothorp Jan 16, 2025
fe948ea
Ignore dupl in _test.go files
roothorp Jan 16, 2025
c05ab5a
api: add optional kubebuilder for flex spec
s-urbaniak Jan 16, 2025
b1b7f77
be more tolerant for flex API not available
s-urbaniak Jan 16, 2025
c9d0e21
flex: respect gov
s-urbaniak Jan 16, 2025
cf56013
address linter comments
s-urbaniak Jan 17, 2025
fd3affa
enable flex
s-urbaniak Jan 17, 2025
7e23be9
use ako deployment type for retrieving clusters from Atlas
s-urbaniak Jan 17, 2025
395aade
fix unit tests
s-urbaniak Jan 17, 2025
64572ea
fix unit tests
s-urbaniak Jan 17, 2025
32c5ba6
regenerate mocks
s-urbaniak Jan 17, 2025
8545ad4
remove checking for serverless vs. non-serverless constraints as it b…
s-urbaniak Jan 17, 2025
45be1fa
check for wrong cluster types explicitely
s-urbaniak Jan 17, 2025
75ec48f
act on not found errors only in GetFlexCluster
s-urbaniak Jan 17, 2025
9f12f2f
use deployment names for getcluster
s-urbaniak Jan 17, 2025
d931e10
add error code from Atlas signalling wrong API call
s-urbaniak Jan 17, 2025
f3a009a
fix tests
s-urbaniak Jan 17, 2025
161a172
fix linter
s-urbaniak Jan 17, 2025
19e283b
Fix flex e2e
roothorp Jan 17, 2025
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
1 change: 1 addition & 0 deletions .github/workflows/test-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ jobs:
"reconcile-one",
"reconcile-two",
"backup-compliance",
"flex",
]
steps:
- name: Get repo files from cache
Expand Down
74 changes: 74 additions & 0 deletions api/v1/atlasdeployment_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ type AtlasDeploymentSpec struct {
// ProcessArgs allows to modify Advanced Configuration Options
// +optional
ProcessArgs *ProcessArgs `json:"processArgs,omitempty"`

// Configuration for the Flex cluster API. https://www.mongodb.com/docs/atlas/reference/api-resources-spec/v2/#tag/Flex-Clusters
// +optional
FlexSpec *FlexSpec `json:"flexSpec,omitempty"`
}

type SearchNode struct {
Expand Down Expand Up @@ -465,6 +469,9 @@ func (c *AtlasDeployment) GetDeploymentName() string {
if c.IsServerless() {
return c.Spec.ServerlessSpec.Name
}
if c.IsFlex() {
return c.Spec.FlexSpec.Name
}
if c.IsAdvancedDeployment() {
return c.Spec.DeploymentSpec.Name
}
Expand All @@ -482,6 +489,10 @@ func (c *AtlasDeployment) IsAdvancedDeployment() bool {
return c.Spec.DeploymentSpec != nil
}

func (c *AtlasDeployment) IsFlex() bool {
return c.Spec.FlexSpec != nil
}

func (c *AtlasDeployment) GetReplicationSetID() string {
if len(c.Status.ReplicaSets) > 0 {
return c.Status.ReplicaSets[0].ID
Expand Down Expand Up @@ -530,6 +541,41 @@ func (c *AtlasDeployment) ProjectDualRef() *ProjectDualReference {
return &c.Spec.ProjectDualReference
}

type FlexSpec struct {
// Human-readable label that identifies the instance.
// +required
Name string `json:"name"`
s-urbaniak marked this conversation as resolved.
Show resolved Hide resolved

// List that contains key-value pairs between 1 to 255 characters in length for tagging and categorizing the instance.
// +kubebuilder:validation:MaxItems=50
// +optional
Tags []*TagSpec `json:"tags,omitempty"`

// Flag that indicates whether termination protection is enabled on the cluster.
// If set to true, MongoDB Cloud won't delete the cluster. If set to false, MongoDB Cloud will delete the cluster.
// +kubebuilder:default:=false
// +optional
TerminationProtectionEnabled bool `json:"terminationProtectionEnabled,omitempty"`

// Group of cloud provider settings that configure the provisioned MongoDB flex cluster.
// +required
ProviderSettings *FlexProviderSettings `json:"providerSettings"`
s-urbaniak marked this conversation as resolved.
Show resolved Hide resolved
}

type FlexProviderSettings struct {
// Cloud service provider on which MongoDB Atlas provisions the flex cluster.
// +kubebuilder:validation:Enum=AWS;GCP;AZURE
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Backing Provider cannot be modified after cluster creation"
// +required
BackingProviderName string `json:"backingProviderName,omitempty"`
s-urbaniak marked this conversation as resolved.
Show resolved Hide resolved

// Human-readable label that identifies the geographic location of your MongoDB flex cluster.
// The region you choose can affect network latency for clients accessing your databases.
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Region Name cannot be modified after cluster creation"
// +required
RegionName string `json:"regionName,omitempty"`
s-urbaniak marked this conversation as resolved.
Show resolved Hide resolved
}

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

func NewDeployment(namespace, name, nameInAtlas string) *AtlasDeployment {
Expand Down Expand Up @@ -583,6 +629,24 @@ func newServerlessInstance(namespace, name, nameInAtlas, backingProviderName, re
}
}

func newFlexInstance(namespace, name, nameInAtlas, backingProviderName, regionName string) *AtlasDeployment {
return &AtlasDeployment{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
Spec: AtlasDeploymentSpec{
FlexSpec: &FlexSpec{
Name: nameInAtlas,
ProviderSettings: &FlexProviderSettings{
BackingProviderName: backingProviderName,
RegionName: regionName,
},
},
},
}
}

func addReplicaIfNotAdded(deployment *AtlasDeployment) {
if deployment == nil {
return
Expand Down Expand Up @@ -767,6 +831,16 @@ func NewDefaultAWSServerlessInstance(namespace, projectName string) *AtlasDeploy
).WithProjectName(projectName)
}

func NewDefaultAWSFlexInstance(namespace, projectName string) *AtlasDeployment {
return newFlexInstance(
namespace,
"test-flex-instance-k8s",
"test-flex-instance",
"AWS",
"US_EAST_1",
).WithProjectName(projectName)
}

func (c *AtlasDeployment) AtlasName() string {
if c.Spec.DeploymentSpec != nil {
return c.Spec.DeploymentSpec.Name
Expand Down
51 changes: 51 additions & 0 deletions api/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

67 changes: 67 additions & 0 deletions config/crd/bases/atlas.mongodb.com_atlasdeployments.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,73 @@ spec:
required:
- id
type: object
flexSpec:
description: Configuration for the Flex cluster API. https://www.mongodb.com/docs/atlas/reference/api-resources-spec/v2/#tag/Flex-Clusters
properties:
name:
description: Human-readable label that identifies the instance.
type: string
providerSettings:
description: Group of cloud provider settings that configure the
provisioned MongoDB flex cluster.
properties:
backingProviderName:
description: Cloud service provider on which MongoDB Atlas
provisions the flex cluster.
enum:
- AWS
- GCP
- AZURE
type: string
x-kubernetes-validations:
- message: Backing Provider cannot be modified after cluster
creation
rule: self == oldSelf
regionName:
description: |-
Human-readable label that identifies the geographic location of your MongoDB flex cluster.
The region you choose can affect network latency for clients accessing your databases.
type: string
x-kubernetes-validations:
- message: Region Name cannot be modified after cluster creation
rule: self == oldSelf
required:
- backingProviderName
- regionName
type: object
tags:
description: List that contains key-value pairs between 1 to 255
characters in length for tagging and categorizing the instance.
items:
description: TagSpec holds a key-value pair for resource tagging
on this deployment.
properties:
key:
maxLength: 255
minLength: 1
pattern: ^[a-zA-Z0-9][a-zA-Z0-9 @_.+`;`-]*$
type: string
value:
maxLength: 255
minLength: 1
pattern: ^[a-zA-Z0-9][a-zA-Z0-9@_.+`;`-]*$
type: string
required:
- key
- value
type: object
maxItems: 50
type: array
terminationProtectionEnabled:
default: false
description: |-
Flag that indicates whether termination protection is enabled on the cluster.
If set to true, MongoDB Cloud won't delete the cluster. If set to false, MongoDB Cloud will delete the cluster.
type: boolean
required:
- name
- providerSettings
type: object
processArgs:
description: ProcessArgs allows to modify Advanced Configuration Options
properties:
Expand Down
7 changes: 7 additions & 0 deletions internal/controller/atlas/api_error.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ const (
// a serverless instance from the cluster API, which is not allowed
ServerlessInstanceFromClusterAPI = "CANNOT_USE_SERVERLESS_INSTANCE_IN_CLUSTER_API"

ClusterInstanceFromServerlessAPI = "CANNOT_USE_CLUSTER_IN_SERVERLESS_INSTANCE_API"

// Resource not found
ResourceNotFound = "RESOURCE_NOT_FOUND"

Expand All @@ -37,4 +39,9 @@ const (
BackupComplianceNotMet = "BACKUP_POLICIES_NOT_MEETING_BACKUP_COMPLIANCE_POLICY_REQUIREMENTS"

ProviderUnsupported = "PROVIDER_UNSUPPORTED"

// Cannot use the Flex API to interact with non-Flex clusters
NonFlexInFlexAPI = "CANNOT_USE_NON_FLEX_CLUSTER_IN_FLEX_API"

FeatureUnsupported = "FEATURE_UNSUPPORTED"
)
6 changes: 5 additions & 1 deletion internal/controller/atlasdatabaseuser/databaseuser.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,12 @@ func (r *AtlasDatabaseUserReconciler) handleDatabaseUser(ctx *workflow.Context,
if err != nil {
return r.terminate(ctx, atlasDatabaseUser, api.DatabaseUserReadyType, workflow.AtlasAPIAccessNotConfigured, true, err)
}
sdkClientSet, _, err := r.AtlasProvider.SdkClientSet(ctx.Context, credentials, r.Log)
if err != nil {
return r.terminate(ctx, atlasDatabaseUser, api.DatabaseUserReadyType, workflow.AtlasAPIAccessNotConfigured, true, err)
}
dbUserService := dbuser.NewAtlasUsers(sdkClient.DatabaseUsersApi)
deploymentService := deployment.NewAtlasDeployments(sdkClient.ClustersApi, sdkClient.ServerlessInstancesApi, sdkClient.GlobalClustersApi, r.AtlasProvider.IsCloudGov())
deploymentService := deployment.NewAtlasDeployments(sdkClient.ClustersApi, sdkClient.ServerlessInstancesApi, sdkClient.GlobalClustersApi, sdkClientSet.SdkClient20241113001.FlexClustersApi, r.AtlasProvider.IsCloudGov())
atlasProject, err := r.ResolveProject(ctx.Context, sdkClient, atlasDatabaseUser, orgID)
if err != nil {
return r.terminate(ctx, atlasDatabaseUser, api.DatabaseUserReadyType, workflow.AtlasAPIAccessNotConfigured, true, err)
Expand Down
8 changes: 8 additions & 0 deletions internal/controller/atlasdatabaseuser/databaseuser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
"github.com/stretchr/testify/mock"
"go.mongodb.org/atlas-sdk/v20231115008/admin"
"go.mongodb.org/atlas-sdk/v20231115008/mockadmin"
adminv20241113001 "go.mongodb.org/atlas-sdk/v20241113001/admin"

"go.uber.org/zap"
"go.uber.org/zap/zaptest"
corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -191,6 +193,9 @@ func TestHandleDatabaseUser(t *testing.T) {

return &admin.APIClient{ProjectsApi: projectAPI, ClustersApi: clusterAPI, DatabaseUsersApi: userAPI}, "", nil
},
SdkSetClientFunc: func(secretRef *client.ObjectKey, log *zap.SugaredLogger) (*atlas.ClientSet, string, error) {
return &atlas.ClientSet{SdkClient20241113001: &adminv20241113001.APIClient{}}, "", nil
},
},
expectedResult: ctrl.Result{RequeueAfter: workflow.DefaultRetry},
expectedConditions: []api.Condition{
Expand Down Expand Up @@ -2247,5 +2252,8 @@ func DefaultTestProvider(t *testing.T) *atlasmock.TestProvider {
DatabaseUsersApi: userAPI,
}, "", nil
},
SdkSetClientFunc: func(secretRef *client.ObjectKey, log *zap.SugaredLogger) (*atlas.ClientSet, string, error) {
return &atlas.ClientSet{SdkClient20241113001: &adminv20241113001.APIClient{}}, "", nil
},
}
}
Loading
Loading