github.com/GoogleCloudPlatform/terraformer@v0.8.18/providers/aws/aws_provider.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  	"os"
    19  	"strconv"
    20  
    21  	"github.com/GoogleCloudPlatform/terraformer/terraformutils"
    22  	"github.com/pkg/errors"
    23  	"github.com/zclconf/go-cty/cty"
    24  )
    25  
    26  type AWSProvider struct { //nolint
    27  	terraformutils.Provider
    28  	region  string
    29  	profile string
    30  }
    31  
    32  const GlobalRegion = "aws-global"
    33  const MainRegionPublicPartition = "us-east-1"
    34  const NoRegion = ""
    35  
    36  // SupportedGlobalResources should be bound to a default region. AWS doesn't specify in which region default services are
    37  // placed (see  https://docs.aws.amazon.com/general/latest/gr/rande.html), so we shouldn't assume any region as well
    38  //
    39  // AWS WAF V2 if added, should not be included in this list since it is a composition of regional and global resources.
    40  var SupportedGlobalResources = []string{
    41  	"budgets",
    42  	"cloudfront",
    43  	"ecrpublic",
    44  	"iam",
    45  	"organization",
    46  	"route53",
    47  	"waf",
    48  }
    49  
    50  func (p AWSProvider) GetResourceConnections() map[string]map[string][]string {
    51  	return map[string]map[string][]string{
    52  		"alb": {
    53  			"sg":     []string{"security_groups", "id"},
    54  			"subnet": []string{"subnets", "id"},
    55  			"alb": []string{
    56  				"load_balancer_arn", "id",
    57  				"listener_arn", "id",
    58  				// TF ALB TG attachment logic doesn't work well with references (doesn't interpolate)
    59  			},
    60  		},
    61  		"auto_scaling": {
    62  			"sg":     []string{"security_groups", "id"},
    63  			"subnet": []string{"vpc_zone_identifier", "id"},
    64  		},
    65  		"ec2_instance": {
    66  			"sg":     []string{"vpc_security_group_ids", "id"},
    67  			"subnet": []string{"subnet_id", "id"},
    68  			"ebs":    []string{"ebs_block_device", "id"},
    69  		},
    70  		"elasticache": {
    71  			"vpc":    []string{"vpc_id", "id"},
    72  			"subnet": []string{"subnet_ids", "id"},
    73  			"sg":     []string{"security_group_ids", "id"},
    74  		},
    75  		"ebs": {
    76  			// TF EBS attachment logic doesn't work well with references (doesn't interpolate)
    77  		},
    78  		"ecs": {
    79  			// ECS is not able anymore to support references (doesn't interpolate)
    80  			"subnet": []string{"network_configuration.subnets", "id"},
    81  			"sg":     []string{"network_configuration.security_groups", "id"},
    82  		},
    83  		"eks": {
    84  			"subnet": []string{"vpc_config.subnet_ids", "id"},
    85  			"sg":     []string{"vpc_config.security_group_ids", "id"},
    86  		},
    87  		"elb": {
    88  			"sg":     []string{"security_groups", "id"},
    89  			"subnet": []string{"subnets", "id"},
    90  		},
    91  		"igw": {"vpc": []string{"vpc_id", "id"}},
    92  		"msk": {
    93  			"subnet": []string{"broker_node_group_info.client_subnets", "id"},
    94  			"sg":     []string{"broker_node_group_info.security_groups", "id"},
    95  		},
    96  		"nacl": {
    97  			"subnet": []string{"subnet_ids", "id"},
    98  			"vpc":    []string{"vpc_id", "id"},
    99  		},
   100  		"organization": {
   101  			"organization": []string{
   102  				"policy_id", "id",
   103  				"parent_id", "id",
   104  				"target_id", "id",
   105  			},
   106  		},
   107  		"rds": {
   108  			"subnet": []string{"subnet_ids", "id"},
   109  			"sg":     []string{"vpc_security_group_ids", "id"},
   110  		},
   111  		"route_table": {
   112  			"route_table": []string{"route_table_id", "id"},
   113  			"subnet":      []string{"subnet_id", "id"},
   114  			"vpc":         []string{"vpc_id", "id"},
   115  		},
   116  		"sns": {
   117  			"sns": []string{"topic_arn", "id"},
   118  			"sqs": []string{"endpoint", "arn"},
   119  		},
   120  		"sg": {
   121  			"sg": []string{
   122  				"egress.security_groups", "id",
   123  				"ingress.security_groups", "id",
   124  				"security_group_id", "id",
   125  				"source_security_group_id", "id",
   126  			},
   127  		},
   128  		"subnet": {"vpc": []string{"vpc_id", "id"}},
   129  		"transit_gateway": {
   130  			"vpc":             []string{"vpc_id", "id"},
   131  			"transit_gateway": []string{"transit_gateway_id", "id"},
   132  			"subnet":          []string{"subnet_ids", "id"},
   133  			"vpn_connection":  []string{"vpn_connection_id", "id"},
   134  		},
   135  		"vpn_gateway": {"vpc": []string{"vpc_id", "id"}},
   136  		"vpn_connection": {
   137  			"customer_gateway": []string{"customer_gateway_id", "id"},
   138  			"vpn_gateway":      []string{"vpn_gateway_id", "id"},
   139  		},
   140  	}
   141  }
   142  
   143  func (p AWSProvider) GetProviderData(arg ...string) map[string]interface{} {
   144  	awsConfig := map[string]interface{}{}
   145  
   146  	if p.region == GlobalRegion {
   147  		awsConfig["region"] = MainRegionPublicPartition // For TF to workaround terraform-providers/terraform-provider-aws#1043
   148  	} else if p.region != NoRegion {
   149  		awsConfig["region"] = p.region
   150  	}
   151  
   152  	return map[string]interface{}{
   153  		"provider": map[string]interface{}{
   154  			"aws": awsConfig,
   155  		},
   156  	}
   157  }
   158  
   159  func (p *AWSProvider) GetConfig() cty.Value {
   160  	if p.region != GlobalRegion {
   161  		return cty.ObjectVal(map[string]cty.Value{
   162  			"region":                 cty.StringVal(p.region),
   163  			"skip_region_validation": cty.True,
   164  		})
   165  	}
   166  	return cty.ObjectVal(map[string]cty.Value{
   167  		"region":                 cty.StringVal(""),
   168  		"skip_region_validation": cty.True,
   169  	})
   170  }
   171  
   172  func (p *AWSProvider) GetBasicConfig() cty.Value {
   173  	return p.GetConfig()
   174  }
   175  
   176  // check projectName in env params
   177  func (p *AWSProvider) Init(args []string) error {
   178  	p.region = args[0]
   179  	p.profile = args[1]
   180  
   181  	// Terraformer accepts region and profile configuration, so we must detect what env variables to adjust to make Go SDK rely on them. AWS_SDK_LOAD_CONFIG here must be checked to determine correct variable to set.
   182  	enableSharedConfig, _ := strconv.ParseBool(os.Getenv("AWS_SDK_LOAD_CONFIG"))
   183  	var err error
   184  	if p.region != GlobalRegion && p.region != NoRegion {
   185  		if enableSharedConfig {
   186  			err = os.Setenv("AWS_DEFAULT_REGION", p.region)
   187  		} else {
   188  			err = os.Setenv("AWS_REGION", p.region)
   189  		}
   190  		if err != nil {
   191  			return err
   192  		}
   193  	}
   194  
   195  	if p.profile != "default" && p.profile != "" {
   196  		if enableSharedConfig {
   197  			err = os.Setenv("AWS_DEFAULT_PROFILE", p.profile)
   198  		} else {
   199  			err = os.Setenv("AWS_PROFILE", p.profile)
   200  		}
   201  		if err != nil {
   202  			return err
   203  		}
   204  	}
   205  	return nil
   206  }
   207  
   208  func (p *AWSProvider) GetName() string {
   209  	return "aws"
   210  }
   211  
   212  func (p *AWSProvider) InitService(serviceName string, verbose bool) error {
   213  	var isSupported bool
   214  	if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported {
   215  		return errors.New("aws: " + serviceName + " not supported service")
   216  	}
   217  	p.Service = p.GetSupportedService()[serviceName]
   218  	p.Service.SetName(serviceName)
   219  	p.Service.SetVerbose(verbose)
   220  	p.Service.SetProviderName(p.GetName())
   221  	p.Service.SetArgs(map[string]interface{}{
   222  		"region":                 p.region,
   223  		"profile":                p.profile,
   224  		"skip_region_validation": true,
   225  	})
   226  	return nil
   227  }
   228  
   229  // GetAWSSupportService return map of support service for AWS
   230  func (p *AWSProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
   231  	return map[string]terraformutils.ServiceGenerator{
   232  		"accessanalyzer":    &AwsFacade{service: &AccessAnalyzerGenerator{}},
   233  		"acm":               &AwsFacade{service: &ACMGenerator{}},
   234  		"alb":               &AwsFacade{service: &AlbGenerator{}},
   235  		"api_gateway":       &AwsFacade{service: &APIGatewayGenerator{}},
   236  		"appsync":           &AwsFacade{service: &AppSyncGenerator{}},
   237  		"auto_scaling":      &AwsFacade{service: &AutoScalingGenerator{}},
   238  		"batch":             &AwsFacade{service: &BatchGenerator{}},
   239  		"budgets":           &AwsFacade{service: &BudgetsGenerator{}},
   240  		"cloud9":            &AwsFacade{service: &Cloud9Generator{}},
   241  		"cloudformation":    &AwsFacade{service: &CloudFormationGenerator{}},
   242  		"cloudfront":        &AwsFacade{service: &CloudFrontGenerator{}},
   243  		"cloudhsm":          &AwsFacade{service: &CloudHsmGenerator{}},
   244  		"cloudtrail":        &AwsFacade{service: &CloudTrailGenerator{}},
   245  		"cloudwatch":        &AwsFacade{service: &CloudWatchGenerator{}},
   246  		"codebuild":         &AwsFacade{service: &CodeBuildGenerator{}},
   247  		"codecommit":        &AwsFacade{service: &CodeCommitGenerator{}},
   248  		"codedeploy":        &AwsFacade{service: &CodeDeployGenerator{}},
   249  		"codepipeline":      &AwsFacade{service: &CodePipelineGenerator{}},
   250  		"cognito":           &AwsFacade{service: &CognitoGenerator{}},
   251  		"config":            &AwsFacade{service: &ConfigGenerator{}},
   252  		"customer_gateway":  &AwsFacade{service: &CustomerGatewayGenerator{}},
   253  		"datapipeline":      &AwsFacade{service: &DataPipelineGenerator{}},
   254  		"devicefarm":        &AwsFacade{service: &DeviceFarmGenerator{}},
   255  		"docdb":             &AwsFacade{service: &DocDBGenerator{}},
   256  		"dynamodb":          &AwsFacade{service: &DynamoDbGenerator{}},
   257  		"ebs":               &AwsFacade{service: &EbsGenerator{}},
   258  		"ec2_instance":      &AwsFacade{service: &Ec2Generator{}},
   259  		"ecr":               &AwsFacade{service: &EcrGenerator{}},
   260  		"ecrpublic":         &AwsFacade{service: &EcrPublicGenerator{}},
   261  		"ecs":               &AwsFacade{service: &EcsGenerator{}},
   262  		"efs":               &AwsFacade{service: &EfsGenerator{}},
   263  		"eks":               &AwsFacade{service: &EksGenerator{}},
   264  		"eip":               &AwsFacade{service: &ElasticIPGenerator{}},
   265  		"elasticache":       &AwsFacade{service: &ElastiCacheGenerator{}},
   266  		"elastic_beanstalk": &AwsFacade{service: &BeanstalkGenerator{}},
   267  		"elb":               &AwsFacade{service: &ElbGenerator{}},
   268  		"emr":               &AwsFacade{service: &EmrGenerator{}},
   269  		"eni":               &AwsFacade{service: &EniGenerator{}},
   270  		"es":                &AwsFacade{service: &EsGenerator{}},
   271  		"firehose":          &AwsFacade{service: &FirehoseGenerator{}},
   272  		"glue":              &AwsFacade{service: &GlueGenerator{}},
   273  		"iam":               &AwsFacade{service: &IamGenerator{}},
   274  		"igw":               &AwsFacade{service: &IgwGenerator{}},
   275  		"iot":               &AwsFacade{service: &IotGenerator{}},
   276  		"kinesis":           &AwsFacade{service: &KinesisGenerator{}},
   277  		"kms":               &AwsFacade{service: &KmsGenerator{}},
   278  		"lambda":            &AwsFacade{service: &LambdaGenerator{}},
   279  		"logs":              &AwsFacade{service: &LogsGenerator{}},
   280  		"media_package":     &AwsFacade{service: &MediaPackageGenerator{}},
   281  		"media_store":       &AwsFacade{service: &MediaStoreGenerator{}},
   282  		"msk":               &AwsFacade{service: &MskGenerator{}},
   283  		"nacl":              &AwsFacade{service: &NaclGenerator{}},
   284  		"nat":               &AwsFacade{service: &NatGatewayGenerator{}},
   285  		"opsworks":          &AwsFacade{service: &OpsworksGenerator{}},
   286  		"organization":      &AwsFacade{service: &OrganizationGenerator{}},
   287  		"qldb":              &AwsFacade{service: &QLDBGenerator{}},
   288  		"rds":               &AwsFacade{service: &RDSGenerator{}},
   289  		"resourcegroups":    &AwsFacade{service: &ResourceGroupsGenerator{}},
   290  		"route53":           &AwsFacade{service: &Route53Generator{}},
   291  		"route_table":       &AwsFacade{service: &RouteTableGenerator{}},
   292  		"s3":                &AwsFacade{service: &S3Generator{}},
   293  		"secretsmanager":    &AwsFacade{service: &SecretsManagerGenerator{}},
   294  		"securityhub":       &AwsFacade{service: &SecurityhubGenerator{}},
   295  		"servicecatalog":    &AwsFacade{service: &ServiceCatalogGenerator{}},
   296  		"ses":               &AwsFacade{service: &SesGenerator{}},
   297  		"sfn":               &AwsFacade{service: &SfnGenerator{}},
   298  		"sg":                &AwsFacade{service: &SecurityGenerator{}},
   299  		"sqs":               &AwsFacade{service: &SqsGenerator{}},
   300  		"sns":               &AwsFacade{service: &SnsGenerator{}},
   301  		"ssm":               &AwsFacade{service: &SsmGenerator{}},
   302  		"subnet":            &AwsFacade{service: &SubnetGenerator{}},
   303  		"swf":               &AwsFacade{service: &SWFGenerator{}},
   304  		"transit_gateway":   &AwsFacade{service: &TransitGatewayGenerator{}},
   305  		"waf":               &AwsFacade{service: &WafGenerator{}},
   306  		"waf_regional":      &AwsFacade{service: &WafRegionalGenerator{}},
   307  		"vpc":               &AwsFacade{service: &VpcGenerator{}},
   308  		"vpc_peering":       &AwsFacade{service: &VpcPeeringConnectionGenerator{}},
   309  		"vpn_connection":    &AwsFacade{service: &VpnConnectionGenerator{}},
   310  		"vpn_gateway":       &AwsFacade{service: &VpnGatewayGenerator{}},
   311  		"workspaces":        &AwsFacade{service: &WorkspacesGenerator{}},
   312  		"xray":              &AwsFacade{service: &XrayGenerator{}},
   313  	}
   314  }
   315  
   316  func StringValue(value *string) string {
   317  	if value != nil {
   318  		return *value
   319  	}
   320  	return ""
   321  }