Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Resource: aws_swf_domain #2803

Merged
merged 1 commit into from
Jul 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions aws/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ import (
"github.com/aws/aws-sdk-go/service/sqs"
"github.com/aws/aws-sdk-go/service/ssm"
"github.com/aws/aws-sdk-go/service/sts"
"github.com/aws/aws-sdk-go/service/swf"
"github.com/aws/aws-sdk-go/service/waf"
"github.com/aws/aws-sdk-go/service/wafregional"
"github.com/davecgh/go-spew/spew"
Expand Down Expand Up @@ -195,6 +196,7 @@ type AWSClient struct {
sdconn *servicediscovery.ServiceDiscovery
sfnconn *sfn.SFN
ssmconn *ssm.SSM
swfconn *swf.SWF
wafconn *waf.WAF
wafregionalconn *wafregional.WAFRegional
iotconn *iot.IoT
Expand Down Expand Up @@ -444,6 +446,7 @@ func (c *Config) Client() (interface{}, error) {
client.snsconn = sns.New(awsSnsSess)
client.sqsconn = sqs.New(awsSqsSess)
client.ssmconn = ssm.New(sess)
client.swfconn = swf.New(sess)
client.wafconn = waf.New(sess)
client.wafregionalconn = wafregional.New(sess)
client.batchconn = batch.New(sess)
Expand Down
1 change: 1 addition & 0 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,7 @@ func Provider() terraform.ResourceProvider {
"aws_sfn_state_machine": resourceAwsSfnStateMachine(),
"aws_default_subnet": resourceAwsDefaultSubnet(),
"aws_subnet": resourceAwsSubnet(),
"aws_swf_domain": resourceAwsSwfDomain(),
"aws_volume_attachment": resourceAwsVolumeAttachment(),
"aws_vpc_dhcp_options_association": resourceAwsVpcDhcpOptionsAssociation(),
"aws_default_vpc_dhcp_options": resourceAwsDefaultVpcDhcpOptions(),
Expand Down
126 changes: 126 additions & 0 deletions aws/resource_aws_swf_domain.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package aws

import (
"fmt"
"strconv"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/swf"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsSwfDomain() *schema.Resource {
return &schema.Resource{
Create: resourceAwsSwfDomainCreate,
Read: resourceAwsSwfDomainRead,
Delete: resourceAwsSwfDomainDelete,
Importer: &schema.ResourceImporter{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The acceptance testing is currently not exercising resource importing. To add it we can add the following TestStep to TestAccAwsSwfDomain_basic:

{
  ResourceName: "aws_swf_domain.test",
  ImportState: true,
  ImportStateVerify: true,
  ImportStateVerifyIgnore: []string{"name_prefix"}, // this line is only necessary if the test configuration is using name_prefix
},

State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
ConflictsWith: []string{"name_prefix"},
},
"name_prefix": &schema.Schema{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor nitpick: the &schema.Schema declaration here is unnecessary since Go 1.7 as its already defined by map[string]*schema.Schema above

The same applies to both description and workflow_execution_retention_period_in_days below.

Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"description": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"workflow_execution_retention_period_in_days": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
value, err := strconv.Atoi(v.(string))
if err != nil || value > 90 || value < 0 {
es = append(es, fmt.Errorf(
"%q must be between 0 and 90 days inclusive", k))
}
return
},
},
},
}
}

func resourceAwsSwfDomainCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).swfconn

var name string

if v, ok := d.GetOk("name"); ok {
name = v.(string)
} else if v, ok := d.GetOk("name_prefix"); ok {
name = resource.PrefixedUniqueId(v.(string))
} else {
name = resource.UniqueId()
}
d.Set("name", name)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The d.Set("name", name) here should be extraneous as its handled (properly) in the read function.


input := &swf.RegisterDomainInput{
Name: aws.String(name),
WorkflowExecutionRetentionPeriodInDays: aws.String(d.Get("workflow_execution_retention_period_in_days").(string)),
}

if v, ok := d.GetOk("description"); ok {
input.Description = aws.String(v.(string))
}

_, err := conn.RegisterDomain(input)
if err != nil {
return err
}

d.SetId(name)

return resourceAwsSwfDomainRead(d, meta)
}

func resourceAwsSwfDomainRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).swfconn

input := &swf.DescribeDomainInput{
Name: aws.String(d.Id()),
}

resp, err := conn.DescribeDomain(input)
if err != nil {
return err
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should perform a check here to allow Terraform to properly suggest recreating the resource if it is deleted outside Terraform as well as return a more helpful message about when the error occurred:

if err != nil {
  if isAWSErr(err, swf.ErrCodeUnknownResourceFault, "") {
    log.Printf("[WARN] SWF Domain %q not found, removing from state", d.Id())
    d.SetId("")
    return nil
  }
  return fmt.Errorf("error reading SWF Domain: %s", err)
}

}

info := resp.DomainInfo
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To prevent potential panics, we should perform nil checks for the nested structures:

if resp.DomainInfo == nil || resp.DomainInfo.Configuration == nil {
  log.Printf("[WARN] SWF Domain %q not found, removing from state", d.Id())
  d.SetId("")
  return nil
}

config := resp.Configuration
d.Set("name", info.Name)
d.Set("description", info.Description)
d.Set("workflow_execution_retention_period_in_days", config.WorkflowExecutionRetentionPeriodInDays)

return nil
}

func resourceAwsSwfDomainDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).swfconn

input := &swf.DeprecateDomainInput{
Name: aws.String(d.Get("name").(string)),
}

_, err := conn.DeprecateDomain(input)
if err != nil {
return err
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should allow the resource to skip returning an error if its already been deprecated/deleted:

if err != nil {
  if isAWSErr(err, swf.ErrCodeDomainDeprecatedFault, "") {
    return nil
  }
  if isAWSErr(err, swf.ErrCodeUnknownResourceFault, "") {
    return nil
  }
  return fmt.Errorf("error deleting SWF Domain: %s", err)
}

}

d.SetId("")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor nitpick: calling d.SetId("") during the delete function is extraneous


return nil
}
90 changes: 90 additions & 0 deletions aws/resource_aws_swf_domain_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package aws

import (
"fmt"
"testing"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/swf"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)

func TestAccAwsSwfDomain_basic(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this resource is accepting three ways to configure the name (via name, via name_prefix, and via generated ID), there should be three separate acceptance tests to cover each scenario separately.

resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testAccCheckAwsSwfDomainDestroy,
Steps: []resource.TestStep{
{
Config: fmt.Sprintf(testAccAwsSwfDomainConfig, "test_swf_domain_"),
Check: testAccCheckAwsSwfDomainExists("aws_swf_domain.test"),
},
},
})
}

func testAccCheckAwsSwfDomainDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).swfconn

for _, rs := range s.RootModule().Resources {
if rs.Type != "aws_swf_domain" {
continue
}

name := rs.Primary.ID
input := &swf.DescribeDomainInput{
Name: aws.String(name),
}

resp, err := conn.DescribeDomain(input)
if err != nil {
return err
}

if *resp.DomainInfo.Status != "DEPRECATED" {
return fmt.Errorf(`SWF Domain %s status is %s instead of "DEPRECATED". Failing!`, name, *resp.DomainInfo.Status)
}
}

return nil
}

func testAccCheckAwsSwfDomainExists(n string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("SWF Domain not found: %s", n)
}

if rs.Primary.ID == "" {
return fmt.Errorf("SWF Domain name not set")
}

name := rs.Primary.ID
conn := testAccProvider.Meta().(*AWSClient).swfconn

input := &swf.DescribeDomainInput{
Name: aws.String(name),
}

resp, err := conn.DescribeDomain(input)
if err != nil {
return fmt.Errorf("SWF Domain %s not found in AWS", name)
}

if *resp.DomainInfo.Status != "REGISTERED" {
return fmt.Errorf(`SWF Domain %s status is %s instead of "REGISTERED". Failing!`, name, *resp.DomainInfo.Status)
}
return nil
}
}

const testAccAwsSwfDomainConfig = `
resource "aws_swf_domain" "test" {
name_prefix = "%s"
workflow_execution_retention_period_in_days = 1
}
`
10 changes: 10 additions & 0 deletions website/aws.erb
Original file line number Diff line number Diff line change
Expand Up @@ -1615,6 +1615,16 @@
</ul>
</li>

<li<%= sidebar_current("docs-aws-resource-swf") %>>
<a href="#">SWF Resources</a>
<ul class="nav nav-visible">

<li<%= sidebar_current("docs-aws-resource-swf-domain") %>>
<a href="/docs/providers/aws/r/swf_domain.html">aws_swf_domain</a>
</li>

</ul>
</li>

<li<%= sidebar_current("docs-aws-resource-(default|customer|egress-only-internet-gateway|flow|internet-gateway|main-route|network|route-|security-group|security-group-attachment|subnet|vpc|vpn)") %>>
<a href="#">VPC Resources</a>
Expand Down
48 changes: 48 additions & 0 deletions website/docs/r/swf_domain.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
layout: "aws"
page_title: "AWS: aws_swf_domain"
sidebar_current: "docs-aws-resource-swf-domain"
description: |-
Provides an SWF Domain resource
---

# aws_swf_domain

Provides an SWF Domain resource.

## Example Usage

To register a basic SWF domain:

```hcl
resource "aws_swf_domain" "foo" {
name = "foo"
description = "Terraform SWF Domain"
workflow_execution_retention_period_in_days = 30
}
```

## Argument Reference

The following arguments are supported:

* `name` - (Optional, Forces new resource) The name of the domain. If omitted, Terraform will assign a random, unique name.
* `name_prefix` - (Optional, Forces new resource) Creates a unique name beginning with the specified prefix. Conflicts with `name`.
* `description` - (Optional, Forces new resource) The domain description.
* `workflow_execution_retention_period_in_days` - (Required, Forces new resource) Length of time that SWF will continue to retain information about the workflow execution after the workflow execution is complete, must be between 0 and 90 days.

## Attributes Reference

The following attributes are exported:

* `name` - The name of the parameter.
* `description` - The domain description.
* `workflow_execution_retention_period_in_days` - Length of time that SWF will continue to retain information about the workflow execution after the workflow execution is complete.

## Import

SWF Domains can be imported using the `name`, e.g.

```
$ terraform import aws_swf_domain.foo test-domain
```