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 }