-
Notifications
You must be signed in to change notification settings - Fork 7
/
root.go
132 lines (121 loc) · 3.7 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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package command
import (
"fmt"
"os"
"strings"
"time"
"github.com/lunarway/release-manager/cmd/hamctl/command/completion"
"github.com/lunarway/release-manager/internal/git"
"github.com/lunarway/release-manager/internal/http"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"gopkg.in/yaml.v2"
)
// NewRoot returns a new instance of a hamctl command.
func NewRoot(version *string) (*cobra.Command, error) {
var service, email string
client := http.Client{
Metadata: http.Metadata{
CLIVersion: *version,
},
}
var command = &cobra.Command{
Use: "hamctl",
Short: "hamctl controls a release manager server",
BashCompletionFunction: completion.Hamctl,
PersistentPreRunE: func(c *cobra.Command, args []string) error {
// all commands but version and completion requires the "service" flag
// if this is one of them, skip the check
if c.Name() == "version" || c.Name() == "completion" {
return nil
}
defaultShuttleString(shuttleSpecFromFile, &service, func(s *shuttleSpec) string {
return s.Vars.Service
})
if client.BaseURL == "" {
client.BaseURL = os.Getenv("HAMCTL_URL")
}
if client.Metadata.AuthToken == "" {
client.Metadata.AuthToken = os.Getenv("HAMCTL_AUTH_TOKEN")
}
var missingFlags []string
if service == "" {
missingFlags = append(missingFlags, "service")
}
if email == "" {
_, email, _ = git.CommitterDetails()
if email == "" {
missingFlags = append(missingFlags, "user-email")
}
}
client.Metadata.CallerEmail = email
if len(missingFlags) != 0 {
return errors.Errorf(`required flag(s) "%s" not set`, strings.Join(missingFlags, `", "`))
}
return nil
},
Run: func(c *cobra.Command, args []string) {
c.HelpFunc()(c, args)
},
}
command.AddCommand(
NewCompletion(command),
NewDescribe(&client, &service),
NewPolicy(&client, &service),
NewPromote(&client, &service),
NewRelease(&client, &service, func(f string, args ...interface{}) {
fmt.Printf(f, args...)
}),
NewRollback(&client, &service),
NewStatus(&client, &service),
NewVersion(*version),
)
command.PersistentFlags().DurationVar(&client.Timeout, "http-timeout", 120*time.Second, "HTTP request timeout")
command.PersistentFlags().StringVar(&client.BaseURL, "http-base-url", "", "address of the http release manager server")
command.PersistentFlags().StringVar(&client.Metadata.AuthToken, "http-auth-token", "", "auth token for the http service")
command.PersistentFlags().StringVar(&service, "service", "", "service name to execute commands for")
command.PersistentFlags().StringVar(&email, "user-email", "", "email of user performing the command (defaults to Git configurated user.email)")
return command, nil
}
type shuttleSpec struct {
Vars shuttleSpecVars
}
type shuttleSpecVars struct {
Service string `yaml:"service"`
K8S struct {
Namespace string `yaml:"namespace"`
} `yaml:"k8s"`
}
// shuttleSpecFromFile tries to read a shuttle specification.
func shuttleSpecFromFile() (shuttleSpec, bool) {
f, err := os.Open("shuttle.yaml")
if err != nil {
return shuttleSpec{}, false
}
var spec shuttleSpec
decoder := yaml.NewDecoder(f)
err = decoder.Decode(&spec)
if err != nil {
return shuttleSpec{}, false
}
return spec, true
}
// defaultShuttleString writes a value from a shuttle specification to flagValue
// if the provided flagValue is empty and the value in the spec is set.
func defaultShuttleString(shuttleLocator func() (shuttleSpec, bool), flagValue *string, f func(s *shuttleSpec) string) {
if flagValue == nil {
return
}
t := strings.TrimSpace(*flagValue)
if t != "" {
return
}
spec, ok := shuttleLocator()
if !ok {
return
}
t = f(&spec)
if t != "" {
*flagValue = t
}
}