github.com/bradfeehan/terraform@v0.7.0-rc3.0.20170529055808-34b45c5ad841/builtin/providers/docker/resource_docker_container_test.go (about)

     1  package docker
     2  
     3  import (
     4  	"archive/tar"
     5  	"bytes"
     6  	"fmt"
     7  	"testing"
     8  
     9  	dc "github.com/fsouza/go-dockerclient"
    10  	"github.com/hashicorp/terraform/helper/resource"
    11  	"github.com/hashicorp/terraform/terraform"
    12  )
    13  
    14  func TestAccDockerContainer_basic(t *testing.T) {
    15  	var c dc.Container
    16  	resource.Test(t, resource.TestCase{
    17  		PreCheck:  func() { testAccPreCheck(t) },
    18  		Providers: testAccProviders,
    19  		Steps: []resource.TestStep{
    20  			resource.TestStep{
    21  				Config: testAccDockerContainerConfig,
    22  				Check: resource.ComposeTestCheckFunc(
    23  					testAccContainerRunning("docker_container.foo", &c),
    24  				),
    25  			},
    26  		},
    27  	})
    28  }
    29  
    30  func TestAccDockerContainerPath_validation(t *testing.T) {
    31  	cases := []struct {
    32  		Value    string
    33  		ErrCount int
    34  	}{
    35  		{Value: "/var/log", ErrCount: 0},
    36  		{Value: "/tmp", ErrCount: 0},
    37  		{Value: "C:\\Windows\\System32", ErrCount: 0},
    38  		{Value: "C:\\Program Files\\MSBuild", ErrCount: 0},
    39  		{Value: "test", ErrCount: 1},
    40  		{Value: "C:Test", ErrCount: 1},
    41  		{Value: "", ErrCount: 1},
    42  	}
    43  
    44  	for _, tc := range cases {
    45  		_, errors := validateDockerContainerPath(tc.Value, "docker_container")
    46  
    47  		if len(errors) != tc.ErrCount {
    48  			t.Fatalf("Expected the Docker Container Path to trigger a validation error")
    49  		}
    50  	}
    51  }
    52  
    53  func TestAccDockerContainer_volume(t *testing.T) {
    54  	var c dc.Container
    55  
    56  	testCheck := func(*terraform.State) error {
    57  		if len(c.Mounts) != 1 {
    58  			return fmt.Errorf("Incorrect number of mounts: expected 1, got %d", len(c.Mounts))
    59  		}
    60  
    61  		for _, v := range c.Mounts {
    62  			if v.Name != "testAccDockerContainerVolume_volume" {
    63  				continue
    64  			}
    65  
    66  			if v.Destination != "/tmp/volume" {
    67  				return fmt.Errorf("Bad destination on mount: expected /tmp/volume, got %q", v.Destination)
    68  			}
    69  
    70  			if v.Mode != "rw" {
    71  				return fmt.Errorf("Bad mode on mount: expected rw, got %q", v.Mode)
    72  			}
    73  
    74  			return nil
    75  		}
    76  
    77  		return fmt.Errorf("Mount for testAccDockerContainerVolume_volume not found")
    78  	}
    79  
    80  	resource.Test(t, resource.TestCase{
    81  		PreCheck:  func() { testAccPreCheck(t) },
    82  		Providers: testAccProviders,
    83  		Steps: []resource.TestStep{
    84  			resource.TestStep{
    85  				Config: testAccDockerContainerVolumeConfig,
    86  				Check: resource.ComposeTestCheckFunc(
    87  					testAccContainerRunning("docker_container.foo", &c),
    88  					testCheck,
    89  				),
    90  			},
    91  		},
    92  	})
    93  }
    94  
    95  func TestAccDockerContainer_customized(t *testing.T) {
    96  	var c dc.Container
    97  
    98  	testCheck := func(*terraform.State) error {
    99  		if len(c.Config.Entrypoint) < 3 ||
   100  			(c.Config.Entrypoint[0] != "/bin/bash" &&
   101  				c.Config.Entrypoint[1] != "-c" &&
   102  				c.Config.Entrypoint[2] != "ping localhost") {
   103  			return fmt.Errorf("Container wrong entrypoint: %s", c.Config.Entrypoint)
   104  		}
   105  
   106  		if c.Config.User != "root:root" {
   107  			return fmt.Errorf("Container wrong user: %s", c.Config.User)
   108  		}
   109  
   110  		if c.HostConfig.RestartPolicy.Name == "on-failure" {
   111  			if c.HostConfig.RestartPolicy.MaximumRetryCount != 5 {
   112  				return fmt.Errorf("Container has wrong restart policy max retry count: %d", c.HostConfig.RestartPolicy.MaximumRetryCount)
   113  			}
   114  		} else {
   115  			return fmt.Errorf("Container has wrong restart policy: %s", c.HostConfig.RestartPolicy.Name)
   116  		}
   117  
   118  		if c.HostConfig.Memory != (512 * 1024 * 1024) {
   119  			return fmt.Errorf("Container has wrong memory setting: %d", c.HostConfig.Memory)
   120  		}
   121  
   122  		if c.HostConfig.MemorySwap != (2048 * 1024 * 1024) {
   123  			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)
   124  		}
   125  
   126  		if c.HostConfig.CPUShares != 32 {
   127  			return fmt.Errorf("Container has wrong cpu shares setting: %d", c.HostConfig.CPUShares)
   128  		}
   129  
   130  		if len(c.HostConfig.DNS) != 1 {
   131  			return fmt.Errorf("Container does not have the correct number of dns entries: %d", len(c.HostConfig.DNS))
   132  		}
   133  
   134  		if c.HostConfig.DNS[0] != "8.8.8.8" {
   135  			return fmt.Errorf("Container has wrong dns setting: %v", c.HostConfig.DNS[0])
   136  		}
   137  
   138  		if len(c.HostConfig.DNSOptions) != 1 {
   139  			return fmt.Errorf("Container does not have the correct number of dns option entries: %d", len(c.HostConfig.DNS))
   140  		}
   141  
   142  		if c.HostConfig.DNSOptions[0] != "rotate" {
   143  			return fmt.Errorf("Container has wrong dns option setting: %v", c.HostConfig.DNS[0])
   144  		}
   145  
   146  		if len(c.HostConfig.DNSSearch) != 1 {
   147  			return fmt.Errorf("Container does not have the correct number of dns search entries: %d", len(c.HostConfig.DNS))
   148  		}
   149  
   150  		if c.HostConfig.DNSSearch[0] != "example.com" {
   151  			return fmt.Errorf("Container has wrong dns search setting: %v", c.HostConfig.DNS[0])
   152  		}
   153  
   154  		if len(c.HostConfig.CapAdd) != 1 {
   155  			return fmt.Errorf("Container does not have the correct number of Capabilities in ADD: %d", len(c.HostConfig.CapAdd))
   156  		}
   157  
   158  		if c.HostConfig.CapAdd[0] != "ALL" {
   159  			return fmt.Errorf("Container has wrong CapAdd setting: %v", c.HostConfig.CapAdd[0])
   160  		}
   161  
   162  		if len(c.HostConfig.CapDrop) != 1 {
   163  			return fmt.Errorf("Container does not have the correct number of Capabilities in Drop: %d", len(c.HostConfig.CapDrop))
   164  		}
   165  
   166  		if c.HostConfig.CapDrop[0] != "SYS_ADMIN" {
   167  			return fmt.Errorf("Container has wrong CapDrop setting: %v", c.HostConfig.CapDrop[0])
   168  		}
   169  
   170  		if c.HostConfig.CPUShares != 32 {
   171  			return fmt.Errorf("Container has wrong cpu shares setting: %d", c.HostConfig.CPUShares)
   172  		}
   173  
   174  		if c.HostConfig.CPUShares != 32 {
   175  			return fmt.Errorf("Container has wrong cpu shares setting: %d", c.HostConfig.CPUShares)
   176  		}
   177  
   178  		if c.Config.Labels["env"] != "prod" || c.Config.Labels["role"] != "test" {
   179  			return fmt.Errorf("Container does not have the correct labels")
   180  		}
   181  
   182  		if c.HostConfig.LogConfig.Type != "json-file" {
   183  			return fmt.Errorf("Container does not have the correct log config: %s", c.HostConfig.LogConfig.Type)
   184  		}
   185  
   186  		if c.HostConfig.LogConfig.Config["max-size"] != "10m" {
   187  			return fmt.Errorf("Container does not have the correct max-size log option: %v", c.HostConfig.LogConfig.Config["max-size"])
   188  		}
   189  
   190  		if c.HostConfig.LogConfig.Config["max-file"] != "20" {
   191  			return fmt.Errorf("Container does not have the correct max-file log option: %v", c.HostConfig.LogConfig.Config["max-file"])
   192  		}
   193  
   194  		if len(c.HostConfig.ExtraHosts) != 2 {
   195  			return fmt.Errorf("Container does not have correct number of extra host entries, got %d", len(c.HostConfig.ExtraHosts))
   196  		}
   197  
   198  		if c.HostConfig.ExtraHosts[0] != "testhost2:10.0.2.0" {
   199  			return fmt.Errorf("Container has incorrect extra host string: %q", c.HostConfig.ExtraHosts[0])
   200  		}
   201  
   202  		if c.HostConfig.ExtraHosts[1] != "testhost:10.0.1.0" {
   203  			return fmt.Errorf("Container has incorrect extra host string: %q", c.HostConfig.ExtraHosts[1])
   204  		}
   205  
   206  		if _, ok := c.NetworkSettings.Networks["test"]; !ok {
   207  			return fmt.Errorf("Container is not connected to the right user defined network: test")
   208  		}
   209  
   210  		return nil
   211  	}
   212  
   213  	resource.Test(t, resource.TestCase{
   214  		PreCheck:  func() { testAccPreCheck(t) },
   215  		Providers: testAccProviders,
   216  		Steps: []resource.TestStep{
   217  			resource.TestStep{
   218  				Config: testAccDockerContainerCustomizedConfig,
   219  				Check: resource.ComposeTestCheckFunc(
   220  					testAccContainerRunning("docker_container.foo", &c),
   221  					testCheck,
   222  				),
   223  			},
   224  		},
   225  	})
   226  }
   227  
   228  func TestAccDockerContainer_upload(t *testing.T) {
   229  	var c dc.Container
   230  
   231  	testCheck := func(*terraform.State) error {
   232  		client := testAccProvider.Meta().(*dc.Client)
   233  
   234  		buf := new(bytes.Buffer)
   235  		opts := dc.DownloadFromContainerOptions{
   236  			OutputStream: buf,
   237  			Path:         "/terraform/test.txt",
   238  		}
   239  
   240  		if err := client.DownloadFromContainer(c.ID, opts); err != nil {
   241  			return fmt.Errorf("Unable to download a file from container: %s", err)
   242  		}
   243  
   244  		r := bytes.NewReader(buf.Bytes())
   245  		tr := tar.NewReader(r)
   246  
   247  		if _, err := tr.Next(); err != nil {
   248  			return fmt.Errorf("Unable to read content of tar archive: %s", err)
   249  		}
   250  
   251  		fbuf := new(bytes.Buffer)
   252  		fbuf.ReadFrom(tr)
   253  		content := fbuf.String()
   254  
   255  		if content != "foo" {
   256  			return fmt.Errorf("file content is invalid")
   257  		}
   258  
   259  		return nil
   260  	}
   261  
   262  	resource.Test(t, resource.TestCase{
   263  		PreCheck:  func() { testAccPreCheck(t) },
   264  		Providers: testAccProviders,
   265  		Steps: []resource.TestStep{
   266  			resource.TestStep{
   267  				Config: testAccDockerContainerUploadConfig,
   268  				Check: resource.ComposeTestCheckFunc(
   269  					testAccContainerRunning("docker_container.foo", &c),
   270  					testCheck,
   271  				),
   272  			},
   273  		},
   274  	})
   275  }
   276  
   277  func testAccContainerRunning(n string, container *dc.Container) resource.TestCheckFunc {
   278  	return func(s *terraform.State) error {
   279  		rs, ok := s.RootModule().Resources[n]
   280  		if !ok {
   281  			return fmt.Errorf("Not found: %s", n)
   282  		}
   283  
   284  		if rs.Primary.ID == "" {
   285  			return fmt.Errorf("No ID is set")
   286  		}
   287  
   288  		client := testAccProvider.Meta().(*dc.Client)
   289  		containers, err := client.ListContainers(dc.ListContainersOptions{})
   290  		if err != nil {
   291  			return err
   292  		}
   293  
   294  		for _, c := range containers {
   295  			if c.ID == rs.Primary.ID {
   296  				inspected, err := client.InspectContainer(c.ID)
   297  				if err != nil {
   298  					return fmt.Errorf("Container could not be inspected: %s", err)
   299  				}
   300  				*container = *inspected
   301  				return nil
   302  			}
   303  		}
   304  
   305  		return fmt.Errorf("Container not found: %s", rs.Primary.ID)
   306  	}
   307  }
   308  
   309  const testAccDockerContainerConfig = `
   310  resource "docker_image" "foo" {
   311  	name = "nginx:latest"
   312  }
   313  
   314  resource "docker_container" "foo" {
   315  	name = "tf-test"
   316  	image = "${docker_image.foo.latest}"
   317  }
   318  `
   319  
   320  const testAccDockerContainerVolumeConfig = `
   321  resource "docker_image" "foo" {
   322  	name = "nginx:latest"
   323  }
   324  
   325  resource "docker_volume" "foo" {
   326      name = "testAccDockerContainerVolume_volume"
   327  }
   328  
   329  resource "docker_container" "foo" {
   330  	name = "tf-test"
   331  	image = "${docker_image.foo.latest}"
   332  
   333      volumes {
   334          volume_name = "${docker_volume.foo.name}"
   335          container_path = "/tmp/volume"
   336          read_only = false
   337      }
   338  }
   339  `
   340  
   341  const testAccDockerContainerCustomizedConfig = `
   342  resource "docker_image" "foo" {
   343  	name = "nginx:latest"
   344  }
   345  
   346  resource "docker_container" "foo" {
   347  	name = "tf-test"
   348  	image = "${docker_image.foo.latest}"
   349  	entrypoint = ["/bin/bash", "-c", "ping localhost"]
   350  	user = "root:root"
   351  	restart = "on-failure"
   352  	destroy_grace_seconds = 10
   353  	max_retry_count = 5
   354  	memory = 512
   355  	memory_swap = 2048
   356  	cpu_shares = 32
   357  
   358  	capabilities {
   359  		add= ["ALL"]
   360  		drop = ["SYS_ADMIN"]
   361  	}
   362  
   363  	dns = ["8.8.8.8"]
   364  	dns_opts = ["rotate"]
   365  	dns_search = ["example.com"]
   366  	labels {
   367  		env = "prod"
   368  		role = "test"
   369  	}
   370  	log_driver = "json-file"
   371  	log_opts = {
   372  		max-size = "10m"
   373  		max-file = 20
   374  	}
   375  	network_mode = "bridge"
   376  
   377  	networks = ["${docker_network.test_network.name}"]
   378  	network_alias = ["tftest"]
   379  
   380  	host {
   381  		host = "testhost"
   382  		ip = "10.0.1.0"
   383  	}
   384  
   385  	host {
   386  		host = "testhost2"
   387  		ip = "10.0.2.0"
   388  	}
   389  }
   390  
   391  resource "docker_network" "test_network" {
   392    name = "test"
   393  }
   394  `
   395  
   396  const testAccDockerContainerUploadConfig = `
   397  resource "docker_image" "foo" {
   398  	name = "nginx:latest"
   399  }
   400  
   401  resource "docker_container" "foo" {
   402  	name = "tf-test"
   403  	image = "${docker_image.foo.latest}"
   404  
   405  	upload {
   406  		content = "foo"
   407  		file = "/terraform/test.txt"
   408  	}
   409  }
   410  `