diff --git a/builtin/providers/docker/resource_docker_container.go b/builtin/providers/docker/resource_docker_container.go index 2fb4efc29bb4..6bc03de3ef8e 100644 --- a/builtin/providers/docker/resource_docker_container.go +++ b/builtin/providers/docker/resource_docker_container.go @@ -138,6 +138,33 @@ func resourceDockerContainer() *schema.Resource { ForceNew: true, }, + "capabilities": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + ForceNew: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "add": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + ForceNew: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + }, + + "drop": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + ForceNew: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + }, + }, + }, + Set: resourceDockerCapabilitiesHash, + }, + "volumes": &schema.Schema{ Type: schema.TypeSet, Optional: true, @@ -396,6 +423,21 @@ func resourceDockerContainer() *schema.Resource { } } +func resourceDockerCapabilitiesHash(v interface{}) int { + var buf bytes.Buffer + m := v.(map[string]interface{}) + + if v, ok := m["add"]; ok { + buf.WriteString(fmt.Sprintf("%v-", v)) + } + + if v, ok := m["remove"]; ok { + buf.WriteString(fmt.Sprintf("%v-", v)) + } + + return hashcode.String(buf.String()) +} + func resourceDockerPortsHash(v interface{}) int { var buf bytes.Buffer m := v.(map[string]interface{}) diff --git a/builtin/providers/docker/resource_docker_container_funcs.go b/builtin/providers/docker/resource_docker_container_funcs.go index f74264a7740b..ba7d54aa2eb1 100644 --- a/builtin/providers/docker/resource_docker_container_funcs.go +++ b/builtin/providers/docker/resource_docker_container_funcs.go @@ -126,6 +126,15 @@ func resourceDockerContainerCreate(d *schema.ResourceData, meta interface{}) err hostConfig.VolumesFrom = volumesFrom } + if v, ok := d.GetOk("capabilities"); ok { + for _, capInt := range v.(*schema.Set).List() { + capa := capInt.(map[string]interface{}) + hostConfig.CapAdd = stringSetToStringSlice(capa["add"].(*schema.Set)) + hostConfig.CapDrop = stringSetToStringSlice(capa["drop"].(*schema.Set)) + break + } + } + if v, ok := d.GetOk("dns"); ok { hostConfig.DNS = stringSetToStringSlice(v.(*schema.Set)) } diff --git a/builtin/providers/docker/resource_docker_container_test.go b/builtin/providers/docker/resource_docker_container_test.go index 99f0ab3e987b..1da7e87e62f0 100644 --- a/builtin/providers/docker/resource_docker_container_test.go +++ b/builtin/providers/docker/resource_docker_container_test.go @@ -128,6 +128,22 @@ func TestAccDockerContainer_customized(t *testing.T) { return fmt.Errorf("Container has wrong dns search setting: %v", c.HostConfig.DNS[0]) } + if len(c.HostConfig.CapAdd) != 1 { + return fmt.Errorf("Container does not have the correct number of Capabilities in ADD: %d", len(c.HostConfig.CapAdd)) + } + + if c.HostConfig.CapAdd[0] != "ALL" { + return fmt.Errorf("Container has wrong CapAdd setting: %v", c.HostConfig.CapAdd[0]) + } + + if len(c.HostConfig.CapDrop) != 1 { + return fmt.Errorf("Container does not have the correct number of Capabilities in Drop: %d", len(c.HostConfig.CapDrop)) + } + + if c.HostConfig.CapDrop[0] != "SYS_ADMIN" { + return fmt.Errorf("Container has wrong CapDrop setting: %v", c.HostConfig.CapDrop[0]) + } + if c.HostConfig.CPUShares != 32 { return fmt.Errorf("Container has wrong cpu shares setting: %d", c.HostConfig.CPUShares) } @@ -311,6 +327,12 @@ resource "docker_container" "foo" { memory = 512 memory_swap = 2048 cpu_shares = 32 + + capabilities { + add= ["ALL"] + drop = ["SYS_ADMIN"] + } + dns = ["8.8.8.8"] dns_opts = ["rotate"] dns_search = ["example.com"] diff --git a/website/source/docs/providers/docker/r/container.html.markdown b/website/source/docs/providers/docker/r/container.html.markdown index 77783a906a08..8a7671591a4b 100644 --- a/website/source/docs/providers/docker/r/container.html.markdown +++ b/website/source/docs/providers/docker/r/container.html.markdown @@ -62,6 +62,7 @@ The following arguments are supported: * `must_run` - (Optional, bool) If true, then the Docker container will be kept running. If false, then as long as the container exists, Terraform assumes it is successful. +* `capabilities` - (Optional, block) See [Capabilities](#capabilities) below for details. * `ports` - (Optional, block) See [Ports](#ports) below for details. * `host` - (Optional, block) See [Extra Hosts](#extra_hosts) below for details. @@ -82,6 +83,27 @@ The following arguments are supported: * `destroy_grace_seconds` - (Optional, int) If defined will attempt to stop the container before destroying. Container will be destroyed after `n` seconds or on successful stop. * `upload` - (Optional, block) See [File Upload](#upload) below for details. + +### Capabilities + +`capabilities` is a block within the configuration that allows you to add or drop linux capabilities. For more information about what capabilities you can add and drop please visit the docker run documentation. + +* `add` - (Optional, set of strings) list of linux capabilities to add. +* `drop` - (Optional, set of strings) list of linux capabilities to drop. + +Example: + +``` +resource "docker_container" "ubuntu" { + name = "foo" + image = "${docker_image.ubuntu.latest}" + capabilities { + add = ["ALL"] + drop = ["SYS_ADMIN"] + } +} +``` + ### Ports