github.com/mponton/terratest@v0.44.0/modules/docker/inspect_test.go (about)

     1  package docker
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/mponton/terratest/modules/random"
     9  	"github.com/mponton/terratest/modules/shell"
    10  	"github.com/stretchr/testify/require"
    11  )
    12  
    13  const dockerInspectTestImage = "nginx:1.17-alpine"
    14  
    15  func TestInspect(t *testing.T) {
    16  	t.Parallel()
    17  
    18  	// append timestamp to container name to allow running tests in parallel
    19  	name := "inspect-test-" + random.UniqueId()
    20  
    21  	// running the container detached to allow inspection while it is running
    22  	options := &RunOptions{
    23  		Detach: true,
    24  		Name:   name,
    25  	}
    26  
    27  	id := RunAndGetID(t, dockerInspectTestImage, options)
    28  	defer removeContainer(t, id)
    29  
    30  	c := Inspect(t, id)
    31  
    32  	require.Equal(t, id, c.ID)
    33  	require.Equal(t, name, c.Name)
    34  	require.IsType(t, time.Time{}, c.Created)
    35  	require.Equal(t, true, c.Running)
    36  }
    37  
    38  func TestInspectWithExposedPort(t *testing.T) {
    39  	t.Parallel()
    40  
    41  	// choosing an unique high port to avoid conflict on test machines
    42  	port := 13031
    43  
    44  	options := &RunOptions{
    45  		Detach:       true,
    46  		OtherOptions: []string{fmt.Sprintf("-p=%d:80", port)},
    47  	}
    48  
    49  	id := RunAndGetID(t, dockerInspectTestImage, options)
    50  	defer removeContainer(t, id)
    51  
    52  	c := Inspect(t, id)
    53  
    54  	require.NotEmptyf(t, c.Ports, "Container's exposed ports should not be empty")
    55  	require.EqualValues(t, 80, c.Ports[0].ContainerPort)
    56  	require.EqualValues(t, port, c.Ports[0].HostPort)
    57  }
    58  
    59  func TestInspectWithRandomExposedPort(t *testing.T) {
    60  	t.Parallel()
    61  
    62  	var expectedPort uint16 = 80
    63  	var unexpectedPort uint16 = 1234
    64  	options := &RunOptions{
    65  		Detach:       true,
    66  		OtherOptions: []string{fmt.Sprintf("-P")},
    67  	}
    68  
    69  	id := RunAndGetID(t, dockerInspectTestImage, options)
    70  	defer removeContainer(t, id)
    71  
    72  	c := Inspect(t, id)
    73  
    74  	require.NotEmptyf(t, c.Ports, "Container's exposed ports should not be empty")
    75  	require.NotEqualf(t, uint16(0), c.GetExposedHostPort(expectedPort), fmt.Sprintf("There are no exposed port %d!", expectedPort))
    76  	require.Equalf(t, uint16(0), c.GetExposedHostPort(unexpectedPort), fmt.Sprintf("There is an unexpected exposed port %d!", unexpectedPort))
    77  }
    78  
    79  func TestInspectWithHostVolume(t *testing.T) {
    80  	t.Parallel()
    81  
    82  	c := runWithVolume(t, "/tmp:/foo/bar")
    83  
    84  	require.NotEmptyf(t, c.Binds, "Container's host volumes should not be empty")
    85  	require.Equal(t, "/tmp", c.Binds[0].Source)
    86  	require.Equal(t, "/foo/bar", c.Binds[0].Destination)
    87  }
    88  
    89  func TestInspectWithAnonymousVolume(t *testing.T) {
    90  	t.Parallel()
    91  
    92  	c := runWithVolume(t, "/foo/bar")
    93  
    94  	require.Empty(t, c.Binds, "Container's host volumes be empty when using an anonymous volume")
    95  }
    96  
    97  func TestInspectWithNamedVolume(t *testing.T) {
    98  	t.Parallel()
    99  
   100  	c := runWithVolume(t, "foobar:/foo/bar")
   101  
   102  	require.NotEmptyf(t, c.Binds, "Container's host volumes should not be empty")
   103  	require.Equal(t, "foobar", c.Binds[0].Source)
   104  	require.Equal(t, "/foo/bar", c.Binds[0].Destination)
   105  }
   106  
   107  func TestInspectWithInvalidContainerID(t *testing.T) {
   108  	t.Parallel()
   109  
   110  	_, err := InspectE(t, "This is not a valid container ID")
   111  	require.Error(t, err)
   112  }
   113  
   114  func TestInspectWithUnknownContainerID(t *testing.T) {
   115  	t.Parallel()
   116  
   117  	_, err := InspectE(t, "abcde123456")
   118  	require.Error(t, err)
   119  }
   120  
   121  func TestInspectReturnsCorrectHealthCheckWhenStarting(t *testing.T) {
   122  	t.Parallel()
   123  
   124  	c := runWithHealthCheck(t, "service nginx status", time.Second, 0)
   125  
   126  	require.Equal(t, "starting", c.Health.Status)
   127  	require.Equal(t, uint8(0), c.Health.FailingStreak)
   128  	require.Emptyf(t, c.Health.Log, "Mising log of health check runs")
   129  }
   130  
   131  func TestInspectReturnsCorrectHealthCheckWhenUnhealthy(t *testing.T) {
   132  	t.Parallel()
   133  
   134  	c := runWithHealthCheck(t, "service nginx status", time.Second, 5*time.Second)
   135  
   136  	require.Equal(t, "unhealthy", c.Health.Status)
   137  	require.NotEqual(t, uint8(0), c.Health.FailingStreak)
   138  	require.NotEmptyf(t, c.Health.Log, "Mising log of health check runs")
   139  	require.Equal(t, uint8(0x7f), c.Health.Log[0].ExitCode)
   140  	require.Equal(t, "/bin/sh: service nginx status: not found\n", c.Health.Log[0].Output)
   141  }
   142  
   143  func runWithHealthCheck(t *testing.T, check string, frequency time.Duration, delay time.Duration) *ContainerInspect {
   144  	// append timestamp to container name to allow running tests in parallel
   145  	name := "inspect-test-" + random.UniqueId()
   146  
   147  	// running the container detached to allow inspection while it is running
   148  	options := &RunOptions{
   149  		Detach: true,
   150  		Name:   name,
   151  		OtherOptions: []string{
   152  			fmt.Sprintf("--health-cmd='%s'", check),
   153  			fmt.Sprintf("--health-interval=%s", frequency),
   154  		},
   155  	}
   156  
   157  	id := RunAndGetID(t, dockerInspectTestImage, options)
   158  	defer removeContainer(t, id)
   159  
   160  	time.Sleep(delay)
   161  
   162  	return Inspect(t, id)
   163  }
   164  
   165  func runWithVolume(t *testing.T, volume string) *ContainerInspect {
   166  	options := &RunOptions{
   167  		Detach:  true,
   168  		Volumes: []string{volume},
   169  	}
   170  
   171  	id := RunAndGetID(t, dockerInspectTestImage, options)
   172  	defer removeContainer(t, id)
   173  
   174  	return Inspect(t, id)
   175  }
   176  
   177  func removeContainer(t *testing.T, id string) {
   178  	cmd := shell.Command{
   179  		Command: "docker",
   180  		Args:    []string{"container", "rm", "--force", id},
   181  	}
   182  
   183  	shell.RunCommand(t, cmd)
   184  }