aboutsummaryrefslogtreecommitdiffsponsor
diff options
context:
space:
mode:
-rw-r--r--cmd/mirror/main.go22
-rw-r--r--contrib/slackbuild/mirror.SlackBuild1
-rw-r--r--contrib/slackbuild/rc.mirror2
-rw-r--r--internal/service/config.go59
-rw-r--r--internal/service/service.go2
5 files changed, 66 insertions, 20 deletions
diff --git a/cmd/mirror/main.go b/cmd/mirror/main.go
index e823039..e8a00ac 100644
--- a/cmd/mirror/main.go
+++ b/cmd/mirror/main.go
@@ -13,14 +13,16 @@ import (
var Version string
type Flags struct {
- Config string
- Version bool
+ Config string
+ ConfigDir string
+ Version bool
}
func ParseFlags() *Flags {
var flags Flags
- flag.StringVar(&flags.Config, "config", "/etc/mirror/mirror.toml", "configuration file")
+ flag.StringVar(&flags.Config, "config", "/etc/mirror/mirror.toml", "configuration file which takes precedence")
+ flag.StringVar(&flags.ConfigDir, "config-dir", "/etc/mirror/conf.d", "configuration directory")
flag.BoolVar(&flags.Version, "version", false, "print version")
flag.Parse()
@@ -39,13 +41,23 @@ func main() {
if flags.Version {
fmt.Println(Version)
+
os.Exit(0)
}
- cfg, err := service.ReadConfig(flags.Config)
+ var cfg service.Config
+
+ c, err := service.ReadConfigDir(flags.ConfigDir)
+ exitOnError(err)
+
+ cfg.Append(c)
+
+ c, err = service.ReadConfig(flags.Config)
exitOnError(err)
- srv, err := service.NewService(cfg)
+ cfg.Append(c)
+
+ srv, err := service.NewService(&cfg)
exitOnError(err)
err = srv.Run()
diff --git a/contrib/slackbuild/mirror.SlackBuild b/contrib/slackbuild/mirror.SlackBuild
index 9dadca2..fb1b92e 100644
--- a/contrib/slackbuild/mirror.SlackBuild
+++ b/contrib/slackbuild/mirror.SlackBuild
@@ -64,6 +64,7 @@ mkdir -p "$PKG/etc/rc.d"
cat "$CWD/rc.mirror" > "$PKG/etc/rc.d/rc.mirror.new"
mkdir -p $PKG/etc/mirror
cat "$CWD/mirror.toml" > "$PKG/etc/mirror/mirror.toml.new"
+mkdir -p $PKG/etc/mirror/conf.d
mkdir -p "$PKG/var/log/mirror"
cd "$PKG"
diff --git a/contrib/slackbuild/rc.mirror b/contrib/slackbuild/rc.mirror
index df3c72f..362a3f1 100644
--- a/contrib/slackbuild/rc.mirror
+++ b/contrib/slackbuild/rc.mirror
@@ -20,7 +20,7 @@ start() {
--user=mirror \
--pidfiles=/run/mirror \
--output=/var/log/mirror/mirror.log \
- -- mirror -config /etc/mirror/mirror.toml
+ -- mirror
}
stop() {
diff --git a/internal/service/config.go b/internal/service/config.go
index 27368b3..bfe271e 100644
--- a/internal/service/config.go
+++ b/internal/service/config.go
@@ -3,6 +3,8 @@ package service
import (
"fmt"
"os"
+ "path"
+ "path/filepath"
"time"
"git.server.ky/slackcoder/mirror/internal"
@@ -13,6 +15,10 @@ type Duration struct {
time.Duration
}
+func DurationRef(v time.Duration) *Duration {
+ return &Duration{v}
+}
+
func (s Duration) MarshalText() ([]byte, error) {
return []byte(s.Duration.String()), nil
}
@@ -29,8 +35,8 @@ func (s *Duration) UnmarshalText(text []byte) error {
// Global parameters
type GlobalConfig struct {
- MaxInterval Duration `toml:"max-interval"`
- MinInterval Duration `toml:"min-interval"`
+ MaxInterval *Duration `toml:"max-interval"`
+ MinInterval *Duration `toml:"min-interval"`
}
type Config struct {
@@ -44,18 +50,17 @@ func (c *Config) String() string {
var DefaultConfig = Config{
GlobalConfig: GlobalConfig{
- MaxInterval: Duration{24 * time.Hour},
- MinInterval: Duration{time.Hour},
+ MaxInterval: DurationRef(24 * time.Hour),
+ MinInterval: DurationRef(time.Hour),
},
}
+// Read the given configuration file.
func ReadConfig(fp string) (*Config, error) {
var config Config
f, err := os.Open(fp)
- if os.IsNotExist(err) {
- return nil, nil
- } else if err != nil {
+ if err != nil {
return nil, err
}
defer f.Close()
@@ -68,14 +73,42 @@ func ReadConfig(fp string) (*Config, error) {
return &config, nil
}
-func (c *Config) Merge(src *Config) {
- if c.MaxInterval.Duration == 0 && src.MaxInterval.Duration != 0 {
+// Read all configuration in the given directory.
+func ReadConfigDir(fp string) (*Config, error) {
+ var cfg Config
+
+ confDPath := path.Join(path.Join(fp, "conf.d"))
+ confDDir, err := os.ReadDir(confDPath)
+ if os.IsNotExist(err) {
+ // No directory is an empty one.
+ return &Config{}, nil
+ } else if err != nil {
+ return nil, err
+ }
+
+ for _, entry := range confDDir {
+ if filepath.Ext(entry.Name()) != ".toml" {
+ continue
+ }
+
+ entryCfg, err := ReadConfig(filepath.Join(confDPath, entry.Name()))
+ if err != nil {
+ return nil, err
+ }
+
+ cfg.Append(entryCfg)
+ }
+
+ return &cfg, nil
+}
+
+// Apply the given configuration parameters.
+func (c *Config) Append(src *Config) {
+ if src.MaxInterval != nil {
c.MaxInterval = src.MaxInterval
}
- if c.MinInterval.Duration == 0 && src.MinInterval.Duration != 0 {
+ if src.MinInterval != nil {
c.MinInterval = src.MinInterval
}
- if len(c.Mirrors) == 0 {
- c.Mirrors = src.Mirrors
- }
+ c.Mirrors = append(c.Mirrors, src.Mirrors...)
}
diff --git a/internal/service/service.go b/internal/service/service.go
index 637a1cf..21df14b 100644
--- a/internal/service/service.go
+++ b/internal/service/service.go
@@ -32,7 +32,7 @@ type Service struct {
func NewService(cfg *Config) (*Service, error) {
// Apply defaults
- cfg.Merge(&DefaultConfig)
+ cfg.Append(&DefaultConfig)
for _, cmd := range requiredCommands {
if err := internal.RequireCommand(cmd); err != nil {