Skip to content

Commit

Permalink
Alloydb crr secondary instance (GoogleCloudPlatform#9203)
Browse files Browse the repository at this point in the history
Co-authored-by: Riley Karson <[email protected]>
Co-authored-by: Shubham Sahu <[email protected]>
  • Loading branch information
3 people authored and jiayimeow committed Oct 31, 2023
1 parent 5fe6a45 commit 50cd570
Show file tree
Hide file tree
Showing 8 changed files with 830 additions and 4 deletions.
12 changes: 12 additions & 0 deletions mmv1/products/alloydb/Cluster.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ examples:
skip_docs: true
custom_code: !ruby/object:Provider::Terraform::CustomCode
pre_create: templates/terraform/pre_create/alloydb_cluster.go.erb
pre_delete: templates/terraform/pre_delete/alloydb_cluster.go.erb
parameters:
- !ruby/object:Api::Type::String
name: 'clusterId'
Expand Down Expand Up @@ -492,3 +493,14 @@ properties:
description: |
Name of the primary cluster must be in the format
'projects/{project}/locations/{location}/clusters/{cluster_id}'
virtual_fields:
- !ruby/object:Api::Type::Enum
name: 'deletion_policy'
description: |
Policy to determine if the cluster should be deleted forcefully.
Deleting a cluster forcefully, deletes the cluster and all its associated instances within the cluster.
Deleting a Secondary cluster with a secondary instance REQUIRES setting deletion_policy = "FORCE" otherwise an error is returned. This is needed as there is no support to delete just the secondary instance, and the only way to delete secondary instance is to delete the associated secondary cluster forcefully which also deletes the secondary instance.
values:
- :DEFAULT
- :FORCE
default_value: :DEFAULT
50 changes: 46 additions & 4 deletions mmv1/products/alloydb/Instance.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@

--- !ruby/object:Api::Resource
name: 'Instance'
docs: !ruby/object:Provider::Terraform::Docs
warning: |
Deleting an instance with instanceType = SECONDARY does not delete the secondary instance, and abandons it instead.
Use deletion_policy = "FORCE" in the associated secondary cluster and delete the cluster forcefully to delete the secondary cluster as well its associated secondary instance.
Users can undo the delete secondary instance action by importing the deleted secondary instance by calling terraform import.
self_link: '{{cluster}}/instances/{{instance_id}}'
base_url: '{{cluster}}/instances?instanceId={{instance_id}}'
update_verb: :PATCH
Expand All @@ -28,9 +33,9 @@ async: !ruby/object:Api::OpAsync
base_url: '{{op_id}}'
wait_ms: 1000
timeouts: !ruby/object:Api::Timeouts
insert_minutes: 40
update_minutes: 40
delete_minutes: 40
insert_minutes: 120
update_minutes: 120
delete_minutes: 120
result: !ruby/object:Api::OpAsync::Result
path: 'response'
status: !ruby/object:Api::OpAsync::Status
Expand All @@ -49,6 +54,8 @@ skip_sweeper: true
autogen_async: true
custom_code: !ruby/object:Provider::Terraform::CustomCode
custom_import: templates/terraform/custom_import/alloydb_instance.go.erb
pre_create: templates/terraform/pre_create/alloydb_instance.go.erb
pre_delete: templates/terraform/pre_delete/alloydb_instance.go.erb
examples:
- !ruby/object:Provider::Terraform::Examples
name: 'alloydb_instance_basic'
Expand All @@ -61,6 +68,19 @@ examples:
- 'reconciling'
- 'update_time'
skip_test: true
- !ruby/object:Provider::Terraform::Examples
name: 'alloydb_secondary_instance_basic'
primary_resource_id: 'secondary'
vars:
alloydb_primary_cluster_name: 'alloydb-primary-cluster'
alloydb_primary_instance_name: 'alloydb-primary-instance'
alloydb_secondary_cluster_name: 'alloydb-secondary-cluster'
alloydb_secondary_instance_name: 'alloydb-secondary-instance'
network_name: 'alloydb-secondary-network'
ignore_read_extra:
- 'reconciling'
- 'update_time'
skip_test: true
- !ruby/object:Provider::Terraform::Examples
name: 'alloydb_instance_basic_test'
primary_resource_id: 'default'
Expand All @@ -74,6 +94,21 @@ examples:
- 'reconciling'
- 'update_time'
skip_docs: true
- !ruby/object:Provider::Terraform::Examples
name: 'alloydb_secondary_instance_basic_test'
primary_resource_id: 'secondary'
vars:
alloydb_primary_cluster_name: 'alloydb-primary-cluster'
alloydb_primary_instance_name: 'alloydb-primary-instance'
alloydb_secondary_cluster_name: 'alloydb-secondary-cluster'
alloydb_secondary_instance_name: 'alloydb-secondary-instance'
network_name: 'alloydb-secondary-network'
test_vars_overrides:
network_name: 'acctest.BootstrapSharedServiceNetworkingConnection(t, "alloydbinstance-network-config-1")'
ignore_read_extra:
- 'reconciling'
- 'update_time'
skip_docs: true
parameters:
- !ruby/object:Api::Type::ResourceRef
name: 'cluster'
Expand Down Expand Up @@ -167,10 +202,17 @@ properties:
required: true
immutable: true
description: |
The type of the instance. If the instance type is READ_POOL, provide the associated PRIMARY instance in the `depends_on` meta-data attribute.
The type of the instance.
If the instance type is READ_POOL, provide the associated PRIMARY/SECONDARY instance in the `depends_on` meta-data attribute.
If the instance type is SECONDARY, point to the cluster_type of the associated secondary cluster instead of mentioning SECONDARY.
Example: {instance_type = google_alloydb_cluster.<secondary_cluster_name>.cluster_type} instead of {instance_type = SECONDARY}
If the instance type is SECONDARY, the terraform delete instance operation does not delete the secondary instance but abandons it instead.
Use deletion_policy = "FORCE" in the associated secondary cluster and delete the cluster forcefully to delete the secondary cluster as well its associated secondary instance.
Users can undo the delete secondary instance action by importing the deleted secondary instance by calling terraform import.
values:
- :PRIMARY
- :READ_POOL
- :SECONDARY
- !ruby/object:Api::Type::String
name: 'ipAddress'
output: true
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
resource "google_alloydb_cluster" "primary" {
cluster_id = "<%= ctx[:vars]['alloydb_primary_cluster_name'] %>"
location = "us-central1"
network = google_compute_network.default.id
}

resource "google_alloydb_instance" "primary" {
cluster = google_alloydb_cluster.primary.name
instance_id = "<%= ctx[:vars]['alloydb_primary_instance_name'] %>"
instance_type = "PRIMARY"

machine_config {
cpu_count = 2
}

depends_on = [google_service_networking_connection.vpc_connection]
}

resource "google_alloydb_cluster" "secondary" {
cluster_id = "<%= ctx[:vars]['alloydb_secondary_cluster_name'] %>"
location = "us-east1"
network = google_compute_network.default.id
cluster_type = "SECONDARY"

continuous_backup_config {
enabled = false
}

secondary_config {
primary_cluster_name = google_alloydb_cluster.primary.name
}

deletion_policy = "FORCE"

depends_on = [google_alloydb_instance.primary]
}

resource "google_alloydb_instance" "<%= ctx[:primary_resource_id] %>" {
cluster = google_alloydb_cluster.secondary.name
instance_id = "<%= ctx[:vars]['alloydb_secondary_instance_name'] %>"
instance_type = google_alloydb_cluster.secondary.cluster_type

machine_config {
cpu_count = 2
}

depends_on = [google_service_networking_connection.vpc_connection]
}

data "google_project" "project" {}

resource "google_compute_network" "default" {
name = "<%= ctx[:vars]['network_name'] %>"
}

resource "google_compute_global_address" "private_ip_alloc" {
name = "<%= ctx[:vars]['alloydb_secondary_instance_name'] %>"
address_type = "INTERNAL"
purpose = "VPC_PEERING"
prefix_length = 16
network = google_compute_network.default.id
}

resource "google_service_networking_connection" "vpc_connection" {
network = google_compute_network.default.id
service = "servicenetworking.googleapis.com"
reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
resource "google_alloydb_cluster" "primary" {
cluster_id = "<%= ctx[:vars]['alloydb_primary_cluster_name'] %>"
location = "us-central1"
network = data.google_compute_network.default.id
}

resource "google_alloydb_instance" "primary" {
cluster = google_alloydb_cluster.primary.name
instance_id = "<%= ctx[:vars]['alloydb_primary_instance_name'] %>"
instance_type = "PRIMARY"

machine_config {
cpu_count = 2
}
}

resource "google_alloydb_cluster" "secondary" {
cluster_id = "<%= ctx[:vars]['alloydb_secondary_cluster_name'] %>"
location = "us-east1"
network = data.google_compute_network.default.id
cluster_type = "SECONDARY"

continuous_backup_config {
enabled = false
}

secondary_config {
primary_cluster_name = google_alloydb_cluster.primary.name
}

deletion_policy = "FORCE"

depends_on = [google_alloydb_instance.primary]
}

resource "google_alloydb_instance" "<%= ctx[:primary_resource_id] %>" {
cluster = google_alloydb_cluster.secondary.name
instance_id = "<%= ctx[:vars]['alloydb_secondary_instance_name'] %>"
instance_type = google_alloydb_cluster.secondary.cluster_type

machine_config {
cpu_count = 2
}
}

data "google_project" "project" {}

data "google_compute_network" "default" {
name = "<%= ctx[:vars]['network_name'] %>"
}
5 changes: 5 additions & 0 deletions mmv1/templates/terraform/pre_create/alloydb_instance.go.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Read the config and call createsecondary api if instance_type is SECONDARY

if instanceType := d.Get("instance_type"); instanceType == "SECONDARY" {
url = strings.Replace(url, "instances?instanceId", "instances:createsecondary?instanceId", 1)
}
4 changes: 4 additions & 0 deletions mmv1/templates/terraform/pre_delete/alloydb_cluster.go.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Forcefully delete the secondary cluster and the dependent instances because deletion of secondary instance is not supported.
if deletionPolicy := d.Get("deletion_policy"); deletionPolicy == "FORCE" {
url = url + "?force=true"
}
18 changes: 18 additions & 0 deletions mmv1/templates/terraform/pre_delete/alloydb_instance.go.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Read the config and avoid calling the delete API if the instance_type is SECONDARY and instead return nil
// Returning nil is equivalent of returning a success message to the users
// This is done because deletion of secondary instance is not supported
// Instead users should be deleting the secondary cluster which will forcefully delete the associated secondary instance
// A warning message prompts the user to delete the associated secondary cluster.
// Users can always undo the delete secondary instance action by importing the deleted secondary instance by calling terraform import

var instanceType interface{}
instanceTypeProp, err := expandAlloydbInstanceInstanceType(d.Get("instance_type"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("instance_type"); !tpgresource.IsEmptyValue(reflect.ValueOf(instanceTypeProp)) && (ok || !reflect.DeepEqual(v, instanceTypeProp)) {
instanceType = instanceTypeProp
}
if instanceType != nil && instanceType == "SECONDARY" {
log.Printf("[WARNING] This operation didn't delete the Secondary Instance %q. Please delete the associated Secondary Cluster as well to delete the entire cluster and the secondary instance.\n", d.Id())
return nil
}
Loading

0 comments on commit 50cd570

Please sign in to comment.