github.com/minamijoyo/terraform@v0.7.8-0.20161029001309-18b3736ba44b/builtin/providers/docker/resource_docker_container.go (about) 1 package docker 2 3 import ( 4 "bytes" 5 "fmt" 6 7 "regexp" 8 9 "github.com/hashicorp/terraform/helper/hashcode" 10 "github.com/hashicorp/terraform/helper/schema" 11 ) 12 13 func resourceDockerContainer() *schema.Resource { 14 return &schema.Resource{ 15 Create: resourceDockerContainerCreate, 16 Read: resourceDockerContainerRead, 17 Update: resourceDockerContainerUpdate, 18 Delete: resourceDockerContainerDelete, 19 20 Schema: map[string]*schema.Schema{ 21 "name": &schema.Schema{ 22 Type: schema.TypeString, 23 Required: true, 24 ForceNew: true, 25 }, 26 27 // Indicates whether the container must be running. 28 // 29 // An assumption is made that configured containers 30 // should be running; if not, they should not be in 31 // the configuration. Therefore a stopped container 32 // should be started. Set to false to have the 33 // provider leave the container alone. 34 // 35 // Actively-debugged containers are likely to be 36 // stopped and started manually, and Docker has 37 // some provisions for restarting containers that 38 // stop. The utility here comes from the fact that 39 // this will delete and re-create the container 40 // following the principle that the containers 41 // should be pristine when started. 42 "must_run": &schema.Schema{ 43 Type: schema.TypeBool, 44 Default: true, 45 Optional: true, 46 }, 47 48 // ForceNew is not true for image because we need to 49 // sane this against Docker image IDs, as each image 50 // can have multiple names/tags attached do it. 51 "image": &schema.Schema{ 52 Type: schema.TypeString, 53 Required: true, 54 ForceNew: true, 55 }, 56 57 "hostname": &schema.Schema{ 58 Type: schema.TypeString, 59 Optional: true, 60 ForceNew: true, 61 }, 62 63 "domainname": &schema.Schema{ 64 Type: schema.TypeString, 65 Optional: true, 66 ForceNew: true, 67 }, 68 69 "command": &schema.Schema{ 70 Type: schema.TypeList, 71 Optional: true, 72 ForceNew: true, 73 Elem: &schema.Schema{Type: schema.TypeString}, 74 }, 75 76 "entrypoint": &schema.Schema{ 77 Type: schema.TypeList, 78 Optional: true, 79 ForceNew: true, 80 Elem: &schema.Schema{Type: schema.TypeString}, 81 }, 82 83 "user": &schema.Schema{ 84 Type: schema.TypeString, 85 Optional: true, 86 ForceNew: true, 87 Elem: &schema.Schema{Type: schema.TypeString}, 88 }, 89 90 "dns": &schema.Schema{ 91 Type: schema.TypeSet, 92 Optional: true, 93 ForceNew: true, 94 Elem: &schema.Schema{Type: schema.TypeString}, 95 Set: schema.HashString, 96 }, 97 98 "dns_opts": &schema.Schema{ 99 Type: schema.TypeSet, 100 Optional: true, 101 ForceNew: true, 102 Elem: &schema.Schema{Type: schema.TypeString}, 103 Set: schema.HashString, 104 }, 105 106 "dns_search": &schema.Schema{ 107 Type: schema.TypeSet, 108 Optional: true, 109 ForceNew: true, 110 Elem: &schema.Schema{Type: schema.TypeString}, 111 Set: schema.HashString, 112 }, 113 114 "publish_all_ports": &schema.Schema{ 115 Type: schema.TypeBool, 116 Optional: true, 117 ForceNew: true, 118 }, 119 120 "restart": &schema.Schema{ 121 Type: schema.TypeString, 122 Optional: true, 123 ForceNew: true, 124 Default: "no", 125 ValidateFunc: func(v interface{}, k string) (ws []string, es []error) { 126 value := v.(string) 127 if !regexp.MustCompile(`^(no|on-failure|always|unless-stopped)$`).MatchString(value) { 128 es = append(es, fmt.Errorf( 129 "%q must be one of \"no\", \"on-failure\", \"always\" or \"unless-stopped\"", k)) 130 } 131 return 132 }, 133 }, 134 135 "max_retry_count": &schema.Schema{ 136 Type: schema.TypeInt, 137 Optional: true, 138 ForceNew: true, 139 }, 140 141 "volumes": &schema.Schema{ 142 Type: schema.TypeSet, 143 Optional: true, 144 ForceNew: true, 145 Elem: &schema.Resource{ 146 Schema: map[string]*schema.Schema{ 147 "from_container": &schema.Schema{ 148 Type: schema.TypeString, 149 Optional: true, 150 ForceNew: true, 151 }, 152 153 "container_path": &schema.Schema{ 154 Type: schema.TypeString, 155 Optional: true, 156 ForceNew: true, 157 }, 158 159 "host_path": &schema.Schema{ 160 Type: schema.TypeString, 161 Optional: true, 162 ForceNew: true, 163 ValidateFunc: func(v interface{}, k string) (ws []string, es []error) { 164 value := v.(string) 165 if !regexp.MustCompile(`^/`).MatchString(value) { 166 es = append(es, fmt.Errorf( 167 "%q must be an absolute path", k)) 168 } 169 return 170 }, 171 }, 172 173 "volume_name": &schema.Schema{ 174 Type: schema.TypeString, 175 Optional: true, 176 ForceNew: true, 177 }, 178 179 "read_only": &schema.Schema{ 180 Type: schema.TypeBool, 181 Optional: true, 182 ForceNew: true, 183 }, 184 }, 185 }, 186 Set: resourceDockerVolumesHash, 187 }, 188 189 "ports": &schema.Schema{ 190 Type: schema.TypeSet, 191 Optional: true, 192 ForceNew: true, 193 Elem: &schema.Resource{ 194 Schema: map[string]*schema.Schema{ 195 "internal": &schema.Schema{ 196 Type: schema.TypeInt, 197 Required: true, 198 ForceNew: true, 199 }, 200 201 "external": &schema.Schema{ 202 Type: schema.TypeInt, 203 Optional: true, 204 ForceNew: true, 205 }, 206 207 "ip": &schema.Schema{ 208 Type: schema.TypeString, 209 Optional: true, 210 ForceNew: true, 211 }, 212 213 "protocol": &schema.Schema{ 214 Type: schema.TypeString, 215 Default: "tcp", 216 Optional: true, 217 ForceNew: true, 218 }, 219 }, 220 }, 221 Set: resourceDockerPortsHash, 222 }, 223 224 "host": &schema.Schema{ 225 Type: schema.TypeSet, 226 Optional: true, 227 ForceNew: true, 228 Elem: &schema.Resource{ 229 Schema: map[string]*schema.Schema{ 230 "ip": &schema.Schema{ 231 Type: schema.TypeString, 232 Required: true, 233 ForceNew: true, 234 }, 235 236 "host": &schema.Schema{ 237 Type: schema.TypeString, 238 Required: true, 239 ForceNew: true, 240 }, 241 }, 242 }, 243 Set: resourceDockerHostsHash, 244 }, 245 246 "env": &schema.Schema{ 247 Type: schema.TypeSet, 248 Optional: true, 249 ForceNew: true, 250 Elem: &schema.Schema{Type: schema.TypeString}, 251 Set: schema.HashString, 252 }, 253 254 "links": &schema.Schema{ 255 Type: schema.TypeSet, 256 Optional: true, 257 ForceNew: true, 258 Elem: &schema.Schema{Type: schema.TypeString}, 259 Set: schema.HashString, 260 }, 261 262 "ip_address": &schema.Schema{ 263 Type: schema.TypeString, 264 Computed: true, 265 }, 266 267 "ip_prefix_length": &schema.Schema{ 268 Type: schema.TypeInt, 269 Computed: true, 270 }, 271 272 "gateway": &schema.Schema{ 273 Type: schema.TypeString, 274 Computed: true, 275 }, 276 277 "bridge": &schema.Schema{ 278 Type: schema.TypeString, 279 Computed: true, 280 }, 281 282 "privileged": &schema.Schema{ 283 Type: schema.TypeBool, 284 Optional: true, 285 ForceNew: true, 286 }, 287 288 "destroy_grace_seconds": &schema.Schema{ 289 Type: schema.TypeInt, 290 Optional: true, 291 }, 292 293 "labels": &schema.Schema{ 294 Type: schema.TypeMap, 295 Optional: true, 296 ForceNew: true, 297 }, 298 299 "memory": &schema.Schema{ 300 Type: schema.TypeInt, 301 Optional: true, 302 ForceNew: true, 303 ValidateFunc: func(v interface{}, k string) (ws []string, es []error) { 304 value := v.(int) 305 if value < 0 { 306 es = append(es, fmt.Errorf("%q must be greater than or equal to 0", k)) 307 } 308 return 309 }, 310 }, 311 312 "memory_swap": &schema.Schema{ 313 Type: schema.TypeInt, 314 Optional: true, 315 ForceNew: true, 316 ValidateFunc: func(v interface{}, k string) (ws []string, es []error) { 317 value := v.(int) 318 if value < -1 { 319 es = append(es, fmt.Errorf("%q must be greater than or equal to -1", k)) 320 } 321 return 322 }, 323 }, 324 325 "cpu_shares": &schema.Schema{ 326 Type: schema.TypeInt, 327 Optional: true, 328 ForceNew: true, 329 ValidateFunc: func(v interface{}, k string) (ws []string, es []error) { 330 value := v.(int) 331 if value < 0 { 332 es = append(es, fmt.Errorf("%q must be greater than or equal to 0", k)) 333 } 334 return 335 }, 336 }, 337 338 "log_driver": &schema.Schema{ 339 Type: schema.TypeString, 340 Optional: true, 341 ForceNew: true, 342 Default: "json-file", 343 ValidateFunc: func(v interface{}, k string) (ws []string, es []error) { 344 value := v.(string) 345 if !regexp.MustCompile(`^(json-file|syslog|journald|gelf|fluentd)$`).MatchString(value) { 346 es = append(es, fmt.Errorf( 347 "%q must be one of \"json-file\", \"syslog\", \"journald\", \"gelf\", or \"fluentd\"", k)) 348 } 349 return 350 }, 351 }, 352 353 "log_opts": &schema.Schema{ 354 Type: schema.TypeMap, 355 Optional: true, 356 ForceNew: true, 357 }, 358 359 "network_mode": &schema.Schema{ 360 Type: schema.TypeString, 361 Optional: true, 362 ForceNew: true, 363 }, 364 365 "networks": &schema.Schema{ 366 Type: schema.TypeSet, 367 Optional: true, 368 ForceNew: true, 369 Elem: &schema.Schema{Type: schema.TypeString}, 370 Set: schema.HashString, 371 }, 372 }, 373 } 374 } 375 376 func resourceDockerPortsHash(v interface{}) int { 377 var buf bytes.Buffer 378 m := v.(map[string]interface{}) 379 380 buf.WriteString(fmt.Sprintf("%v-", m["internal"].(int))) 381 382 if v, ok := m["external"]; ok { 383 buf.WriteString(fmt.Sprintf("%v-", v.(int))) 384 } 385 386 if v, ok := m["ip"]; ok { 387 buf.WriteString(fmt.Sprintf("%v-", v.(string))) 388 } 389 390 if v, ok := m["protocol"]; ok { 391 buf.WriteString(fmt.Sprintf("%v-", v.(string))) 392 } 393 394 return hashcode.String(buf.String()) 395 } 396 397 func resourceDockerHostsHash(v interface{}) int { 398 var buf bytes.Buffer 399 m := v.(map[string]interface{}) 400 401 if v, ok := m["ip"]; ok { 402 buf.WriteString(fmt.Sprintf("%v-", v.(string))) 403 } 404 405 if v, ok := m["host"]; ok { 406 buf.WriteString(fmt.Sprintf("%v-", v.(string))) 407 } 408 409 return hashcode.String(buf.String()) 410 } 411 412 func resourceDockerVolumesHash(v interface{}) int { 413 var buf bytes.Buffer 414 m := v.(map[string]interface{}) 415 416 if v, ok := m["from_container"]; ok { 417 buf.WriteString(fmt.Sprintf("%v-", v.(string))) 418 } 419 420 if v, ok := m["container_path"]; ok { 421 buf.WriteString(fmt.Sprintf("%v-", v.(string))) 422 } 423 424 if v, ok := m["host_path"]; ok { 425 buf.WriteString(fmt.Sprintf("%v-", v.(string))) 426 } 427 428 if v, ok := m["volume_name"]; ok { 429 buf.WriteString(fmt.Sprintf("%v-", v.(string))) 430 } 431 432 if v, ok := m["read_only"]; ok { 433 buf.WriteString(fmt.Sprintf("%v-", v.(bool))) 434 } 435 436 return hashcode.String(buf.String()) 437 }