Skip to content

Commit

Permalink
Added Step Function Activity & Step Function State Machine
Browse files Browse the repository at this point in the history
  • Loading branch information
Ninir committed Jan 25, 2017
1 parent 6d026b1 commit 0d24ef5
Show file tree
Hide file tree
Showing 5 changed files with 403 additions and 0 deletions.
1 change: 1 addition & 0 deletions builtin/providers/aws/provider.go
Expand Up @@ -380,6 +380,7 @@ func Provider() terraform.ResourceProvider {
"aws_sns_topic": resourceAwsSnsTopic(),
"aws_sns_topic_policy": resourceAwsSnsTopicPolicy(),
"aws_sns_topic_subscription": resourceAwsSnsTopicSubscription(),
"aws_sfn_state_machine": resourceAwsSfnStateMachine(),
"aws_subnet": resourceAwsSubnet(),
"aws_volume_attachment": resourceAwsVolumeAttachment(),
"aws_vpc_dhcp_options_association": resourceAwsVpcDhcpOptionsAssociation(),
Expand Down
115 changes: 115 additions & 0 deletions builtin/providers/aws/resource_aws_sfn_state_machine.go
@@ -0,0 +1,115 @@
package aws

import (
"fmt"
"log"
"time"

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

func resourceAwsSfnStateMachine() *schema.Resource {
return &schema.Resource{
Create: resourceAwsSfnStateMachineCreate,
Read: resourceAwsSfnStateMachineRead,
Delete: resourceAwsSfnStateMachineDelete,

Schema: map[string]*schema.Schema{
"definition": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validateSfnStateMachineDefinition,
},

"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validateSfnStateMachineName,
},

"role_arn": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validateArn,
},

"creation_date": {
Type: schema.TypeString,
Computed: true,
},

"status": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

func resourceAwsSfnStateMachineCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).sfnconn
log.Printf("[DEBUG] Creating Step Function State Machine")

params := &sfn.CreateStateMachineInput{
Definition: aws.String(d.Get("definition").(string)),
Name: aws.String(d.Get("name").(string)),
RoleArn: aws.String(d.Get("role_arn").(string)),
}

activity, err := conn.CreateStateMachine(params)
if err != nil {
return fmt.Errorf("Error creating Step Function State Machine: %s", err)
}

d.SetId(*activity.StateMachineArn)

return resourceAwsSfnStateMachineRead(d, meta)
}

func resourceAwsSfnStateMachineRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).sfnconn
log.Printf("[DEBUG] Reading Step Function State Machine: %s", d.Id())

sm, err := conn.DescribeStateMachine(&sfn.DescribeStateMachineInput{
StateMachineArn: aws.String(d.Id()),
})
if err != nil {
if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "NotFoundException" {
d.SetId("")
return nil
}
return err
}

d.Set("status", sm.Status)

if err := d.Set("creation_date", sm.CreationDate.Format(time.RFC3339)); err != nil {
log.Printf("[DEBUG] Error setting creation_date: %s", err)
}

return nil
}

func resourceAwsSfnStateMachineDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).sfnconn
log.Printf("[DEBUG] Deleting Step Functions State Machine: %s", d.Id())

return resource.Retry(5*time.Minute, func() *resource.RetryError {
_, err := conn.DeleteStateMachine(&sfn.DeleteStateMachineInput{
StateMachineArn: aws.String(d.Id()),
})

if err == nil {
return nil
}

return resource.NonRetryableError(err)
})
}
196 changes: 196 additions & 0 deletions builtin/providers/aws/resource_aws_sfn_state_machine_test.go
@@ -0,0 +1,196 @@
package aws

import (
"fmt"
"testing"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/sfn"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)

func TestAccAWSSfn_basic(t *testing.T) {
name := acctest.RandString(10)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSSfnDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSSfnBasicConfig(name),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSSfnExists("aws_sfn_state_machine.foo"),
),
},
},
})
}

func testAccCheckAWSSfnExists(n string) 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 Step Function ID set")
}

conn := testAccProvider.Meta().(*AWSClient).sfnconn

_, err := conn.DescribeStateMachine(&sfn.DescribeStateMachineInput{
StateMachineArn: aws.String(rs.Primary.ID),
})

if err != nil {
return err
}

return nil
}
}

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

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

out, err := conn.DescribeStateMachine(&sfn.DescribeStateMachineInput{
StateMachineArn: aws.String(rs.Primary.ID),
})

if err != nil {
if wserr, ok := err.(awserr.Error); ok && wserr.Code() == "StateMachineDoesNotExist" {
return nil
}
return err
}

if out != nil && *out.Status != sfn.StateMachineStatusDeleting {
return fmt.Errorf("Expected AWS Step Function to be destroyed, but was still found")
}

return nil
}

return fmt.Errorf("Default error in Step Function Test")
}

func testAccAWSSfnBasicConfig(rName string) string {
return fmt.Sprintf(`
data "aws_region" "current" {
current = true
}
resource "aws_iam_role_policy" "iam_policy_for_lambda" {
name = "iam_policy_for_lambda_%s"
role = "${aws_iam_role.iam_for_lambda.id}"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*"
}]
}
EOF
}
resource "aws_iam_role" "iam_for_lambda" {
name = "iam_for_lambda_%s"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_iam_role_policy" "iam_policy_for_sfn" {
name = "iam_policy_for_sfn_%s"
role = "${aws_iam_role.iam_for_sfn.id}"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"lambda:InvokeFunction"
],
"Resource": "*"
}
]
}
EOF
}
resource "aws_iam_role" "iam_for_sfn" {
name = "iam_for_sfn_%s"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "states.${data.aws_region.current.name}.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
}
resource "aws_lambda_function" "lambda_function_test" {
filename = "test-fixtures/lambdatest.zip"
function_name = "sfn-%s"
role = "${aws_iam_role.iam_for_lambda.arn}"
handler = "exports.example"
runtime = "nodejs4.3"
}
resource "aws_sfn_state_machine" "foo" {
name = "test_sfn_%s"
role_arn = "${aws_iam_role.iam_for_sfn.arn}"
definition = <<EOF
{
"Comment": "A Hello World example of the Amazon States Language using an AWS Lambda Function",
"StartAt": "HelloWorld",
"States": {
"HelloWorld": {
"Type": "Task",
"Resource": "${aws_lambda_function.lambda_function_test.arn}",
"End": true
}
}
}
EOF
}
`, rName, rName, rName, rName, rName, rName)
}
22 changes: 22 additions & 0 deletions builtin/providers/aws/validators.go
Expand Up @@ -727,3 +727,25 @@ func validateAwsEcsPlacementStrategy(stratType, stratField string) error {
}
return nil
}

func validateSfnStateMachineDefinition(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)
if len(value) > 1048576 {
errors = append(errors, fmt.Errorf("%q cannot be longer than 1048576 characters", k))
}
return
}

func validateSfnStateMachineName(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)
if len(value) > 80 {
errors = append(errors, fmt.Errorf("%q cannot be longer than 80 characters", k))
}

if !regexp.MustCompile(`^[a-zA-Z0-9-_]+$`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"%q must be composed with only these characters [a-zA-Z0-9-_]: %v", k, value))
}

return
}

0 comments on commit 0d24ef5

Please sign in to comment.