github.com/gwilym/terraform@v0.3.8-0.20151231151641-c7573de75b19/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 "dns": &schema.Schema{ 84 Type: schema.TypeSet, 85 Optional: true, 86 ForceNew: true, 87 Elem: &schema.Schema{Type: schema.TypeString}, 88 Set: stringSetHash, 89 }, 90 91 "publish_all_ports": &schema.Schema{ 92 Type: schema.TypeBool, 93 Optional: true, 94 ForceNew: true, 95 }, 96 97 "restart": &schema.Schema{ 98 Type: schema.TypeString, 99 Optional: true, 100 ForceNew: true, 101 Default: "no", 102 ValidateFunc: func(v interface{}, k string) (ws []string, es []error) { 103 value := v.(string) 104 if !regexp.MustCompile(`^(no|on-failure|always)$`).MatchString(value) { 105 es = append(es, fmt.Errorf( 106 "%q must be one of \"no\", \"on-failure\", or \"always\"", k)) 107 } 108 return 109 }, 110 }, 111 112 "max_retry_count": &schema.Schema{ 113 Type: schema.TypeInt, 114 Optional: true, 115 ForceNew: true, 116 }, 117 118 "volumes": &schema.Schema{ 119 Type: schema.TypeSet, 120 Optional: true, 121 ForceNew: true, 122 Elem: getVolumesElem(), 123 Set: resourceDockerVolumesHash, 124 }, 125 126 "ports": &schema.Schema{ 127 Type: schema.TypeSet, 128 Optional: true, 129 ForceNew: true, 130 Elem: getPortsElem(), 131 Set: resourceDockerPortsHash, 132 }, 133 134 "env": &schema.Schema{ 135 Type: schema.TypeSet, 136 Optional: true, 137 ForceNew: true, 138 Elem: &schema.Schema{Type: schema.TypeString}, 139 Set: stringSetHash, 140 }, 141 142 "links": &schema.Schema{ 143 Type: schema.TypeSet, 144 Optional: true, 145 ForceNew: true, 146 Elem: &schema.Schema{Type: schema.TypeString}, 147 Set: stringSetHash, 148 }, 149 150 "ip_address": &schema.Schema{ 151 Type: schema.TypeString, 152 Computed: true, 153 }, 154 155 "ip_prefix_length": &schema.Schema{ 156 Type: schema.TypeInt, 157 Computed: true, 158 }, 159 160 "gateway": &schema.Schema{ 161 Type: schema.TypeString, 162 Computed: true, 163 }, 164 165 "bridge": &schema.Schema{ 166 Type: schema.TypeString, 167 Computed: true, 168 }, 169 170 "privileged": &schema.Schema{ 171 Type: schema.TypeBool, 172 Optional: true, 173 ForceNew: true, 174 }, 175 176 "labels": &schema.Schema{ 177 Type: schema.TypeMap, 178 Optional: true, 179 ForceNew: true, 180 }, 181 182 "memory": &schema.Schema{ 183 Type: schema.TypeInt, 184 Optional: true, 185 ForceNew: true, 186 ValidateFunc: func(v interface{}, k string) (ws []string, es []error) { 187 value := v.(int) 188 if value < 0 { 189 es = append(es, fmt.Errorf("%q must be greater than or equal to 0", k)) 190 } 191 return 192 }, 193 }, 194 195 "memory_swap": &schema.Schema{ 196 Type: schema.TypeInt, 197 Optional: true, 198 ForceNew: true, 199 ValidateFunc: func(v interface{}, k string) (ws []string, es []error) { 200 value := v.(int) 201 if value < -1 { 202 es = append(es, fmt.Errorf("%q must be greater than or equal to -1", k)) 203 } 204 return 205 }, 206 }, 207 208 "cpu_shares": &schema.Schema{ 209 Type: schema.TypeInt, 210 Optional: true, 211 ForceNew: true, 212 ValidateFunc: func(v interface{}, k string) (ws []string, es []error) { 213 value := v.(int) 214 if value < 0 { 215 es = append(es, fmt.Errorf("%q must be greater than or equal to 0", k)) 216 } 217 return 218 }, 219 }, 220 221 "log_driver": &schema.Schema{ 222 Type: schema.TypeString, 223 Optional: true, 224 ForceNew: true, 225 Default: "json-file", 226 ValidateFunc: func(v interface{}, k string) (ws []string, es []error) { 227 value := v.(string) 228 if !regexp.MustCompile(`^(json-file|syslog|journald|gelf|fluentd)$`).MatchString(value) { 229 es = append(es, fmt.Errorf( 230 "%q must be one of \"json-file\", \"syslog\", \"journald\", \"gelf\", or \"fluentd\"", k)) 231 } 232 return 233 }, 234 }, 235 236 "log_opts": &schema.Schema{ 237 Type: schema.TypeMap, 238 Optional: true, 239 ForceNew: true, 240 }, 241 }, 242 } 243 } 244 245 func getVolumesElem() *schema.Resource { 246 return &schema.Resource{ 247 Schema: map[string]*schema.Schema{ 248 "from_container": &schema.Schema{ 249 Type: schema.TypeString, 250 Optional: true, 251 ForceNew: true, 252 }, 253 254 "container_path": &schema.Schema{ 255 Type: schema.TypeString, 256 Optional: true, 257 ForceNew: true, 258 }, 259 260 "host_path": &schema.Schema{ 261 Type: schema.TypeString, 262 Optional: true, 263 ForceNew: true, 264 }, 265 266 "read_only": &schema.Schema{ 267 Type: schema.TypeBool, 268 Optional: true, 269 ForceNew: true, 270 }, 271 }, 272 } 273 } 274 275 func getPortsElem() *schema.Resource { 276 return &schema.Resource{ 277 Schema: map[string]*schema.Schema{ 278 "internal": &schema.Schema{ 279 Type: schema.TypeInt, 280 Required: true, 281 ForceNew: true, 282 }, 283 284 "external": &schema.Schema{ 285 Type: schema.TypeInt, 286 Optional: true, 287 ForceNew: true, 288 }, 289 290 "ip": &schema.Schema{ 291 Type: schema.TypeString, 292 Optional: true, 293 ForceNew: true, 294 }, 295 296 "protocol": &schema.Schema{ 297 Type: schema.TypeString, 298 Default: "tcp", 299 Optional: true, 300 ForceNew: true, 301 }, 302 }, 303 } 304 } 305 306 func resourceDockerPortsHash(v interface{}) int { 307 var buf bytes.Buffer 308 m := v.(map[string]interface{}) 309 310 buf.WriteString(fmt.Sprintf("%v-", m["internal"].(int))) 311 312 if v, ok := m["external"]; ok { 313 buf.WriteString(fmt.Sprintf("%v-", v.(int))) 314 } 315 316 if v, ok := m["ip"]; ok { 317 buf.WriteString(fmt.Sprintf("%v-", v.(string))) 318 } 319 320 if v, ok := m["protocol"]; ok { 321 buf.WriteString(fmt.Sprintf("%v-", v.(string))) 322 } 323 324 return hashcode.String(buf.String()) 325 } 326 327 func resourceDockerVolumesHash(v interface{}) int { 328 var buf bytes.Buffer 329 m := v.(map[string]interface{}) 330 331 if v, ok := m["from_container"]; ok { 332 buf.WriteString(fmt.Sprintf("%v-", v.(string))) 333 } 334 335 if v, ok := m["container_path"]; ok { 336 buf.WriteString(fmt.Sprintf("%v-", v.(string))) 337 } 338 339 if v, ok := m["host_path"]; ok { 340 buf.WriteString(fmt.Sprintf("%v-", v.(string))) 341 } 342 343 if v, ok := m["read_only"]; ok { 344 buf.WriteString(fmt.Sprintf("%v-", v.(bool))) 345 } 346 347 return hashcode.String(buf.String()) 348 } 349 350 func stringSetHash(v interface{}) int { 351 return hashcode.String(v.(string)) 352 }