From c61d3ac38e59309a9a97d9f53fdf85966daee7e2 Mon Sep 17 00:00:00 2001 From: Brian Flad Date: Mon, 16 Jul 2018 16:29:02 -0400 Subject: [PATCH 1/2] New Resource: aws_storagegateway_gateway Removes unreleased and invalid aws_storagegateway_gateway_activation_key data source -- the activation key is not accessible after gateway activation --- aws/config.go | 3 + ...s_storagegateway_gateway_activation_key.go | 94 ---- ...ragegateway_gateway_activation_key_test.go | 203 ------- aws/provider.go | 200 +++---- aws/resource_aws_storagegateway_gateway.go | 286 ++++++++++ ...esource_aws_storagegateway_gateway_test.go | 518 ++++++++++++++++++ website/aws.erb | 14 +- ...teway_gateway_activation_key.html.markdown | 41 -- .../r/storagegateway_gateway.html.markdown | 97 ++++ 9 files changed, 1015 insertions(+), 441 deletions(-) delete mode 100644 aws/data_source_aws_storagegateway_gateway_activation_key.go delete mode 100644 aws/data_source_aws_storagegateway_gateway_activation_key_test.go create mode 100644 aws/resource_aws_storagegateway_gateway.go create mode 100644 aws/resource_aws_storagegateway_gateway_test.go delete mode 100644 website/docs/d/storagegateway_gateway_activation_key.html.markdown create mode 100644 website/docs/r/storagegateway_gateway.html.markdown diff --git a/aws/config.go b/aws/config.go index df113d1869e..2219539d2b9 100644 --- a/aws/config.go +++ b/aws/config.go @@ -89,6 +89,7 @@ import ( "github.com/aws/aws-sdk-go/service/sns" "github.com/aws/aws-sdk-go/service/sqs" "github.com/aws/aws-sdk-go/service/ssm" + "github.com/aws/aws-sdk-go/service/storagegateway" "github.com/aws/aws-sdk-go/service/sts" "github.com/aws/aws-sdk-go/service/swf" "github.com/aws/aws-sdk-go/service/waf" @@ -222,6 +223,7 @@ type AWSClient struct { sdconn *servicediscovery.ServiceDiscovery sfnconn *sfn.SFN ssmconn *ssm.SSM + storagegatewayconn *storagegateway.StorageGateway swfconn *swf.SWF wafconn *waf.WAF wafregionalconn *wafregional.WAFRegional @@ -518,6 +520,7 @@ func (c *Config) Client() (interface{}, error) { client.snsconn = sns.New(awsSnsSess) client.sqsconn = sqs.New(awsSqsSess) client.ssmconn = ssm.New(awsSsmSess) + client.storagegatewayconn = storagegateway.New(sess) client.swfconn = swf.New(sess) client.wafconn = waf.New(sess) client.wafregionalconn = wafregional.New(sess) diff --git a/aws/data_source_aws_storagegateway_gateway_activation_key.go b/aws/data_source_aws_storagegateway_gateway_activation_key.go deleted file mode 100644 index 7fe70663ce2..00000000000 --- a/aws/data_source_aws_storagegateway_gateway_activation_key.go +++ /dev/null @@ -1,94 +0,0 @@ -package aws - -import ( - "fmt" - "log" - "net" - "net/http" - "time" - - "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/helper/schema" - "github.com/hashicorp/terraform/helper/validation" -) - -func dataSourceAwsStorageGatewayGatewayActivationKey() *schema.Resource { - return &schema.Resource{ - Read: dataSourceAwsStorageGatewayGatewayActivationKeyRead, - Timeouts: &schema.ResourceTimeout{ - Read: schema.DefaultTimeout(10 * time.Minute), - }, - - Schema: map[string]*schema.Schema{ - "activation_key": { - Type: schema.TypeString, - Computed: true, - }, - "ip_address": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.SingleIP(), - }, - }, - } -} - -func dataSourceAwsStorageGatewayGatewayActivationKeyRead(d *schema.ResourceData, meta interface{}) error { - client := &http.Client{ - CheckRedirect: func(req *http.Request, via []*http.Request) error { - return http.ErrUseLastResponse - }, - Timeout: time.Second * 10, - } - - var activationKey string - activationRegion := meta.(*AWSClient).region - ipAddress := d.Get("ip_address").(string) - - requestURL := fmt.Sprintf("http://%s/?activationRegion=%s", ipAddress, activationRegion) - log.Printf("[DEBUG] Creating HTTP request: %s", requestURL) - request, err := http.NewRequest("GET", requestURL, nil) - if err != nil { - return fmt.Errorf("error creating HTTP request: %s", err) - } - - err = resource.Retry(d.Timeout(schema.TimeoutCreate), func() *resource.RetryError { - log.Printf("[DEBUG] Making HTTP request: %s", request.URL.String()) - response, err := client.Do(request) - if err != nil { - if err, ok := err.(net.Error); ok { - errMessage := fmt.Errorf("error making HTTP request: %s", err) - log.Printf("[DEBUG] retryable %s", errMessage) - return resource.RetryableError(errMessage) - } - return resource.NonRetryableError(fmt.Errorf("error making HTTP request: %s", err)) - } - - log.Printf("[DEBUG] Received HTTP response: %#v", response) - if response.StatusCode != 302 { - return resource.NonRetryableError(fmt.Errorf("expected HTTP status code 302, received: %d", response.StatusCode)) - } - - redirectURL, err := response.Location() - if err != nil { - return resource.NonRetryableError(fmt.Errorf("error extracting HTTP Location header: %s", err)) - } - - activationKey = redirectURL.Query().Get("activationKey") - - return nil - }) - if err != nil { - return fmt.Errorf("error retrieving activation key from IP Address (%s): %s", ipAddress, err) - } - if activationKey == "" { - return fmt.Errorf("empty activationKey received from IP Address: %s", ipAddress) - } - - d.SetId(activationKey) - d.Set("activation_key", activationKey) - d.Set("ip_address", d.Id()) - - return nil -} diff --git a/aws/data_source_aws_storagegateway_gateway_activation_key_test.go b/aws/data_source_aws_storagegateway_gateway_activation_key_test.go deleted file mode 100644 index 275aa48b011..00000000000 --- a/aws/data_source_aws_storagegateway_gateway_activation_key_test.go +++ /dev/null @@ -1,203 +0,0 @@ -package aws - -import ( - "fmt" - "testing" - - "github.com/hashicorp/terraform/helper/acctest" - "github.com/hashicorp/terraform/helper/resource" -) - -func TestAccAWSStorageGatewayGatewayActivationKeyDataSource_FileGateway(t *testing.T) { - rName := acctest.RandomWithPrefix("tf-acc-test") - dataSourceName := "data.aws_storagegateway_gateway_activation_key.test" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - Steps: []resource.TestStep{ - { - Config: testAccAWSStorageGatewayGatewayActivationKeyDataSourceConfig_FileGateway(rName), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttrSet(dataSourceName, "activation_key"), - ), - }, - }, - }) -} - -func TestAccAWSStorageGatewayGatewayActivationKeyDataSource_TapeAndVolumeGateway(t *testing.T) { - t.Skip("Currently the EC2 instance webserver is never reachable, its likely an instance configuration error.") - - rName := acctest.RandomWithPrefix("tf-acc-test") - dataSourceName := "data.aws_storagegateway_gateway_activation_key.test" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - Steps: []resource.TestStep{ - { - Config: testAccAWSStorageGatewayGatewayActivationKeyDataSourceConfig_TapeAndVolumeGateway(rName), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttrSet(dataSourceName, "activation_key"), - ), - }, - }, - }) -} - -// testAccAWSStorageGateway_VPCBase provides a publicly accessible subnet -// and security group, suitable for Storage Gateway EC2 instances of any type -func testAccAWSStorageGateway_VPCBase(rName string) string { - return fmt.Sprintf(` -resource "aws_vpc" "test" { - cidr_block = "10.0.0.0/16" - - tags { - Name = %q - } -} - -resource "aws_subnet" "test" { - cidr_block = "10.0.0.0/24" - vpc_id = "${aws_vpc.test.id}" - - tags { - Name = %q - } -} - -resource "aws_internet_gateway" "test" { - vpc_id = "${aws_vpc.test.id}" - - tags { - Name = %q - } -} - -resource "aws_route_table" "test" { - vpc_id = "${aws_vpc.test.id}" - - route { - cidr_block = "0.0.0.0/0" - gateway_id = "${aws_internet_gateway.test.id}" - } - - tags { - Name = %q - } -} - -resource "aws_route_table_association" "test" { - subnet_id = "${aws_subnet.test.id}" - route_table_id = "${aws_route_table.test.id}" -} - -resource "aws_security_group" "test" { - name = %q - vpc_id = "${aws_vpc.test.id}" - - egress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] - } - - ingress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] - } - - tags { - Name = %q - } -} -`, rName, rName, rName, rName, rName, rName) -} - -// testAccAWSStorageGateway_FileGatewayBase uses the "thinstaller" Storage -// Gateway AMI for File Gateways -func testAccAWSStorageGateway_FileGatewayBase(rName string) string { - return testAccAWSStorageGateway_VPCBase(rName) + fmt.Sprintf(` -data "aws_ami" "aws-thinstaller" { - most_recent = true - - filter { - name = "owner-alias" - values = ["amazon"] - } - - filter { - name = "name" - values = ["aws-thinstaller-*"] - } -} - -resource "aws_instance" "test" { - depends_on = ["aws_internet_gateway.test"] - - ami = "${data.aws_ami.aws-thinstaller.id}" - associate_public_ip_address = true - instance_type = "t2.micro" - vpc_security_group_ids = ["${aws_security_group.test.id}"] - subnet_id = "${aws_subnet.test.id}" - - tags { - Name = %q - } -} -`, rName) -} - -// testAccAWSStorageGateway_TapeAndVolumeGatewayBase uses the Storage Gateway -// AMI for either Tape or Volume Gateways -func testAccAWSStorageGateway_TapeAndVolumeGatewayBase(rName string) string { - return testAccAWSStorageGateway_VPCBase(rName) + fmt.Sprintf(` -data "aws_ami" "aws-storage-gateway-2" { - most_recent = true - - filter { - name = "owner-alias" - values = ["amazon"] - } - - filter { - name = "name" - values = ["aws-storage-gateway-2.*"] - } -} - -resource "aws_instance" "test" { - depends_on = ["aws_internet_gateway.test"] - - ami = "${data.aws_ami.aws-storage-gateway-2.id}" - associate_public_ip_address = true - instance_type = "t2.micro" - vpc_security_group_ids = ["${aws_security_group.test.id}"] - subnet_id = "${aws_subnet.test.id}" - - tags { - Name = %q - } -} -`, rName) -} - -func testAccAWSStorageGatewayGatewayActivationKeyDataSourceConfig_FileGateway(rName string) string { - return testAccAWSStorageGateway_FileGatewayBase(rName) + ` -data "aws_storagegateway_gateway_activation_key" "test" { - ip_address = "${aws_instance.test.public_ip}" -} -` -} - -func testAccAWSStorageGatewayGatewayActivationKeyDataSourceConfig_TapeAndVolumeGateway(rName string) string { - return testAccAWSStorageGateway_TapeAndVolumeGatewayBase(rName) + ` -data "aws_storagegateway_gateway_activation_key" "test" { - ip_address = "${aws_instance.test.public_ip}" -} -` -} diff --git a/aws/provider.go b/aws/provider.go index 69edf435d28..bef96b0a721 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -160,106 +160,105 @@ func Provider() terraform.ResourceProvider { }, DataSourcesMap: map[string]*schema.Resource{ - "aws_acm_certificate": dataSourceAwsAcmCertificate(), - "aws_acmpca_certificate_authority": dataSourceAwsAcmpcaCertificateAuthority(), - "aws_ami": dataSourceAwsAmi(), - "aws_ami_ids": dataSourceAwsAmiIds(), - "aws_api_gateway_rest_api": dataSourceAwsApiGatewayRestApi(), - "aws_arn": dataSourceAwsArn(), - "aws_autoscaling_groups": dataSourceAwsAutoscalingGroups(), - "aws_availability_zone": dataSourceAwsAvailabilityZone(), - "aws_availability_zones": dataSourceAwsAvailabilityZones(), - "aws_batch_compute_environment": dataSourceAwsBatchComputeEnvironment(), - "aws_batch_job_queue": dataSourceAwsBatchJobQueue(), - "aws_billing_service_account": dataSourceAwsBillingServiceAccount(), - "aws_caller_identity": dataSourceAwsCallerIdentity(), - "aws_canonical_user_id": dataSourceAwsCanonicalUserId(), - "aws_cloudformation_export": dataSourceAwsCloudFormationExport(), - "aws_cloudformation_stack": dataSourceAwsCloudFormationStack(), - "aws_cloudtrail_service_account": dataSourceAwsCloudTrailServiceAccount(), - "aws_cloudwatch_log_group": dataSourceAwsCloudwatchLogGroup(), - "aws_cognito_user_pools": dataSourceAwsCognitoUserPools(), - "aws_codecommit_repository": dataSourceAwsCodeCommitRepository(), - "aws_db_instance": dataSourceAwsDbInstance(), - "aws_db_snapshot": dataSourceAwsDbSnapshot(), - "aws_dx_gateway": dataSourceAwsDxGateway(), - "aws_dynamodb_table": dataSourceAwsDynamoDbTable(), - "aws_ebs_snapshot": dataSourceAwsEbsSnapshot(), - "aws_ebs_snapshot_ids": dataSourceAwsEbsSnapshotIds(), - "aws_ebs_volume": dataSourceAwsEbsVolume(), - "aws_ecr_repository": dataSourceAwsEcrRepository(), - "aws_ecs_cluster": dataSourceAwsEcsCluster(), - "aws_ecs_container_definition": dataSourceAwsEcsContainerDefinition(), - "aws_ecs_service": dataSourceAwsEcsService(), - "aws_ecs_task_definition": dataSourceAwsEcsTaskDefinition(), - "aws_efs_file_system": dataSourceAwsEfsFileSystem(), - "aws_efs_mount_target": dataSourceAwsEfsMountTarget(), - "aws_eip": dataSourceAwsEip(), - "aws_eks_cluster": dataSourceAwsEksCluster(), - "aws_elastic_beanstalk_hosted_zone": dataSourceAwsElasticBeanstalkHostedZone(), - "aws_elastic_beanstalk_solution_stack": dataSourceAwsElasticBeanstalkSolutionStack(), - "aws_elasticache_cluster": dataSourceAwsElastiCacheCluster(), - "aws_elb": dataSourceAwsElb(), - "aws_elasticache_replication_group": dataSourceAwsElasticacheReplicationGroup(), - "aws_elb_hosted_zone_id": dataSourceAwsElbHostedZoneId(), - "aws_elb_service_account": dataSourceAwsElbServiceAccount(), - "aws_glue_script": dataSourceAwsGlueScript(), - "aws_iam_account_alias": dataSourceAwsIamAccountAlias(), - "aws_iam_group": dataSourceAwsIAMGroup(), - "aws_iam_instance_profile": dataSourceAwsIAMInstanceProfile(), - "aws_iam_policy": dataSourceAwsIAMPolicy(), - "aws_iam_policy_document": dataSourceAwsIamPolicyDocument(), - "aws_iam_role": dataSourceAwsIAMRole(), - "aws_iam_server_certificate": dataSourceAwsIAMServerCertificate(), - "aws_iam_user": dataSourceAwsIAMUser(), - "aws_internet_gateway": dataSourceAwsInternetGateway(), - "aws_iot_endpoint": dataSourceAwsIotEndpoint(), - "aws_inspector_rules_packages": dataSourceAwsInspectorRulesPackages(), - "aws_instance": dataSourceAwsInstance(), - "aws_instances": dataSourceAwsInstances(), - "aws_ip_ranges": dataSourceAwsIPRanges(), - "aws_kinesis_stream": dataSourceAwsKinesisStream(), - "aws_kms_alias": dataSourceAwsKmsAlias(), - "aws_kms_ciphertext": dataSourceAwsKmsCiphertext(), - "aws_kms_key": dataSourceAwsKmsKey(), - "aws_kms_secret": dataSourceAwsKmsSecret(), - "aws_lambda_function": dataSourceAwsLambdaFunction(), - "aws_lambda_invocation": dataSourceAwsLambdaInvocation(), - "aws_launch_configuration": dataSourceAwsLaunchConfiguration(), - "aws_mq_broker": dataSourceAwsMqBroker(), - "aws_nat_gateway": dataSourceAwsNatGateway(), - "aws_network_acls": dataSourceAwsNetworkAcls(), - "aws_network_interface": dataSourceAwsNetworkInterface(), - "aws_partition": dataSourceAwsPartition(), - "aws_prefix_list": dataSourceAwsPrefixList(), - "aws_pricing_product": dataSourceAwsPricingProduct(), - "aws_rds_cluster": dataSourceAwsRdsCluster(), - "aws_redshift_cluster": dataSourceAwsRedshiftCluster(), - "aws_redshift_service_account": dataSourceAwsRedshiftServiceAccount(), - "aws_region": dataSourceAwsRegion(), - "aws_route": dataSourceAwsRoute(), - "aws_route_table": dataSourceAwsRouteTable(), - "aws_route_tables": dataSourceAwsRouteTables(), - "aws_route53_zone": dataSourceAwsRoute53Zone(), - "aws_s3_bucket": dataSourceAwsS3Bucket(), - "aws_s3_bucket_object": dataSourceAwsS3BucketObject(), - "aws_secretsmanager_secret": dataSourceAwsSecretsManagerSecret(), - "aws_secretsmanager_secret_version": dataSourceAwsSecretsManagerSecretVersion(), - "aws_sns_topic": dataSourceAwsSnsTopic(), - "aws_sqs_queue": dataSourceAwsSqsQueue(), - "aws_ssm_parameter": dataSourceAwsSsmParameter(), - "aws_storagegateway_gateway_activation_key": dataSourceAwsStorageGatewayGatewayActivationKey(), - "aws_subnet": dataSourceAwsSubnet(), - "aws_subnet_ids": dataSourceAwsSubnetIDs(), - "aws_vpcs": dataSourceAwsVpcs(), - "aws_security_group": dataSourceAwsSecurityGroup(), - "aws_security_groups": dataSourceAwsSecurityGroups(), - "aws_vpc": dataSourceAwsVpc(), - "aws_vpc_dhcp_options": dataSourceAwsVpcDhcpOptions(), - "aws_vpc_endpoint": dataSourceAwsVpcEndpoint(), - "aws_vpc_endpoint_service": dataSourceAwsVpcEndpointService(), - "aws_vpc_peering_connection": dataSourceAwsVpcPeeringConnection(), - "aws_vpn_gateway": dataSourceAwsVpnGateway(), + "aws_acm_certificate": dataSourceAwsAcmCertificate(), + "aws_acmpca_certificate_authority": dataSourceAwsAcmpcaCertificateAuthority(), + "aws_ami": dataSourceAwsAmi(), + "aws_ami_ids": dataSourceAwsAmiIds(), + "aws_api_gateway_rest_api": dataSourceAwsApiGatewayRestApi(), + "aws_arn": dataSourceAwsArn(), + "aws_autoscaling_groups": dataSourceAwsAutoscalingGroups(), + "aws_availability_zone": dataSourceAwsAvailabilityZone(), + "aws_availability_zones": dataSourceAwsAvailabilityZones(), + "aws_batch_compute_environment": dataSourceAwsBatchComputeEnvironment(), + "aws_batch_job_queue": dataSourceAwsBatchJobQueue(), + "aws_billing_service_account": dataSourceAwsBillingServiceAccount(), + "aws_caller_identity": dataSourceAwsCallerIdentity(), + "aws_canonical_user_id": dataSourceAwsCanonicalUserId(), + "aws_cloudformation_export": dataSourceAwsCloudFormationExport(), + "aws_cloudformation_stack": dataSourceAwsCloudFormationStack(), + "aws_cloudtrail_service_account": dataSourceAwsCloudTrailServiceAccount(), + "aws_cloudwatch_log_group": dataSourceAwsCloudwatchLogGroup(), + "aws_cognito_user_pools": dataSourceAwsCognitoUserPools(), + "aws_codecommit_repository": dataSourceAwsCodeCommitRepository(), + "aws_db_instance": dataSourceAwsDbInstance(), + "aws_db_snapshot": dataSourceAwsDbSnapshot(), + "aws_dx_gateway": dataSourceAwsDxGateway(), + "aws_dynamodb_table": dataSourceAwsDynamoDbTable(), + "aws_ebs_snapshot": dataSourceAwsEbsSnapshot(), + "aws_ebs_snapshot_ids": dataSourceAwsEbsSnapshotIds(), + "aws_ebs_volume": dataSourceAwsEbsVolume(), + "aws_ecr_repository": dataSourceAwsEcrRepository(), + "aws_ecs_cluster": dataSourceAwsEcsCluster(), + "aws_ecs_container_definition": dataSourceAwsEcsContainerDefinition(), + "aws_ecs_service": dataSourceAwsEcsService(), + "aws_ecs_task_definition": dataSourceAwsEcsTaskDefinition(), + "aws_efs_file_system": dataSourceAwsEfsFileSystem(), + "aws_efs_mount_target": dataSourceAwsEfsMountTarget(), + "aws_eip": dataSourceAwsEip(), + "aws_eks_cluster": dataSourceAwsEksCluster(), + "aws_elastic_beanstalk_hosted_zone": dataSourceAwsElasticBeanstalkHostedZone(), + "aws_elastic_beanstalk_solution_stack": dataSourceAwsElasticBeanstalkSolutionStack(), + "aws_elasticache_cluster": dataSourceAwsElastiCacheCluster(), + "aws_elb": dataSourceAwsElb(), + "aws_elasticache_replication_group": dataSourceAwsElasticacheReplicationGroup(), + "aws_elb_hosted_zone_id": dataSourceAwsElbHostedZoneId(), + "aws_elb_service_account": dataSourceAwsElbServiceAccount(), + "aws_glue_script": dataSourceAwsGlueScript(), + "aws_iam_account_alias": dataSourceAwsIamAccountAlias(), + "aws_iam_group": dataSourceAwsIAMGroup(), + "aws_iam_instance_profile": dataSourceAwsIAMInstanceProfile(), + "aws_iam_policy": dataSourceAwsIAMPolicy(), + "aws_iam_policy_document": dataSourceAwsIamPolicyDocument(), + "aws_iam_role": dataSourceAwsIAMRole(), + "aws_iam_server_certificate": dataSourceAwsIAMServerCertificate(), + "aws_iam_user": dataSourceAwsIAMUser(), + "aws_internet_gateway": dataSourceAwsInternetGateway(), + "aws_iot_endpoint": dataSourceAwsIotEndpoint(), + "aws_inspector_rules_packages": dataSourceAwsInspectorRulesPackages(), + "aws_instance": dataSourceAwsInstance(), + "aws_instances": dataSourceAwsInstances(), + "aws_ip_ranges": dataSourceAwsIPRanges(), + "aws_kinesis_stream": dataSourceAwsKinesisStream(), + "aws_kms_alias": dataSourceAwsKmsAlias(), + "aws_kms_ciphertext": dataSourceAwsKmsCiphertext(), + "aws_kms_key": dataSourceAwsKmsKey(), + "aws_kms_secret": dataSourceAwsKmsSecret(), + "aws_lambda_function": dataSourceAwsLambdaFunction(), + "aws_lambda_invocation": dataSourceAwsLambdaInvocation(), + "aws_launch_configuration": dataSourceAwsLaunchConfiguration(), + "aws_mq_broker": dataSourceAwsMqBroker(), + "aws_nat_gateway": dataSourceAwsNatGateway(), + "aws_network_acls": dataSourceAwsNetworkAcls(), + "aws_network_interface": dataSourceAwsNetworkInterface(), + "aws_partition": dataSourceAwsPartition(), + "aws_prefix_list": dataSourceAwsPrefixList(), + "aws_pricing_product": dataSourceAwsPricingProduct(), + "aws_rds_cluster": dataSourceAwsRdsCluster(), + "aws_redshift_cluster": dataSourceAwsRedshiftCluster(), + "aws_redshift_service_account": dataSourceAwsRedshiftServiceAccount(), + "aws_region": dataSourceAwsRegion(), + "aws_route": dataSourceAwsRoute(), + "aws_route_table": dataSourceAwsRouteTable(), + "aws_route_tables": dataSourceAwsRouteTables(), + "aws_route53_zone": dataSourceAwsRoute53Zone(), + "aws_s3_bucket": dataSourceAwsS3Bucket(), + "aws_s3_bucket_object": dataSourceAwsS3BucketObject(), + "aws_secretsmanager_secret": dataSourceAwsSecretsManagerSecret(), + "aws_secretsmanager_secret_version": dataSourceAwsSecretsManagerSecretVersion(), + "aws_sns_topic": dataSourceAwsSnsTopic(), + "aws_sqs_queue": dataSourceAwsSqsQueue(), + "aws_ssm_parameter": dataSourceAwsSsmParameter(), + "aws_subnet": dataSourceAwsSubnet(), + "aws_subnet_ids": dataSourceAwsSubnetIDs(), + "aws_vpcs": dataSourceAwsVpcs(), + "aws_security_group": dataSourceAwsSecurityGroup(), + "aws_security_groups": dataSourceAwsSecurityGroups(), + "aws_vpc": dataSourceAwsVpc(), + "aws_vpc_dhcp_options": dataSourceAwsVpcDhcpOptions(), + "aws_vpc_endpoint": dataSourceAwsVpcEndpoint(), + "aws_vpc_endpoint_service": dataSourceAwsVpcEndpointService(), + "aws_vpc_peering_connection": dataSourceAwsVpcPeeringConnection(), + "aws_vpn_gateway": dataSourceAwsVpnGateway(), // Adding the Aliases for the ALB -> LB Rename "aws_lb": dataSourceAwsLb(), @@ -582,6 +581,7 @@ func Provider() terraform.ResourceProvider { "aws_ssm_patch_group": resourceAwsSsmPatchGroup(), "aws_ssm_parameter": resourceAwsSsmParameter(), "aws_ssm_resource_data_sync": resourceAwsSsmResourceDataSync(), + "aws_storagegateway_gateway": resourceAwsStorageGatewayGateway(), "aws_spot_datafeed_subscription": resourceAwsSpotDataFeedSubscription(), "aws_spot_instance_request": resourceAwsSpotInstanceRequest(), "aws_spot_fleet_request": resourceAwsSpotFleetRequest(), diff --git a/aws/resource_aws_storagegateway_gateway.go b/aws/resource_aws_storagegateway_gateway.go new file mode 100644 index 00000000000..fca86b9f966 --- /dev/null +++ b/aws/resource_aws_storagegateway_gateway.go @@ -0,0 +1,286 @@ +package aws + +import ( + "fmt" + "log" + "net" + "net/http" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/storagegateway" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/helper/validation" +) + +func resourceAwsStorageGatewayGateway() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsStorageGatewayGatewayCreate, + Read: resourceAwsStorageGatewayGatewayRead, + Update: resourceAwsStorageGatewayGatewayUpdate, + Delete: resourceAwsStorageGatewayGatewayDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(10 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "arn": { + Type: schema.TypeString, + Computed: true, + }, + "activation_key": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + ConflictsWith: []string{"gateway_ip_address"}, + }, + "gateway_id": { + Type: schema.TypeString, + Computed: true, + }, + "gateway_ip_address": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + ConflictsWith: []string{"activation_key"}, + }, + "gateway_name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.NoZeroValues, + }, + "gateway_timezone": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.NoZeroValues, + }, + "gateway_type": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: "STORED", + ValidateFunc: validation.StringInSlice([]string{ + "CACHED", + "FILE_S3", + "STORED", + "VTL", + }, false), + }, + "medium_changer_type": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + "AWS-Gateway-VTL", + "STK-L700", + }, false), + }, + "tape_drive_type": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + "IBM-ULT3580-TD5", + }, false), + }, + }, + } +} + +func resourceAwsStorageGatewayGatewayCreate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).storagegatewayconn + region := meta.(*AWSClient).region + + activationKey := d.Get("activation_key").(string) + gatewayIpAddress := d.Get("gateway_ip_address").(string) + + // Perform one time fetch of activation key from gateway IP address + if activationKey == "" { + if gatewayIpAddress == "" { + return fmt.Errorf("either activation_key or gateway_ip_address must be provided") + } + + client := &http.Client{ + CheckRedirect: func(req *http.Request, via []*http.Request) error { + return http.ErrUseLastResponse + }, + Timeout: time.Second * 10, + } + + requestURL := fmt.Sprintf("http://%s/?activationRegion=%s", gatewayIpAddress, region) + log.Printf("[DEBUG] Creating HTTP request: %s", requestURL) + request, err := http.NewRequest("GET", requestURL, nil) + if err != nil { + return fmt.Errorf("error creating HTTP request: %s", err) + } + + err = resource.Retry(d.Timeout(schema.TimeoutCreate), func() *resource.RetryError { + log.Printf("[DEBUG] Making HTTP request: %s", request.URL.String()) + response, err := client.Do(request) + if err != nil { + if err, ok := err.(net.Error); ok { + errMessage := fmt.Errorf("error making HTTP request: %s", err) + log.Printf("[DEBUG] retryable %s", errMessage) + return resource.RetryableError(errMessage) + } + return resource.NonRetryableError(fmt.Errorf("error making HTTP request: %s", err)) + } + + log.Printf("[DEBUG] Received HTTP response: %#v", response) + if response.StatusCode != 302 { + return resource.NonRetryableError(fmt.Errorf("expected HTTP status code 302, received: %d", response.StatusCode)) + } + + redirectURL, err := response.Location() + if err != nil { + return resource.NonRetryableError(fmt.Errorf("error extracting HTTP Location header: %s", err)) + } + + activationKey = redirectURL.Query().Get("activationKey") + + return nil + }) + if err != nil { + return fmt.Errorf("error retrieving activation key from IP Address (%s): %s", gatewayIpAddress, err) + } + if activationKey == "" { + return fmt.Errorf("empty activationKey received from IP Address: %s", gatewayIpAddress) + } + } + + input := &storagegateway.ActivateGatewayInput{ + ActivationKey: aws.String(activationKey), + GatewayRegion: aws.String(region), + GatewayName: aws.String(d.Get("gateway_name").(string)), + GatewayTimezone: aws.String(d.Get("gateway_timezone").(string)), + GatewayType: aws.String(d.Get("gateway_type").(string)), + } + + if v, ok := d.GetOk("medium_changer_type"); ok { + input.MediumChangerType = aws.String(v.(string)) + } + + if v, ok := d.GetOk("tape_drive_type"); ok { + input.TapeDriveType = aws.String(v.(string)) + } + + log.Printf("[DEBUG] Activating Storage Gateway Gateway: %s", input) + output, err := conn.ActivateGateway(input) + if err != nil { + return fmt.Errorf("error activating Storage Gateway Gateway: %s", err) + } + + d.SetId(aws.StringValue(output.GatewayARN)) + + // Gateway activations can take a few minutes + err = resource.Retry(d.Timeout(schema.TimeoutCreate), func() *resource.RetryError { + _, err := conn.DescribeGatewayInformation(&storagegateway.DescribeGatewayInformationInput{ + GatewayARN: aws.String(d.Id()), + }) + if err != nil { + if isAWSErr(err, storagegateway.ErrorCodeGatewayNotConnected, "") { + return resource.RetryableError(err) + } + if isAWSErr(err, storagegateway.ErrCodeInvalidGatewayRequestException, "") { + return resource.RetryableError(err) + } + return resource.NonRetryableError(err) + } + + return nil + }) + if err != nil { + return fmt.Errorf("error waiting for Storage Gateway Gateway activation: %s", err) + } + + return resourceAwsStorageGatewayGatewayRead(d, meta) +} + +func resourceAwsStorageGatewayGatewayRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).storagegatewayconn + + input := &storagegateway.DescribeGatewayInformationInput{ + GatewayARN: aws.String(d.Id()), + } + + log.Printf("[DEBUG] Reading Storage Gateway Gateway: %s", input) + output, err := conn.DescribeGatewayInformation(input) + if err != nil { + if isAWSErrStorageGatewayGatewayNotFound(err) { + log.Printf("[WARN] Storage Gateway Gateway %q not found - removing from state", d.Id()) + d.SetId("") + return nil + } + return fmt.Errorf("error reading Storage Gateway Gateway: %s", err) + } + + // The Storage Gateway API currently provides no way to read this value + d.Set("activation_key", d.Get("activation_key").(string)) + d.Set("arn", output.GatewayARN) + d.Set("gateway_id", output.GatewayId) + // The Storage Gateway API currently provides no way to read this value + d.Set("gateway_ip_address", d.Get("gateway_ip_address").(string)) + d.Set("gateway_name", output.GatewayName) + d.Set("gateway_timezone", output.GatewayTimezone) + d.Set("gateway_type", output.GatewayType) + // The Storage Gateway API currently provides no way to read this value + d.Set("medium_changer_type", d.Get("medium_changer_type").(string)) + // The Storage Gateway API currently provides no way to read this value + d.Set("tape_drive_type", d.Get("tape_drive_type").(string)) + + return nil +} + +func resourceAwsStorageGatewayGatewayUpdate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).storagegatewayconn + + input := &storagegateway.UpdateGatewayInformationInput{ + GatewayARN: aws.String(d.Id()), + GatewayName: aws.String(d.Get("gateway_name").(string)), + GatewayTimezone: aws.String(d.Get("gateway_timezone").(string)), + } + + log.Printf("[DEBUG] Updating Storage Gateway Gateway: %s", input) + _, err := conn.UpdateGatewayInformation(input) + if err != nil { + return fmt.Errorf("error updating Storage Gateway Gateway: %s", err) + } + + return resourceAwsStorageGatewayGatewayRead(d, meta) +} + +func resourceAwsStorageGatewayGatewayDelete(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).storagegatewayconn + + input := &storagegateway.DeleteGatewayInput{ + GatewayARN: aws.String(d.Id()), + } + + log.Printf("[DEBUG] Deleting Storage Gateway Gateway: %s", input) + _, err := conn.DeleteGateway(input) + if err != nil { + if isAWSErrStorageGatewayGatewayNotFound(err) { + return nil + } + return fmt.Errorf("error deleting Storage Gateway Gateway: %s", err) + } + + return nil +} + +// The API returns multiple responses for a missing gateway +func isAWSErrStorageGatewayGatewayNotFound(err error) bool { + if isAWSErr(err, storagegateway.ErrCodeInvalidGatewayRequestException, "The specified gateway was not found.") { + return true + } + if isAWSErr(err, storagegateway.ErrorCodeGatewayNotFound, "") { + return true + } + return false +} diff --git a/aws/resource_aws_storagegateway_gateway_test.go b/aws/resource_aws_storagegateway_gateway_test.go new file mode 100644 index 00000000000..f312eb3df3f --- /dev/null +++ b/aws/resource_aws_storagegateway_gateway_test.go @@ -0,0 +1,518 @@ +package aws + +import ( + "fmt" + "log" + "regexp" + "strings" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/storagegateway" + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func init() { + resource.AddTestSweepers("aws_storagegateway_gateway", &resource.Sweeper{ + Name: "aws_storagegateway_gateway", + F: testSweepStorageGatewayGateways, + }) +} + +func testSweepStorageGatewayGateways(region string) error { + client, err := sharedClientForRegion(region) + if err != nil { + return fmt.Errorf("error getting client: %s", err) + } + conn := client.(*AWSClient).storagegatewayconn + + err = conn.ListGatewaysPages(&storagegateway.ListGatewaysInput{}, func(page *storagegateway.ListGatewaysOutput, isLast bool) bool { + if len(page.Gateways) == 0 { + log.Print("[DEBUG] No Storage Gateway Gateways to sweep") + return true + } + + for _, gateway := range page.Gateways { + name := aws.StringValue(gateway.GatewayName) + if !strings.HasPrefix(name, "tf-acc-test-") { + log.Printf("[INFO] Skipping Storage Gateway Gateway: %s", name) + continue + } + log.Printf("[INFO] Deleting Storage Gateway Gateway: %s", name) + input := &storagegateway.DeleteGatewayInput{ + GatewayARN: gateway.GatewayARN, + } + + _, err := conn.DeleteGateway(input) + if err != nil { + if isAWSErr(err, storagegateway.ErrorCodeGatewayNotFound, "") { + continue + } + log.Printf("[ERROR] Failed to delete Storage Gateway Gateway (%s): %s", name, err) + } + } + + return !isLast + }) + if err != nil { + if testSweepSkipSweepError(err) { + log.Printf("[WARN] Skipping Storage Gateway Gateway sweep for %s: %s", region, err) + return nil + } + return fmt.Errorf("Error retrieving Storage Gateway Gateways: %s", err) + } + return nil +} + +func TestAccAWSStorageGatewayGateway_GatewayType_Cached(t *testing.T) { + var gateway storagegateway.DescribeGatewayInformationOutput + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_storagegateway_gateway.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSStorageGatewayGatewayDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSStorageGatewayGatewayConfig_GatewayType_Cached(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSStorageGatewayGatewayExists(resourceName, &gateway), + resource.TestMatchResourceAttr(resourceName, "arn", regexp.MustCompile(`^arn:[^:]+:storagegateway:[^:]+:[^:]+:gateway/sgw-.+$`)), + resource.TestCheckResourceAttrSet(resourceName, "gateway_id"), + resource.TestCheckResourceAttr(resourceName, "gateway_name", rName), + resource.TestCheckResourceAttr(resourceName, "gateway_timezone", "GMT"), + resource.TestCheckResourceAttr(resourceName, "gateway_type", "CACHED"), + resource.TestCheckResourceAttr(resourceName, "medium_changer_type", ""), + resource.TestCheckResourceAttr(resourceName, "tape_drive_type", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"activation_key", "gateway_ip_address"}, + }, + }, + }) +} + +func TestAccAWSStorageGatewayGateway_GatewayType_FileS3(t *testing.T) { + var gateway storagegateway.DescribeGatewayInformationOutput + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_storagegateway_gateway.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSStorageGatewayGatewayDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSStorageGatewayGatewayConfig_GatewayType_FileS3(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSStorageGatewayGatewayExists(resourceName, &gateway), + resource.TestMatchResourceAttr(resourceName, "arn", regexp.MustCompile(`^arn:[^:]+:storagegateway:[^:]+:[^:]+:gateway/sgw-.+$`)), + resource.TestCheckResourceAttrSet(resourceName, "gateway_id"), + resource.TestCheckResourceAttr(resourceName, "gateway_name", rName), + resource.TestCheckResourceAttr(resourceName, "gateway_timezone", "GMT"), + resource.TestCheckResourceAttr(resourceName, "gateway_type", "FILE_S3"), + resource.TestCheckResourceAttr(resourceName, "medium_changer_type", ""), + resource.TestCheckResourceAttr(resourceName, "tape_drive_type", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"activation_key", "gateway_ip_address"}, + }, + }, + }) +} + +func TestAccAWSStorageGatewayGateway_GatewayType_Stored(t *testing.T) { + var gateway storagegateway.DescribeGatewayInformationOutput + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_storagegateway_gateway.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSStorageGatewayGatewayDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSStorageGatewayGatewayConfig_GatewayType_Stored(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSStorageGatewayGatewayExists(resourceName, &gateway), + resource.TestMatchResourceAttr(resourceName, "arn", regexp.MustCompile(`^arn:[^:]+:storagegateway:[^:]+:[^:]+:gateway/sgw-.+$`)), + resource.TestCheckResourceAttrSet(resourceName, "gateway_id"), + resource.TestCheckResourceAttr(resourceName, "gateway_name", rName), + resource.TestCheckResourceAttr(resourceName, "gateway_timezone", "GMT"), + resource.TestCheckResourceAttr(resourceName, "gateway_type", "STORED"), + resource.TestCheckResourceAttr(resourceName, "medium_changer_type", ""), + resource.TestCheckResourceAttr(resourceName, "tape_drive_type", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"activation_key", "gateway_ip_address"}, + }, + }, + }) +} + +func TestAccAWSStorageGatewayGateway_GatewayType_Vtl(t *testing.T) { + var gateway storagegateway.DescribeGatewayInformationOutput + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_storagegateway_gateway.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSStorageGatewayGatewayDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSStorageGatewayGatewayConfig_GatewayType_Vtl(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSStorageGatewayGatewayExists(resourceName, &gateway), + resource.TestMatchResourceAttr(resourceName, "arn", regexp.MustCompile(`^arn:[^:]+:storagegateway:[^:]+:[^:]+:gateway/sgw-.+$`)), + resource.TestCheckResourceAttrSet(resourceName, "gateway_id"), + resource.TestCheckResourceAttr(resourceName, "gateway_name", rName), + resource.TestCheckResourceAttr(resourceName, "gateway_timezone", "GMT"), + resource.TestCheckResourceAttr(resourceName, "gateway_type", "VTL"), + resource.TestCheckResourceAttr(resourceName, "medium_changer_type", ""), + resource.TestCheckResourceAttr(resourceName, "tape_drive_type", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"activation_key", "gateway_ip_address"}, + }, + }, + }) +} + +func TestAccAWSStorageGatewayGateway_GatewayName(t *testing.T) { + var gateway storagegateway.DescribeGatewayInformationOutput + rName1 := acctest.RandomWithPrefix("tf-acc-test") + rName2 := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_storagegateway_gateway.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSStorageGatewayGatewayDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSStorageGatewayGatewayConfig_GatewayType_FileS3(rName1), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSStorageGatewayGatewayExists(resourceName, &gateway), + resource.TestCheckResourceAttr(resourceName, "gateway_name", rName1), + ), + }, + { + Config: testAccAWSStorageGatewayGatewayConfig_GatewayType_FileS3(rName2), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSStorageGatewayGatewayExists(resourceName, &gateway), + resource.TestCheckResourceAttr(resourceName, "gateway_name", rName2), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"activation_key", "gateway_ip_address"}, + }, + }, + }) +} + +func TestAccAWSStorageGatewayGateway_GatewayTimezone(t *testing.T) { + var gateway storagegateway.DescribeGatewayInformationOutput + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_storagegateway_gateway.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSStorageGatewayGatewayDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSStorageGatewayGatewayConfig_GatewayTimezone(rName, "GMT-1:00"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSStorageGatewayGatewayExists(resourceName, &gateway), + resource.TestCheckResourceAttr(resourceName, "gateway_timezone", "GMT-1:00"), + ), + }, + { + Config: testAccAWSStorageGatewayGatewayConfig_GatewayTimezone(rName, "GMT-2:00"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSStorageGatewayGatewayExists(resourceName, &gateway), + resource.TestCheckResourceAttr(resourceName, "gateway_timezone", "GMT-2:00"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"activation_key", "gateway_ip_address"}, + }, + }, + }) +} + +func testAccCheckAWSStorageGatewayGatewayDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).storagegatewayconn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_storagegateway_gateway" { + continue + } + + input := &storagegateway.DescribeGatewayInformationInput{ + GatewayARN: aws.String(rs.Primary.ID), + } + + _, err := conn.DescribeGatewayInformation(input) + + if err != nil { + if isAWSErrStorageGatewayGatewayNotFound(err) { + return nil + } + return err + } + } + + return nil + +} + +func testAccCheckAWSStorageGatewayGatewayExists(resourceName string, gateway *storagegateway.DescribeGatewayInformationOutput) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Not found: %s", resourceName) + } + + conn := testAccProvider.Meta().(*AWSClient).storagegatewayconn + input := &storagegateway.DescribeGatewayInformationInput{ + GatewayARN: aws.String(rs.Primary.ID), + } + + output, err := conn.DescribeGatewayInformation(input) + + if err != nil { + return err + } + + if output == nil { + return fmt.Errorf("Gateway %q does not exist", rs.Primary.ID) + } + + *gateway = *output + + return nil + } +} + +// testAccAWSStorageGateway_VPCBase provides a publicly accessible subnet +// and security group, suitable for Storage Gateway EC2 instances of any type +func testAccAWSStorageGateway_VPCBase(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { + cidr_block = "10.0.0.0/16" + + tags { + Name = %q + } +} + +resource "aws_subnet" "test" { + cidr_block = "10.0.0.0/24" + vpc_id = "${aws_vpc.test.id}" + + tags { + Name = %q + } +} + +resource "aws_internet_gateway" "test" { + vpc_id = "${aws_vpc.test.id}" + + tags { + Name = %q + } +} + +resource "aws_route_table" "test" { + vpc_id = "${aws_vpc.test.id}" + + route { + cidr_block = "0.0.0.0/0" + gateway_id = "${aws_internet_gateway.test.id}" + } + + tags { + Name = %q + } +} + +resource "aws_route_table_association" "test" { + subnet_id = "${aws_subnet.test.id}" + route_table_id = "${aws_route_table.test.id}" +} + +resource "aws_security_group" "test" { + vpc_id = "${aws_vpc.test.id}" + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + ingress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + tags { + Name = %q + } +} +`, rName, rName, rName, rName, rName) +} + +// testAccAWSStorageGateway_FileGatewayBase uses the "thinstaller" Storage +// Gateway AMI for File Gateways +func testAccAWSStorageGateway_FileGatewayBase(rName string) string { + return testAccAWSStorageGateway_VPCBase(rName) + fmt.Sprintf(` +data "aws_ami" "aws-thinstaller" { + most_recent = true + + filter { + name = "owner-alias" + values = ["amazon"] + } + + filter { + name = "name" + values = ["aws-thinstaller-*"] + } +} + +resource "aws_instance" "test" { + depends_on = ["aws_internet_gateway.test"] + + ami = "${data.aws_ami.aws-thinstaller.id}" + associate_public_ip_address = true + # https://docs.aws.amazon.com/storagegateway/latest/userguide/Requirements.html + instance_type = "m4.xlarge" + vpc_security_group_ids = ["${aws_security_group.test.id}"] + subnet_id = "${aws_subnet.test.id}" + + tags { + Name = %q + } +} +`, rName) +} + +// testAccAWSStorageGateway_TapeAndVolumeGatewayBase uses the Storage Gateway +// AMI for either Tape or Volume Gateways +func testAccAWSStorageGateway_TapeAndVolumeGatewayBase(rName string) string { + return testAccAWSStorageGateway_VPCBase(rName) + fmt.Sprintf(` +data "aws_ami" "aws-storage-gateway-2" { + most_recent = true + + filter { + name = "owner-alias" + values = ["amazon"] + } + + filter { + name = "name" + values = ["aws-storage-gateway-2.*"] + } +} + +resource "aws_instance" "test" { + depends_on = ["aws_internet_gateway.test"] + + ami = "${data.aws_ami.aws-storage-gateway-2.id}" + associate_public_ip_address = true + # https://docs.aws.amazon.com/storagegateway/latest/userguide/Requirements.html + instance_type = "m4.xlarge" + vpc_security_group_ids = ["${aws_security_group.test.id}"] + subnet_id = "${aws_subnet.test.id}" + + tags { + Name = %q + } +} +`, rName) +} + +func testAccAWSStorageGatewayGatewayConfig_GatewayType_Cached(rName string) string { + return testAccAWSStorageGateway_TapeAndVolumeGatewayBase(rName) + fmt.Sprintf(` +resource "aws_storagegateway_gateway" "test" { + gateway_ip_address = "${aws_instance.test.public_ip}" + gateway_name = %q + gateway_timezone = "GMT" + gateway_type = "CACHED" +} +`, rName) +} + +func testAccAWSStorageGatewayGatewayConfig_GatewayType_FileS3(rName string) string { + return testAccAWSStorageGateway_FileGatewayBase(rName) + fmt.Sprintf(` +resource "aws_storagegateway_gateway" "test" { + gateway_ip_address = "${aws_instance.test.public_ip}" + gateway_name = %q + gateway_timezone = "GMT" + gateway_type = "FILE_S3" +} +`, rName) +} + +func testAccAWSStorageGatewayGatewayConfig_GatewayType_Stored(rName string) string { + return testAccAWSStorageGateway_TapeAndVolumeGatewayBase(rName) + fmt.Sprintf(` +resource "aws_storagegateway_gateway" "test" { + gateway_ip_address = "${aws_instance.test.public_ip}" + gateway_name = %q + gateway_timezone = "GMT" + gateway_type = "STORED" +} +`, rName) +} + +func testAccAWSStorageGatewayGatewayConfig_GatewayType_Vtl(rName string) string { + return testAccAWSStorageGateway_TapeAndVolumeGatewayBase(rName) + fmt.Sprintf(` +resource "aws_storagegateway_gateway" "test" { + gateway_ip_address = "${aws_instance.test.public_ip}" + gateway_name = %q + gateway_timezone = "GMT" + gateway_type = "VTL" +} +`, rName) +} + +func testAccAWSStorageGatewayGatewayConfig_GatewayTimezone(rName, gatewayTimezone string) string { + return testAccAWSStorageGateway_FileGatewayBase(rName) + fmt.Sprintf(` +resource "aws_storagegateway_gateway" "test" { + gateway_ip_address = "${aws_instance.test.public_ip}" + gateway_name = %q + gateway_timezone = %q + gateway_type = "FILE_S3" +} +`, rName, gatewayTimezone) +} diff --git a/website/aws.erb b/website/aws.erb index 8e2b70f7ab6..db7fdaa08b4 100644 --- a/website/aws.erb +++ b/website/aws.erb @@ -328,9 +328,6 @@ > aws_ssm_parameter - > - aws_storagegateway_gateway_activation_key - > aws_subnet @@ -2111,6 +2108,17 @@ + > + Storage Gateway Resources + + + > SWF Resources