From db9b9b179209bff0a243bc44d068ba111c5e0e68 Mon Sep 17 00:00:00 2001 From: Brian Flad Date: Fri, 20 Jul 2018 16:33:58 -0400 Subject: [PATCH 1/2] New Resource: aws_storagegateway_cache --- aws/provider.go | 1 + aws/resource_aws_storagegateway_cache.go | 131 ++++++++++++++ aws/resource_aws_storagegateway_cache_test.go | 165 ++++++++++++++++++ website/aws.erb | 4 + .../docs/r/storagegateway_cache.html.markdown | 43 +++++ 5 files changed, 344 insertions(+) create mode 100644 aws/resource_aws_storagegateway_cache.go create mode 100644 aws/resource_aws_storagegateway_cache_test.go create mode 100644 website/docs/r/storagegateway_cache.html.markdown diff --git a/aws/provider.go b/aws/provider.go index c1912d77a4a..6d1859af9ac 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -585,6 +585,7 @@ func Provider() terraform.ResourceProvider { "aws_ssm_patch_group": resourceAwsSsmPatchGroup(), "aws_ssm_parameter": resourceAwsSsmParameter(), "aws_ssm_resource_data_sync": resourceAwsSsmResourceDataSync(), + "aws_storagegateway_cache": resourceAwsStorageGatewayCache(), "aws_storagegateway_gateway": resourceAwsStorageGatewayGateway(), "aws_storagegateway_nfs_file_share": resourceAwsStorageGatewayNfsFileShare(), "aws_storagegateway_upload_buffer": resourceAwsStorageGatewayUploadBuffer(), diff --git a/aws/resource_aws_storagegateway_cache.go b/aws/resource_aws_storagegateway_cache.go new file mode 100644 index 00000000000..24b720431dc --- /dev/null +++ b/aws/resource_aws_storagegateway_cache.go @@ -0,0 +1,131 @@ +package aws + +import ( + "fmt" + "log" + "strings" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/arn" + "github.com/aws/aws-sdk-go/service/storagegateway" + "github.com/hashicorp/terraform/helper/schema" +) + +func resourceAwsStorageGatewayCache() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsStorageGatewayCacheCreate, + Read: resourceAwsStorageGatewayCacheRead, + Delete: schema.Noop, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "disk_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "gateway_arn": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validateArn, + }, + }, + } +} + +func resourceAwsStorageGatewayCacheCreate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).storagegatewayconn + + diskID := d.Get("disk_id").(string) + gatewayARN := d.Get("gateway_arn").(string) + + input := &storagegateway.AddCacheInput{ + DiskIds: []*string{aws.String(diskID)}, + GatewayARN: aws.String(gatewayARN), + } + + log.Printf("[DEBUG] Adding Storage Gateway cache: %s", input) + _, err := conn.AddCache(input) + if err != nil { + return fmt.Errorf("error adding Storage Gateway cache: %s", err) + } + + d.SetId(fmt.Sprintf("%s:%s", gatewayARN, diskID)) + + return resourceAwsStorageGatewayCacheRead(d, meta) +} + +func resourceAwsStorageGatewayCacheRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).storagegatewayconn + + gatewayARN, diskID, err := decodeStorageGatewayID(d.Id()) + if err != nil { + return err + } + + input := &storagegateway.DescribeCacheInput{ + GatewayARN: aws.String(gatewayARN), + } + + log.Printf("[DEBUG] Reading Storage Gateway cache: %s", input) + output, err := conn.DescribeCache(input) + if err != nil { + if isAWSErrStorageGatewayGatewayNotFound(err) { + log.Printf("[WARN] Storage Gateway cache %q not found - removing from state", d.Id()) + d.SetId("") + return nil + } + return fmt.Errorf("error reading Storage Gateway cache: %s", err) + } + + if output == nil || len(output.DiskIds) == 0 { + log.Printf("[WARN] Storage Gateway cache %q not found - removing from state", d.Id()) + d.SetId("") + return nil + } + + found := false + for _, existingDiskID := range output.DiskIds { + if aws.StringValue(existingDiskID) == diskID { + found = true + break + } + } + + if !found { + log.Printf("[WARN] Storage Gateway cache %q not found - removing from state", d.Id()) + d.SetId("") + return nil + } + + d.Set("disk_id", diskID) + d.Set("gateway_arn", gatewayARN) + + return nil +} + +func decodeStorageGatewayID(id string) (string, string, error) { + // id = arn:aws:storagegateway:us-east-1:123456789012:gateway/sgw-12345678:pci-0000:03:00.0-scsi-0:0:0:0 + idFormatErr := fmt.Errorf("expected ID in form of GatewayARN:DiskId, received: %s", id) + gatewayARNAndDisk, err := arn.Parse(id) + if err != nil { + return "", "", idFormatErr + } + // gatewayARNAndDisk.Resource = gateway/sgw-12345678:pci-0000:03:00.0-scsi-0:0:0:0 + resourceParts := strings.SplitN(gatewayARNAndDisk.Resource, ":", 2) + if len(resourceParts) != 2 { + return "", "", idFormatErr + } + // resourceParts = ["gateway/sgw-12345678", "pci-0000:03:00.0-scsi-0:0:0:0"] + gatewayARN := &arn.ARN{ + AccountID: gatewayARNAndDisk.AccountID, + Partition: gatewayARNAndDisk.Partition, + Region: gatewayARNAndDisk.Region, + Service: gatewayARNAndDisk.Service, + Resource: resourceParts[0], + } + return gatewayARN.String(), resourceParts[1], nil +} diff --git a/aws/resource_aws_storagegateway_cache_test.go b/aws/resource_aws_storagegateway_cache_test.go new file mode 100644 index 00000000000..9a9cc637d96 --- /dev/null +++ b/aws/resource_aws_storagegateway_cache_test.go @@ -0,0 +1,165 @@ +package aws + +import ( + "fmt" + "regexp" + "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 TestDecodeStorageGatewayCacheID(t *testing.T) { + var testCases = []struct { + Input string + ExpectedGatewayARN string + ExpectedDiskID string + ErrCount int + }{ + { + Input: "arn:aws:storagegateway:us-east-1:123456789012:gateway/sgw-12345678:pci-0000:03:00.0-scsi-0:0:0:0", + ExpectedGatewayARN: "arn:aws:storagegateway:us-east-1:123456789012:gateway/sgw-12345678", + ExpectedDiskID: "pci-0000:03:00.0-scsi-0:0:0:0", + ErrCount: 0, + }, + { + Input: "sgw-12345678:pci-0000:03:00.0-scsi-0:0:0:0", + ErrCount: 1, + }, + { + Input: "example:pci-0000:03:00.0-scsi-0:0:0:0", + ErrCount: 1, + }, + { + Input: "arn:aws:storagegateway:us-east-1:123456789012:gateway/sgw-12345678", + ErrCount: 1, + }, + { + Input: "pci-0000:03:00.0-scsi-0:0:0:0", + ErrCount: 1, + }, + { + Input: "gateway/sgw-12345678", + ErrCount: 1, + }, + { + Input: "sgw-12345678", + ErrCount: 1, + }, + } + + for _, tc := range testCases { + gatewayARN, diskID, err := decodeStorageGatewayID(tc.Input) + if tc.ErrCount == 0 && err != nil { + t.Fatalf("expected %q not to trigger an error, received: %s", tc.Input, err) + } + if tc.ErrCount > 0 && err == nil { + t.Fatalf("expected %q to trigger an error", tc.Input) + } + if gatewayARN != tc.ExpectedGatewayARN { + t.Fatalf("expected %q to return Gateway ARN %q, received: %s", tc.Input, tc.ExpectedGatewayARN, gatewayARN) + } + if diskID != tc.ExpectedDiskID { + t.Fatalf("expected %q to return Disk ID %q, received: %s", tc.Input, tc.ExpectedDiskID, diskID) + } + } +} + +func TestAccAWSStorageGatewayCache_Basic(t *testing.T) { + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_storagegateway_cache.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + // Storage Gateway API does not support removing caches + // CheckDestroy: testAccCheckAWSStorageGatewayCacheDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSStorageGatewayCacheConfig_Basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSStorageGatewayCacheExists(resourceName), + resource.TestCheckResourceAttrSet(resourceName, "disk_id"), + resource.TestMatchResourceAttr(resourceName, "gateway_arn", regexp.MustCompile(`^arn:[^:]+:storagegateway:[^:]+:[^:]+:gateway/sgw-.+$`)), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccCheckAWSStorageGatewayCacheExists(resourceName string) 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 + + gatewayARN, diskID, err := decodeStorageGatewayID(rs.Primary.ID) + if err != nil { + return err + } + + input := &storagegateway.DescribeCacheInput{ + GatewayARN: aws.String(gatewayARN), + } + + output, err := conn.DescribeCache(input) + + if err != nil { + return fmt.Errorf("error reading Storage Gateway cache: %s", err) + } + + if output == nil || len(output.DiskIds) == 0 { + return fmt.Errorf("Storage Gateway cache %q not found", rs.Primary.ID) + } + + for _, existingDiskID := range output.DiskIds { + if aws.StringValue(existingDiskID) == diskID { + return nil + } + } + + return fmt.Errorf("Storage Gateway cache %q not found", rs.Primary.ID) + } +} + +func testAccAWSStorageGatewayCacheConfig_Basic(rName string) string { + return testAccAWSStorageGatewayGatewayConfig_GatewayType_FileS3(rName) + fmt.Sprintf(` +resource "aws_ebs_volume" "test" { + availability_zone = "${aws_instance.test.availability_zone}" + size = "10" + type = "gp2" + + tags { + Name = %q + } +} + +resource "aws_volume_attachment" "test" { + device_name = "/dev/xvdb" + force_detach = true + instance_id = "${aws_instance.test.id}" + volume_id = "${aws_ebs_volume.test.id}" +} + +data "aws_storagegateway_local_disk" "test" { + disk_path = "${aws_volume_attachment.test.device_name}" + gateway_arn = "${aws_storagegateway_gateway.test.arn}" +} + +resource "aws_storagegateway_cache" "test" { + disk_id = "${data.aws_storagegateway_local_disk.test.id}" + gateway_arn = "${aws_storagegateway_gateway.test.arn}" +} +`, rName) +} diff --git a/website/aws.erb b/website/aws.erb index b01383b131b..b62dbe499e4 100644 --- a/website/aws.erb +++ b/website/aws.erb @@ -2140,6 +2140,10 @@ Storage Gateway Resources