github.com/GoogleCloudPlatform/terraformer@v0.8.18/providers/aws/autoscaling.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  
    20  	"github.com/GoogleCloudPlatform/terraformer/terraformutils"
    21  
    22  	"github.com/aws/aws-sdk-go-v2/service/autoscaling"
    23  	"github.com/aws/aws-sdk-go-v2/service/ec2"
    24  
    25  	"github.com/aws/aws-sdk-go-v2/aws"
    26  )
    27  
    28  var AsgAllowEmptyValues = []string{"tags."}
    29  
    30  type AutoScalingGenerator struct {
    31  	AWSService
    32  }
    33  
    34  func (g *AutoScalingGenerator) loadAutoScalingGroups(svc *autoscaling.Client) error {
    35  	p := autoscaling.NewDescribeAutoScalingGroupsPaginator(svc, &autoscaling.DescribeAutoScalingGroupsInput{})
    36  	for p.HasMorePages() {
    37  		page, err := p.NextPage(context.TODO())
    38  		if err != nil {
    39  			return err
    40  		}
    41  		for _, asg := range page.AutoScalingGroups {
    42  			resourceName := StringValue(asg.AutoScalingGroupName)
    43  			g.Resources = append(g.Resources, terraformutils.NewResource(
    44  				resourceName,
    45  				resourceName,
    46  				"aws_autoscaling_group",
    47  				"aws",
    48  				map[string]string{
    49  					"force_delete":              "false",
    50  					"metrics_granularity":       "1Minute",
    51  					"wait_for_capacity_timeout": "10m",
    52  				},
    53  				AsgAllowEmptyValues,
    54  				map[string]interface{}{},
    55  			))
    56  		}
    57  	}
    58  	return nil
    59  }
    60  
    61  func (g *AutoScalingGenerator) loadLaunchConfigurations(svc *autoscaling.Client) error {
    62  	p := autoscaling.NewDescribeLaunchConfigurationsPaginator(svc, &autoscaling.DescribeLaunchConfigurationsInput{})
    63  	for p.HasMorePages() {
    64  		page, err := p.NextPage(context.TODO())
    65  		if err != nil {
    66  			return err
    67  		}
    68  		for _, lc := range page.LaunchConfigurations {
    69  			resourceName := StringValue(lc.LaunchConfigurationName)
    70  			attributes := map[string]string{}
    71  			// only for LaunchConfigurations with userdata, we want get user_data_base64
    72  			if StringValue(lc.UserData) != "" {
    73  				attributes["user_data_base64"] = "=" // need set not empty string to get user_data_base64 from provider
    74  			}
    75  			g.Resources = append(g.Resources, terraformutils.NewResource(
    76  				resourceName,
    77  				resourceName,
    78  				"aws_launch_configuration",
    79  				"aws",
    80  				attributes,
    81  				AsgAllowEmptyValues,
    82  				map[string]interface{}{},
    83  			))
    84  		}
    85  	}
    86  	return nil
    87  }
    88  
    89  func (g *AutoScalingGenerator) loadLaunchTemplates(config aws.Config) error {
    90  	ec2svc := ec2.NewFromConfig(config)
    91  
    92  	p := ec2.NewDescribeLaunchTemplatesPaginator(ec2svc, &ec2.DescribeLaunchTemplatesInput{})
    93  	for p.HasMorePages() {
    94  		page, err := p.NextPage(context.TODO())
    95  		if err != nil {
    96  			return err
    97  		}
    98  		for _, lt := range page.LaunchTemplates {
    99  			g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
   100  				StringValue(lt.LaunchTemplateId),
   101  				StringValue(lt.LaunchTemplateName),
   102  				"aws_launch_template",
   103  				"aws",
   104  				AsgAllowEmptyValues,
   105  			))
   106  		}
   107  	}
   108  	return nil
   109  }
   110  
   111  // Generate TerraformResources from AWS API,
   112  // from each ASG create 1 TerraformResource.
   113  // Need only ASG name as ID for terraform resource
   114  // AWS api support paging
   115  func (g *AutoScalingGenerator) InitResources() error {
   116  	config, e := g.generateConfig()
   117  	if e != nil {
   118  		return e
   119  	}
   120  	svc := autoscaling.NewFromConfig(config)
   121  	if err := g.loadAutoScalingGroups(svc); err != nil {
   122  		return err
   123  	}
   124  	if err := g.loadLaunchConfigurations(svc); err != nil {
   125  		return err
   126  	}
   127  	if err := g.loadLaunchTemplates(config); err != nil {
   128  		return err
   129  	}
   130  	return nil
   131  }
   132  
   133  func (g *AutoScalingGenerator) PostConvertHook() error {
   134  	for i, r := range g.Resources {
   135  		if r.InstanceInfo.Type != "aws_autoscaling_group" {
   136  			continue
   137  		}
   138  		if lcName, exist := r.InstanceState.Attributes["launch_configuration"]; exist {
   139  			for _, lc := range g.Resources {
   140  				if lc.InstanceInfo.Type != "aws_launch_configuration" {
   141  					continue
   142  				}
   143  				if lcName == lc.InstanceState.Attributes["name"] {
   144  					g.Resources[i].Item["launch_configuration"] = "${aws_launch_configuration." + lc.ResourceName + ".name}"
   145  					continue
   146  				}
   147  			}
   148  		}
   149  		// TODO add LaunchTemplate and mix policy connection naming
   150  	}
   151  	// TODO fix tfVar value
   152  	/*
   153  		templateFiles := []terraformutils.Resource{}
   154  		for i, r := range g.Resources {
   155  			if r.InstanceInfo.Type != "aws_launch_configuration" {
   156  				continue
   157  			}
   158  			if userDataBase64, exist := r.InstanceState.Attributes["user_data_base64"]; exist {
   159  				userData, err := base64.StdEncoding.DecodeString(userDataBase64)
   160  				if err != nil {
   161  					continue
   162  				}
   163  				fileName := "userdata-" + r.ServiceName + ".txt"
   164  				err = ioutil.WriteFile(fileName, userData, os.ModePerm) // TODO write files in tf file path
   165  				if err != nil {
   166  					continue
   167  				}
   168  				userDataFile := terraformutils.NewResource(
   169  					r.ServiceName+"_userdata",
   170  					r.ServiceName+"_userdata",
   171  					"template_file",
   172  					"",
   173  					map[string]string{},
   174  					[]string{},
   175  					map[string]string{},
   176  				)
   177  				tfVar := strings.Replace(fmt.Sprintf("${base64decode(file(\"%s\"))}", fileName), "\\\"", "\"", -1)
   178  				userDataFile.Item = map[string]interface{}{
   179  					"template": tfVar,
   180  				}
   181  
   182  				delete(g.Resources[i].Item, "user_data_base64")
   183  				g.Resources[i].Item["user_data"] = "${template_file." + userDataFile.ServiceName + ".rendered}"
   184  				templateFiles = append(templateFiles, userDataFile)
   185  			}
   186  		}
   187  		g.Resources = append(g.Resources, templateFiles...)
   188  	*/
   189  	return nil
   190  }