From 87faf855aa6d09343239df27d955e0b992753e5a Mon Sep 17 00:00:00 2001 From: Radek Simko Date: Sun, 3 May 2015 23:12:50 +0100 Subject: [PATCH] provider/aws: Add new resource - aws_ecs_task_definition --- builtin/providers/aws/provider.go | 1 + .../aws/resource_aws_ecs_task_definition.go | 158 ++++++++++++++++++ .../resource_aws_ecs_task_definition_test.go | 111 ++++++++++++ builtin/providers/aws/structure.go | 77 +++++++++ 4 files changed, 347 insertions(+) create mode 100644 builtin/providers/aws/resource_aws_ecs_task_definition.go create mode 100644 builtin/providers/aws/resource_aws_ecs_task_definition_test.go diff --git a/builtin/providers/aws/provider.go b/builtin/providers/aws/provider.go index 2aa094d6d..90b8d0cb6 100644 --- a/builtin/providers/aws/provider.go +++ b/builtin/providers/aws/provider.go @@ -92,6 +92,7 @@ func Provider() terraform.ResourceProvider { "aws_db_subnet_group": resourceAwsDbSubnetGroup(), "aws_ebs_volume": resourceAwsEbsVolume(), "aws_ecs_cluster": resourceAwsEcsCluster(), + "aws_ecs_task_definition": resourceAwsEcsTaskDefinition(), "aws_eip": resourceAwsEip(), "aws_elasticache_cluster": resourceAwsElasticacheCluster(), "aws_elasticache_security_group": resourceAwsElasticacheSecurityGroup(), diff --git a/builtin/providers/aws/resource_aws_ecs_task_definition.go b/builtin/providers/aws/resource_aws_ecs_task_definition.go new file mode 100644 index 000000000..bdc260a41 --- /dev/null +++ b/builtin/providers/aws/resource_aws_ecs_task_definition.go @@ -0,0 +1,158 @@ +package aws + +import ( + "bytes" + "crypto/sha1" + "encoding/hex" + "fmt" + "log" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/ecs" + "github.com/hashicorp/terraform/helper/hashcode" + "github.com/hashicorp/terraform/helper/schema" +) + +func resourceAwsEcsTaskDefinition() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsEcsTaskDefinitionCreate, + Read: resourceAwsEcsTaskDefinitionRead, + Update: resourceAwsEcsTaskDefinitionUpdate, + Delete: resourceAwsEcsTaskDefinitionDelete, + + Schema: map[string]*schema.Schema{ + "arn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + + "family": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "revision": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + }, + + "container_definitions": &schema.Schema{ + Type: schema.TypeString, + Required: true, + StateFunc: func(v interface{}) string { + hash := sha1.Sum([]byte(v.(string))) + return hex.EncodeToString(hash[:]) + }, + }, + + "volume": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "host_path": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + }, + }, + Set: resourceAwsEcsTaskDefinitionVolumeHash, + }, + }, + } +} + +func resourceAwsEcsTaskDefinitionCreate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).ecsconn + + rawDefinitions := d.Get("container_definitions").(string) + definitions, err := expandEcsContainerDefinitions(rawDefinitions) + if err != nil { + return err + } + + input := ecs.RegisterTaskDefinitionInput{ + ContainerDefinitions: definitions, + Family: aws.String(d.Get("family").(string)), + } + + if v, ok := d.GetOk("volume"); ok { + volumes, err := expandEcsVolumes(v.(*schema.Set).List()) + if err != nil { + return err + } + input.Volumes = volumes + } + + log.Printf("[DEBUG] Registering ECS task definition: %#v", input) + out, err := conn.RegisterTaskDefinition(&input) + if err != nil { + return err + } + + taskDefinition := *out.TaskDefinition + + log.Printf("[DEBUG] ECS task definition registered: %#v (rev. %d)", + *taskDefinition.TaskDefinitionARN, *taskDefinition.Revision) + + d.SetId(*taskDefinition.Family) + d.Set("arn", *taskDefinition.TaskDefinitionARN) + + return resourceAwsEcsTaskDefinitionRead(d, meta) +} + +func resourceAwsEcsTaskDefinitionRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).ecsconn + + log.Printf("[DEBUG] Reading task definition %s", d.Id()) + out, err := conn.DescribeTaskDefinition(&ecs.DescribeTaskDefinitionInput{ + TaskDefinition: aws.String(d.Get("arn").(string)), + }) + if err != nil { + return err + } + log.Printf("[DEBUG] Received task definition %#v", out) + + taskDefinition := out.TaskDefinition + + d.SetId(*taskDefinition.Family) + d.Set("arn", *taskDefinition.TaskDefinitionARN) + d.Set("family", *taskDefinition.Family) + d.Set("revision", *taskDefinition.Revision) + d.Set("container_definitions", taskDefinition.ContainerDefinitions) + d.Set("volumes", flattenEcsVolumes(taskDefinition.Volumes)) + + return nil +} + +func resourceAwsEcsTaskDefinitionUpdate(d *schema.ResourceData, meta interface{}) error { + return resourceAwsEcsTaskDefinitionCreate(d, meta) +} + +func resourceAwsEcsTaskDefinitionDelete(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).ecsconn + + // NOT YET IMPLEMENTED o_O + _, err := conn.DeregisterTaskDefinition(&ecs.DeregisterTaskDefinitionInput{ + TaskDefinition: aws.String(d.Id()), + }) + + log.Printf("[DEBUG] Deregistering task definition %s returned %#v", d.Id(), err) + + return nil +} + +func resourceAwsEcsTaskDefinitionVolumeHash(v interface{}) int { + var buf bytes.Buffer + m := v.(map[string]interface{}) + buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) + buf.WriteString(fmt.Sprintf("%s-", m["host_path"].(string))) + + return hashcode.String(buf.String()) +} diff --git a/builtin/providers/aws/resource_aws_ecs_task_definition_test.go b/builtin/providers/aws/resource_aws_ecs_task_definition_test.go new file mode 100644 index 000000000..f866f1fa3 --- /dev/null +++ b/builtin/providers/aws/resource_aws_ecs_task_definition_test.go @@ -0,0 +1,111 @@ +package aws + +import ( + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/ecs" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccAWSEcsTaskDefinition(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSEcsTaskDefinitionDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSEcsTaskDefinition, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSEcsTaskDefinitionExists("aws_ecs_task_definition.jenkins"), + ), + }, + }, + }) +} + +func testAccCheckAWSEcsTaskDefinitionDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).ecsconn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_ecs_task_definition" { + continue + } + + out, err := conn.DescribeTaskDefinition(&ecs.DescribeTaskDefinitionInput{ + TaskDefinition: aws.String(rs.Primary.ID), + }) + + if err == nil { + if out.TaskDefinition != nil { + return fmt.Errorf("ECS task definition still exists:\n%#v", *out.TaskDefinition) + } + } + + return err + } + + return nil +} + +func testAccCheckAWSEcsTaskDefinitionExists(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + _, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("Not found: %s", name) + } + + return nil + } +} + +var testAccAWSEcsTaskDefinition = ` +resource "aws_ecs_task_definition" "jenkins" { + family = "jenkins" + container_definitions = <