This repository has been archived by the owner on Oct 9, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 23
/
config_cmd.go
113 lines (92 loc) · 2.74 KB
/
config_cmd.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 config
import (
"context"
"os"
"strings"
"github.com/fatih/color"
"github.com/spf13/cobra"
)
const (
PathFlag = "file"
StrictModeFlag = "strict"
CommandValidate = "validate"
CommandDiscover = "discover"
)
type AccessorProvider func(options Options) Accessor
type printer interface {
Printf(format string, i ...interface{})
Println(i ...interface{})
}
func NewConfigCommand(accessorProvider AccessorProvider) *cobra.Command {
opts := Options{}
rootCmd := &cobra.Command{
Use: "config",
Short: "Runs various config commands, look at the help of this command to get a list of available commands..",
ValidArgs: []string{CommandValidate, CommandDiscover},
}
validateCmd := &cobra.Command{
Use: "validate",
Short: "Validates the loaded config.",
RunE: func(cmd *cobra.Command, args []string) error {
return validate(accessorProvider(opts), cmd)
},
}
discoverCmd := &cobra.Command{
Use: "discover",
Short: "Searches for a config in one of the default search paths.",
RunE: func(cmd *cobra.Command, args []string) error {
return validate(accessorProvider(opts), cmd)
},
}
// Configure Root Command
rootCmd.PersistentFlags().StringArrayVar(&opts.SearchPaths, PathFlag, []string{}, `Passes the config file to load.
If empty, it'll first search for the config file path then, if found, will load config from there.`)
rootCmd.AddCommand(validateCmd)
rootCmd.AddCommand(discoverCmd)
// Configure Validate Command
validateCmd.Flags().BoolVar(&opts.StrictMode, StrictModeFlag, false, `Validates that all keys in loaded config
map to already registered sections.`)
return rootCmd
}
// Redirects Stdout to a string buffer until context is cancelled.
func redirectStdOut() (old, new *os.File) {
old = os.Stdout // keep backup of the real stdout
var err error
_, new, err = os.Pipe()
if err != nil {
panic(err)
}
os.Stdout = new
return
}
func validate(accessor Accessor, p printer) error {
// Redirect stdout
old, n := redirectStdOut()
defer func() {
err := n.Close()
if err != nil {
panic(err)
}
}()
defer func() { os.Stdout = old }()
err := accessor.UpdateConfig(context.Background())
printInfo(p, accessor)
if err == nil {
green := color.New(color.FgGreen).SprintFunc()
p.Println(green("Validated config file successfully."))
} else {
red := color.New(color.FgRed).SprintFunc()
p.Println(red("Failed to validate config file."))
}
return err
}
func printInfo(p printer, v Accessor) {
cfgFile := v.ConfigFilesUsed()
if len(cfgFile) != 0 {
green := color.New(color.FgGreen).SprintFunc()
p.Printf("Config file(s) found at: %v\n", green(strings.Join(cfgFile, "\n")))
} else {
red := color.New(color.FgRed).SprintFunc()
p.Println(red("Couldn't find a config file."))
}
}