...
1
16
17 package drain
18
19 import (
20 "context"
21 "fmt"
22
23 corev1 "k8s.io/api/core/v1"
24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
25 "k8s.io/apimachinery/pkg/runtime"
26 "k8s.io/apimachinery/pkg/runtime/schema"
27
28 "k8s.io/apimachinery/pkg/types"
29 "k8s.io/apimachinery/pkg/util/json"
30 "k8s.io/apimachinery/pkg/util/strategicpatch"
31 "k8s.io/client-go/kubernetes"
32 )
33
34
35 type CordonHelper struct {
36 node *corev1.Node
37 desired bool
38 }
39
40
41 func NewCordonHelper(node *corev1.Node) *CordonHelper {
42 return &CordonHelper{
43 node: node,
44 }
45 }
46
47
48
49 func NewCordonHelperFromRuntimeObject(nodeObject runtime.Object, scheme *runtime.Scheme, gvk schema.GroupVersionKind) (*CordonHelper, error) {
50 nodeObject, err := scheme.ConvertToVersion(nodeObject, gvk.GroupVersion())
51 if err != nil {
52 return nil, err
53 }
54
55 node, ok := nodeObject.(*corev1.Node)
56 if !ok {
57 return nil, fmt.Errorf("unexpected type %T", nodeObject)
58 }
59
60 return NewCordonHelper(node), nil
61 }
62
63
64
65 func (c *CordonHelper) UpdateIfRequired(desired bool) bool {
66 c.desired = desired
67
68 return c.node.Spec.Unschedulable != c.desired
69 }
70
71
72
73
74
75 func (c *CordonHelper) PatchOrReplace(clientset kubernetes.Interface, serverDryRun bool) (error, error) {
76 return c.PatchOrReplaceWithContext(context.TODO(), clientset, serverDryRun)
77 }
78
79
80
81 func (c *CordonHelper) PatchOrReplaceWithContext(clientCtx context.Context, clientset kubernetes.Interface, serverDryRun bool) (error, error) {
82 client := clientset.CoreV1().Nodes()
83
84 oldData, err := json.Marshal(c.node)
85 if err != nil {
86 return err, nil
87 }
88
89 c.node.Spec.Unschedulable = c.desired
90
91 newData, err := json.Marshal(c.node)
92 if err != nil {
93 return err, nil
94 }
95
96 patchBytes, patchErr := strategicpatch.CreateTwoWayMergePatch(oldData, newData, c.node)
97 if patchErr == nil {
98 patchOptions := metav1.PatchOptions{}
99 if serverDryRun {
100 patchOptions.DryRun = []string{metav1.DryRunAll}
101 }
102 _, err = client.Patch(clientCtx, c.node.Name, types.StrategicMergePatchType, patchBytes, patchOptions)
103 } else {
104 updateOptions := metav1.UpdateOptions{}
105 if serverDryRun {
106 updateOptions.DryRun = []string{metav1.DryRunAll}
107 }
108 _, err = client.Update(clientCtx, c.node, updateOptions)
109 }
110 return err, patchErr
111 }
112
View as plain text