diff --git a/Dockerfile.local b/Dockerfile.local new file mode 100644 index 000000000..1c66de73e --- /dev/null +++ b/Dockerfile.local @@ -0,0 +1,8 @@ +FROM golang:1.17-buster@sha256:3e663ba6af8281b04975b0a34a14d538cdd7d284213f83f05aaf596b80a8c725 as builder + +COPY . /src +WORKDIR /src +RUN CGO_ENABLED=0 make dist + +FROM scratch AS exporter +COPY --from=builder /src/bin/ / \ No newline at end of file diff --git a/README.md b/README.md index e4374a741..ee40862c2 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,10 @@ Options: applies missing (out-of-order) migrations -certfile string file path to root CA's certificates in pem format (only support on mysql) + -sslcert string + file path to SSL certificates in pem format (only support on mysql) + -sslkey string + file path to SSL key in pem format (only support on mysql) -dir string directory with migration files (default ".") -h print help @@ -239,7 +243,7 @@ language plpgsql; Go 1.16 introduced new feature: [compile-time embedding](https://pkg.go.dev/embed/) files into binary and corresponding [filesystem abstraction](https://pkg.go.dev/io/fs/). -This feature can be used only for applying existing migrations. Modifying operations such as +This feature can be used only for applying existing migrations. Modifying operations such as `fix` and `create` will continue to operate on OS filesystem even if using embedded files. This is expected behaviour because `io/fs` interfaces allows read-only access. @@ -250,7 +254,7 @@ package main import ( "database/sql" "embed" - + "github.com/pressly/goose/v3" ) @@ -258,8 +262,8 @@ import ( var embedMigrations embed.FS func main() { - var db *sql.DB - // setup database + var db *sql.DB + // setup database goose.SetBaseFS(embedMigrations) @@ -312,6 +316,14 @@ func Down(tx *sql.Tx) error { } ``` +# Development + +This can be used to build local `goose` binaries without having the latest Go version installed locally. + +```bash +DOCKER_BUILDKIT=1 docker build -f Dockerfile.local --output bin . +``` + # Hybrid Versioning Please, read the [versioning problem](https://github.com/pressly/goose/issues/63#issuecomment-428681694) first. diff --git a/cmd/goose/driver_mysql.go b/cmd/goose/driver_mysql.go index 1b287b800..8d93cf736 100644 --- a/cmd/goose/driver_mysql.go +++ b/cmd/goose/driver_mysql.go @@ -19,11 +19,11 @@ import ( // the parameter `parseTime` set to true. This allows internal goose logic // to assume that DATETIME/DATE/TIMESTAMP can be scanned into the time.Time // type. -func normalizeDBString(driver string, str string, certfile string) string { +func normalizeDBString(driver string, str string, certfile string, sslcert string, sslkey string) string { if driver == "mysql" { var isTLS = certfile != "" if isTLS { - if err := registerTLSConfig(certfile); err != nil { + if err := registerTLSConfig(certfile, sslcert, sslkey); err != nil { log.Fatalf("goose run: %v", err) } } @@ -55,7 +55,7 @@ func normalizeMySQLDSN(dsn string, tls bool) (string, error) { return config.FormatDSN(), nil } -func registerTLSConfig(pemfile string) error { +func registerTLSConfig(pemfile string, sslcert string, sslkey string) error { rootCertPool := x509.NewCertPool() pem, err := ioutil.ReadFile(pemfile) if err != nil { @@ -64,7 +64,16 @@ func registerTLSConfig(pemfile string) error { if ok := rootCertPool.AppendCertsFromPEM(pem); !ok { return fmt.Errorf("failed to append PEM: %q", pemfile) } - return mysql.RegisterTLSConfig(tlsConfigKey, &tls.Config{ + + tlsConfig := &tls.Config{ RootCAs: rootCertPool, - }) + } + if sslcert != "" && sslkey != "" { + cert, err := tls.LoadX509KeyPair(sslcert, sslkey) + if err != nil { + return fmt.Errorf("failed to load x509 keypair: %w", err) + } + tlsConfig.Certificates = append(tlsConfig.Certificates, cert) + } + return mysql.RegisterTLSConfig(tlsConfigKey, tlsConfig) } diff --git a/cmd/goose/main.go b/cmd/goose/main.go index 7ae42bc91..4790049c4 100644 --- a/cmd/goose/main.go +++ b/cmd/goose/main.go @@ -20,6 +20,8 @@ var ( certfile = flags.String("certfile", "", "file path to root CA's certificates in pem format (only support on mysql)") sequential = flags.Bool("s", false, "use sequential numbering for new migrations") allowMissing = flags.Bool("allow-missing", false, "applies missing (out-of-order) migrations") + sslcert = flags.String("ssl-cert", "", "file path to SSL certificates in pem format (only support on mysql)") + sslkey = flags.String("ssl-key", "", "file path to SSL key in pem format (only support on mysql)") ) var ( @@ -78,7 +80,7 @@ func main() { if driver == "sqlite3" { driver = "sqlite" } - db, err := goose.OpenDBWithDriver(driver, normalizeDBString(driver, dbstring, *certfile)) + db, err := goose.OpenDBWithDriver(driver, normalizeDBString(driver, dbstring, *certfile, *sslcert, *sslkey)) if err != nil { log.Fatalf("-dbstring=%q: %v\n", dbstring, err) }