Skip to content

Commit 114bbc1

Browse files
haoucTimothy-Dougherty
authored andcommitted
Adding supports for unweighted target group through feature gate and checking SSL policy availability. (kubernetes-sigs#2380)
* Adding supports for air gapped regions through feature gate. * Updated changes according to comments and changed feature gate to feature gates * Updates for configuration doc * Updated feature gates doc and key name
1 parent f83cc12 commit 114bbc1

File tree

11 files changed

+83
-56
lines changed

11 files changed

+83
-56
lines changed

controllers/ingress/group_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ func NewGroupReconciler(cloud aws.Cloud, k8sClient client.Client, eventRecorder
5151
enhancedBackendBuilder := ingress.NewDefaultEnhancedBackendBuilder(k8sClient, annotationParser, authConfigBuilder)
5252
referenceIndexer := ingress.NewDefaultReferenceIndexer(enhancedBackendBuilder, authConfigBuilder, logger)
5353
trackingProvider := tracking.NewDefaultProvider(ingressTagPrefix, config.ClusterName)
54-
elbv2TaggingManager := elbv2deploy.NewDefaultTaggingManager(cloud.ELBV2(), cloud.VpcID(), config.FeatureGate, logger)
54+
elbv2TaggingManager := elbv2deploy.NewDefaultTaggingManager(cloud.ELBV2(), cloud.VpcID(), config.FeatureGates, logger)
5555
modelBuilder := ingress.NewDefaultModelBuilder(k8sClient, eventRecorder,
5656
cloud.EC2(), cloud.ACM(),
5757
annotationParser, subnetsResolver,

controllers/service/service_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func NewServiceReconciler(cloud aws.Cloud, k8sClient client.Client, eventRecorde
4040

4141
annotationParser := annotations.NewSuffixAnnotationParser(serviceAnnotationPrefix)
4242
trackingProvider := tracking.NewDefaultProvider(serviceTagPrefix, config.ClusterName)
43-
elbv2TaggingManager := elbv2.NewDefaultTaggingManager(cloud.ELBV2(), cloud.VpcID(), config.FeatureGate, logger)
43+
elbv2TaggingManager := elbv2.NewDefaultTaggingManager(cloud.ELBV2(), cloud.VpcID(), config.FeatureGates, logger)
4444
modelBuilder := service.NewDefaultModelBuilder(annotationParser, subnetsResolver, vpcResolver, trackingProvider,
4545
elbv2TaggingManager, config.ClusterName, config.DefaultTags, config.ExternalManagedTags, config.DefaultSSLPolicy)
4646
stackMarshaller := deploy.NewDefaultStackMarshaller()

docs/deploy/configurations.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ Currently, you can set only 1 namespace to watch in this flag. See [this Kuberne
8383
|enable-waf | boolean | true | Enable WAF addon for ALB |
8484
|enable-wafv2 | boolean | true | Enable WAF V2 addon for ALB |
8585
|external-managed-tags | stringList | | AWS Tag keys that will be managed externally. Specified Tags are ignored during reconciliation |
86-
|feature-gate | string | true | A set of key=value pairs to enable or disable features |
86+
|[feature-gates](#feature-gates) | stringMap | | A set of key=value pairs to enable or disable features |
8787
|ingress-class | string | alb | Name of the ingress class this controller satisfies |
8888
|ingress-max-concurrent-reconciles | int | 3 | Maximum number of concurrently running reconcile loops for ingress |
8989
|kubeconfig | string | in-cluster config | Path to the kubeconfig file containing authorization and API server information |
@@ -102,6 +102,7 @@ Currently, you can set only 1 namespace to watch in this flag. See [this Kuberne
102102
|webhook-cert-file | string | tls.crt | The server certificate name |
103103
|webhook-key-file | string | tls.key | The server key name |
104104

105+
105106
### disable-ingress-class-annotation
106107
`--disable-ingress-class-annotation` controls whether to disable new usage of the `kubernetes.io/ingress.class` annotation.
107108

@@ -129,3 +130,12 @@ WAF Regional:^AssociateWebACL|DisassociateWebACL=0.5:1,WAF Regional:^GetWebACLFo
129130
130131
### Instance metadata
131132
If running on EC2, the default values are obtained from the instance metadata service.
133+
134+
135+
### Feature Gates
136+
They are a set of kye=value pairs that describe AWS load balance controller features. You can use it as flags `--feature-gates=key1=value1,key2=value2`
137+
138+
|Features-gate Supported Key | Type | Default Value | Description |
139+
|---------------------------------------|---------------------------------|-----------------|-------------|
140+
|ListenerRulesTagging | string | true | Enable or disable tagging AWS load balancer listeners and rules |
141+
|WeightedTargetGroups | string | true | Enable or disable weighted target groups |

main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ func loadControllerConfig() (config.ControllerConfig, error) {
174174
AWSConfig: aws.CloudConfig{
175175
ThrottleConfig: defaultAWSThrottleCFG,
176176
},
177-
FeatureGate: config.NewFeatureGate(),
177+
FeatureGates: config.NewFeatureGates(),
178178
}
179179

180180
fs := pflag.NewFlagSet("", pflag.ExitOnError)

pkg/config/controller_config.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ type ControllerConfig struct {
9090
// DisableRestrictedSGRules specifies whether to use restricted security group rules
9191
DisableRestrictedSGRules bool
9292

93-
FeatureGate FeatureGate
93+
FeatureGates FeatureGates
9494
}
9595

9696
// BindFlags binds the command line flags to the fields in the config object
@@ -119,7 +119,7 @@ func (cfg *ControllerConfig) BindFlags(fs *pflag.FlagSet) {
119119
fs.BoolVar(&cfg.DisableRestrictedSGRules, flagDisableRestrictedSGRules, defaultDisableRestrictedSGRules,
120120
"Disable the usage of restricted security group rules")
121121

122-
cfg.FeatureGate.BindFlags(fs)
122+
cfg.FeatureGates.BindFlags(fs)
123123
cfg.AWSConfig.BindFlags(fs)
124124
cfg.RuntimeConfig.BindFlags(fs)
125125

pkg/config/feature_gate.go renamed to pkg/config/feature_gates.go

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@ import (
1010
type Feature string
1111

1212
const (
13-
EnableListenerRulesTagging Feature = "enable-listener-rules-tagging"
13+
ListenerRulesTagging Feature = "ListenerRulesTagging"
14+
WeightedTargetGroups Feature = "WeightedTargetGroups"
1415
)
1516

16-
type FeatureGate interface {
17+
type FeatureGates interface {
1718
// Enabled returns whether a feature is enabled
1819
Enabled(feature Feature) bool
1920

@@ -23,43 +24,44 @@ type FeatureGate interface {
2324
// Disable will disable a feature
2425
Disable(feature Feature)
2526

26-
// BindFlags bind featureGate flags
27+
// BindFlags bind featureGates flags
2728
BindFlags(fs *pflag.FlagSet)
2829
}
2930

30-
var _ FeatureGate = (*defaultFeatureGate)(nil)
31-
var _ pflag.Value = (*defaultFeatureGate)(nil)
31+
var _ FeatureGates = (*defaultFeatureGates)(nil)
32+
var _ pflag.Value = (*defaultFeatureGates)(nil)
3233

33-
type defaultFeatureGate struct {
34+
type defaultFeatureGates struct {
3435
featureState map[Feature]bool
3536
}
3637

37-
// NewFeatureGate constructs new featureGate
38-
func NewFeatureGate() FeatureGate {
39-
return &defaultFeatureGate{
38+
// NewFeatureGates constructs new featureGates
39+
func NewFeatureGates() FeatureGates {
40+
return &defaultFeatureGates{
4041
featureState: map[Feature]bool{
41-
EnableListenerRulesTagging: true,
42+
ListenerRulesTagging: true,
43+
WeightedTargetGroups: true,
4244
},
4345
}
4446
}
4547

46-
func (f *defaultFeatureGate) BindFlags(fs *pflag.FlagSet) {
47-
fs.Var(f, "feature-gate", "A set of key=bool pairs enable/disable features")
48+
func (f *defaultFeatureGates) BindFlags(fs *pflag.FlagSet) {
49+
fs.Var(f, "feature-gates", "A set of key=bool pairs enable/disable features")
4850
}
4951

50-
func (f *defaultFeatureGate) Enabled(feature Feature) bool {
52+
func (f *defaultFeatureGates) Enabled(feature Feature) bool {
5153
return f.featureState[feature]
5254
}
5355

54-
func (f *defaultFeatureGate) Enable(feature Feature) {
56+
func (f *defaultFeatureGates) Enable(feature Feature) {
5557
f.featureState[feature] = true
5658
}
5759

58-
func (f *defaultFeatureGate) Disable(feature Feature) {
60+
func (f *defaultFeatureGates) Disable(feature Feature) {
5961
f.featureState[feature] = false
6062
}
6163

62-
func (f *defaultFeatureGate) String() string {
64+
func (f *defaultFeatureGates) String() string {
6365
var featureSettings []string
6466
for feature, enabled := range f.featureState {
6567
featureSettings = append(featureSettings, fmt.Sprintf("%v=%v", feature, enabled))
@@ -68,7 +70,7 @@ func (f *defaultFeatureGate) String() string {
6870
}
6971

7072
// SplitMapStringBool parse comma-separated string of key1=value1,key2=value2. value is either true or false
71-
func (f *defaultFeatureGate) SplitMapStringBool(str string) (map[string]bool, error) {
73+
func (f *defaultFeatureGates) SplitMapStringBool(str string) (map[string]bool, error) {
7274
result := make(map[string]bool)
7375
for _, s := range strings.Split(str, ",") {
7476
if len(s) == 0 {
@@ -88,10 +90,10 @@ func (f *defaultFeatureGate) SplitMapStringBool(str string) (map[string]bool, er
8890
return result, nil
8991
}
9092

91-
func (f *defaultFeatureGate) Set(value string) error {
93+
func (f *defaultFeatureGates) Set(value string) error {
9294
settings, err := f.SplitMapStringBool(value)
9395
if err != nil {
94-
return fmt.Errorf("failed to parse feature-gate settings due to %v", err)
96+
return fmt.Errorf("failed to parse feature-gates settings due to %v", err)
9597
}
9698
for k, v := range settings {
9799
_, ok := f.featureState[Feature(k)]
@@ -103,6 +105,6 @@ func (f *defaultFeatureGate) Set(value string) error {
103105
return nil
104106
}
105107

106-
func (f *defaultFeatureGate) Type() string {
108+
func (f *defaultFeatureGates) Type() string {
107109
return "mapStringBool"
108110
}

pkg/deploy/elbv2/listener_manager.go

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,13 @@ type ListenerManager interface {
2828
}
2929

3030
func NewDefaultListenerManager(elbv2Client services.ELBV2, trackingProvider tracking.Provider,
31-
taggingManager TaggingManager, externalManagedTags []string, featureGate config.FeatureGate, logger logr.Logger) *defaultListenerManager {
31+
taggingManager TaggingManager, externalManagedTags []string, featureGates config.FeatureGates, logger logr.Logger) *defaultListenerManager {
3232
return &defaultListenerManager{
3333
elbv2Client: elbv2Client,
3434
trackingProvider: trackingProvider,
3535
taggingManager: taggingManager,
3636
externalManagedTags: externalManagedTags,
37-
featureGate: featureGate,
37+
featureGates: featureGates,
3838
logger: logger,
3939
waitLSExistencePollInterval: defaultWaitLSExistencePollInterval,
4040
waitLSExistenceTimeout: defaultWaitLSExistenceTimeout,
@@ -49,20 +49,20 @@ type defaultListenerManager struct {
4949
trackingProvider tracking.Provider
5050
taggingManager TaggingManager
5151
externalManagedTags []string
52-
featureGate config.FeatureGate
52+
featureGates config.FeatureGates
5353
logger logr.Logger
5454

5555
waitLSExistencePollInterval time.Duration
5656
waitLSExistenceTimeout time.Duration
5757
}
5858

5959
func (m *defaultListenerManager) Create(ctx context.Context, resLS *elbv2model.Listener) (elbv2model.ListenerStatus, error) {
60-
req, err := buildSDKCreateListenerInput(resLS.Spec)
60+
req, err := buildSDKCreateListenerInput(resLS.Spec, m.featureGates)
6161
if err != nil {
6262
return elbv2model.ListenerStatus{}, err
6363
}
6464
var lsTags map[string]string
65-
if m.featureGate.Enabled(config.EnableListenerRulesTagging) {
65+
if m.featureGates.Enabled(config.ListenerRulesTagging) {
6666
lsTags = m.trackingProvider.ResourceTags(resLS.Stack(), resLS, resLS.Spec.Tags)
6767
}
6868
req.Tags = convertTagsToSDKTags(lsTags)
@@ -92,7 +92,7 @@ func (m *defaultListenerManager) Create(ctx context.Context, resLS *elbv2model.L
9292
}
9393

9494
func (m *defaultListenerManager) Update(ctx context.Context, resLS *elbv2model.Listener, sdkLS ListenerWithTags) (elbv2model.ListenerStatus, error) {
95-
if m.featureGate.Enabled(config.EnableListenerRulesTagging) {
95+
if m.featureGates.Enabled(config.ListenerRulesTagging) {
9696
if err := m.updateSDKListenerWithTags(ctx, resLS, sdkLS); err != nil {
9797
return elbv2model.ListenerStatus{}, err
9898
}
@@ -128,7 +128,7 @@ func (m *defaultListenerManager) updateSDKListenerWithTags(ctx context.Context,
128128
}
129129

130130
func (m *defaultListenerManager) updateSDKListenerWithSettings(ctx context.Context, resLS *elbv2model.Listener, sdkLS ListenerWithTags) error {
131-
desiredDefaultActions, err := buildSDKActions(resLS.Spec.DefaultActions)
131+
desiredDefaultActions, err := buildSDKActions(resLS.Spec.DefaultActions, m.featureGates)
132132
if err != nil {
133133
return err
134134
}
@@ -156,6 +156,12 @@ func (m *defaultListenerManager) updateSDKListenerWithSettings(ctx context.Conte
156156
// currentExtraCertificates is the current extra certificates, if it's nil, the current extra certificates will be fetched from AWS.
157157
func (m *defaultListenerManager) updateSDKListenerWithExtraCertificates(ctx context.Context, resLS *elbv2model.Listener,
158158
sdkLS ListenerWithTags, isNewSDKListener bool) error {
159+
// if TLS is not supported, we shouldn't update
160+
if sdkLS.Listener.SslPolicy == nil {
161+
m.logger.V(1).Info("SDK Listner doesn't have SSL Policy set, we skip updating extra certs for non-TLS listener.")
162+
return nil
163+
}
164+
159165
desiredExtraCertARNs := sets.NewString()
160166
_, desiredExtraCerts := buildSDKCertificates(resLS.Spec.Certificates)
161167
for _, cert := range desiredExtraCerts {
@@ -262,7 +268,7 @@ func isSDKListenerSettingsDrifted(lsSpec elbv2model.ListenerSpec, sdkLS Listener
262268
return false
263269
}
264270

265-
func buildSDKCreateListenerInput(lsSpec elbv2model.ListenerSpec) (*elbv2sdk.CreateListenerInput, error) {
271+
func buildSDKCreateListenerInput(lsSpec elbv2model.ListenerSpec, featureGates config.FeatureGates) (*elbv2sdk.CreateListenerInput, error) {
266272
ctx := context.Background()
267273
lbARN, err := lsSpec.LoadBalancerARN.Resolve(ctx)
268274
if err != nil {
@@ -272,7 +278,7 @@ func buildSDKCreateListenerInput(lsSpec elbv2model.ListenerSpec) (*elbv2sdk.Crea
272278
sdkObj.LoadBalancerArn = awssdk.String(lbARN)
273279
sdkObj.Port = awssdk.Int64(lsSpec.Port)
274280
sdkObj.Protocol = awssdk.String(string(lsSpec.Protocol))
275-
defaultActions, err := buildSDKActions(lsSpec.DefaultActions)
281+
defaultActions, err := buildSDKActions(lsSpec.DefaultActions, featureGates)
276282
if err != nil {
277283
return nil, err
278284
}

pkg/deploy/elbv2/listener_rule_manager.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@ type ListenerRuleManager interface {
2727

2828
// NewDefaultListenerRuleManager constructs new defaultListenerRuleManager.
2929
func NewDefaultListenerRuleManager(elbv2Client services.ELBV2, trackingProvider tracking.Provider,
30-
taggingManager TaggingManager, externalManagedTags []string, featureGate config.FeatureGate, logger logr.Logger) *defaultListenerRuleManager {
30+
taggingManager TaggingManager, externalManagedTags []string, featureGates config.FeatureGates, logger logr.Logger) *defaultListenerRuleManager {
3131
return &defaultListenerRuleManager{
3232
elbv2Client: elbv2Client,
3333
trackingProvider: trackingProvider,
3434
taggingManager: taggingManager,
3535
externalManagedTags: externalManagedTags,
36-
featureGate: featureGate,
36+
featureGates: featureGates,
3737
logger: logger,
3838
waitLSExistencePollInterval: defaultWaitLSExistencePollInterval,
3939
waitLSExistenceTimeout: defaultWaitLSExistenceTimeout,
@@ -46,20 +46,20 @@ type defaultListenerRuleManager struct {
4646
trackingProvider tracking.Provider
4747
taggingManager TaggingManager
4848
externalManagedTags []string
49-
featureGate config.FeatureGate
49+
featureGates config.FeatureGates
5050
logger logr.Logger
5151

5252
waitLSExistencePollInterval time.Duration
5353
waitLSExistenceTimeout time.Duration
5454
}
5555

5656
func (m *defaultListenerRuleManager) Create(ctx context.Context, resLR *elbv2model.ListenerRule) (elbv2model.ListenerRuleStatus, error) {
57-
req, err := buildSDKCreateListenerRuleInput(resLR.Spec)
57+
req, err := buildSDKCreateListenerRuleInput(resLR.Spec, m.featureGates)
5858
if err != nil {
5959
return elbv2model.ListenerRuleStatus{}, err
6060
}
6161
var ruleTags map[string]string
62-
if m.featureGate.Enabled(config.EnableListenerRulesTagging) {
62+
if m.featureGates.Enabled(config.ListenerRulesTagging) {
6363
ruleTags = m.trackingProvider.ResourceTags(resLR.Stack(), resLR, resLR.Spec.Tags)
6464
}
6565
req.Tags = convertTagsToSDKTags(ruleTags)
@@ -90,7 +90,7 @@ func (m *defaultListenerRuleManager) Create(ctx context.Context, resLR *elbv2mod
9090
}
9191

9292
func (m *defaultListenerRuleManager) Update(ctx context.Context, resLR *elbv2model.ListenerRule, sdkLR ListenerRuleWithTags) (elbv2model.ListenerRuleStatus, error) {
93-
if m.featureGate.Enabled(config.EnableListenerRulesTagging) {
93+
if m.featureGates.Enabled(config.ListenerRulesTagging) {
9494
if err := m.updateSDKListenerRuleWithTags(ctx, resLR, sdkLR); err != nil {
9595
return elbv2model.ListenerRuleStatus{}, err
9696
}
@@ -116,7 +116,7 @@ func (m *defaultListenerRuleManager) Delete(ctx context.Context, sdkLR ListenerR
116116
}
117117

118118
func (m *defaultListenerRuleManager) updateSDKListenerRuleWithSettings(ctx context.Context, resLR *elbv2model.ListenerRule, sdkLR ListenerRuleWithTags) error {
119-
desiredActions, err := buildSDKActions(resLR.Spec.Actions)
119+
desiredActions, err := buildSDKActions(resLR.Spec.Actions, m.featureGates)
120120
if err != nil {
121121
return err
122122
}
@@ -161,7 +161,7 @@ func isSDKListenerRuleSettingsDrifted(lrSpec elbv2model.ListenerRuleSpec, sdkLR
161161
return false
162162
}
163163

164-
func buildSDKCreateListenerRuleInput(lrSpec elbv2model.ListenerRuleSpec) (*elbv2sdk.CreateRuleInput, error) {
164+
func buildSDKCreateListenerRuleInput(lrSpec elbv2model.ListenerRuleSpec, featureGates config.FeatureGates) (*elbv2sdk.CreateRuleInput, error) {
165165
ctx := context.Background()
166166
lsARN, err := lrSpec.ListenerARN.Resolve(ctx)
167167
if err != nil {
@@ -170,7 +170,7 @@ func buildSDKCreateListenerRuleInput(lrSpec elbv2model.ListenerRuleSpec) (*elbv2
170170
sdkObj := &elbv2sdk.CreateRuleInput{}
171171
sdkObj.ListenerArn = awssdk.String(lsARN)
172172
sdkObj.Priority = awssdk.Int64(lrSpec.Priority)
173-
actions, err := buildSDKActions(lrSpec.Actions)
173+
actions, err := buildSDKActions(lrSpec.Actions, featureGates)
174174
if err != nil {
175175
return nil, err
176176
}

pkg/deploy/elbv2/listener_utils.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"github.com/aws/aws-sdk-go/aws/awserr"
77
elbv2sdk "github.com/aws/aws-sdk-go/service/elbv2"
88
"github.com/pkg/errors"
9+
"sigs.k8s.io/aws-load-balancer-controller/pkg/config"
910
elbv2model "sigs.k8s.io/aws-load-balancer-controller/pkg/model/elbv2"
1011
"time"
1112
)
@@ -15,12 +16,12 @@ const (
1516
defaultWaitLSExistenceTimeout = 20 * time.Second
1617
)
1718

18-
func buildSDKActions(modelActions []elbv2model.Action) ([]*elbv2sdk.Action, error) {
19+
func buildSDKActions(modelActions []elbv2model.Action, featureGates config.FeatureGates) ([]*elbv2sdk.Action, error) {
1920
var sdkActions []*elbv2sdk.Action
2021
if len(modelActions) != 0 {
2122
sdkActions = make([]*elbv2sdk.Action, 0, len(modelActions))
2223
for index, modelAction := range modelActions {
23-
sdkAction, err := buildSDKAction(modelAction)
24+
sdkAction, err := buildSDKAction(modelAction, featureGates)
2425
sdkAction.Order = awssdk.Int64(int64(index) + 1)
2526
if err != nil {
2627
return nil, err
@@ -31,7 +32,7 @@ func buildSDKActions(modelActions []elbv2model.Action) ([]*elbv2sdk.Action, erro
3132
return sdkActions, nil
3233
}
3334

34-
func buildSDKAction(modelAction elbv2model.Action) (*elbv2sdk.Action, error) {
35+
func buildSDKAction(modelAction elbv2model.Action, featureGates config.FeatureGates) (*elbv2sdk.Action, error) {
3536
sdkObj := &elbv2sdk.Action{}
3637
sdkObj.Type = awssdk.String(string(modelAction.Type))
3738
if modelAction.AuthenticateCognitoConfig != nil {
@@ -51,7 +52,15 @@ func buildSDKAction(modelAction elbv2model.Action) (*elbv2sdk.Action, error) {
5152
if err != nil {
5253
return nil, err
5354
}
54-
sdkObj.ForwardConfig = forwardConfig
55+
if !featureGates.Enabled(config.WeightedTargetGroups) {
56+
if len(forwardConfig.TargetGroups) == 1 {
57+
sdkObj.TargetGroupArn = forwardConfig.TargetGroups[0].TargetGroupArn
58+
} else {
59+
return nil, errors.New("Weighted target groups feature is disabled.")
60+
}
61+
} else {
62+
sdkObj.ForwardConfig = forwardConfig
63+
}
5564
}
5665
return sdkObj, nil
5766
}

0 commit comments

Comments
 (0)