From 685dc35a6bde993ae87b5089e0e2cfedf07504bb Mon Sep 17 00:00:00 2001 From: Jakub Kania Date: Wed, 4 Sep 2019 00:19:06 +0200 Subject: [PATCH] Add AWS Lightsail Disk resource --- aws/provider.go | 1 + aws/resource_aws_lightsail_disk.go | 120 ++++++++++ aws/resource_aws_lightsail_disk_test.go | 241 ++++++++++++++++++++ website/aws.erb | 3 + website/docs/r/lightsail_disk.html.markdown | 48 ++++ 5 files changed, 413 insertions(+) create mode 100644 aws/resource_aws_lightsail_disk.go create mode 100644 aws/resource_aws_lightsail_disk_test.go create mode 100644 website/docs/r/lightsail_disk.html.markdown diff --git a/aws/provider.go b/aws/provider.go index abe8391c72ff..4885394cde4e 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -620,6 +620,7 @@ func Provider() terraform.ResourceProvider { "aws_licensemanager_license_configuration": resourceAwsLicenseManagerLicenseConfiguration(), "aws_lightsail_domain": resourceAwsLightsailDomain(), "aws_lightsail_instance": resourceAwsLightsailInstance(), + "aws_lightsail_disk": resourceAwsLightsailDisk(), "aws_lightsail_key_pair": resourceAwsLightsailKeyPair(), "aws_lightsail_static_ip": resourceAwsLightsailStaticIp(), "aws_lightsail_static_ip_attachment": resourceAwsLightsailStaticIpAttachment(), diff --git a/aws/resource_aws_lightsail_disk.go b/aws/resource_aws_lightsail_disk.go new file mode 100644 index 000000000000..271765661170 --- /dev/null +++ b/aws/resource_aws_lightsail_disk.go @@ -0,0 +1,120 @@ +package aws + +import ( + "fmt" + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/lightsail" + "github.com/hashicorp/terraform/helper/schema" + "log" + "time" +) + +func resourceAwsLightsailDisk() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsLightsailDiskCreate, + Read: resourceAwsLightsailDiskRead, + Delete: resourceAwsLightsailDiskDelete, + Update: resourceAwsLightsailDiskUpdate, + + Schema: map[string]*schema.Schema{ + "availability_zone": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "created_at": { + Type: schema.TypeString, + Computed: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "size": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + }, + "tags": tagsSchema(), + }, + } +} + +func resourceAwsLightsailDiskCreate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).lightsailconn + req := &lightsail.CreateDiskInput{ + DiskName: aws.String(d.Get("name").(string)), + AvailabilityZone: aws.String(d.Get("availability_zone").(string)), + SizeInGb: aws.Int64(int64(d.Get("size").(int))), + } + + tags := tagsFromMapLightsail(d.Get("tags").(map[string]interface{})) + + if len(tags) != 0 { + req.Tags = tags + } + + _, err := conn.CreateDisk(req) + + if err != nil { + return err + } + // The name is unique for all resource per az so we can use it as the id + d.SetId(d.Get("name").(string)) + + return resourceAwsLightsailDiskRead(d, meta) +} + +func resourceAwsLightsailDiskRead(d *schema.ResourceData, meta interface{}) error { + + conn := meta.(*AWSClient).lightsailconn + resp, err := conn.GetDisk(&lightsail.GetDiskInput{ + DiskName: aws.String(d.Id()), + }) + + if err != nil { + return err + } + + if resp == nil { + log.Printf("[WARN] Lightsail Disk (%s) not found, nil response from server, removing from state", d.Id()) + d.SetId("") + return nil + } + + i := resp.Disk + + d.Set("name", i.Name) + d.Set("availability_zone", i.Location) + d.Set("size", i.SizeInGb) + d.Set("created_at", i.CreatedAt.Format(time.RFC3339)) + if err := d.Set("tags", tagsToMapLightsail(i.Tags)); err != nil { + return fmt.Errorf("Error setting tags: %s", err) + } + + return nil +} + +func resourceAwsLightsailDiskDelete(d *schema.ResourceData, meta interface{}) error { + + conn := meta.(*AWSClient).lightsailconn + _, err := conn.DeleteDisk(&lightsail.DeleteDiskInput{ + DiskName: aws.String(d.Id()), + }) + + return err +} + +func resourceAwsLightsailDiskUpdate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).lightsailconn + + if d.HasChange("tags") { + if err := setTagsLightsail(conn, d); err != nil { + return err + } + d.SetPartial("tags") + } + + return resourceAwsLightsailDiskRead(d, meta) +} diff --git a/aws/resource_aws_lightsail_disk_test.go b/aws/resource_aws_lightsail_disk_test.go new file mode 100644 index 000000000000..22a7d6e1ceab --- /dev/null +++ b/aws/resource_aws_lightsail_disk_test.go @@ -0,0 +1,241 @@ +package aws + +import ( + "errors" + "fmt" + "testing" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/service/lightsail" + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccAWSLightsailDisk_basic(t *testing.T) { + var conf lightsail.Disk + diskName := fmt.Sprintf("tf-test-lightsail-%d", acctest.RandInt()) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSLightsailDisk(t) }, + IDRefreshName: "aws_lightsail_disk.test", + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSLightsailDiskDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSLightsailDiskConfig_basic(diskName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSLightsailDiskExists("aws_lightsail_disk.test", &conf), + resource.TestCheckResourceAttrSet("aws_lightsail_disk.test", "availability_zone"), + resource.TestCheckResourceAttrSet("aws_lightsail_disk.test", "created_at"), + resource.TestCheckResourceAttrSet("aws_lightsail_disk.test", "name"), + resource.TestCheckResourceAttrSet("aws_lightsail_disk.test", "size"), + resource.TestCheckResourceAttr("aws_lightsail_disk.test", "tags.%", "0"), + ), + }, + }, + }) +} + +func TestAccAWSLightsailDisk_Tags(t *testing.T) { + var conf lightsail.Disk + lightsailName := fmt.Sprintf("tf-test-lightsail-%d", acctest.RandInt()) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSLightsail(t) }, + IDRefreshName: "aws_lightsail_disk.test", + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSLightsailDiskDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSLightsailDiskConfig_tags1(lightsailName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSLightsailDiskExists("aws_lightsail_disk.test", &conf), + resource.TestCheckResourceAttrSet("aws_lightsail_disk.test", "availability_zone"), + resource.TestCheckResourceAttrSet("aws_lightsail_disk.test", "created_at"), + resource.TestCheckResourceAttrSet("aws_lightsail_disk.test", "name"), + resource.TestCheckResourceAttrSet("aws_lightsail_disk.test", "size"), + resource.TestCheckResourceAttr("aws_lightsail_disk.test", "tags.%", "1"), + ), + }, + { + Config: testAccAWSLightsailDiskConfig_tags2(lightsailName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSLightsailDiskExists("aws_lightsail_disk.test", &conf), + resource.TestCheckResourceAttrSet("aws_lightsail_disk.test", "availability_zone"), + resource.TestCheckResourceAttrSet("aws_lightsail_disk.test", "created_at"), + resource.TestCheckResourceAttrSet("aws_lightsail_disk.test", "name"), + resource.TestCheckResourceAttrSet("aws_lightsail_disk.test", "size"), + resource.TestCheckResourceAttr("aws_lightsail_disk.test", "tags.%", "2"), + ), + }, + }, + }) +} + +func TestAccAWSLightsailDisk_disapear(t *testing.T) { + var conf lightsail.Disk + lightsailName := fmt.Sprintf("tf-test-lightsail-%d", acctest.RandInt()) + + testDestroy := func(*terraform.State) error { + // reach out and DELETE the Disk + conn := testAccProvider.Meta().(*AWSClient).lightsailconn + _, err := conn.DeleteDisk(&lightsail.DeleteDiskInput{ + DiskName: aws.String(lightsailName), + }) + + if err != nil { + return fmt.Errorf("error deleting Lightsail Disk in disappear test") + } + + // sleep 7 seconds to give it time, so we don't have to poll + time.Sleep(7 * time.Second) + + return nil + } + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSLightsail(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSLightsailDiskDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSLightsailDiskConfig_basic(lightsailName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSLightsailDiskExists("aws_lightsail_disk.test", &conf), + testDestroy, + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccCheckAWSLightsailDiskExists(n string, res *lightsail.Disk) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return errors.New("No LightsailDisk ID is set") + } + + conn := testAccProvider.Meta().(*AWSClient).lightsailconn + + respDisk, err := conn.GetDisk(&lightsail.GetDiskInput{ + DiskName: aws.String(rs.Primary.Attributes["name"]), + }) + + if err != nil { + return err + } + + if respDisk == nil || respDisk.Disk == nil { + return fmt.Errorf("Disk (%s) not found", rs.Primary.Attributes["name"]) + } + *res = *respDisk.Disk + return nil + } +} + +func testAccCheckAWSLightsailDiskDestroy(s *terraform.State) error { + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_lightsail_disk" { + continue + } + + conn := testAccProvider.Meta().(*AWSClient).lightsailconn + + respDisk, err := conn.GetDisk(&lightsail.GetDiskInput{ + DiskName: aws.String(rs.Primary.Attributes["name"]), + }) + + if err == nil { + if respDisk.Disk != nil { + return fmt.Errorf("LightsailDisk %q still exists", rs.Primary.ID) + } + } + + // Verify the error + if awsErr, ok := err.(awserr.Error); ok { + if awsErr.Code() == "NotFoundException" { + return nil + } + } + return err + } + + return nil +} + +func testAccPreCheckAWSLightsailDisk(t *testing.T) { + conn := testAccProvider.Meta().(*AWSClient).lightsailconn + + input := &lightsail.GetDisksInput{} + + _, err := conn.GetDisks(input) + + if testAccPreCheckSkipError(err) { + t.Skipf("skipping acceptance testing: %s", err) + } + + if err != nil { + t.Fatalf("unexpected PreCheck error: %s", err) + } +} + +func testAccAWSLightsailDiskConfig_basic(diskName string) string { + return fmt.Sprintf(` +data "aws_availability_zones" "available" { + state = "available" +} + +resource "aws_lightsail_disk" "test" { + availability_zone = "${data.aws_availability_zones.available.names[0]}" + name = "%s" + size = 8 +} + +`, diskName) +} + +func testAccAWSLightsailDiskConfig_tags1(diskName string) string { + return fmt.Sprintf(` +data "aws_availability_zones" "available" { + state = "available" +} + +resource "aws_lightsail_disk" "test" { + availability_zone = "${data.aws_availability_zones.available.names[0]}" + name = "%s" + size = 8 + tags = { + Name = "tf-test" + } +} + +`, diskName) +} + +func testAccAWSLightsailDiskConfig_tags2(diskName string) string { + return fmt.Sprintf(` +data "aws_availability_zones" "available" { + state = "available" +} + +resource "aws_lightsail_disk" "test" { + availability_zone = "${data.aws_availability_zones.available.names[0]}" + name = "%s" + size = 8 + tags = { + Name = "tf-test" + ExtraName = "tf-test" + } +} +`, diskName) +} diff --git a/website/aws.erb b/website/aws.erb index 135d1e5cf79c..ecd4e09556b1 100644 --- a/website/aws.erb +++ b/website/aws.erb @@ -2032,6 +2032,9 @@
  • Resources