author | Alberto Bertogli
<albertito@blitiri.com.ar> 2020-05-16 22:22:00 UTC |
committer | Alberto Bertogli
<albertito@blitiri.com.ar> 2020-05-16 23:10:06 UTC |
parent | 7909b479ebdcaa84e3d847927929d8f4505f20a6 |
chasquid.go | +3 | -1 |
cmd/chasquid-util/chasquid-util.go | +4 | -4 |
docs/man/chasquid.1 | +6 | -1 |
docs/man/chasquid.1.pod | +6 | -0 |
internal/config/config.go | +10 | -2 |
internal/config/config_test.go | +25 | -6 |
diff --git a/chasquid.go b/chasquid.go index f992c0b..059d2df 100644 --- a/chasquid.go +++ b/chasquid.go @@ -37,6 +37,8 @@ import ( var ( configDir = flag.String("config_dir", "/etc/chasquid", "configuration directory") + configOverrides = flag.String("config_overrides", "", + "override configuration values (in text protobuf format)") showVer = flag.Bool("version", false, "show version and exit") ) @@ -70,7 +72,7 @@ func main() { // Seed the PRNG, just to prevent for it to be totally predictable. rand.Seed(time.Now().UnixNano()) - conf, err := config.Load(*configDir + "/chasquid.conf") + conf, err := config.Load(*configDir+"/chasquid.conf", *configOverrides) if err != nil { log.Fatalf("Error loading config: %v", err) } diff --git a/cmd/chasquid-util/chasquid-util.go b/cmd/chasquid-util/chasquid-util.go index fa4be3d..f8eae2d 100644 --- a/cmd/chasquid-util/chasquid-util.go +++ b/cmd/chasquid-util/chasquid-util.go @@ -204,7 +204,7 @@ func userRemove() { // chasquid-util aliases-resolve <address> func aliasesResolve() { - conf, err := config.Load(configDir + "/chasquid.conf") + conf, err := config.Load(configDir+"/chasquid.conf", "") if err != nil { Fatalf("Error loading config: %v", err) } @@ -248,7 +248,7 @@ func aliasesResolve() { // chasquid-util print-config func printConfig() { - conf, err := config.Load(configDir + "/chasquid.conf") + conf, err := config.Load(configDir+"/chasquid.conf", "") if err != nil { Fatalf("Error loading config: %v", err) } @@ -260,7 +260,7 @@ func printConfig() { func domaininfoRemove() { domain := args["<domain>"].(string) - conf, err := config.Load(configDir + "/chasquid.conf") + conf, err := config.Load(configDir+"/chasquid.conf", "") if err != nil { Fatalf("Error loading config: %v", err) } @@ -290,7 +290,7 @@ func aliasesAdd() { Fatalf("Domain doesn't exist") } - conf, err := config.Load(configDir + "/chasquid.conf") + conf, err := config.Load(configDir+"/chasquid.conf", "") if err != nil { Fatalf("Error loading config: %v", err) } diff --git a/docs/man/chasquid.1 b/docs/man/chasquid.1 index 0a9afb7..1394a43 100644 --- a/docs/man/chasquid.1 +++ b/docs/man/chasquid.1 @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "chasquid 1" -.TH chasquid 1 "2018-07-22" "" "" +.TH chasquid 1 "2020-05-16" "" "" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l @@ -154,6 +154,11 @@ It's written in Go, and distributed under the Apache license 2.0. .IP "\fB\-config_dir\fR \fIdir\fR" 8 .IX Item "-config_dir dir" configuration directory (default \fI/etc/chasquid\fR) +.IP "\fB\-config_overrides\fR \fIconfig\fR" 8 +.IX Item "-config_overrides config" +configuration values (in text protobuf format) to override the on-disk +configuration with. This should only be needed in very specific cases for +deployments where editing the configuration file is not feasible. .IP "\fB\-alsologtostderr\fR" 8 .IX Item "-alsologtostderr" also log to stderr, in addition to the file diff --git a/docs/man/chasquid.1.pod b/docs/man/chasquid.1.pod index 56035d1..8f328e1 100644 --- a/docs/man/chasquid.1.pod +++ b/docs/man/chasquid.1.pod @@ -22,6 +22,12 @@ It's written in Go, and distributed under the Apache license 2.0. configuration directory (default F</etc/chasquid>) +=item B<-config_overrides> I<config> + +configuration values (in text protobuf format) to override the on-disk +configuration with. This should only be needed in very specific cases for +deployments where editing the configuration file is not feasible. + =item B<-alsologtostderr> also log to stderr, in addition to the file diff --git a/internal/config/config.go b/internal/config/config.go index bb0564d..3731dc5 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -33,8 +33,8 @@ var defaultConfig = &Config{ MailLogPath: "<syslog>", } -// Load the config from the given file. -func Load(path string) (*Config, error) { +// Load the config from the given file, with the given overrides. +func Load(path, overrides string) (*Config, error) { // Start with a copy of the default config. c := proto.Clone(defaultConfig).(*Config) @@ -51,6 +51,14 @@ func Load(path string) (*Config, error) { } override(c, fromFile) + // Handle command line overrides. + fromOverrides := &Config{} + err = prototext.Unmarshal([]byte(overrides), fromOverrides) + if err != nil { + return nil, fmt.Errorf("parsing override: %v", err) + } + override(c, fromOverrides) + // Handle hostname separate, because if it is set, we don't need to call // os.Hostname which can fail. if c.Hostname == "" { diff --git a/internal/config/config_test.go b/internal/config/config_test.go index b0e54c2..d539187 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -27,7 +27,7 @@ func mustCreateConfig(t *testing.T, contents string) (string, string) { func TestEmptyConfig(t *testing.T) { tmpDir, path := mustCreateConfig(t, "") defer testlib.RemoveIfOk(t, tmpDir) - c, err := Load(path) + c, err := Load(path, "") if err != nil { t.Fatalf("error loading empty config: %v", err) } @@ -59,12 +59,18 @@ func TestFullConfig(t *testing.T) { tmpDir, path := mustCreateConfig(t, confStr) defer testlib.RemoveIfOk(t, tmpDir) + overrideStr := ` + hostname: "proust" + submission_address: ":999" + dovecot_auth: true + ` + expected := &Config{ - Hostname: "joust", + Hostname: "proust", MaxDataSizeMb: 26, SmtpAddress: []string{":1234", ":5678"}, - SubmissionAddress: []string{":10001", ":10002"}, + SubmissionAddress: []string{":999"}, SubmissionOverTlsAddress: []string{"systemd"}, MonitoringAddress: ":1111", @@ -77,9 +83,11 @@ func TestFullConfig(t *testing.T) { DropCharacters: ".", MailLogPath: "<syslog>", + + DovecotAuth: true, } - c, err := Load(path) + c, err := Load(path, overrideStr) if err != nil { t.Fatalf("error loading non-existent config: %v", err) } @@ -93,7 +101,7 @@ func TestFullConfig(t *testing.T) { } func TestErrorLoading(t *testing.T) { - c, err := Load("/does/not/exist") + c, err := Load("/does/not/exist", "") if err == nil { t.Fatalf("loaded a non-existent config: %v", c) } @@ -104,7 +112,18 @@ func TestBrokenConfig(t *testing.T) { t, "<invalid> this is not a valid protobuf") defer testlib.RemoveIfOk(t, tmpDir) - c, err := Load(path) + c, err := Load(path, "") + if err == nil { + t.Fatalf("loaded an invalid config: %v", c) + } +} + +func TestBrokenOverride(t *testing.T) { + tmpDir, path := mustCreateConfig( + t, `hostname: "test"`) + defer testlib.RemoveIfOk(t, tmpDir) + + c, err := Load(path, "broken override") if err == nil { t.Fatalf("loaded an invalid config: %v", c) }