/
node_updator.go
97 lines (80 loc) · 2.19 KB
/
node_updator.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
package lvmetrics
import (
"bytes"
"strconv"
"github.com/cybozu-go/log"
"github.com/cybozu-go/topolvm"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer/json"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/strategicpatch"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"
)
var resourceEncoder runtime.Encoder = json.NewSerializer(json.DefaultMetaFactory, scheme.Scheme, scheme.Scheme, false)
func encodeToJSON(obj runtime.Object) ([]byte, error) {
buf := &bytes.Buffer{}
err := resourceEncoder.Encode(obj, buf)
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// NodePatcher patches node annotations
type NodePatcher struct {
k8sClient *kubernetes.Clientset
nodeName string
}
// NodeMetrics represents nodes metrics
type NodeMetrics struct {
FreeBytes uint64
}
// Annotate adds annotations to node
func (n *NodeMetrics) Annotate(node *corev1.Node) {
node.Annotations[topolvm.CapacityKey] = strconv.FormatUint(n.FreeBytes, 10)
}
// NewNodePatcher creates NodePatcher
func NewNodePatcher(nodeName string) (*NodePatcher, error) {
config, err := rest.InClusterConfig()
if err != nil {
return nil, err
}
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
return nil, err
}
return &NodePatcher{clientset, nodeName}, nil
}
// Patch updates node annotations with patch
func (n *NodePatcher) Patch(met *NodeMetrics) error {
node, err := n.k8sClient.CoreV1().Nodes().Get(n.nodeName, metav1.GetOptions{})
if err != nil {
return err
}
original, err := encodeToJSON(node)
if err != nil {
return err
}
met.Annotate(node)
modified, err := encodeToJSON(node)
if err != nil {
return err
}
if bytes.Equal(original, modified) {
log.Debug("no diff", nil)
return nil
}
patch, err := strategicpatch.CreateTwoWayMergePatch(original, modified, node)
if err != nil {
return err
}
log.Info("update annotations", map[string]interface{}{
"node": n.nodeName,
"capacity": met.FreeBytes,
})
_, err = n.k8sClient.CoreV1().Nodes().Patch(n.nodeName, types.StrategicMergePatchType, patch)
return err
}