forked from ekristen/aws-nuke
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathelbv2-listenerrule.go
158 lines (130 loc) · 3.98 KB
/
elbv2-listenerrule.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package resources
import (
"context"
"fmt"
"github.com/sirupsen/logrus"
"github.com/aws/aws-sdk-go/service/elbv2"
"github.com/ekristen/libnuke/pkg/registry"
"github.com/ekristen/libnuke/pkg/resource"
"github.com/ekristen/libnuke/pkg/slices"
"github.com/ekristen/libnuke/pkg/types"
"github.com/ekristen/aws-nuke/v3/pkg/nuke"
)
var elbv2ListenerRulePageSize int64 = 400 // AWS has a limit of 100 rules per listener
const ELBv2ListenerRuleResource = "ELBv2ListenerRule"
func init() {
registry.Register(®istry.Registration{
Name: ELBv2ListenerRuleResource,
Scope: nuke.Account,
Lister: &ELBv2ListenerRuleLister{},
})
}
type ELBv2ListenerRuleLister struct{}
func (l *ELBv2ListenerRuleLister) List(_ context.Context, o interface{}) ([]resource.Resource, error) {
opts := o.(*nuke.ListerOpts)
svc := elbv2.New(opts.Session)
// We need to retrieve ELBs then Listeners then Rules
lbs := make([]*elbv2.LoadBalancer, 0)
err := svc.DescribeLoadBalancersPages(
nil,
func(page *elbv2.DescribeLoadBalancersOutput, lastPage bool) bool {
lbs = append(lbs, page.LoadBalancers...)
return !lastPage
},
)
if err != nil {
return nil, err
}
// Required for batched tag retrieval later
ruleArns := make([]*string, 0)
ruleArnToResource := make(map[string]*ELBv2ListenerRule)
resources := make([]resource.Resource, 0)
for _, lb := range lbs {
err := svc.DescribeListenersPages(
&elbv2.DescribeListenersInput{
LoadBalancerArn: lb.LoadBalancerArn,
},
func(page *elbv2.DescribeListenersOutput, lastPage bool) bool {
for _, listener := range page.Listeners {
rules, err := svc.DescribeRules(&elbv2.DescribeRulesInput{
ListenerArn: listener.ListenerArn,
PageSize: &elbv2ListenerRulePageSize,
})
if err == nil {
for _, rule := range rules.Rules {
// Skip default rules as they cannot be deleted
if rule.IsDefault != nil && *rule.IsDefault {
continue
}
listenerRule := &ELBv2ListenerRule{
svc: svc,
ruleArn: rule.RuleArn,
lbName: lb.LoadBalancerName,
listenerArn: listener.ListenerArn,
}
ruleArns = append(ruleArns, rule.RuleArn)
resources = append(resources, listenerRule)
ruleArnToResource[*rule.RuleArn] = listenerRule
}
} else {
logrus.
WithError(err).
WithField("listenerArn", listener.ListenerArn).
Error("Failed to list listener rules for listener")
}
}
return !lastPage
},
)
if err != nil {
logrus.
WithError(err).
WithField("loadBalancerArn", lb.LoadBalancerArn).
Error("Failed to list listeners for load balancer")
}
}
// Tags for Rules need to be fetched separately. We can only specify up to 20 in a single call.
// See: https://github.com/aws/aws-sdk-go/blob/0e8c61841163762f870f6976775800ded4a789b0/service/elbv2/api.go#L5398
for _, ruleChunk := range slices.Chunk(ruleArns, 20) {
tagResp, err := svc.DescribeTags(&elbv2.DescribeTagsInput{
ResourceArns: ruleChunk,
})
if err != nil {
return nil, err
}
for _, elbv2TagInfo := range tagResp.TagDescriptions {
rule := ruleArnToResource[*elbv2TagInfo.ResourceArn]
rule.tags = elbv2TagInfo.Tags
}
}
return resources, nil
}
type ELBv2ListenerRule struct {
svc *elbv2.ELBV2
ruleArn *string
lbName *string
listenerArn *string
tags []*elbv2.Tag
}
func (e *ELBv2ListenerRule) Remove(_ context.Context) error {
_, err := e.svc.DeleteRule(&elbv2.DeleteRuleInput{
RuleArn: e.ruleArn,
})
if err != nil {
return err
}
return nil
}
func (e *ELBv2ListenerRule) Properties() types.Properties {
properties := types.NewProperties()
properties.Set("ARN", e.ruleArn)
properties.Set("ListenerARN", e.listenerArn)
properties.Set("LoadBalancerName", e.lbName)
for _, tagValue := range e.tags {
properties.SetTag(tagValue.Key, tagValue.Value)
}
return properties
}
func (e *ELBv2ListenerRule) String() string {
return fmt.Sprintf("%s -> %s", *e.lbName, *e.ruleArn)
}