github.com/openshift/installer@v1.4.17/pkg/destroy/aws/elbhelpers.go (about) 1 package aws 2 3 import ( 4 "context" 5 "strings" 6 7 "github.com/aws/aws-sdk-go/aws" 8 "github.com/aws/aws-sdk-go/aws/arn" 9 "github.com/aws/aws-sdk-go/aws/awserr" 10 "github.com/aws/aws-sdk-go/aws/session" 11 "github.com/aws/aws-sdk-go/service/elb" 12 "github.com/aws/aws-sdk-go/service/elbv2" 13 "github.com/pkg/errors" 14 "github.com/sirupsen/logrus" 15 ) 16 17 func deleteElasticLoadBalancing(ctx context.Context, session *session.Session, arn arn.ARN, logger logrus.FieldLogger) error { 18 resourceType, id, err := splitSlash("resource", arn.Resource) 19 if err != nil { 20 return err 21 } 22 logger = logger.WithField("id", id) 23 24 switch resourceType { 25 case "loadbalancer": 26 segments := strings.SplitN(id, "/", 2) 27 if len(segments) == 1 { 28 return deleteElasticLoadBalancerClassic(ctx, elb.New(session), id, logger) 29 } else if len(segments) != 2 { 30 return errors.Errorf("cannot parse subresource %q into {subtype}/{id}", id) 31 } 32 subtype := segments[0] 33 id = segments[1] 34 switch subtype { 35 case "net": 36 return deleteElasticLoadBalancerV2(ctx, elbv2.New(session), arn, logger) 37 default: 38 return errors.Errorf("unrecognized elastic load balancing resource subtype %s", subtype) 39 } 40 case "targetgroup": 41 return deleteElasticLoadBalancerTargetGroup(ctx, elbv2.New(session), arn, logger) 42 case "listener": 43 return deleteElasticLoadBalancerListener(ctx, elbv2.New(session), arn, logger) 44 default: 45 return errors.Errorf("unrecognized elastic load balancing resource type %s", resourceType) 46 } 47 } 48 49 func deleteElasticLoadBalancerClassic(ctx context.Context, client *elb.ELB, name string, logger logrus.FieldLogger) error { 50 _, err := client.DeleteLoadBalancerWithContext(ctx, &elb.DeleteLoadBalancerInput{ 51 LoadBalancerName: aws.String(name), 52 }) 53 if err != nil { 54 return err 55 } 56 57 logger.Info("Deleted") 58 return nil 59 } 60 61 func deleteElasticLoadBalancerClassicByVPC(ctx context.Context, client *elb.ELB, vpc string, logger logrus.FieldLogger) error { 62 var lastError error 63 err := client.DescribeLoadBalancersPagesWithContext( 64 ctx, 65 &elb.DescribeLoadBalancersInput{}, 66 func(results *elb.DescribeLoadBalancersOutput, lastPage bool) bool { 67 logger.Debugf("iterating over a page of %d v1 load balancers", len(results.LoadBalancerDescriptions)) 68 for _, lb := range results.LoadBalancerDescriptions { 69 lbLogger := logger.WithField("classic load balancer", *lb.LoadBalancerName) 70 71 if lb.VPCId == nil { 72 lbLogger.Warn("classic load balancer does not have a VPC ID so could not determine whether it should be deleted") 73 continue 74 } 75 76 if *lb.VPCId != vpc { 77 continue 78 } 79 80 err := deleteElasticLoadBalancerClassic(ctx, client, *lb.LoadBalancerName, lbLogger) 81 if err != nil { 82 if lastError != nil { 83 logger.Debug(lastError) 84 } 85 lastError = errors.Wrapf(err, "deleting classic load balancer %s", *lb.LoadBalancerName) 86 } 87 } 88 89 return !lastPage 90 }, 91 ) 92 93 if lastError != nil { 94 return lastError 95 } 96 return err 97 } 98 99 func deleteElasticLoadBalancerTargetGroup(ctx context.Context, client *elbv2.ELBV2, arn arn.ARN, logger logrus.FieldLogger) error { 100 _, err := client.DeleteTargetGroupWithContext(ctx, &elbv2.DeleteTargetGroupInput{ 101 TargetGroupArn: aws.String(arn.String()), 102 }) 103 if err != nil { 104 return err 105 } 106 107 logger.Info("Deleted") 108 return nil 109 } 110 111 func isListenerNotFound(err interface{}) bool { 112 if aerr, ok := err.(awserr.Error); ok { 113 if aerr.Code() == elbv2.ErrCodeListenerNotFoundException { 114 return true 115 } 116 } 117 return false 118 } 119 120 func deleteElasticLoadBalancerListener(ctx context.Context, client *elbv2.ELBV2, arn arn.ARN, logger logrus.FieldLogger) error { 121 _, err := client.DeleteListenerWithContext(ctx, &elbv2.DeleteListenerInput{ 122 ListenerArn: aws.String(arn.String()), 123 }) 124 if err != nil { 125 if isListenerNotFound(err) { 126 logger.Info("Not found or already deleted") 127 return nil 128 } 129 return err 130 } 131 132 logger.Info("Deleted") 133 return nil 134 } 135 136 func deleteElasticLoadBalancerV2(ctx context.Context, client *elbv2.ELBV2, arn arn.ARN, logger logrus.FieldLogger) error { 137 _, err := client.DeleteLoadBalancerWithContext(ctx, &elbv2.DeleteLoadBalancerInput{ 138 LoadBalancerArn: aws.String(arn.String()), 139 }) 140 if err != nil { 141 return err 142 } 143 144 logger.Info("Deleted") 145 return nil 146 } 147 148 func deleteElasticLoadBalancerV2ByVPC(ctx context.Context, client *elbv2.ELBV2, vpc string, logger logrus.FieldLogger) error { 149 var lastError error 150 err := client.DescribeLoadBalancersPagesWithContext( 151 ctx, 152 &elbv2.DescribeLoadBalancersInput{}, 153 func(results *elbv2.DescribeLoadBalancersOutput, lastPage bool) bool { 154 logger.Debugf("iterating over a page of %d v2 load balancers", len(results.LoadBalancers)) 155 for _, lb := range results.LoadBalancers { 156 if lb.VpcId == nil { 157 logger.WithField("load balancer", *lb.LoadBalancerArn).Warn("load balancer does not have a VPC ID so could not determine whether it should be deleted") 158 continue 159 } 160 161 if *lb.VpcId != vpc { 162 continue 163 } 164 165 parsed, err := arn.Parse(*lb.LoadBalancerArn) 166 if err != nil { 167 if lastError != nil { 168 logger.Debug(lastError) 169 } 170 lastError = errors.Wrap(err, "parse ARN for load balancer") 171 continue 172 } 173 174 err = deleteElasticLoadBalancerV2(ctx, client, parsed, logger.WithField("load balancer", parsed.Resource)) 175 if err != nil { 176 if lastError != nil { 177 logger.Debug(lastError) 178 } 179 lastError = errors.Wrapf(err, "deleting %s", parsed.String()) 180 } 181 } 182 183 return !lastPage 184 }, 185 ) 186 187 if lastError != nil { 188 return lastError 189 } 190 return err 191 }