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