Skip to content

Commit

Permalink
Merge pull request #1 from coreos/master
Browse files Browse the repository at this point in the history
Merge from coreos/alb-ingress-controller
  • Loading branch information
andrewtandoc authored Apr 7, 2018
2 parents c594ac7 + 245bb34 commit 428dbc6
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ spec:
nodeSelector:
{{ toYaml .Values.controller.nodeSelector | indent 8 }}
{{- end }}
{{- if .Values.controller.tolerations }}
tolerations:
{{ toYaml .Values.controller.tolerations | indent 8 }}
{{- end }}
Expand Down
3 changes: 3 additions & 0 deletions docs/ingress-resources.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ alb.ingress.kubernetes.io/security-groups
alb.ingress.kubernetes.io/subnets
alb.ingress.kubernetes.io/successCodes
alb.ingress.kubernetes.io/tags
alb.ingress.kubernetes.io/ip-address-type
```
Optional annotations are:
Expand Down Expand Up @@ -104,3 +105,5 @@ Optional annotations are:
- **successCodes**: Defines the HTTP status code that should be expected when doing health checks against the defined `healthcheck-path`. When omitted, `200` is used.
- **tags**: Defines [AWS Tags](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html) that should be applied to the ALB instance and Target groups.
- **ip-address-type**: The IP address type thats used to either route IPv4 traffic only or to route both IPv4 and IPv6 traffic. Can be either `dualstack` or `ipv4`. When omitted `ipv4` is used.
1 change: 1 addition & 0 deletions examples/iam-policy.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"elasticloadbalancing:ModifyTargetGroup",
"elasticloadbalancing:RegisterTargets",
"elasticloadbalancing:RemoveTags",
"elasticloadbalancing:SetIpAddressType",
"elasticloadbalancing:SetSecurityGroups",
"elasticloadbalancing:SetSubnets"
],
Expand Down
37 changes: 31 additions & 6 deletions pkg/alb/loadbalancer/loadbalancer.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import (
"encoding/hex"
"fmt"
"reflect"
"regexp"
"sort"
"strings"
"time"

"github.com/aws/aws-sdk-go/aws"
Expand Down Expand Up @@ -56,6 +56,7 @@ const (
attributesModified
managedSecurityGroupsModified
connectionIdleTimeoutModified
ipAddressTypeModified
)

type NewDesiredLoadBalancerOptions struct {
Expand All @@ -77,8 +78,7 @@ func (a portList) Less(i, j int) bool { return a[i] < a[j] }

// NewDesiredLoadBalancer returns a new loadbalancer.LoadBalancer based on the parameters provided.
func NewDesiredLoadBalancer(o *NewDesiredLoadBalancerOptions) *LoadBalancer {
// TODO: LB name must contain only alphanumeric characters or hyphens, and must
// not begin or end with a hyphen.
// TODO: LB name must not begin with a hyphen.
name := createLBName(o.Namespace, o.IngressName, o.ALBNamePrefix)

newLoadBalancer := &LoadBalancer{
Expand All @@ -89,6 +89,7 @@ func NewDesiredLoadBalancer(o *NewDesiredLoadBalancerOptions) *LoadBalancer {
AvailabilityZones: o.Annotations.Subnets.AsAvailabilityZones(),
LoadBalancerName: aws.String(name),
Scheme: o.Annotations.Scheme,
IpAddressType: o.Annotations.IpAddressType,
SecurityGroups: o.Annotations.SecurityGroups,
VpcId: o.Annotations.VPCID,
},
Expand Down Expand Up @@ -338,6 +339,7 @@ func (lb *LoadBalancer) create(rOpts *ReconcileOptions) error {
Name: lb.Desired.LoadBalancerName,
Subnets: util.AvailabilityZones(lb.Desired.AvailabilityZones).AsSubnets(),
Scheme: lb.Desired.Scheme,
IpAddressType: lb.Desired.IpAddressType,
Tags: lb.DesiredTags,
SecurityGroups: sgs,
}
Expand Down Expand Up @@ -438,6 +440,22 @@ func (lb *LoadBalancer) modify(rOpts *ReconcileOptions) error {
log.Prettify(lb.Current.AvailabilityZones))
}

// Modify IP address type
if needsMod&ipAddressTypeModified != 0 {
lb.logger.Infof("Start IP address type modification.")
in := &elbv2.SetIpAddressTypeInput{
LoadBalancerArn: lb.Current.LoadBalancerArn,
IpAddressType: lb.Desired.IpAddressType,
}
if _,err := albelbv2.ELBV2svc.SetIpAddressType(in); err != nil {
return fmt.Errorf("Failure Setting ALB IpAddressType: %s", err)
}
lb.Current.IpAddressType = lb.Desired.IpAddressType
rOpts.Eventf(api.EventTypeNormal, "MODIFY", "%s ip address type modified", *lb.Current.LoadBalancerName)
lb.logger.Infof("Completed IP address type modification. Type is %s.", *lb.Current.LoadBalancerName,
*lb.Current.IpAddressType)
}

// Modify Tags
if needsMod&tagsModified != 0 {
lb.logger.Infof("Start ELBV2 tag modification.")
Expand Down Expand Up @@ -572,6 +590,11 @@ func (lb *LoadBalancer) needsModification() (loadBalancerChange, bool) {
return changes, false
}

if !util.DeepEqual(lb.Current.IpAddressType, lb.Desired.IpAddressType) {
changes |= ipAddressTypeModified
return changes, true
}

currentSubnets := util.AvailabilityZones(lb.Current.AvailabilityZones).AsSubnets()
desiredSubnets := util.AvailabilityZones(lb.Desired.AvailabilityZones).AsSubnets()
sort.Sort(currentSubnets)
Expand Down Expand Up @@ -639,10 +662,12 @@ func createLBName(namespace string, ingressName string, clustername string) stri
hasher := md5.New()
hasher.Write([]byte(namespace + ingressName))
hash := hex.EncodeToString(hasher.Sum(nil))[:4]

r, _ := regexp.Compile("[[:^alnum:]]")
name := fmt.Sprintf("%s-%s-%s",
clustername,
strings.Replace(namespace, "-", "", -1),
strings.Replace(ingressName, "-", "", -1),
r.ReplaceAllString(clustername, "-"),
r.ReplaceAllString(namespace, ""),
r.ReplaceAllString(ingressName, ""),
)
if len(name) > 26 {
name = name[:26]
Expand Down
15 changes: 15 additions & 0 deletions pkg/annotations/annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ const (
unhealthyThresholdCountKey = "alb.ingress.kubernetes.io/unhealthy-threshold-count"
portKey = "alb.ingress.kubernetes.io/listen-ports"
schemeKey = "alb.ingress.kubernetes.io/scheme"
ipAddressTypeKey = "alb.ingress.kubernetes.io/ip-address-type"
securityGroupsKey = "alb.ingress.kubernetes.io/security-groups"
subnetsKey = "alb.ingress.kubernetes.io/subnets"
successCodesKey = "alb.ingress.kubernetes.io/successCodes"
Expand All @@ -61,6 +62,7 @@ type Annotations struct {
UnhealthyThresholdCount *int64
Ports []PortData
Scheme *string
IpAddressType *string
SecurityGroups util.AWSStringSlice
Subnets util.Subnets
SuccessCodes *string
Expand Down Expand Up @@ -104,6 +106,7 @@ func ParseAnnotations(annotations map[string]string, clusterName string, ingress
a.setUnhealthyThresholdCount(annotations),
a.setPorts(annotations),
a.setScheme(annotations, ingressNamespace, ingressName),
a.setIpAddressType(annotations),
a.setSecurityGroups(annotations),
a.setSubnets(annotations, clusterName),
a.setSuccessCodes(annotations),
Expand Down Expand Up @@ -337,6 +340,18 @@ func (a *Annotations) setScheme(annotations map[string]string, ingressNamespace,
return nil
}

func (a *Annotations) setIpAddressType(annotations map[string]string) error {
switch {
case annotations[ipAddressTypeKey] == "":
a.IpAddressType = aws.String("ipv4")
return nil
case annotations[ipAddressTypeKey] != "ipv4" && annotations[ipAddressTypeKey] != "dualstack":
return fmt.Errorf("ALB IP Address Type [%v] must be either `ipv4` or `dualstack`", annotations[ipAddressTypeKey])
}
a.IpAddressType = aws.String(annotations[ipAddressTypeKey])
return nil
}

func (a *Annotations) setSecurityGroups(annotations map[string]string) error {
// no security groups specified means controller should manage them, if so return and sg will be
// created and managed during reconcile.
Expand Down
30 changes: 30 additions & 0 deletions pkg/annotations/annotations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,36 @@ func TestSetScheme(t *testing.T) {
}
}

func TestSetIpAddressType(t *testing.T) {
var tests = []struct {
ipAddressType string
expected string
pass bool
}{
{"", "ipv4", true}, // ip-address-type has a sane default
{"/", "", false},
{"ipv4", "ipv4", true},
{"ipv4", "dualstack", false},
{"dualstack", "ipv4", false},
{"dualstack", "dualstack", true},
}

for _, tt := range tests {
a := &Annotations{}

err := a.setIpAddressType(map[string]string{ipAddressTypeKey: tt.ipAddressType})
if err != nil && tt.pass {
t.Errorf("setIpAddressType(%v): expected %v, actual %v", tt.ipAddressType, tt.pass, err)
}
if err == nil && tt.pass && tt.expected != *a.IpAddressType {
t.Errorf("setIpAddressType(%v): expected %v, actual %v", tt.ipAddressType, tt.expected, *a.IpAddressType)
}
if err == nil && !tt.pass && tt.expected == *a.IpAddressType {
t.Errorf("setIpAddressType(%v): expected %v, actual %v", tt.ipAddressType, tt.expected, *a.IpAddressType)
}
}
}

// Should fail to create due to healthchecktimeout being greater than HealthcheckIntervalSeconds
func TestHealthcheckSecondsValidation(t *testing.T) {
a := &Annotations{}
Expand Down

0 comments on commit 428dbc6

Please sign in to comment.