Skip to content

Commit f15d051

Browse files
Support Cloud SQL Address Range Picker for Clones and Read replicas (#5664) (#11058)
Signed-off-by: Modular Magician <[email protected]>
1 parent 55c3302 commit f15d051

File tree

6 files changed

+220
-5
lines changed

6 files changed

+220
-5
lines changed

.changelog/5664.txt

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
```release-note:enhancement
2+
sql: added field `clone.allocated_ip_range` to support address range picker for clone for resource `google_sql_database_instance`
3+
```
4+
```release-note:enhancement
5+
sql: added support for address range picker for read replicas for resource `google_sql_database_instance`
6+
```

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ require (
2424
golang.org/x/mod v0.5.0 // indirect
2525
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420
2626
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
27-
google.golang.org/api v0.65.0
27+
google.golang.org/api v0.66.0
2828
google.golang.org/grpc v1.40.1
2929
)
3030

go.sum

+7-1
Original file line numberDiff line numberDiff line change
@@ -1153,6 +1153,8 @@ golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBc
11531153
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
11541154
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
11551155
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
1156+
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
1157+
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
11561158
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
11571159
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
11581160
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@@ -1311,6 +1313,8 @@ google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tD
13111313
google.golang.org/api v0.64.0/go.mod h1:931CdxA8Rm4t6zqTFGSsgwbAEZ2+GMYurbndwSimebM=
13121314
google.golang.org/api v0.65.0 h1:MTW9c+LIBAbwoS1Gb+YV7NjFBt2f7GtAS5hIzh2NjgQ=
13131315
google.golang.org/api v0.65.0/go.mod h1:ArYhxgGadlWmqO1IqVujw6Cs8IdD33bTmzKo2Sh+cbg=
1316+
google.golang.org/api v0.66.0 h1:CbGy4LEiXCVCiNEDFgGpWOVwsDT7E2Qej1ZvN1P7KPg=
1317+
google.golang.org/api v0.66.0/go.mod h1:I1dmXYpX7HGwz/ejRxwQp2qj5bFAz93HiCU1C1oYd9M=
13141318
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
13151319
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
13161320
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@@ -1394,6 +1398,8 @@ google.golang.org/genproto v0.0.0-20211223182754-3ac035c7e7cb/go.mod h1:5CzLGKJ6
13941398
google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
13951399
google.golang.org/genproto v0.0.0-20220111164026-67b88f271998 h1:g/x+MYjJYDEP3OBCYYmwIbt4x6k3gryb+ohyOR7PXfI=
13961400
google.golang.org/genproto v0.0.0-20220111164026-67b88f271998/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
1401+
google.golang.org/genproto v0.0.0-20220114231437-d2e6a121cae0 h1:aCsSLXylHWFno0r4S3joLpiaWayvqd2Mn4iSvx4WZZc=
1402+
google.golang.org/genproto v0.0.0-20220114231437-d2e6a121cae0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
13971403
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
13981404
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
13991405
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
@@ -1495,4 +1501,4 @@ rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE=
14951501
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
14961502
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
14971503
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
1498-
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
1504+
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=

google/resource_sql_database_instance.go

+7-2
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,6 @@ settings.backup_configuration.binary_log_enabled are both set to true.`,
310310
"allocated_ip_range": {
311311
Type: schema.TypeString,
312312
Optional: true,
313-
ForceNew: true,
314313
AtLeastOneOf: ipConfigurationKeys,
315314
Description: `The name of the allocated ip range for the private ip CloudSQL instance. For example: "google-managed-services-default". If set, the instance ip will be created in the allocated range. The range name must comply with RFC 1035. Specifically, the name must be 1-63 characters long and match the regular expression [a-z]([-a-z0-9]*[a-z0-9])?.`,
316315
},
@@ -684,6 +683,11 @@ settings.backup_configuration.binary_log_enabled are both set to true.`,
684683
DiffSuppressFunc: timestampDiffSuppress(time.RFC3339Nano),
685684
Description: `The timestamp of the point in time that should be restored.`,
686685
},
686+
"allocated_ip_range": {
687+
Type: schema.TypeString,
688+
Optional: true,
689+
Description: `The name of the allocated ip range for the private ip CloudSQL instance. For example: "google-managed-services-default". If set, the cloned instance ip will be created in the allocated range. The range name must comply with [RFC 1035](https://tools.ietf.org/html/rfc1035). Specifically, the name must be 1-63 characters long and match the regular expression [a-z]([-a-z0-9]*[a-z0-9])?.`,
690+
},
687691
},
688692
},
689693
},
@@ -988,7 +992,8 @@ func expandCloneContext(configured []interface{}) (*sqladmin.CloneContext, strin
988992
_cloneConfiguration := configured[0].(map[string]interface{})
989993

990994
return &sqladmin.CloneContext{
991-
PointInTime: _cloneConfiguration["point_in_time"].(string),
995+
PointInTime: _cloneConfiguration["point_in_time"].(string),
996+
AllocatedIpRange: _cloneConfiguration["allocated_ip_range"].(string),
992997
}, _cloneConfiguration["source_instance_name"].(string)
993998
}
994999

google/resource_sql_database_instance_test.go

+197-1
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,8 @@ func TestAccSqlDatabaseInstance_withPrivateNetwork_withAllocatedIpRange(t *testi
696696
databaseName := "tf-test-" + randString(t, 10)
697697
addressName := "tf-test-" + randString(t, 10)
698698
networkName := BootstrapSharedTestNetwork(t, "sql-instance-private-allocated-ip-range")
699+
addressName_update := "tf-test-" + randString(t, 10) + "update"
700+
networkName_update := BootstrapSharedTestNetwork(t, "sql-instance-private-allocated-ip-range-update")
699701

700702
vcrTest(t, resource.TestCase{
701703
PreCheck: func() { testAccPreCheck(t) },
@@ -711,6 +713,77 @@ func TestAccSqlDatabaseInstance_withPrivateNetwork_withAllocatedIpRange(t *testi
711713
ImportStateVerify: true,
712714
ImportStateVerifyIgnore: []string{"deletion_protection"},
713715
},
716+
{
717+
Config: testAccSqlDatabaseInstance_withPrivateNetwork_withAllocatedIpRange(databaseName, networkName_update, addressName_update),
718+
},
719+
{
720+
ResourceName: "google_sql_database_instance.instance",
721+
ImportState: true,
722+
ImportStateVerify: true,
723+
ImportStateVerifyIgnore: []string{"deletion_protection"},
724+
},
725+
},
726+
})
727+
}
728+
729+
func TestAccSqlDatabaseInstance_withPrivateNetwork_withAllocatedIpRangeReplica(t *testing.T) {
730+
t.Parallel()
731+
732+
databaseName := "tf-test-" + randString(t, 10)
733+
addressName := "tf-test-" + randString(t, 10)
734+
networkName := BootstrapSharedTestNetwork(t, "sql-instance-private-replica")
735+
736+
vcrTest(t, resource.TestCase{
737+
PreCheck: func() { testAccPreCheck(t) },
738+
Providers: testAccProviders,
739+
CheckDestroy: testAccSqlDatabaseInstanceDestroyProducer(t),
740+
Steps: []resource.TestStep{
741+
{
742+
Config: testAccSqlDatabaseInstance_withPrivateNetwork_withAllocatedIpRangeReplica(databaseName, networkName, addressName),
743+
},
744+
{
745+
ResourceName: "google_sql_database_instance.instance",
746+
ImportState: true,
747+
ImportStateVerify: true,
748+
ImportStateVerifyIgnore: []string{"deletion_protection"},
749+
},
750+
{
751+
ResourceName: "google_sql_database_instance.replica1",
752+
ImportState: true,
753+
ImportStateVerify: true,
754+
ImportStateVerifyIgnore: ignoredReplicaConfigurationFields,
755+
},
756+
},
757+
})
758+
}
759+
760+
func TestAccSqlDatabaseInstance_withPrivateNetwork_withAllocatedIpRangeClone(t *testing.T) {
761+
t.Parallel()
762+
763+
databaseName := "tf-test-" + randString(t, 10)
764+
addressName := "tf-test-" + randString(t, 10)
765+
networkName := BootstrapSharedTestNetwork(t, "sql-instance-private-clone")
766+
767+
vcrTest(t, resource.TestCase{
768+
PreCheck: func() { testAccPreCheck(t) },
769+
Providers: testAccProviders,
770+
CheckDestroy: testAccSqlDatabaseInstanceDestroyProducer(t),
771+
Steps: []resource.TestStep{
772+
{
773+
Config: testAccSqlDatabaseInstance_withPrivateNetwork_withAllocatedIpRangeClone(databaseName, networkName, addressName),
774+
},
775+
{
776+
ResourceName: "google_sql_database_instance.instance",
777+
ImportState: true,
778+
ImportStateVerify: true,
779+
ImportStateVerifyIgnore: []string{"deletion_protection"},
780+
},
781+
{
782+
ResourceName: "google_sql_database_instance.clone1",
783+
ImportState: true,
784+
ImportStateVerify: true,
785+
ImportStateVerifyIgnore: []string{"deletion_protection", "clone"},
786+
},
714787
},
715788
})
716789
}
@@ -1095,7 +1168,7 @@ resource "google_compute_global_address" "foobar" {
10951168
name = "%s"
10961169
purpose = "VPC_PEERING"
10971170
address_type = "INTERNAL"
1098-
prefix_length = 24
1171+
prefix_length = 16
10991172
network = data.google_compute_network.servicenet.self_link
11001173
}
11011174
@@ -1123,6 +1196,129 @@ resource "google_sql_database_instance" "instance" {
11231196
`, networkName, addressRangeName, databaseName)
11241197
}
11251198

1199+
func testAccSqlDatabaseInstance_withPrivateNetwork_withAllocatedIpRangeReplica(databaseName, networkName, addressRangeName string) string {
1200+
return fmt.Sprintf(`
1201+
data "google_compute_network" "servicenet" {
1202+
name = "%s"
1203+
}
1204+
1205+
resource "google_compute_global_address" "foobar" {
1206+
name = "%s"
1207+
purpose = "VPC_PEERING"
1208+
address_type = "INTERNAL"
1209+
prefix_length = 16
1210+
network = data.google_compute_network.servicenet.self_link
1211+
}
1212+
1213+
resource "google_service_networking_connection" "foobar" {
1214+
network = data.google_compute_network.servicenet.self_link
1215+
service = "servicenetworking.googleapis.com"
1216+
reserved_peering_ranges = [google_compute_global_address.foobar.name]
1217+
}
1218+
1219+
resource "google_sql_database_instance" "instance" {
1220+
depends_on = [google_service_networking_connection.foobar]
1221+
name = "%s"
1222+
region = "us-central1"
1223+
database_version = "MYSQL_5_7"
1224+
deletion_protection = false
1225+
settings {
1226+
tier = "db-f1-micro"
1227+
ip_configuration {
1228+
ipv4_enabled = "false"
1229+
private_network = data.google_compute_network.servicenet.self_link
1230+
}
1231+
backup_configuration {
1232+
enabled = true
1233+
start_time = "00:00"
1234+
binary_log_enabled = true
1235+
}
1236+
}
1237+
}
1238+
resource "google_sql_database_instance" "replica1" {
1239+
depends_on = [google_service_networking_connection.foobar]
1240+
name = "%s-replica1"
1241+
region = "us-central1"
1242+
database_version = "MYSQL_5_7"
1243+
deletion_protection = false
1244+
settings {
1245+
tier = "db-f1-micro"
1246+
ip_configuration {
1247+
ipv4_enabled = "false"
1248+
private_network = data.google_compute_network.servicenet.self_link
1249+
allocated_ip_range = google_compute_global_address.foobar.name
1250+
}
1251+
}
1252+
1253+
master_instance_name = google_sql_database_instance.instance.name
1254+
1255+
replica_configuration {
1256+
connect_retry_interval = 100
1257+
master_heartbeat_period = 10000
1258+
password = "password"
1259+
username = "username"
1260+
ssl_cipher = "ALL"
1261+
verify_server_certificate = false
1262+
}
1263+
}
1264+
`, networkName, addressRangeName, databaseName, databaseName)
1265+
}
1266+
1267+
func testAccSqlDatabaseInstance_withPrivateNetwork_withAllocatedIpRangeClone(databaseName, networkName, addressRangeName string) string {
1268+
return fmt.Sprintf(`
1269+
data "google_compute_network" "servicenet" {
1270+
name = "%s"
1271+
}
1272+
1273+
resource "google_compute_global_address" "foobar" {
1274+
name = "%s"
1275+
purpose = "VPC_PEERING"
1276+
address_type = "INTERNAL"
1277+
prefix_length = 16
1278+
network = data.google_compute_network.servicenet.self_link
1279+
}
1280+
1281+
resource "google_service_networking_connection" "foobar" {
1282+
network = data.google_compute_network.servicenet.self_link
1283+
service = "servicenetworking.googleapis.com"
1284+
reserved_peering_ranges = [google_compute_global_address.foobar.name]
1285+
}
1286+
1287+
resource "google_sql_database_instance" "instance" {
1288+
depends_on = [google_service_networking_connection.foobar]
1289+
name = "%s"
1290+
region = "us-central1"
1291+
database_version = "MYSQL_5_7"
1292+
deletion_protection = false
1293+
settings {
1294+
tier = "db-f1-micro"
1295+
ip_configuration {
1296+
ipv4_enabled = "false"
1297+
private_network = data.google_compute_network.servicenet.self_link
1298+
}
1299+
backup_configuration {
1300+
enabled = true
1301+
start_time = "00:00"
1302+
binary_log_enabled = true
1303+
}
1304+
}
1305+
}
1306+
1307+
resource "google_sql_database_instance" "clone1" {
1308+
name = "%s-clone1"
1309+
region = "us-central1"
1310+
database_version = "MYSQL_5_7"
1311+
deletion_protection = false
1312+
1313+
clone {
1314+
source_instance_name = google_sql_database_instance.instance.name
1315+
allocated_ip_range = google_compute_global_address.foobar.name
1316+
}
1317+
1318+
}
1319+
`, networkName, addressRangeName, databaseName, databaseName)
1320+
}
1321+
11261322
var testGoogleSqlDatabaseInstance_settings = `
11271323
resource "google_sql_database_instance" "instance" {
11281324
name = "%s"

website/docs/r/sql_database_instance.html.markdown

+2
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,8 @@ The optional `clone` block supports:
379379

380380
A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits. Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z".
381381

382+
* `allocated_ip_range` - (Optional) The name of the allocated ip range for the private ip CloudSQL instance. For example: "google-managed-services-default". If set, the cloned instance ip will be created in the allocated range. The range name must comply with [RFC 1035](https://tools.ietf.org/html/rfc1035). Specifically, the name must be 1-63 characters long and match the regular expression [a-z]([-a-z0-9]*[a-z0-9])?.
383+
382384
The optional `restore_backup_context` block supports:
383385
**NOTE:** Restoring from a backup is an imperative action and not recommended via Terraform. Adding or modifying this
384386
block during resource creation/update will trigger the restore action after the resource is created/updated.

0 commit comments

Comments
 (0)