-
Notifications
You must be signed in to change notification settings - Fork 540
/
awsmachine_tags.go
130 lines (108 loc) · 4.27 KB
/
awsmachine_tags.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
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package controllers
import (
infrav1 "sigs.k8s.io/cluster-api-provider-aws/api/v1alpha3"
service "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services"
)
const (
// TagsLastAppliedAnnotation is the key for the machine object annotation
// which tracks the SecurityGroups that the machine actuator is responsible
// for. These are the SecurityGroups that have been handled by the
// AdditionalTags in the Machine Provider Config.
// See https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/
// for annotation formatting rules.
TagsLastAppliedAnnotation = "sigs.k8s.io/cluster-api-provider-aws-last-applied-tags"
)
// Ensure that the tags of the machine are correct
// Returns bool, error
// Bool indicates if changes were made or not, allowing the caller to decide
// if the machine should be updated.
func (r *AWSMachineReconciler) ensureTags(svc service.EC2MachineInterface, machine *infrav1.AWSMachine, instanceID *string, additionalTags map[string]string) (bool, error) {
annotation, err := r.machineAnnotationJSON(machine, TagsLastAppliedAnnotation)
if err != nil {
return false, err
}
// Check if the instance tags were changed. If they were, update them.
// It would be possible here to only send new/updated tags, but for the
// moment we send everything, even if only a single tag was created or
// upated.
changed, created, deleted, newAnnotation := r.tagsChanged(annotation, additionalTags)
if changed {
err = svc.UpdateResourceTags(instanceID, created, deleted)
if err != nil {
return false, err
}
// We also need to update the annotation if anything changed.
err = r.updateMachineAnnotationJSON(machine, TagsLastAppliedAnnotation, newAnnotation)
if err != nil {
return false, err
}
}
return changed, nil
}
// tagsChanged determines which tags to delete and which to add.
func (r *AWSMachineReconciler) tagsChanged(annotation map[string]interface{}, src map[string]string) (bool, map[string]string, map[string]string, map[string]interface{}) {
// Bool tracking if we found any changed state.
changed := false
// Tracking for created/updated
created := map[string]string{}
// Tracking for tags that were deleted.
deleted := map[string]string{}
// The new annotation that we need to set if anything is created/updated.
newAnnotation := map[string]interface{}{}
// Loop over annotation, checking if entries are in src.
// If an entry is present in annotation but not src, it has been deleted
// since last time. We flag this in the deleted map.
for t, v := range annotation {
_, ok := src[t]
// Entry isn't in src, it has been deleted.
if !ok {
// Cast v to a string here. This should be fine, tags are always
// strings.
deleted[t] = v.(string)
changed = true
}
}
// Loop over src, checking for entries in annotation.
//
// If an entry is in src, but not annotation, it has been created since
// last time.
//
// If an entry is in both src and annotation, we compare their values, if
// the value in src differs from that in annotation, the tag has been
// updated since last time.
for t, v := range src {
av, ok := annotation[t]
// Entries in the src always need to be noted in the newAnnotation. We
// know they're going to be created or updated.
newAnnotation[t] = v
// Entry isn't in annotation, it's new.
if !ok {
created[t] = v
newAnnotation[t] = v
changed = true
continue
}
// Entry is in annotation, has the value changed?
if v != av {
created[t] = v
changed = true
}
// Entry existed in both src and annotation, and their values were
// equal. Nothing to do.
}
// We made it through the loop, and everything that was in src, was also
// in dst. Nothing changed.
return changed, created, deleted, newAnnotation
}