Skip to content

Commit

Permalink
parse config before viper to allow environment variables via gotpl (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
Hermsi1337 authored Mar 20, 2020
1 parent 22160b2 commit 250a391
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 15 deletions.
1 change: 1 addition & 0 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ dockers:
- quay.io/mittwald/brudi:stable
binaries:
- brudi
dockerfile: build/docker/Dockerfile
goos: linux
goarch: amd64
goarm: ''
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ BINARY_NAME = brudi
COMMIT_HASH = $(shell git rev-parse --verify HEAD)
CURDIR = $(shell pwd)

.PHONY: build

all: dep test lint build

dep:
Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,15 @@ The docker-image comes with all required binaries.
### Configuration
As already mentioned, `brudi` is configured via `.yaml`. The default path for this file is `${HOME}/.brudi.yaml`, but it's adjustable via `-c` or `--config`.
The config file itself can include environment-variables via `go-template`:
```yaml
restic:
global:
flags:
repo: "{{ .Env.RESTIC_REPOSITORY }}"
```
Since the configuration provided by the `.yaml`-file is mapped to the corresponding CLI-flags, you can adjust literally every parameter of your source backup.
Therefore you can simply refer to the official documentation for explanations on the available flags:
Expand Down
File renamed without changes.
69 changes: 54 additions & 15 deletions cmd/root.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package cmd

import (
"bytes"
"html/template"
"io/ioutil"
"os"
"path"
"strings"

"github.com/mitchellh/go-homedir"
Expand Down Expand Up @@ -42,32 +47,66 @@ func Execute() error {
}

func initConfig() {
if cfgFile != "" {
viper.SetConfigFile(cfgFile)
} else {
if cfgFile == "" {
home, err := homedir.Dir()
if err != nil {
log.WithError(err).Fatal("unable to determine homedir for current user")
}

viper.AddConfigPath(home)
viper.SetConfigName(".brudi.yaml")
cfgFile = path.Join(home, ".brudi.yaml")
}

viper.SetConfigType("yaml")
logFields := log.WithField("cfgFile", cfgFile)

viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
viper.AutomaticEnv()
info, err := os.Stat(cfgFile)
if os.IsNotExist(err) {
logFields.Warn("config does not exist")
return
} else if info.IsDir() {
logFields.Warn("config is a directory")
return
}

var cfgContent []byte
cfgContent, err = ioutil.ReadFile(cfgFile)
if err != nil {
log.WithError(err).Fatal("failed while reading config")
}

var tpl *template.Template
tpl, err = template.New("").Parse(string(cfgContent))
if err != nil {
log.WithError(err).Fatal()
}

type templateData struct {
Env map[string]string
}

if err := viper.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
// cfg file not found; ignore error if desired
} else {
log.WithError(err).Fatal("failed while reading config")
data := templateData{
Env: make(map[string]string),
}

for _, e := range os.Environ() {
e := strings.SplitN(e, "=", 2)
if len(e) > 1 {
data.Env[e[0]] = e[1]
}
}

if len(viper.ConfigFileUsed()) > 0 {
log.WithField("config", viper.ConfigFileUsed()).Info("config loaded")
renderedCfg := new(bytes.Buffer)
err = tpl.Execute(renderedCfg, &data)
if err != nil {
log.WithError(err).Fatal()
}

viper.SetConfigType("yaml")
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
viper.AutomaticEnv()

if err := viper.ReadConfig(renderedCfg); err != nil {
log.WithError(err).Fatal("failed while reading config")
}

log.WithField("config", cfgFile).Info("config loaded")
}

0 comments on commit 250a391

Please sign in to comment.