mirror of
https://blitiri.com.ar/repos/chasquid
synced 2025-12-17 14:37:02 +00:00
config: Allow overrides from the command line
This patch allows the configuration values to be overridden from the command-line, with a new -config_overrides flag. There is a fairly specific use case for this, when editing the configuration file is not feasible or convenient (e.g. running an user-supplied configuration in a managed environment).
This commit is contained in:
@@ -37,6 +37,8 @@ import (
|
|||||||
var (
|
var (
|
||||||
configDir = flag.String("config_dir", "/etc/chasquid",
|
configDir = flag.String("config_dir", "/etc/chasquid",
|
||||||
"configuration directory")
|
"configuration directory")
|
||||||
|
configOverrides = flag.String("config_overrides", "",
|
||||||
|
"override configuration values (in text protobuf format)")
|
||||||
showVer = flag.Bool("version", false, "show version and exit")
|
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.
|
// Seed the PRNG, just to prevent for it to be totally predictable.
|
||||||
rand.Seed(time.Now().UnixNano())
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
|
||||||
conf, err := config.Load(*configDir + "/chasquid.conf")
|
conf, err := config.Load(*configDir+"/chasquid.conf", *configOverrides)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error loading config: %v", err)
|
log.Fatalf("Error loading config: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ func userRemove() {
|
|||||||
|
|
||||||
// chasquid-util aliases-resolve <address>
|
// chasquid-util aliases-resolve <address>
|
||||||
func aliasesResolve() {
|
func aliasesResolve() {
|
||||||
conf, err := config.Load(configDir + "/chasquid.conf")
|
conf, err := config.Load(configDir+"/chasquid.conf", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fatalf("Error loading config: %v", err)
|
Fatalf("Error loading config: %v", err)
|
||||||
}
|
}
|
||||||
@@ -248,7 +248,7 @@ func aliasesResolve() {
|
|||||||
|
|
||||||
// chasquid-util print-config
|
// chasquid-util print-config
|
||||||
func printConfig() {
|
func printConfig() {
|
||||||
conf, err := config.Load(configDir + "/chasquid.conf")
|
conf, err := config.Load(configDir+"/chasquid.conf", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fatalf("Error loading config: %v", err)
|
Fatalf("Error loading config: %v", err)
|
||||||
}
|
}
|
||||||
@@ -260,7 +260,7 @@ func printConfig() {
|
|||||||
func domaininfoRemove() {
|
func domaininfoRemove() {
|
||||||
domain := args["<domain>"].(string)
|
domain := args["<domain>"].(string)
|
||||||
|
|
||||||
conf, err := config.Load(configDir + "/chasquid.conf")
|
conf, err := config.Load(configDir+"/chasquid.conf", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fatalf("Error loading config: %v", err)
|
Fatalf("Error loading config: %v", err)
|
||||||
}
|
}
|
||||||
@@ -290,7 +290,7 @@ func aliasesAdd() {
|
|||||||
Fatalf("Domain doesn't exist")
|
Fatalf("Domain doesn't exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
conf, err := config.Load(configDir + "/chasquid.conf")
|
conf, err := config.Load(configDir+"/chasquid.conf", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fatalf("Error loading config: %v", err)
|
Fatalf("Error loading config: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,7 +133,7 @@
|
|||||||
.\" ========================================================================
|
.\" ========================================================================
|
||||||
.\"
|
.\"
|
||||||
.IX Title "chasquid 1"
|
.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
|
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
|
||||||
.\" way too many mistakes in technical documents.
|
.\" way too many mistakes in technical documents.
|
||||||
.if n .ad l
|
.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
|
.IP "\fB\-config_dir\fR \fIdir\fR" 8
|
||||||
.IX Item "-config_dir dir"
|
.IX Item "-config_dir dir"
|
||||||
configuration directory (default \fI/etc/chasquid\fR)
|
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
|
.IP "\fB\-alsologtostderr\fR" 8
|
||||||
.IX Item "-alsologtostderr"
|
.IX Item "-alsologtostderr"
|
||||||
also log to stderr, in addition to the file
|
also log to stderr, in addition to the file
|
||||||
|
|||||||
@@ -22,6 +22,12 @@ It's written in Go, and distributed under the Apache license 2.0.
|
|||||||
|
|
||||||
configuration directory (default F</etc/chasquid>)
|
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>
|
=item B<-alsologtostderr>
|
||||||
|
|
||||||
also log to stderr, in addition to the file
|
also log to stderr, in addition to the file
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ var defaultConfig = &Config{
|
|||||||
MailLogPath: "<syslog>",
|
MailLogPath: "<syslog>",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the config from the given file.
|
// Load the config from the given file, with the given overrides.
|
||||||
func Load(path string) (*Config, error) {
|
func Load(path, overrides string) (*Config, error) {
|
||||||
// Start with a copy of the default config.
|
// Start with a copy of the default config.
|
||||||
c := proto.Clone(defaultConfig).(*Config)
|
c := proto.Clone(defaultConfig).(*Config)
|
||||||
|
|
||||||
@@ -51,6 +51,14 @@ func Load(path string) (*Config, error) {
|
|||||||
}
|
}
|
||||||
override(c, fromFile)
|
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
|
// Handle hostname separate, because if it is set, we don't need to call
|
||||||
// os.Hostname which can fail.
|
// os.Hostname which can fail.
|
||||||
if c.Hostname == "" {
|
if c.Hostname == "" {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ func mustCreateConfig(t *testing.T, contents string) (string, string) {
|
|||||||
func TestEmptyConfig(t *testing.T) {
|
func TestEmptyConfig(t *testing.T) {
|
||||||
tmpDir, path := mustCreateConfig(t, "")
|
tmpDir, path := mustCreateConfig(t, "")
|
||||||
defer testlib.RemoveIfOk(t, tmpDir)
|
defer testlib.RemoveIfOk(t, tmpDir)
|
||||||
c, err := Load(path)
|
c, err := Load(path, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error loading empty config: %v", err)
|
t.Fatalf("error loading empty config: %v", err)
|
||||||
}
|
}
|
||||||
@@ -59,12 +59,18 @@ func TestFullConfig(t *testing.T) {
|
|||||||
tmpDir, path := mustCreateConfig(t, confStr)
|
tmpDir, path := mustCreateConfig(t, confStr)
|
||||||
defer testlib.RemoveIfOk(t, tmpDir)
|
defer testlib.RemoveIfOk(t, tmpDir)
|
||||||
|
|
||||||
|
overrideStr := `
|
||||||
|
hostname: "proust"
|
||||||
|
submission_address: ":999"
|
||||||
|
dovecot_auth: true
|
||||||
|
`
|
||||||
|
|
||||||
expected := &Config{
|
expected := &Config{
|
||||||
Hostname: "joust",
|
Hostname: "proust",
|
||||||
MaxDataSizeMb: 26,
|
MaxDataSizeMb: 26,
|
||||||
|
|
||||||
SmtpAddress: []string{":1234", ":5678"},
|
SmtpAddress: []string{":1234", ":5678"},
|
||||||
SubmissionAddress: []string{":10001", ":10002"},
|
SubmissionAddress: []string{":999"},
|
||||||
SubmissionOverTlsAddress: []string{"systemd"},
|
SubmissionOverTlsAddress: []string{"systemd"},
|
||||||
MonitoringAddress: ":1111",
|
MonitoringAddress: ":1111",
|
||||||
|
|
||||||
@@ -77,9 +83,11 @@ func TestFullConfig(t *testing.T) {
|
|||||||
DropCharacters: ".",
|
DropCharacters: ".",
|
||||||
|
|
||||||
MailLogPath: "<syslog>",
|
MailLogPath: "<syslog>",
|
||||||
|
|
||||||
|
DovecotAuth: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
c, err := Load(path)
|
c, err := Load(path, overrideStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error loading non-existent config: %v", err)
|
t.Fatalf("error loading non-existent config: %v", err)
|
||||||
}
|
}
|
||||||
@@ -93,7 +101,7 @@ func TestFullConfig(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestErrorLoading(t *testing.T) {
|
func TestErrorLoading(t *testing.T) {
|
||||||
c, err := Load("/does/not/exist")
|
c, err := Load("/does/not/exist", "")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("loaded a non-existent config: %v", c)
|
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")
|
t, "<invalid> this is not a valid protobuf")
|
||||||
defer testlib.RemoveIfOk(t, tmpDir)
|
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 {
|
if err == nil {
|
||||||
t.Fatalf("loaded an invalid config: %v", c)
|
t.Fatalf("loaded an invalid config: %v", c)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user