github.com/awslabs/fargate@v0.2.3/elbv2/listener.go (about)

     1  package elbv2
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  	"strconv"
     7  
     8  	"github.com/aws/aws-sdk-go/aws"
     9  	awselbv2 "github.com/aws/aws-sdk-go/service/elbv2"
    10  	"github.com/jpignata/fargate/console"
    11  )
    12  
    13  type CreateListenerInput struct {
    14  	Port                  int64
    15  	Protocol              string
    16  	CertificateArns       []string
    17  	LoadBalancerArn       string
    18  	DefaultTargetGroupArn string
    19  }
    20  
    21  type Rule struct {
    22  	Type           string
    23  	Value          string
    24  	TargetGroupArn string
    25  	Priority       int
    26  	Arn            string
    27  	IsDefault      bool
    28  }
    29  
    30  func (r *Rule) String() string {
    31  	if r.Value != "" {
    32  		return fmt.Sprintf("%s=%s", r.Type, r.Value)
    33  	} else {
    34  		return fmt.Sprintf("%s", r.Type)
    35  	}
    36  }
    37  
    38  type Listener struct {
    39  	Arn             string
    40  	Port            int64
    41  	Protocol        string
    42  	CertificateArns []string
    43  	Rules           []Rule
    44  }
    45  
    46  func (l *Listener) String() string {
    47  	return fmt.Sprintf("%s:%d", l.Protocol, l.Port)
    48  }
    49  
    50  func (input *CreateListenerInput) SetCertificateArns(arns []string) {
    51  	input.CertificateArns = arns
    52  }
    53  
    54  func (elbv2 *ELBV2) CreateListener(i *CreateListenerInput) string {
    55  	console.Debug("Creating ELB listener [%s:%s]", i.Protocol, i.Port)
    56  
    57  	action := &awselbv2.Action{
    58  		TargetGroupArn: aws.String(i.DefaultTargetGroupArn),
    59  		Type:           aws.String(awselbv2.ActionTypeEnumForward),
    60  	}
    61  
    62  	input := &awselbv2.CreateListenerInput{
    63  		Port:            aws.Int64(i.Port),
    64  		Protocol:        aws.String(i.Protocol),
    65  		LoadBalancerArn: aws.String(i.LoadBalancerArn),
    66  		DefaultActions:  []*awselbv2.Action{action},
    67  	}
    68  
    69  	if len(i.CertificateArns) > 0 {
    70  		certificates := []*awselbv2.Certificate{}
    71  
    72  		for _, certificateArn := range i.CertificateArns {
    73  			certificates = append(certificates,
    74  				&awselbv2.Certificate{
    75  					CertificateArn: aws.String(certificateArn),
    76  				},
    77  			)
    78  		}
    79  
    80  		input.SetCertificates(certificates)
    81  	}
    82  
    83  	resp, err := elbv2.svc.CreateListener(input)
    84  
    85  	if err != nil || len(resp.Listeners) != 1 {
    86  		console.ErrorExit(err, "Could not create ELB listener")
    87  	}
    88  
    89  	return aws.StringValue(resp.Listeners[0].ListenerArn)
    90  }
    91  
    92  func (elbv2 *ELBV2) ModifyLoadBalancerDefaultAction(lbArn, targetGroupArn string) {
    93  	for _, listener := range elbv2.GetListeners(lbArn) {
    94  		elbv2.ModifyListenerDefaultAction(listener.Arn, targetGroupArn)
    95  	}
    96  }
    97  
    98  func (elbv2 *ELBV2) ModifyListenerDefaultAction(listenerArn, targetGroupArn string) {
    99  	action := &awselbv2.Action{
   100  		TargetGroupArn: aws.String(targetGroupArn),
   101  		Type:           aws.String(awselbv2.ActionTypeEnumForward),
   102  	}
   103  
   104  	elbv2.svc.ModifyListener(
   105  		&awselbv2.ModifyListenerInput{
   106  			ListenerArn:    aws.String(listenerArn),
   107  			DefaultActions: []*awselbv2.Action{action},
   108  		},
   109  	)
   110  }
   111  
   112  func (elbv2 *ELBV2) AddRule(lbArn, targetGroupArn string, rule Rule) {
   113  	console.Debug("Adding ELB listener rule [%s=%s]", rule.Type, rule.Value)
   114  
   115  	listeners := elbv2.GetListeners(lbArn)
   116  
   117  	for _, listener := range listeners {
   118  		elbv2.AddRuleToListener(listener.Arn, targetGroupArn, rule)
   119  	}
   120  }
   121  
   122  func (elbv2 *ELBV2) AddRuleToListener(listenerArn, targetGroupArn string, rule Rule) {
   123  	var ruleType string
   124  
   125  	if rule.Type == "HOST" {
   126  		ruleType = "host-header"
   127  	} else {
   128  		ruleType = "path-pattern"
   129  	}
   130  
   131  	ruleCondition := &awselbv2.RuleCondition{
   132  		Field:  aws.String(ruleType),
   133  		Values: aws.StringSlice([]string{rule.Value}),
   134  	}
   135  	highestPriority := elbv2.GetHighestPriorityFromListener(listenerArn)
   136  	priority := highestPriority + 10
   137  	action := &awselbv2.Action{
   138  		TargetGroupArn: aws.String(targetGroupArn),
   139  		Type:           aws.String(awselbv2.ActionTypeEnumForward),
   140  	}
   141  
   142  	elbv2.svc.CreateRule(
   143  		&awselbv2.CreateRuleInput{
   144  			Priority:    aws.Int64(priority),
   145  			ListenerArn: aws.String(listenerArn),
   146  			Actions:     []*awselbv2.Action{action},
   147  			Conditions:  []*awselbv2.RuleCondition{ruleCondition},
   148  		},
   149  	)
   150  }
   151  
   152  func (elbv2 *ELBV2) DescribeRules(listenerArn string) []Rule {
   153  	var rules []Rule
   154  
   155  	resp, err := elbv2.svc.DescribeRules(
   156  		&awselbv2.DescribeRulesInput{
   157  			ListenerArn: aws.String(listenerArn),
   158  		},
   159  	)
   160  
   161  	if err != nil {
   162  		console.ErrorExit(err, "Could not describe ELB rules")
   163  	}
   164  
   165  	for _, r := range resp.Rules {
   166  		for _, c := range r.Conditions {
   167  			var field string
   168  
   169  			switch aws.StringValue(c.Field) {
   170  			case "host-header":
   171  				field = "HOST"
   172  			case "path-pattern":
   173  				field = "PATH"
   174  			}
   175  
   176  			for _, v := range c.Values {
   177  				priority, _ := strconv.Atoi(aws.StringValue(r.Priority))
   178  
   179  				rule := Rule{
   180  					Arn:            aws.StringValue(r.RuleArn),
   181  					Priority:       priority,
   182  					TargetGroupArn: aws.StringValue(r.Actions[0].TargetGroupArn),
   183  					Type:           field,
   184  					Value:          aws.StringValue(v),
   185  				}
   186  
   187  				rules = append(rules, rule)
   188  			}
   189  		}
   190  
   191  		if aws.BoolValue(r.IsDefault) == true {
   192  			rule := Rule{
   193  				TargetGroupArn: aws.StringValue(r.Actions[0].TargetGroupArn),
   194  				Type:           "DEFAULT",
   195  				IsDefault:      true,
   196  			}
   197  
   198  			rules = append(rules, rule)
   199  		}
   200  	}
   201  
   202  	return rules
   203  }
   204  
   205  func (elbv2 *ELBV2) GetHighestPriorityFromListener(listenerArn string) int64 {
   206  	var priorities []int
   207  
   208  	resp, err := elbv2.svc.DescribeRules(
   209  		&awselbv2.DescribeRulesInput{
   210  			ListenerArn: aws.String(listenerArn),
   211  		},
   212  	)
   213  
   214  	if err != nil {
   215  		console.ErrorExit(err, "Could not retrieve ELB listener rules")
   216  	}
   217  
   218  	for _, rule := range resp.Rules {
   219  		priority, _ := strconv.Atoi(aws.StringValue(rule.Priority))
   220  		priorities = append(priorities, priority)
   221  	}
   222  
   223  	sort.Ints(priorities)
   224  
   225  	return int64(priorities[len(priorities)-1])
   226  }
   227  
   228  func (elbv2 *ELBV2) GetListeners(lbArn string) []Listener {
   229  	var listeners []Listener
   230  
   231  	input := &awselbv2.DescribeListenersInput{
   232  		LoadBalancerArn: aws.String(lbArn),
   233  	}
   234  
   235  	err := elbv2.svc.DescribeListenersPages(
   236  		input,
   237  		func(resp *awselbv2.DescribeListenersOutput, lastPage bool) bool {
   238  			for _, l := range resp.Listeners {
   239  				listener := Listener{
   240  					Arn:      aws.StringValue(l.ListenerArn),
   241  					Port:     aws.Int64Value(l.Port),
   242  					Protocol: aws.StringValue(l.Protocol),
   243  				}
   244  
   245  				for _, certificate := range l.Certificates {
   246  					listener.CertificateArns = append(
   247  						listener.CertificateArns,
   248  						aws.StringValue(certificate.CertificateArn),
   249  					)
   250  				}
   251  
   252  				listeners = append(listeners, listener)
   253  			}
   254  
   255  			return true
   256  		},
   257  	)
   258  
   259  	if err != nil {
   260  		console.ErrorExit(err, "Could not retrieve ELB listeners")
   261  	}
   262  
   263  	return listeners
   264  }
   265  
   266  func (elbv2 *ELBV2) DeleteRule(ruleArn string) {
   267  	_, err := elbv2.svc.DeleteRule(
   268  		&awselbv2.DeleteRuleInput{
   269  			RuleArn: aws.String(ruleArn),
   270  		},
   271  	)
   272  
   273  	if err != nil {
   274  		console.ErrorExit(err, "Could not delete ELB rule")
   275  	}
   276  }