Skip to content

Commit 47da7f8

Browse files
Add interfaces for CLI unit testing and env test
Signed-off-by: Nathan LeClaire <nathan.leclaire@gmail.com>
1 parent 7b483fe commit 47da7f8

File tree

12 files changed

+734
-107
lines changed

12 files changed

+734
-107
lines changed
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package commandstest
2+
3+
import (
4+
"github.com/codegangsta/cli"
5+
)
6+
7+
type FakeFlagger struct {
8+
Data map[string]interface{}
9+
}
10+
11+
type FakeCommandLine struct {
12+
LocalFlags, GlobalFlags *FakeFlagger
13+
HelpShown bool
14+
CliArgs []string
15+
}
16+
17+
func (ff FakeFlagger) String(key string) string {
18+
if value, ok := ff.Data[key]; ok {
19+
return value.(string)
20+
}
21+
return ""
22+
}
23+
24+
func (ff FakeFlagger) StringSlice(key string) []string {
25+
if value, ok := ff.Data[key]; ok {
26+
return value.([]string)
27+
}
28+
return []string{}
29+
}
30+
31+
func (ff FakeFlagger) Int(key string) int {
32+
if value, ok := ff.Data[key]; ok {
33+
return value.(int)
34+
}
35+
return 0
36+
}
37+
38+
func (ff FakeFlagger) Bool(key string) bool {
39+
if value, ok := ff.Data[key]; ok {
40+
return value.(bool)
41+
}
42+
return false
43+
}
44+
45+
func (fcli *FakeCommandLine) String(key string) string {
46+
return fcli.LocalFlags.String(key)
47+
}
48+
49+
func (fcli *FakeCommandLine) StringSlice(key string) []string {
50+
return fcli.LocalFlags.StringSlice(key)
51+
}
52+
53+
func (fcli *FakeCommandLine) Int(key string) int {
54+
return fcli.LocalFlags.Int(key)
55+
}
56+
57+
func (fcli *FakeCommandLine) Bool(key string) bool {
58+
return fcli.LocalFlags.Bool(key)
59+
}
60+
61+
func (fcli *FakeCommandLine) GlobalString(key string) string {
62+
return fcli.GlobalFlags.String(key)
63+
}
64+
65+
func (fcli *FakeCommandLine) Generic(name string) interface{} {
66+
return fcli.LocalFlags.Data[name]
67+
}
68+
69+
func (fcli *FakeCommandLine) FlagNames() []string {
70+
flagNames := []string{}
71+
for key := range fcli.LocalFlags.Data {
72+
flagNames = append(flagNames, key)
73+
}
74+
75+
return flagNames
76+
}
77+
78+
func (fcli *FakeCommandLine) ShowHelp() {
79+
fcli.HelpShown = true
80+
}
81+
82+
func (fcli *FakeCommandLine) Application() *cli.App {
83+
return cli.NewApp()
84+
}
85+
86+
func (fcli *FakeCommandLine) Args() cli.Args {
87+
return fcli.CliArgs
88+
}
89+
90+
func (fcli *FakeCommandLine) ShowVersion() {
91+
return
92+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package commandstest

commands/config.go

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ import (
1414
"github.com/docker/machine/libmachine/state"
1515
)
1616

17+
var (
18+
defaultConnChecker ConnChecker
19+
)
20+
21+
func init() {
22+
defaultConnChecker = &MachineConnChecker{}
23+
}
24+
1725
// ErrCertInvalid for when the cert is computed to be invalid.
1826
type ErrCertInvalid struct {
1927
wrappedErr error
@@ -41,7 +49,7 @@ func cmdConfig(c CommandLine, api libmachine.API) error {
4149
return err
4250
}
4351

44-
dockerHost, authOptions, err := runConnectionBoilerplate(host, c)
52+
dockerHost, authOptions, err := defaultConnChecker.Check(host, c.Bool("swarm"))
4553
if err != nil {
4654
return fmt.Errorf("Error running connection boilerplate: %s", err)
4755
}
@@ -54,7 +62,13 @@ func cmdConfig(c CommandLine, api libmachine.API) error {
5462
return nil
5563
}
5664

57-
func runConnectionBoilerplate(h *host.Host, c CommandLine) (string, *auth.Options, error) {
65+
type ConnChecker interface {
66+
Check(*host.Host, bool) (string, *auth.Options, error)
67+
}
68+
69+
type MachineConnChecker struct{}
70+
71+
func (mcc *MachineConnChecker) Check(h *host.Host, swarm bool) (string, *auth.Options, error) {
5872
hostState, err := h.Driver.GetState()
5973
if err != nil {
6074
// TODO: This is a common operation and should have a commonly
@@ -70,7 +84,7 @@ func runConnectionBoilerplate(h *host.Host, c CommandLine) (string, *auth.Option
7084
return "", &auth.Options{}, fmt.Errorf("Error getting driver URL: %s", err)
7185
}
7286

73-
if c.Bool("swarm") {
87+
if swarm {
7488
var err error
7589
dockerHost, err = parseSwarm(dockerHost, h)
7690
if err != nil {

commands/env.go

Lines changed: 45 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,13 @@ const (
2121
var (
2222
errImproperEnvArgs = errors.New("Error: Expected one machine name")
2323
errImproperUnsetEnvArgs = errors.New("Error: Expected no machine name when the -u flag is present")
24+
defaultUsageHinter UsageHintGenerator
2425
)
2526

27+
func init() {
28+
defaultUsageHinter = &EnvUsageHintGenerator{}
29+
}
30+
2631
type ShellConfig struct {
2732
Prefix string
2833
Delimiter string
@@ -37,48 +42,62 @@ type ShellConfig struct {
3742
}
3843

3944
func cmdEnv(c CommandLine, api libmachine.API) error {
45+
var (
46+
err error
47+
shellCfg *ShellConfig
48+
)
49+
4050
// Ensure that log messages always go to stderr when this command is
4151
// being run (it is intended to be run in a subshell)
4252
log.SetOutWriter(os.Stderr)
4353

4454
if c.Bool("unset") {
45-
return unset(c, api)
55+
shellCfg, err = shellCfgUnset(c, api)
56+
if err != nil {
57+
return err
58+
}
59+
} else {
60+
shellCfg, err = shellCfgSet(c, api)
61+
if err != nil {
62+
return err
63+
}
4664
}
47-
return set(c, api)
65+
66+
return executeTemplateStdout(shellCfg)
4867
}
4968

50-
func set(c CommandLine, api libmachine.API) error {
69+
func shellCfgSet(c CommandLine, api libmachine.API) (*ShellConfig, error) {
5170
if len(c.Args()) != 1 {
52-
return errImproperEnvArgs
71+
return nil, errImproperEnvArgs
5372
}
5473

5574
host, err := api.Load(c.Args().First())
5675
if err != nil {
57-
return err
76+
return nil, err
5877
}
5978

60-
dockerHost, _, err := runConnectionBoilerplate(host, c)
79+
dockerHost, _, err := defaultConnChecker.Check(host, c.Bool("swarm"))
6180
if err != nil {
62-
return fmt.Errorf("Error running connection boilerplate: %s", err)
81+
return nil, fmt.Errorf("Error checking TLS connection: %s", err)
6382
}
6483

65-
userShell, err := getShell(c)
84+
userShell, err := getShell(c.String("shell"))
6685
if err != nil {
67-
return err
86+
return nil, err
6887
}
6988

7089
shellCfg := &ShellConfig{
7190
DockerCertPath: filepath.Join(mcndirs.GetMachineDir(), host.Name),
7291
DockerHost: dockerHost,
7392
DockerTLSVerify: "1",
74-
UsageHint: generateUsageHint(userShell, os.Args),
93+
UsageHint: defaultUsageHinter.GenerateUsageHint(userShell, os.Args),
7594
MachineName: host.Name,
7695
}
7796

7897
if c.Bool("no-proxy") {
7998
ip, err := host.Driver.GetIP()
8099
if err != nil {
81-
return fmt.Errorf("Error getting host IP: %s", err)
100+
return nil, fmt.Errorf("Error getting host IP: %s", err)
82101
}
83102

84103
noProxyVar, noProxyValue := findNoProxyFromEnv()
@@ -116,21 +135,21 @@ func set(c CommandLine, api libmachine.API) error {
116135
shellCfg.Delimiter = "=\""
117136
}
118137

119-
return executeTemplateStdout(shellCfg)
138+
return shellCfg, nil
120139
}
121140

122-
func unset(c CommandLine, api libmachine.API) error {
141+
func shellCfgUnset(c CommandLine, api libmachine.API) (*ShellConfig, error) {
123142
if len(c.Args()) != 0 {
124-
return errImproperUnsetEnvArgs
143+
return nil, errImproperUnsetEnvArgs
125144
}
126145

127-
userShell, err := getShell(c)
146+
userShell, err := getShell(c.String("shell"))
128147
if err != nil {
129-
return err
148+
return nil, err
130149
}
131150

132151
shellCfg := &ShellConfig{
133-
UsageHint: generateUsageHint(userShell, os.Args),
152+
UsageHint: defaultUsageHinter.GenerateUsageHint(userShell, os.Args),
134153
}
135154

136155
if c.Bool("no-proxy") {
@@ -156,7 +175,7 @@ func unset(c CommandLine, api libmachine.API) error {
156175
shellCfg.Delimiter = ""
157176
}
158177

159-
return executeTemplateStdout(shellCfg)
178+
return shellCfg, nil
160179
}
161180

162181
func executeTemplateStdout(shellCfg *ShellConfig) error {
@@ -169,8 +188,7 @@ func executeTemplateStdout(shellCfg *ShellConfig) error {
169188
return tmpl.Execute(os.Stdout, shellCfg)
170189
}
171190

172-
func getShell(c CommandLine) (string, error) {
173-
userShell := c.String("shell")
191+
func getShell(userShell string) (string, error) {
174192
if userShell != "" {
175193
return userShell, nil
176194
}
@@ -190,7 +208,13 @@ func findNoProxyFromEnv() (string, string) {
190208
return noProxyVar, noProxyValue
191209
}
192210

193-
func generateUsageHint(userShell string, args []string) string {
211+
type UsageHintGenerator interface {
212+
GenerateUsageHint(string, []string) string
213+
}
214+
215+
type EnvUsageHintGenerator struct{}
216+
217+
func (g *EnvUsageHintGenerator) GenerateUsageHint(userShell string, args []string) string {
194218
cmd := ""
195219
comment := "#"
196220

0 commit comments

Comments
 (0)