github.com/GoogleCloudPlatform/terraformer@v0.8.18/providers/aws/alb.go (about)

     1  // Copyright 2018 The Terraformer Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package aws
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"log"
    21  
    22  	"github.com/GoogleCloudPlatform/terraformer/terraformutils"
    23  	"github.com/aws/aws-sdk-go-v2/aws"
    24  	"github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2"
    25  	"github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2/types"
    26  	"github.com/hashicorp/terraform/helper/resource"
    27  )
    28  
    29  var AlbAllowEmptyValues = []string{"tags.", "^condition."}
    30  
    31  type AlbGenerator struct {
    32  	AWSService
    33  }
    34  
    35  func (g *AlbGenerator) loadLB(svc *elasticloadbalancingv2.Client) error {
    36  	p := elasticloadbalancingv2.NewDescribeLoadBalancersPaginator(svc, &elasticloadbalancingv2.DescribeLoadBalancersInput{})
    37  	for p.HasMorePages() {
    38  		page, err := p.NextPage(context.TODO())
    39  		if err != nil {
    40  			return err
    41  		}
    42  		for _, lb := range page.LoadBalancers {
    43  			resourceName := StringValue(lb.LoadBalancerName)
    44  			g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
    45  				*lb.LoadBalancerArn,
    46  				resourceName,
    47  				"aws_lb",
    48  				"aws",
    49  				AlbAllowEmptyValues,
    50  			))
    51  			err := g.loadLBListener(svc, lb.LoadBalancerArn)
    52  			if err != nil {
    53  				log.Println(err)
    54  			}
    55  		}
    56  	}
    57  	return nil
    58  }
    59  
    60  func (g *AlbGenerator) loadLBListener(svc *elasticloadbalancingv2.Client, loadBalancerArn *string) error {
    61  	p := elasticloadbalancingv2.NewDescribeListenersPaginator(svc, &elasticloadbalancingv2.DescribeListenersInput{LoadBalancerArn: loadBalancerArn})
    62  	for p.HasMorePages() {
    63  		page, err := p.NextPage(context.TODO())
    64  		if err != nil {
    65  			return err
    66  		}
    67  		for _, ls := range page.Listeners {
    68  			resourceName := *ls.ListenerArn
    69  			g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
    70  				resourceName,
    71  				resourceName,
    72  				"aws_lb_listener",
    73  				"aws",
    74  				AlbAllowEmptyValues,
    75  			))
    76  			err := g.loadLBListenerRule(svc, ls.ListenerArn)
    77  			if err != nil {
    78  				log.Println(err)
    79  			}
    80  			err = g.loadLBListenerCertificate(svc, &ls)
    81  			if err != nil {
    82  				log.Println(err)
    83  			}
    84  		}
    85  	}
    86  	return nil
    87  }
    88  
    89  func (g *AlbGenerator) loadLBListenerRule(svc *elasticloadbalancingv2.Client, listenerArn *string) error {
    90  	var marker *string
    91  	for {
    92  		lsrs, err := svc.DescribeRules(context.TODO(), &elasticloadbalancingv2.DescribeRulesInput{
    93  			ListenerArn: listenerArn,
    94  			Marker:      marker,
    95  			PageSize:    aws.Int32(400)},
    96  		)
    97  		if err != nil {
    98  			return err
    99  		}
   100  		for _, lsr := range lsrs.Rules {
   101  			if !lsr.IsDefault {
   102  				resourceName := *lsr.RuleArn
   103  				g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
   104  					resourceName,
   105  					resourceName,
   106  					"aws_lb_listener_rule",
   107  					"aws",
   108  					AlbAllowEmptyValues,
   109  				))
   110  			}
   111  		}
   112  		marker = lsrs.NextMarker
   113  		if marker == nil {
   114  			break
   115  		}
   116  	}
   117  	return nil
   118  }
   119  
   120  func (g *AlbGenerator) loadLBListenerCertificate(svc *elasticloadbalancingv2.Client, loadBalancer *types.Listener) error {
   121  	lcs, err := svc.DescribeListenerCertificates(context.TODO(), &elasticloadbalancingv2.DescribeListenerCertificatesInput{
   122  		ListenerArn: loadBalancer.ListenerArn,
   123  	})
   124  	if err != nil {
   125  		return err
   126  	}
   127  	for _, lc := range lcs.Certificates {
   128  		certificateArn := *lc.CertificateArn
   129  		if certificateArn == *loadBalancer.Certificates[0].CertificateArn { // discard default certificate
   130  			continue
   131  		}
   132  		g.Resources = append(g.Resources, terraformutils.NewResource(
   133  			certificateArn,
   134  			certificateArn,
   135  			"aws_lb_listener_certificate",
   136  			"aws",
   137  			map[string]string{
   138  				"listener_arn":    *loadBalancer.ListenerArn,
   139  				"certificate_arn": certificateArn,
   140  			},
   141  			AlbAllowEmptyValues,
   142  			map[string]interface{}{},
   143  		))
   144  	}
   145  	return err
   146  }
   147  
   148  func (g *AlbGenerator) loadLBTargetGroup(svc *elasticloadbalancingv2.Client) error {
   149  	p := elasticloadbalancingv2.NewDescribeTargetGroupsPaginator(svc, &elasticloadbalancingv2.DescribeTargetGroupsInput{})
   150  	for p.HasMorePages() {
   151  		page, err := p.NextPage(context.TODO())
   152  		if err != nil {
   153  			return err
   154  		}
   155  		for _, tg := range page.TargetGroups {
   156  			resourceName := StringValue(tg.TargetGroupName)
   157  			g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
   158  				*tg.TargetGroupArn,
   159  				resourceName,
   160  				"aws_lb_target_group",
   161  				"aws",
   162  				AlbAllowEmptyValues,
   163  			))
   164  			err := g.loadTargetGroupTargets(svc, tg.TargetGroupArn)
   165  			if err != nil {
   166  				log.Println(err)
   167  			}
   168  		}
   169  	}
   170  	return nil
   171  }
   172  
   173  func (g *AlbGenerator) loadTargetGroupTargets(svc *elasticloadbalancingv2.Client, targetGroupArn *string) error {
   174  	targetHealths, err := svc.DescribeTargetHealth(context.TODO(), &elasticloadbalancingv2.DescribeTargetHealthInput{
   175  		TargetGroupArn: targetGroupArn,
   176  	})
   177  	if err != nil {
   178  		return err
   179  	}
   180  	for _, tgh := range targetHealths.TargetHealthDescriptions {
   181  		id := resource.PrefixedUniqueId(fmt.Sprintf("%s-", *targetGroupArn))
   182  		g.Resources = append(g.Resources, terraformutils.NewResource(
   183  			id,
   184  			id,
   185  			"aws_lb_target_group_attachment",
   186  			"aws",
   187  			map[string]string{
   188  				"target_id":        *tgh.Target.Id,
   189  				"target_group_arn": *targetGroupArn,
   190  			},
   191  			AlbAllowEmptyValues,
   192  			map[string]interface{}{},
   193  		))
   194  	}
   195  	return nil
   196  }
   197  
   198  // Generate TerraformResources from AWS API,
   199  func (g *AlbGenerator) InitResources() error {
   200  	config, e := g.generateConfig()
   201  	if e != nil {
   202  		return e
   203  	}
   204  	svc := elasticloadbalancingv2.NewFromConfig(config)
   205  	if err := g.loadLB(svc); err != nil {
   206  		return err
   207  	}
   208  	if err := g.loadLBTargetGroup(svc); err != nil {
   209  		return err
   210  	}
   211  	return nil
   212  }
   213  
   214  func (g *AlbGenerator) PostConvertHook() error {
   215  	for _, r := range g.Resources {
   216  		if r.InstanceInfo.Type != "aws_lb_listener" {
   217  			continue
   218  		}
   219  		if r.InstanceState.Attributes["default_action.0.order"] == "0" {
   220  			delete(r.Item["default_action"].([]interface{})[0].(map[string]interface{}), "order")
   221  		}
   222  	}
   223  
   224  	for i, r := range g.Resources {
   225  		if r.InstanceInfo.Type != "aws_lb_listener_rule" {
   226  			continue
   227  		}
   228  		if r.InstanceState.Attributes["action.0.order"] == "0" {
   229  			delete(r.Item["action"].([]interface{})[0].(map[string]interface{}), "order")
   230  		}
   231  		for _, lb := range g.Resources {
   232  			if lb.InstanceInfo.Type != "aws_lb_listener_certificate" {
   233  				continue
   234  			}
   235  			if r.InstanceState.Attributes["certificate_arn"] == lb.InstanceState.Attributes["arn"] {
   236  				g.Resources[i].Item["certificate_arn"] = "${aws_lb_listener_certificate." + lb.ResourceName + ".arn}"
   237  			}
   238  		}
   239  	}
   240  
   241  	for _, r := range g.Resources {
   242  		if r.InstanceInfo.Type != "aws_lb" {
   243  			continue
   244  		}
   245  		if val, ok := r.InstanceState.Attributes["access_logs.0.enabled"]; ok && val == "false" {
   246  			delete(r.Item, "access_logs")
   247  		}
   248  	}
   249  	return nil
   250  }