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 }