forked from rancher/rancher
-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils.go
130 lines (115 loc) · 3.23 KB
/
utils.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
package nodedriver
import (
"fmt"
"net/rpc"
"reflect"
"strconv"
"strings"
"github.com/docker/machine/libmachine/drivers/plugin/localbinary"
rpcdriver "github.com/docker/machine/libmachine/drivers/rpc"
cli "github.com/docker/machine/libmachine/mcnflag"
v3 "github.com/rancher/types/apis/management.cattle.io/v3"
"github.com/sirupsen/logrus"
)
var (
// secretFields lists all the hard-coded fields that should hidden as password
secretFields = map[string]struct{}{
// ec2
"secretKey": {},
// digitalOcean
"accessToken": {},
// azure
"clientSecret": {},
// packet, rackspace, softlayer
"apiKey": {},
// vSphere, openstack, vmwarevcloudair
"password": {},
// exoscale
"apiSecretKey": {},
// otc
"accessKeySecret": {},
}
)
func FlagToField(flag cli.Flag) (string, v3.Field, error) {
field := v3.Field{
Create: true,
Update: true,
Type: "string",
}
name, err := ToLowerCamelCase(flag.String())
if err != nil {
return name, field, err
}
switch v := flag.(type) {
case *cli.StringFlag:
if isPassword(name) {
field.Type = "password"
}
field.Description = v.Usage
field.Default.StringValue = v.Value
case *cli.IntFlag:
// This will make the int flag appear as a string field in the rancher API, but we are doing this to maintain
// backward compatibility, at least until we fix a bug that prevents nodeDriver schemas from updating upon
// a Rancher upgrade
field.Description = v.Usage
field.Default.StringValue = strconv.Itoa(v.Value)
case *cli.BoolFlag:
field.Type = "boolean"
field.Description = v.Usage
case *cli.StringSliceFlag:
field.Type = "array[string]"
field.Description = v.Usage
field.Default.StringSliceValue = v.Value
case *BoolPointerFlag:
field.Type = "boolean"
field.Description = v.Usage
default:
return name, field, fmt.Errorf("unknown type of flag %v: %v", flag, reflect.TypeOf(flag))
}
return name, field, nil
}
func isPassword(key string) bool {
_, ok := secretFields[key]
return ok
}
func ToLowerCamelCase(nodeFlagName string) (string, error) {
parts := strings.SplitN(nodeFlagName, "-", 2)
if len(parts) != 2 {
return "", fmt.Errorf("parameter %s does not follow expected naming convention [DRIVER]-[FLAG-NAME]", nodeFlagName)
}
flagNameParts := strings.Split(parts[1], "-")
flagName := flagNameParts[0]
for _, flagNamePart := range flagNameParts[1:] {
flagName = flagName + strings.ToUpper(flagNamePart[:1]) + flagNamePart[1:]
}
return flagName, nil
}
func getCreateFlagsForDriver(driver string) ([]cli.Flag, error) {
logrus.Debug("Starting binary ", driver)
p, err := localbinary.NewPlugin(driver)
if err != nil {
return nil, err
}
go func() {
err := p.Serve()
if err != nil {
logrus.Debugf("Error serving plugin server for driver=%s, err=%v", driver, err)
}
}()
defer p.Close()
addr, err := p.Address()
if err != nil {
return nil, err
}
rpcclient, err := rpc.DialHTTP("tcp", addr)
if err != nil {
return nil, fmt.Errorf("Error dialing to plugin server's address(%v), err=%v", addr, err)
}
defer rpcclient.Close()
c := rpcdriver.NewInternalClient(rpcclient)
var flags []cli.Flag
if err := c.Call(".GetCreateFlags", struct{}{}, &flags); err != nil {
return nil, fmt.Errorf("Error getting flags err=%v", err)
}
return flags, nil
}