github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/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  							ForceNew: true,
    74  						},
    75  
    76  						"host_path": {
    77  							Type:     schema.TypeString,
    78  							Optional: true,
    79  							ForceNew: true,
    80  						},
    81  					},
    82  				},
    83  				Set: resourceAwsEcsTaskDefinitionVolumeHash,
    84  			},
    85  
    86  			"placement_constraints": {
    87  				Type:     schema.TypeSet,
    88  				Optional: true,
    89  				ForceNew: true,
    90  				MaxItems: 10,
    91  				Elem: &schema.Resource{
    92  					Schema: map[string]*schema.Schema{
    93  						"type": {
    94  							Type:     schema.TypeString,
    95  							ForceNew: true,
    96  							Required: true,
    97  						},
    98  						"expression": {
    99  							Type:     schema.TypeString,
   100  							ForceNew: true,
   101  							Optional: true,
   102  						},
   103  					},
   104  				},
   105  			},
   106  		},
   107  	}
   108  }
   109  
   110  func validateAwsEcsTaskDefinitionNetworkMode(v interface{}, k string) (ws []string, errors []error) {
   111  	value := strings.ToLower(v.(string))
   112  	validTypes := map[string]struct{}{
   113  		"bridge": {},
   114  		"host":   {},
   115  		"none":   {},
   116  	}
   117  
   118  	if _, ok := validTypes[value]; !ok {
   119  		errors = append(errors, fmt.Errorf("ECS Task Definition network_mode %q is invalid, must be `bridge`, `host` or `none`", value))
   120  	}
   121  	return
   122  }
   123  
   124  func resourceAwsEcsTaskDefinitionCreate(d *schema.ResourceData, meta interface{}) error {
   125  	conn := meta.(*AWSClient).ecsconn
   126  
   127  	rawDefinitions := d.Get("container_definitions").(string)
   128  	definitions, err := expandEcsContainerDefinitions(rawDefinitions)
   129  	if err != nil {
   130  		return err
   131  	}
   132  
   133  	input := ecs.RegisterTaskDefinitionInput{
   134  		ContainerDefinitions: definitions,
   135  		Family:               aws.String(d.Get("family").(string)),
   136  	}
   137  
   138  	if v, ok := d.GetOk("task_role_arn"); ok {
   139  		input.TaskRoleArn = aws.String(v.(string))
   140  	}
   141  
   142  	if v, ok := d.GetOk("network_mode"); ok {
   143  		input.NetworkMode = aws.String(v.(string))
   144  	}
   145  
   146  	if v, ok := d.GetOk("volume"); ok {
   147  		volumes, err := expandEcsVolumes(v.(*schema.Set).List())
   148  		if err != nil {
   149  			return err
   150  		}
   151  		input.Volumes = volumes
   152  	}
   153  
   154  	constraints := d.Get("placement_constraints").(*schema.Set).List()
   155  	if len(constraints) > 0 {
   156  		var pc []*ecs.TaskDefinitionPlacementConstraint
   157  		for _, raw := range constraints {
   158  			p := raw.(map[string]interface{})
   159  			t := p["type"].(string)
   160  			e := p["expression"].(string)
   161  			if err := validateAwsEcsPlacementConstraint(t, e); err != nil {
   162  				return err
   163  			}
   164  			pc = append(pc, &ecs.TaskDefinitionPlacementConstraint{
   165  				Type:       aws.String(t),
   166  				Expression: aws.String(e),
   167  			})
   168  		}
   169  		input.PlacementConstraints = pc
   170  	}
   171  
   172  	log.Printf("[DEBUG] Registering ECS task definition: %s", input)
   173  	out, err := conn.RegisterTaskDefinition(&input)
   174  	if err != nil {
   175  		return err
   176  	}
   177  
   178  	taskDefinition := *out.TaskDefinition
   179  
   180  	log.Printf("[DEBUG] ECS task definition registered: %q (rev. %d)",
   181  		*taskDefinition.TaskDefinitionArn, *taskDefinition.Revision)
   182  
   183  	d.SetId(*taskDefinition.Family)
   184  	d.Set("arn", taskDefinition.TaskDefinitionArn)
   185  
   186  	return resourceAwsEcsTaskDefinitionRead(d, meta)
   187  }
   188  
   189  func resourceAwsEcsTaskDefinitionRead(d *schema.ResourceData, meta interface{}) error {
   190  	conn := meta.(*AWSClient).ecsconn
   191  
   192  	log.Printf("[DEBUG] Reading task definition %s", d.Id())
   193  	out, err := conn.DescribeTaskDefinition(&ecs.DescribeTaskDefinitionInput{
   194  		TaskDefinition: aws.String(d.Get("arn").(string)),
   195  	})
   196  	if err != nil {
   197  		return err
   198  	}
   199  	log.Printf("[DEBUG] Received task definition %s", out)
   200  
   201  	taskDefinition := out.TaskDefinition
   202  
   203  	d.SetId(*taskDefinition.Family)
   204  	d.Set("arn", taskDefinition.TaskDefinitionArn)
   205  	d.Set("family", taskDefinition.Family)
   206  	d.Set("revision", taskDefinition.Revision)
   207  	d.Set("container_definitions", taskDefinition.ContainerDefinitions)
   208  	d.Set("task_role_arn", taskDefinition.TaskRoleArn)
   209  	d.Set("network_mode", taskDefinition.NetworkMode)
   210  	d.Set("volumes", flattenEcsVolumes(taskDefinition.Volumes))
   211  	if err := d.Set("placement_constraints", flattenPlacementConstraints(taskDefinition.PlacementConstraints)); err != nil {
   212  		log.Printf("[ERR] Error setting placement_constraints for (%s): %s", d.Id(), err)
   213  	}
   214  
   215  	return nil
   216  }
   217  
   218  func flattenPlacementConstraints(pcs []*ecs.TaskDefinitionPlacementConstraint) []map[string]interface{} {
   219  	if len(pcs) == 0 {
   220  		return nil
   221  	}
   222  	results := make([]map[string]interface{}, 0)
   223  	for _, pc := range pcs {
   224  		c := make(map[string]interface{})
   225  		c["type"] = *pc.Type
   226  		c["expression"] = *pc.Expression
   227  		results = append(results, c)
   228  	}
   229  	return results
   230  }
   231  
   232  func resourceAwsEcsTaskDefinitionDelete(d *schema.ResourceData, meta interface{}) error {
   233  	conn := meta.(*AWSClient).ecsconn
   234  
   235  	_, err := conn.DeregisterTaskDefinition(&ecs.DeregisterTaskDefinitionInput{
   236  		TaskDefinition: aws.String(d.Get("arn").(string)),
   237  	})
   238  	if err != nil {
   239  		return err
   240  	}
   241  
   242  	log.Printf("[DEBUG] Task definition %q deregistered.", d.Get("arn").(string))
   243  
   244  	return nil
   245  }
   246  
   247  func resourceAwsEcsTaskDefinitionVolumeHash(v interface{}) int {
   248  	var buf bytes.Buffer
   249  	m := v.(map[string]interface{})
   250  	buf.WriteString(fmt.Sprintf("%s-", m["name"].(string)))
   251  	buf.WriteString(fmt.Sprintf("%s-", m["host_path"].(string)))
   252  
   253  	return hashcode.String(buf.String())
   254  }