forked from adampointer/cali
-
Notifications
You must be signed in to change notification settings - Fork 7
/
cli.go
153 lines (129 loc) · 4.24 KB
/
cli.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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package cali
import (
"fmt"
"runtime"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
const (
workdir = "/tmp/workspace"
)
var (
debug, jsonLogs, nonInteractive bool
dockerHost string
myFlags *viper.Viper
gitCfg *GitCheckoutConfig
)
// cobraFunc represents the function signiture which cobra uses for it's Run, PreRun, PostRun etc.
type cobraFunc func(cmd *cobra.Command, args []string)
// commands is a set of commands
type commands map[string]*Command
// Cli is the application itself
type Cli struct {
Name string
cfgFile *string
cmds commands
*Command
}
// NewCli returns a brand new cli
func NewCli(n string) *Cli {
c := Cli{
Name: n,
cmds: make(commands),
Command: &Command{
name: n,
cobra: &cobra.Command{Use: n},
},
}
c.cobra.PersistentPreRun = func(cmd *cobra.Command, args []string) {
if debug {
log.SetLevel(log.DebugLevel)
}
if jsonLogs {
log.SetFormatter(&log.JSONFormatter{})
}
}
myFlags = viper.New()
return &c
}
// NewCommand returns a brand new command attached to it's parent cli
func (c *Cli) NewCommand(n string) *Command {
cmd := &Command{
name: n,
cobra: &cobra.Command{Use: n},
}
c.cmds[n] = cmd
cmd.setPreRun(func(c *cobra.Command, args []string) {
// PreRun function is optional
if cmd.RunTask.init != nil {
cmd.RunTask.init(cmd.RunTask, args)
}
})
cmd.setRun(func(c *cobra.Command, args []string) {
cmd.RunTask.f(cmd.RunTask, args)
})
c.cobra.AddCommand(cmd.cobra)
return cmd
}
// FlagValues returns the wrapped viper object allowing the API consumer to use methods
// like GetString to get values from config
func (c *Cli) FlagValues() *viper.Viper {
return myFlags
}
// initFlags does the intial setup of the root command's persistent flags
func (c *Cli) initFlags() {
var cfg string
txt := fmt.Sprintf("config file (default is $HOME/.%s.yaml)", c.Name)
c.cobra.PersistentFlags().StringVar(&cfg, "config", "", txt)
c.cfgFile = &cfg
var dockerSocket string
if runtime.GOOS == "windows" {
dockerSocket = "npipe:////./pipe/docker_engine"
} else {
dockerSocket = "unix:///var/run/docker.sock"
}
c.Flags().StringVarP(&dockerHost, "docker-host", "H", dockerSocket, "URI of Docker Daemon")
_ = myFlags.BindPFlag("docker-host", c.Flags().Lookup("docker-host"))
myFlags.SetDefault("docker-host", dockerSocket)
c.Flags().BoolVarP(&debug, "debug", "d", false, "Debug mode")
_ = myFlags.BindPFlag("debug", c.Flags().Lookup("debug"))
myFlags.SetDefault("debug", true)
c.Flags().BoolVarP(&jsonLogs, "json", "j", false, "Log in json format")
_ = myFlags.BindPFlag("json", c.Flags().Lookup("json"))
myFlags.SetDefault("json", true)
c.Flags().BoolVarP(&nonInteractive, "non-interactive", "N", false, "Do not create a tty for Docker")
_ = myFlags.BindPFlag("non-interactive", c.Flags().Lookup("non-interactive"))
myFlags.SetDefault("non-interactive", false)
gitCfg = new(GitCheckoutConfig)
c.Flags().StringVarP(&gitCfg.Repo, "git", "g", "", "Git repo to checkout and build. Default behaviour is to build $PWD.")
_ = myFlags.BindPFlag("git", c.Flags().Lookup("git"))
c.Flags().StringVarP(&gitCfg.Branch, "git-branch", "b", "master", "Branch to checkout. Only makes sense when combined with the --git flag.")
_ = myFlags.BindPFlag("branch", c.Flags().Lookup("branch"))
myFlags.SetDefault("branch", "master")
c.Flags().StringVarP(&gitCfg.RelPath, "git-path", "P", "", "Path within a git repo where we want to operate.")
_ = myFlags.BindPFlag("git-path", c.Flags().Lookup("git-path"))
}
// initConfig does the initial setup of viper
func (c *Cli) initConfig() {
if *c.cfgFile != "" {
myFlags.SetConfigFile(*c.cfgFile)
} else {
myFlags.SetConfigName(fmt.Sprintf(".%s", c.Name))
myFlags.AddConfigPath(".") // First check current working directory
myFlags.AddConfigPath("$HOME") // Fallback to home directory, if that is not set
}
myFlags.AutomaticEnv()
// If a config file is found, read it in.
_ = myFlags.ReadInConfig()
// Above returns an error if it doesn't find a config file
// But we don't care
}
// Start the fans please!
func (c *Cli) Start() {
c.initFlags()
cobra.OnInitialize(c.initConfig)
if err := c.cobra.Execute(); err != nil {
log.Fatalf("%s", err)
}
}