From 90889632e0f57c4e2d6daeb08f5c32e115c6fc48 Mon Sep 17 00:00:00 2001 From: Raphael Randschau Date: Wed, 15 Jun 2016 19:55:45 +0200 Subject: [PATCH] Add aws_ecs_container_definition data source this datasource allows terraform to work with externally modified state, e.g. when you're using an ECS service which is continously updated by your CI via the AWS CLI. right now you'd have to wrap terraform into a shell script which looks up the current image digest, so running terraform won't change the updated service. using the aws_ecs_container_definition data source you can now leverage terraform, removing the wrapper entirely. --- ...ata_source_aws_ecs_container_definition.go | 98 +++++++++++++++++++ ...ource_aws_ecs_container_definition_test.go | 62 ++++++++++++ builtin/providers/aws/provider.go | 9 +- .../d/ecs_container_definition.html.markdown | 41 ++++++++ website/source/layouts/aws.erb | 3 + 5 files changed, 209 insertions(+), 4 deletions(-) create mode 100644 builtin/providers/aws/data_source_aws_ecs_container_definition.go create mode 100644 builtin/providers/aws/data_source_aws_ecs_container_definition_test.go create mode 100644 website/source/docs/providers/aws/d/ecs_container_definition.html.markdown diff --git a/builtin/providers/aws/data_source_aws_ecs_container_definition.go b/builtin/providers/aws/data_source_aws_ecs_container_definition.go new file mode 100644 index 0000000000..ecc1b20b7c --- /dev/null +++ b/builtin/providers/aws/data_source_aws_ecs_container_definition.go @@ -0,0 +1,98 @@ +package aws + +import ( + "fmt" + "strings" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/ecs" + "github.com/hashicorp/terraform/helper/schema" +) + +func dataSourceAwsEcsContainerDefinition() *schema.Resource { + return &schema.Resource{ + Read: dataSourceAwsEcsContainerDefinitionRead, + + Schema: map[string]*schema.Schema{ + "task_definition": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "container_name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + // Computed values. + "image": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + "image_digest": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + "cpu": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + }, + "memory": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + }, + "disable_networking": &schema.Schema{ + Type: schema.TypeBool, + Computed: true, + }, + "docker_labels": &schema.Schema{ + Type: schema.TypeMap, + Computed: true, + Elem: schema.TypeString, + }, + "environment": &schema.Schema{ + Type: schema.TypeMap, + Computed: true, + Elem: schema.TypeString, + }, + }, + } +} + +func dataSourceAwsEcsContainerDefinitionRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).ecsconn + + desc, err := conn.DescribeTaskDefinition(&ecs.DescribeTaskDefinitionInput{ + TaskDefinition: aws.String(d.Get("task_definition").(string)), + }) + if err != nil { + return err + } + + taskDefinition := *desc.TaskDefinition + for _, def := range taskDefinition.ContainerDefinitions { + if aws.StringValue(def.Name) != d.Get("container_name").(string) { + continue + } + + d.SetId(fmt.Sprintf("%s/%s", aws.StringValue(taskDefinition.TaskDefinitionArn), d.Get("container_name").(string))) + d.Set("image", aws.StringValue(def.Image)) + d.Set("image_digest", strings.Split(aws.StringValue(def.Image), ":")[1]) + d.Set("cpu", aws.Int64Value(def.Cpu)) + d.Set("memory", aws.Int64Value(def.Memory)) + d.Set("disable_networking", aws.BoolValue(def.DisableNetworking)) + d.Set("docker_labels", aws.StringValueMap(def.DockerLabels)) + + var environment = map[string]string{} + for _, keyValuePair := range def.Environment { + environment[aws.StringValue(keyValuePair.Name)] = aws.StringValue(keyValuePair.Value) + } + d.Set("environment", environment) + } + + if d.Id() == "" { + return fmt.Errorf("container with name %q not found in task definition %q", d.Get("container_name").(string), d.Get("task_definition").(string)) + } + + return nil +} diff --git a/builtin/providers/aws/data_source_aws_ecs_container_definition_test.go b/builtin/providers/aws/data_source_aws_ecs_container_definition_test.go new file mode 100644 index 0000000000..c0037e6825 --- /dev/null +++ b/builtin/providers/aws/data_source_aws_ecs_container_definition_test.go @@ -0,0 +1,62 @@ +package aws + +import ( + "testing" + + "github.com/hashicorp/terraform/helper/resource" +) + +func TestAccAWSAmiDataSource_ecsContainerDefinition(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckAwsEcsContainerDefinitionDataSourceConfig, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("data.aws_ecs_container_definition.mongo", "image", "mongo:latest"), + resource.TestCheckResourceAttr("data.aws_ecs_container_definition.mongo", "memory", "128"), + resource.TestCheckResourceAttr("data.aws_ecs_container_definition.mongo", "cpu", "128"), + resource.TestCheckResourceAttr("data.aws_ecs_container_definition.mongo", "environment.SECRET", "KEY"), + ), + }, + }, + }) +} + +const testAccCheckAwsEcsContainerDefinitionDataSourceConfig = ` +resource "aws_ecs_cluster" "default" { + name = "terraformecstest1" +} + +resource "aws_ecs_task_definition" "mongo" { + family = "mongodb" + container_definitions = <> aws_ami + > + aws_ecs_container_definition + > aws_availability_zones