From 900e14e16895eb31e40f9e5c86fe9b7413f2c1d2 Mon Sep 17 00:00:00 2001 From: stack72 Date: Wed, 24 Aug 2016 10:51:57 +0100 Subject: [PATCH] provider/aws: New resource `aws_spot_datafeed_subscription` Fixes: #4922 ``` % make testacc TEST=./builtin/providers/aws TESTARGS='-run=TestAccAWSSpotDatafeedSubscription_' ==> Checking that code complies with gofmt requirements... /Users/stacko/Code/go/bin/stringer go generate $(go list ./... | grep -v /terraform/vendor/) 2016/08/24 10:46:23 Generated command/internal_plugin_list.go TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAccAWSSpotDatafeedSubscription_ -timeout 120m === RUN TestAccAWSSpotDatafeedSubscription_importBasic --- PASS: TestAccAWSSpotDatafeedSubscription_importBasic (56.31s) === RUN TestAccAWSSpotDatafeedSubscription_basic --- PASS: TestAccAWSSpotDatafeedSubscription_basic (56.77s) === RUN TestAccAWSSpotDatafeedSubscription_disappears --- PASS: TestAccAWSSpotDatafeedSubscription_disappears (56.79s) PASS ok github.com/hashicorp/terraform/builtin/providers/aws 169.893s ``` --- ...ort_aws_spot_datafeed_subscription_test.go | 30 ++++ builtin/providers/aws/provider.go | 1 + ...resource_aws_spot_datafeed_subscription.go | 93 ++++++++++++ ...rce_aws_spot_datafeed_subscription_test.go | 139 ++++++++++++++++++ .../iam_account_password_policy.html.markdown | 2 +- .../spot_datafeed_subscription.html.markdown | 39 +++++ website/source/layouts/aws.erb | 4 + 7 files changed, 307 insertions(+), 1 deletion(-) create mode 100644 builtin/providers/aws/import_aws_spot_datafeed_subscription_test.go create mode 100644 builtin/providers/aws/resource_aws_spot_datafeed_subscription.go create mode 100644 builtin/providers/aws/resource_aws_spot_datafeed_subscription_test.go create mode 100644 website/source/docs/providers/aws/r/spot_datafeed_subscription.html.markdown diff --git a/builtin/providers/aws/import_aws_spot_datafeed_subscription_test.go b/builtin/providers/aws/import_aws_spot_datafeed_subscription_test.go new file mode 100644 index 0000000000..8d60f39945 --- /dev/null +++ b/builtin/providers/aws/import_aws_spot_datafeed_subscription_test.go @@ -0,0 +1,30 @@ +package aws + +import ( + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" +) + +func TestAccAWSSpotDatafeedSubscription_importBasic(t *testing.T) { + resourceName := "aws_spot_datafeed_subscription.default" + ri := acctest.RandInt() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSSpotDatafeedSubscriptionDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSSpotDatafeedSubscription(ri), + }, + + resource.TestStep{ + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} diff --git a/builtin/providers/aws/provider.go b/builtin/providers/aws/provider.go index 9d1580d2b6..ac01488dfa 100644 --- a/builtin/providers/aws/provider.go +++ b/builtin/providers/aws/provider.go @@ -316,6 +316,7 @@ func Provider() terraform.ResourceProvider { "aws_simpledb_domain": resourceAwsSimpleDBDomain(), "aws_ssm_association": resourceAwsSsmAssociation(), "aws_ssm_document": resourceAwsSsmDocument(), + "aws_spot_datafeed_subscription": resourceAwsSpotDataFeedSubscription(), "aws_spot_instance_request": resourceAwsSpotInstanceRequest(), "aws_spot_fleet_request": resourceAwsSpotFleetRequest(), "aws_sqs_queue": resourceAwsSqsQueue(), diff --git a/builtin/providers/aws/resource_aws_spot_datafeed_subscription.go b/builtin/providers/aws/resource_aws_spot_datafeed_subscription.go new file mode 100644 index 0000000000..2e3322710c --- /dev/null +++ b/builtin/providers/aws/resource_aws_spot_datafeed_subscription.go @@ -0,0 +1,93 @@ +package aws + +import ( + "log" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/service/ec2" + "github.com/hashicorp/errwrap" + "github.com/hashicorp/terraform/helper/schema" +) + +func resourceAwsSpotDataFeedSubscription() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsSpotDataFeedSubscriptionCreate, + Read: resourceAwsSpotDataFeedSubscriptionRead, + Delete: resourceAwsSpotDataFeedSubscriptionDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "bucket": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "prefix": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + }, + } +} + +func resourceAwsSpotDataFeedSubscriptionCreate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).ec2conn + + params := &ec2.CreateSpotDatafeedSubscriptionInput{ + Bucket: aws.String(d.Get("bucket").(string)), + } + + if v, ok := d.GetOk("prefix"); ok { + params.Prefix = aws.String(v.(string)) + } + + log.Printf("[INFO] Creating Spot Datafeed Subscription") + _, err := conn.CreateSpotDatafeedSubscription(params) + if err != nil { + return errwrap.Wrapf("Error Creating Spot Datafeed Subscription: {{err}}", err) + } + + d.SetId("spot-datafeed-subscription") + + return resourceAwsSpotDataFeedSubscriptionRead(d, meta) +} +func resourceAwsSpotDataFeedSubscriptionRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).ec2conn + + resp, err := conn.DescribeSpotDatafeedSubscription(&ec2.DescribeSpotDatafeedSubscriptionInput{}) + if err != nil { + cgw, ok := err.(awserr.Error) + if ok && cgw.Code() == "InvalidSpotDatafeed.NotFound" { + log.Printf("[WARNING] Spot Datafeed Subscription Not Found so refreshing from state") + d.SetId("") + return nil + } + return errwrap.Wrapf("Error Describing Spot Datafeed Subscription: {{err}}", err) + } + + if resp == nil { + log.Printf("[WARNING] Spot Datafeed Subscription Not Found so refreshing from state") + d.SetId("") + return nil + } + + subscription := *resp.SpotDatafeedSubscription + d.Set("bucket", subscription.Bucket) + d.Set("prefix", subscription.Prefix) + + return nil +} +func resourceAwsSpotDataFeedSubscriptionDelete(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).ec2conn + + log.Printf("[INFO] Deleting Spot Datafeed Subscription") + _, err := conn.DeleteSpotDatafeedSubscription(&ec2.DeleteSpotDatafeedSubscriptionInput{}) + if err != nil { + return errwrap.Wrapf("Error deleting Spot Datafeed Subscription: {{err}}", err) + } + return nil +} diff --git a/builtin/providers/aws/resource_aws_spot_datafeed_subscription_test.go b/builtin/providers/aws/resource_aws_spot_datafeed_subscription_test.go new file mode 100644 index 0000000000..d12e7e7654 --- /dev/null +++ b/builtin/providers/aws/resource_aws_spot_datafeed_subscription_test.go @@ -0,0 +1,139 @@ +package aws + +import ( + "fmt" + "testing" + "time" + + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/service/ec2" + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccAWSSpotDatafeedSubscription_basic(t *testing.T) { + var subscription ec2.SpotDatafeedSubscription + ri := acctest.RandInt() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSSpotDatafeedSubscriptionDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSSpotDatafeedSubscription(ri), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSSpotDatafeedSubscriptionExists("aws_spot_datafeed_subscription.default", &subscription), + ), + }, + }, + }) +} + +func testAccCheckAWSSpotDatafeedSubscriptionDisappears(subscription *ec2.SpotDatafeedSubscription) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).ec2conn + + _, err := conn.DeleteSpotDatafeedSubscription(&ec2.DeleteSpotDatafeedSubscriptionInput{}) + if err != nil { + return err + } + + return resource.Retry(40*time.Minute, func() *resource.RetryError { + _, err := conn.DescribeSpotDatafeedSubscription(&ec2.DescribeSpotDatafeedSubscriptionInput{}) + if err != nil { + cgw, ok := err.(awserr.Error) + if ok && cgw.Code() == "InvalidSpotDatafeed.NotFound" { + return nil + } + return resource.NonRetryableError( + fmt.Errorf("Error retrieving Spot Datafeed Subscription: %s", err)) + } + return resource.RetryableError(fmt.Errorf("Waiting for Spot Datafeed Subscription")) + }) + } +} + +func TestAccAWSSpotDatafeedSubscription_disappears(t *testing.T) { + var subscription ec2.SpotDatafeedSubscription + ri := acctest.RandInt() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSSpotDatafeedSubscriptionDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSSpotDatafeedSubscription(ri), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSSpotDatafeedSubscriptionExists("aws_spot_datafeed_subscription.default", &subscription), + testAccCheckAWSSpotDatafeedSubscriptionDisappears(&subscription), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccCheckAWSSpotDatafeedSubscriptionExists(n string, subscription *ec2.SpotDatafeedSubscription) 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 fmt.Errorf("No policy ID is set") + } + + conn := testAccProvider.Meta().(*AWSClient).ec2conn + + resp, err := conn.DescribeSpotDatafeedSubscription(&ec2.DescribeSpotDatafeedSubscriptionInput{}) + if err != nil { + return err + } + + *subscription = *resp.SpotDatafeedSubscription + + return nil + } +} + +func testAccCheckAWSSpotDatafeedSubscriptionDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).ec2conn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_spot_datafeed_subscription" { + continue + } + + // Try to get subscription + _, err := conn.DescribeSpotDatafeedSubscription(&ec2.DescribeSpotDatafeedSubscriptionInput{}) + if err == nil { + return fmt.Errorf("still exist.") + } + + awsErr, ok := err.(awserr.Error) + if !ok { + return err + } + if awsErr.Code() != "InvalidSpotDatafeed.NotFound" { + return err + } + } + + return nil +} + +func testAccAWSSpotDatafeedSubscription(randInt int) string { + return fmt.Sprintf(` +resource "aws_s3_bucket" "default" { + bucket = "tf-spot-datafeed-%d" +} + +resource "aws_spot_datafeed_subscription" "default" { + bucket = "${aws_s3_bucket.default.bucket}" +} +`, randInt) +} diff --git a/website/source/docs/providers/aws/r/iam_account_password_policy.html.markdown b/website/source/docs/providers/aws/r/iam_account_password_policy.html.markdown index 208e1e4507..ce51ee2b47 100644 --- a/website/source/docs/providers/aws/r/iam_account_password_policy.html.markdown +++ b/website/source/docs/providers/aws/r/iam_account_password_policy.html.markdown @@ -53,7 +53,7 @@ The following attributes are exported: ## Import -IAM Account Password Policy can be imported using the work `iam-account-password-policy`, e.g. +IAM Account Password Policy can be imported using the word `iam-account-password-policy`, e.g. ``` $ terraform import aws_iam_account_password_policy.strict iam-account-password-policy diff --git a/website/source/docs/providers/aws/r/spot_datafeed_subscription.html.markdown b/website/source/docs/providers/aws/r/spot_datafeed_subscription.html.markdown new file mode 100644 index 0000000000..25ad0b2564 --- /dev/null +++ b/website/source/docs/providers/aws/r/spot_datafeed_subscription.html.markdown @@ -0,0 +1,39 @@ +--- +layout: "aws" +page_title: "AWS: aws_spot_datafeed_subscription" +sidebar_current: "docs-aws-resource-spot-datafleet-subscription" +description: |- + Provides a Spot Datafeed Subscription resource. +--- + +# aws\_spot\_datafeed\_subscription + +-> **Note:** There is only a single subscription allowed per account. + +To help you understand the charges for your Spot instances, Amazon EC2 provides a data feed that describes your Spot instance usage and pricing. +This data feed is sent to an Amazon S3 bucket that you specify when you subscribe to the data feed. + +## Example Usage + +``` +resource "aws_s3_bucket" "default" { + bucket = "tf-spot-datafeed" +} + +resource "aws_spot_datafeed_subscription" "default" { + bucket = "${aws_s3_bucket.default.bucket}" +} +``` + +## Argument Reference +* `bucket` - (Required) The Amazon S3 bucket in which to store the Spot instance data feed. +* `prefix` - (Optional) A prefix for the data feed file names. + + +## Import + +A Spot Datafeed Subscription can be imported using the word `spot-datafeed-subscription`, e.g. + +``` +$ terraform import aws_spot_datafeed_subscription.mysubscription spot-datafeed-subscription +``` \ No newline at end of file diff --git a/website/source/layouts/aws.erb b/website/source/layouts/aws.erb index 6a2ae1614b..867003bc18 100644 --- a/website/source/layouts/aws.erb +++ b/website/source/layouts/aws.erb @@ -335,6 +335,10 @@ aws_proxy_protocol_policy + > + aws_spot_datafeed_subscription + + > aws_spot_fleet_request