diff --git a/google-beta/resource_sql_database_instance.go b/google-beta/resource_sql_database_instance.go index b78018efcf..5691d1e02b 100644 --- a/google-beta/resource_sql_database_instance.go +++ b/google-beta/resource_sql_database_instance.go @@ -16,6 +16,8 @@ import ( "google.golang.org/api/sqladmin/v1beta4" ) +const privateNetworkLinkRegex = "projects/(" + ProjectRegex + ")/global/networks/((?:[a-z](?:[-a-z0-9]*[a-z0-9])?))$" + var sqlDatabaseAuthorizedNetWorkSchemaElem *schema.Resource = &schema.Resource{ Schema: map[string]*schema.Schema{ "expiration_time": &schema.Schema{ @@ -180,6 +182,12 @@ func resourceSqlDatabaseInstance() *schema.Resource { Type: schema.TypeBool, Optional: true, }, + "private_network": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateRegexp(privateNetworkLinkRegex), + DiffSuppressFunc: compareSelfLinkRelativePaths, + }, }, }, }, @@ -265,6 +273,10 @@ func resourceSqlDatabaseInstance() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, "time_to_retire": &schema.Schema{ Type: schema.TypeString, Optional: true, @@ -612,10 +624,13 @@ func expandIpConfiguration(configured []interface{}) *sqladmin.IpConfiguration { } _ipConfiguration := configured[0].(map[string]interface{}) + return &sqladmin.IpConfiguration{ Ipv4Enabled: _ipConfiguration["ipv4_enabled"].(bool), RequireSsl: _ipConfiguration["require_ssl"].(bool), + PrivateNetwork: _ipConfiguration["private_network"].(string), AuthorizedNetworks: expandAuthorizedNetworks(_ipConfiguration["authorized_networks"].(*schema.Set).List()), + ForceSendFields: []string{"Ipv4Enabled"}, } } func expandAuthorizedNetworks(configured []interface{}) []*sqladmin.AclEntry { @@ -694,7 +709,6 @@ func resourceSqlDatabaseInstanceRead(d *schema.ResourceData, meta interface{}) e if err := d.Set("replica_configuration", flattenReplicaConfiguration(instance.ReplicaConfiguration, d)); err != nil { log.Printf("[WARN] Failed to set SQL Database Instance Replica Configuration") } - ipAddresses := flattenIpAddresses(instance.IpAddresses) if err := d.Set("ip_address", ipAddresses); err != nil { log.Printf("[WARN] Failed to set SQL Database Instance IP Addresses") @@ -1124,8 +1138,9 @@ func flattenDatabaseFlags(databaseFlags []*sqladmin.DatabaseFlags) []map[string] func flattenIpConfiguration(ipConfiguration *sqladmin.IpConfiguration) interface{} { data := map[string]interface{}{ - "ipv4_enabled": ipConfiguration.Ipv4Enabled, - "require_ssl": ipConfiguration.RequireSsl, + "ipv4_enabled": ipConfiguration.Ipv4Enabled, + "private_network": ipConfiguration.PrivateNetwork, + "require_ssl": ipConfiguration.RequireSsl, } if ipConfiguration.AuthorizedNetworks != nil { @@ -1204,6 +1219,7 @@ func flattenIpAddresses(ipAddresses []*sqladmin.IpMapping) []map[string]interfac for _, ip := range ipAddresses { data := map[string]interface{}{ "ip_address": ip.IpAddress, + "type": ip.Type, "time_to_retire": ip.TimeToRetire, } diff --git a/google-beta/resource_sql_database_instance_test.go b/google-beta/resource_sql_database_instance_test.go index 2de6139060..ce770f768e 100644 --- a/google-beta/resource_sql_database_instance_test.go +++ b/google-beta/resource_sql_database_instance_test.go @@ -853,6 +853,30 @@ func testAccCheckGoogleSqlDatabaseInstanceExists(n string, } } +func TestAccSqlDatabaseInstance_withPrivateNetwork(t *testing.T) { + t.Parallel() + + databaseName := "tf-test-" + acctest.RandString(10) + networkName := "tf-test-" + acctest.RandString(10) + addressName := "tf-test-" + acctest.RandString(10) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccSqlDatabaseInstanceDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccSqlDatabaseInstance_withPrivateNetwork(databaseName, networkName, addressName), + }, + resource.TestStep{ + ResourceName: "google_sql_database_instance.instance", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccSqlDatabaseInstanceDestroy(s *terraform.State) error { for _, rs := range s.RootModule().Resources { config := testAccProvider.Meta().(*Config) @@ -974,6 +998,42 @@ resource "google_sql_database_instance" "instance-failover" { `, instanceName, failoverName) } +func testAccSqlDatabaseInstance_withPrivateNetwork(databaseName, networkName, addressRangeName string) string { + return fmt.Sprintf(` +resource "google_compute_network" "foobar" { + name = "%s" + auto_create_subnetworks = false +} + +resource "google_compute_global_address" "foobar" { + name = "%s" + purpose = "VPC_PEERING" + address_type = "INTERNAL" + prefix_length = 16 + network = "${google_compute_network.foobar.self_link}" +} + +resource "google_service_networking_connection" "foobar" { + network = "${google_compute_network.foobar.self_link}" + service = "servicenetworking.googleapis.com" + reserved_peering_ranges = ["${google_compute_global_address.foobar.name}"] +} + +resource "google_sql_database_instance" "instance" { + depends_on = ["google_service_networking_connection.foobar"] + name = "%s" + region = "us-central1" + settings { + tier = "db-f1-micro" + ip_configuration { + ipv4_enabled = "false" + private_network = "${google_compute_network.foobar.self_link}" + } + } +} +`, networkName, addressRangeName, databaseName) +} + var testGoogleSqlDatabaseInstance_settings = ` resource "google_sql_database_instance" "instance" { name = "tf-lw-%d" diff --git a/website/docs/r/sql_database_instance.html.markdown b/website/docs/r/sql_database_instance.html.markdown index 7a2a2a5d9d..280dbee20b 100644 --- a/website/docs/r/sql_database_instance.html.markdown +++ b/website/docs/r/sql_database_instance.html.markdown @@ -108,6 +108,42 @@ resource "google_sql_database_instance" "postgres" { } ``` +### Private IP Instance + + +```hcl +resource "google_compute_network" "private_network" { + name = "private_network" +} + +resource "google_compute_global_address" "private_ip_address" { + name = "private_ip_address" + purpose = "VPC_PEERING" + address_type = "INTERNAL" + prefix_length = 16 + network = "${google_compute_network.private_network.self_link}" +} + +resource "google_service_networking_connection" "private_vpc_connection" { + network = "${google_compute_network.private_network.self_link}" + service = "servicenetworking.googleapis.com" + reserved_peering_ranges = ["${google_compute_global_address.private_ip_address.name}"] +} + +resource "google_sql_database_instance" "instance" { + depends_on = ["google_service_networking_connection.private_vpc_connection"] + name = "private_instance" + region = "us-central1" + settings { + tier = "db-f1-micro" + ip_configuration { + ipv4_enabled = "false" + private_network = "${google_compute_network.private_network.self_link}" + } + } +} +``` + ## Argument Reference The following arguments are supported: @@ -205,6 +241,8 @@ The optional `settings.ip_configuration` subblock supports: * `require_ssl` - (Optional) True if mysqld should default to `REQUIRE X509` for users connecting over IP. +* `private_network` - (Optional) The resource link for the VPC network from which the Cloud SQL instance is accessible for private IP. + The optional `settings.ip_configuration.authorized_networks[]` sublist supports: * `expiration_time` - (Optional) The [RFC 3339](https://tools.ietf.org/html/rfc3339) @@ -286,6 +324,8 @@ when the resource is configured with a `count`. * `ip_address.0.time_to_retire` - The time this IP address will be retired, in RFC 3339 format. +* `ip_address.0.type` - The type of this IP address. A PRIMARY address is an address that can accept incoming connections. An OUTGOING address is the source address of connections originating from the instance, if supported. A PRIVATE address is an address for an instance which has been configured to use private networking see: [Private IP](https://cloud.google.com/sql/docs/mysql/private-ip). + * `self_link` - The URI of the created resource. * `settings.version` - Used to make sure changes to the `settings` block are