Configure GCP Database Migration Jobs

The gcp:databasemigrationservice/migrationJob:MigrationJob resource, part of the Pulumi GCP provider, defines a Database Migration Service job that orchestrates continuous or one-time replication between source and destination databases. This guide focuses on three capabilities: MySQL to Cloud SQL migrations, PostgreSQL to Cloud SQL migrations, and PostgreSQL to AlloyDB migrations.

Migration jobs connect source and destination databases via ConnectionProfile resources. The examples are intentionally small. Combine them with your own connection profiles, database instances, and network configuration.

Migrate MySQL to Cloud SQL with VPC peering

Teams migrating MySQL databases to Cloud SQL often need continuous replication to minimize downtime. VPC peering enables private connectivity between source and destination databases.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const project = gcp.organizations.getProject({});
const sourceCsql = new gcp.sql.DatabaseInstance("source_csql", {
    name: "source-csql",
    databaseVersion: "MYSQL_5_7",
    settings: {
        tier: "db-n1-standard-1",
        deletionProtectionEnabled: false,
    },
    deletionProtection: false,
});
const sourceSqlClientCert = new gcp.sql.SslCert("source_sql_client_cert", {
    commonName: "cert",
    instance: sourceCsql.name,
}, {
    dependsOn: [sourceCsql],
});
const sourceSqldbUser = new gcp.sql.User("source_sqldb_user", {
    name: "username",
    instance: sourceCsql.name,
    password: "password",
}, {
    dependsOn: [sourceSqlClientCert],
});
const sourceCp = new gcp.databasemigrationservice.ConnectionProfile("source_cp", {
    location: "us-central1",
    connectionProfileId: "source-cp",
    displayName: "source-cp_display",
    labels: {
        foo: "bar",
    },
    mysql: {
        host: sourceCsql.ipAddresses.apply(ipAddresses => ipAddresses[0].ipAddress),
        port: 3306,
        username: sourceSqldbUser.name,
        password: sourceSqldbUser.password,
        ssl: {
            clientKey: sourceSqlClientCert.privateKey,
            clientCertificate: sourceSqlClientCert.cert,
            caCertificate: sourceSqlClientCert.serverCaCert,
            type: "SERVER_CLIENT",
        },
        cloudSqlId: "source-csql",
    },
}, {
    dependsOn: [sourceSqldbUser],
});
const destinationCsql = new gcp.sql.DatabaseInstance("destination_csql", {
    name: "destination-csql",
    databaseVersion: "MYSQL_5_7",
    settings: {
        tier: "db-n1-standard-1",
        deletionProtectionEnabled: false,
    },
    deletionProtection: false,
});
const destinationCp = new gcp.databasemigrationservice.ConnectionProfile("destination_cp", {
    location: "us-central1",
    connectionProfileId: "destination-cp",
    displayName: "destination-cp_display",
    labels: {
        foo: "bar",
    },
    mysql: {
        cloudSqlId: "destination-csql",
    },
}, {
    dependsOn: [destinationCsql],
});
const _default = new gcp.compute.Network("default", {name: "destination-csql"});
const mysqltomysql = new gcp.databasemigrationservice.MigrationJob("mysqltomysql", {
    location: "us-central1",
    migrationJobId: "my-migrationid",
    displayName: "my-migrationid_display",
    labels: {
        foo: "bar",
    },
    performanceConfig: {
        dumpParallelLevel: "MAX",
    },
    vpcPeeringConnectivity: {
        vpc: _default.id,
    },
    dumpType: "LOGICAL",
    dumpFlags: {
        dumpFlags: [{
            name: "max-allowed-packet",
            value: "1073741824",
        }],
    },
    source: sourceCp.name,
    destination: destinationCp.name,
    type: "CONTINUOUS",
});
import pulumi
import pulumi_gcp as gcp

project = gcp.organizations.get_project()
source_csql = gcp.sql.DatabaseInstance("source_csql",
    name="source-csql",
    database_version="MYSQL_5_7",
    settings={
        "tier": "db-n1-standard-1",
        "deletion_protection_enabled": False,
    },
    deletion_protection=False)
source_sql_client_cert = gcp.sql.SslCert("source_sql_client_cert",
    common_name="cert",
    instance=source_csql.name,
    opts = pulumi.ResourceOptions(depends_on=[source_csql]))
source_sqldb_user = gcp.sql.User("source_sqldb_user",
    name="username",
    instance=source_csql.name,
    password="password",
    opts = pulumi.ResourceOptions(depends_on=[source_sql_client_cert]))
source_cp = gcp.databasemigrationservice.ConnectionProfile("source_cp",
    location="us-central1",
    connection_profile_id="source-cp",
    display_name="source-cp_display",
    labels={
        "foo": "bar",
    },
    mysql={
        "host": source_csql.ip_addresses[0].ip_address,
        "port": 3306,
        "username": source_sqldb_user.name,
        "password": source_sqldb_user.password,
        "ssl": {
            "client_key": source_sql_client_cert.private_key,
            "client_certificate": source_sql_client_cert.cert,
            "ca_certificate": source_sql_client_cert.server_ca_cert,
            "type": "SERVER_CLIENT",
        },
        "cloud_sql_id": "source-csql",
    },
    opts = pulumi.ResourceOptions(depends_on=[source_sqldb_user]))
destination_csql = gcp.sql.DatabaseInstance("destination_csql",
    name="destination-csql",
    database_version="MYSQL_5_7",
    settings={
        "tier": "db-n1-standard-1",
        "deletion_protection_enabled": False,
    },
    deletion_protection=False)
destination_cp = gcp.databasemigrationservice.ConnectionProfile("destination_cp",
    location="us-central1",
    connection_profile_id="destination-cp",
    display_name="destination-cp_display",
    labels={
        "foo": "bar",
    },
    mysql={
        "cloud_sql_id": "destination-csql",
    },
    opts = pulumi.ResourceOptions(depends_on=[destination_csql]))
default = gcp.compute.Network("default", name="destination-csql")
mysqltomysql = gcp.databasemigrationservice.MigrationJob("mysqltomysql",
    location="us-central1",
    migration_job_id="my-migrationid",
    display_name="my-migrationid_display",
    labels={
        "foo": "bar",
    },
    performance_config={
        "dump_parallel_level": "MAX",
    },
    vpc_peering_connectivity={
        "vpc": default.id,
    },
    dump_type="LOGICAL",
    dump_flags={
        "dump_flags": [{
            "name": "max-allowed-packet",
            "value": "1073741824",
        }],
    },
    source=source_cp.name,
    destination=destination_cp.name,
    type="CONTINUOUS")
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/databasemigrationservice"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/sql"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := organizations.LookupProject(ctx, &organizations.LookupProjectArgs{}, nil)
		if err != nil {
			return err
		}
		sourceCsql, err := sql.NewDatabaseInstance(ctx, "source_csql", &sql.DatabaseInstanceArgs{
			Name:            pulumi.String("source-csql"),
			DatabaseVersion: pulumi.String("MYSQL_5_7"),
			Settings: &sql.DatabaseInstanceSettingsArgs{
				Tier:                      pulumi.String("db-n1-standard-1"),
				DeletionProtectionEnabled: pulumi.Bool(false),
			},
			DeletionProtection: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		sourceSqlClientCert, err := sql.NewSslCert(ctx, "source_sql_client_cert", &sql.SslCertArgs{
			CommonName: pulumi.String("cert"),
			Instance:   sourceCsql.Name,
		}, pulumi.DependsOn([]pulumi.Resource{
			sourceCsql,
		}))
		if err != nil {
			return err
		}
		sourceSqldbUser, err := sql.NewUser(ctx, "source_sqldb_user", &sql.UserArgs{
			Name:     pulumi.String("username"),
			Instance: sourceCsql.Name,
			Password: pulumi.String("password"),
		}, pulumi.DependsOn([]pulumi.Resource{
			sourceSqlClientCert,
		}))
		if err != nil {
			return err
		}
		sourceCp, err := databasemigrationservice.NewConnectionProfile(ctx, "source_cp", &databasemigrationservice.ConnectionProfileArgs{
			Location:            pulumi.String("us-central1"),
			ConnectionProfileId: pulumi.String("source-cp"),
			DisplayName:         pulumi.String("source-cp_display"),
			Labels: pulumi.StringMap{
				"foo": pulumi.String("bar"),
			},
			Mysql: &databasemigrationservice.ConnectionProfileMysqlArgs{
				Host: sourceCsql.IpAddresses.ApplyT(func(ipAddresses []sql.DatabaseInstanceIpAddress) (*string, error) {
					return &ipAddresses[0].IpAddress, nil
				}).(pulumi.StringPtrOutput),
				Port:     pulumi.Int(3306),
				Username: sourceSqldbUser.Name,
				Password: sourceSqldbUser.Password,
				Ssl: &databasemigrationservice.ConnectionProfileMysqlSslArgs{
					ClientKey:         sourceSqlClientCert.PrivateKey,
					ClientCertificate: sourceSqlClientCert.Cert,
					CaCertificate:     sourceSqlClientCert.ServerCaCert,
					Type:              pulumi.String("SERVER_CLIENT"),
				},
				CloudSqlId: pulumi.String("source-csql"),
			},
		}, pulumi.DependsOn([]pulumi.Resource{
			sourceSqldbUser,
		}))
		if err != nil {
			return err
		}
		destinationCsql, err := sql.NewDatabaseInstance(ctx, "destination_csql", &sql.DatabaseInstanceArgs{
			Name:            pulumi.String("destination-csql"),
			DatabaseVersion: pulumi.String("MYSQL_5_7"),
			Settings: &sql.DatabaseInstanceSettingsArgs{
				Tier:                      pulumi.String("db-n1-standard-1"),
				DeletionProtectionEnabled: pulumi.Bool(false),
			},
			DeletionProtection: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		destinationCp, err := databasemigrationservice.NewConnectionProfile(ctx, "destination_cp", &databasemigrationservice.ConnectionProfileArgs{
			Location:            pulumi.String("us-central1"),
			ConnectionProfileId: pulumi.String("destination-cp"),
			DisplayName:         pulumi.String("destination-cp_display"),
			Labels: pulumi.StringMap{
				"foo": pulumi.String("bar"),
			},
			Mysql: &databasemigrationservice.ConnectionProfileMysqlArgs{
				CloudSqlId: pulumi.String("destination-csql"),
			},
		}, pulumi.DependsOn([]pulumi.Resource{
			destinationCsql,
		}))
		if err != nil {
			return err
		}
		_default, err := compute.NewNetwork(ctx, "default", &compute.NetworkArgs{
			Name: pulumi.String("destination-csql"),
		})
		if err != nil {
			return err
		}
		_, err = databasemigrationservice.NewMigrationJob(ctx, "mysqltomysql", &databasemigrationservice.MigrationJobArgs{
			Location:       pulumi.String("us-central1"),
			MigrationJobId: pulumi.String("my-migrationid"),
			DisplayName:    pulumi.String("my-migrationid_display"),
			Labels: pulumi.StringMap{
				"foo": pulumi.String("bar"),
			},
			PerformanceConfig: &databasemigrationservice.MigrationJobPerformanceConfigArgs{
				DumpParallelLevel: pulumi.String("MAX"),
			},
			VpcPeeringConnectivity: &databasemigrationservice.MigrationJobVpcPeeringConnectivityArgs{
				Vpc: _default.ID(),
			},
			DumpType: pulumi.String("LOGICAL"),
			DumpFlags: &databasemigrationservice.MigrationJobDumpFlagsArgs{
				DumpFlags: databasemigrationservice.MigrationJobDumpFlagsDumpFlagArray{
					&databasemigrationservice.MigrationJobDumpFlagsDumpFlagArgs{
						Name:  pulumi.String("max-allowed-packet"),
						Value: pulumi.String("1073741824"),
					},
				},
			},
			Source:      sourceCp.Name,
			Destination: destinationCp.Name,
			Type:        pulumi.String("CONTINUOUS"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var project = Gcp.Organizations.GetProject.Invoke();

    var sourceCsql = new Gcp.Sql.DatabaseInstance("source_csql", new()
    {
        Name = "source-csql",
        DatabaseVersion = "MYSQL_5_7",
        Settings = new Gcp.Sql.Inputs.DatabaseInstanceSettingsArgs
        {
            Tier = "db-n1-standard-1",
            DeletionProtectionEnabled = false,
        },
        DeletionProtection = false,
    });

    var sourceSqlClientCert = new Gcp.Sql.SslCert("source_sql_client_cert", new()
    {
        CommonName = "cert",
        Instance = sourceCsql.Name,
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            sourceCsql,
        },
    });

    var sourceSqldbUser = new Gcp.Sql.User("source_sqldb_user", new()
    {
        Name = "username",
        Instance = sourceCsql.Name,
        Password = "password",
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            sourceSqlClientCert,
        },
    });

    var sourceCp = new Gcp.DatabaseMigrationService.ConnectionProfile("source_cp", new()
    {
        Location = "us-central1",
        ConnectionProfileId = "source-cp",
        DisplayName = "source-cp_display",
        Labels = 
        {
            { "foo", "bar" },
        },
        Mysql = new Gcp.DatabaseMigrationService.Inputs.ConnectionProfileMysqlArgs
        {
            Host = sourceCsql.IpAddresses.Apply(ipAddresses => ipAddresses[0].IpAddress),
            Port = 3306,
            Username = sourceSqldbUser.Name,
            Password = sourceSqldbUser.Password,
            Ssl = new Gcp.DatabaseMigrationService.Inputs.ConnectionProfileMysqlSslArgs
            {
                ClientKey = sourceSqlClientCert.PrivateKey,
                ClientCertificate = sourceSqlClientCert.Cert,
                CaCertificate = sourceSqlClientCert.ServerCaCert,
                Type = "SERVER_CLIENT",
            },
            CloudSqlId = "source-csql",
        },
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            sourceSqldbUser,
        },
    });

    var destinationCsql = new Gcp.Sql.DatabaseInstance("destination_csql", new()
    {
        Name = "destination-csql",
        DatabaseVersion = "MYSQL_5_7",
        Settings = new Gcp.Sql.Inputs.DatabaseInstanceSettingsArgs
        {
            Tier = "db-n1-standard-1",
            DeletionProtectionEnabled = false,
        },
        DeletionProtection = false,
    });

    var destinationCp = new Gcp.DatabaseMigrationService.ConnectionProfile("destination_cp", new()
    {
        Location = "us-central1",
        ConnectionProfileId = "destination-cp",
        DisplayName = "destination-cp_display",
        Labels = 
        {
            { "foo", "bar" },
        },
        Mysql = new Gcp.DatabaseMigrationService.Inputs.ConnectionProfileMysqlArgs
        {
            CloudSqlId = "destination-csql",
        },
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            destinationCsql,
        },
    });

    var @default = new Gcp.Compute.Network("default", new()
    {
        Name = "destination-csql",
    });

    var mysqltomysql = new Gcp.DatabaseMigrationService.MigrationJob("mysqltomysql", new()
    {
        Location = "us-central1",
        MigrationJobId = "my-migrationid",
        DisplayName = "my-migrationid_display",
        Labels = 
        {
            { "foo", "bar" },
        },
        PerformanceConfig = new Gcp.DatabaseMigrationService.Inputs.MigrationJobPerformanceConfigArgs
        {
            DumpParallelLevel = "MAX",
        },
        VpcPeeringConnectivity = new Gcp.DatabaseMigrationService.Inputs.MigrationJobVpcPeeringConnectivityArgs
        {
            Vpc = @default.Id,
        },
        DumpType = "LOGICAL",
        DumpFlags = new Gcp.DatabaseMigrationService.Inputs.MigrationJobDumpFlagsArgs
        {
            DumpFlags = new[]
            {
                new Gcp.DatabaseMigrationService.Inputs.MigrationJobDumpFlagsDumpFlagArgs
                {
                    Name = "max-allowed-packet",
                    Value = "1073741824",
                },
            },
        },
        Source = sourceCp.Name,
        Destination = destinationCp.Name,
        Type = "CONTINUOUS",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.organizations.inputs.GetProjectArgs;
import com.pulumi.gcp.sql.DatabaseInstance;
import com.pulumi.gcp.sql.DatabaseInstanceArgs;
import com.pulumi.gcp.sql.inputs.DatabaseInstanceSettingsArgs;
import com.pulumi.gcp.sql.SslCert;
import com.pulumi.gcp.sql.SslCertArgs;
import com.pulumi.gcp.sql.User;
import com.pulumi.gcp.sql.UserArgs;
import com.pulumi.gcp.databasemigrationservice.ConnectionProfile;
import com.pulumi.gcp.databasemigrationservice.ConnectionProfileArgs;
import com.pulumi.gcp.databasemigrationservice.inputs.ConnectionProfileMysqlArgs;
import com.pulumi.gcp.databasemigrationservice.inputs.ConnectionProfileMysqlSslArgs;
import com.pulumi.gcp.compute.Network;
import com.pulumi.gcp.compute.NetworkArgs;
import com.pulumi.gcp.databasemigrationservice.MigrationJob;
import com.pulumi.gcp.databasemigrationservice.MigrationJobArgs;
import com.pulumi.gcp.databasemigrationservice.inputs.MigrationJobPerformanceConfigArgs;
import com.pulumi.gcp.databasemigrationservice.inputs.MigrationJobVpcPeeringConnectivityArgs;
import com.pulumi.gcp.databasemigrationservice.inputs.MigrationJobDumpFlagsArgs;
import com.pulumi.resources.CustomResourceOptions;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        final var project = OrganizationsFunctions.getProject(GetProjectArgs.builder()
            .build());

        var sourceCsql = new DatabaseInstance("sourceCsql", DatabaseInstanceArgs.builder()
            .name("source-csql")
            .databaseVersion("MYSQL_5_7")
            .settings(DatabaseInstanceSettingsArgs.builder()
                .tier("db-n1-standard-1")
                .deletionProtectionEnabled(false)
                .build())
            .deletionProtection(false)
            .build());

        var sourceSqlClientCert = new SslCert("sourceSqlClientCert", SslCertArgs.builder()
            .commonName("cert")
            .instance(sourceCsql.name())
            .build(), CustomResourceOptions.builder()
                .dependsOn(sourceCsql)
                .build());

        var sourceSqldbUser = new User("sourceSqldbUser", UserArgs.builder()
            .name("username")
            .instance(sourceCsql.name())
            .password("password")
            .build(), CustomResourceOptions.builder()
                .dependsOn(sourceSqlClientCert)
                .build());

        var sourceCp = new ConnectionProfile("sourceCp", ConnectionProfileArgs.builder()
            .location("us-central1")
            .connectionProfileId("source-cp")
            .displayName("source-cp_display")
            .labels(Map.of("foo", "bar"))
            .mysql(ConnectionProfileMysqlArgs.builder()
                .host(sourceCsql.ipAddresses().applyValue(_ipAddresses -> _ipAddresses[0].ipAddress()))
                .port(3306)
                .username(sourceSqldbUser.name())
                .password(sourceSqldbUser.password())
                .ssl(ConnectionProfileMysqlSslArgs.builder()
                    .clientKey(sourceSqlClientCert.privateKey())
                    .clientCertificate(sourceSqlClientCert.cert())
                    .caCertificate(sourceSqlClientCert.serverCaCert())
                    .type("SERVER_CLIENT")
                    .build())
                .cloudSqlId("source-csql")
                .build())
            .build(), CustomResourceOptions.builder()
                .dependsOn(sourceSqldbUser)
                .build());

        var destinationCsql = new DatabaseInstance("destinationCsql", DatabaseInstanceArgs.builder()
            .name("destination-csql")
            .databaseVersion("MYSQL_5_7")
            .settings(DatabaseInstanceSettingsArgs.builder()
                .tier("db-n1-standard-1")
                .deletionProtectionEnabled(false)
                .build())
            .deletionProtection(false)
            .build());

        var destinationCp = new ConnectionProfile("destinationCp", ConnectionProfileArgs.builder()
            .location("us-central1")
            .connectionProfileId("destination-cp")
            .displayName("destination-cp_display")
            .labels(Map.of("foo", "bar"))
            .mysql(ConnectionProfileMysqlArgs.builder()
                .cloudSqlId("destination-csql")
                .build())
            .build(), CustomResourceOptions.builder()
                .dependsOn(destinationCsql)
                .build());

        var default_ = new Network("default", NetworkArgs.builder()
            .name("destination-csql")
            .build());

        var mysqltomysql = new MigrationJob("mysqltomysql", MigrationJobArgs.builder()
            .location("us-central1")
            .migrationJobId("my-migrationid")
            .displayName("my-migrationid_display")
            .labels(Map.of("foo", "bar"))
            .performanceConfig(MigrationJobPerformanceConfigArgs.builder()
                .dumpParallelLevel("MAX")
                .build())
            .vpcPeeringConnectivity(MigrationJobVpcPeeringConnectivityArgs.builder()
                .vpc(default_.id())
                .build())
            .dumpType("LOGICAL")
            .dumpFlags(MigrationJobDumpFlagsArgs.builder()
                .dumpFlags(MigrationJobDumpFlagsDumpFlagArgs.builder()
                    .name("max-allowed-packet")
                    .value("1073741824")
                    .build())
                .build())
            .source(sourceCp.name())
            .destination(destinationCp.name())
            .type("CONTINUOUS")
            .build());

    }
}
resources:
  sourceCsql:
    type: gcp:sql:DatabaseInstance
    name: source_csql
    properties:
      name: source-csql
      databaseVersion: MYSQL_5_7
      settings:
        tier: db-n1-standard-1
        deletionProtectionEnabled: false
      deletionProtection: false
  sourceSqlClientCert:
    type: gcp:sql:SslCert
    name: source_sql_client_cert
    properties:
      commonName: cert
      instance: ${sourceCsql.name}
    options:
      dependsOn:
        - ${sourceCsql}
  sourceSqldbUser:
    type: gcp:sql:User
    name: source_sqldb_user
    properties:
      name: username
      instance: ${sourceCsql.name}
      password: password
    options:
      dependsOn:
        - ${sourceSqlClientCert}
  sourceCp:
    type: gcp:databasemigrationservice:ConnectionProfile
    name: source_cp
    properties:
      location: us-central1
      connectionProfileId: source-cp
      displayName: source-cp_display
      labels:
        foo: bar
      mysql:
        host: ${sourceCsql.ipAddresses[0].ipAddress}
        port: 3306
        username: ${sourceSqldbUser.name}
        password: ${sourceSqldbUser.password}
        ssl:
          clientKey: ${sourceSqlClientCert.privateKey}
          clientCertificate: ${sourceSqlClientCert.cert}
          caCertificate: ${sourceSqlClientCert.serverCaCert}
          type: SERVER_CLIENT
        cloudSqlId: source-csql
    options:
      dependsOn:
        - ${sourceSqldbUser}
  destinationCsql:
    type: gcp:sql:DatabaseInstance
    name: destination_csql
    properties:
      name: destination-csql
      databaseVersion: MYSQL_5_7
      settings:
        tier: db-n1-standard-1
        deletionProtectionEnabled: false
      deletionProtection: false
  destinationCp:
    type: gcp:databasemigrationservice:ConnectionProfile
    name: destination_cp
    properties:
      location: us-central1
      connectionProfileId: destination-cp
      displayName: destination-cp_display
      labels:
        foo: bar
      mysql:
        cloudSqlId: destination-csql
    options:
      dependsOn:
        - ${destinationCsql}
  default:
    type: gcp:compute:Network
    properties:
      name: destination-csql
  mysqltomysql:
    type: gcp:databasemigrationservice:MigrationJob
    properties:
      location: us-central1
      migrationJobId: my-migrationid
      displayName: my-migrationid_display
      labels:
        foo: bar
      performanceConfig:
        dumpParallelLevel: MAX
      vpcPeeringConnectivity:
        vpc: ${default.id}
      dumpType: LOGICAL
      dumpFlags:
        dumpFlags:
          - name: max-allowed-packet
            value: '1073741824'
      source: ${sourceCp.name}
      destination: ${destinationCp.name}
      type: CONTINUOUS
variables:
  project:
    fn::invoke:
      function: gcp:organizations:getProject
      arguments: {}

The source and destination properties reference ConnectionProfile resources that define database endpoints and credentials. The type property set to CONTINUOUS enables ongoing replication rather than a one-time copy. The vpcPeeringConnectivity block establishes private network connectivity through the specified VPC. The performanceConfig controls parallelism during the initial dump phase, and dumpType specifies whether to use logical or physical backup methods.

Migrate PostgreSQL to Cloud SQL with static IP

PostgreSQL migrations to Cloud SQL can use static IP connectivity when VPC peering isn’t available or when the source database needs to allowlist specific IP addresses.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const project = gcp.organizations.getProject({});
const sourceCsql = new gcp.sql.DatabaseInstance("source_csql", {
    name: "source-csql",
    databaseVersion: "POSTGRES_15",
    settings: {
        tier: "db-custom-2-13312",
        deletionProtectionEnabled: false,
    },
    deletionProtection: false,
});
const sourceSqlClientCert = new gcp.sql.SslCert("source_sql_client_cert", {
    commonName: "cert",
    instance: sourceCsql.name,
}, {
    dependsOn: [sourceCsql],
});
const sourceSqldbUser = new gcp.sql.User("source_sqldb_user", {
    name: "username",
    instance: sourceCsql.name,
    password: "password",
}, {
    dependsOn: [sourceSqlClientCert],
});
const sourceCp = new gcp.databasemigrationservice.ConnectionProfile("source_cp", {
    location: "us-central1",
    connectionProfileId: "source-cp",
    displayName: "source-cp_display",
    labels: {
        foo: "bar",
    },
    postgresql: {
        host: sourceCsql.ipAddresses.apply(ipAddresses => ipAddresses[0].ipAddress),
        port: 3306,
        username: sourceSqldbUser.name,
        password: sourceSqldbUser.password,
        ssl: {
            clientKey: sourceSqlClientCert.privateKey,
            clientCertificate: sourceSqlClientCert.cert,
            caCertificate: sourceSqlClientCert.serverCaCert,
            type: "SERVER_CLIENT",
        },
        cloudSqlId: "source-csql",
    },
}, {
    dependsOn: [sourceSqldbUser],
});
const destinationCsql = new gcp.sql.DatabaseInstance("destination_csql", {
    name: "destination-csql",
    databaseVersion: "POSTGRES_15",
    settings: {
        tier: "db-custom-2-13312",
        deletionProtectionEnabled: false,
    },
    deletionProtection: false,
});
const destinationCp = new gcp.databasemigrationservice.ConnectionProfile("destination_cp", {
    location: "us-central1",
    connectionProfileId: "destination-cp",
    displayName: "destination-cp_display",
    labels: {
        foo: "bar",
    },
    postgresql: {
        cloudSqlId: "destination-csql",
    },
}, {
    dependsOn: [destinationCsql],
});
const psqltopsql = new gcp.databasemigrationservice.MigrationJob("psqltopsql", {
    location: "us-central1",
    migrationJobId: "my-migrationid",
    displayName: "my-migrationid_display",
    labels: {
        foo: "bar",
    },
    staticIpConnectivity: {},
    source: sourceCp.name,
    destination: destinationCp.name,
    type: "CONTINUOUS",
});
import pulumi
import pulumi_gcp as gcp

project = gcp.organizations.get_project()
source_csql = gcp.sql.DatabaseInstance("source_csql",
    name="source-csql",
    database_version="POSTGRES_15",
    settings={
        "tier": "db-custom-2-13312",
        "deletion_protection_enabled": False,
    },
    deletion_protection=False)
source_sql_client_cert = gcp.sql.SslCert("source_sql_client_cert",
    common_name="cert",
    instance=source_csql.name,
    opts = pulumi.ResourceOptions(depends_on=[source_csql]))
source_sqldb_user = gcp.sql.User("source_sqldb_user",
    name="username",
    instance=source_csql.name,
    password="password",
    opts = pulumi.ResourceOptions(depends_on=[source_sql_client_cert]))
source_cp = gcp.databasemigrationservice.ConnectionProfile("source_cp",
    location="us-central1",
    connection_profile_id="source-cp",
    display_name="source-cp_display",
    labels={
        "foo": "bar",
    },
    postgresql={
        "host": source_csql.ip_addresses[0].ip_address,
        "port": 3306,
        "username": source_sqldb_user.name,
        "password": source_sqldb_user.password,
        "ssl": {
            "client_key": source_sql_client_cert.private_key,
            "client_certificate": source_sql_client_cert.cert,
            "ca_certificate": source_sql_client_cert.server_ca_cert,
            "type": "SERVER_CLIENT",
        },
        "cloud_sql_id": "source-csql",
    },
    opts = pulumi.ResourceOptions(depends_on=[source_sqldb_user]))
destination_csql = gcp.sql.DatabaseInstance("destination_csql",
    name="destination-csql",
    database_version="POSTGRES_15",
    settings={
        "tier": "db-custom-2-13312",
        "deletion_protection_enabled": False,
    },
    deletion_protection=False)
destination_cp = gcp.databasemigrationservice.ConnectionProfile("destination_cp",
    location="us-central1",
    connection_profile_id="destination-cp",
    display_name="destination-cp_display",
    labels={
        "foo": "bar",
    },
    postgresql={
        "cloud_sql_id": "destination-csql",
    },
    opts = pulumi.ResourceOptions(depends_on=[destination_csql]))
psqltopsql = gcp.databasemigrationservice.MigrationJob("psqltopsql",
    location="us-central1",
    migration_job_id="my-migrationid",
    display_name="my-migrationid_display",
    labels={
        "foo": "bar",
    },
    static_ip_connectivity={},
    source=source_cp.name,
    destination=destination_cp.name,
    type="CONTINUOUS")
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/databasemigrationservice"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/sql"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := organizations.LookupProject(ctx, &organizations.LookupProjectArgs{}, nil)
		if err != nil {
			return err
		}
		sourceCsql, err := sql.NewDatabaseInstance(ctx, "source_csql", &sql.DatabaseInstanceArgs{
			Name:            pulumi.String("source-csql"),
			DatabaseVersion: pulumi.String("POSTGRES_15"),
			Settings: &sql.DatabaseInstanceSettingsArgs{
				Tier:                      pulumi.String("db-custom-2-13312"),
				DeletionProtectionEnabled: pulumi.Bool(false),
			},
			DeletionProtection: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		sourceSqlClientCert, err := sql.NewSslCert(ctx, "source_sql_client_cert", &sql.SslCertArgs{
			CommonName: pulumi.String("cert"),
			Instance:   sourceCsql.Name,
		}, pulumi.DependsOn([]pulumi.Resource{
			sourceCsql,
		}))
		if err != nil {
			return err
		}
		sourceSqldbUser, err := sql.NewUser(ctx, "source_sqldb_user", &sql.UserArgs{
			Name:     pulumi.String("username"),
			Instance: sourceCsql.Name,
			Password: pulumi.String("password"),
		}, pulumi.DependsOn([]pulumi.Resource{
			sourceSqlClientCert,
		}))
		if err != nil {
			return err
		}
		sourceCp, err := databasemigrationservice.NewConnectionProfile(ctx, "source_cp", &databasemigrationservice.ConnectionProfileArgs{
			Location:            pulumi.String("us-central1"),
			ConnectionProfileId: pulumi.String("source-cp"),
			DisplayName:         pulumi.String("source-cp_display"),
			Labels: pulumi.StringMap{
				"foo": pulumi.String("bar"),
			},
			Postgresql: &databasemigrationservice.ConnectionProfilePostgresqlArgs{
				Host: sourceCsql.IpAddresses.ApplyT(func(ipAddresses []sql.DatabaseInstanceIpAddress) (*string, error) {
					return &ipAddresses[0].IpAddress, nil
				}).(pulumi.StringPtrOutput),
				Port:     pulumi.Int(3306),
				Username: sourceSqldbUser.Name,
				Password: sourceSqldbUser.Password,
				Ssl: &databasemigrationservice.ConnectionProfilePostgresqlSslArgs{
					ClientKey:         sourceSqlClientCert.PrivateKey,
					ClientCertificate: sourceSqlClientCert.Cert,
					CaCertificate:     sourceSqlClientCert.ServerCaCert,
					Type:              pulumi.String("SERVER_CLIENT"),
				},
				CloudSqlId: pulumi.String("source-csql"),
			},
		}, pulumi.DependsOn([]pulumi.Resource{
			sourceSqldbUser,
		}))
		if err != nil {
			return err
		}
		destinationCsql, err := sql.NewDatabaseInstance(ctx, "destination_csql", &sql.DatabaseInstanceArgs{
			Name:            pulumi.String("destination-csql"),
			DatabaseVersion: pulumi.String("POSTGRES_15"),
			Settings: &sql.DatabaseInstanceSettingsArgs{
				Tier:                      pulumi.String("db-custom-2-13312"),
				DeletionProtectionEnabled: pulumi.Bool(false),
			},
			DeletionProtection: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		destinationCp, err := databasemigrationservice.NewConnectionProfile(ctx, "destination_cp", &databasemigrationservice.ConnectionProfileArgs{
			Location:            pulumi.String("us-central1"),
			ConnectionProfileId: pulumi.String("destination-cp"),
			DisplayName:         pulumi.String("destination-cp_display"),
			Labels: pulumi.StringMap{
				"foo": pulumi.String("bar"),
			},
			Postgresql: &databasemigrationservice.ConnectionProfilePostgresqlArgs{
				CloudSqlId: pulumi.String("destination-csql"),
			},
		}, pulumi.DependsOn([]pulumi.Resource{
			destinationCsql,
		}))
		if err != nil {
			return err
		}
		_, err = databasemigrationservice.NewMigrationJob(ctx, "psqltopsql", &databasemigrationservice.MigrationJobArgs{
			Location:       pulumi.String("us-central1"),
			MigrationJobId: pulumi.String("my-migrationid"),
			DisplayName:    pulumi.String("my-migrationid_display"),
			Labels: pulumi.StringMap{
				"foo": pulumi.String("bar"),
			},
			StaticIpConnectivity: &databasemigrationservice.MigrationJobStaticIpConnectivityArgs{},
			Source:               sourceCp.Name,
			Destination:          destinationCp.Name,
			Type:                 pulumi.String("CONTINUOUS"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var project = Gcp.Organizations.GetProject.Invoke();

    var sourceCsql = new Gcp.Sql.DatabaseInstance("source_csql", new()
    {
        Name = "source-csql",
        DatabaseVersion = "POSTGRES_15",
        Settings = new Gcp.Sql.Inputs.DatabaseInstanceSettingsArgs
        {
            Tier = "db-custom-2-13312",
            DeletionProtectionEnabled = false,
        },
        DeletionProtection = false,
    });

    var sourceSqlClientCert = new Gcp.Sql.SslCert("source_sql_client_cert", new()
    {
        CommonName = "cert",
        Instance = sourceCsql.Name,
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            sourceCsql,
        },
    });

    var sourceSqldbUser = new Gcp.Sql.User("source_sqldb_user", new()
    {
        Name = "username",
        Instance = sourceCsql.Name,
        Password = "password",
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            sourceSqlClientCert,
        },
    });

    var sourceCp = new Gcp.DatabaseMigrationService.ConnectionProfile("source_cp", new()
    {
        Location = "us-central1",
        ConnectionProfileId = "source-cp",
        DisplayName = "source-cp_display",
        Labels = 
        {
            { "foo", "bar" },
        },
        Postgresql = new Gcp.DatabaseMigrationService.Inputs.ConnectionProfilePostgresqlArgs
        {
            Host = sourceCsql.IpAddresses.Apply(ipAddresses => ipAddresses[0].IpAddress),
            Port = 3306,
            Username = sourceSqldbUser.Name,
            Password = sourceSqldbUser.Password,
            Ssl = new Gcp.DatabaseMigrationService.Inputs.ConnectionProfilePostgresqlSslArgs
            {
                ClientKey = sourceSqlClientCert.PrivateKey,
                ClientCertificate = sourceSqlClientCert.Cert,
                CaCertificate = sourceSqlClientCert.ServerCaCert,
                Type = "SERVER_CLIENT",
            },
            CloudSqlId = "source-csql",
        },
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            sourceSqldbUser,
        },
    });

    var destinationCsql = new Gcp.Sql.DatabaseInstance("destination_csql", new()
    {
        Name = "destination-csql",
        DatabaseVersion = "POSTGRES_15",
        Settings = new Gcp.Sql.Inputs.DatabaseInstanceSettingsArgs
        {
            Tier = "db-custom-2-13312",
            DeletionProtectionEnabled = false,
        },
        DeletionProtection = false,
    });

    var destinationCp = new Gcp.DatabaseMigrationService.ConnectionProfile("destination_cp", new()
    {
        Location = "us-central1",
        ConnectionProfileId = "destination-cp",
        DisplayName = "destination-cp_display",
        Labels = 
        {
            { "foo", "bar" },
        },
        Postgresql = new Gcp.DatabaseMigrationService.Inputs.ConnectionProfilePostgresqlArgs
        {
            CloudSqlId = "destination-csql",
        },
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            destinationCsql,
        },
    });

    var psqltopsql = new Gcp.DatabaseMigrationService.MigrationJob("psqltopsql", new()
    {
        Location = "us-central1",
        MigrationJobId = "my-migrationid",
        DisplayName = "my-migrationid_display",
        Labels = 
        {
            { "foo", "bar" },
        },
        StaticIpConnectivity = null,
        Source = sourceCp.Name,
        Destination = destinationCp.Name,
        Type = "CONTINUOUS",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.organizations.inputs.GetProjectArgs;
import com.pulumi.gcp.sql.DatabaseInstance;
import com.pulumi.gcp.sql.DatabaseInstanceArgs;
import com.pulumi.gcp.sql.inputs.DatabaseInstanceSettingsArgs;
import com.pulumi.gcp.sql.SslCert;
import com.pulumi.gcp.sql.SslCertArgs;
import com.pulumi.gcp.sql.User;
import com.pulumi.gcp.sql.UserArgs;
import com.pulumi.gcp.databasemigrationservice.ConnectionProfile;
import com.pulumi.gcp.databasemigrationservice.ConnectionProfileArgs;
import com.pulumi.gcp.databasemigrationservice.inputs.ConnectionProfilePostgresqlArgs;
import com.pulumi.gcp.databasemigrationservice.inputs.ConnectionProfilePostgresqlSslArgs;
import com.pulumi.gcp.databasemigrationservice.MigrationJob;
import com.pulumi.gcp.databasemigrationservice.MigrationJobArgs;
import com.pulumi.gcp.databasemigrationservice.inputs.MigrationJobStaticIpConnectivityArgs;
import com.pulumi.resources.CustomResourceOptions;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        final var project = OrganizationsFunctions.getProject(GetProjectArgs.builder()
            .build());

        var sourceCsql = new DatabaseInstance("sourceCsql", DatabaseInstanceArgs.builder()
            .name("source-csql")
            .databaseVersion("POSTGRES_15")
            .settings(DatabaseInstanceSettingsArgs.builder()
                .tier("db-custom-2-13312")
                .deletionProtectionEnabled(false)
                .build())
            .deletionProtection(false)
            .build());

        var sourceSqlClientCert = new SslCert("sourceSqlClientCert", SslCertArgs.builder()
            .commonName("cert")
            .instance(sourceCsql.name())
            .build(), CustomResourceOptions.builder()
                .dependsOn(sourceCsql)
                .build());

        var sourceSqldbUser = new User("sourceSqldbUser", UserArgs.builder()
            .name("username")
            .instance(sourceCsql.name())
            .password("password")
            .build(), CustomResourceOptions.builder()
                .dependsOn(sourceSqlClientCert)
                .build());

        var sourceCp = new ConnectionProfile("sourceCp", ConnectionProfileArgs.builder()
            .location("us-central1")
            .connectionProfileId("source-cp")
            .displayName("source-cp_display")
            .labels(Map.of("foo", "bar"))
            .postgresql(ConnectionProfilePostgresqlArgs.builder()
                .host(sourceCsql.ipAddresses().applyValue(_ipAddresses -> _ipAddresses[0].ipAddress()))
                .port(3306)
                .username(sourceSqldbUser.name())
                .password(sourceSqldbUser.password())
                .ssl(ConnectionProfilePostgresqlSslArgs.builder()
                    .clientKey(sourceSqlClientCert.privateKey())
                    .clientCertificate(sourceSqlClientCert.cert())
                    .caCertificate(sourceSqlClientCert.serverCaCert())
                    .type("SERVER_CLIENT")
                    .build())
                .cloudSqlId("source-csql")
                .build())
            .build(), CustomResourceOptions.builder()
                .dependsOn(sourceSqldbUser)
                .build());

        var destinationCsql = new DatabaseInstance("destinationCsql", DatabaseInstanceArgs.builder()
            .name("destination-csql")
            .databaseVersion("POSTGRES_15")
            .settings(DatabaseInstanceSettingsArgs.builder()
                .tier("db-custom-2-13312")
                .deletionProtectionEnabled(false)
                .build())
            .deletionProtection(false)
            .build());

        var destinationCp = new ConnectionProfile("destinationCp", ConnectionProfileArgs.builder()
            .location("us-central1")
            .connectionProfileId("destination-cp")
            .displayName("destination-cp_display")
            .labels(Map.of("foo", "bar"))
            .postgresql(ConnectionProfilePostgresqlArgs.builder()
                .cloudSqlId("destination-csql")
                .build())
            .build(), CustomResourceOptions.builder()
                .dependsOn(destinationCsql)
                .build());

        var psqltopsql = new MigrationJob("psqltopsql", MigrationJobArgs.builder()
            .location("us-central1")
            .migrationJobId("my-migrationid")
            .displayName("my-migrationid_display")
            .labels(Map.of("foo", "bar"))
            .staticIpConnectivity(MigrationJobStaticIpConnectivityArgs.builder()
                .build())
            .source(sourceCp.name())
            .destination(destinationCp.name())
            .type("CONTINUOUS")
            .build());

    }
}
resources:
  sourceCsql:
    type: gcp:sql:DatabaseInstance
    name: source_csql
    properties:
      name: source-csql
      databaseVersion: POSTGRES_15
      settings:
        tier: db-custom-2-13312
        deletionProtectionEnabled: false
      deletionProtection: false
  sourceSqlClientCert:
    type: gcp:sql:SslCert
    name: source_sql_client_cert
    properties:
      commonName: cert
      instance: ${sourceCsql.name}
    options:
      dependsOn:
        - ${sourceCsql}
  sourceSqldbUser:
    type: gcp:sql:User
    name: source_sqldb_user
    properties:
      name: username
      instance: ${sourceCsql.name}
      password: password
    options:
      dependsOn:
        - ${sourceSqlClientCert}
  sourceCp:
    type: gcp:databasemigrationservice:ConnectionProfile
    name: source_cp
    properties:
      location: us-central1
      connectionProfileId: source-cp
      displayName: source-cp_display
      labels:
        foo: bar
      postgresql:
        host: ${sourceCsql.ipAddresses[0].ipAddress}
        port: 3306
        username: ${sourceSqldbUser.name}
        password: ${sourceSqldbUser.password}
        ssl:
          clientKey: ${sourceSqlClientCert.privateKey}
          clientCertificate: ${sourceSqlClientCert.cert}
          caCertificate: ${sourceSqlClientCert.serverCaCert}
          type: SERVER_CLIENT
        cloudSqlId: source-csql
    options:
      dependsOn:
        - ${sourceSqldbUser}
  destinationCsql:
    type: gcp:sql:DatabaseInstance
    name: destination_csql
    properties:
      name: destination-csql
      databaseVersion: POSTGRES_15
      settings:
        tier: db-custom-2-13312
        deletionProtectionEnabled: false
      deletionProtection: false
  destinationCp:
    type: gcp:databasemigrationservice:ConnectionProfile
    name: destination_cp
    properties:
      location: us-central1
      connectionProfileId: destination-cp
      displayName: destination-cp_display
      labels:
        foo: bar
      postgresql:
        cloudSqlId: destination-csql
    options:
      dependsOn:
        - ${destinationCsql}
  psqltopsql:
    type: gcp:databasemigrationservice:MigrationJob
    properties:
      location: us-central1
      migrationJobId: my-migrationid
      displayName: my-migrationid_display
      labels:
        foo: bar
      staticIpConnectivity: {}
      source: ${sourceCp.name}
      destination: ${destinationCp.name}
      type: CONTINUOUS
variables:
  project:
    fn::invoke:
      function: gcp:organizations:getProject
      arguments: {}

The staticIpConnectivity property (set to an empty object) tells the migration service to use the destination database’s public IP for connectivity. The source database must allow incoming connections from this IP address. This approach works when VPC peering isn’t feasible but requires firewall rules on the source side.

Migrate PostgreSQL to AlloyDB with static IP

AlloyDB provides a PostgreSQL-compatible managed database with enhanced performance. Migrations from Cloud SQL PostgreSQL to AlloyDB use the same connectivity patterns as Cloud SQL-to-Cloud SQL migrations.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const project = gcp.organizations.getProject({});
const sourceCsql = new gcp.sql.DatabaseInstance("source_csql", {
    name: "source-csql",
    databaseVersion: "POSTGRES_15",
    settings: {
        tier: "db-custom-2-13312",
        deletionProtectionEnabled: false,
    },
    deletionProtection: false,
});
const sourceSqlClientCert = new gcp.sql.SslCert("source_sql_client_cert", {
    commonName: "cert",
    instance: sourceCsql.name,
}, {
    dependsOn: [sourceCsql],
});
const sourceSqldbUser = new gcp.sql.User("source_sqldb_user", {
    name: "username",
    instance: sourceCsql.name,
    password: "password",
}, {
    dependsOn: [sourceSqlClientCert],
});
const sourceCp = new gcp.databasemigrationservice.ConnectionProfile("source_cp", {
    location: "us-central1",
    connectionProfileId: "source-cp",
    displayName: "source-cp_display",
    labels: {
        foo: "bar",
    },
    postgresql: {
        host: sourceCsql.ipAddresses.apply(ipAddresses => ipAddresses[0].ipAddress),
        port: 3306,
        username: sourceSqldbUser.name,
        password: sourceSqldbUser.password,
        ssl: {
            clientKey: sourceSqlClientCert.privateKey,
            clientCertificate: sourceSqlClientCert.cert,
            caCertificate: sourceSqlClientCert.serverCaCert,
            type: "SERVER_CLIENT",
        },
        cloudSqlId: "source-csql",
    },
}, {
    dependsOn: [sourceSqldbUser],
});
const _default = new gcp.compute.Network("default", {name: "destination-alloydb"});
const destinationAlloydb = new gcp.alloydb.Cluster("destination_alloydb", {
    clusterId: "destination-alloydb",
    location: "us-central1",
    networkConfig: {
        network: _default.id,
    },
    databaseVersion: "POSTGRES_15",
    initialUser: {
        user: "destination-alloydb",
        password: "destination-alloydb",
    },
    deletionProtection: false,
});
const privateIpAlloc = new gcp.compute.GlobalAddress("private_ip_alloc", {
    name: "destination-alloydb",
    addressType: "INTERNAL",
    purpose: "VPC_PEERING",
    prefixLength: 16,
    network: _default.id,
});
const vpcConnection = new gcp.servicenetworking.Connection("vpc_connection", {
    network: _default.id,
    service: "servicenetworking.googleapis.com",
    reservedPeeringRanges: [privateIpAlloc.name],
});
const destinationAlloydbPrimary = new gcp.alloydb.Instance("destination_alloydb_primary", {
    cluster: destinationAlloydb.name,
    instanceId: "destination-alloydb-primary",
    instanceType: "PRIMARY",
}, {
    dependsOn: [vpcConnection],
});
const destinationCp = new gcp.databasemigrationservice.ConnectionProfile("destination_cp", {
    location: "us-central1",
    connectionProfileId: "destination-cp",
    displayName: "destination-cp_display",
    labels: {
        foo: "bar",
    },
    postgresql: {
        alloydbClusterId: "destination-alloydb",
    },
}, {
    dependsOn: [
        destinationAlloydb,
        destinationAlloydbPrimary,
    ],
});
const psqltoalloydb = new gcp.databasemigrationservice.MigrationJob("psqltoalloydb", {
    location: "us-central1",
    migrationJobId: "my-migrationid",
    displayName: "my-migrationid_display",
    labels: {
        foo: "bar",
    },
    staticIpConnectivity: {},
    source: sourceCp.name,
    destination: destinationCp.name,
    type: "CONTINUOUS",
});
import pulumi
import pulumi_gcp as gcp

project = gcp.organizations.get_project()
source_csql = gcp.sql.DatabaseInstance("source_csql",
    name="source-csql",
    database_version="POSTGRES_15",
    settings={
        "tier": "db-custom-2-13312",
        "deletion_protection_enabled": False,
    },
    deletion_protection=False)
source_sql_client_cert = gcp.sql.SslCert("source_sql_client_cert",
    common_name="cert",
    instance=source_csql.name,
    opts = pulumi.ResourceOptions(depends_on=[source_csql]))
source_sqldb_user = gcp.sql.User("source_sqldb_user",
    name="username",
    instance=source_csql.name,
    password="password",
    opts = pulumi.ResourceOptions(depends_on=[source_sql_client_cert]))
source_cp = gcp.databasemigrationservice.ConnectionProfile("source_cp",
    location="us-central1",
    connection_profile_id="source-cp",
    display_name="source-cp_display",
    labels={
        "foo": "bar",
    },
    postgresql={
        "host": source_csql.ip_addresses[0].ip_address,
        "port": 3306,
        "username": source_sqldb_user.name,
        "password": source_sqldb_user.password,
        "ssl": {
            "client_key": source_sql_client_cert.private_key,
            "client_certificate": source_sql_client_cert.cert,
            "ca_certificate": source_sql_client_cert.server_ca_cert,
            "type": "SERVER_CLIENT",
        },
        "cloud_sql_id": "source-csql",
    },
    opts = pulumi.ResourceOptions(depends_on=[source_sqldb_user]))
default = gcp.compute.Network("default", name="destination-alloydb")
destination_alloydb = gcp.alloydb.Cluster("destination_alloydb",
    cluster_id="destination-alloydb",
    location="us-central1",
    network_config={
        "network": default.id,
    },
    database_version="POSTGRES_15",
    initial_user={
        "user": "destination-alloydb",
        "password": "destination-alloydb",
    },
    deletion_protection=False)
private_ip_alloc = gcp.compute.GlobalAddress("private_ip_alloc",
    name="destination-alloydb",
    address_type="INTERNAL",
    purpose="VPC_PEERING",
    prefix_length=16,
    network=default.id)
vpc_connection = gcp.servicenetworking.Connection("vpc_connection",
    network=default.id,
    service="servicenetworking.googleapis.com",
    reserved_peering_ranges=[private_ip_alloc.name])
destination_alloydb_primary = gcp.alloydb.Instance("destination_alloydb_primary",
    cluster=destination_alloydb.name,
    instance_id="destination-alloydb-primary",
    instance_type="PRIMARY",
    opts = pulumi.ResourceOptions(depends_on=[vpc_connection]))
destination_cp = gcp.databasemigrationservice.ConnectionProfile("destination_cp",
    location="us-central1",
    connection_profile_id="destination-cp",
    display_name="destination-cp_display",
    labels={
        "foo": "bar",
    },
    postgresql={
        "alloydb_cluster_id": "destination-alloydb",
    },
    opts = pulumi.ResourceOptions(depends_on=[
            destination_alloydb,
            destination_alloydb_primary,
        ]))
psqltoalloydb = gcp.databasemigrationservice.MigrationJob("psqltoalloydb",
    location="us-central1",
    migration_job_id="my-migrationid",
    display_name="my-migrationid_display",
    labels={
        "foo": "bar",
    },
    static_ip_connectivity={},
    source=source_cp.name,
    destination=destination_cp.name,
    type="CONTINUOUS")
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/alloydb"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/databasemigrationservice"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/servicenetworking"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/sql"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := organizations.LookupProject(ctx, &organizations.LookupProjectArgs{}, nil)
		if err != nil {
			return err
		}
		sourceCsql, err := sql.NewDatabaseInstance(ctx, "source_csql", &sql.DatabaseInstanceArgs{
			Name:            pulumi.String("source-csql"),
			DatabaseVersion: pulumi.String("POSTGRES_15"),
			Settings: &sql.DatabaseInstanceSettingsArgs{
				Tier:                      pulumi.String("db-custom-2-13312"),
				DeletionProtectionEnabled: pulumi.Bool(false),
			},
			DeletionProtection: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		sourceSqlClientCert, err := sql.NewSslCert(ctx, "source_sql_client_cert", &sql.SslCertArgs{
			CommonName: pulumi.String("cert"),
			Instance:   sourceCsql.Name,
		}, pulumi.DependsOn([]pulumi.Resource{
			sourceCsql,
		}))
		if err != nil {
			return err
		}
		sourceSqldbUser, err := sql.NewUser(ctx, "source_sqldb_user", &sql.UserArgs{
			Name:     pulumi.String("username"),
			Instance: sourceCsql.Name,
			Password: pulumi.String("password"),
		}, pulumi.DependsOn([]pulumi.Resource{
			sourceSqlClientCert,
		}))
		if err != nil {
			return err
		}
		sourceCp, err := databasemigrationservice.NewConnectionProfile(ctx, "source_cp", &databasemigrationservice.ConnectionProfileArgs{
			Location:            pulumi.String("us-central1"),
			ConnectionProfileId: pulumi.String("source-cp"),
			DisplayName:         pulumi.String("source-cp_display"),
			Labels: pulumi.StringMap{
				"foo": pulumi.String("bar"),
			},
			Postgresql: &databasemigrationservice.ConnectionProfilePostgresqlArgs{
				Host: sourceCsql.IpAddresses.ApplyT(func(ipAddresses []sql.DatabaseInstanceIpAddress) (*string, error) {
					return &ipAddresses[0].IpAddress, nil
				}).(pulumi.StringPtrOutput),
				Port:     pulumi.Int(3306),
				Username: sourceSqldbUser.Name,
				Password: sourceSqldbUser.Password,
				Ssl: &databasemigrationservice.ConnectionProfilePostgresqlSslArgs{
					ClientKey:         sourceSqlClientCert.PrivateKey,
					ClientCertificate: sourceSqlClientCert.Cert,
					CaCertificate:     sourceSqlClientCert.ServerCaCert,
					Type:              pulumi.String("SERVER_CLIENT"),
				},
				CloudSqlId: pulumi.String("source-csql"),
			},
		}, pulumi.DependsOn([]pulumi.Resource{
			sourceSqldbUser,
		}))
		if err != nil {
			return err
		}
		_default, err := compute.NewNetwork(ctx, "default", &compute.NetworkArgs{
			Name: pulumi.String("destination-alloydb"),
		})
		if err != nil {
			return err
		}
		destinationAlloydb, err := alloydb.NewCluster(ctx, "destination_alloydb", &alloydb.ClusterArgs{
			ClusterId: pulumi.String("destination-alloydb"),
			Location:  pulumi.String("us-central1"),
			NetworkConfig: &alloydb.ClusterNetworkConfigArgs{
				Network: _default.ID(),
			},
			DatabaseVersion: pulumi.String("POSTGRES_15"),
			InitialUser: &alloydb.ClusterInitialUserArgs{
				User:     pulumi.String("destination-alloydb"),
				Password: pulumi.String("destination-alloydb"),
			},
			DeletionProtection: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		privateIpAlloc, err := compute.NewGlobalAddress(ctx, "private_ip_alloc", &compute.GlobalAddressArgs{
			Name:         pulumi.String("destination-alloydb"),
			AddressType:  pulumi.String("INTERNAL"),
			Purpose:      pulumi.String("VPC_PEERING"),
			PrefixLength: pulumi.Int(16),
			Network:      _default.ID(),
		})
		if err != nil {
			return err
		}
		vpcConnection, err := servicenetworking.NewConnection(ctx, "vpc_connection", &servicenetworking.ConnectionArgs{
			Network: _default.ID(),
			Service: pulumi.String("servicenetworking.googleapis.com"),
			ReservedPeeringRanges: pulumi.StringArray{
				privateIpAlloc.Name,
			},
		})
		if err != nil {
			return err
		}
		destinationAlloydbPrimary, err := alloydb.NewInstance(ctx, "destination_alloydb_primary", &alloydb.InstanceArgs{
			Cluster:      destinationAlloydb.Name,
			InstanceId:   pulumi.String("destination-alloydb-primary"),
			InstanceType: pulumi.String("PRIMARY"),
		}, pulumi.DependsOn([]pulumi.Resource{
			vpcConnection,
		}))
		if err != nil {
			return err
		}
		destinationCp, err := databasemigrationservice.NewConnectionProfile(ctx, "destination_cp", &databasemigrationservice.ConnectionProfileArgs{
			Location:            pulumi.String("us-central1"),
			ConnectionProfileId: pulumi.String("destination-cp"),
			DisplayName:         pulumi.String("destination-cp_display"),
			Labels: pulumi.StringMap{
				"foo": pulumi.String("bar"),
			},
			Postgresql: &databasemigrationservice.ConnectionProfilePostgresqlArgs{
				AlloydbClusterId: pulumi.String("destination-alloydb"),
			},
		}, pulumi.DependsOn([]pulumi.Resource{
			destinationAlloydb,
			destinationAlloydbPrimary,
		}))
		if err != nil {
			return err
		}
		_, err = databasemigrationservice.NewMigrationJob(ctx, "psqltoalloydb", &databasemigrationservice.MigrationJobArgs{
			Location:       pulumi.String("us-central1"),
			MigrationJobId: pulumi.String("my-migrationid"),
			DisplayName:    pulumi.String("my-migrationid_display"),
			Labels: pulumi.StringMap{
				"foo": pulumi.String("bar"),
			},
			StaticIpConnectivity: &databasemigrationservice.MigrationJobStaticIpConnectivityArgs{},
			Source:               sourceCp.Name,
			Destination:          destinationCp.Name,
			Type:                 pulumi.String("CONTINUOUS"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var project = Gcp.Organizations.GetProject.Invoke();

    var sourceCsql = new Gcp.Sql.DatabaseInstance("source_csql", new()
    {
        Name = "source-csql",
        DatabaseVersion = "POSTGRES_15",
        Settings = new Gcp.Sql.Inputs.DatabaseInstanceSettingsArgs
        {
            Tier = "db-custom-2-13312",
            DeletionProtectionEnabled = false,
        },
        DeletionProtection = false,
    });

    var sourceSqlClientCert = new Gcp.Sql.SslCert("source_sql_client_cert", new()
    {
        CommonName = "cert",
        Instance = sourceCsql.Name,
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            sourceCsql,
        },
    });

    var sourceSqldbUser = new Gcp.Sql.User("source_sqldb_user", new()
    {
        Name = "username",
        Instance = sourceCsql.Name,
        Password = "password",
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            sourceSqlClientCert,
        },
    });

    var sourceCp = new Gcp.DatabaseMigrationService.ConnectionProfile("source_cp", new()
    {
        Location = "us-central1",
        ConnectionProfileId = "source-cp",
        DisplayName = "source-cp_display",
        Labels = 
        {
            { "foo", "bar" },
        },
        Postgresql = new Gcp.DatabaseMigrationService.Inputs.ConnectionProfilePostgresqlArgs
        {
            Host = sourceCsql.IpAddresses.Apply(ipAddresses => ipAddresses[0].IpAddress),
            Port = 3306,
            Username = sourceSqldbUser.Name,
            Password = sourceSqldbUser.Password,
            Ssl = new Gcp.DatabaseMigrationService.Inputs.ConnectionProfilePostgresqlSslArgs
            {
                ClientKey = sourceSqlClientCert.PrivateKey,
                ClientCertificate = sourceSqlClientCert.Cert,
                CaCertificate = sourceSqlClientCert.ServerCaCert,
                Type = "SERVER_CLIENT",
            },
            CloudSqlId = "source-csql",
        },
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            sourceSqldbUser,
        },
    });

    var @default = new Gcp.Compute.Network("default", new()
    {
        Name = "destination-alloydb",
    });

    var destinationAlloydb = new Gcp.Alloydb.Cluster("destination_alloydb", new()
    {
        ClusterId = "destination-alloydb",
        Location = "us-central1",
        NetworkConfig = new Gcp.Alloydb.Inputs.ClusterNetworkConfigArgs
        {
            Network = @default.Id,
        },
        DatabaseVersion = "POSTGRES_15",
        InitialUser = new Gcp.Alloydb.Inputs.ClusterInitialUserArgs
        {
            User = "destination-alloydb",
            Password = "destination-alloydb",
        },
        DeletionProtection = false,
    });

    var privateIpAlloc = new Gcp.Compute.GlobalAddress("private_ip_alloc", new()
    {
        Name = "destination-alloydb",
        AddressType = "INTERNAL",
        Purpose = "VPC_PEERING",
        PrefixLength = 16,
        Network = @default.Id,
    });

    var vpcConnection = new Gcp.ServiceNetworking.Connection("vpc_connection", new()
    {
        Network = @default.Id,
        Service = "servicenetworking.googleapis.com",
        ReservedPeeringRanges = new[]
        {
            privateIpAlloc.Name,
        },
    });

    var destinationAlloydbPrimary = new Gcp.Alloydb.Instance("destination_alloydb_primary", new()
    {
        Cluster = destinationAlloydb.Name,
        InstanceId = "destination-alloydb-primary",
        InstanceType = "PRIMARY",
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            vpcConnection,
        },
    });

    var destinationCp = new Gcp.DatabaseMigrationService.ConnectionProfile("destination_cp", new()
    {
        Location = "us-central1",
        ConnectionProfileId = "destination-cp",
        DisplayName = "destination-cp_display",
        Labels = 
        {
            { "foo", "bar" },
        },
        Postgresql = new Gcp.DatabaseMigrationService.Inputs.ConnectionProfilePostgresqlArgs
        {
            AlloydbClusterId = "destination-alloydb",
        },
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            destinationAlloydb,
            destinationAlloydbPrimary,
        },
    });

    var psqltoalloydb = new Gcp.DatabaseMigrationService.MigrationJob("psqltoalloydb", new()
    {
        Location = "us-central1",
        MigrationJobId = "my-migrationid",
        DisplayName = "my-migrationid_display",
        Labels = 
        {
            { "foo", "bar" },
        },
        StaticIpConnectivity = null,
        Source = sourceCp.Name,
        Destination = destinationCp.Name,
        Type = "CONTINUOUS",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.organizations.inputs.GetProjectArgs;
import com.pulumi.gcp.sql.DatabaseInstance;
import com.pulumi.gcp.sql.DatabaseInstanceArgs;
import com.pulumi.gcp.sql.inputs.DatabaseInstanceSettingsArgs;
import com.pulumi.gcp.sql.SslCert;
import com.pulumi.gcp.sql.SslCertArgs;
import com.pulumi.gcp.sql.User;
import com.pulumi.gcp.sql.UserArgs;
import com.pulumi.gcp.databasemigrationservice.ConnectionProfile;
import com.pulumi.gcp.databasemigrationservice.ConnectionProfileArgs;
import com.pulumi.gcp.databasemigrationservice.inputs.ConnectionProfilePostgresqlArgs;
import com.pulumi.gcp.databasemigrationservice.inputs.ConnectionProfilePostgresqlSslArgs;
import com.pulumi.gcp.compute.Network;
import com.pulumi.gcp.compute.NetworkArgs;
import com.pulumi.gcp.alloydb.Cluster;
import com.pulumi.gcp.alloydb.ClusterArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterNetworkConfigArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterInitialUserArgs;
import com.pulumi.gcp.compute.GlobalAddress;
import com.pulumi.gcp.compute.GlobalAddressArgs;
import com.pulumi.gcp.servicenetworking.Connection;
import com.pulumi.gcp.servicenetworking.ConnectionArgs;
import com.pulumi.gcp.alloydb.Instance;
import com.pulumi.gcp.alloydb.InstanceArgs;
import com.pulumi.gcp.databasemigrationservice.MigrationJob;
import com.pulumi.gcp.databasemigrationservice.MigrationJobArgs;
import com.pulumi.gcp.databasemigrationservice.inputs.MigrationJobStaticIpConnectivityArgs;
import com.pulumi.resources.CustomResourceOptions;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        final var project = OrganizationsFunctions.getProject(GetProjectArgs.builder()
            .build());

        var sourceCsql = new DatabaseInstance("sourceCsql", DatabaseInstanceArgs.builder()
            .name("source-csql")
            .databaseVersion("POSTGRES_15")
            .settings(DatabaseInstanceSettingsArgs.builder()
                .tier("db-custom-2-13312")
                .deletionProtectionEnabled(false)
                .build())
            .deletionProtection(false)
            .build());

        var sourceSqlClientCert = new SslCert("sourceSqlClientCert", SslCertArgs.builder()
            .commonName("cert")
            .instance(sourceCsql.name())
            .build(), CustomResourceOptions.builder()
                .dependsOn(sourceCsql)
                .build());

        var sourceSqldbUser = new User("sourceSqldbUser", UserArgs.builder()
            .name("username")
            .instance(sourceCsql.name())
            .password("password")
            .build(), CustomResourceOptions.builder()
                .dependsOn(sourceSqlClientCert)
                .build());

        var sourceCp = new ConnectionProfile("sourceCp", ConnectionProfileArgs.builder()
            .location("us-central1")
            .connectionProfileId("source-cp")
            .displayName("source-cp_display")
            .labels(Map.of("foo", "bar"))
            .postgresql(ConnectionProfilePostgresqlArgs.builder()
                .host(sourceCsql.ipAddresses().applyValue(_ipAddresses -> _ipAddresses[0].ipAddress()))
                .port(3306)
                .username(sourceSqldbUser.name())
                .password(sourceSqldbUser.password())
                .ssl(ConnectionProfilePostgresqlSslArgs.builder()
                    .clientKey(sourceSqlClientCert.privateKey())
                    .clientCertificate(sourceSqlClientCert.cert())
                    .caCertificate(sourceSqlClientCert.serverCaCert())
                    .type("SERVER_CLIENT")
                    .build())
                .cloudSqlId("source-csql")
                .build())
            .build(), CustomResourceOptions.builder()
                .dependsOn(sourceSqldbUser)
                .build());

        var default_ = new Network("default", NetworkArgs.builder()
            .name("destination-alloydb")
            .build());

        var destinationAlloydb = new Cluster("destinationAlloydb", ClusterArgs.builder()
            .clusterId("destination-alloydb")
            .location("us-central1")
            .networkConfig(ClusterNetworkConfigArgs.builder()
                .network(default_.id())
                .build())
            .databaseVersion("POSTGRES_15")
            .initialUser(ClusterInitialUserArgs.builder()
                .user("destination-alloydb")
                .password("destination-alloydb")
                .build())
            .deletionProtection(false)
            .build());

        var privateIpAlloc = new GlobalAddress("privateIpAlloc", GlobalAddressArgs.builder()
            .name("destination-alloydb")
            .addressType("INTERNAL")
            .purpose("VPC_PEERING")
            .prefixLength(16)
            .network(default_.id())
            .build());

        var vpcConnection = new Connection("vpcConnection", ConnectionArgs.builder()
            .network(default_.id())
            .service("servicenetworking.googleapis.com")
            .reservedPeeringRanges(privateIpAlloc.name())
            .build());

        var destinationAlloydbPrimary = new Instance("destinationAlloydbPrimary", InstanceArgs.builder()
            .cluster(destinationAlloydb.name())
            .instanceId("destination-alloydb-primary")
            .instanceType("PRIMARY")
            .build(), CustomResourceOptions.builder()
                .dependsOn(vpcConnection)
                .build());

        var destinationCp = new ConnectionProfile("destinationCp", ConnectionProfileArgs.builder()
            .location("us-central1")
            .connectionProfileId("destination-cp")
            .displayName("destination-cp_display")
            .labels(Map.of("foo", "bar"))
            .postgresql(ConnectionProfilePostgresqlArgs.builder()
                .alloydbClusterId("destination-alloydb")
                .build())
            .build(), CustomResourceOptions.builder()
                .dependsOn(                
                    destinationAlloydb,
                    destinationAlloydbPrimary)
                .build());

        var psqltoalloydb = new MigrationJob("psqltoalloydb", MigrationJobArgs.builder()
            .location("us-central1")
            .migrationJobId("my-migrationid")
            .displayName("my-migrationid_display")
            .labels(Map.of("foo", "bar"))
            .staticIpConnectivity(MigrationJobStaticIpConnectivityArgs.builder()
                .build())
            .source(sourceCp.name())
            .destination(destinationCp.name())
            .type("CONTINUOUS")
            .build());

    }
}
resources:
  sourceCsql:
    type: gcp:sql:DatabaseInstance
    name: source_csql
    properties:
      name: source-csql
      databaseVersion: POSTGRES_15
      settings:
        tier: db-custom-2-13312
        deletionProtectionEnabled: false
      deletionProtection: false
  sourceSqlClientCert:
    type: gcp:sql:SslCert
    name: source_sql_client_cert
    properties:
      commonName: cert
      instance: ${sourceCsql.name}
    options:
      dependsOn:
        - ${sourceCsql}
  sourceSqldbUser:
    type: gcp:sql:User
    name: source_sqldb_user
    properties:
      name: username
      instance: ${sourceCsql.name}
      password: password
    options:
      dependsOn:
        - ${sourceSqlClientCert}
  sourceCp:
    type: gcp:databasemigrationservice:ConnectionProfile
    name: source_cp
    properties:
      location: us-central1
      connectionProfileId: source-cp
      displayName: source-cp_display
      labels:
        foo: bar
      postgresql:
        host: ${sourceCsql.ipAddresses[0].ipAddress}
        port: 3306
        username: ${sourceSqldbUser.name}
        password: ${sourceSqldbUser.password}
        ssl:
          clientKey: ${sourceSqlClientCert.privateKey}
          clientCertificate: ${sourceSqlClientCert.cert}
          caCertificate: ${sourceSqlClientCert.serverCaCert}
          type: SERVER_CLIENT
        cloudSqlId: source-csql
    options:
      dependsOn:
        - ${sourceSqldbUser}
  destinationAlloydb:
    type: gcp:alloydb:Cluster
    name: destination_alloydb
    properties:
      clusterId: destination-alloydb
      location: us-central1
      networkConfig:
        network: ${default.id}
      databaseVersion: POSTGRES_15
      initialUser:
        user: destination-alloydb
        password: destination-alloydb
      deletionProtection: false
  destinationAlloydbPrimary:
    type: gcp:alloydb:Instance
    name: destination_alloydb_primary
    properties:
      cluster: ${destinationAlloydb.name}
      instanceId: destination-alloydb-primary
      instanceType: PRIMARY
    options:
      dependsOn:
        - ${vpcConnection}
  privateIpAlloc:
    type: gcp:compute:GlobalAddress
    name: private_ip_alloc
    properties:
      name: destination-alloydb
      addressType: INTERNAL
      purpose: VPC_PEERING
      prefixLength: 16
      network: ${default.id}
  vpcConnection:
    type: gcp:servicenetworking:Connection
    name: vpc_connection
    properties:
      network: ${default.id}
      service: servicenetworking.googleapis.com
      reservedPeeringRanges:
        - ${privateIpAlloc.name}
  default:
    type: gcp:compute:Network
    properties:
      name: destination-alloydb
  destinationCp:
    type: gcp:databasemigrationservice:ConnectionProfile
    name: destination_cp
    properties:
      location: us-central1
      connectionProfileId: destination-cp
      displayName: destination-cp_display
      labels:
        foo: bar
      postgresql:
        alloydbClusterId: destination-alloydb
    options:
      dependsOn:
        - ${destinationAlloydb}
        - ${destinationAlloydbPrimary}
  psqltoalloydb:
    type: gcp:databasemigrationservice:MigrationJob
    properties:
      location: us-central1
      migrationJobId: my-migrationid
      displayName: my-migrationid_display
      labels:
        foo: bar
      staticIpConnectivity: {}
      source: ${sourceCp.name}
      destination: ${destinationCp.name}
      type: CONTINUOUS
variables:
  project:
    fn::invoke:
      function: gcp:organizations:getProject
      arguments: {}

The destination ConnectionProfile references an AlloyDB cluster via alloydbClusterId rather than a Cloud SQL instance. AlloyDB requires VPC peering for its own connectivity (configured via servicenetworking.Connection), but the migration job itself uses staticIpConnectivity to connect from the source. The migration service handles the complexity of routing data through the appropriate network paths.

Beyond these examples

These snippets focus on specific migration job features: MySQL and PostgreSQL migration types, VPC peering and static IP connectivity, and Cloud SQL and AlloyDB destinations. They’re intentionally minimal rather than full migration workflows.

The examples rely on pre-existing infrastructure such as ConnectionProfile resources for source and destination, Cloud SQL instances or AlloyDB clusters, and VPC networks and service networking peering. They focus on configuring the migration job rather than provisioning the surrounding database infrastructure.

To keep things focused, common migration patterns are omitted, including:

  • Reverse SSH connectivity (reverseSshConnectivity)
  • Custom dump paths in Cloud Storage (dumpPath)
  • Dump flags for MySQL migrations (dumpFlags)
  • One-time migration jobs (type: ONE_TIME)

These omissions are intentional: the goal is to illustrate how each migration connectivity method is wired, not provide drop-in database migration modules. See the Database Migration Service MigrationJob resource reference for all available configuration options.

Let's configure GCP Database Migration Jobs

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Configuration & Immutability
What properties can't I change after creating a migration job?
The following properties are immutable: destination, source, type, location, migrationJobId, and project. Plan these values carefully before creation, as changes require recreating the migration job.
What's the difference between ONE_TIME and CONTINUOUS migration types?
ONE_TIME performs a single migration, while CONTINUOUS keeps replicating changes from source to destination. The type property is required and immutable.
Can I use both dumpPath and dumpFlags in my migration job?
No, dumpPath and dumpFlags are mutually exclusive. Use dumpPath for pre-existing dump files in Cloud Storage, or dumpFlags to configure dump behavior.
Dump Configuration
What dump types are supported for MySQL migrations?
MySQL to CloudSQL migrations support LOGICAL or PHYSICAL dump types via the dumpType property. This setting only applies to MySQL migrations.
How do I configure dump parallelism for better performance?
Use the performanceConfig property with dumpParallelLevel set to MAX (as shown in the MySQL to MySQL example) to enable parallel dump operations.
Networking & Connectivity
What connectivity options are available for migration jobs?

You have three options:

  1. VPC Peering - Use vpcPeeringConnectivity with a VPC network ID
  2. Static IP - Use staticIpConnectivity (empty object) for public IP connections
  3. Reverse SSH - Use reverseSshConnectivity for SSH tunnel connections
How do I migrate from Postgres to AlloyDB?
Create a destination ConnectionProfile with postgresql.alloydbClusterId pointing to your AlloyDB cluster, then use staticIpConnectivity for the migration job.
Resource Management
Why don't I see all labels on my migration job?
The labels field is non-authoritative and only manages labels in your configuration. Use effectiveLabels to see all labels present on the resource, including those set by other clients.

Using a different cloud?

Explore database guides for other cloud providers: