Skip to content

Merge tags from alb.ingress.kubernetes.io/tags #2480

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/guide/ingress/annotations.md
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,8 @@ The AWS Load Balancer Controller automatically applies following tags to the AWS
In addition, you can use annotations to specify additional tags

- <a name="tags">`alb.ingress.kubernetes.io/tags`</a> specifies additional tags that will be applied to AWS resources created.
In case of target group, the controller will merge the tags from the ingress and the backend service giving precedence
to the values specified on the service when there is conflict.

!!!example
```
Expand Down
17 changes: 11 additions & 6 deletions pkg/ingress/model_build_tags.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,19 @@ func (t *defaultModelBuildTask) buildIngressResourceTags(ing ClassifiedIngress)

// buildIngressBackendResourceTags builds the AWS Tags used for a single Ingress and Backend. e.g. TargetGroup.
// Note: the Tags specified via IngressClass takes higher priority than tags specified via annotation on Ingress or Service.
// the Tags annotation of Service takes higher priority than annotation of Ingress. (TODO: we might consider change this behavior to merge tags instead)
// the target group will have the merged tags specified by the annotations of both Ingress and Service
// the Tags annotation of Service takes higher priority if there is conflict between the tags of Ingress and Service
func (t *defaultModelBuildTask) buildIngressBackendResourceTags(ing ClassifiedIngress, backend *corev1.Service) (map[string]string, error) {
mergedAnnotations := algorithm.MergeStringMap(backend.Annotations, ing.Ing.Annotations)
var annotationTags map[string]string
if _, err := t.annotationParser.ParseStringMapAnnotation(annotations.IngressSuffixTags, &annotationTags, mergedAnnotations); err != nil {
var backendAnnotationTags map[string]string
var ingressAnnotationTags map[string]string
if _, err := t.annotationParser.ParseStringMapAnnotation(annotations.IngressSuffixTags, &backendAnnotationTags, backend.Annotations); err != nil {
return nil, err
}
if err := t.validateTagCollisionWithExternalManagedTags(annotationTags); err != nil {
if _, err := t.annotationParser.ParseStringMapAnnotation(annotations.IngressSuffixTags, &ingressAnnotationTags, ing.Ing.Annotations); err != nil {
return nil, err
}
mergedAnnotationTags := algorithm.MergeStringMap(backendAnnotationTags, ingressAnnotationTags)
if err := t.validateTagCollisionWithExternalManagedTags(mergedAnnotationTags); err != nil {
return nil, errors.Wrapf(err, "failed build tags for Ingress %v and Service %v",
k8s.NamespacedName(ing.Ing).String(), k8s.NamespacedName(backend).String())
}
Expand All @@ -66,7 +71,7 @@ func (t *defaultModelBuildTask) buildIngressBackendResourceTags(ing ClassifiedIn
return nil, err
}

return algorithm.MergeStringMap(ingClassTags, annotationTags), nil
return algorithm.MergeStringMap(ingClassTags, mergedAnnotationTags), nil
}

// buildIngressClassResourceTags builds the AWS Tags for a IngressClass.
Expand Down
54 changes: 54 additions & 0 deletions pkg/ingress/model_build_tags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ func Test_defaultModelBuildTask_buildIngressBackendResourceTags(t *testing.T) {
want: map[string]string{
"tag-c": "value-c1",
"tag-d": "value-d1",
"tag-e": "value-e",
},
},
{
Expand Down Expand Up @@ -403,6 +404,59 @@ func Test_defaultModelBuildTask_buildIngressBackendResourceTags(t *testing.T) {
"tag-e": "value-e",
},
},
{
name: "non-empty annotation tags from Ingress and Service, non-empty IngressClass tags",
fields: fields{
externalManagedTags: sets.NewString("tag-a", "tag-b"),
},
args: args{
ing: ClassifiedIngress{
Ing: &networking.Ingress{
ObjectMeta: metav1.ObjectMeta{
Namespace: "awesome-ns",
Name: "awesome-ing",
Annotations: map[string]string{
"alb.ingress.kubernetes.io/tags": "tag-c=value-c,tag-d=value-d, tag-f=value-f",
},
},
},
IngClassConfig: ClassConfiguration{
IngClassParams: &elbv2api.IngressClassParams{
ObjectMeta: metav1.ObjectMeta{
Name: "awesome-class",
},
Spec: elbv2api.IngressClassParamsSpec{
Tags: []elbv2api.Tag{
{
Key: "tag-d",
Value: "value-d1",
},
{
Key: "tag-e",
Value: "value-e",
},
},
},
},
},
},
backend: &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Namespace: "awesome-ns",
Name: "awesome-svc",
Annotations: map[string]string{
"alb.ingress.kubernetes.io/tags": "tag-c=value-c,tag-d=value-d2",
},
},
},
},
want: map[string]string{
"tag-c": "value-c",
"tag-d": "value-d1",
"tag-e": "value-e",
"tag-f": "value-f",
},
},
{
name: "empty tags from Ingress & Service, empty tags from IngressClass",
fields: fields{
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/ingress/multi_path_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ func (s *multiPathBackendStack) buildIngressResource(ns *corev1.Namespace, ingID
backendSVC := svcByBackendID[pathCFG.BackendID]
exact := networking.PathTypeExact
ing.Spec.Rules[0].HTTP.Paths = append(ing.Spec.Rules[0].HTTP.Paths, networking.HTTPIngressPath{
Path: pathCFG.Path,
Path: pathCFG.Path,
PathType: &exact,
Backend: networking.IngressBackend{
Service: &networking.IngressServiceBackend{
Expand Down