2015-03-27 18:33:17 -04:00
package docker
import (
2016-12-05 06:06:34 -05:00
"archive/tar"
"bytes"
2015-03-28 21:45:36 -04:00
"fmt"
2019-05-26 05:42:53 -04:00
"os"
2018-10-08 09:02:13 -04:00
"reflect"
2018-04-20 05:30:45 -04:00
"strconv"
"strings"
2015-03-27 18:33:17 -04:00
"testing"
2018-10-25 02:01:38 -04:00
"time"
2015-03-27 18:33:17 -04:00
2018-10-26 01:24:22 -04:00
"github.com/docker/docker/api/types/container"
2018-07-03 11:30:53 -04:00
"context"
2018-10-09 16:32:26 -04:00
2018-07-03 11:30:53 -04:00
"github.com/docker/docker/api/types"
2015-03-27 18:33:17 -04:00
"github.com/hashicorp/terraform/helper/resource"
2015-03-28 21:45:36 -04:00
"github.com/hashicorp/terraform/terraform"
2015-03-27 18:33:17 -04:00
)
2018-08-06 08:21:02 -04:00
func TestMapTypeMapValsToStringSlice ( t * testing . T ) {
typeMap := make ( map [ string ] interface { } )
typeMap [ "foo" ] = "bar"
typeMap [ "" ] = ""
stringSlice := mapTypeMapValsToStringSlice ( typeMap )
if len ( stringSlice ) != 1 {
t . Fatalf ( "slice should have length 1 but has %v" , len ( stringSlice ) )
}
}
2019-05-26 05:42:53 -04:00
func TestAccDockerContainer_private_image ( t * testing . T ) {
registry := "127.0.0.1:15000"
image := "127.0.0.1:15000/tftest-service:v1"
wd , _ := os . Getwd ( )
dockerConfig := wd + "/../scripts/testing/dockerconfig.json"
var c types . ContainerJSON
resource . Test ( t , resource . TestCase {
PreCheck : func ( ) { testAccPreCheck ( t ) } ,
Providers : testAccProviders ,
Steps : [ ] resource . TestStep {
{
Config : fmt . Sprintf ( testAccDockerContainerPrivateImage , registry , dockerConfig , image ) ,
Check : resource . ComposeTestCheckFunc (
testAccContainerRunning ( "docker_container.foo" , & c ) ,
) ,
} ,
} ,
CheckDestroy : checkAndRemoveImages ,
} )
}
2015-03-27 18:33:17 -04:00
func TestAccDockerContainer_basic ( t * testing . T ) {
2018-07-03 11:30:53 -04:00
var c types . ContainerJSON
2015-03-27 18:33:17 -04:00
resource . Test ( t , resource . TestCase {
PreCheck : func ( ) { testAccPreCheck ( t ) } ,
Providers : testAccProviders ,
Steps : [ ] resource . TestStep {
2019-03-01 16:02:17 -05:00
{
2015-03-27 18:33:17 -04:00
Config : testAccDockerContainerConfig ,
Check : resource . ComposeTestCheckFunc (
2015-10-26 17:24:48 -04:00
testAccContainerRunning ( "docker_container.foo" , & c ) ,
2015-03-27 18:33:17 -04:00
) ,
} ,
} ,
} )
}
2018-10-25 01:21:48 -04:00
func TestAccDockerContainer_basic_network ( t * testing . T ) {
var c types . ContainerJSON
resource . Test ( t , resource . TestCase {
PreCheck : func ( ) { testAccPreCheck ( t ) } ,
Providers : testAccProviders ,
Steps : [ ] resource . TestStep {
2019-03-01 16:02:17 -05:00
{
2018-10-25 01:21:48 -04:00
Config : testAccDockerContainerWith2BridgeNetworkConfig ,
Check : resource . ComposeTestCheckFunc (
testAccContainerRunning ( "docker_container.foo" , & c ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "bridge" , "" ) ,
resource . TestCheckResourceAttrSet ( "docker_container.foo" , "ip_address" ) ,
resource . TestCheckResourceAttrSet ( "docker_container.foo" , "ip_prefix_length" ) ,
resource . TestCheckResourceAttrSet ( "docker_container.foo" , "gateway" ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "network_data.#" , "2" ) ,
resource . TestCheckResourceAttrSet ( "docker_container.foo" , "network_data.0.network_name" ) ,
resource . TestCheckResourceAttrSet ( "docker_container.foo" , "network_data.0.ip_address" ) ,
resource . TestCheckResourceAttrSet ( "docker_container.foo" , "network_data.0.ip_prefix_length" ) ,
resource . TestCheckResourceAttrSet ( "docker_container.foo" , "network_data.0.gateway" ) ,
resource . TestCheckResourceAttrSet ( "docker_container.foo" , "network_data.1.network_name" ) ,
resource . TestCheckResourceAttrSet ( "docker_container.foo" , "network_data.1.ip_address" ) ,
resource . TestCheckResourceAttrSet ( "docker_container.foo" , "network_data.1.ip_prefix_length" ) ,
resource . TestCheckResourceAttrSet ( "docker_container.foo" , "network_data.1.gateway" ) ,
) ,
} ,
} ,
} )
}
func TestAccDockerContainer_2networks_withmode ( t * testing . T ) {
var c types . ContainerJSON
resource . Test ( t , resource . TestCase {
PreCheck : func ( ) { testAccPreCheck ( t ) } ,
Providers : testAccProviders ,
Steps : [ ] resource . TestStep {
2019-03-01 16:02:17 -05:00
{
2018-10-25 01:21:48 -04:00
Config : testAccDockerContainer2NetworksConfig ,
Check : resource . ComposeTestCheckFunc (
testAccContainerRunning ( "docker_container.foo" , & c ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "bridge" , "" ) ,
resource . TestCheckResourceAttrSet ( "docker_container.foo" , "ip_address" ) ,
resource . TestCheckResourceAttrSet ( "docker_container.foo" , "ip_prefix_length" ) ,
resource . TestCheckResourceAttrSet ( "docker_container.foo" , "gateway" ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "network_data.#" , "2" ) ,
resource . TestCheckResourceAttrSet ( "docker_container.foo" , "network_data.0.network_name" ) ,
resource . TestCheckResourceAttrSet ( "docker_container.foo" , "network_data.0.ip_address" ) ,
resource . TestCheckResourceAttrSet ( "docker_container.foo" , "network_data.0.ip_prefix_length" ) ,
resource . TestCheckResourceAttrSet ( "docker_container.foo" , "network_data.0.gateway" ) ,
resource . TestCheckResourceAttrSet ( "docker_container.foo" , "network_data.1.network_name" ) ,
resource . TestCheckResourceAttrSet ( "docker_container.foo" , "network_data.1.ip_address" ) ,
resource . TestCheckResourceAttrSet ( "docker_container.foo" , "network_data.1.ip_prefix_length" ) ,
resource . TestCheckResourceAttrSet ( "docker_container.foo" , "network_data.1.gateway" ) ,
resource . TestCheckResourceAttr ( "docker_container.bar" , "network_alias.#" , "1" ) ,
resource . TestCheckResourceAttr ( "docker_container.bar" , "bridge" , "" ) ,
resource . TestCheckResourceAttrSet ( "docker_container.bar" , "ip_address" ) ,
resource . TestCheckResourceAttrSet ( "docker_container.bar" , "ip_prefix_length" ) ,
resource . TestCheckResourceAttrSet ( "docker_container.bar" , "gateway" ) ,
resource . TestCheckResourceAttr ( "docker_container.bar" , "network_data.#" , "1" ) ,
resource . TestCheckResourceAttrSet ( "docker_container.bar" , "network_data.0.network_name" ) ,
resource . TestCheckResourceAttrSet ( "docker_container.bar" , "network_data.0.ip_address" ) ,
resource . TestCheckResourceAttrSet ( "docker_container.bar" , "network_data.0.ip_prefix_length" ) ,
resource . TestCheckResourceAttrSet ( "docker_container.bar" , "network_data.0.gateway" ) ,
) ,
} ,
} ,
} )
}
2015-03-27 18:33:17 -04:00
2017-05-15 06:09:50 -04:00
func TestAccDockerContainerPath_validation ( t * testing . T ) {
cases := [ ] struct {
Value string
ErrCount int
} {
{ Value : "/var/log" , ErrCount : 0 } ,
{ Value : "/tmp" , ErrCount : 0 } ,
{ Value : "C:\\Windows\\System32" , ErrCount : 0 } ,
{ Value : "C:\\Program Files\\MSBuild" , ErrCount : 0 } ,
{ Value : "test" , ErrCount : 1 } ,
{ Value : "C:Test" , ErrCount : 1 } ,
{ Value : "" , ErrCount : 1 } ,
}
for _ , tc := range cases {
_ , errors := validateDockerContainerPath ( tc . Value , "docker_container" )
if len ( errors ) != tc . ErrCount {
t . Fatalf ( "Expected the Docker Container Path to trigger a validation error" )
}
}
}
2016-01-15 16:59:33 -05:00
func TestAccDockerContainer_volume ( t * testing . T ) {
2018-07-03 11:30:53 -04:00
var c types . ContainerJSON
2016-01-15 16:59:33 -05:00
testCheck := func ( * terraform . State ) error {
2016-06-29 04:38:56 -04:00
if len ( c . Mounts ) != 1 {
return fmt . Errorf ( "Incorrect number of mounts: expected 1, got %d" , len ( c . Mounts ) )
2016-01-15 16:59:33 -05:00
}
for _ , v := range c . Mounts {
if v . Name != "testAccDockerContainerVolume_volume" {
continue
}
if v . Destination != "/tmp/volume" {
return fmt . Errorf ( "Bad destination on mount: expected /tmp/volume, got %q" , v . Destination )
}
if v . Mode != "rw" {
return fmt . Errorf ( "Bad mode on mount: expected rw, got %q" , v . Mode )
}
return nil
}
return fmt . Errorf ( "Mount for testAccDockerContainerVolume_volume not found" )
}
resource . Test ( t , resource . TestCase {
PreCheck : func ( ) { testAccPreCheck ( t ) } ,
Providers : testAccProviders ,
Steps : [ ] resource . TestStep {
2019-03-01 16:02:17 -05:00
{
2016-01-15 16:59:33 -05:00
Config : testAccDockerContainerVolumeConfig ,
Check : resource . ComposeTestCheckFunc (
testAccContainerRunning ( "docker_container.foo" , & c ) ,
testCheck ,
) ,
} ,
} ,
} )
}
2019-05-26 05:59:29 -04:00
func TestAccDockerContainer_mounts ( t * testing . T ) {
var c types . ContainerJSON
testCheck := func ( * terraform . State ) error {
if len ( c . Mounts ) != 2 {
return fmt . Errorf ( "Incorrect number of mounts: expected 2, got %d" , len ( c . Mounts ) )
}
for _ , v := range c . Mounts {
if v . Destination != "/mount/test" && v . Destination != "/mount/tmpfs" {
return fmt . Errorf ( "Bad destination on mount: expected /mount/test or /mount/tmpfs, got %q" , v . Destination )
}
}
return nil
}
resource . Test ( t , resource . TestCase {
PreCheck : func ( ) { testAccPreCheck ( t ) } ,
Providers : testAccProviders ,
Steps : [ ] resource . TestStep {
{
Config : testAccDockerContainerMountsConfig ,
Check : resource . ComposeTestCheckFunc (
testAccContainerRunning ( "docker_container.foo_mounts" , & c ) ,
testCheck ,
) ,
} ,
} ,
} )
}
func TestAccDockerContainer_tmpfs ( t * testing . T ) {
var c types . ContainerJSON
testCheck := func ( * terraform . State ) error {
if len ( c . HostConfig . Tmpfs ) != 1 {
return fmt . Errorf ( "Incorrect number of tmpfs: expected 1, got %d" , len ( c . HostConfig . Tmpfs ) )
}
for mountPath , _ := range c . HostConfig . Tmpfs {
if mountPath != "/mount/tmpfs" {
return fmt . Errorf ( "Bad destination on tmpfs: expected /mount/tmpfs, got %q" , mountPath )
}
}
return nil
}
resource . Test ( t , resource . TestCase {
PreCheck : func ( ) { testAccPreCheck ( t ) } ,
Providers : testAccProviders ,
Steps : [ ] resource . TestStep {
{
Config : testAccDockerContainerTmpfsConfig ,
Check : resource . ComposeTestCheckFunc (
testAccContainerRunning ( "docker_container.foo" , & c ) ,
testCheck ,
) ,
} ,
} ,
} )
}
2015-10-27 12:08:57 -04:00
func TestAccDockerContainer_customized ( t * testing . T ) {
2018-07-03 11:30:53 -04:00
var c types . ContainerJSON
2015-10-26 17:24:48 -04:00
testCheck := func ( * terraform . State ) error {
if len ( c . Config . Entrypoint ) < 3 ||
( c . Config . Entrypoint [ 0 ] != "/bin/bash" &&
c . Config . Entrypoint [ 1 ] != "-c" &&
c . Config . Entrypoint [ 2 ] != "ping localhost" ) {
return fmt . Errorf ( "Container wrong entrypoint: %s" , c . Config . Entrypoint )
}
2015-10-27 12:08:57 -04:00
2016-04-04 22:43:59 -04:00
if c . Config . User != "root:root" {
return fmt . Errorf ( "Container wrong user: %s" , c . Config . User )
}
2015-10-27 12:08:57 -04:00
if c . HostConfig . RestartPolicy . Name == "on-failure" {
if c . HostConfig . RestartPolicy . MaximumRetryCount != 5 {
return fmt . Errorf ( "Container has wrong restart policy max retry count: %d" , c . HostConfig . RestartPolicy . MaximumRetryCount )
}
} else {
return fmt . Errorf ( "Container has wrong restart policy: %s" , c . HostConfig . RestartPolicy . Name )
}
2015-11-04 15:46:24 -05:00
if c . HostConfig . Memory != ( 512 * 1024 * 1024 ) {
2015-10-27 19:53:49 -04:00
return fmt . Errorf ( "Container has wrong memory setting: %d" , c . HostConfig . Memory )
}
2015-11-04 15:46:24 -05:00
if c . HostConfig . MemorySwap != ( 2048 * 1024 * 1024 ) {
2016-06-29 10:48:15 -04:00
return fmt . Errorf ( "Container has wrong memory swap setting: %d\n\r\tPlease check that you machine supports memory swap (you can do that by running 'docker info' command)." , c . HostConfig . MemorySwap )
2015-10-27 19:53:49 -04:00
}
2015-11-04 15:46:24 -05:00
if c . HostConfig . CPUShares != 32 {
2015-10-27 19:53:49 -04:00
return fmt . Errorf ( "Container has wrong cpu shares setting: %d" , c . HostConfig . CPUShares )
}
2015-11-03 15:20:58 -05:00
2018-10-28 04:12:38 -04:00
if c . HostConfig . CpusetCpus != "0-1" {
return fmt . Errorf ( "Container has wrong cpu set setting: %s" , c . HostConfig . CpusetCpus )
}
2016-06-29 08:38:46 -04:00
if len ( c . HostConfig . DNS ) != 1 {
return fmt . Errorf ( "Container does not have the correct number of dns entries: %d" , len ( c . HostConfig . DNS ) )
}
if c . HostConfig . DNS [ 0 ] != "8.8.8.8" {
return fmt . Errorf ( "Container has wrong dns setting: %v" , c . HostConfig . DNS [ 0 ] )
}
if len ( c . HostConfig . DNSOptions ) != 1 {
return fmt . Errorf ( "Container does not have the correct number of dns option entries: %d" , len ( c . HostConfig . DNS ) )
}
if c . HostConfig . DNSOptions [ 0 ] != "rotate" {
return fmt . Errorf ( "Container has wrong dns option setting: %v" , c . HostConfig . DNS [ 0 ] )
}
if len ( c . HostConfig . DNSSearch ) != 1 {
return fmt . Errorf ( "Container does not have the correct number of dns search entries: %d" , len ( c . HostConfig . DNS ) )
}
if c . HostConfig . DNSSearch [ 0 ] != "example.com" {
return fmt . Errorf ( "Container has wrong dns search setting: %v" , c . HostConfig . DNS [ 0 ] )
}
2017-03-07 11:48:20 -05:00
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 ] )
}
2016-06-29 08:38:46 -04:00
if c . HostConfig . CPUShares != 32 {
return fmt . Errorf ( "Container has wrong cpu shares setting: %d" , c . HostConfig . CPUShares )
}
if c . HostConfig . CPUShares != 32 {
return fmt . Errorf ( "Container has wrong cpu shares setting: %d" , c . HostConfig . CPUShares )
}
2015-11-03 15:20:58 -05:00
if c . Config . Labels [ "env" ] != "prod" || c . Config . Labels [ "role" ] != "test" {
return fmt . Errorf ( "Container does not have the correct labels" )
}
2015-11-04 12:42:55 -05:00
if c . HostConfig . LogConfig . Type != "json-file" {
return fmt . Errorf ( "Container does not have the correct log config: %s" , c . HostConfig . LogConfig . Type )
}
if c . HostConfig . LogConfig . Config [ "max-size" ] != "10m" {
return fmt . Errorf ( "Container does not have the correct max-size log option: %v" , c . HostConfig . LogConfig . Config [ "max-size" ] )
}
if c . HostConfig . LogConfig . Config [ "max-file" ] != "20" {
return fmt . Errorf ( "Container does not have the correct max-file log option: %v" , c . HostConfig . LogConfig . Config [ "max-file" ] )
}
2016-01-14 21:59:07 -05:00
if len ( c . HostConfig . ExtraHosts ) != 2 {
return fmt . Errorf ( "Container does not have correct number of extra host entries, got %d" , len ( c . HostConfig . ExtraHosts ) )
}
2018-02-09 14:11:30 -05:00
if c . HostConfig . ExtraHosts [ 0 ] != "testhost:10.0.1.0" {
return fmt . Errorf ( "Container has incorrect extra host string at 0: %q" , c . HostConfig . ExtraHosts [ 0 ] )
2016-01-14 21:59:07 -05:00
}
2018-02-09 14:11:30 -05:00
if c . HostConfig . ExtraHosts [ 1 ] != "testhost2:10.0.2.0" {
return fmt . Errorf ( "Container has incorrect extra host string at 1: %q" , c . HostConfig . ExtraHosts [ 1 ] )
2016-01-14 21:59:07 -05:00
}
2017-05-22 09:20:32 -04:00
if _ , ok := c . NetworkSettings . Networks [ "test" ] ; ! ok {
return fmt . Errorf ( "Container is not connected to the right user defined network: test" )
}
2018-04-20 05:35:49 -04:00
if len ( c . HostConfig . Ulimits ) != 2 {
return fmt . Errorf ( "Container doesn't have 2 ulimits" )
}
2018-04-20 06:07:35 -04:00
if c . HostConfig . Ulimits [ 1 ] . Name != "nproc" {
2018-04-20 05:35:49 -04:00
return fmt . Errorf ( "Container doesn't have a nproc ulimit" )
}
2018-04-20 06:07:35 -04:00
if c . HostConfig . Ulimits [ 1 ] . Hard != 1024 {
2018-04-20 05:35:49 -04:00
return fmt . Errorf ( "Container doesn't have a correct nproc hard limit" )
}
2018-04-20 06:07:35 -04:00
if c . HostConfig . Ulimits [ 1 ] . Soft != 512 {
2018-04-20 05:35:49 -04:00
return fmt . Errorf ( "Container doesn't have a correct mem nproc limit" )
}
2018-04-20 06:07:35 -04:00
if c . HostConfig . Ulimits [ 0 ] . Name != "nofile" {
2018-04-20 05:35:49 -04:00
return fmt . Errorf ( "Container doesn't have a nofile ulimit" )
}
2018-04-20 06:07:35 -04:00
if c . HostConfig . Ulimits [ 0 ] . Hard != 262144 {
2018-04-20 05:35:49 -04:00
return fmt . Errorf ( "Container doesn't have a correct nofile hard limit" )
}
2018-04-20 06:07:35 -04:00
if c . HostConfig . Ulimits [ 0 ] . Soft != 200000 {
2018-04-20 05:35:49 -04:00
return fmt . Errorf ( "Container doesn't have a correct nofile soft limit" )
}
2018-10-11 04:55:18 -04:00
if c . HostConfig . PidMode != "host" {
return fmt . Errorf ( "Container doesn't have a correct pid mode" )
}
if c . HostConfig . UsernsMode != "testuser:231072:65536" {
return fmt . Errorf ( "Container doesn't have a correct userns mode" )
}
2015-10-26 17:24:48 -04:00
return nil
}
resource . Test ( t , resource . TestCase {
2019-03-05 09:53:56 -05:00
PreCheck : func ( ) { testAccPreCheck ( t ) ; testAccCheckSwapLimit ( t ) } ,
2015-10-26 17:24:48 -04:00
Providers : testAccProviders ,
Steps : [ ] resource . TestStep {
2019-03-01 16:02:17 -05:00
{
2015-10-27 12:08:57 -04:00
Config : testAccDockerContainerCustomizedConfig ,
2015-10-26 17:24:48 -04:00
Check : resource . ComposeTestCheckFunc (
testAccContainerRunning ( "docker_container.foo" , & c ) ,
testCheck ,
) ,
} ,
} ,
} )
}
2019-03-05 09:53:56 -05:00
func testAccCheckSwapLimit ( t * testing . T ) {
client := testAccProvider . Meta ( ) . ( * ProviderConfig ) . DockerClient
info , err := client . Info ( context . Background ( ) )
if err != nil {
t . Fatalf ( "Failed to check swap limit capability: %s" , err )
}
if ! info . SwapLimit {
t . Skip ( "Swap limit capability not available, skipping test" )
}
}
2016-12-05 06:06:34 -05:00
func TestAccDockerContainer_upload ( t * testing . T ) {
2018-07-03 11:30:53 -04:00
var c types . ContainerJSON
2016-12-05 06:06:34 -05:00
testCheck := func ( * terraform . State ) error {
2017-11-21 04:14:07 -05:00
client := testAccProvider . Meta ( ) . ( * ProviderConfig ) . DockerClient
2016-12-05 06:06:34 -05:00
2018-07-03 11:30:53 -04:00
srcPath := "/terraform/test.txt"
r , _ , err := client . CopyFromContainer ( context . Background ( ) , c . ID , srcPath )
if err != nil {
2016-12-05 06:06:34 -05:00
return fmt . Errorf ( "Unable to download a file from container: %s" , err )
}
tr := tar . NewReader ( r )
2018-04-20 05:30:45 -04:00
if header , err := tr . Next ( ) ; err != nil {
2016-12-05 06:06:34 -05:00
return fmt . Errorf ( "Unable to read content of tar archive: %s" , err )
2018-04-20 05:30:45 -04:00
} else {
mode := strconv . FormatInt ( header . Mode , 8 )
if ! strings . HasSuffix ( mode , "744" ) {
return fmt . Errorf ( "File permissions are incorrect: %s" , mode )
}
2016-12-05 06:06:34 -05:00
}
fbuf := new ( bytes . Buffer )
fbuf . ReadFrom ( tr )
content := fbuf . String ( )
if content != "foo" {
return fmt . Errorf ( "file content is invalid" )
}
return nil
}
resource . Test ( t , resource . TestCase {
PreCheck : func ( ) { testAccPreCheck ( t ) } ,
Providers : testAccProviders ,
Steps : [ ] resource . TestStep {
2019-03-01 16:02:17 -05:00
{
2016-12-05 06:06:34 -05:00
Config : testAccDockerContainerUploadConfig ,
Check : resource . ComposeTestCheckFunc (
testAccContainerRunning ( "docker_container.foo" , & c ) ,
testCheck ,
) ,
} ,
} ,
} )
}
2018-04-20 05:14:44 -04:00
func TestAccDockerContainer_device ( t * testing . T ) {
2018-07-03 11:30:53 -04:00
var c types . ContainerJSON
2018-04-20 05:14:44 -04:00
testCheck := func ( * terraform . State ) error {
client := testAccProvider . Meta ( ) . ( * ProviderConfig ) . DockerClient
2018-07-03 11:30:53 -04:00
createExecOpts := types . ExecConfig {
Cmd : [ ] string { "dd" , "if=/dev/zero_test" , "of=/tmp/test.txt" , "count=10" , "bs=1" } ,
2018-04-20 05:14:44 -04:00
}
2018-07-03 11:30:53 -04:00
exec , err := client . ContainerExecCreate ( context . Background ( ) , c . ID , createExecOpts )
2018-04-20 05:14:44 -04:00
if err != nil {
return fmt . Errorf ( "Unable to create a exec instance on container: %s" , err )
}
2018-07-03 11:30:53 -04:00
startExecOpts := types . ExecStartCheck { }
if err := client . ContainerExecStart ( context . Background ( ) , exec . ID , startExecOpts ) ; err != nil {
2018-04-20 05:14:44 -04:00
return fmt . Errorf ( "Unable to run exec a instance on container: %s" , err )
}
2018-07-03 11:30:53 -04:00
srcPath := "/tmp/test.txt"
out , _ , err := client . CopyFromContainer ( context . Background ( ) , c . ID , srcPath )
if err != nil {
2018-04-20 05:14:44 -04:00
return fmt . Errorf ( "Unable to download a file from container: %s" , err )
}
2018-07-03 11:30:53 -04:00
tr := tar . NewReader ( out )
2018-04-20 05:14:44 -04:00
if _ , err := tr . Next ( ) ; err != nil {
return fmt . Errorf ( "Unable to read content of tar archive: %s" , err )
}
fbuf := new ( bytes . Buffer )
fbuf . ReadFrom ( tr )
content := fbuf . Bytes ( )
if len ( content ) != 10 {
return fmt . Errorf ( "Incorrect size of file: %d" , len ( content ) )
}
for _ , value := range content {
if value != 0 {
return fmt . Errorf ( "Incorrect content in file: %v" , content )
}
}
return nil
}
resource . Test ( t , resource . TestCase {
PreCheck : func ( ) { testAccPreCheck ( t ) } ,
Providers : testAccProviders ,
Steps : [ ] resource . TestStep {
2019-03-01 16:02:17 -05:00
{
2018-04-20 05:14:44 -04:00
Config : testAccDockerContainerDeviceConfig ,
Check : resource . ComposeTestCheckFunc (
testAccContainerRunning ( "docker_container.foo" , & c ) ,
testCheck ,
) ,
} ,
} ,
} )
}
2018-10-29 01:36:21 -04:00
2018-10-09 16:32:26 -04:00
func TestAccDockerContainer_port_internal ( t * testing . T ) {
var c types . ContainerJSON
testCheck := func ( * terraform . State ) error {
portMap := c . NetworkSettings . NetworkSettingsBase . Ports
portBindings , ok := portMap [ "80/tcp" ]
if ! ok || len ( portMap [ "80/tcp" ] ) == 0 {
return fmt . Errorf ( "Port 80 on tcp is not set" )
}
portBindingsLength := len ( portBindings )
if portBindingsLength != 1 {
return fmt . Errorf ( "Expected 1 binding on port 80, but was %d" , portBindingsLength )
}
if len ( portBindings [ 0 ] . HostIP ) == 0 {
return fmt . Errorf ( "Expected host IP to be set, but was empty" )
}
if len ( portBindings [ 0 ] . HostPort ) == 0 {
return fmt . Errorf ( "Expected host port to be set, but was empty" )
}
return nil
}
resource . Test ( t , resource . TestCase {
PreCheck : func ( ) { testAccPreCheck ( t ) } ,
Providers : testAccProviders ,
Steps : [ ] resource . TestStep {
2019-03-01 16:02:17 -05:00
{
2018-10-09 16:32:26 -04:00
Config : testAccDockerContainerInternalPortConfig ,
Check : resource . ComposeTestCheckFunc (
testAccContainerRunning ( "docker_container.foo" , & c ) ,
testCheck ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "name" , "tf-test" ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "ports.#" , "1" ) ,
2018-10-16 12:49:57 -04:00
resource . TestCheckResourceAttr ( "docker_container.foo" , "ports.0.internal" , "80" ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "ports.0.ip" , "0.0.0.0" ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "ports.0.protocol" , "tcp" ) ,
testValueHigherEqualThan ( "docker_container.foo" , "ports.0.external" , 32768 ) ,
2018-10-09 16:32:26 -04:00
) ,
} ,
} ,
} )
}
2018-10-29 01:36:21 -04:00
2018-10-16 12:49:57 -04:00
func TestAccDockerContainer_port_multiple_internal ( t * testing . T ) {
var c types . ContainerJSON
testCheck := func ( * terraform . State ) error {
portMap := c . NetworkSettings . NetworkSettingsBase . Ports
portBindings , ok := portMap [ "80/tcp" ]
if ! ok || len ( portMap [ "80/tcp" ] ) == 0 {
return fmt . Errorf ( "Port 80 on tcp is not set" )
}
portBindingsLength := len ( portBindings )
if portBindingsLength != 1 {
return fmt . Errorf ( "Expected 1 binding on port 80, but was %d" , portBindingsLength )
}
if len ( portBindings [ 0 ] . HostIP ) == 0 {
return fmt . Errorf ( "Expected host IP to be set, but was empty" )
}
if len ( portBindings [ 0 ] . HostPort ) == 0 {
return fmt . Errorf ( "Expected host port to be set, but was empty" )
}
portBindings , ok = portMap [ "81/tcp" ]
if ! ok || len ( portMap [ "81/tcp" ] ) == 0 {
return fmt . Errorf ( "Port 81 on tcp is not set" )
}
portBindingsLength = len ( portBindings )
if portBindingsLength != 1 {
return fmt . Errorf ( "Expected 1 binding on port 81, but was %d" , portBindingsLength )
}
if len ( portBindings [ 0 ] . HostIP ) == 0 {
return fmt . Errorf ( "Expected host IP to be set, but was empty" )
}
if len ( portBindings [ 0 ] . HostPort ) == 0 {
return fmt . Errorf ( "Expected host port to be set, but was empty" )
}
return nil
}
resource . Test ( t , resource . TestCase {
PreCheck : func ( ) { testAccPreCheck ( t ) } ,
Providers : testAccProviders ,
Steps : [ ] resource . TestStep {
2019-03-01 16:02:17 -05:00
{
2018-10-16 12:49:57 -04:00
Config : testAccDockerContainerMultipleInternalPortConfig ,
Check : resource . ComposeTestCheckFunc (
testAccContainerRunning ( "docker_container.foo" , & c ) ,
testCheck ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "name" , "tf-test" ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "ports.#" , "2" ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "ports.0.internal" , "80" ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "ports.0.ip" , "0.0.0.0" ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "ports.0.protocol" , "tcp" ) ,
testValueHigherEqualThan ( "docker_container.foo" , "ports.0.external" , 32768 ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "ports.1.internal" , "81" ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "ports.1.ip" , "0.0.0.0" ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "ports.1.protocol" , "tcp" ) ,
testValueHigherEqualThan ( "docker_container.foo" , "ports.1.external" , 32768 ) ,
) ,
} ,
} ,
} )
}
2018-10-09 16:32:26 -04:00
func TestAccDockerContainer_port ( t * testing . T ) {
var c types . ContainerJSON
testCheck := func ( * terraform . State ) error {
portMap := c . NetworkSettings . NetworkSettingsBase . Ports
portBindings , ok := portMap [ "80/tcp" ]
if ! ok || len ( portMap [ "80/tcp" ] ) == 0 {
return fmt . Errorf ( "Port 80 on tcp is not set" )
}
portBindingsLength := len ( portBindings )
if portBindingsLength != 1 {
return fmt . Errorf ( "Expected 1 binding on port 80, but was %d" , portBindingsLength )
}
if len ( portBindings [ 0 ] . HostIP ) == 0 {
return fmt . Errorf ( "Expected host IP to be set, but was empty" )
}
if len ( portBindings [ 0 ] . HostPort ) == 0 {
return fmt . Errorf ( "Expected host port to be set, but was empty" )
}
return nil
}
resource . Test ( t , resource . TestCase {
PreCheck : func ( ) { testAccPreCheck ( t ) } ,
Providers : testAccProviders ,
Steps : [ ] resource . TestStep {
2019-03-01 16:02:17 -05:00
{
2018-10-09 16:32:26 -04:00
Config : testAccDockerContainerPortConfig ,
Check : resource . ComposeTestCheckFunc (
testAccContainerRunning ( "docker_container.foo" , & c ) ,
testCheck ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "name" , "tf-test" ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "ports.#" , "1" ) ,
2018-10-16 12:49:57 -04:00
resource . TestCheckResourceAttr ( "docker_container.foo" , "ports.0.internal" , "80" ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "ports.0.ip" , "0.0.0.0" ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "ports.0.protocol" , "tcp" ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "ports.0.external" , "32787" ) ,
) ,
} ,
} ,
} )
}
2018-10-29 01:36:21 -04:00
2018-10-16 12:49:57 -04:00
func TestAccDockerContainer_multiple_ports ( t * testing . T ) {
var c types . ContainerJSON
testCheck := func ( * terraform . State ) error {
portMap := c . NetworkSettings . NetworkSettingsBase . Ports
portBindings , ok := portMap [ "80/tcp" ]
if ! ok || len ( portMap [ "80/tcp" ] ) == 0 {
return fmt . Errorf ( "Port 80 on tcp is not set" )
}
portBindingsLength := len ( portBindings )
if portBindingsLength != 1 {
return fmt . Errorf ( "Expected 1 binding on port 80, but was %d" , portBindingsLength )
}
if len ( portBindings [ 0 ] . HostIP ) == 0 {
return fmt . Errorf ( "Expected host IP to be set, but was empty" )
}
if len ( portBindings [ 0 ] . HostPort ) == 0 {
return fmt . Errorf ( "Expected host port to be set, but was empty" )
}
portBindings , ok = portMap [ "81/tcp" ]
if ! ok || len ( portMap [ "81/tcp" ] ) == 0 {
return fmt . Errorf ( "Port 81 on tcp is not set" )
}
portBindingsLength = len ( portBindings )
if portBindingsLength != 1 {
return fmt . Errorf ( "Expected 1 binding on port 81, but was %d" , portBindingsLength )
}
if len ( portBindings [ 0 ] . HostIP ) == 0 {
return fmt . Errorf ( "Expected host IP to be set, but was empty" )
}
if len ( portBindings [ 0 ] . HostPort ) == 0 {
return fmt . Errorf ( "Expected host port to be set, but was empty" )
}
return nil
}
resource . Test ( t , resource . TestCase {
PreCheck : func ( ) { testAccPreCheck ( t ) } ,
Providers : testAccProviders ,
Steps : [ ] resource . TestStep {
2019-03-01 16:02:17 -05:00
{
2018-10-16 12:49:57 -04:00
Config : testAccDockerContainerMultiplePortConfig ,
Check : resource . ComposeTestCheckFunc (
testAccContainerRunning ( "docker_container.foo" , & c ) ,
testCheck ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "name" , "tf-test" ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "ports.#" , "2" ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "ports.0.internal" , "80" ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "ports.0.ip" , "0.0.0.0" ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "ports.0.protocol" , "tcp" ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "ports.0.external" , "32787" ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "ports.1.internal" , "81" ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "ports.1.ip" , "0.0.0.0" ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "ports.1.protocol" , "tcp" ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "ports.1.external" , "32788" ) ,
2018-10-09 16:32:26 -04:00
) ,
} ,
} ,
} )
}
2018-04-20 05:14:44 -04:00
2018-10-25 02:01:38 -04:00
func TestAccDockerContainer_rm ( t * testing . T ) {
var c types . ContainerJSON
testCheck := func ( * terraform . State ) error {
if ! c . HostConfig . AutoRemove {
return fmt . Errorf ( "Container doesn't have a correct autoremove flag" )
}
return nil
}
resource . Test ( t , resource . TestCase {
PreCheck : func ( ) { testAccPreCheck ( t ) } ,
Providers : testAccProviders ,
CheckDestroy : testAccContainerWaitConditionRemoved ( "docker_container.foo" , & c ) ,
Steps : [ ] resource . TestStep {
2019-03-01 16:02:17 -05:00
{
2018-10-25 02:01:38 -04:00
Config : testAccDockerContainerRmConfig ,
Check : resource . ComposeTestCheckFunc (
testAccContainerRunning ( "docker_container.foo" , & c ) ,
testCheck ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "name" , "tf-test" ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "rm" , "true" ) ,
) ,
} ,
} ,
} )
}
2018-10-28 13:41:47 -04:00
func TestAccDockerContainer_healthcheck ( t * testing . T ) {
2018-10-25 02:01:38 -04:00
var c types . ContainerJSON
testCheck := func ( * terraform . State ) error {
2018-10-28 13:41:47 -04:00
if ! reflect . DeepEqual ( c . Config . Healthcheck . Test , [ ] string { "CMD" , "/bin/true" } ) {
return fmt . Errorf ( "Container doesn't have a correct healthcheck test" )
2018-10-25 02:01:38 -04:00
}
2018-10-28 13:41:47 -04:00
if c . Config . Healthcheck . Interval != 30000000000 {
return fmt . Errorf ( "Container doesn't have a correct healthcheck interval" )
2018-10-25 02:01:38 -04:00
}
2018-10-28 13:41:47 -04:00
if c . Config . Healthcheck . Timeout != 5000000000 {
return fmt . Errorf ( "Container doesn't have a correct healthcheck timeout" )
}
if c . Config . Healthcheck . StartPeriod != 15000000000 {
return fmt . Errorf ( "Container doesn't have a correct healthcheck retries" )
}
if c . Config . Healthcheck . Retries != 10 {
return fmt . Errorf ( "Container doesn't have a correct healthcheck retries" )
2018-10-25 02:01:38 -04:00
}
return nil
}
2018-10-28 13:41:47 -04:00
resource . Test ( t , resource . TestCase {
PreCheck : func ( ) { testAccPreCheck ( t ) } ,
Providers : testAccProviders ,
Steps : [ ] resource . TestStep {
2019-03-01 16:02:17 -05:00
{
2018-10-28 13:41:47 -04:00
Config : testAccDockerContainerHealthcheckConfig ,
Check : resource . ComposeTestCheckFunc (
testAccContainerRunning ( "docker_container.foo" , & c ) ,
testCheck ,
) ,
} ,
} ,
} )
}
2018-10-25 02:01:38 -04:00
2018-10-28 13:41:47 -04:00
func TestAccDockerContainer_nostart ( t * testing . T ) {
var c types . ContainerJSON
2018-10-25 02:01:38 -04:00
resource . Test ( t , resource . TestCase {
PreCheck : func ( ) { testAccPreCheck ( t ) } ,
Providers : testAccProviders ,
Steps : [ ] resource . TestStep {
2019-03-01 16:02:17 -05:00
{
2018-10-28 13:41:47 -04:00
Config : testAccDockerContainerNoStartConfig ,
2018-10-25 02:01:38 -04:00
Check : resource . ComposeTestCheckFunc (
testAccContainerNotRunning ( "docker_container.foo" , & c ) ,
) ,
} ,
} ,
} )
}
2018-10-28 13:41:47 -04:00
func TestAccDockerContainer_attach ( t * testing . T ) {
2018-10-25 02:01:38 -04:00
var c types . ContainerJSON
resource . Test ( t , resource . TestCase {
PreCheck : func ( ) { testAccPreCheck ( t ) } ,
Providers : testAccProviders ,
Steps : [ ] resource . TestStep {
2019-03-01 16:02:17 -05:00
{
2018-10-28 13:41:47 -04:00
Config : testAccDockerContainerAttachConfig ,
2018-10-25 02:01:38 -04:00
Check : resource . ComposeTestCheckFunc (
2018-10-28 13:41:47 -04:00
testAccContainerNotRunning ( "docker_container.foo" , & c ) ,
2018-10-25 02:01:38 -04:00
resource . TestCheckResourceAttr ( "docker_container.foo" , "name" , "tf-test" ) ,
2018-10-28 13:41:47 -04:00
resource . TestCheckResourceAttr ( "docker_container.foo" , "attach" , "true" ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "must_run" , "false" ) ,
2018-10-25 02:01:38 -04:00
) ,
} ,
} ,
} )
}
2018-10-28 13:41:47 -04:00
func TestAccDockerContainer_logs ( t * testing . T ) {
2018-10-26 01:37:45 -04:00
var c types . ContainerJSON
2018-10-28 13:41:47 -04:00
2018-10-08 09:02:13 -04:00
resource . Test ( t , resource . TestCase {
PreCheck : func ( ) { testAccPreCheck ( t ) } ,
Providers : testAccProviders ,
Steps : [ ] resource . TestStep {
2019-03-01 16:02:17 -05:00
{
2018-10-28 13:41:47 -04:00
Config : testAccDockerContainerLogsConfig ,
2018-10-08 09:02:13 -04:00
Check : resource . ComposeTestCheckFunc (
2018-10-28 13:41:47 -04:00
testAccContainerNotRunning ( "docker_container.foo" , & c ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "name" , "tf-test" ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "attach" , "true" ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "logs" , "true" ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "must_run" , "false" ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "container_logs" , "\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u00021\n\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u00022\n\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u00023\n\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u00024\n\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u00025\n\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u00026\n\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u00027\n\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u00028\n\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u00029\n\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u000310\n" ) ,
2018-10-08 09:02:13 -04:00
) ,
} ,
} ,
} )
}
2018-10-28 13:41:47 -04:00
func TestAccDockerContainer_exitcode ( t * testing . T ) {
2018-10-27 04:09:03 -04:00
var c types . ContainerJSON
2018-10-28 13:41:47 -04:00
2018-10-08 14:14:30 -04:00
resource . Test ( t , resource . TestCase {
PreCheck : func ( ) { testAccPreCheck ( t ) } ,
Providers : testAccProviders ,
Steps : [ ] resource . TestStep {
2019-03-01 16:02:17 -05:00
{
2018-10-28 13:41:47 -04:00
Config : testAccDockerContainerExitCodeConfig ,
2018-10-08 14:14:30 -04:00
Check : resource . ComposeTestCheckFunc (
2018-10-28 13:41:47 -04:00
testAccContainerWaitConditionNotRunning ( "docker_container.foo" , & c ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "name" , "tf-test" ) ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "exit_code" , "123" ) ,
2018-10-08 14:14:30 -04:00
) ,
} ,
} ,
} )
}
2018-10-29 01:36:21 -04:00
func TestAccDockerContainer_ipv4address ( t * testing . T ) {
var c types . ContainerJSON
testCheck := func ( * terraform . State ) error {
networks := c . NetworkSettings . Networks
if len ( networks ) != 1 {
return fmt . Errorf ( "Container doesn't have a correct network" )
}
if _ , ok := networks [ "tf-test" ] ; ! ok {
return fmt . Errorf ( "Container doesn't have a correct network" )
}
if c . NetworkSettings . Networks [ "tf-test" ] . IPAMConfig == nil {
return fmt . Errorf ( "Container doesn't have a correct IPAM config" )
}
if c . NetworkSettings . Networks [ "tf-test" ] . IPAMConfig . IPv4Address != "10.0.1.123" {
return fmt . Errorf ( "Container doesn't have a correct IPv4 address" )
}
return nil
}
resource . Test ( t , resource . TestCase {
PreCheck : func ( ) { testAccPreCheck ( t ) } ,
Providers : testAccProviders ,
Steps : [ ] resource . TestStep {
2019-03-01 16:02:17 -05:00
{
2018-10-29 01:36:21 -04:00
Config : testAccDockerContainerNetworksIPv4AddressConfig ,
Check : resource . ComposeTestCheckFunc (
testAccContainerRunning ( "docker_container.foo" , & c ) ,
testCheck ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "name" , "tf-test" ) ,
) ,
} ,
} ,
} )
}
func TestAccDockerContainer_ipv6address ( t * testing . T ) {
var c types . ContainerJSON
testCheck := func ( * terraform . State ) error {
networks := c . NetworkSettings . Networks
if len ( networks ) != 1 {
return fmt . Errorf ( "Container doesn't have a correct network" )
}
if _ , ok := networks [ "tf-test" ] ; ! ok {
return fmt . Errorf ( "Container doesn't have a correct network" )
}
if c . NetworkSettings . Networks [ "tf-test" ] . IPAMConfig == nil {
return fmt . Errorf ( "Container doesn't have a correct IPAM config" )
}
if c . NetworkSettings . Networks [ "tf-test" ] . IPAMConfig . IPv6Address != "fd00:0:0:0::123" {
return fmt . Errorf ( "Container doesn't have a correct IPv6 address" )
}
return nil
}
resource . Test ( t , resource . TestCase {
PreCheck : func ( ) { testAccPreCheck ( t ) } ,
Providers : testAccProviders ,
Steps : [ ] resource . TestStep {
2019-03-01 16:02:17 -05:00
{
2018-10-29 01:36:21 -04:00
Config : testAccDockerContainerNetworksIPv6AddressConfig ,
Check : resource . ComposeTestCheckFunc (
testAccContainerRunning ( "docker_container.foo" , & c ) ,
testCheck ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "name" , "tf-test" ) ,
) ,
} ,
} ,
} )
}
func TestAccDockerContainer_dualstackaddress ( t * testing . T ) {
var c types . ContainerJSON
testCheck := func ( * terraform . State ) error {
networks := c . NetworkSettings . Networks
if len ( networks ) != 1 {
return fmt . Errorf ( "Container doesn't have a correct network" )
}
if _ , ok := networks [ "tf-test" ] ; ! ok {
return fmt . Errorf ( "Container doesn't have a correct network" )
}
if c . NetworkSettings . Networks [ "tf-test" ] . IPAMConfig == nil {
return fmt . Errorf ( "Container doesn't have a correct IPAM config" )
}
if c . NetworkSettings . Networks [ "tf-test" ] . IPAMConfig . IPv4Address != "10.0.1.123" {
return fmt . Errorf ( "Container doesn't have a correct IPv4 address" )
}
if c . NetworkSettings . Networks [ "tf-test" ] . IPAMConfig . IPv6Address != "fd00:0:0:0::123" {
return fmt . Errorf ( "Container doesn't have a correct IPv6 address" )
}
return nil
}
resource . Test ( t , resource . TestCase {
PreCheck : func ( ) { testAccPreCheck ( t ) } ,
Providers : testAccProviders ,
Steps : [ ] resource . TestStep {
2019-03-01 16:02:17 -05:00
{
2018-10-29 01:36:21 -04:00
Config : testAccDockerContainerNetworksDualStackAddressConfig ,
Check : resource . ComposeTestCheckFunc (
testAccContainerRunning ( "docker_container.foo" , & c ) ,
testCheck ,
resource . TestCheckResourceAttr ( "docker_container.foo" , "name" , "tf-test" ) ,
) ,
} ,
} ,
} )
}
2018-07-03 11:30:53 -04:00
func testAccContainerRunning ( n string , container * types . ContainerJSON ) resource . TestCheckFunc {
2015-03-28 21:45:36 -04:00
return func ( s * terraform . State ) error {
rs , ok := s . RootModule ( ) . Resources [ n ]
if ! ok {
return fmt . Errorf ( "Not found: %s" , n )
}
if rs . Primary . ID == "" {
return fmt . Errorf ( "No ID is set" )
}
2017-11-21 04:14:07 -05:00
client := testAccProvider . Meta ( ) . ( * ProviderConfig ) . DockerClient
2018-07-03 11:30:53 -04:00
containers , err := client . ContainerList ( context . Background ( ) , types . ContainerListOptions { } )
2015-03-28 21:45:36 -04:00
if err != nil {
return err
}
for _ , c := range containers {
if c . ID == rs . Primary . ID {
2018-07-03 11:30:53 -04:00
inspected , err := client . ContainerInspect ( context . Background ( ) , c . ID )
2015-10-26 17:24:48 -04:00
if err != nil {
return fmt . Errorf ( "Container could not be inspected: %s" , err )
}
2018-07-03 11:30:53 -04:00
* container = inspected
2015-03-28 21:45:36 -04:00
return nil
}
}
return fmt . Errorf ( "Container not found: %s" , rs . Primary . ID )
}
}
2018-10-25 02:01:38 -04:00
func testAccContainerNotRunning ( n string , container * types . ContainerJSON ) resource . TestCheckFunc {
return func ( s * terraform . State ) error {
rs , ok := s . RootModule ( ) . Resources [ n ]
if ! ok {
return fmt . Errorf ( "Not found: %s" , n )
}
2018-10-28 13:41:47 -04:00
2018-10-25 02:01:38 -04:00
if rs . Primary . ID == "" {
return fmt . Errorf ( "No ID is set" )
}
2018-10-28 13:41:47 -04:00
2018-10-25 02:01:38 -04:00
client := testAccProvider . Meta ( ) . ( * ProviderConfig ) . DockerClient
2018-10-28 02:29:02 -04:00
containers , err := client . ContainerList ( context . Background ( ) , types . ContainerListOptions {
All : true ,
} )
2018-10-25 02:01:38 -04:00
if err != nil {
return err
}
2018-10-28 13:41:47 -04:00
2018-10-25 02:01:38 -04:00
for _ , c := range containers {
if c . ID == rs . Primary . ID {
2018-10-28 02:29:02 -04:00
inspected , err := client . ContainerInspect ( context . Background ( ) , c . ID )
if err != nil {
return fmt . Errorf ( "Container could not be inspected: %s" , err )
}
* container = inspected
if container . State . Running {
return fmt . Errorf ( "Container is running: %s" , rs . Primary . ID )
}
2018-10-25 02:01:38 -04:00
}
}
2018-10-28 13:41:47 -04:00
2018-10-25 02:01:38 -04:00
return nil
}
}
func testAccContainerWaitConditionNotRunning ( n string , ct * types . ContainerJSON ) resource . TestCheckFunc {
return func ( s * terraform . State ) error {
rs , ok := s . RootModule ( ) . Resources [ n ]
if ! ok {
return fmt . Errorf ( "Not found: %s" , n )
}
if rs . Primary . ID == "" {
return fmt . Errorf ( "No ID is set" )
}
client := testAccProvider . Meta ( ) . ( * ProviderConfig ) . DockerClient
ctx , cancel := context . WithTimeout ( context . Background ( ) , 30 * time . Second )
defer cancel ( )
statusC , errC := client . ContainerWait ( ctx , rs . Primary . ID , container . WaitConditionNotRunning )
select {
case err := <- errC :
{
if err != nil {
return fmt . Errorf ( "Container is still running" )
}
}
case <- statusC :
}
return nil
}
}
func testAccContainerWaitConditionRemoved ( n string , ct * types . ContainerJSON ) resource . TestCheckFunc {
return func ( s * terraform . State ) error {
rs , ok := s . RootModule ( ) . Resources [ n ]
if ! ok {
return fmt . Errorf ( "Not found: %s" , n )
}
if rs . Primary . ID == "" {
return fmt . Errorf ( "No ID is set" )
}
client := testAccProvider . Meta ( ) . ( * ProviderConfig ) . DockerClient
ctx , cancel := context . WithTimeout ( context . Background ( ) , 30 * time . Second )
defer cancel ( )
statusC , errC := client . ContainerWait ( ctx , rs . Primary . ID , container . WaitConditionRemoved )
select {
case err := <- errC :
{
if err != nil {
return fmt . Errorf ( "Container has not been removed" )
}
}
case <- statusC :
}
return nil
}
}
2018-10-16 12:49:57 -04:00
func testValueHigherEqualThan ( name , key string , value int ) resource . TestCheckFunc {
return func ( s * terraform . State ) error {
ms := s . RootModule ( )
rs , ok := ms . Resources [ name ]
if ! ok {
return fmt . Errorf ( "Not found: %s" , name )
}
is := rs . Primary
if is == nil {
return fmt . Errorf ( "No primary instance: %s" , name )
}
vRaw , ok := is . Attributes [ key ]
if ! ok {
return fmt . Errorf ( "%s: Attribute '%s' not found" , name , key )
}
v , err := strconv . Atoi ( vRaw )
if err != nil {
return fmt . Errorf ( "'%s' is not a number" , vRaw )
}
if v < value {
return fmt . Errorf ( "'%v' is smaller than '%v', but was expected to be equal or greater" , v , value )
}
return nil
}
}
2019-05-26 05:42:53 -04:00
const testAccDockerContainerPrivateImage = `
provider "docker" {
alias = "private"
registry_auth {
address = "%s"
config_file = "%s"
}
}
resource "docker_container" "foo" {
provider = "docker.private"
name = "tf-test"
image = "%s"
}
`
2015-03-27 18:33:17 -04:00
const testAccDockerContainerConfig = `
resource "docker_image" "foo" {
2015-06-29 17:09:05 -04:00
name = "nginx:latest"
2015-03-27 18:33:17 -04:00
}
resource "docker_container" "foo" {
name = "tf-test"
image = "${docker_image.foo.latest}"
}
`
2016-01-14 21:59:07 -05:00
2018-10-25 01:21:48 -04:00
const testAccDockerContainerWith2BridgeNetworkConfig = `
resource "docker_network" "tftest" {
name = "tftest-contnw"
}
resource "docker_network" "tftest_2" {
name = "tftest-contnw-2"
}
resource "docker_image" "foo" {
name = "nginx:latest"
}
resource "docker_container" "foo" {
name = "tf-test"
image = "${docker_image.foo.latest}"
networks = [
"${docker_network.tftest.name}" ,
"${docker_network.tftest_2.name}"
]
}
`
2016-01-15 16:59:33 -05:00
const testAccDockerContainerVolumeConfig = `
resource "docker_image" "foo" {
name = "nginx:latest"
}
resource "docker_volume" "foo" {
name = "testAccDockerContainerVolume_volume"
}
resource "docker_container" "foo" {
name = "tf-test"
image = "${docker_image.foo.latest}"
volumes {
volume_name = "${docker_volume.foo.name}"
container_path = "/tmp/volume"
read_only = false
}
}
`
2019-05-26 05:59:29 -04:00
const testAccDockerContainerMountsConfig = `
resource "docker_image" "foo_mounts" {
name = "nginx:latest"
}
resource "docker_volume" "foo_mounts" {
name = "testAccDockerContainerMounts_volume"
}
resource "docker_container" "foo_mounts" {
name = "tf-test"
image = "${docker_image.foo_mounts.latest}"
2019-06-10 18:24:55 -04:00
mounts {
target = "/mount/test"
source = "${docker_volume.foo_mounts.name}"
type = "volume"
read_only = true
}
mounts {
target = "/mount/tmpfs"
type = "tmpfs"
}
2019-05-26 05:59:29 -04:00
}
`
const testAccDockerContainerTmpfsConfig = `
resource "docker_image" "foo" {
name = "nginx:latest"
}
resource "docker_container" "foo" {
name = "tf-test"
image = "${docker_image.foo.latest}"
tmpfs = {
"/mount/tmpfs" = "rw,noexec,nosuid"
}
}
`
2015-10-27 12:08:57 -04:00
const testAccDockerContainerCustomizedConfig = `
2015-10-26 17:24:48 -04:00
resource "docker_image" "foo" {
name = "nginx:latest"
}
resource "docker_container" "foo" {
name = "tf-test"
image = "${docker_image.foo.latest}"
2016-01-14 21:59:07 -05:00
entrypoint = [ "/bin/bash" , "-c" , "ping localhost" ]
2016-04-04 22:43:59 -04:00
user = "root:root"
2016-01-14 21:59:07 -05:00
restart = "on-failure"
2016-07-11 11:03:02 -04:00
destroy_grace_seconds = 10
2016-01-14 21:59:07 -05:00
max_retry_count = 5
memory = 512
memory_swap = 2048
cpu_shares = 32
2018-10-28 04:12:38 -04:00
cpu_set = "0-1"
2017-03-07 11:48:20 -05:00
capabilities {
2019-03-05 09:53:56 -05:00
add = [ "ALL" ]
2017-03-07 11:48:20 -05:00
drop = [ "SYS_ADMIN" ]
}
2016-06-29 08:38:46 -04:00
dns = [ "8.8.8.8" ]
dns_opts = [ "rotate" ]
dns_search = [ "example.com" ]
2019-06-10 18:24:55 -04:00
labels = {
2016-01-14 21:59:07 -05:00
env = "prod"
role = "test"
}
log_driver = "json-file"
log_opts = {
max - size = "10m"
max - file = 20
2015-11-04 12:42:55 -05:00
}
2016-01-01 03:57:21 -05:00
network_mode = "bridge"
2016-01-14 21:59:07 -05:00
2019-06-10 18:24:55 -04:00
networks_advanced {
name = "${docker_network.test_network.name}"
aliases = [ "tftest" ]
}
2017-05-22 09:20:32 -04:00
2016-01-14 21:59:07 -05:00
host {
host = "testhost"
ip = "10.0.1.0"
}
host {
host = "testhost2"
ip = "10.0.2.0"
}
2018-04-20 05:35:49 -04:00
ulimit {
name = "nproc"
hard = 1024
soft = 512
}
ulimit {
name = "nofile"
hard = 262144
soft = 200000
}
2018-10-11 04:55:18 -04:00
pid_mode = "host"
userns_mode = "testuser:231072:65536"
2015-10-26 17:24:48 -04:00
}
2017-05-22 09:20:32 -04:00
resource "docker_network" "test_network" {
name = "test"
}
2015-10-26 17:24:48 -04:00
`
2016-12-05 06:06:34 -05:00
const testAccDockerContainerUploadConfig = `
resource "docker_image" "foo" {
name = "nginx:latest"
}
resource "docker_container" "foo" {
name = "tf-test"
image = "${docker_image.foo.latest}"
upload {
content = "foo"
file = "/terraform/test.txt"
2018-04-20 05:30:45 -04:00
executable = true
2016-12-05 06:06:34 -05:00
}
}
`
2018-04-20 05:14:44 -04:00
const testAccDockerContainerDeviceConfig = `
resource "docker_image" "foo" {
name = "nginx:latest"
}
resource "docker_container" "foo" {
name = "tf-test"
image = "${docker_image.foo.latest}"
devices {
2018-10-29 01:36:21 -04:00
host_path = "/dev/zero"
container_path = "/dev/zero_test"
2018-04-20 05:14:44 -04:00
}
}
`
2018-10-09 16:32:26 -04:00
const testAccDockerContainerInternalPortConfig = `
resource "docker_image" "foo" {
name = "nginx:latest"
keep_locally = true
}
resource "docker_container" "foo" {
name = "tf-test"
image = "${docker_image.foo.latest}"
2019-06-10 18:24:55 -04:00
2018-10-09 16:32:26 -04:00
ports {
2018-10-25 02:01:38 -04:00
internal = 80
2018-10-09 16:32:26 -04:00
}
}
`
2018-10-16 12:49:57 -04:00
const testAccDockerContainerMultipleInternalPortConfig = `
resource "docker_image" "foo" {
name = "nginx:latest"
keep_locally = true
}
resource "docker_container" "foo" {
name = "tf-test"
image = "${docker_image.foo.latest}"
2019-06-10 18:24:55 -04:00
ports {
internal = 80
}
ports {
internal = 81
}
2018-10-16 12:49:57 -04:00
}
`
2018-10-09 16:32:26 -04:00
const testAccDockerContainerPortConfig = `
resource "docker_image" "foo" {
name = "nginx:latest"
keep_locally = true
}
resource "docker_container" "foo" {
name = "tf-test"
image = "${docker_image.foo.latest}"
ports {
2018-10-25 02:01:38 -04:00
internal = 80
external = 32787
2018-10-09 16:32:26 -04:00
}
}
`
2018-10-16 12:49:57 -04:00
const testAccDockerContainerMultiplePortConfig = `
resource "docker_image" "foo" {
name = "nginx:latest"
keep_locally = true
}
resource "docker_container" "foo" {
name = "tf-test"
image = "${docker_image.foo.latest}"
2019-06-10 18:24:55 -04:00
ports {
internal = 80
external = 32787
}
ports {
internal = 81
external = 32788
}
2018-10-16 12:49:57 -04:00
}
`
2018-10-25 02:01:38 -04:00
2018-10-25 01:21:48 -04:00
const testAccDockerContainer2NetworksConfig = `
resource "docker_image" "foo" {
name = "nginx:latest"
keep_locally = true
}
resource "docker_network" "test_network_1" {
name = "tftest-1"
}
resource "docker_network" "test_network_2" {
name = "tftest-2"
}
resource "docker_container" "foo" {
name = "tf-test"
image = "${docker_image.foo.latest}"
network_mode = "${docker_network.test_network_1.name}"
networks = [ "${docker_network.test_network_2.name}" ]
network_alias = [ "tftest-container" ]
}
resource "docker_container" "bar" {
name = "tf-test-bar"
image = "${docker_image.foo.latest}"
network_mode = "bridge"
networks = [ "${docker_network.test_network_2.name}" ]
network_alias = [ "tftest-container-foo" ]
}
`
2018-10-28 13:41:47 -04:00
2018-10-08 09:02:13 -04:00
const testAccDockerContainerHealthcheckConfig = `
resource "docker_image" "foo" {
name = "nginx:latest"
keep_locally = true
}
resource "docker_container" "foo" {
2018-10-25 03:50:33 -04:00
name = "tf-test"
image = "${docker_image.foo.latest}"
healthcheck {
test = [ "CMD" , "/bin/true" ]
interval = "30s"
timeout = "5s"
start_period = "15s"
retries = 10
}
2018-10-08 09:02:13 -04:00
}
`
2018-10-27 04:09:03 -04:00
const testAccDockerContainerNoStartConfig = `
resource "docker_image" "foo" {
name = "nginx:latest"
keep_locally = true
}
resource "docker_container" "foo" {
name = "tf-test"
image = "nginx:latest"
start = false
must_run = false
2018-10-08 14:14:30 -04:00
}
`
2018-10-29 01:36:21 -04:00
const testAccDockerContainerNetworksIPv4AddressConfig = `
resource "docker_network" "test" {
name = "tf-test"
ipam_config {
subnet = "10.0.1.0/24"
}
}
resource "docker_image" "foo" {
name = "nginx:latest"
keep_locally = true
}
resource "docker_container" "foo" {
name = "tf-test"
image = "${docker_image.foo.latest}"
2019-06-10 18:24:55 -04:00
networks_advanced {
name = "${docker_network.test.name}"
ipv4_address = "10.0.1.123"
}
2018-10-29 01:36:21 -04:00
}
`
const testAccDockerContainerNetworksIPv6AddressConfig = `
resource "docker_network" "test" {
name = "tf-test"
ipv6 = true
ipam_config {
subnet = "fd00::1/64"
}
}
resource "docker_image" "foo" {
name = "nginx:latest"
keep_locally = true
}
resource "docker_container" "foo" {
name = "tf-test"
image = "${docker_image.foo.latest}"
2019-06-10 18:24:55 -04:00
networks_advanced {
name = "${docker_network.test.name}"
ipv6_address = "fd00:0:0:0::123"
}
2018-10-29 01:36:21 -04:00
}
`
const testAccDockerContainerNetworksDualStackAddressConfig = `
resource "docker_network" "test" {
name = "tf-test"
ipv6 = true
2019-06-10 18:24:55 -04:00
ipam_config {
subnet = "10.0.1.0/24"
}
ipam_config {
subnet = "fd00::1/64"
}
2018-10-29 01:36:21 -04:00
}
resource "docker_image" "foo" {
name = "nginx:latest"
keep_locally = true
}
resource "docker_container" "foo" {
name = "tf-test"
image = "${docker_image.foo.latest}"
2019-06-10 18:24:55 -04:00
networks_advanced {
name = "${docker_network.test.name}"
ipv4_address = "10.0.1.123"
ipv6_address = "fd00:0:0:0::123"
}
2018-10-29 01:36:21 -04:00
}
`
2018-10-28 13:41:47 -04:00
const testAccDockerContainerRmConfig = `
resource "docker_image" "foo" {
name = "busybox:latest"
keep_locally = true
}
2018-10-29 02:07:37 -04:00
resource "docker_container" "foo" {
2018-10-28 13:41:47 -04:00
name = "tf-test"
image = "${docker_image.foo.latest}"
command = [ "/bin/sleep" , "15" ]
rm = true
}
`
const testAccDockerContainerAttachConfig = `
resource "docker_image" "foo" {
name = "busybox:latest"
keep_locally = true
}
2018-10-29 02:07:37 -04:00
resource "docker_container" "foo" {
2018-10-28 13:41:47 -04:00
name = "tf-test"
image = "${docker_image.foo.latest}"
command = [ "/bin/sh" , "-c" , "for i in $(seq 1 15); do sleep 1; done" ]
attach = true
must_run = false
}
`
const testAccDockerContainerLogsConfig = `
resource "docker_image" "foo" {
2018-10-29 02:07:37 -04:00
name = "busybox:latest"
keep_locally = true
2018-10-28 13:41:47 -04:00
}
resource "docker_container" "foo" {
2018-10-29 02:07:37 -04:00
name = "tf-test"
image = "${docker_image.foo.latest}"
command = [ "/bin/sh" , "-c" , "for i in $(seq 1 10); do echo \"$i\"; done" ]
attach = true
logs = true
must_run = false
2018-10-28 13:41:47 -04:00
}
`
const testAccDockerContainerExitCodeConfig = `
resource "docker_image" "foo" {
name = "busybox:latest"
keep_locally = true
}
2018-10-29 02:07:37 -04:00
resource "docker_container" "foo" {
2018-10-28 13:41:47 -04:00
name = "tf-test"
image = "${docker_image.foo.latest}"
command = [ "/bin/sh" , "-c" , "exit 123" ]
attach = true
must_run = false
}
`