github.com/recobe182/terraform@v0.8.5-0.20170117231232-49ab22a935b7/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  							Required: 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  			pc = append(pc, &ecs.TaskDefinitionPlacementConstraint{
   158  				Type:       aws.String(p["type"].(string)),
   159  				Expression: aws.String(p["expression"].(string)),
   160  			})
   161  		}
   162  		input.PlacementConstraints = pc
   163  	}
   164  
   165  	log.Printf("[DEBUG] Registering ECS task definition: %s", input)
   166  	out, err := conn.RegisterTaskDefinition(&input)
   167  	if err != nil {
   168  		return err
   169  	}
   170  
   171  	taskDefinition := *out.TaskDefinition
   172  
   173  	log.Printf("[DEBUG] ECS task definition registered: %q (rev. %d)",
   174  		*taskDefinition.TaskDefinitionArn, *taskDefinition.Revision)
   175  
   176  	d.SetId(*taskDefinition.Family)
   177  	d.Set("arn", taskDefinition.TaskDefinitionArn)
   178  
   179  	return resourceAwsEcsTaskDefinitionRead(d, meta)
   180  }
   181  
   182  func resourceAwsEcsTaskDefinitionRead(d *schema.ResourceData, meta interface{}) error {
   183  	conn := meta.(*AWSClient).ecsconn
   184  
   185  	log.Printf("[DEBUG] Reading task definition %s", d.Id())
   186  	out, err := conn.DescribeTaskDefinition(&ecs.DescribeTaskDefinitionInput{
   187  		TaskDefinition: aws.String(d.Get("arn").(string)),
   188  	})
   189  	if err != nil {
   190  		return err
   191  	}
   192  	log.Printf("[DEBUG] Received task definition %s", out)
   193  
   194  	taskDefinition := out.TaskDefinition
   195  
   196  	d.SetId(*taskDefinition.Family)
   197  	d.Set("arn", taskDefinition.TaskDefinitionArn)
   198  	d.Set("family", taskDefinition.Family)
   199  	d.Set("revision", taskDefinition.Revision)
   200  	d.Set("container_definitions", taskDefinition.ContainerDefinitions)
   201  	d.Set("task_role_arn", taskDefinition.TaskRoleArn)
   202  	d.Set("network_mode", taskDefinition.NetworkMode)
   203  	d.Set("volumes", flattenEcsVolumes(taskDefinition.Volumes))
   204  	if err := d.Set("placement_constraints", flattenPlacementConstraints(taskDefinition.PlacementConstraints)); err != nil {
   205  		log.Printf("[ERR] Error setting placement_constraints for (%s): %s", d.Id(), err)
   206  	}
   207  
   208  	return nil
   209  }
   210  
   211  func flattenPlacementConstraints(pcs []*ecs.TaskDefinitionPlacementConstraint) []map[string]interface{} {
   212  	if len(pcs) == 0 {
   213  		return nil
   214  	}
   215  	results := make([]map[string]interface{}, 0)
   216  	for _, pc := range pcs {
   217  		c := make(map[string]interface{})
   218  		c["type"] = *pc.Type
   219  		c["expression"] = *pc.Expression
   220  		results = append(results, c)
   221  	}
   222  	return results
   223  }
   224  
   225  func resourceAwsEcsTaskDefinitionDelete(d *schema.ResourceData, meta interface{}) error {
   226  	conn := meta.(*AWSClient).ecsconn
   227  
   228  	_, err := conn.DeregisterTaskDefinition(&ecs.DeregisterTaskDefinitionInput{
   229  		TaskDefinition: aws.String(d.Get("arn").(string)),
   230  	})
   231  	if err != nil {
   232  		return err
   233  	}
   234  
   235  	log.Printf("[DEBUG] Task definition %q deregistered.", d.Get("arn").(string))
   236  
   237  	return nil
   238  }
   239  
   240  func resourceAwsEcsTaskDefinitionVolumeHash(v interface{}) int {
   241  	var buf bytes.Buffer
   242  	m := v.(map[string]interface{})
   243  	buf.WriteString(fmt.Sprintf("%s-", m["name"].(string)))
   244  	buf.WriteString(fmt.Sprintf("%s-", m["host_path"].(string)))
   245  
   246  	return hashcode.String(buf.String())
   247  }