Skip to content
Merged
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
8 changes: 6 additions & 2 deletions pgmgr/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type argumentContext interface {
Int(string) int
StringSlice(string) []string
Bool(string) bool
IsSet(string) bool
}

// Config stores the options used by pgmgr.
Expand Down Expand Up @@ -55,7 +56,7 @@ func LoadConfig(config *Config, ctx argumentContext) error {
// load configuration from file first; then override with
// flags or env vars if they're present.
configFile := ctx.String("config-file")
if err := config.populateFromFile(configFile); err != nil {
if err := config.populateFromFile(configFile, ctx.IsSet("config-file")); err != nil {
return err
}

Expand All @@ -77,12 +78,15 @@ func LoadConfig(config *Config, ctx argumentContext) error {
return config.validate()
}

func (config *Config) populateFromFile(configFile string) error {
func (config *Config) populateFromFile(configFile string, explicit bool) error {
if configFile == "" {
return nil
}
contents, err := os.ReadFile(configFile)
if err != nil {
if !explicit && errors.Is(err, os.ErrNotExist) {
return nil
}
return err
}
if err := json.Unmarshal(contents, &config); err != nil {
Expand Down
58 changes: 58 additions & 0 deletions pgmgr/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package pgmgr
import (
"fmt"
"os"
"path/filepath"
"testing"
)

Expand All @@ -12,6 +13,7 @@ type TestContext struct {
IntVals map[string]int
StringSliceVals map[string][]string
BoolVals map[string]bool
IsSetVals map[string]bool
}

func (t *TestContext) String(key string) string {
Expand All @@ -26,6 +28,9 @@ func (t *TestContext) StringSlice(key string) []string {
func (t *TestContext) Bool(key string) bool {
return t.BoolVals[key]
}
func (t *TestContext) IsSet(key string) bool {
return t.IsSetVals[key]
}

func TestDefaults(t *testing.T) {
c := &Config{}
Expand Down Expand Up @@ -193,3 +198,56 @@ func TestQuotedMigrationTable(t *testing.T) {
t.Fatal(`Schema-qualified migration table should be "abc"."def", got`, c.quotedMigrationTable())
}
}

func TestMissingDefaultConfigFile(t *testing.T) {
// Simulate production: no .pgmgr.json in the working dir,
// config-file flag was NOT explicitly set by the user.
c := &Config{}
ctx := &TestContext{
StringVals: map[string]string{
"config-file": filepath.Join(t.TempDir(), ".pgmgr.json"),
},
IsSetVals: map[string]bool{
"config-file": false, // key distinction: user did not pass --config-file
},
}

if err := LoadConfig(c, ctx); err != nil {
t.Fatal("LoadConfig should succeed when default config file is missing, but got:", err)
}
}

func TestExplicitMissingConfigFileErrors(t *testing.T) {
c := &Config{}
ctx := &TestContext{
StringVals: map[string]string{
"config-file": filepath.Join(t.TempDir(), "explicit-missing.json"),
},
IsSetVals: map[string]bool{
"config-file": true, // user explicitly passed --config-file
},
}

if err := LoadConfig(c, ctx); err == nil {
t.Fatal("LoadConfig should fail when explicitly-given config file is missing")
}
}

func TestExplicitEnvVarMissingConfigFileErrors(t *testing.T) {
// When PGMGR_CONFIG_FILE env var is set to a path that doesn't exist,
// LoadConfig should fail — the user explicitly configured a path.
missingPath := filepath.Join(t.TempDir(), "from-env-var.json")
c := &Config{}
ctx := &TestContext{
StringVals: map[string]string{
"config-file": missingPath,
},
IsSetVals: map[string]bool{
"config-file": true, // urfave/cli sets IsSet=true when EnvVar is present
},
}

if err := LoadConfig(c, ctx); err == nil {
t.Fatal("LoadConfig should fail when config file path from env var does not exist")
}
}
Loading