github.com/acm1/terraform@v0.6.2-0.20150729164239-1f314444f45c/builtin/providers/aws/provider.go (about) 1 package aws 2 3 import ( 4 "net" 5 "sync" 6 "time" 7 8 "github.com/awslabs/aws-sdk-go/aws/credentials" 9 "github.com/hashicorp/terraform/helper/hashcode" 10 "github.com/hashicorp/terraform/helper/schema" 11 "github.com/hashicorp/terraform/terraform" 12 ) 13 14 // Provider returns a terraform.ResourceProvider. 15 func Provider() terraform.ResourceProvider { 16 // TODO: Move the validation to this, requires conditional schemas 17 // TODO: Move the configuration to this, requires validation 18 19 // These variables are closed within the `getCreds` function below. 20 // This function is responsible for reading credentials from the 21 // environment in the case that they're not explicitly specified 22 // in the Terraform configuration. 23 // 24 // By using the getCreds function here instead of making the default 25 // empty, we avoid asking for input on credentials if they're available 26 // in the environment. 27 var credVal credentials.Value 28 var credErr error 29 var once sync.Once 30 getCreds := func() { 31 // Build the list of providers to look for creds in 32 providers := []credentials.Provider{ 33 &credentials.EnvProvider{}, 34 &credentials.SharedCredentialsProvider{}, 35 } 36 37 // We only look in the EC2 metadata API if we can connect 38 // to the metadata service within a reasonable amount of time 39 conn, err := net.DialTimeout("tcp", "169.254.169.254:80", 100*time.Millisecond) 40 if err == nil { 41 conn.Close() 42 providers = append(providers, &credentials.EC2RoleProvider{}) 43 } 44 45 credVal, credErr = credentials.NewChainCredentials(providers).Get() 46 47 // If we didn't successfully find any credentials, just 48 // set the error to nil. 49 if credErr == credentials.ErrNoValidProvidersFoundInChain { 50 credErr = nil 51 } 52 } 53 54 // getCredDefault is a function used by DefaultFunc below to 55 // get the default value for various parts of the credentials. 56 // This function properly handles loading the credentials, checking 57 // for errors, etc. 58 getCredDefault := func(def interface{}, f func() string) (interface{}, error) { 59 once.Do(getCreds) 60 61 // If there was an error, that is always first 62 if credErr != nil { 63 return nil, credErr 64 } 65 66 // If the value is empty string, return nil (not set) 67 val := f() 68 if val == "" { 69 return def, nil 70 } 71 72 return val, nil 73 } 74 75 // The actual provider 76 return &schema.Provider{ 77 Schema: map[string]*schema.Schema{ 78 "access_key": &schema.Schema{ 79 Type: schema.TypeString, 80 Required: true, 81 DefaultFunc: func() (interface{}, error) { 82 return getCredDefault(nil, func() string { 83 return credVal.AccessKeyID 84 }) 85 }, 86 Description: descriptions["access_key"], 87 }, 88 89 "secret_key": &schema.Schema{ 90 Type: schema.TypeString, 91 Required: true, 92 DefaultFunc: func() (interface{}, error) { 93 return getCredDefault(nil, func() string { 94 return credVal.SecretAccessKey 95 }) 96 }, 97 Description: descriptions["secret_key"], 98 }, 99 100 "token": &schema.Schema{ 101 Type: schema.TypeString, 102 Optional: true, 103 DefaultFunc: func() (interface{}, error) { 104 return getCredDefault("", func() string { 105 return credVal.SessionToken 106 }) 107 }, 108 Description: descriptions["token"], 109 }, 110 111 "region": &schema.Schema{ 112 Type: schema.TypeString, 113 Required: true, 114 DefaultFunc: schema.MultiEnvDefaultFunc([]string{ 115 "AWS_REGION", 116 "AWS_DEFAULT_REGION", 117 }, nil), 118 Description: descriptions["region"], 119 InputDefault: "us-east-1", 120 }, 121 122 "max_retries": &schema.Schema{ 123 Type: schema.TypeInt, 124 Optional: true, 125 Default: 11, 126 Description: descriptions["max_retries"], 127 }, 128 129 "allowed_account_ids": &schema.Schema{ 130 Type: schema.TypeSet, 131 Elem: &schema.Schema{Type: schema.TypeString}, 132 Optional: true, 133 ConflictsWith: []string{"forbidden_account_ids"}, 134 Set: func(v interface{}) int { 135 return hashcode.String(v.(string)) 136 }, 137 }, 138 139 "forbidden_account_ids": &schema.Schema{ 140 Type: schema.TypeSet, 141 Elem: &schema.Schema{Type: schema.TypeString}, 142 Optional: true, 143 ConflictsWith: []string{"allowed_account_ids"}, 144 Set: func(v interface{}) int { 145 return hashcode.String(v.(string)) 146 }, 147 }, 148 }, 149 150 ResourcesMap: map[string]*schema.Resource{ 151 "aws_app_cookie_stickiness_policy": resourceAwsAppCookieStickinessPolicy(), 152 "aws_autoscaling_group": resourceAwsAutoscalingGroup(), 153 "aws_autoscaling_notification": resourceAwsAutoscalingNotification(), 154 "aws_autoscaling_policy": resourceAwsAutoscalingPolicy(), 155 "aws_cloudwatch_metric_alarm": resourceAwsCloudWatchMetricAlarm(), 156 "aws_customer_gateway": resourceAwsCustomerGateway(), 157 "aws_db_instance": resourceAwsDbInstance(), 158 "aws_db_parameter_group": resourceAwsDbParameterGroup(), 159 "aws_db_security_group": resourceAwsDbSecurityGroup(), 160 "aws_db_subnet_group": resourceAwsDbSubnetGroup(), 161 "aws_dynamodb_table": resourceAwsDynamoDbTable(), 162 "aws_ebs_volume": resourceAwsEbsVolume(), 163 "aws_ecs_cluster": resourceAwsEcsCluster(), 164 "aws_ecs_service": resourceAwsEcsService(), 165 "aws_ecs_task_definition": resourceAwsEcsTaskDefinition(), 166 "aws_eip": resourceAwsEip(), 167 "aws_elasticache_cluster": resourceAwsElasticacheCluster(), 168 "aws_elasticache_parameter_group": resourceAwsElasticacheParameterGroup(), 169 "aws_elasticache_security_group": resourceAwsElasticacheSecurityGroup(), 170 "aws_elasticache_subnet_group": resourceAwsElasticacheSubnetGroup(), 171 "aws_elb": resourceAwsElb(), 172 "aws_flow_log": resourceAwsFlowLog(), 173 "aws_iam_access_key": resourceAwsIamAccessKey(), 174 "aws_iam_group_policy": resourceAwsIamGroupPolicy(), 175 "aws_iam_group": resourceAwsIamGroup(), 176 "aws_iam_group_membership": resourceAwsIamGroupMembership(), 177 "aws_iam_instance_profile": resourceAwsIamInstanceProfile(), 178 "aws_iam_policy": resourceAwsIamPolicy(), 179 "aws_iam_policy_attachment": resourceAwsIamPolicyAttachment(), 180 "aws_iam_role_policy": resourceAwsIamRolePolicy(), 181 "aws_iam_role": resourceAwsIamRole(), 182 "aws_iam_server_certificate": resourceAwsIAMServerCertificate(), 183 "aws_iam_user_policy": resourceAwsIamUserPolicy(), 184 "aws_iam_user": resourceAwsIamUser(), 185 "aws_instance": resourceAwsInstance(), 186 "aws_internet_gateway": resourceAwsInternetGateway(), 187 "aws_key_pair": resourceAwsKeyPair(), 188 "aws_kinesis_stream": resourceAwsKinesisStream(), 189 "aws_lambda_function": resourceAwsLambdaFunction(), 190 "aws_launch_configuration": resourceAwsLaunchConfiguration(), 191 "aws_lb_cookie_stickiness_policy": resourceAwsLBCookieStickinessPolicy(), 192 "aws_main_route_table_association": resourceAwsMainRouteTableAssociation(), 193 "aws_network_acl": resourceAwsNetworkAcl(), 194 "aws_network_interface": resourceAwsNetworkInterface(), 195 "aws_proxy_protocol_policy": resourceAwsProxyProtocolPolicy(), 196 "aws_route53_delegation_set": resourceAwsRoute53DelegationSet(), 197 "aws_route53_record": resourceAwsRoute53Record(), 198 "aws_route53_zone_association": resourceAwsRoute53ZoneAssociation(), 199 "aws_route53_zone": resourceAwsRoute53Zone(), 200 "aws_route53_health_check": resourceAwsRoute53HealthCheck(), 201 "aws_route_table": resourceAwsRouteTable(), 202 "aws_route_table_association": resourceAwsRouteTableAssociation(), 203 "aws_s3_bucket": resourceAwsS3Bucket(), 204 "aws_security_group": resourceAwsSecurityGroup(), 205 "aws_security_group_rule": resourceAwsSecurityGroupRule(), 206 "aws_spot_instance_request": resourceAwsSpotInstanceRequest(), 207 "aws_sqs_queue": resourceAwsSqsQueue(), 208 "aws_sns_topic": resourceAwsSnsTopic(), 209 "aws_sns_topic_subscription": resourceAwsSnsTopicSubscription(), 210 "aws_subnet": resourceAwsSubnet(), 211 "aws_volume_attachment": resourceAwsVolumeAttachment(), 212 "aws_vpc_dhcp_options_association": resourceAwsVpcDhcpOptionsAssociation(), 213 "aws_vpc_dhcp_options": resourceAwsVpcDhcpOptions(), 214 "aws_vpc_peering_connection": resourceAwsVpcPeeringConnection(), 215 "aws_vpc": resourceAwsVpc(), 216 "aws_vpc_endpoint": resourceAwsVpcEndpoint(), 217 "aws_vpn_connection": resourceAwsVpnConnection(), 218 "aws_vpn_connection_route": resourceAwsVpnConnectionRoute(), 219 "aws_vpn_gateway": resourceAwsVpnGateway(), 220 }, 221 222 ConfigureFunc: providerConfigure, 223 } 224 } 225 226 var descriptions map[string]string 227 228 func init() { 229 descriptions = map[string]string{ 230 "region": "The region where AWS operations will take place. Examples\n" + 231 "are us-east-1, us-west-2, etc.", 232 233 "access_key": "The access key for API operations. You can retrieve this\n" + 234 "from the 'Security & Credentials' section of the AWS console.", 235 236 "secret_key": "The secret key for API operations. You can retrieve this\n" + 237 "from the 'Security & Credentials' section of the AWS console.", 238 239 "token": "session token. A session token is only required if you are\n" + 240 "using temporary security credentials.", 241 242 "max_retries": "The maximum number of times an AWS API request is\n" + 243 "being executed. If the API request still fails, an error is\n" + 244 "thrown.", 245 } 246 } 247 248 func providerConfigure(d *schema.ResourceData) (interface{}, error) { 249 config := Config{ 250 AccessKey: d.Get("access_key").(string), 251 SecretKey: d.Get("secret_key").(string), 252 Token: d.Get("token").(string), 253 Region: d.Get("region").(string), 254 MaxRetries: d.Get("max_retries").(int), 255 } 256 257 if v, ok := d.GetOk("allowed_account_ids"); ok { 258 config.AllowedAccountIds = v.(*schema.Set).List() 259 } 260 261 if v, ok := d.GetOk("forbidden_account_ids"); ok { 262 config.ForbiddenAccountIds = v.(*schema.Set).List() 263 } 264 265 return config.Client() 266 }