github.com/andresvia/terraform@v0.6.15-0.20160412045437-d51c75946785/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 "publish_all_ports": &schema.Schema{ 99 Type: schema.TypeBool, 100 Optional: true, 101 ForceNew: true, 102 }, 103 104 "restart": &schema.Schema{ 105 Type: schema.TypeString, 106 Optional: true, 107 ForceNew: true, 108 Default: "no", 109 ValidateFunc: func(v interface{}, k string) (ws []string, es []error) { 110 value := v.(string) 111 if !regexp.MustCompile(`^(no|on-failure|always|unless-stopped)$`).MatchString(value) { 112 es = append(es, fmt.Errorf( 113 "%q must be one of \"no\", \"on-failure\", \"always\" or \"unless-stopped\"", k)) 114 } 115 return 116 }, 117 }, 118 119 "max_retry_count": &schema.Schema{ 120 Type: schema.TypeInt, 121 Optional: true, 122 ForceNew: true, 123 }, 124 125 "volumes": &schema.Schema{ 126 Type: schema.TypeSet, 127 Optional: true, 128 ForceNew: true, 129 Elem: &schema.Resource{ 130 Schema: map[string]*schema.Schema{ 131 "from_container": &schema.Schema{ 132 Type: schema.TypeString, 133 Optional: true, 134 ForceNew: true, 135 }, 136 137 "container_path": &schema.Schema{ 138 Type: schema.TypeString, 139 Optional: true, 140 ForceNew: true, 141 }, 142 143 "host_path": &schema.Schema{ 144 Type: schema.TypeString, 145 Optional: true, 146 ForceNew: true, 147 ValidateFunc: func(v interface{}, k string) (ws []string, es []error) { 148 value := v.(string) 149 if !regexp.MustCompile(`^/`).MatchString(value) { 150 es = append(es, fmt.Errorf( 151 "%q must be an absolute path", k)) 152 } 153 return 154 }, 155 }, 156 157 "volume_name": &schema.Schema{ 158 Type: schema.TypeString, 159 Optional: true, 160 ForceNew: true, 161 }, 162 163 "read_only": &schema.Schema{ 164 Type: schema.TypeBool, 165 Optional: true, 166 ForceNew: true, 167 }, 168 }, 169 }, 170 Set: resourceDockerVolumesHash, 171 }, 172 173 "ports": &schema.Schema{ 174 Type: schema.TypeSet, 175 Optional: true, 176 ForceNew: true, 177 Elem: &schema.Resource{ 178 Schema: map[string]*schema.Schema{ 179 "internal": &schema.Schema{ 180 Type: schema.TypeInt, 181 Required: true, 182 ForceNew: true, 183 }, 184 185 "external": &schema.Schema{ 186 Type: schema.TypeInt, 187 Optional: true, 188 ForceNew: true, 189 }, 190 191 "ip": &schema.Schema{ 192 Type: schema.TypeString, 193 Optional: true, 194 ForceNew: true, 195 }, 196 197 "protocol": &schema.Schema{ 198 Type: schema.TypeString, 199 Default: "tcp", 200 Optional: true, 201 ForceNew: true, 202 }, 203 }, 204 }, 205 Set: resourceDockerPortsHash, 206 }, 207 208 "host": &schema.Schema{ 209 Type: schema.TypeSet, 210 Optional: true, 211 ForceNew: true, 212 Elem: &schema.Resource{ 213 Schema: map[string]*schema.Schema{ 214 "ip": &schema.Schema{ 215 Type: schema.TypeString, 216 Optional: true, 217 ForceNew: true, 218 }, 219 220 "host": &schema.Schema{ 221 Type: schema.TypeString, 222 Optional: true, 223 ForceNew: true, 224 }, 225 }, 226 }, 227 Set: resourceDockerHostsHash, 228 }, 229 230 "env": &schema.Schema{ 231 Type: schema.TypeSet, 232 Optional: true, 233 ForceNew: true, 234 Elem: &schema.Schema{Type: schema.TypeString}, 235 Set: schema.HashString, 236 }, 237 238 "links": &schema.Schema{ 239 Type: schema.TypeSet, 240 Optional: true, 241 ForceNew: true, 242 Elem: &schema.Schema{Type: schema.TypeString}, 243 Set: schema.HashString, 244 }, 245 246 "ip_address": &schema.Schema{ 247 Type: schema.TypeString, 248 Computed: true, 249 }, 250 251 "ip_prefix_length": &schema.Schema{ 252 Type: schema.TypeInt, 253 Computed: true, 254 }, 255 256 "gateway": &schema.Schema{ 257 Type: schema.TypeString, 258 Computed: true, 259 }, 260 261 "bridge": &schema.Schema{ 262 Type: schema.TypeString, 263 Computed: true, 264 }, 265 266 "privileged": &schema.Schema{ 267 Type: schema.TypeBool, 268 Optional: true, 269 ForceNew: true, 270 }, 271 272 "labels": &schema.Schema{ 273 Type: schema.TypeMap, 274 Optional: true, 275 ForceNew: true, 276 }, 277 278 "memory": &schema.Schema{ 279 Type: schema.TypeInt, 280 Optional: true, 281 ForceNew: true, 282 ValidateFunc: func(v interface{}, k string) (ws []string, es []error) { 283 value := v.(int) 284 if value < 0 { 285 es = append(es, fmt.Errorf("%q must be greater than or equal to 0", k)) 286 } 287 return 288 }, 289 }, 290 291 "memory_swap": &schema.Schema{ 292 Type: schema.TypeInt, 293 Optional: true, 294 ForceNew: true, 295 ValidateFunc: func(v interface{}, k string) (ws []string, es []error) { 296 value := v.(int) 297 if value < -1 { 298 es = append(es, fmt.Errorf("%q must be greater than or equal to -1", k)) 299 } 300 return 301 }, 302 }, 303 304 "cpu_shares": &schema.Schema{ 305 Type: schema.TypeInt, 306 Optional: true, 307 ForceNew: true, 308 ValidateFunc: func(v interface{}, k string) (ws []string, es []error) { 309 value := v.(int) 310 if value < 0 { 311 es = append(es, fmt.Errorf("%q must be greater than or equal to 0", k)) 312 } 313 return 314 }, 315 }, 316 317 "log_driver": &schema.Schema{ 318 Type: schema.TypeString, 319 Optional: true, 320 ForceNew: true, 321 Default: "json-file", 322 ValidateFunc: func(v interface{}, k string) (ws []string, es []error) { 323 value := v.(string) 324 if !regexp.MustCompile(`^(json-file|syslog|journald|gelf|fluentd)$`).MatchString(value) { 325 es = append(es, fmt.Errorf( 326 "%q must be one of \"json-file\", \"syslog\", \"journald\", \"gelf\", or \"fluentd\"", k)) 327 } 328 return 329 }, 330 }, 331 332 "log_opts": &schema.Schema{ 333 Type: schema.TypeMap, 334 Optional: true, 335 ForceNew: true, 336 }, 337 338 "network_mode": &schema.Schema{ 339 Type: schema.TypeString, 340 Optional: true, 341 ForceNew: true, 342 }, 343 344 "networks": &schema.Schema{ 345 Type: schema.TypeSet, 346 Optional: true, 347 ForceNew: true, 348 Elem: &schema.Schema{Type: schema.TypeString}, 349 Set: schema.HashString, 350 }, 351 }, 352 } 353 } 354 355 func resourceDockerPortsHash(v interface{}) int { 356 var buf bytes.Buffer 357 m := v.(map[string]interface{}) 358 359 buf.WriteString(fmt.Sprintf("%v-", m["internal"].(int))) 360 361 if v, ok := m["external"]; ok { 362 buf.WriteString(fmt.Sprintf("%v-", v.(int))) 363 } 364 365 if v, ok := m["ip"]; ok { 366 buf.WriteString(fmt.Sprintf("%v-", v.(string))) 367 } 368 369 if v, ok := m["protocol"]; ok { 370 buf.WriteString(fmt.Sprintf("%v-", v.(string))) 371 } 372 373 return hashcode.String(buf.String()) 374 } 375 376 func resourceDockerHostsHash(v interface{}) int { 377 var buf bytes.Buffer 378 m := v.(map[string]interface{}) 379 380 if v, ok := m["ip"]; ok { 381 buf.WriteString(fmt.Sprintf("%v-", v.(string))) 382 } 383 384 if v, ok := m["host"]; ok { 385 buf.WriteString(fmt.Sprintf("%v-", v.(string))) 386 } 387 388 return hashcode.String(buf.String()) 389 } 390 391 func resourceDockerVolumesHash(v interface{}) int { 392 var buf bytes.Buffer 393 m := v.(map[string]interface{}) 394 395 if v, ok := m["from_container"]; ok { 396 buf.WriteString(fmt.Sprintf("%v-", v.(string))) 397 } 398 399 if v, ok := m["container_path"]; ok { 400 buf.WriteString(fmt.Sprintf("%v-", v.(string))) 401 } 402 403 if v, ok := m["host_path"]; ok { 404 buf.WriteString(fmt.Sprintf("%v-", v.(string))) 405 } 406 407 if v, ok := m["volume_name"]; ok { 408 buf.WriteString(fmt.Sprintf("%v-", v.(string))) 409 } 410 411 if v, ok := m["read_only"]; ok { 412 buf.WriteString(fmt.Sprintf("%v-", v.(bool))) 413 } 414 415 return hashcode.String(buf.String()) 416 }