Merge pull request #45932 from lpabon/elbtag_pr
Automatic merge from submit-queue (batch tested with PRs 45518, 46127, 46146, 45932, 45003) aws: Support for ELB tagging by users This PR provides support for tagging AWS ELBs using information in an annotation and provided as a list of comma separated key-value pairs. Closes https://github.com/kubernetes/community/pull/404
This commit is contained in:
commit
29b3bb44ba
@ -131,6 +131,12 @@ const ServiceAnnotationLoadBalancerSSLPorts = "service.beta.kubernetes.io/aws-lo
|
|||||||
// a HTTP listener is used.
|
// a HTTP listener is used.
|
||||||
const ServiceAnnotationLoadBalancerBEProtocol = "service.beta.kubernetes.io/aws-load-balancer-backend-protocol"
|
const ServiceAnnotationLoadBalancerBEProtocol = "service.beta.kubernetes.io/aws-load-balancer-backend-protocol"
|
||||||
|
|
||||||
|
// ServiceAnnotationLoadBalancerAdditionalTags is the annotation used on the service
|
||||||
|
// to specify a comma-separated list of key-value pairs which will be recorded as
|
||||||
|
// additional tags in the ELB.
|
||||||
|
// For example: "Key1=Val1,Key2=Val2,KeyNoVal1=,KeyNoVal2"
|
||||||
|
const ServiceAnnotationLoadBalancerAdditionalTags = "service.beta.kubernetes.io/aws-load-balancer-additional-resource-tags"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// volumeAttachmentConsecutiveErrorLimit is the number of consecutive errors we will ignore when waiting for a volume to attach/detach
|
// volumeAttachmentConsecutiveErrorLimit is the number of consecutive errors we will ignore when waiting for a volume to attach/detach
|
||||||
volumeAttachmentStatusConsecutiveErrorLimit = 10
|
volumeAttachmentStatusConsecutiveErrorLimit = 10
|
||||||
@ -2792,6 +2798,7 @@ func (c *Cloud) EnsureLoadBalancer(clusterName string, apiService *v1.Service, n
|
|||||||
internalELB,
|
internalELB,
|
||||||
proxyProtocol,
|
proxyProtocol,
|
||||||
loadBalancerAttributes,
|
loadBalancerAttributes,
|
||||||
|
annotations,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go/aws"
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
"github.com/aws/aws-sdk-go/service/ec2"
|
"github.com/aws/aws-sdk-go/service/ec2"
|
||||||
@ -31,7 +32,36 @@ import (
|
|||||||
|
|
||||||
const ProxyProtocolPolicyName = "k8s-proxyprotocol-enabled"
|
const ProxyProtocolPolicyName = "k8s-proxyprotocol-enabled"
|
||||||
|
|
||||||
func (c *Cloud) ensureLoadBalancer(namespacedName types.NamespacedName, loadBalancerName string, listeners []*elb.Listener, subnetIDs []string, securityGroupIDs []string, internalELB, proxyProtocol bool, loadBalancerAttributes *elb.LoadBalancerAttributes) (*elb.LoadBalancerDescription, error) {
|
// getLoadBalancerAdditionalTags converts the comma separated list of key-value
|
||||||
|
// pairs in the ServiceAnnotationLoadBalancerAdditionalTags annotation and returns
|
||||||
|
// it as a map.
|
||||||
|
func getLoadBalancerAdditionalTags(annotations map[string]string) map[string]string {
|
||||||
|
additionalTags := make(map[string]string)
|
||||||
|
if additionalTagsList, ok := annotations[ServiceAnnotationLoadBalancerAdditionalTags]; ok {
|
||||||
|
additionalTagsList = strings.TrimSpace(additionalTagsList)
|
||||||
|
|
||||||
|
// Break up list of "Key1=Val,Key2=Val2"
|
||||||
|
tagList := strings.Split(additionalTagsList, ",")
|
||||||
|
|
||||||
|
// Break up "Key=Val"
|
||||||
|
for _, tagSet := range tagList {
|
||||||
|
tag := strings.Split(strings.TrimSpace(tagSet), "=")
|
||||||
|
|
||||||
|
// Accept "Key=val" or "Key=" or just "Key"
|
||||||
|
if len(tag) >= 2 && len(tag[0]) != 0 {
|
||||||
|
// There is a key and a value, so save it
|
||||||
|
additionalTags[tag[0]] = tag[1]
|
||||||
|
} else if len(tag) == 1 && len(tag[0]) != 0 {
|
||||||
|
// Just "Key"
|
||||||
|
additionalTags[tag[0]] = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return additionalTags
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Cloud) ensureLoadBalancer(namespacedName types.NamespacedName, loadBalancerName string, listeners []*elb.Listener, subnetIDs []string, securityGroupIDs []string, internalELB, proxyProtocol bool, loadBalancerAttributes *elb.LoadBalancerAttributes, annotations map[string]string) (*elb.LoadBalancerDescription, error) {
|
||||||
loadBalancer, err := c.describeLoadBalancer(loadBalancerName)
|
loadBalancer, err := c.describeLoadBalancer(loadBalancerName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -55,9 +85,12 @@ func (c *Cloud) ensureLoadBalancer(namespacedName types.NamespacedName, loadBala
|
|||||||
|
|
||||||
createRequest.SecurityGroups = stringPointerArray(securityGroupIDs)
|
createRequest.SecurityGroups = stringPointerArray(securityGroupIDs)
|
||||||
|
|
||||||
tags := c.tagging.buildTags(ResourceLifecycleOwned, map[string]string{
|
// Get additional tags set by the user
|
||||||
TagNameKubernetesService: namespacedName.String(),
|
tags := getLoadBalancerAdditionalTags(annotations)
|
||||||
})
|
|
||||||
|
// Add default tags
|
||||||
|
tags[TagNameKubernetesService] = namespacedName.String()
|
||||||
|
tags = c.tagging.buildTags(ResourceLifecycleOwned, tags)
|
||||||
|
|
||||||
for k, v := range tags {
|
for k, v := range tags {
|
||||||
createRequest.Tags = append(createRequest.Tags, &elb.Tag{
|
createRequest.Tags = append(createRequest.Tags, &elb.Tag{
|
||||||
|
@ -1284,3 +1284,68 @@ func TestProxyProtocolEnabled(t *testing.T) {
|
|||||||
result = proxyProtocolEnabled(fakeBackend)
|
result = proxyProtocolEnabled(fakeBackend)
|
||||||
assert.False(t, result, "did not expect to find %s in %s", ProxyProtocolPolicyName, policies)
|
assert.False(t, result, "did not expect to find %s in %s", ProxyProtocolPolicyName, policies)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetLoadBalancerAdditionalTags(t *testing.T) {
|
||||||
|
tagTests := []struct {
|
||||||
|
Annotations map[string]string
|
||||||
|
Tags map[string]string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Annotations: map[string]string{
|
||||||
|
ServiceAnnotationLoadBalancerAdditionalTags: "Key=Val",
|
||||||
|
},
|
||||||
|
Tags: map[string]string{
|
||||||
|
"Key": "Val",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Annotations: map[string]string{
|
||||||
|
ServiceAnnotationLoadBalancerAdditionalTags: "Key1=Val1, Key2=Val2",
|
||||||
|
},
|
||||||
|
Tags: map[string]string{
|
||||||
|
"Key1": "Val1",
|
||||||
|
"Key2": "Val2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Annotations: map[string]string{
|
||||||
|
ServiceAnnotationLoadBalancerAdditionalTags: "Key1=, Key2=Val2",
|
||||||
|
"anotherKey": "anotherValue",
|
||||||
|
},
|
||||||
|
Tags: map[string]string{
|
||||||
|
"Key1": "",
|
||||||
|
"Key2": "Val2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"Nothing": "Key1=, Key2=Val2, Key3",
|
||||||
|
},
|
||||||
|
Tags: map[string]string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Annotations: map[string]string{
|
||||||
|
ServiceAnnotationLoadBalancerAdditionalTags: "K=V K1=V2,Key1========, =====, ======Val, =Val, , 234,",
|
||||||
|
},
|
||||||
|
Tags: map[string]string{
|
||||||
|
"K": "V K1",
|
||||||
|
"Key1": "",
|
||||||
|
"234": "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tagTest := range tagTests {
|
||||||
|
result := getLoadBalancerAdditionalTags(tagTest.Annotations)
|
||||||
|
for k, v := range result {
|
||||||
|
if len(result) != len(tagTest.Tags) {
|
||||||
|
t.Errorf("incorrect expected length: %v != %v", result, tagTest.Tags)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if tagTest.Tags[k] != v {
|
||||||
|
t.Errorf("%s != %s", tagTest.Tags[k], v)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user