Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions cmd/apply/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ var (
applyUser string
applyPassword string
applySchema string
applySSLMode string
applyFile string
applyPlan string
applyAutoApprove bool
Expand All @@ -50,6 +51,7 @@ func init() {
ApplyCmd.Flags().StringVar(&applyUser, "user", "", "Database user name (required) (env: PGUSER)")
ApplyCmd.Flags().StringVar(&applyPassword, "password", "", "Database password (optional, can also use PGPASSWORD env var)")
ApplyCmd.Flags().StringVar(&applySchema, "schema", "public", "Schema name")
ApplyCmd.Flags().StringVar(&applySSLMode, "sslmode", "prefer", "SSL mode (disable, allow, prefer, require, verify-ca, verify-full) (env: PGSSLMODE)")

// Desired state schema file flag
ApplyCmd.Flags().StringVar(&applyFile, "file", "", "Path to desired state SQL schema file")
Expand Down Expand Up @@ -82,6 +84,14 @@ func RunApply(cmd *cobra.Command, args []string) error {
}
}

// Derive final sslmode: use flag if provided, otherwise check environment variable
finalSSLMode := applySSLMode
if cmd == nil || !cmd.Flags().Changed("sslmode") {
if envSSLMode := os.Getenv("PGSSLMODE"); envSSLMode != "" {
finalSSLMode = envSSLMode
}
}

var migrationPlan *plan.Plan
var err error

Expand Down Expand Up @@ -117,6 +127,7 @@ func RunApply(cmd *cobra.Command, args []string) error {
User: applyUser,
Password: finalPassword,
Schema: applySchema,
SSLMode: finalSSLMode,
File: applyFile,
ApplicationName: applyApplicationName,
}
Expand All @@ -130,7 +141,7 @@ func RunApply(cmd *cobra.Command, args []string) error {

// Validate schema fingerprint if plan has one
if migrationPlan.SourceFingerprint != nil {
err := validateSchemaFingerprint(migrationPlan, applyHost, applyPort, applyDB, applyUser, finalPassword, applySchema, applyApplicationName)
err := validateSchemaFingerprint(migrationPlan, applyHost, applyPort, applyDB, applyUser, finalPassword, applySchema, finalSSLMode, applyApplicationName)
if err != nil {
return err
}
Expand Down Expand Up @@ -171,7 +182,7 @@ func RunApply(cmd *cobra.Command, args []string) error {
Database: applyDB,
User: applyUser,
Password: finalPassword,
SSLMode: "prefer",
SSLMode: finalSSLMode,
ApplicationName: applyApplicationName,
}

Expand Down Expand Up @@ -225,9 +236,9 @@ func RunApply(cmd *cobra.Command, args []string) error {
}

// validateSchemaFingerprint validates that the current database schema matches the expected fingerprint
func validateSchemaFingerprint(migrationPlan *plan.Plan, host string, port int, db, user, password, schema, applicationName string) error {
func validateSchemaFingerprint(migrationPlan *plan.Plan, host string, port int, db, user, password, schema, sslmode, applicationName string) error {
// Get current state from target database
currentStateIR, err := util.GetIRFromDatabase(host, port, db, user, password, schema, applicationName)
currentStateIR, err := util.GetIRFromDatabaseWithSSLMode(host, port, db, user, password, schema, sslmode, applicationName)
if err != nil {
return fmt.Errorf("failed to get current database state for fingerprint validation: %w", err)
}
Expand Down
12 changes: 11 additions & 1 deletion cmd/dump/dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ var (
user string
password string
schema string
sslmode string
multiFile bool
file string
)
Expand All @@ -40,6 +41,7 @@ func init() {
DumpCmd.Flags().StringVar(&user, "user", "", "Database user name (required) (env: PGUSER)")
DumpCmd.Flags().StringVar(&password, "password", "", "Database password (optional, can also use PGPASSWORD env var)")
DumpCmd.Flags().StringVar(&schema, "schema", "public", "Schema name to dump (default: public)")
DumpCmd.Flags().StringVar(&sslmode, "sslmode", "prefer", "SSL mode (disable, allow, prefer, require, verify-ca, verify-full) (env: PGSSLMODE)")
DumpCmd.Flags().BoolVar(&multiFile, "multi-file", false, "Output schema to multiple files organized by object type")
DumpCmd.Flags().StringVar(&file, "file", "", "Output file path (required when --multi-file is used)")
}
Expand All @@ -60,14 +62,22 @@ func runDump(cmd *cobra.Command, args []string) error {
}
}

// Derive final sslmode: use flag if provided, otherwise check environment variable
finalSSLMode := sslmode
if cmd == nil || !cmd.Flags().Changed("sslmode") {
if envSSLMode := os.Getenv("PGSSLMODE"); envSSLMode != "" {
finalSSLMode = envSSLMode
}
}

// Build database connection
config := &util.ConnectionConfig{
Host: host,
Port: port,
Database: db,
User: user,
Password: finalPassword,
SSLMode: "prefer",
SSLMode: finalSSLMode,
ApplicationName: "pgschema",
}

Expand Down
15 changes: 14 additions & 1 deletion cmd/plan/plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ var (
planUser string
planPassword string
planSchema string
planSSLMode string
planFile string
outputHuman string
outputJSON string
Expand All @@ -46,6 +47,7 @@ func init() {
PlanCmd.Flags().StringVar(&planUser, "user", "", "Database user name (required) (env: PGUSER)")
PlanCmd.Flags().StringVar(&planPassword, "password", "", "Database password (optional, can also use PGPASSWORD env var)")
PlanCmd.Flags().StringVar(&planSchema, "schema", "public", "Schema name")
PlanCmd.Flags().StringVar(&planSSLMode, "sslmode", "prefer", "SSL mode (disable, allow, prefer, require, verify-ca, verify-full) (env: PGSSLMODE)")

// Desired state schema file flag
PlanCmd.Flags().StringVar(&planFile, "file", "", "Path to desired state SQL schema file (required)")
Expand All @@ -68,6 +70,14 @@ func runPlan(cmd *cobra.Command, args []string) error {
}
}

// Derive final sslmode: use flag if provided, otherwise check environment variable
finalSSLMode := planSSLMode
if cmd == nil || !cmd.Flags().Changed("sslmode") {
if envSSLMode := os.Getenv("PGSSLMODE"); envSSLMode != "" {
finalSSLMode = envSSLMode
}
}

// Create plan configuration
config := &PlanConfig{
Host: planHost,
Expand All @@ -76,6 +86,7 @@ func runPlan(cmd *cobra.Command, args []string) error {
User: planUser,
Password: finalPassword,
Schema: planSchema,
SSLMode: finalSSLMode,
File: planFile,
ApplicationName: "pgschema",
}
Expand Down Expand Up @@ -110,6 +121,7 @@ type PlanConfig struct {
User string
Password string
Schema string
SSLMode string
File string
ApplicationName string
}
Expand All @@ -130,7 +142,7 @@ func GeneratePlan(config *PlanConfig) (*plan.Plan, error) {
}

// Get current state from target database
currentStateIR, err := util.GetIRFromDatabaseWithIgnoreConfig(config.Host, config.Port, config.DB, config.User, config.Password, config.Schema, config.ApplicationName, ignoreConfig)
currentStateIR, err := util.GetIRFromDatabaseWithIgnoreConfigAndSSLMode(config.Host, config.Port, config.DB, config.User, config.Password, config.Schema, config.SSLMode, config.ApplicationName, ignoreConfig)
if err != nil {
return nil, fmt.Errorf("failed to get current state from database: %w", err)
}
Expand Down Expand Up @@ -249,6 +261,7 @@ func ResetFlags() {
planUser = ""
planPassword = ""
planSchema = "public"
planSSLMode = "prefer"
planFile = ""
outputHuman = ""
outputJSON = ""
Expand Down
16 changes: 14 additions & 2 deletions cmd/util/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,21 @@ func buildDSN(config *ConnectionConfig) string {
}

// GetIRFromDatabase connects to a database and extracts schema using the IR system
// Uses default SSL mode "prefer"
func GetIRFromDatabase(host string, port int, db, user, password, schemaName, applicationName string) (*ir.IR, error) {
return GetIRFromDatabaseWithSSLMode(host, port, db, user, password, schemaName, "prefer", applicationName)
}

// GetIRFromDatabaseWithSSLMode connects to a database and extracts schema using the IR system with custom SSL mode
func GetIRFromDatabaseWithSSLMode(host string, port int, db, user, password, schemaName, sslmode, applicationName string) (*ir.IR, error) {
// Build database connection
config := &ConnectionConfig{
Host: host,
Port: port,
Database: db,
User: user,
Password: password,
SSLMode: "prefer",
SSLMode: sslmode,
ApplicationName: applicationName,
}

Expand Down Expand Up @@ -116,15 +122,21 @@ func GetIRFromDatabase(host string, port int, db, user, password, schemaName, ap
}

// GetIRFromDatabaseWithIgnoreConfig gets the IR from a database with ignore configuration
// Uses default SSL mode "prefer"
func GetIRFromDatabaseWithIgnoreConfig(host string, port int, db, user, password, schemaName, applicationName string, ignoreConfig *ir.IgnoreConfig) (*ir.IR, error) {
return GetIRFromDatabaseWithIgnoreConfigAndSSLMode(host, port, db, user, password, schemaName, "prefer", applicationName, ignoreConfig)
}

// GetIRFromDatabaseWithIgnoreConfigAndSSLMode gets the IR from a database with ignore configuration and custom SSL mode
func GetIRFromDatabaseWithIgnoreConfigAndSSLMode(host string, port int, db, user, password, schemaName, sslmode, applicationName string, ignoreConfig *ir.IgnoreConfig) (*ir.IR, error) {
// Build database connection
config := &ConnectionConfig{
Host: host,
Port: port,
Database: db,
User: user,
Password: password,
SSLMode: "prefer",
SSLMode: sslmode,
ApplicationName: applicationName,
}

Expand Down