github.com/simonswine/terraform@v0.9.0-beta2/builtin/providers/aws/resource_aws_ecs_task_definition.go (about)

     1  package aws
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/sha1"
     6  	"encoding/hex"
     7  	"fmt"
     8  	"log"
     9  	"strings"
    10  
    11  	"github.com/aws/aws-sdk-go/aws"
    12  	"github.com/aws/aws-sdk-go/service/ecs"
    13  	"github.com/hashicorp/terraform/helper/hashcode"
    14  	"github.com/hashicorp/terraform/helper/schema"
    15  )
    16  
    17  func resourceAwsEcsTaskDefinition() *schema.Resource {
    18  	return &schema.Resource{
    19  		Create: resourceAwsEcsTaskDefinitionCreate,
    20  		Read:   resourceAwsEcsTaskDefinitionRead,
    21  		Delete: resourceAwsEcsTaskDefinitionDelete,
    22  
    23  		Schema: map[string]*schema.Schema{
    24  			"arn": {
    25  				Type:     schema.TypeString,
    26  				Computed: true,
    27  			},
    28  
    29  			"family": {
    30  				Type:     schema.TypeString,
    31  				Required: true,
    32  				ForceNew: true,
    33  			},
    34  
    35  			"revision": {
    36  				Type:     schema.TypeInt,
    37  				Computed: true,
    38  			},
    39  
    40  			"container_definitions": {
    41  				Type:     schema.TypeString,
    42  				Required: true,
    43  				ForceNew: true,
    44  				StateFunc: func(v interface{}) string {
    45  					hash := sha1.Sum([]byte(v.(string)))
    46  					return hex.EncodeToString(hash[:])
    47  				},
    48  			},
    49  
    50  			"task_role_arn": {
    51  				Type:     schema.TypeString,
    52  				Optional: true,
    53  				ForceNew: true,
    54  			},
    55  
    56  			"network_mode": {
    57  				Type:         schema.TypeString,
    58  				Optional:     true,
    59  				Computed:     true,
    60  				ForceNew:     true,
    61  				ValidateFunc: validateAwsEcsTaskDefinitionNetworkMode,
    62  			},
    63  
    64  			"volume": {
    65  				Type:     schema.TypeSet,
    66  				Optional: true,
    67  				ForceNew: true,
    68  				Elem: &schema.Resource{
    69  					Schema: map[string]*schema.Schema{
    70  						"name": {
    71  							Type:     schema.TypeString,
    72  							Required: true,
    73  						},
    74  
    75  						"host_path": {
    76  							Type:     schema.TypeString,
    77  							Optional: true,
    78  						},
    79  					},
    80  				},
    81  				Set: resourceAwsEcsTaskDefinitionVolumeHash,
    82  			},
    83  
    84  			"placement_constraints": {
    85  				Type:     schema.TypeSet,
    86  				Optional: true,
    87  				ForceNew: true,
    88  				MaxItems: 10,
    89  				Elem: &schema.Resource{
    90  					Schema: map[string]*schema.Schema{
    91  						"type": {
    92  							Type:     schema.TypeString,
    93  							ForceNew: true,
    94  							Required: true,
    95  						},
    96  						"expression": {
    97  							Type:     schema.TypeString,
    98  							ForceNew: true,
    99  							Optional: true,
   100  						},
   101  					},
   102  				},
   103  			},
   104  		},
   105  	}
   106  }
   107  
   108  func validateAwsEcsTaskDefinitionNetworkMode(v interface{}, k string) (ws []string, errors []error) {
   109  	value := strings.ToLower(v.(string))
   110  	validTypes := map[string]struct{}{
   111  		"bridge": {},
   112  		"host":   {},
   113  		"none":   {},
   114  	}
   115  
   116  	if _, ok := validTypes[value]; !ok {
   117  		errors = append(errors, fmt.Errorf("ECS Task Definition network_mode %q is invalid, must be `bridge`, `host` or `none`", value))
   118  	}
   119  	return
   120  }
   121  
   122  func resourceAwsEcsTaskDefinitionCreate(d *schema.ResourceData, meta interface{}) error {
   123  	conn := meta.(*AWSClient).ecsconn
   124  
   125  	rawDefinitions := d.Get("container_definitions").(string)
   126  	definitions, err := expandEcsContainerDefinitions(rawDefinitions)
   127  	if err != nil {
   128  		return err
   129  	}
   130  
   131  	input := ecs.RegisterTaskDefinitionInput{
   132  		ContainerDefinitions: definitions,
   133  		Family:               aws.String(d.Get("family").(string)),
   134  	}
   135  
   136  	if v, ok := d.GetOk("task_role_arn"); ok {
   137  		input.TaskRoleArn = aws.String(v.(string))
   138  	}
   139  
   140  	if v, ok := d.GetOk("network_mode"); ok {
   141  		input.NetworkMode = aws.String(v.(string))
   142  	}
   143  
   144  	if v, ok := d.GetOk("volume"); ok {
   145  		volumes, err := expandEcsVolumes(v.(*schema.Set).List())
   146  		if err != nil {
   147  			return err
   148  		}
   149  		input.Volumes = volumes
   150  	}
   151  
   152  	constraints := d.Get("placement_constraints").(*schema.Set).List()
   153  	if len(constraints) > 0 {
   154  		var pc []*ecs.TaskDefinitionPlacementConstraint
   155  		for _, raw := range constraints {
   156  			p := raw.(map[string]interface{})
   157  			t := p["type"].(string)
   158  			e := p["expression"].(string)
   159  			if err := validateAwsEcsPlacementConstraint(t, e); err != nil {
   160  				return err
   161  			}
   162  			pc = append(pc, &ecs.TaskDefinitionPlacementConstraint{
   163  				Type:       aws.String(t),
   164  				Expression: aws.String(e),
   165  			})
   166  		}
   167  		input.PlacementConstraints = pc
   168  	}
   169  
   170  	log.Printf("[DEBUG] Registering ECS task definition: %s", input)
   171  	out, err := conn.RegisterTaskDefinition(&input)
   172  	if err != nil {
   173  		return err
   174  	}
   175  
   176  	taskDefinition := *out.TaskDefinition
   177  
   178  	log.Printf("[DEBUG] ECS task definition registered: %q (rev. %d)",
   179  		*taskDefinition.TaskDefinitionArn, *taskDefinition.Revision)
   180  
   181  	d.SetId(*taskDefinition.Family)
   182  	d.Set("arn", taskDefinition.TaskDefinitionArn)
   183  
   184  	return resourceAwsEcsTaskDefinitionRead(d, meta)
   185  }
   186  
   187  func resourceAwsEcsTaskDefinitionRead(d *schema.ResourceData, meta interface{}) error {
   188  	conn := meta.(*AWSClient).ecsconn
   189  
   190  	log.Printf("[DEBUG] Reading task definition %s", d.Id())
   191  	out, err := conn.DescribeTaskDefinition(&ecs.DescribeTaskDefinitionInput{
   192  		TaskDefinition: aws.String(d.Get("arn").(string)),
   193  	})
   194  	if err != nil {
   195  		return err
   196  	}
   197  	log.Printf("[DEBUG] Received task definition %s", out)
   198  
   199  	taskDefinition := out.TaskDefinition
   200  
   201  	d.SetId(*taskDefinition.Family)
   202  	d.Set("arn", taskDefinition.TaskDefinitionArn)
   203  	d.Set("family", taskDefinition.Family)
   204  	d.Set("revision", taskDefinition.Revision)
   205  	d.Set("container_definitions", taskDefinition.ContainerDefinitions)
   206  	d.Set("task_role_arn", taskDefinition.TaskRoleArn)
   207  	d.Set("network_mode", taskDefinition.NetworkMode)
   208  	d.Set("volumes", flattenEcsVolumes(taskDefinition.Volumes))
   209  	if err := d.Set("placement_constraints", flattenPlacementConstraints(taskDefinition.PlacementConstraints)); err != nil {
   210  		log.Printf("[ERR] Error setting placement_constraints for (%s): %s", d.Id(), err)
   211  	}
   212  
   213  	return nil
   214  }
   215  
   216  func flattenPlacementConstraints(pcs []*ecs.TaskDefinitionPlacementConstraint) []map[string]interface{} {
   217  	if len(pcs) == 0 {
   218  		return nil
   219  	}
   220  	results := make([]map[string]interface{}, 0)
   221  	for _, pc := range pcs {
   222  		c := make(map[string]interface{})
   223  		c["type"] = *pc.Type
   224  		c["expression"] = *pc.Expression
   225  		results = append(results, c)
   226  	}
   227  	return results
   228  }
   229  
   230  func resourceAwsEcsTaskDefinitionDelete(d *schema.ResourceData, meta interface{}) error {
   231  	conn := meta.(*AWSClient).ecsconn
   232  
   233  	_, err := conn.DeregisterTaskDefinition(&ecs.DeregisterTaskDefinitionInput{
   234  		TaskDefinition: aws.String(d.Get("arn").(string)),
   235  	})
   236  	if err != nil {
   237  		return err
   238  	}
   239  
   240  	log.Printf("[DEBUG] Task definition %q deregistered.", d.Get("arn").(string))
   241  
   242  	return nil
   243  }
   244  
   245  func resourceAwsEcsTaskDefinitionVolumeHash(v interface{}) int {
   246  	var buf bytes.Buffer
   247  	m := v.(map[string]interface{})
   248  	buf.WriteString(fmt.Sprintf("%s-", m["name"].(string)))
   249  	buf.WriteString(fmt.Sprintf("%s-", m["host_path"].(string)))
   250  
   251  	return hashcode.String(buf.String())
   252  }