squish
squish

Reputation: 1116

How can I run migrations, using go-migrate, inside cloud run against a postgres cloud sql instance?

I've been stuck this issue for the past few days. Here is my database that connects to the DB instance and attempts to run migrations against it:

func connectToDb() (*pgxpool.Pool, error) {
    appConfig := utils.GetConfig()
    l := utils.GetLogger()

    // Configure the driver to connect to the database
    dsn := fmt.Sprintf("user=%s password=%s dbname=%s sslmode=disable", appConfig.DatabaseUser, appConfig.DatabasePassword, appConfig.DatabaseName)
    config, err := pgxpool.ParseConfig(dsn)
    if err != nil {
        l.Err(err).Msg("Failed to parse config")
        return nil, err
    }

    // Create a new dialer with any options
    d, err := cloudsqlconn.NewDialer(context.Background())
    if err != nil {
        l.Err(err).Msg("Failed to create dialer")
        return nil, err
    }

    // Tell the driver to use the Cloud SQL Go Connector to create connections
    config.ConnConfig.DialFunc = func(ctx context.Context, _ string, instance string) (net.Conn, error) {
        return d.Dial(ctx, appConfig.DbInstanceConnectionName)
    }

    // Interact with the driver directly as you normally would
    pool, err := pgxpool.NewWithConfig(context.Background(), config)
    if err != nil {
        l.Err(err).Msg("Failed to connect to database")
        return nil, err
    }

    l.Info().Msgf("Connected to database")

    l.Info().Msgf("Running migrations...")
    // ########## This does not work ##########
    m, err := migrate.New(
        "file:///app/db/postgres/migration",
        fmt.Sprintf("user=%s password=%s database=%s host=%s",
            appConfig.DatabaseUser,
            appConfig.DatabasePassword,
            appConfig.DatabaseName,
            "/cloudsql/"+appConfig.DbInstanceConnectionName,
        ), 
    )

    if err != nil {
        l.Err(err).Msg("Failed to create migration")
        return nil, err
    }

    err = m.Up()
    if err != nil && err != migrate.ErrNoChange {
        l.Err(err).Msg("Failed to run migrations")
        return nil, err
    }

    l.Info().Msg("Migrations complete")

    return pool, nil
}

I have ensured Cloud Run has the correct permissions and followed Google's example code - https://github.com/GoogleCloudPlatform/cloud-sql-go-connector?tab=readme-ov-file#using-the-dialer-with-pgx

It works, I believe I am connected, I cannot seem to pass this connection to go-migrate.

The error In cloud logs are:

90m2024-07-07T21:32:21ZFailed to create migrationerror="no scheme"

Edit 1: In response to Brits comment, I have now added the following:

db := stdlib.OpenDBFromPool(pool)

driver, err := postgres.WithInstance(db, &postgres.Config{})

if err != nil {
    l.Err(err).Msg("Failed to create driver")
    return nil, err
}

m, err := migrate.NewWithDatabaseInstance(
    "file:///app/db/postgres/migration",
    appConfig.DatabaseName,
    driver,
)

This is error I get in cloud run: 2024-07-08T08:03:37Z ERR error pinging database error="failed to connect to user=dev_db_user database=myapp: /tmp/.s.PGSQL.5432 (/tmp): failed SASL auth: FATAL: password authentication failed for user \"dev_db_user\" (SQLSTATE 28P01)"\

I can confirm I am using the correct password and the environment variables are there. I have tried hard coding the values in, rather than using environment variables and it still fails.

Upvotes: 2

Views: 48

Answers (0)

Related Questions