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

INTMDB-314 Cluster Tenant Upgrade #874

Merged
merged 28 commits into from
Nov 2, 2022
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
4a93435
Initial commit for cluster upgrade
evertsd Oct 18, 2022
0d8b28a
Updated to use a custom customizeDiff func
evertsd Oct 18, 2022
7cbd85c
Setting cluster_id and resource ID to the updated values in the case …
evertsd Oct 18, 2022
a8838f4
Updated logic for determining whether upgrade is required
evertsd Oct 20, 2022
c520728
Removed conflation on willUpgrade and tenant changes. Added error che…
evertsd Oct 20, 2022
1359a18
Updated cluster docs to denote upgrade support
evertsd Oct 24, 2022
49554e9
Added an example tenant upgrade
evertsd Oct 24, 2022
618e09d
Fixed formatting issues
evertsd Oct 24, 2022
d3c6edb
Added code to upgrade advanced_cluster
evertsd Oct 25, 2022
0d2cf1f
Moved example again, for some reason
evertsd Oct 25, 2022
0bad5b2
Moved examples, got advanced-cluster tenantUpgrade working
evertsd Oct 27, 2022
23f5f77
Fixed linter issues with advanced cluster
evertsd Oct 27, 2022
ffb1d9b
removed unnecessary explicit setting of cluster_id
evertsd Oct 27, 2022
c48654b
Updated new examples to work with tf 0.13
evertsd Oct 27, 2022
2643228
Update website/docs/r/advanced_cluster.html.markdown
evertsd Oct 31, 2022
42a8b2c
Update website/docs/r/advanced_cluster.html.markdown
evertsd Oct 31, 2022
16e7e5f
Update website/docs/r/advanced_cluster.html.markdown
evertsd Oct 31, 2022
4b4610a
Update website/docs/r/cluster.html.markdown
evertsd Oct 31, 2022
98e3c4a
Addressed some criticisms of new tenant-upgrade examples
evertsd Oct 31, 2022
b1aa405
Merge branch 'INTMDB-314' of github.com:mongodb/terraform-provider-mo…
evertsd Oct 31, 2022
155354f
Applied suggested docs changes for cluster tenant upgrade
evertsd Oct 31, 2022
34b9266
Apply suggestions from code review
evertsd Oct 31, 2022
fd6db2c
Updated cluster tenant upgrade readme to match that of the advanced c…
evertsd Oct 31, 2022
baf23fe
Addressed last remaining README suggestions for new examples
evertsd Oct 31, 2022
cdad1a8
Fixed naming on variables and re-pausing cluster after upgrade if nec…
evertsd Nov 1, 2022
07e953b
Reduced nested ifs in cluster update
evertsd Nov 1, 2022
6b9f9cf
No longer attempting to unpause tenant tier clusters prior to upgrade…
evertsd Nov 2, 2022
785476c
Fixed linter error on bool init
evertsd Nov 2, 2022
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
32 changes: 32 additions & 0 deletions examples/atlas-advanced-cluster/tenant-upgrade/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# MongoDB Atlas Provider -- Advanced Cluster Tenant Upgrade
This example creates a project and cluster. It is intended to show how to upgrade from shared, aka tenant, to dedicated tier.

Variables Required:
- `atlas_org_id`: ID of the Atlas organization
- `public_key`: Atlas public key
- `private_key`: Atlas private key
- `provider_name`: Name of provider to use for cluster (TENANT, AWS, GCP)
- `backing_provider_name`: If provider_name is tenant, the backing provider (AWS, GCP)
- `provider_instance_size_name`: Size of the cluster (Shared: M0, M2, M5, Dedicated: M10+.)

For this example, first we'll start out on the shared tier, then upgrade to a dedicated tier.

Utilize the following to execute a working example, replacing the org id, public and private key with your values:

Apply with the following `terraform.tfvars` to first create a shared tier cluster:
```
atlas_org_id = "627a9687f7f7f7f774de306f14"
public_key = <REDACTED>
private_key = <REDACTED>
provider_name = "TENANT"
backing_provider_name = "AWS"
provider_instance_size_name = "M2"
```

Apply with the following `terraform.tfvars` to upgrade the shared tier cluster you just created to dedicated tier:
```
atlas_org_id = "627a9687f7f7f7f774de306f14"
public_key = <REDACTED>
private_key = <REDACTED>
provider_name = "GCP"
provider_instance_size_name = "M10"
29 changes: 29 additions & 0 deletions examples/atlas-advanced-cluster/tenant-upgrade/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
provider "mongodbatlas" {
public_key = var.public_key
private_key = var.private_key
}

resource "mongodbatlas_advanced_cluster" "cluster" {
project_id = mongodbatlas_project.project.id
name = "ClusterToUpgrade"
cluster_type = "REPLICASET"

replication_specs {
num_shards = 1

region_configs {
electable_specs {
instance_size = var.provider_instance_size_name
}
provider_name = var.provider_name
backing_provider_name = var.backing_provider_name
region_name = "US_EAST_1"
priority = 7
}
}
}

resource "mongodbatlas_project" "project" {
name = "TenantUpgradeTest"
org_id = var.atlas_org_id
}
22 changes: 22 additions & 0 deletions examples/atlas-advanced-cluster/tenant-upgrade/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
variable "atlas_org_id" {
description = "Atlas organization id"
default = ""
}
variable "public_key" {
description = "Public API key to authenticate to Atlas"
}
variable "private_key" {
description = "Private API key to authenticate to Atlas"
}
variable "provider_name" {
description = "Atlas cluster provider name"
default = "AWS"
}
variable "backing_provider_name" {
description = "Atlas cluster backing provider name"
default = null
}
variable "provider_instance_size_name" {
description = "Atlas cluster provider instance name"
default = "M10"
}
8 changes: 8 additions & 0 deletions examples/atlas-advanced-cluster/tenant-upgrade/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
terraform {
required_providers {
mongodbatlas = {
source = "mongodb/mongodbatlas"
}
}
required_version = ">= 0.13"
}
33 changes: 33 additions & 0 deletions examples/atlas-cluster/tenant-upgrade/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# MongoDB Atlas Provider -- Cluster Tenant Upgrade
This example creates a project and cluster. It is intended to show how to upgrade from shared, aka tenant, to dedicated tier.

Variables Required:
evertsd marked this conversation as resolved.
Show resolved Hide resolved
- `atlas_org_id`: ID of the Atlas organization
- `public_key`: Atlas public key
- `private_key`: Atlas private key
- `provider_name`: Name of provider to use for cluster (TENANT, AWS, GCP)
- `backing_provider_name`: If provider_name is tenant, the backing provider (AWS, GCP)
- `provider_instance_size_name`: Size of the cluster (Shared: M0, M2, M5, Dedicated: M10+.)

For this example, first we'll start out on the shared tier, then upgrade to a dedicated tier.


Utilize the following to execute a working example, replacing the org id, public and private key with your values:

Apply with the following `terraform.tfvars` to first create a shared tier cluster:
```
atlas_org_id = "627a9687f7f7f7f774de306f14"
public_key = <REDACTED>
private_key = <REDACTED>
provider_name = "TENANT"
backing_provider_name = "AWS"
provider_instance_size_name = "M2"
```

Apply with the following `terraform.tfvars` to upgrade the shared tier cluster you just created to dedicated tier:
```
atlas_org_id = "627a9687f7f7f7f774de306f14"
public_key = <REDACTED>
private_key = <REDACTED>
provider_name = "GCP"
provider_instance_size_name = "M10"
19 changes: 19 additions & 0 deletions examples/atlas-cluster/tenant-upgrade/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
provider "mongodbatlas" {
public_key = var.public_key
private_key = var.private_key
}

resource "mongodbatlas_cluster" "cluster" {
project_id = mongodbatlas_project.project.id
name = "ClusterToUpgrade"
cluster_type = "REPLICASET"
provider_name = var.provider_name
backing_provider_name = var.backing_provider_name
provider_region_name = "US_EAST_1"
provider_instance_size_name = var.provider_instance_size_name
}

resource "mongodbatlas_project" "project" {
name = "TenantUpgradeTest"
org_id = var.atlas_org_id
}
22 changes: 22 additions & 0 deletions examples/atlas-cluster/tenant-upgrade/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
variable "atlas_org_id" {
description = "Atlas organization id"
default = ""
}
variable "public_key" {
description = "Public API key to authenticate to Atlas"
}
variable "private_key" {
description = "Private API key to authenticate to Atlas"
}
variable "provider_name" {
description = "Atlas cluster provider name"
default = "AWS"
}
variable "backing_provider_name" {
description = "Atlas cluster backing provider name"
default = null
}
variable "provider_instance_size_name" {
description = "Atlas cluster provider instance name"
default = "M10"
}
8 changes: 8 additions & 0 deletions examples/atlas-cluster/tenant-upgrade/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
terraform {
required_providers {
mongodbatlas = {
source = "mongodb/mongodbatlas"
}
}
required_version = ">= 0.13"
}
96 changes: 95 additions & 1 deletion mongodbatlas/resource_mongodbatlas_advanced_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (
matlas "go.mongodb.org/atlas/mongodbatlas"
)

type acCtxKey string

const (
errorClusterAdvancedCreate = "error creating MongoDB ClusterAdvanced: %s"
errorClusterAdvancedRead = "error reading MongoDB ClusterAdvanced (%s): %s"
Expand All @@ -31,11 +33,13 @@ const (
errorAdvancedClusterAdvancedConfRead = "error reading Advanced Configuration Option form MongoDB Cluster (%s): %s"
)

var upgradeRequestCtxKey acCtxKey = "upgradeRequest"

func resourceMongoDBAtlasAdvancedCluster() *schema.Resource {
return &schema.Resource{
CreateWithoutTimeout: resourceMongoDBAtlasAdvancedClusterCreate,
ReadWithoutTimeout: resourceMongoDBAtlasAdvancedClusterRead,
UpdateWithoutTimeout: resourceMongoDBAtlasAdvancedClusterUpdate,
UpdateWithoutTimeout: resourceMongoDBAtlasAdvancedClusterUpdateOrUpgrade,
DeleteWithoutTimeout: resourceMongoDBAtlasAdvancedClusterDelete,
Importer: &schema.ResourceImporter{
StateContext: resourceMongoDBAtlasAdvancedClusterImportState,
Expand Down Expand Up @@ -511,6 +515,64 @@ func resourceMongoDBAtlasAdvancedClusterRead(ctx context.Context, d *schema.Reso
return nil
}

func resourceMongoDBAtlasAdvancedClusterUpdateOrUpgrade(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
upgradeRequest := getUpgradeRequest(d)

if upgradeRequest != nil {
upgradeCtx := context.WithValue(ctx, upgradeRequestCtxKey, upgradeRequest)
return resourceMongoDBAtlasAdvancedClusterUpgrade(upgradeCtx, d, meta)
}

return resourceMongoDBAtlasAdvancedClusterUpdate(ctx, d, meta)
}
evertsd marked this conversation as resolved.
Show resolved Hide resolved

func resourceMongoDBAtlasAdvancedClusterUpgrade(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn := meta.(*MongoDBClient).Atlas
ids := decodeStateID(d.Id())
projectID := ids["project_id"]
clusterName := ids["cluster_name"]

var upgradeResponse *matlas.Cluster
var err error
upgradeRequest := ctx.Value(upgradeRequestCtxKey).(*matlas.Cluster)

if upgradeRequest == nil {
return diag.FromErr(fmt.Errorf("upgrade called without %s in ctx", string(upgradeRequestCtxKey)))
}

err = resource.RetryContext(ctx, 3*time.Hour, func() *resource.RetryError {
upgradeResponse, _, err = upgradeCluster(ctx, conn, upgradeRequest, projectID, clusterName)
if err != nil {
var target *matlas.ErrorResponse
if errors.As(err, &target) && target.ErrorCode == "CANNOT_UPDATE_PAUSED_CLUSTER" {
clusterRequest := &matlas.AdvancedCluster{
Paused: pointy.Bool(false),
}
_, _, err := updateAdvancedCluster(ctx, conn, clusterRequest, projectID, clusterName)
if err != nil {
return resource.NonRetryableError(fmt.Errorf(errorClusterAdvancedUpdate, clusterName, err))
}
}
if errors.As(err, &target) && target.HTTPCode == 400 {
return resource.NonRetryableError(fmt.Errorf(errorClusterAdvancedUpdate, clusterName, err))
}
}
return nil
})
evertsd marked this conversation as resolved.
Show resolved Hide resolved

if err != nil {
return diag.FromErr(fmt.Errorf(errorClusterAdvancedUpdate, clusterName, err))
}

d.SetId(encodeStateID(map[string]string{
"cluster_id": upgradeResponse.ID,
"project_id": projectID,
"cluster_name": clusterName,
}))

return resourceMongoDBAtlasAdvancedClusterRead(ctx, d, meta)
}

func resourceMongoDBAtlasAdvancedClusterUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
// Get client connection.
conn := meta.(*MongoDBClient).Atlas
Expand Down Expand Up @@ -1079,6 +1141,38 @@ func replicationSpecsHashSet(v interface{}) int {
return schema.HashString(buf.String())
}

func getUpgradeRequest(d *schema.ResourceData) *matlas.Cluster {
if !d.HasChange("replication_specs") {
return nil
}

crs, nrs := d.GetChange("replication_specs")
cReplicationSpecs := expandAdvancedReplicationSpecs(crs.(*schema.Set).List())
nReplicationSpecs := expandAdvancedReplicationSpecs(nrs.(*schema.Set).List())
evertsd marked this conversation as resolved.
Show resolved Hide resolved

if len(cReplicationSpecs) != 1 || len(nReplicationSpecs) != 1 || len(cReplicationSpecs[0].RegionConfigs) != 1 || len(nReplicationSpecs[0].RegionConfigs) != 1 {
return nil
}

cRegionConfig := cReplicationSpecs[0].RegionConfigs[0]
nRegionConfig := nReplicationSpecs[0].RegionConfigs[0]
cInstanceSize := cRegionConfig.ElectableSpecs.InstanceSize

if cRegionConfig.ElectableSpecs.InstanceSize == nRegionConfig.ElectableSpecs.InstanceSize || !(cInstanceSize == "M0" ||
cInstanceSize == "M2" ||
cInstanceSize == "M5") {
return nil
}

return &matlas.Cluster{
ProviderSettings: &matlas.ProviderSettings{
ProviderName: nRegionConfig.ProviderName,
InstanceSizeName: nRegionConfig.ElectableSpecs.InstanceSize,
RegionName: nRegionConfig.RegionName,
},
}
}

func updateAdvancedCluster(ctx context.Context, conn *matlas.Client, request *matlas.AdvancedCluster, projectID, name string) (*matlas.AdvancedCluster, *matlas.Response, error) {
cluster, resp, err := conn.AdvancedClusters.Update(ctx, projectID, name, request)
if err != nil {
Expand Down
Loading