/
flags.go
168 lines (151 loc) · 4.95 KB
/
flags.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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
package utils
import (
"errors"
"fmt"
"strings"
"github.com/spf13/cobra"
"github.com/Azure/kubectl-aks/cmd/utils/config"
)
const (
NodeKey = "node"
SubscriptionIDKey = "subscription"
ResourceGroupKey = "resource-group"
ClusterNameKey = "cluster-name"
NodeResourceGroupKey = "node-resource-group"
VMSSKey = "vmss"
VMSSInstanceIDKey = "instance-id"
ResourceIDKey = "id"
)
// We need package level variables to ensure that the viper flag binding works correctly.
// See: https://github.com/spf13/viper/issues/375#issuecomment-578552586
var (
node string
subscriptionID string
nodeResourceGroup string
vmss string
vmssInstanceID string
resourceID string
)
// CommonFlags contains CLI flags common for all subcommands
type CommonFlags struct {
Verbose bool
}
func AddCommonFlags(command *cobra.Command, flags *CommonFlags) {
command.PersistentFlags().BoolVarP(
&flags.Verbose,
"verbose", "v",
false,
"Verbose output.",
)
}
// AddNodeFlags adds node flags and binds them to config/environment variables
// Every command that allows user to specify the node name has three options:
// (1) Provide the kubernetes node name
// (2) Provide the VMMS instance information (--subscription, --node-resource-group, --vmss and --instance-id)
// (3) Provide Resource ID (/subscriptions/mySubID/resourceGroups/myRG/providers/myProvider/virtualMachineScaleSets/myVMSS/virtualMachines/myInsID)
func AddNodeFlags(command *cobra.Command) {
addNodeFlags(command, false)
}
// AddNodeFlagsOnly adds node flags without binding config/environment variables
func AddNodeFlagsOnly(command *cobra.Command) {
addNodeFlags(command, true)
}
func addNodeFlags(command *cobra.Command, useFlagsOnly bool) {
command.PersistentFlags().StringVarP(
&node,
NodeKey, "",
"",
"Kubernetes node name.",
)
command.PersistentFlags().StringVarP(
&subscriptionID,
SubscriptionIDKey, "",
"",
"Subscription ID.",
)
command.PersistentFlags().StringVarP(
&nodeResourceGroup,
NodeResourceGroupKey, "",
"",
"Node resource group name.",
)
command.PersistentFlags().StringVarP(
&vmss,
VMSSKey, "",
"",
"Virtual machine scale set name.",
)
command.PersistentFlags().StringVarP(
&vmssInstanceID,
VMSSInstanceIDKey, "",
"",
"VM scale set instance ID.",
)
command.PersistentFlags().StringVarP(
&resourceID,
ResourceIDKey, "",
"",
`Resource ID containing all information of the VMSS instance using format:
e.g. /subscriptions/mySubID/resourceGroups/myRG/providers/myProvider/virtualMachineScaleSets/myVMSS/virtualMachines/myInsID.
Notice it is not case sensitive.`,
)
command.PersistentPreRunE = func(cmd *cobra.Command, args []string) error {
// If node or resource ID is set, we don't need to read the config file
// nor the environment variables because the CLI flags have precedence.
if !useFlagsOnly && node == "" && resourceID == "" {
config := config.New()
if cc, ok := config.CurrentConfig(); ok {
config = cc
}
// bind environment variables
config.AutomaticEnv()
config.SetEnvPrefix("kubectl_aks")
config.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
// bind CLI flags
if err := config.BindPFlags(cmd.PersistentFlags()); err != nil {
return fmt.Errorf("binding flags: %w", err)
}
// set the values with precedence:
// (1) CLI flag
// (2) environment variable
// (3) config file
node = config.GetString(NodeKey)
subscriptionID = config.GetString(SubscriptionIDKey)
nodeResourceGroup = config.GetString(NodeResourceGroupKey)
vmss = config.GetString(VMSSKey)
vmssInstanceID = config.GetString(VMSSInstanceIDKey)
resourceID = config.GetString(ResourceIDKey)
}
// validate the parameters
var nodeSet, vmssInfoSet, resourceIDSet bool
if node != "" {
nodeSet = true
}
if subscriptionID != "" && nodeResourceGroup != "" && vmss != "" && vmssInstanceID != "" {
vmssInfoSet = true
}
if resourceID != "" {
resourceIDSet = true
}
if !nodeSet && !vmssInfoSet && !resourceIDSet {
if subscriptionID != "" || nodeResourceGroup != "" || vmss != "" || vmssInstanceID != "" {
return errors.New("specify complete VMMS instance information ('subscription', 'node-resource-group', 'vmss' and 'instance-id')")
}
return errors.New("specify either 'node' or 'id' or VMMS instance information ('subscription', 'node-resource-group', 'vmss' and 'instance-id')")
} else if nodeSet {
if vmssInfoSet {
return errors.New("specify either 'node' or VMMS instance information ('subscription', 'node-resource-group', 'vmss' and 'instance-id')")
}
if resourceIDSet {
return errors.New("specify either 'node' or 'id'")
}
} else if vmssInfoSet {
if resourceIDSet {
return errors.New("specify either VMMS instance information ('subscription', 'node-resource-group', 'vmss' and 'instance-id') or 'id'")
}
}
return nil
}
}