@@ 21,6 21,7 @@ const (
// Config is the configuration of the bridge.
type Config struct {
+ Include string
BaseURL string
HTTPAddress string
LogLevel string
@@ 82,60 83,40 @@ type resolvedConfig struct {
Priority string
}
-// ReadConfig reads an scfg formatted file and returns the configuration struct.
-func ReadConfig(path string) (*Config, error) {
- cfg, err := scfg.Load(path)
- if err != nil {
- return nil, err
- }
-
- config := new(Config)
- // Set default values
- config.HTTPAddress = "127.0.0.1:8080"
- config.LogLevel = "info"
- config.LogFormat = "text"
- config.AlertMode = Multi
-
- config.Cache.Type = "disabled"
- config.Cache.Duration = time.Hour * 24
- // memory
- config.Cache.CleanupInterval = time.Hour
- // redis
- config.Cache.RedisURL = "redis://localhost:6379"
-
- d := cfg.Get("log-level")
+func parseBlock(block scfg.Block, config *Config) error {
+ d := block.Get("log-level")
if d != nil {
if err := d.ParseParams(&config.LogLevel); err != nil {
- return nil, err
+ return err
}
}
- d = cfg.Get("log-format")
+ d = block.Get("log-format")
if d != nil {
if err := d.ParseParams(&config.LogFormat); err != nil {
- return nil, err
+ return err
}
}
- d = cfg.Get("http-address")
+ d = block.Get("http-address")
if d != nil {
if err := d.ParseParams(&config.HTTPAddress); err != nil {
- return nil, err
+ return err
}
}
- d = cfg.Get("base-url")
+ d = block.Get("base-url")
if d != nil {
if err := d.ParseParams(&config.BaseURL); err != nil {
- return nil, err
+ return err
}
}
- d = cfg.Get("alert-mode")
+ d = block.Get("alert-mode")
if d != nil {
var mode string
if err := d.ParseParams(&mode); err != nil {
- return nil, err
+ return err
}
switch strings.ToLower(mode) {
@@ 146,36 127,31 @@ func ReadConfig(path string) (*Config, error) {
config.AlertMode = Multi
default:
- return nil, fmt.Errorf("%q directive: illegal mode %q", d.Name, mode)
+ return fmt.Errorf("%q directive: illegal mode %q", d.Name, mode)
}
}
- d = cfg.Get("user")
+ d = block.Get("user")
if d != nil {
if err := d.ParseParams(&config.User); err != nil {
- return nil, err
+ return err
}
}
- d = cfg.Get("password")
+ d = block.Get("password")
if d != nil {
if err := d.ParseParams(&config.Password); err != nil {
- return nil, err
+ return err
}
}
- if (config.Password != "" && config.User == "") ||
- (config.Password == "" && config.User != "") {
- return nil, errors.New("user and password have to be set together")
- }
-
- labelsDir := cfg.Get("labels")
+ labelsDir := block.Get("labels")
if labelsDir != nil {
d = labelsDir.Children.Get("order")
if d != nil {
var order string
if err := d.ParseParams(&order); err != nil {
- return nil, err
+ return err
}
config.Labels.Order = strings.Split(order, ",")
@@ 188,13 164,13 @@ func ReadConfig(path string) (*Config, error) {
var name string
if err := labelDir.ParseParams(&name); err != nil {
- return nil, err
+ return err
}
d = labelDir.Children.Get("priority")
if d != nil {
if err := d.ParseParams(&labelConfig.Priority); err != nil {
- return nil, err
+ return err
}
}
@@ 202,7 178,7 @@ func ReadConfig(path string) (*Config, error) {
if d != nil {
var tags string
if err := d.ParseParams(&tags); err != nil {
- return nil, err
+ return err
}
labelConfig.Tags = strings.Split(tags, ",")
@@ 211,21 187,21 @@ func ReadConfig(path string) (*Config, error) {
d = labelDir.Children.Get("icon")
if d != nil {
if err := d.ParseParams(&labelConfig.Icon); err != nil {
- return nil, err
+ return err
}
}
d = labelDir.Children.Get("email-address")
if d != nil {
if err := d.ParseParams(&labelConfig.EmailAddress); err != nil {
- return nil, err
+ return err
}
}
d = labelDir.Children.Get("call")
if d != nil {
if err := d.ParseParams(&labelConfig.Call); err != nil {
- return nil, err
+ return err
}
}
@@ 236,80 212,67 @@ func ReadConfig(path string) (*Config, error) {
config.Labels.Label = labels
}
- ntfyDir := cfg.Get("ntfy")
- if ntfyDir == nil {
- return nil, fmt.Errorf("%q directive missing", "ntfy")
- }
-
- d = ntfyDir.Children.Get("topic")
- if d == nil {
- return nil, fmt.Errorf("%q missing from %q directive", "topic", "ntfy")
- }
- if err := d.ParseParams(&config.Ntfy.Topic); err != nil {
- return nil, err
- }
-
- d = ntfyDir.Children.Get("user")
- if d != nil {
- if err := d.ParseParams(&config.Ntfy.User); err != nil {
- return nil, err
+ ntfyDir := block.Get("ntfy")
+ if ntfyDir != nil {
+ d = ntfyDir.Children.Get("topic")
+ if d != nil {
+ if err := d.ParseParams(&config.Ntfy.Topic); err != nil {
+ return err
+ }
}
- }
- d = ntfyDir.Children.Get("password")
- if d != nil {
- if err := d.ParseParams(&config.Ntfy.Password); err != nil {
- return nil, err
+ d = ntfyDir.Children.Get("user")
+ if d != nil {
+ if err := d.ParseParams(&config.Ntfy.User); err != nil {
+ return err
+ }
}
- }
- if (config.Ntfy.Password != "" && config.Ntfy.User == "") ||
- (config.Ntfy.Password == "" && config.Ntfy.User != "") {
- return nil, errors.New("ntfy: user and password have to be set together")
- }
+ d = ntfyDir.Children.Get("password")
+ if d != nil {
+ if err := d.ParseParams(&config.Ntfy.Password); err != nil {
+ return err
+ }
+ }
- d = ntfyDir.Children.Get("access-token")
- if d != nil {
- if err := d.ParseParams(&config.Ntfy.AccessToken); err != nil {
- return nil, err
+ d = ntfyDir.Children.Get("access-token")
+ if d != nil {
+ if err := d.ParseParams(&config.Ntfy.AccessToken); err != nil {
+ return err
+ }
}
- }
- if config.Ntfy.User != "" && config.Ntfy.AccessToken != "" {
- return nil, errors.New("ntfy: cannot use both an access-token and a user/password at the same time")
- }
+ d = ntfyDir.Children.Get("certificate-fingerprint")
+ if d != nil {
+ if err := d.ParseParams(&config.Ntfy.CertFingerprint); err != nil {
+ return err
+ }
- d = ntfyDir.Children.Get("certificate-fingerprint")
- if d != nil {
- if err := d.ParseParams(&config.Ntfy.CertFingerprint); err != nil {
- return nil, err
+ // hex.EncodeToString outputs a lower case string
+ config.Ntfy.CertFingerprint = strings.ToLower(strings.ReplaceAll(config.Ntfy.CertFingerprint, ":", ""))
}
- // hex.EncodeToString outputs a lower case string
- config.Ntfy.CertFingerprint = strings.ToLower(strings.ReplaceAll(config.Ntfy.CertFingerprint, ":", ""))
- }
-
- d = ntfyDir.Children.Get("email-address")
- if d != nil {
- if err := d.ParseParams(&config.Ntfy.EmailAddress); err != nil {
- return nil, err
+ d = ntfyDir.Children.Get("email-address")
+ if d != nil {
+ if err := d.ParseParams(&config.Ntfy.EmailAddress); err != nil {
+ return err
+ }
}
- }
- d = ntfyDir.Children.Get("call")
- if d != nil {
- if err := d.ParseParams(&config.Ntfy.Call); err != nil {
- return nil, err
+ d = ntfyDir.Children.Get("call")
+ if d != nil {
+ if err := d.ParseParams(&config.Ntfy.Call); err != nil {
+ return err
+ }
}
}
- cacheDir := cfg.Get("cache")
-
+ cacheDir := block.Get("cache")
if cacheDir != nil {
d = cacheDir.Children.Get("type")
if d != nil {
if err := d.ParseParams(&config.Cache.Type); err != nil {
- return nil, err
+ return err
}
}
@@ 317,12 280,12 @@ func ReadConfig(path string) (*Config, error) {
d = cacheDir.Children.Get("duration")
if d != nil {
if err := d.ParseParams(&durationString); err != nil {
- return nil, err
+ return err
}
duration, err := time.ParseDuration(durationString)
if err != nil {
- return nil, err
+ return err
}
config.Cache.Duration = duration
@@ 333,12 296,12 @@ func ReadConfig(path string) (*Config, error) {
d = cacheDir.Children.Get("cleanup-interval")
if d != nil {
if err := d.ParseParams(&cleanupIntervalString); err != nil {
- return nil, err
+ return err
}
interval, err := time.ParseDuration(cleanupIntervalString)
if err != nil {
- return nil, err
+ return err
}
config.Cache.CleanupInterval = interval
@@ 348,24 311,23 @@ func ReadConfig(path string) (*Config, error) {
d = cacheDir.Children.Get("redis-url")
if d != nil {
if err := d.ParseParams(&config.Cache.RedisURL); err != nil {
- return nil, err
+ return err
}
}
}
- amDir := cfg.Get("alertmanager")
-
+ amDir := block.Get("alertmanager")
if amDir != nil {
var durationString string
d = amDir.Children.Get("silence-duration")
if d != nil {
if err := d.ParseParams(&durationString); err != nil {
- return nil, err
+ return err
}
duration, err := time.ParseDuration(durationString)
if err != nil {
- return nil, err
+ return err
}
config.Am.SilenceDuration = duration
@@ 374,37 336,32 @@ func ReadConfig(path string) (*Config, error) {
d = amDir.Children.Get("user")
if d != nil {
if err := d.ParseParams(&config.Am.User); err != nil {
- return nil, err
+ return err
}
}
d = amDir.Children.Get("password")
if d != nil {
if err := d.ParseParams(&config.Am.Password); err != nil {
- return nil, err
+ return err
}
}
- if (config.Am.Password != "" && config.Am.User == "") ||
- (config.Am.Password == "" && config.Am.User != "") {
- return nil, errors.New("alertmanager: user and password have to be set together")
- }
-
d = amDir.Children.Get("url")
if d != nil {
if err := d.ParseParams(&config.Am.URL); err != nil {
- return nil, err
+ return err
}
}
}
- resolvedDir := cfg.Get("resolved")
+ resolvedDir := block.Get("resolved")
if resolvedDir != nil {
d = resolvedDir.Children.Get("tags")
if d != nil {
var tags string
if err := d.ParseParams(&tags); err != nil {
- return nil, err
+ return err
}
config.Resolved.Tags = strings.Split(tags, ",")
@@ 413,17 370,87 @@ func ReadConfig(path string) (*Config, error) {
d = resolvedDir.Children.Get("icon")
if d != nil {
if err := d.ParseParams(&config.Resolved.Icon); err != nil {
- return nil, err
+ return err
}
}
d = resolvedDir.Children.Get("priority")
if d != nil {
if err := d.ParseParams(&config.Resolved.Priority); err != nil {
- return nil, err
+ return err
}
}
}
+ return nil
+}
+
+// ReadConfig reads an scfg formatted file and returns the configuration struct.
+func ReadConfig(path string) (*Config, error) {
+ cfg, err := scfg.Load(path)
+ if err != nil {
+ return nil, err
+ }
+
+ config := new(Config)
+ // Set default values
+ config.HTTPAddress = "127.0.0.1:8080"
+ config.LogLevel = "info"
+ config.LogFormat = "text"
+ config.AlertMode = Multi
+
+ config.Cache.Type = "disabled"
+ config.Cache.Duration = time.Hour * 24
+ // memory
+ config.Cache.CleanupInterval = time.Hour
+ // redis
+ config.Cache.RedisURL = "redis://localhost:6379"
+
+ includeDirs := cfg.GetAll("include")
+ for _, d := range includeDirs {
+ var includePath string
+ if err := d.ParseParams(&includePath); err != nil {
+ return nil, err
+ }
+
+ block, err := scfg.Load(includePath)
+ if err != nil {
+ return nil, fmt.Errorf("cannot load included config file %q: %v", includePath, err)
+ }
+
+ if err := parseBlock(block, config); err != nil {
+ return nil, fmt.Errorf("cannot parse included config file %q: %v", includePath, err)
+ }
+ }
+
+ err = parseBlock(cfg, config)
+ if err != nil {
+ return nil, err
+ }
+
+ // Check settings
+ if (config.Password != "" && config.User == "") ||
+ (config.Password == "" && config.User != "") {
+ return nil, errors.New("user and password have to be set together")
+ }
+
+ if config.Ntfy.Topic == "" {
+ return nil, fmt.Errorf("%q missing from %q directive", "topic", "ntfy")
+ }
+
+ if (config.Ntfy.Password != "" && config.Ntfy.User == "") ||
+ (config.Ntfy.Password == "" && config.Ntfy.User != "") {
+ return nil, errors.New("ntfy: user and password have to be set together")
+ }
+
+ if config.Ntfy.User != "" && config.Ntfy.AccessToken != "" {
+ return nil, errors.New("ntfy: cannot use both an access-token and a user/password at the same time")
+ }
+
+ if (config.Am.Password != "" && config.Am.User == "") ||
+ (config.Am.Password == "" && config.Am.User != "") {
+ return nil, errors.New("alertmanager: user and password have to be set together")
+ }
+
return config, nil
}