From f655a17741783737c6e2dfec87486312e50a7526 Mon Sep 17 00:00:00 2001 From: The Magician Date: Mon, 2 Oct 2023 20:12:27 -0400 Subject: [PATCH] Add Oracle support to DBMS (#9114) (#6426) [upstream:e42af6b9a19a00d387c3dbbb340bd33630cd94a3] Signed-off-by: Modular Magician --- .changelog/9114.txt | 3 + ...se_migration_service_connection_profile.go | 631 +++++++++++++++++- ...gration_service_connection_profile_test.go | 3 +- ...n_service_connection_profile.html.markdown | 131 +++- 4 files changed, 762 insertions(+), 6 deletions(-) create mode 100644 .changelog/9114.txt diff --git a/.changelog/9114.txt b/.changelog/9114.txt new file mode 100644 index 0000000000..17f68a4804 --- /dev/null +++ b/.changelog/9114.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +databasemigrationservice: added support for `oracle` profiles to `google_database_migration_service_connection_profile` +``` diff --git a/google-beta/services/databasemigrationservice/resource_database_migration_service_connection_profile.go b/google-beta/services/databasemigrationservice/resource_database_migration_service_connection_profile.go index f3bb879157..acf5c15d03 100644 --- a/google-beta/services/databasemigrationservice/resource_database_migration_service_connection_profile.go +++ b/google-beta/services/databasemigrationservice/resource_database_migration_service_connection_profile.go @@ -173,7 +173,7 @@ It is specified in the form: 'projects/{project_number}/global/networks/{network }, }, }, - ExactlyOneOf: []string{"mysql", "postgresql", "cloudsql", "alloydb"}, + ExactlyOneOf: []string{"mysql", "postgresql", "oracle", "cloudsql", "alloydb"}, }, "cloudsql": { Type: schema.TypeList, @@ -357,7 +357,7 @@ For more information, see https://cloud.google.com/sql/docs/mysql/instance-setti }, }, }, - ExactlyOneOf: []string{"mysql", "postgresql", "cloudsql", "alloydb"}, + ExactlyOneOf: []string{"mysql", "postgresql", "oracle", "cloudsql", "alloydb"}, }, "display_name": { Type: schema.TypeString, @@ -461,7 +461,162 @@ If this field is used then the 'clientCertificate' field is mandatory.`, }, }, }, - ExactlyOneOf: []string{"mysql", "postgresql", "cloudsql", "alloydb"}, + ExactlyOneOf: []string{"mysql", "postgresql", "oracle", "cloudsql", "alloydb"}, + }, + "oracle": { + Type: schema.TypeList, + Optional: true, + Description: `Specifies connection parameters required specifically for Oracle databases.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "database_service": { + Type: schema.TypeString, + Required: true, + Description: `Required. Database service for the Oracle connection.`, + }, + "host": { + Type: schema.TypeString, + Required: true, + Description: `Required. The IP or hostname of the source Oracle database.`, + }, + "password": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `Required. Input only. The password for the user that Database Migration Service will be using to connect to the database. +This field is not returned on request, and the value is encrypted when stored in Database Migration Service.`, + Sensitive: true, + }, + "port": { + Type: schema.TypeInt, + Required: true, + Description: `Required. The network port of the source Oracle database.`, + }, + "username": { + Type: schema.TypeString, + Required: true, + Description: `Required. The username that Database Migration Service will use to connect to the database. The value is encrypted when stored in Database Migration Service.`, + }, + "forward_ssh_connectivity": { + Type: schema.TypeList, + Optional: true, + Description: `SSL configuration for the destination to connect to the source database.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "hostname": { + Type: schema.TypeString, + Required: true, + Description: `Required. Hostname for the SSH tunnel.`, + }, + "port": { + Type: schema.TypeInt, + Required: true, + Description: `Port for the SSH tunnel, default value is 22.`, + }, + "username": { + Type: schema.TypeString, + Required: true, + Description: `Required. Username for the SSH tunnel.`, + }, + "password": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `Input only. SSH password. Only one of 'password' and 'private_key' can be configured.`, + Sensitive: true, + ExactlyOneOf: []string{}, + }, + "private_key": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `Input only. SSH private key. Only one of 'password' and 'private_key' can be configured.`, + Sensitive: true, + ExactlyOneOf: []string{"oracle.0.forward_ssh_connectivity.0.password", "oracle.0.forward_ssh_connectivity.0.private_key"}, + }, + }, + }, + ExactlyOneOf: []string{}, + }, + "private_connectivity": { + Type: schema.TypeList, + Optional: true, + Description: `Configuration for using a private network to communicate with the source database`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "private_connection": { + Type: schema.TypeString, + Required: true, + Description: `Required. The resource name (URI) of the private connection.`, + }, + }, + }, + ExactlyOneOf: []string{"oracle.0.static_service_ip_connectivity", "oracle.0.forward_ssh_connectivity", "oracle.0.private_connectivity"}, + }, + "ssl": { + Type: schema.TypeList, + Optional: true, + Description: `SSL configuration for the destination to connect to the source database.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ca_certificate": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `Required. Input only. The x509 PEM-encoded certificate of the CA that signed the source database server's certificate. +The replica will use this certificate to verify it's connecting to the right host.`, + Sensitive: true, + }, + "client_certificate": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `Input only. The x509 PEM-encoded certificate that will be used by the replica to authenticate against the source database server. +If this field is used then the 'clientKey' field is mandatory`, + Sensitive: true, + RequiredWith: []string{}, + }, + "client_key": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `Input only. The unencrypted PKCS#1 or PKCS#8 PEM-encoded private key associated with the Client Certificate. +If this field is used then the 'clientCertificate' field is mandatory.`, + Sensitive: true, + RequiredWith: []string{}, + }, + "type": { + Type: schema.TypeString, + Computed: true, + Description: `The current connection profile state.`, + }, + }, + }, + }, + "static_service_ip_connectivity": { + Type: schema.TypeList, + Optional: true, + Description: `This object has no nested fields. + +Static IP address connectivity configured on service project.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{}, + }, + ExactlyOneOf: []string{}, + }, + "password_set": { + Type: schema.TypeBool, + Computed: true, + Description: `Output only. Indicates If this connection profile password is stored.`, + }, + }, + }, + ExactlyOneOf: []string{"mysql", "postgresql", "oracle", "cloudsql", "alloydb"}, }, "postgresql": { Type: schema.TypeList, @@ -551,7 +706,7 @@ If this field is used then the 'clientCertificate' field is mandatory.`, }, }, }, - ExactlyOneOf: []string{"mysql", "postgresql", "cloudsql", "alloydb"}, + ExactlyOneOf: []string{"mysql", "postgresql", "oracle", "cloudsql", "alloydb"}, }, "create_time": { Type: schema.TypeString, @@ -650,6 +805,12 @@ func resourceDatabaseMigrationServiceConnectionProfileCreate(d *schema.ResourceD } else if v, ok := d.GetOkExists("postgresql"); !tpgresource.IsEmptyValue(reflect.ValueOf(postgresqlProp)) && (ok || !reflect.DeepEqual(v, postgresqlProp)) { obj["postgresql"] = postgresqlProp } + oracleProp, err := expandDatabaseMigrationServiceConnectionProfileOracle(d.Get("oracle"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("oracle"); !tpgresource.IsEmptyValue(reflect.ValueOf(oracleProp)) && (ok || !reflect.DeepEqual(v, oracleProp)) { + obj["oracle"] = oracleProp + } cloudsqlProp, err := expandDatabaseMigrationServiceConnectionProfileCloudsql(d.Get("cloudsql"), d, config) if err != nil { return err @@ -790,6 +951,9 @@ func resourceDatabaseMigrationServiceConnectionProfileRead(d *schema.ResourceDat if err := d.Set("postgresql", flattenDatabaseMigrationServiceConnectionProfilePostgresql(res["postgresql"], d, config)); err != nil { return fmt.Errorf("Error reading ConnectionProfile: %s", err) } + if err := d.Set("oracle", flattenDatabaseMigrationServiceConnectionProfileOracle(res["oracle"], d, config)); err != nil { + return fmt.Errorf("Error reading ConnectionProfile: %s", err) + } if err := d.Set("cloudsql", flattenDatabaseMigrationServiceConnectionProfileCloudsql(res["cloudsql"], d, config)); err != nil { return fmt.Errorf("Error reading ConnectionProfile: %s", err) } @@ -840,6 +1004,12 @@ func resourceDatabaseMigrationServiceConnectionProfileUpdate(d *schema.ResourceD } else if v, ok := d.GetOkExists("postgresql"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, postgresqlProp)) { obj["postgresql"] = postgresqlProp } + oracleProp, err := expandDatabaseMigrationServiceConnectionProfileOracle(d.Get("oracle"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("oracle"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, oracleProp)) { + obj["oracle"] = oracleProp + } cloudsqlProp, err := expandDatabaseMigrationServiceConnectionProfileCloudsql(d.Get("cloudsql"), d, config) if err != nil { return err @@ -879,6 +1049,10 @@ func resourceDatabaseMigrationServiceConnectionProfileUpdate(d *schema.ResourceD updateMask = append(updateMask, "postgresql") } + if d.HasChange("oracle") { + updateMask = append(updateMask, "oracle") + } + if d.HasChange("cloudsql") { updateMask = append(updateMask, "cloudsql") } @@ -1279,6 +1453,188 @@ func flattenDatabaseMigrationServiceConnectionProfilePostgresqlNetworkArchitectu return v } +func flattenDatabaseMigrationServiceConnectionProfileOracle(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["host"] = + flattenDatabaseMigrationServiceConnectionProfileOracleHost(original["host"], d, config) + transformed["port"] = + flattenDatabaseMigrationServiceConnectionProfileOraclePort(original["port"], d, config) + transformed["username"] = + flattenDatabaseMigrationServiceConnectionProfileOracleUsername(original["username"], d, config) + transformed["password"] = + flattenDatabaseMigrationServiceConnectionProfileOraclePassword(original["password"], d, config) + transformed["password_set"] = + flattenDatabaseMigrationServiceConnectionProfileOraclePasswordSet(original["passwordSet"], d, config) + transformed["database_service"] = + flattenDatabaseMigrationServiceConnectionProfileOracleDatabaseService(original["databaseService"], d, config) + transformed["ssl"] = + flattenDatabaseMigrationServiceConnectionProfileOracleSsl(original["ssl"], d, config) + transformed["static_service_ip_connectivity"] = + flattenDatabaseMigrationServiceConnectionProfileOracleStaticServiceIpConnectivity(original["staticServiceIpConnectivity"], d, config) + transformed["forward_ssh_connectivity"] = + flattenDatabaseMigrationServiceConnectionProfileOracleForwardSshConnectivity(original["forwardSshConnectivity"], d, config) + transformed["private_connectivity"] = + flattenDatabaseMigrationServiceConnectionProfileOraclePrivateConnectivity(original["privateConnectivity"], d, config) + return []interface{}{transformed} +} +func flattenDatabaseMigrationServiceConnectionProfileOracleHost(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenDatabaseMigrationServiceConnectionProfileOraclePort(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { + return intVal + } + } + + // number values are represented as float64 + if floatVal, ok := v.(float64); ok { + intVal := int(floatVal) + return intVal + } + + return v // let terraform core handle it otherwise +} + +func flattenDatabaseMigrationServiceConnectionProfileOracleUsername(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenDatabaseMigrationServiceConnectionProfileOraclePassword(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return d.Get("oracle.0.password") +} + +func flattenDatabaseMigrationServiceConnectionProfileOraclePasswordSet(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenDatabaseMigrationServiceConnectionProfileOracleDatabaseService(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenDatabaseMigrationServiceConnectionProfileOracleSsl(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["type"] = + flattenDatabaseMigrationServiceConnectionProfileOracleSslType(original["type"], d, config) + transformed["client_key"] = + flattenDatabaseMigrationServiceConnectionProfileOracleSslClientKey(original["clientKey"], d, config) + transformed["client_certificate"] = + flattenDatabaseMigrationServiceConnectionProfileOracleSslClientCertificate(original["clientCertificate"], d, config) + transformed["ca_certificate"] = + flattenDatabaseMigrationServiceConnectionProfileOracleSslCaCertificate(original["caCertificate"], d, config) + return []interface{}{transformed} +} +func flattenDatabaseMigrationServiceConnectionProfileOracleSslType(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenDatabaseMigrationServiceConnectionProfileOracleSslClientKey(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return d.Get("oracle.0.ssl.0.client_key") +} + +func flattenDatabaseMigrationServiceConnectionProfileOracleSslClientCertificate(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return d.Get("oracle.0.ssl.0.client_certificate") +} + +func flattenDatabaseMigrationServiceConnectionProfileOracleSslCaCertificate(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return d.Get("oracle.0.ssl.0.ca_certificate") +} + +func flattenDatabaseMigrationServiceConnectionProfileOracleStaticServiceIpConnectivity(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + transformed := make(map[string]interface{}) + return []interface{}{transformed} +} + +func flattenDatabaseMigrationServiceConnectionProfileOracleForwardSshConnectivity(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["hostname"] = + flattenDatabaseMigrationServiceConnectionProfileOracleForwardSshConnectivityHostname(original["hostname"], d, config) + transformed["username"] = + flattenDatabaseMigrationServiceConnectionProfileOracleForwardSshConnectivityUsername(original["username"], d, config) + transformed["port"] = + flattenDatabaseMigrationServiceConnectionProfileOracleForwardSshConnectivityPort(original["port"], d, config) + transformed["password"] = + flattenDatabaseMigrationServiceConnectionProfileOracleForwardSshConnectivityPassword(original["password"], d, config) + transformed["private_key"] = + flattenDatabaseMigrationServiceConnectionProfileOracleForwardSshConnectivityPrivateKey(original["privateKey"], d, config) + return []interface{}{transformed} +} +func flattenDatabaseMigrationServiceConnectionProfileOracleForwardSshConnectivityHostname(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenDatabaseMigrationServiceConnectionProfileOracleForwardSshConnectivityUsername(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenDatabaseMigrationServiceConnectionProfileOracleForwardSshConnectivityPort(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { + return intVal + } + } + + // number values are represented as float64 + if floatVal, ok := v.(float64); ok { + intVal := int(floatVal) + return intVal + } + + return v // let terraform core handle it otherwise +} + +func flattenDatabaseMigrationServiceConnectionProfileOracleForwardSshConnectivityPassword(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return d.Get("oracle.0.forward_ssh_connectivity.0.password") +} + +func flattenDatabaseMigrationServiceConnectionProfileOracleForwardSshConnectivityPrivateKey(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return d.Get("oracle.0.forward_ssh_connectivity.0.private_key") +} + +func flattenDatabaseMigrationServiceConnectionProfileOraclePrivateConnectivity(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["private_connection"] = + flattenDatabaseMigrationServiceConnectionProfileOraclePrivateConnectivityPrivateConnection(original["privateConnection"], d, config) + return []interface{}{transformed} +} +func flattenDatabaseMigrationServiceConnectionProfileOraclePrivateConnectivityPrivateConnection(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + func flattenDatabaseMigrationServiceConnectionProfileCloudsql(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { if v == nil { return nil @@ -1945,6 +2301,273 @@ func expandDatabaseMigrationServiceConnectionProfilePostgresqlNetworkArchitectur return v, nil } +func expandDatabaseMigrationServiceConnectionProfileOracle(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedHost, err := expandDatabaseMigrationServiceConnectionProfileOracleHost(original["host"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHost); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["host"] = transformedHost + } + + transformedPort, err := expandDatabaseMigrationServiceConnectionProfileOraclePort(original["port"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPort); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["port"] = transformedPort + } + + transformedUsername, err := expandDatabaseMigrationServiceConnectionProfileOracleUsername(original["username"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedUsername); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["username"] = transformedUsername + } + + transformedPassword, err := expandDatabaseMigrationServiceConnectionProfileOraclePassword(original["password"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPassword); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["password"] = transformedPassword + } + + transformedPasswordSet, err := expandDatabaseMigrationServiceConnectionProfileOraclePasswordSet(original["password_set"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPasswordSet); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["passwordSet"] = transformedPasswordSet + } + + transformedDatabaseService, err := expandDatabaseMigrationServiceConnectionProfileOracleDatabaseService(original["database_service"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDatabaseService); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["databaseService"] = transformedDatabaseService + } + + transformedSsl, err := expandDatabaseMigrationServiceConnectionProfileOracleSsl(original["ssl"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSsl); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["ssl"] = transformedSsl + } + + transformedStaticServiceIpConnectivity, err := expandDatabaseMigrationServiceConnectionProfileOracleStaticServiceIpConnectivity(original["static_service_ip_connectivity"], d, config) + if err != nil { + return nil, err + } else { + transformed["staticServiceIpConnectivity"] = transformedStaticServiceIpConnectivity + } + + transformedForwardSshConnectivity, err := expandDatabaseMigrationServiceConnectionProfileOracleForwardSshConnectivity(original["forward_ssh_connectivity"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedForwardSshConnectivity); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["forwardSshConnectivity"] = transformedForwardSshConnectivity + } + + transformedPrivateConnectivity, err := expandDatabaseMigrationServiceConnectionProfileOraclePrivateConnectivity(original["private_connectivity"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPrivateConnectivity); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["privateConnectivity"] = transformedPrivateConnectivity + } + + return transformed, nil +} + +func expandDatabaseMigrationServiceConnectionProfileOracleHost(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandDatabaseMigrationServiceConnectionProfileOraclePort(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandDatabaseMigrationServiceConnectionProfileOracleUsername(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandDatabaseMigrationServiceConnectionProfileOraclePassword(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandDatabaseMigrationServiceConnectionProfileOraclePasswordSet(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandDatabaseMigrationServiceConnectionProfileOracleDatabaseService(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandDatabaseMigrationServiceConnectionProfileOracleSsl(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedType, err := expandDatabaseMigrationServiceConnectionProfileOracleSslType(original["type"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedType); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["type"] = transformedType + } + + transformedClientKey, err := expandDatabaseMigrationServiceConnectionProfileOracleSslClientKey(original["client_key"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedClientKey); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["clientKey"] = transformedClientKey + } + + transformedClientCertificate, err := expandDatabaseMigrationServiceConnectionProfileOracleSslClientCertificate(original["client_certificate"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedClientCertificate); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["clientCertificate"] = transformedClientCertificate + } + + transformedCaCertificate, err := expandDatabaseMigrationServiceConnectionProfileOracleSslCaCertificate(original["ca_certificate"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedCaCertificate); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["caCertificate"] = transformedCaCertificate + } + + return transformed, nil +} + +func expandDatabaseMigrationServiceConnectionProfileOracleSslType(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandDatabaseMigrationServiceConnectionProfileOracleSslClientKey(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandDatabaseMigrationServiceConnectionProfileOracleSslClientCertificate(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandDatabaseMigrationServiceConnectionProfileOracleSslCaCertificate(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandDatabaseMigrationServiceConnectionProfileOracleStaticServiceIpConnectivity(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 { + return nil, nil + } + + if l[0] == nil { + transformed := make(map[string]interface{}) + return transformed, nil + } + transformed := make(map[string]interface{}) + + return transformed, nil +} + +func expandDatabaseMigrationServiceConnectionProfileOracleForwardSshConnectivity(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedHostname, err := expandDatabaseMigrationServiceConnectionProfileOracleForwardSshConnectivityHostname(original["hostname"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHostname); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["hostname"] = transformedHostname + } + + transformedUsername, err := expandDatabaseMigrationServiceConnectionProfileOracleForwardSshConnectivityUsername(original["username"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedUsername); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["username"] = transformedUsername + } + + transformedPort, err := expandDatabaseMigrationServiceConnectionProfileOracleForwardSshConnectivityPort(original["port"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPort); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["port"] = transformedPort + } + + transformedPassword, err := expandDatabaseMigrationServiceConnectionProfileOracleForwardSshConnectivityPassword(original["password"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPassword); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["password"] = transformedPassword + } + + transformedPrivateKey, err := expandDatabaseMigrationServiceConnectionProfileOracleForwardSshConnectivityPrivateKey(original["private_key"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPrivateKey); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["privateKey"] = transformedPrivateKey + } + + return transformed, nil +} + +func expandDatabaseMigrationServiceConnectionProfileOracleForwardSshConnectivityHostname(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandDatabaseMigrationServiceConnectionProfileOracleForwardSshConnectivityUsername(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandDatabaseMigrationServiceConnectionProfileOracleForwardSshConnectivityPort(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandDatabaseMigrationServiceConnectionProfileOracleForwardSshConnectivityPassword(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandDatabaseMigrationServiceConnectionProfileOracleForwardSshConnectivityPrivateKey(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandDatabaseMigrationServiceConnectionProfileOraclePrivateConnectivity(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedPrivateConnection, err := expandDatabaseMigrationServiceConnectionProfileOraclePrivateConnectivityPrivateConnection(original["private_connection"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPrivateConnection); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["privateConnection"] = transformedPrivateConnection + } + + return transformed, nil +} + +func expandDatabaseMigrationServiceConnectionProfileOraclePrivateConnectivityPrivateConnection(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + func expandDatabaseMigrationServiceConnectionProfileCloudsql(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { l := v.([]interface{}) if len(l) == 0 || l[0] == nil { diff --git a/google-beta/services/databasemigrationservice/resource_database_migration_service_connection_profile_test.go b/google-beta/services/databasemigrationservice/resource_database_migration_service_connection_profile_test.go index fb642b8f02..bcca8cd34e 100644 --- a/google-beta/services/databasemigrationservice/resource_database_migration_service_connection_profile_test.go +++ b/google-beta/services/databasemigrationservice/resource_database_migration_service_connection_profile_test.go @@ -5,8 +5,9 @@ package databasemigrationservice_test import ( "testing" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-provider-google-beta/google-beta/acctest" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" ) func TestAccDatabaseMigrationServiceConnectionProfile_update(t *testing.T) { diff --git a/website/docs/r/database_migration_service_connection_profile.html.markdown b/website/docs/r/database_migration_service_connection_profile.html.markdown index 5346d60b5b..c091921592 100644 --- a/website/docs/r/database_migration_service_connection_profile.html.markdown +++ b/website/docs/r/database_migration_service_connection_profile.html.markdown @@ -29,7 +29,7 @@ To get more information about ConnectionProfile, see: * [Database Migration](https://cloud.google.com/database-migration/docs/) ~> **Warning:** All arguments including the following potentially sensitive -values will be stored in the raw state as plain text: `mysql.password`, `mysql.ssl.client_key`, `mysql.ssl.client_certificate`, `mysql.ssl.ca_certificate`, `postgresql.password`, `postgresql.ssl.client_key`, `postgresql.ssl.client_certificate`, `postgresql.ssl.ca_certificate`, `cloudsql.settings.root_password`, `alloydb.settings.initial_user.password`. +values will be stored in the raw state as plain text: `mysql.password`, `mysql.ssl.client_key`, `mysql.ssl.client_certificate`, `mysql.ssl.ca_certificate`, `postgresql.password`, `postgresql.ssl.client_key`, `postgresql.ssl.client_certificate`, `postgresql.ssl.ca_certificate`, `oracle.password`, `oracle.ssl.client_key`, `oracle.ssl.client_certificate`, `oracle.ssl.ca_certificate`, `oracle.forward_ssh_connectivity.password`, `oracle.forward_ssh_connectivity.private_key`, `cloudsql.settings.root_password`, `alloydb.settings.initial_user.password`. [Read more about sensitive data in state](https://www.terraform.io/language/state/sensitive-data).
@@ -183,6 +183,27 @@ resource "google_database_migration_service_connection_profile" "postgresprofile depends_on = [google_sql_user.sqldb_user] } ``` +## Example Usage - Database Migration Service Connection Profile Oracle + + +```hcl +resource "google_database_migration_service_connection_profile" "oracleprofile" { + location = "us-central1" + connection_profile_id = "my-profileid" + display_name = "my-profileid_display" + labels = { + foo = "bar" + } + oracle { + host = "host" + port = 1521 + username = "username" + password = "password" + database_service = "dbprovider" + static_service_ip_connectivity {} + } +} +``` ## Example Usage - Database Migration Service Connection Profile Alloydb @@ -279,6 +300,11 @@ The following arguments are supported: Specifies connection parameters required specifically for PostgreSQL databases. Structure is [documented below](#nested_postgresql). +* `oracle` - + (Optional) + Specifies connection parameters required specifically for Oracle databases. + Structure is [documented below](#nested_oracle). + * `cloudsql` - (Optional) Specifies required connection parameters, and, optionally, the parameters required to create a Cloud SQL destination database instance. @@ -417,6 +443,109 @@ The following arguments are supported: The replica will use this certificate to verify it's connecting to the right host. **Note**: This property is sensitive and will not be displayed in the plan. +The `oracle` block supports: + +* `host` - + (Required) + Required. The IP or hostname of the source Oracle database. + +* `port` - + (Required) + Required. The network port of the source Oracle database. + +* `username` - + (Required) + Required. The username that Database Migration Service will use to connect to the database. The value is encrypted when stored in Database Migration Service. + +* `password` - + (Required) + Required. Input only. The password for the user that Database Migration Service will be using to connect to the database. + This field is not returned on request, and the value is encrypted when stored in Database Migration Service. + **Note**: This property is sensitive and will not be displayed in the plan. + +* `password_set` - + (Output) + Output only. Indicates If this connection profile password is stored. + +* `database_service` - + (Required) + Required. Database service for the Oracle connection. + +* `ssl` - + (Optional) + SSL configuration for the destination to connect to the source database. + Structure is [documented below](#nested_ssl). + +* `static_service_ip_connectivity` - + (Optional) + This object has no nested fields. + Static IP address connectivity configured on service project. + +* `forward_ssh_connectivity` - + (Optional) + SSL configuration for the destination to connect to the source database. + Structure is [documented below](#nested_forward_ssh_connectivity). + +* `private_connectivity` - + (Optional) + Configuration for using a private network to communicate with the source database + Structure is [documented below](#nested_private_connectivity). + + +The `ssl` block supports: + +* `type` - + (Output) + The current connection profile state. + +* `client_key` - + (Optional) + Input only. The unencrypted PKCS#1 or PKCS#8 PEM-encoded private key associated with the Client Certificate. + If this field is used then the 'clientCertificate' field is mandatory. + **Note**: This property is sensitive and will not be displayed in the plan. + +* `client_certificate` - + (Optional) + Input only. The x509 PEM-encoded certificate that will be used by the replica to authenticate against the source database server. + If this field is used then the 'clientKey' field is mandatory + **Note**: This property is sensitive and will not be displayed in the plan. + +* `ca_certificate` - + (Required) + Required. Input only. The x509 PEM-encoded certificate of the CA that signed the source database server's certificate. + The replica will use this certificate to verify it's connecting to the right host. + **Note**: This property is sensitive and will not be displayed in the plan. + +The `forward_ssh_connectivity` block supports: + +* `hostname` - + (Required) + Required. Hostname for the SSH tunnel. + +* `username` - + (Required) + Required. Username for the SSH tunnel. + +* `port` - + (Required) + Port for the SSH tunnel, default value is 22. + +* `password` - + (Optional) + Input only. SSH password. Only one of `password` and `private_key` can be configured. + **Note**: This property is sensitive and will not be displayed in the plan. + +* `private_key` - + (Optional) + Input only. SSH private key. Only one of `password` and `private_key` can be configured. + **Note**: This property is sensitive and will not be displayed in the plan. + +The `private_connectivity` block supports: + +* `private_connection` - + (Required) + Required. The resource name (URI) of the private connection. + The `cloudsql` block supports: * `cloud_sql_id` -