Skip to content

Commit cac9d2a

Browse files
committed
feat: Add default tags CLI option [K8SPCORE-1707]
1 parent a8120f7 commit cac9d2a

File tree

4 files changed

+76
-3
lines changed

4 files changed

+76
-3
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,5 @@ bin
2323
*.swp
2424
*.swo
2525
*~
26+
27+
main

controllers/eip_controller.go

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626

2727
corev1 "k8s.io/api/core/v1"
2828
"k8s.io/apimachinery/pkg/types"
29+
"k8s.io/utils/strings/slices"
2930

3031
"github.com/aws/aws-sdk-go/aws"
3132
"github.com/aws/aws-sdk-go/aws/awserr"
@@ -40,6 +41,7 @@ type EIPReconciler struct {
4041
NonCachingClient client.Client
4142
Log logr.Logger
4243
EC2 *ec2.EC2
44+
Tags map[string]string
4345
}
4446

4547
// +kubebuilder:rbac:groups=aws.k8s.logmein.com,resources=eips,verbs=get;list;watch;create;update;patch;delete
@@ -190,6 +192,12 @@ func (r *EIPReconciler) allocateEIP(ctx context.Context, eip *awsv1alpha1.EIP, l
190192
}
191193
}
192194

195+
tags := ec2.TagSpecification{
196+
ResourceType: aws.String("elastic-ip"),
197+
Tags: r.combineDefaultAndDefinedTags(eip),
198+
}
199+
input.TagSpecifications = []*ec2.TagSpecification{&tags}
200+
193201
if resp, err := r.EC2.AllocateAddressWithContext(ctx, input); err != nil {
194202
return err
195203
} else {
@@ -202,7 +210,27 @@ func (r *EIPReconciler) allocateEIP(ctx context.Context, eip *awsv1alpha1.EIP, l
202210
}
203211
}
204212

205-
return r.reconcileTags(ctx, eip, []*ec2.Tag{})
213+
return nil
214+
}
215+
216+
// combineDefaultAndDefinedTags combines the default tags defined in the controller
217+
// with the tags defined in the EIP spec. Tags defined in the EIP spec override
218+
// default tags in case of key conflicts.
219+
func (r EIPReconciler) combineDefaultAndDefinedTags(eip *awsv1alpha1.EIP) []*ec2.Tag {
220+
var tags []*ec2.Tag
221+
for k, v := range r.Tags {
222+
tags = append(tags, &ec2.Tag{
223+
Key: aws.String(k),
224+
Value: aws.String(v),
225+
})
226+
}
227+
for k, v := range *eip.Spec.Tags {
228+
tags = append(tags, &ec2.Tag{
229+
Key: aws.String(k),
230+
Value: aws.String(v),
231+
})
232+
}
233+
return tags
206234
}
207235

208236
func (r *EIPReconciler) reconcileTags(ctx context.Context, eip *awsv1alpha1.EIP, existingTags []*ec2.Tag) error {
@@ -225,6 +253,7 @@ func (r *EIPReconciler) reconcileTags(ctx context.Context, eip *awsv1alpha1.EIP,
225253
tagsToCreate = append(tagsToCreate, &ec2.Tag{Key: aws.String(k), Value: aws.String(v)})
226254
}
227255
}
256+
228257
if len(tagsToCreate) > 0 {
229258
if _, err := r.EC2.CreateTagsWithContext(ctx, &ec2.CreateTagsInput{
230259
Resources: resources,
@@ -234,12 +263,22 @@ func (r *EIPReconciler) reconcileTags(ctx context.Context, eip *awsv1alpha1.EIP,
234263
}
235264
}
236265

266+
convertToStringSlice := func(tags []*ec2.Tag) []string {
267+
var keys []string
268+
for _, tag := range tags {
269+
keys = append(keys, aws.StringValue(tag.Key))
270+
}
271+
return keys
272+
}
273+
combinedTags := convertToStringSlice(r.combineDefaultAndDefinedTags(eip))
274+
237275
var tagsToRemove []*ec2.Tag
238276
for _, tag := range existingTags {
239-
if _, ok := (*eip.Spec.Tags)[aws.StringValue(tag.Key)]; !ok {
277+
if slices.Index(combinedTags, aws.StringValue(tag.Key)) == -1 {
240278
tagsToRemove = append(tagsToRemove, tag)
241279
}
242280
}
281+
243282
if len(tagsToRemove) > 0 {
244283
_, err := r.EC2.DeleteTagsWithContext(ctx, &ec2.DeleteTagsInput{
245284
Resources: resources,

controllers/eni_controller.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ type ENIReconciler struct {
4141
NonCachingClient client.Client
4242
Log logr.Logger
4343
EC2 *ec2.EC2
44+
Tags map[string]string
4445
}
4546

4647
// +kubebuilder:rbac:groups=aws.k8s.logmein.com,resources=enis,verbs=get;list;watch;create;update;patch;delete
@@ -74,6 +75,18 @@ func (r *ENIReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R
7475
if eni.Spec.SecondaryPrivateIPAddressCount > 0 {
7576
input.SecondaryPrivateIpAddressCount = aws.Int64(eni.Spec.SecondaryPrivateIPAddressCount)
7677
}
78+
79+
tags := ec2.TagSpecification{
80+
ResourceType: aws.String("network-interface"),
81+
}
82+
for k, v := range r.Tags {
83+
tags.Tags = append(tags.Tags, &ec2.Tag{
84+
Key: aws.String(k),
85+
Value: aws.String(v),
86+
})
87+
}
88+
input.TagSpecifications = []*ec2.TagSpecification{&tags}
89+
7790
resp, err := r.EC2.CreateNetworkInterface(input)
7891
if err != nil {
7992
return ctrl.Result{}, err

main.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package main
1818
import (
1919
"flag"
2020
"os"
21+
"strings"
2122

2223
"github.com/aws/aws-sdk-go/aws"
2324
"github.com/aws/aws-sdk-go/aws/session"
@@ -45,11 +46,12 @@ func init() {
4546
}
4647

4748
func main() {
48-
var metricsAddr, region, leaderElectionID, leaderElectionNamespace string
49+
var metricsAddr, region, leaderElectionID, leaderElectionNamespace, defaultTags string
4950
flag.StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.")
5051
flag.StringVar(&region, "region", "", "AWS region")
5152
flag.StringVar(&leaderElectionID, "leader-election-id", "k8s-aws-operator", "the name of the configmap do use as leader election lock")
5253
flag.StringVar(&leaderElectionNamespace, "leader-election-namespace", "", "the namespace in which the leader election lock will be held")
54+
flag.StringVar(&defaultTags, "default-tags", "", "default tags to add to created resources, in the format key1=value1,key2=value2")
5355
opts := zap.Options{
5456
Development: true,
5557
}
@@ -90,11 +92,18 @@ func main() {
9092
os.Exit(1)
9193
}
9294

95+
defaultTagsMap := make(map[string]string)
96+
if defaultTags != "" {
97+
parseTags(&defaultTagsMap, defaultTags)
98+
setupLog.Info("Default tags set", "tags", defaultTagsMap)
99+
}
100+
93101
err = (&controllers.EIPReconciler{
94102
Client: cachingClient,
95103
NonCachingClient: nonCachingClient,
96104
Log: ctrl.Log.WithName("controllers").WithName("EIP"),
97105
EC2: ec2,
106+
Tags: defaultTagsMap,
98107
}).SetupWithManager(mgr)
99108
if err != nil {
100109
setupLog.Error(err, "unable to create controller", "controller", "EIP")
@@ -105,6 +114,7 @@ func main() {
105114
NonCachingClient: nonCachingClient,
106115
Log: ctrl.Log.WithName("controllers").WithName("ENI"),
107116
EC2: ec2,
117+
Tags: defaultTagsMap,
108118
}).SetupWithManager(mgr)
109119
if err != nil {
110120
setupLog.Error(err, "unable to create controller", "controller", "ENI")
@@ -126,3 +136,12 @@ func main() {
126136
os.Exit(1)
127137
}
128138
}
139+
140+
func parseTags(tagMap *map[string]string, tags string) {
141+
for _, tag := range strings.Split(tags, ",") {
142+
kv := strings.SplitN(tag, "=", 2)
143+
if len(kv) == 2 {
144+
(*tagMap)[strings.TrimSpace(kv[0])] = strings.TrimSpace(kv[1])
145+
}
146+
}
147+
}

0 commit comments

Comments
 (0)