-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
116 lines (99 loc) · 2.5 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package main
import (
"errors"
"fmt"
"os"
"strings"
"github.com/knadh/koanf/parsers/yaml"
kyaml "github.com/knadh/koanf/parsers/yaml"
"github.com/knadh/koanf/providers/env"
"github.com/knadh/koanf/providers/file"
"github.com/knadh/koanf/providers/posflag"
"github.com/knadh/koanf/v2"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
const (
ENV_PREFIX string = "DEMO_"
)
func main() {
var (
kConfig *koanf.Koanf = nil
)
rootCmd := &cobra.Command{
RunE: func(cmd *cobra.Command, args []string) error {
if kConfig != nil {
b, err := yaml.Parser().Marshal(kConfig.All())
if err != nil {
return err
}
fmt.Fprint(os.Stdout, string(b))
}
return nil
},
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
configFile, err := cmd.Flags().GetString("config")
if err != nil {
return err
}
// Especially paring flags for koanf
err = cmd.Flags().Parse(args)
if err != nil {
return err
}
kConfig, err = prepareKConfig(configFile, cmd.Flags())
if err != nil {
return err
}
return nil
},
Use: "demo",
}
rootCmd.Flags().AddFlagSet(getRootPflagSet())
rootCmd.Execute()
}
func getRootPflagSet() *pflag.FlagSet {
rootPflagSet := pflag.NewFlagSet("root", pflag.ContinueOnError)
rootPflagSet.String("config", "config.yaml", "Configuration file")
rootPflagSet.String("log-level", "info", "Log level")
return rootPflagSet
}
// prepareKConfig loads sources in following order
// 1. config file
// 2. env
// 3. pflagSet (no defaults)
func prepareKConfig(configFile string, parsedPflags *pflag.FlagSet) (*koanf.Koanf, error) {
kConfig := koanf.New(".")
// 1. config file
if _, err := os.Stat(configFile); !errors.Is(err, os.ErrNotExist) {
err = kConfig.Load(file.Provider(configFile), kyaml.Parser())
if err != nil {
return nil, err
}
}
// 2. env vars
err := kConfig.Load(env.Provider(ENV_PREFIX, ".", func(s string) string {
return strings.Replace(strings.ToLower(strings.TrimPrefix(s, ENV_PREFIX)), "_", ".", -1)
}), nil)
if err != nil {
return nil, err
}
// 3. pflag (hopefully only defined flags
err = kConfig.Load(posflag.Provider(parsedPflags, ".", nil), nil, koanf.WithMergeFunc(customMergeFunc))
if err != nil {
return nil, err
}
return kConfig, nil
}
func customMergeFunc(src, dest map[string]interface{}) error {
for srcKey, srcValue := range src {
switch srcKey {
case "log-level":
newKey := "log.level"
dest[newKey] = srcValue
default:
dest[srcKey] = srcValue
}
}
return nil
}