/
root.go
113 lines (91 loc) · 2.54 KB
/
root.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
package cmd
import (
"context"
"fmt"
"os"
"strings"
"github.com/fishnix/tucson/version"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/spf13/viper"
homedir "github.com/mitchellh/go-homedir"
"go.uber.org/zap"
)
var (
cfgFile string
logger *zap.SugaredLogger
rootCmd = &cobra.Command{
Use: "tucson",
Short: "tucson; a place near phoenix™️",
}
)
// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
if err := rootCmd.ExecuteContext(context.Background()); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func init() {
cobra.OnInitialize(initConfig)
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.tucson.yaml)")
rootCmd.PersistentFlags().Bool("debug", false, "enable debug logging")
viperBindFlag("logging.debug", rootCmd.PersistentFlags().Lookup("debug"))
rootCmd.PersistentFlags().Bool("pretty", false, "enable pretty (human readable) logging output")
viperBindFlag("logging.pretty", rootCmd.PersistentFlags().Lookup("pretty"))
}
func initConfig() {
if cfgFile != "" {
viper.SetConfigFile(cfgFile)
} else {
home, err := homedir.Dir()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
viper.AddConfigPath(home)
viper.SetConfigName(".tucson")
}
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
viper.SetEnvPrefix("tucson")
viper.AutomaticEnv()
err := viper.ReadInConfig()
setupLogging()
if err == nil {
logger.Infow("using config file", "file", viper.ConfigFileUsed())
}
}
func setupLogging() {
cfg := zap.NewProductionConfig()
if viper.GetBool("logging.pretty") {
cfg = zap.NewDevelopmentConfig()
}
if viper.GetBool("logging.debug") {
cfg.Level = zap.NewAtomicLevelAt(zap.DebugLevel)
} else {
cfg.Level = zap.NewAtomicLevelAt(zap.InfoLevel)
}
l, err := cfg.Build()
if err != nil {
panic(err)
}
logger = l.Sugar().With("app", "tucson", "version", version.Version)
defer logger.Sync() //nolint:errcheck
}
// viperBindFlag provides a wrapper around the viper bindings that handles error checks
func viperBindFlag(name string, flag *pflag.Flag) {
if err := viper.BindPFlag(name, flag); err != nil {
panic(err)
}
}
func viperBindEnv(name string) {
env := "tucson_" + name
env = strings.ReplaceAll(env, ".", "_")
env = strings.ReplaceAll(env, "-", "_")
env = strings.ToUpper(env)
if err := viper.BindEnv(name, env); err != nil {
panic(err)
}
}