providers/aws/alb.go (221 lines of code) (raw):

// Copyright 2018 The Terraformer Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package aws import ( "context" "fmt" "log" "github.com/GoogleCloudPlatform/terraformer/terraformutils" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2" "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2/types" ) var AlbAllowEmptyValues = []string{"tags.", "^condition."} type AlbGenerator struct { AWSService } func (g *AlbGenerator) loadLB(svc *elasticloadbalancingv2.Client) error { p := elasticloadbalancingv2.NewDescribeLoadBalancersPaginator(svc, &elasticloadbalancingv2.DescribeLoadBalancersInput{}) for p.HasMorePages() { page, err := p.NextPage(context.TODO()) if err != nil { return err } for _, lb := range page.LoadBalancers { resourceName := StringValue(lb.LoadBalancerName) g.Resources = append(g.Resources, terraformutils.NewSimpleResource( *lb.LoadBalancerArn, resourceName, "aws_lb", "aws", AlbAllowEmptyValues, )) err := g.loadLBListener(svc, lb.LoadBalancerArn) if err != nil { log.Println(err) } } } return nil } func (g *AlbGenerator) loadLBListener(svc *elasticloadbalancingv2.Client, loadBalancerArn *string) error { p := elasticloadbalancingv2.NewDescribeListenersPaginator(svc, &elasticloadbalancingv2.DescribeListenersInput{LoadBalancerArn: loadBalancerArn}) for p.HasMorePages() { page, err := p.NextPage(context.TODO()) if err != nil { return err } for _, ls := range page.Listeners { resourceName := *ls.ListenerArn g.Resources = append(g.Resources, terraformutils.NewSimpleResource( resourceName, resourceName, "aws_lb_listener", "aws", AlbAllowEmptyValues, )) err := g.loadLBListenerRule(svc, ls.ListenerArn) if err != nil { log.Println(err) } err = g.loadLBListenerCertificate(svc, &ls) if err != nil { log.Println(err) } } } return nil } func (g *AlbGenerator) loadLBListenerRule(svc *elasticloadbalancingv2.Client, listenerArn *string) error { var marker *string for { lsrs, err := svc.DescribeRules(context.TODO(), &elasticloadbalancingv2.DescribeRulesInput{ ListenerArn: listenerArn, Marker: marker, PageSize: aws.Int32(400)}, ) if err != nil { return err } for _, lsr := range lsrs.Rules { if !*lsr.IsDefault { resourceName := *lsr.RuleArn g.Resources = append(g.Resources, terraformutils.NewSimpleResource( resourceName, resourceName, "aws_lb_listener_rule", "aws", AlbAllowEmptyValues, )) } } marker = lsrs.NextMarker if marker == nil { break } } return nil } func (g *AlbGenerator) loadLBListenerCertificate(svc *elasticloadbalancingv2.Client, loadBalancer *types.Listener) error { lcs, err := svc.DescribeListenerCertificates(context.TODO(), &elasticloadbalancingv2.DescribeListenerCertificatesInput{ ListenerArn: loadBalancer.ListenerArn, }) if err != nil { return err } for _, lc := range lcs.Certificates { certificateArn := *lc.CertificateArn listenerCertificateID := *loadBalancer.ListenerArn + "_" + certificateArn if certificateArn == *loadBalancer.Certificates[0].CertificateArn { // discard default certificate continue } g.Resources = append(g.Resources, terraformutils.NewResource( listenerCertificateID, listenerCertificateID, "aws_lb_listener_certificate", "aws", map[string]string{ "listener_arn": *loadBalancer.ListenerArn, "certificate_arn": certificateArn, }, AlbAllowEmptyValues, map[string]interface{}{}, )) } return err } func (g *AlbGenerator) loadLBTargetGroup(svc *elasticloadbalancingv2.Client) error { p := elasticloadbalancingv2.NewDescribeTargetGroupsPaginator(svc, &elasticloadbalancingv2.DescribeTargetGroupsInput{}) for p.HasMorePages() { page, err := p.NextPage(context.TODO()) if err != nil { return err } for _, tg := range page.TargetGroups { resourceName := StringValue(tg.TargetGroupName) g.Resources = append(g.Resources, terraformutils.NewSimpleResource( *tg.TargetGroupArn, resourceName, "aws_lb_target_group", "aws", AlbAllowEmptyValues, )) err := g.loadTargetGroupTargets(svc, tg.TargetGroupArn) if err != nil { log.Println(err) } } } return nil } func (g *AlbGenerator) loadTargetGroupTargets(svc *elasticloadbalancingv2.Client, targetGroupArn *string) error { targetHealths, err := svc.DescribeTargetHealth(context.TODO(), &elasticloadbalancingv2.DescribeTargetHealthInput{ TargetGroupArn: targetGroupArn, }) if err != nil { return err } for _, tgh := range targetHealths.TargetHealthDescriptions { id := fmt.Sprintf("%s-%s", *targetGroupArn, *tgh.Target.Id) g.Resources = append(g.Resources, terraformutils.NewResource( id, id, "aws_lb_target_group_attachment", "aws", map[string]string{ "target_id": *tgh.Target.Id, "target_group_arn": *targetGroupArn, }, AlbAllowEmptyValues, map[string]interface{}{}, )) } return nil } // Generate TerraformResources from AWS API, func (g *AlbGenerator) InitResources() error { config, e := g.generateConfig() if e != nil { return e } svc := elasticloadbalancingv2.NewFromConfig(config) if err := g.loadLB(svc); err != nil { return err } if err := g.loadLBTargetGroup(svc); err != nil { return err } return nil } func (g *AlbGenerator) PostConvertHook() error { for _, r := range g.Resources { if r.InstanceInfo.Type != "aws_lb_listener" { continue } if r.InstanceState.Attributes["default_action.0.order"] == "0" { delete(r.Item["default_action"].([]interface{})[0].(map[string]interface{}), "order") } } for i, r := range g.Resources { if r.InstanceInfo.Type != "aws_lb_listener_rule" { continue } if r.InstanceState.Attributes["action.0.order"] == "0" { delete(r.Item["action"].([]interface{})[0].(map[string]interface{}), "order") } for _, lb := range g.Resources { if lb.InstanceInfo.Type != "aws_lb_listener_certificate" { continue } if r.InstanceState.Attributes["certificate_arn"] == lb.InstanceState.Attributes["arn"] { g.Resources[i].Item["certificate_arn"] = "${aws_lb_listener_certificate." + lb.ResourceName + ".arn}" } } } for _, r := range g.Resources { if r.InstanceInfo.Type != "aws_lb" { continue } if val, ok := r.InstanceState.Attributes["access_logs.0.enabled"]; ok && val == "false" { delete(r.Item, "access_logs") } } return nil }