This repository has been archived by the owner on Oct 12, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
labelsync.go
136 lines (122 loc) · 5.28 KB
/
labelsync.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
package labelsync
import (
"errors"
"fmt"
"github.com/Azure/go-autorest/autorest/to"
"github.com/go-logr/logr"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/tools/record"
azrsrc "github.com/Azure/node-label-operator/azure/computeresource"
"github.com/Azure/node-label-operator/labelsync/naming"
"github.com/Azure/node-label-operator/labelsync/options"
)
// return patch with new labels, if any, otherwise return nil for no new labels or an error
func TagsToNodes(namespacedName types.NamespacedName, computeResource azrsrc.ComputeResource,
node *corev1.Node, configOptions *options.ConfigOptions, log logr.Logger, recorder record.EventRecorder) ([]byte, error) {
newLabels := map[string]*string{} // should allow for null JSON values
for tagName, tagVal := range computeResource.Tags() {
if !naming.ValidLabelName(tagName) {
log.V(0).Info("invalid label name", "tag name", tagName)
continue
}
if !naming.ValidLabelVal(*tagVal) {
log.V(0).Info("invalid label value", "tag value", *tagVal)
continue
}
validLabelName := naming.ConvertTagNameToValidLabelName(tagName, configOptions.LabelPrefix)
labelVal, ok := node.Labels[validLabelName]
if !ok {
// add tag as label
log.V(1).Info("applying tags to nodes", "tag name", tagName, "tag value", *tagVal)
newLabels[validLabelName] = tagVal
} else if labelVal != *tagVal {
switch configOptions.ConflictPolicy {
case options.ARMPrecedence:
// set label anyway
log.V(1).Info("overriding existing node label with ARM tag", "tag name", tagName, "tag value", tagVal)
newLabels[validLabelName] = tagVal
case options.NodePrecedence:
// do nothing
log.V(0).Info("name->value conflict found", "node label value", labelVal, "ARM tag value", *tagVal)
case options.Ignore:
// raise k8s event
recorder.Event(node, "Warning", "ConflictingTagLabelValues",
fmt.Sprintf("ARM tag was not applied to node because a different value for '%s' already exists (%s != %s).", tagName, *tagVal, labelVal))
log.V(0).Info("name->value conflict found, leaving unchanged", "label value", labelVal, "tag value", *tagVal)
default:
return nil, errors.New("unrecognized conflict policy")
}
}
}
// delete labels if tag has been deleted
// if conflict policy is node precedence (which it will most likely not be), then don't delete tags if they exist on node
if labelDeletionAllowed(configOptions) {
for labelFullName, labelVal := range node.Labels {
if naming.HasLabelPrefix(labelFullName, configOptions.LabelPrefix) {
// check if exists on vm/vmss
labelName := naming.LabelWithoutPrefix(labelFullName, configOptions.LabelPrefix)
_, ok := computeResource.Tags()[labelName]
if !ok { // if label doesn't exist on ARM resource, delete
log.V(1).Info("deleting label from node", "label name", labelFullName, "label value", labelVal)
delete(node.Labels, labelFullName) // for some reason this is needed
newLabels[labelFullName] = nil // this should becomes 'null' in JSON, necessary for merge patch
}
}
}
}
if len(newLabels) == 0 { // to avoid unnecessary patching
return nil, nil
}
patch, err := LabelPatchWithDelete(newLabels)
if err != nil {
return nil, err
}
return patch, nil
}
func LabelsToAzureResource(namespacedName types.NamespacedName, computeResource azrsrc.ComputeResource,
node *corev1.Node, configOptions *options.ConfigOptions, log logr.Logger, recorder record.EventRecorder) (map[string]*string, error) {
if len(computeResource.Tags()) >= naming.MaxNumTags {
log.V(0).Info("can't add any more tags", "number of tags", len(computeResource.Tags()))
return computeResource.Tags(), nil
}
newTags := map[string]*string{}
for labelName, labelVal := range node.Labels {
if !naming.ValidTagName(labelName, configOptions.LabelPrefix) {
log.V(2).Info("invalid tag name", "label name", labelName)
continue
}
if !naming.ValidTagVal(labelVal) {
log.V(2).Info("invalid tag name", "label name", labelName)
continue
}
validTagName := naming.ConvertLabelNameToValidTagName(labelName, configOptions.LabelPrefix)
tagVal, ok := computeResource.Tags()[validTagName]
if !ok {
// add label as tag
log.V(1).Info("applying labels to Azure resource", "label name", labelName, "label value", labelVal)
newTags[validTagName] = to.StringPtr(labelVal)
} else if *tagVal != labelVal {
switch configOptions.ConflictPolicy {
case options.NodePrecedence:
// set tag anyway
log.V(1).Info("overriding existing ARM tag with node label", "label name", labelName, "label value", labelVal)
newTags[validTagName] = to.StringPtr(labelVal)
case options.ARMPrecedence:
// do nothing
log.V(0).Info("name->value conflict found", "node label value", labelVal, "ARM tag value", *tagVal)
case options.Ignore:
// raise k8s event
recorder.Event(node, "Warning", "ConflictingTagLabelValues",
fmt.Sprintf("node label was not applied to Azure resource because a different value for '%s' already exists (%s != %s).", labelName, labelVal, *tagVal))
log.V(0).Info("name->value conflict found, leaving unchanged", "label value", labelVal, "tag value", *tagVal)
default:
return nil, errors.New("unrecognized conflict policy")
}
}
}
if len(newTags) == 0 { // if unchanged
return nil, nil
}
return newTags, nil
}