mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-20 11:48:24 -06:00
* Updated docker container documentation Feedback from ticket #9350 indicated that documentation was out of date renamed `hosts_entry` to `host` added correct type information to *Extra Hosts* section. Refs: 9350 * Fixes for docker_container host object Feedback from ticket #9350 updated codebase so it reflects the requirements from docker in regards to `host` which is `Required` and not optional. It now accurately reflects the docker requirements and the terraform documentation. Test results > Bear in mind the failure it is because my laptop doesnt support memory swap. So this test will always fail. Changing the Schema from `optional` to `required` made no difference to the tests. make testacc TEST=./builtin/providers/docker/ ==> Checking that code complies with gofmt requirements... go generate $(go list ./... | grep -v /terraform/vendor/) 2016/10/14 15:04:40 Generated command/internal_plugin_list.go TF_ACC=1 go test ./builtin/providers/docker/ -v -timeout 120m === RUN TestAccDockerRegistryImage_basic --- PASS: TestAccDockerRegistryImage_basic (4.57s) === RUN TestAccDockerRegistryImage_private --- PASS: TestAccDockerRegistryImage_private (6.22s) === RUN TestProvider --- PASS: TestProvider (0.00s) === RUN TestProvider_impl --- PASS: TestProvider_impl (0.00s) === RUN TestAccDockerContainer_basic --- PASS: TestAccDockerContainer_basic (7.16s) === RUN TestAccDockerContainer_volume --- PASS: TestAccDockerContainer_volume (7.37s) === RUN TestAccDockerContainer_customized --- FAIL: TestAccDockerContainer_customized (18.99s) testing.go:265: Step 0 error: Check failed: Check 2/2 error: Container has wrong memory swap setting: -1 Please check that you machine supports memory swap (you can do that by running 'docker info' command). === RUN TestAccDockerImage_basic --- PASS: TestAccDockerImage_basic (2.58s) === RUN TestAccDockerImage_private --- PASS: TestAccDockerImage_private (2.70s) === RUN TestAccDockerImage_destroy --- PASS: TestAccDockerImage_destroy (30.00s) === RUN TestAccDockerImage_data --- PASS: TestAccDockerImage_data (5.93s) === RUN TestAccDockerNetwork_basic --- PASS: TestAccDockerNetwork_basic (0.24s) === RUN TestAccDockerVolume_basic --- PASS: TestAccDockerVolume_basic (0.05s) FAIL exit status 1 FAIL github.com/hashicorp/terraform/builtin/providers/docker 85.816s Makefile:47: recipe for target 'testacc' failed make: *** [testacc] Error 1 Refs: 9350
438 lines
10 KiB
Go
438 lines
10 KiB
Go
package docker
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
|
|
"regexp"
|
|
|
|
"github.com/hashicorp/terraform/helper/hashcode"
|
|
"github.com/hashicorp/terraform/helper/schema"
|
|
)
|
|
|
|
func resourceDockerContainer() *schema.Resource {
|
|
return &schema.Resource{
|
|
Create: resourceDockerContainerCreate,
|
|
Read: resourceDockerContainerRead,
|
|
Update: resourceDockerContainerUpdate,
|
|
Delete: resourceDockerContainerDelete,
|
|
|
|
Schema: map[string]*schema.Schema{
|
|
"name": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
ForceNew: true,
|
|
},
|
|
|
|
// Indicates whether the container must be running.
|
|
//
|
|
// An assumption is made that configured containers
|
|
// should be running; if not, they should not be in
|
|
// the configuration. Therefore a stopped container
|
|
// should be started. Set to false to have the
|
|
// provider leave the container alone.
|
|
//
|
|
// Actively-debugged containers are likely to be
|
|
// stopped and started manually, and Docker has
|
|
// some provisions for restarting containers that
|
|
// stop. The utility here comes from the fact that
|
|
// this will delete and re-create the container
|
|
// following the principle that the containers
|
|
// should be pristine when started.
|
|
"must_run": &schema.Schema{
|
|
Type: schema.TypeBool,
|
|
Default: true,
|
|
Optional: true,
|
|
},
|
|
|
|
// ForceNew is not true for image because we need to
|
|
// sane this against Docker image IDs, as each image
|
|
// can have multiple names/tags attached do it.
|
|
"image": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
ForceNew: true,
|
|
},
|
|
|
|
"hostname": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
},
|
|
|
|
"domainname": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
},
|
|
|
|
"command": &schema.Schema{
|
|
Type: schema.TypeList,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
Elem: &schema.Schema{Type: schema.TypeString},
|
|
},
|
|
|
|
"entrypoint": &schema.Schema{
|
|
Type: schema.TypeList,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
Elem: &schema.Schema{Type: schema.TypeString},
|
|
},
|
|
|
|
"user": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
Elem: &schema.Schema{Type: schema.TypeString},
|
|
},
|
|
|
|
"dns": &schema.Schema{
|
|
Type: schema.TypeSet,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
Elem: &schema.Schema{Type: schema.TypeString},
|
|
Set: schema.HashString,
|
|
},
|
|
|
|
"dns_opts": &schema.Schema{
|
|
Type: schema.TypeSet,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
Elem: &schema.Schema{Type: schema.TypeString},
|
|
Set: schema.HashString,
|
|
},
|
|
|
|
"dns_search": &schema.Schema{
|
|
Type: schema.TypeSet,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
Elem: &schema.Schema{Type: schema.TypeString},
|
|
Set: schema.HashString,
|
|
},
|
|
|
|
"publish_all_ports": &schema.Schema{
|
|
Type: schema.TypeBool,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
},
|
|
|
|
"restart": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
Default: "no",
|
|
ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
|
|
value := v.(string)
|
|
if !regexp.MustCompile(`^(no|on-failure|always|unless-stopped)$`).MatchString(value) {
|
|
es = append(es, fmt.Errorf(
|
|
"%q must be one of \"no\", \"on-failure\", \"always\" or \"unless-stopped\"", k))
|
|
}
|
|
return
|
|
},
|
|
},
|
|
|
|
"max_retry_count": &schema.Schema{
|
|
Type: schema.TypeInt,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
},
|
|
|
|
"volumes": &schema.Schema{
|
|
Type: schema.TypeSet,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
Elem: &schema.Resource{
|
|
Schema: map[string]*schema.Schema{
|
|
"from_container": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
},
|
|
|
|
"container_path": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
},
|
|
|
|
"host_path": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
|
|
value := v.(string)
|
|
if !regexp.MustCompile(`^/`).MatchString(value) {
|
|
es = append(es, fmt.Errorf(
|
|
"%q must be an absolute path", k))
|
|
}
|
|
return
|
|
},
|
|
},
|
|
|
|
"volume_name": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
},
|
|
|
|
"read_only": &schema.Schema{
|
|
Type: schema.TypeBool,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
},
|
|
},
|
|
},
|
|
Set: resourceDockerVolumesHash,
|
|
},
|
|
|
|
"ports": &schema.Schema{
|
|
Type: schema.TypeSet,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
Elem: &schema.Resource{
|
|
Schema: map[string]*schema.Schema{
|
|
"internal": &schema.Schema{
|
|
Type: schema.TypeInt,
|
|
Required: true,
|
|
ForceNew: true,
|
|
},
|
|
|
|
"external": &schema.Schema{
|
|
Type: schema.TypeInt,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
},
|
|
|
|
"ip": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
},
|
|
|
|
"protocol": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Default: "tcp",
|
|
Optional: true,
|
|
ForceNew: true,
|
|
},
|
|
},
|
|
},
|
|
Set: resourceDockerPortsHash,
|
|
},
|
|
|
|
"host": &schema.Schema{
|
|
Type: schema.TypeSet,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
Elem: &schema.Resource{
|
|
Schema: map[string]*schema.Schema{
|
|
"ip": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
ForceNew: true,
|
|
},
|
|
|
|
"host": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
ForceNew: true,
|
|
},
|
|
},
|
|
},
|
|
Set: resourceDockerHostsHash,
|
|
},
|
|
|
|
"env": &schema.Schema{
|
|
Type: schema.TypeSet,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
Elem: &schema.Schema{Type: schema.TypeString},
|
|
Set: schema.HashString,
|
|
},
|
|
|
|
"links": &schema.Schema{
|
|
Type: schema.TypeSet,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
Elem: &schema.Schema{Type: schema.TypeString},
|
|
Set: schema.HashString,
|
|
},
|
|
|
|
"ip_address": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Computed: true,
|
|
},
|
|
|
|
"ip_prefix_length": &schema.Schema{
|
|
Type: schema.TypeInt,
|
|
Computed: true,
|
|
},
|
|
|
|
"gateway": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Computed: true,
|
|
},
|
|
|
|
"bridge": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Computed: true,
|
|
},
|
|
|
|
"privileged": &schema.Schema{
|
|
Type: schema.TypeBool,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
},
|
|
|
|
"destroy_grace_seconds": &schema.Schema{
|
|
Type: schema.TypeInt,
|
|
Optional: true,
|
|
},
|
|
|
|
"labels": &schema.Schema{
|
|
Type: schema.TypeMap,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
},
|
|
|
|
"memory": &schema.Schema{
|
|
Type: schema.TypeInt,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
|
|
value := v.(int)
|
|
if value < 0 {
|
|
es = append(es, fmt.Errorf("%q must be greater than or equal to 0", k))
|
|
}
|
|
return
|
|
},
|
|
},
|
|
|
|
"memory_swap": &schema.Schema{
|
|
Type: schema.TypeInt,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
|
|
value := v.(int)
|
|
if value < -1 {
|
|
es = append(es, fmt.Errorf("%q must be greater than or equal to -1", k))
|
|
}
|
|
return
|
|
},
|
|
},
|
|
|
|
"cpu_shares": &schema.Schema{
|
|
Type: schema.TypeInt,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
|
|
value := v.(int)
|
|
if value < 0 {
|
|
es = append(es, fmt.Errorf("%q must be greater than or equal to 0", k))
|
|
}
|
|
return
|
|
},
|
|
},
|
|
|
|
"log_driver": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
Default: "json-file",
|
|
ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
|
|
value := v.(string)
|
|
if !regexp.MustCompile(`^(json-file|syslog|journald|gelf|fluentd)$`).MatchString(value) {
|
|
es = append(es, fmt.Errorf(
|
|
"%q must be one of \"json-file\", \"syslog\", \"journald\", \"gelf\", or \"fluentd\"", k))
|
|
}
|
|
return
|
|
},
|
|
},
|
|
|
|
"log_opts": &schema.Schema{
|
|
Type: schema.TypeMap,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
},
|
|
|
|
"network_mode": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
},
|
|
|
|
"networks": &schema.Schema{
|
|
Type: schema.TypeSet,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
Elem: &schema.Schema{Type: schema.TypeString},
|
|
Set: schema.HashString,
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func resourceDockerPortsHash(v interface{}) int {
|
|
var buf bytes.Buffer
|
|
m := v.(map[string]interface{})
|
|
|
|
buf.WriteString(fmt.Sprintf("%v-", m["internal"].(int)))
|
|
|
|
if v, ok := m["external"]; ok {
|
|
buf.WriteString(fmt.Sprintf("%v-", v.(int)))
|
|
}
|
|
|
|
if v, ok := m["ip"]; ok {
|
|
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
|
|
}
|
|
|
|
if v, ok := m["protocol"]; ok {
|
|
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
|
|
}
|
|
|
|
return hashcode.String(buf.String())
|
|
}
|
|
|
|
func resourceDockerHostsHash(v interface{}) int {
|
|
var buf bytes.Buffer
|
|
m := v.(map[string]interface{})
|
|
|
|
if v, ok := m["ip"]; ok {
|
|
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
|
|
}
|
|
|
|
if v, ok := m["host"]; ok {
|
|
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
|
|
}
|
|
|
|
return hashcode.String(buf.String())
|
|
}
|
|
|
|
func resourceDockerVolumesHash(v interface{}) int {
|
|
var buf bytes.Buffer
|
|
m := v.(map[string]interface{})
|
|
|
|
if v, ok := m["from_container"]; ok {
|
|
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
|
|
}
|
|
|
|
if v, ok := m["container_path"]; ok {
|
|
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
|
|
}
|
|
|
|
if v, ok := m["host_path"]; ok {
|
|
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
|
|
}
|
|
|
|
if v, ok := m["volume_name"]; ok {
|
|
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
|
|
}
|
|
|
|
if v, ok := m["read_only"]; ok {
|
|
buf.WriteString(fmt.Sprintf("%v-", v.(bool)))
|
|
}
|
|
|
|
return hashcode.String(buf.String())
|
|
}
|