Skip to content

Commit 57c8ce3

Browse files
authored
Merge pull request #1976 from M00nF1sh/tag_ingClass
add support for tags in ingressClassParams
2 parents bbdd209 + 9565dda commit 57c8ce3

17 files changed

+1086
-232
lines changed

apis/elbv2/v1beta1/ingressclassparams_types.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,15 @@ type IngressGroup struct {
4747
Name string `json:"name"`
4848
}
4949

50+
// Tag defines a AWS Tag on resources.
51+
type Tag struct {
52+
// The key of the tag.
53+
Key string `json:"key"`
54+
55+
// The value of the tag.
56+
Value string `json:"value"`
57+
}
58+
5059
// IngressClassParamsSpec defines the desired state of IngressClassParams
5160
type IngressClassParamsSpec struct {
5261
// NamespaceSelector restrict the namespaces of Ingresses that are allowed to specify the IngressClass with this IngressClassParams.
@@ -65,6 +74,9 @@ type IngressClassParamsSpec struct {
6574
// IPAddressType defines the ip address type for all Ingresses that belong to IngressClass with this IngressClassParams.
6675
// +optional
6776
IPAddressType *IPAddressType `json:"ipAddressType,omitempty"`
77+
78+
// Tags defines list of Tags on AWS resources provisioned for Ingresses that belong to IngressClass with this IngressClassParams.
79+
Tags []Tag `json:"tags,omitempty"`
6880
}
6981

7082
// +kubebuilder:object:root=true

apis/elbv2/v1beta1/zz_generated.deepcopy.go

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/elbv2.k8s.aws_ingressclassparams.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,23 @@ spec:
103103
- internal
104104
- internet-facing
105105
type: string
106+
tags:
107+
description: Tags defines list of Tags on AWS resources provisioned
108+
for Ingresses that belong to IngressClass with this IngressClassParams.
109+
items:
110+
description: Tag defines a AWS Tag on resources.
111+
properties:
112+
key:
113+
description: The key of the tag.
114+
type: string
115+
value:
116+
description: The value of the tag.
117+
type: string
118+
required:
119+
- key
120+
- value
121+
type: object
122+
type: array
106123
type: object
107124
type: object
108125
version: v1beta1

config/crd/bases/elbv2.k8s.aws_targetgroupbindings.yaml

Lines changed: 104 additions & 39 deletions
Large diffs are not rendered by default.

pkg/ingress/model_build_actions.go

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,17 @@ import (
66
awssdk "github.com/aws/aws-sdk-go/aws"
77
"github.com/pkg/errors"
88
corev1 "k8s.io/api/core/v1"
9-
networking "k8s.io/api/networking/v1beta1"
109
"k8s.io/apimachinery/pkg/types"
1110
"sigs.k8s.io/aws-load-balancer-controller/pkg/model/core"
1211
elbv2model "sigs.k8s.io/aws-load-balancer-controller/pkg/model/elbv2"
1312
"strings"
1413
"unicode"
1514
)
1615

17-
func (t *defaultModelBuildTask) buildActions(ctx context.Context, protocol elbv2model.Protocol, ing *networking.Ingress, backend EnhancedBackend) ([]elbv2model.Action, error) {
16+
func (t *defaultModelBuildTask) buildActions(ctx context.Context, protocol elbv2model.Protocol, ing ClassifiedIngress, backend EnhancedBackend) ([]elbv2model.Action, error) {
1817
var actions []elbv2model.Action
1918
if protocol == elbv2model.ProtocolHTTPS {
20-
authAction, err := t.buildAuthAction(ctx, ing, backend)
19+
authAction, err := t.buildAuthAction(ctx, ing.Ing.Namespace, backend)
2120
if err != nil {
2221
return nil, err
2322
}
@@ -33,7 +32,7 @@ func (t *defaultModelBuildTask) buildActions(ctx context.Context, protocol elbv2
3332
return actions, nil
3433
}
3534

36-
func (t *defaultModelBuildTask) buildBackendAction(ctx context.Context, ing *networking.Ingress, actionCfg Action) (elbv2model.Action, error) {
35+
func (t *defaultModelBuildTask) buildBackendAction(ctx context.Context, ing ClassifiedIngress, actionCfg Action) (elbv2model.Action, error) {
3736
switch actionCfg.Type {
3837
case ActionTypeFixedResponse:
3938
return t.buildFixedResponseAction(ctx, actionCfg)
@@ -45,7 +44,7 @@ func (t *defaultModelBuildTask) buildBackendAction(ctx context.Context, ing *net
4544
return elbv2model.Action{}, errors.Errorf("unknown action type: %v", actionCfg.Type)
4645
}
4746

48-
func (t *defaultModelBuildTask) buildAuthAction(ctx context.Context, ing *networking.Ingress, backend EnhancedBackend) (*elbv2model.Action, error) {
47+
func (t *defaultModelBuildTask) buildAuthAction(ctx context.Context, namespace string, backend EnhancedBackend) (*elbv2model.Action, error) {
4948
authCfg := backend.AuthConfig
5049
switch authCfg.Type {
5150
case AuthTypeCognito:
@@ -55,7 +54,7 @@ func (t *defaultModelBuildTask) buildAuthAction(ctx context.Context, ing *networ
5554
}
5655
return &action, nil
5756
case AuthTypeOIDC:
58-
action, err := t.buildAuthenticateOIDCAction(ctx, authCfg, ing.Namespace)
57+
action, err := t.buildAuthenticateOIDCAction(ctx, namespace, authCfg)
5958
if err != nil {
6059
return nil, err
6160
}
@@ -96,7 +95,7 @@ func (t *defaultModelBuildTask) buildRedirectAction(_ context.Context, actionCfg
9695
}, nil
9796
}
9897

99-
func (t *defaultModelBuildTask) buildForwardAction(ctx context.Context, ing *networking.Ingress, actionCfg Action) (elbv2model.Action, error) {
98+
func (t *defaultModelBuildTask) buildForwardAction(ctx context.Context, ing ClassifiedIngress, actionCfg Action) (elbv2model.Action, error) {
10099
if actionCfg.ForwardConfig == nil {
101100
return elbv2model.Action{}, errors.New("missing ForwardConfig")
102101
}
@@ -108,7 +107,7 @@ func (t *defaultModelBuildTask) buildForwardAction(ctx context.Context, ing *net
108107
tgARN = core.LiteralStringToken(*tgt.TargetGroupARN)
109108
} else {
110109
svcKey := types.NamespacedName{
111-
Namespace: ing.Namespace,
110+
Namespace: ing.Ing.Namespace,
112111
Name: awssdk.StringValue(tgt.ServiceName),
113112
}
114113
svc := t.backendServices[svcKey]
@@ -160,7 +159,7 @@ func (t *defaultModelBuildTask) buildAuthenticateCognitoAction(_ context.Context
160159
}, nil
161160
}
162161

163-
func (t *defaultModelBuildTask) buildAuthenticateOIDCAction(ctx context.Context, authCfg AuthConfig, namespace string) (elbv2model.Action, error) {
162+
func (t *defaultModelBuildTask) buildAuthenticateOIDCAction(ctx context.Context, namespace string, authCfg AuthConfig) (elbv2model.Action, error) {
164163
if authCfg.IDPConfigOIDC == nil {
165164
return elbv2model.Action{}, errors.New("missing IDPConfigOIDC")
166165
}

pkg/ingress/model_build_actions_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ func Test_defaultModelBuildTask_buildAuthenticateOIDCAction(t *testing.T) {
238238
task := &defaultModelBuildTask{
239239
k8sClient: k8sClient,
240240
}
241-
got, err := task.buildAuthenticateOIDCAction(context.Background(), tt.args.authCfg, tt.args.namespace)
241+
got, err := task.buildAuthenticateOIDCAction(context.Background(), tt.args.namespace, tt.args.authCfg)
242242
if tt.wantErr != nil {
243243
assert.EqualError(t, err, tt.wantErr.Error())
244244
} else {

pkg/ingress/model_build_listener.go

Lines changed: 16 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import (
1919
elbv2model "sigs.k8s.io/aws-load-balancer-controller/pkg/model/elbv2"
2020
)
2121

22-
func (t *defaultModelBuildTask) buildListener(ctx context.Context, lbARN core.StringToken, port int64, config listenPortConfig, ingList []*networking.Ingress) (*elbv2model.Listener, error) {
22+
func (t *defaultModelBuildTask) buildListener(ctx context.Context, lbARN core.StringToken, port int64, config listenPortConfig, ingList []ClassifiedIngress) (*elbv2model.Listener, error) {
2323
lsSpec, err := t.buildListenerSpec(ctx, lbARN, port, config, ingList)
2424
if err != nil {
2525
return nil, err
@@ -29,12 +29,12 @@ func (t *defaultModelBuildTask) buildListener(ctx context.Context, lbARN core.St
2929
return ls, nil
3030
}
3131

32-
func (t *defaultModelBuildTask) buildListenerSpec(ctx context.Context, lbARN core.StringToken, port int64, config listenPortConfig, ingList []*networking.Ingress) (elbv2model.ListenerSpec, error) {
32+
func (t *defaultModelBuildTask) buildListenerSpec(ctx context.Context, lbARN core.StringToken, port int64, config listenPortConfig, ingList []ClassifiedIngress) (elbv2model.ListenerSpec, error) {
3333
defaultActions, err := t.buildListenerDefaultActions(ctx, config.protocol, ingList)
3434
if err != nil {
3535
return elbv2model.ListenerSpec{}, err
3636
}
37-
tags, err := t.modelBuildListenerTags(ctx, ingList)
37+
tags, err := t.buildListenerTags(ctx, ingList)
3838
if err != nil {
3939
return elbv2model.ListenerSpec{}, err
4040
}
@@ -55,14 +55,14 @@ func (t *defaultModelBuildTask) buildListenerSpec(ctx context.Context, lbARN cor
5555
}, nil
5656
}
5757

58-
func (t *defaultModelBuildTask) buildListenerDefaultActions(ctx context.Context, protocol elbv2model.Protocol, ingList []*networking.Ingress) ([]elbv2model.Action, error) {
58+
func (t *defaultModelBuildTask) buildListenerDefaultActions(ctx context.Context, protocol elbv2model.Protocol, ingList []ClassifiedIngress) ([]elbv2model.Action, error) {
5959
if t.sslRedirectConfig != nil && protocol == elbv2model.ProtocolHTTP {
6060
return []elbv2model.Action{t.buildSSLRedirectAction(ctx, *t.sslRedirectConfig)}, nil
6161
}
6262

63-
ingsWithDefaultBackend := make([]*networking.Ingress, 0, len(ingList))
63+
ingsWithDefaultBackend := make([]ClassifiedIngress, 0, len(ingList))
6464
for _, ing := range ingList {
65-
if ing.Spec.Backend != nil {
65+
if ing.Ing.Spec.Backend != nil {
6666
ingsWithDefaultBackend = append(ingsWithDefaultBackend, ing)
6767
}
6868
}
@@ -73,12 +73,12 @@ func (t *defaultModelBuildTask) buildListenerDefaultActions(ctx context.Context,
7373
if len(ingsWithDefaultBackend) > 1 {
7474
ingKeys := make([]types.NamespacedName, 0, len(ingsWithDefaultBackend))
7575
for _, ing := range ingsWithDefaultBackend {
76-
ingKeys = append(ingKeys, k8s.NamespacedName(ing))
76+
ingKeys = append(ingKeys, k8s.NamespacedName(ing.Ing))
7777
}
7878
return nil, errors.Errorf("multiple ingress defined default backend: %v", ingKeys)
7979
}
8080
ing := ingsWithDefaultBackend[0]
81-
enhancedBackend, err := t.enhancedBackendBuilder.Build(ctx, ing, *ing.Spec.Backend,
81+
enhancedBackend, err := t.enhancedBackendBuilder.Build(ctx, ing.Ing, *ing.Ing.Spec.Backend,
8282
WithLoadBackendServices(true, t.backendServices),
8383
WithLoadAuthConfig(true))
8484
if err != nil {
@@ -87,6 +87,14 @@ func (t *defaultModelBuildTask) buildListenerDefaultActions(ctx context.Context,
8787
return t.buildActions(ctx, protocol, ing, enhancedBackend)
8888
}
8989

90+
func (t *defaultModelBuildTask) buildListenerTags(_ context.Context, ingList []ClassifiedIngress) (map[string]string, error) {
91+
ingGroupTags, err := t.buildIngressGroupResourceTags(ingList)
92+
if err != nil {
93+
return nil, err
94+
}
95+
return algorithm.MergeStringMap(t.defaultTags, ingGroupTags), nil
96+
}
97+
9098
// the listen port config for specific listener port.
9199
type listenPortConfig struct {
92100
protocol elbv2model.Protocol
@@ -227,26 +235,3 @@ func (t *defaultModelBuildTask) computeIngressExplicitSSLPolicy(_ context.Contex
227235
}
228236
return &rawSSLPolicy
229237
}
230-
231-
func (t *defaultModelBuildTask) modelBuildListenerTags(_ context.Context, ingList []*networking.Ingress) (map[string]string, error) {
232-
annotationTags := make(map[string]string)
233-
for _, ing := range ingList {
234-
var rawTags map[string]string
235-
if _, err := t.annotationParser.ParseStringMapAnnotation(annotations.IngressSuffixTags, &rawTags, ing.Annotations); err != nil {
236-
return nil, err
237-
}
238-
for tagKey, tagValue := range rawTags {
239-
if t.externalManagedTags.Has(tagKey) {
240-
return nil, errors.Errorf("external managed tag key %v cannot be specified on Ingress %v",
241-
tagKey, k8s.NamespacedName(ing).String())
242-
}
243-
244-
if existingTagValue, exists := annotationTags[tagKey]; exists && existingTagValue != tagValue {
245-
return nil, errors.Errorf("conflicting tag %v: %v | %v", tagKey, existingTagValue, tagValue)
246-
}
247-
annotationTags[tagKey] = tagValue
248-
}
249-
}
250-
mergedTags := algorithm.MergeStringMap(t.defaultTags, annotationTags)
251-
return mergedTags, nil
252-
}

pkg/ingress/model_build_listener_rules.go

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,41 +8,40 @@ import (
88
"github.com/pkg/errors"
99
networking "k8s.io/api/networking/v1beta1"
1010
"sigs.k8s.io/aws-load-balancer-controller/pkg/algorithm"
11-
"sigs.k8s.io/aws-load-balancer-controller/pkg/annotations"
1211
"sigs.k8s.io/aws-load-balancer-controller/pkg/k8s"
1312
"sigs.k8s.io/aws-load-balancer-controller/pkg/model/core"
1413
elbv2model "sigs.k8s.io/aws-load-balancer-controller/pkg/model/elbv2"
1514
)
1615

17-
func (t *defaultModelBuildTask) buildListenerRules(ctx context.Context, lsARN core.StringToken, port int64, protocol elbv2model.Protocol, ingList []*networking.Ingress) error {
16+
func (t *defaultModelBuildTask) buildListenerRules(ctx context.Context, lsARN core.StringToken, port int64, protocol elbv2model.Protocol, ingList []ClassifiedIngress) error {
1817
if t.sslRedirectConfig != nil && protocol == elbv2model.ProtocolHTTP {
1918
return nil
2019
}
2120

2221
var rules []Rule
2322
for _, ing := range ingList {
24-
for _, rule := range ing.Spec.Rules {
23+
for _, rule := range ing.Ing.Spec.Rules {
2524
if rule.HTTP == nil {
2625
continue
2726
}
2827
for _, path := range rule.HTTP.Paths {
29-
enhancedBackend, err := t.enhancedBackendBuilder.Build(ctx, ing, path.Backend,
28+
enhancedBackend, err := t.enhancedBackendBuilder.Build(ctx, ing.Ing, path.Backend,
3029
WithLoadBackendServices(true, t.backendServices),
3130
WithLoadAuthConfig(true))
3231
if err != nil {
33-
return errors.Wrapf(err, "ingress: %v", k8s.NamespacedName(ing))
32+
return errors.Wrapf(err, "ingress: %v", k8s.NamespacedName(ing.Ing))
3433
}
3534
conditions, err := t.buildRuleConditions(ctx, rule, path, enhancedBackend)
3635
if err != nil {
37-
return errors.Wrapf(err, "ingress: %v", k8s.NamespacedName(ing))
36+
return errors.Wrapf(err, "ingress: %v", k8s.NamespacedName(ing.Ing))
3837
}
3938
actions, err := t.buildActions(ctx, protocol, ing, enhancedBackend)
4039
if err != nil {
41-
return errors.Wrapf(err, "ingress: %v", k8s.NamespacedName(ing))
40+
return errors.Wrapf(err, "ingress: %v", k8s.NamespacedName(ing.Ing))
4241
}
43-
tags, err := t.modelBuildListenerRuleTags(ctx, ing)
42+
tags, err := t.buildListenerRuleTags(ctx, ing)
4443
if err != nil {
45-
return errors.Wrapf(err, "ingress: %v", k8s.NamespacedName(ing))
44+
return errors.Wrapf(err, "ingress: %v", k8s.NamespacedName(ing.Ing))
4645
}
4746
rules = append(rules, Rule{
4847
Conditions: conditions,
@@ -261,17 +260,11 @@ func (t *defaultModelBuildTask) buildPathPatternCondition(_ context.Context, pat
261260
}
262261
}
263262

264-
func (t *defaultModelBuildTask) modelBuildListenerRuleTags(_ context.Context, ing *networking.Ingress) (map[string]string, error) {
265-
var rawTags map[string]string
266-
if _, err := t.annotationParser.ParseStringMapAnnotation(annotations.IngressSuffixTags, &rawTags, ing.Annotations); err != nil {
263+
func (t *defaultModelBuildTask) buildListenerRuleTags(_ context.Context, ing ClassifiedIngress) (map[string]string, error) {
264+
ingTags, err := t.buildIngressResourceTags(ing)
265+
if err != nil {
267266
return nil, err
268267
}
269-
for tagKey := range rawTags {
270-
if t.externalManagedTags.Has(tagKey) {
271-
return nil, errors.Errorf("external managed tag key %v cannot be specified", tagKey)
272-
}
273-
}
274268

275-
mergedTags := algorithm.MergeStringMap(t.defaultTags, rawTags)
276-
return mergedTags, nil
269+
return algorithm.MergeStringMap(t.defaultTags, ingTags), nil
277270
}

pkg/ingress/model_build_load_balancer.go

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -302,26 +302,11 @@ func (t *defaultModelBuildTask) buildLoadBalancerAttributes(_ context.Context) (
302302
}
303303

304304
func (t *defaultModelBuildTask) buildLoadBalancerTags(_ context.Context) (map[string]string, error) {
305-
annotationTags := make(map[string]string)
306-
for _, member := range t.ingGroup.Members {
307-
var rawTags map[string]string
308-
if _, err := t.annotationParser.ParseStringMapAnnotation(annotations.IngressSuffixTags, &rawTags, member.Ing.Annotations); err != nil {
309-
return nil, err
310-
}
311-
for tagKey, tagValue := range rawTags {
312-
if t.externalManagedTags.Has(tagKey) {
313-
return nil, errors.Errorf("external managed tag key %v cannot be specified on Ingress %v",
314-
tagKey, k8s.NamespacedName(member.Ing).String())
315-
}
316-
317-
if existingTagValue, exists := annotationTags[tagKey]; exists && existingTagValue != tagValue {
318-
return nil, errors.Errorf("conflicting tag %v: %v | %v", tagKey, existingTagValue, tagValue)
319-
}
320-
annotationTags[tagKey] = tagValue
321-
}
305+
ingGroupTags, err := t.buildIngressGroupResourceTags(t.ingGroup.Members)
306+
if err != nil {
307+
return nil, err
322308
}
323-
mergedTags := algorithm.MergeStringMap(t.defaultTags, annotationTags)
324-
return mergedTags, nil
309+
return algorithm.MergeStringMap(t.defaultTags, ingGroupTags), nil
325310
}
326311

327312
func (t *defaultModelBuildTask) resolveSecurityGroupIDsViaNameOrIDSlice(ctx context.Context, sgNameOrIDs []string) ([]string, error) {

pkg/ingress/model_build_load_balancer_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ func Test_defaultModelBuildTask_buildLoadBalancerTags(t *testing.T) {
458458
},
459459
externalManagedTags: sets.NewString("k2"),
460460
},
461-
wantErr: errors.New("external managed tag key k2 cannot be specified on Ingress awesome-ns/ing-2"),
461+
wantErr: errors.New("failed build tags for Ingress awesome-ns/ing-2: external managed tag key k2 cannot be specified"),
462462
},
463463
}
464464
for _, tt := range tests {

0 commit comments

Comments
 (0)