-
Notifications
You must be signed in to change notification settings - Fork 0
/
clusteroperator.go
158 lines (129 loc) · 4.11 KB
/
clusteroperator.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
package cmd
import (
"context"
"fmt"
"github.com/spf13/cobra"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
)
const (
MANAGED_STATE = "manage"
UNMANAGED_STATE = "unmanage"
)
var (
example = `
# set a cluster operator to unmanaged
%[1]s clusteroperator unmanage [NAME]
# set a cluster operator to unmanaged
%[1]s clusteroperator manage [NAME]
# optionally scale the operator up or down
%[1]s clusteroperator manage [NAME] --scale
%[1]s clusteroperator unmanage [NAME] --scale
`
)
// ClusterOperatorOptions wraps the cli options
type ClusterOperatorOptions struct {
configFlags *genericclioptions.ConfigFlags
genericclioptions.IOStreams
clusteroperator string
state string
unmanaged bool
scale bool
}
// NewClusterOperatorOptions provides a new instance of ClusterOperatorOptions with default values
func NewClusterOperatorOptions(streams genericclioptions.IOStreams) *ClusterOperatorOptions {
return &ClusterOperatorOptions{
configFlags: genericclioptions.NewConfigFlags(true),
IOStreams: streams,
}
}
// NewCmdClusterOperator provides a cobra command wrapping ClusterOperatorOptions
func NewCmdClusterOperator(streams genericclioptions.IOStreams) *cobra.Command {
// Create the default option set
o := NewClusterOperatorOptions(streams)
// Create the command
cmd := &cobra.Command{
Use: "clusteroperator [manage|unmanage] [NAME]",
Short: "Set a cluster operator to unmanaged or unmanaged",
Example: fmt.Sprintf(example, "oc"),
SilenceUsage: true,
RunE: func(c *cobra.Command, args []string) error {
if err := o.mergeArgs(c, args); err != nil {
return err
}
if err := o.Execute(); err != nil {
return err
}
return nil
},
}
// Add the scale flag
cmd.Flags().BoolVar(&o.scale, "scale", o.scale, "if true, scale the operator deployment appropriately")
o.configFlags.AddFlags(cmd.Flags())
return cmd
}
// mergeArgs takes the user supplied arguments/flags and merges them into the ClusterOperatorOptions struct.
func (o *ClusterOperatorOptions) mergeArgs(c *cobra.Command, args []string) error {
argCount := len(args)
if argCount != 2 {
return fmt.Errorf("expected exactly two arguments, got %d", argCount)
}
o.scale, _ = c.Flags().GetBool("scale")
state := args[0]
if err := o.setManagementState(state); err != nil {
return err
}
co := args[1]
if err := o.setClusterOperatorTarget(co); err != nil {
return err
}
return nil
}
func (o *ClusterOperatorOptions) setManagementState(state string) error {
if state != MANAGED_STATE && state != UNMANAGED_STATE {
return fmt.Errorf("wanted %s or %s, got %s", MANAGED_STATE, UNMANAGED_STATE, o.state)
}
if state == MANAGED_STATE {
o.unmanaged = false
}
if state == UNMANAGED_STATE {
o.unmanaged = true
}
return nil
}
func (o *ClusterOperatorOptions) setClusterOperatorTarget(co string) error {
o.clusteroperator = co
return nil
}
func (o *ClusterOperatorOptions) Execute() error {
cl := o.newRESTClient()
body := buildRequestBody(o.clusteroperator, o.unmanaged)
req := buildRequest(body, cl)
// Execute the patch
res := req.Do(context.TODO())
if err := res.Error(); err != nil {
return err
}
return nil
}
func (o *ClusterOperatorOptions) newRESTClient() rest.Interface {
// Get the config
config, _ := o.configFlags.ToRESTConfig()
// Create a client
clientSet, _ := kubernetes.NewForConfig(config)
return clientSet.RESTClient()
}
// buildRequestBody takes the shortname of a cluster operator (e.g. "dns")
// and builds the request body.
func buildRequestBody(clusterOperatorName string, unmanaged bool) []byte {
con := clusterOperatorName
u := unmanaged
reqBody := fmt.Sprintf(`[{"op":"add","path":"/spec/overrides","value":[{"kind":"Deployment","group":"apps/v1","name":"%s-operator","namespace":"openshift-%s-operator","unmanaged":%t}]}]`, con, con, u)
return []byte(reqBody)
}
func buildRequest(requestBody []byte, restClient rest.Interface) *rest.Request {
rb := requestBody
cl := restClient
return cl.Patch("application/json-patch+json").Body(rb).RequestURI("/apis/config.openshift.io/v1/clusterversions/version")
}