github.com/adityamillind98/moby@v23.0.0-rc.4+incompatible/integration-cli/docker_cli_links_test.go (about)

     1  package main
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"regexp"
     7  	"sort"
     8  	"strings"
     9  	"testing"
    10  
    11  	"github.com/docker/docker/runconfig"
    12  	"gotest.tools/v3/assert"
    13  	"gotest.tools/v3/assert/cmp"
    14  )
    15  
    16  type DockerCLILinksSuite struct {
    17  	ds *DockerSuite
    18  }
    19  
    20  func (s *DockerCLILinksSuite) TearDownTest(c *testing.T) {
    21  	s.ds.TearDownTest(c)
    22  }
    23  
    24  func (s *DockerCLILinksSuite) OnTimeout(c *testing.T) {
    25  	s.ds.OnTimeout(c)
    26  }
    27  
    28  func (s *DockerCLILinksSuite) TestLinksPingUnlinkedContainers(c *testing.T) {
    29  	testRequires(c, DaemonIsLinux)
    30  	_, exitCode, err := dockerCmdWithError("run", "--rm", "busybox", "sh", "-c", "ping -c 1 alias1 -W 1 && ping -c 1 alias2 -W 1")
    31  
    32  	// run ping failed with error
    33  	assert.Equal(c, exitCode, 1, fmt.Sprintf("error: %v", err))
    34  }
    35  
    36  // Test for appropriate error when calling --link with an invalid target container
    37  func (s *DockerCLILinksSuite) TestLinksInvalidContainerTarget(c *testing.T) {
    38  	testRequires(c, DaemonIsLinux)
    39  	out, _, err := dockerCmdWithError("run", "--link", "bogus:alias", "busybox", "true")
    40  
    41  	// an invalid container target should produce an error
    42  	assert.Assert(c, err != nil, "out: %s", out)
    43  	// an invalid container target should produce an error
    44  	// note: convert the output to lowercase first as the error string
    45  	// capitalization was changed after API version 1.32
    46  	assert.Assert(c, strings.Contains(strings.ToLower(out), "could not get container"))
    47  }
    48  
    49  func (s *DockerCLILinksSuite) TestLinksPingLinkedContainers(c *testing.T) {
    50  	testRequires(c, DaemonIsLinux)
    51  	// Test with the three different ways of specifying the default network on Linux
    52  	testLinkPingOnNetwork(c, "")
    53  	testLinkPingOnNetwork(c, "default")
    54  	testLinkPingOnNetwork(c, "bridge")
    55  }
    56  
    57  func testLinkPingOnNetwork(c *testing.T, network string) {
    58  	var postArgs []string
    59  	if network != "" {
    60  		postArgs = append(postArgs, []string{"--net", network}...)
    61  	}
    62  	postArgs = append(postArgs, []string{"busybox", "top"}...)
    63  	runArgs1 := append([]string{"run", "-d", "--name", "container1", "--hostname", "fred"}, postArgs...)
    64  	runArgs2 := append([]string{"run", "-d", "--name", "container2", "--hostname", "wilma"}, postArgs...)
    65  
    66  	// Run the two named containers
    67  	dockerCmd(c, runArgs1...)
    68  	dockerCmd(c, runArgs2...)
    69  
    70  	postArgs = []string{}
    71  	if network != "" {
    72  		postArgs = append(postArgs, []string{"--net", network}...)
    73  	}
    74  	postArgs = append(postArgs, []string{"busybox", "sh", "-c"}...)
    75  
    76  	// Format a run for a container which links to the other two
    77  	runArgs := append([]string{"run", "--rm", "--link", "container1:alias1", "--link", "container2:alias2"}, postArgs...)
    78  	pingCmd := "ping -c 1 %s -W 1 && ping -c 1 %s -W 1"
    79  
    80  	// test ping by alias, ping by name, and ping by hostname
    81  	// 1. Ping by alias
    82  	dockerCmd(c, append(runArgs, fmt.Sprintf(pingCmd, "alias1", "alias2"))...)
    83  	// 2. Ping by container name
    84  	dockerCmd(c, append(runArgs, fmt.Sprintf(pingCmd, "container1", "container2"))...)
    85  	// 3. Ping by hostname
    86  	dockerCmd(c, append(runArgs, fmt.Sprintf(pingCmd, "fred", "wilma"))...)
    87  
    88  	// Clean for next round
    89  	dockerCmd(c, "rm", "-f", "container1")
    90  	dockerCmd(c, "rm", "-f", "container2")
    91  }
    92  
    93  func (s *DockerCLILinksSuite) TestLinksPingLinkedContainersAfterRename(c *testing.T) {
    94  	testRequires(c, DaemonIsLinux)
    95  	out, _ := dockerCmd(c, "run", "-d", "--name", "container1", "busybox", "top")
    96  	idA := strings.TrimSpace(out)
    97  	out, _ = dockerCmd(c, "run", "-d", "--name", "container2", "busybox", "top")
    98  	idB := strings.TrimSpace(out)
    99  	dockerCmd(c, "rename", "container1", "container_new")
   100  	dockerCmd(c, "run", "--rm", "--link", "container_new:alias1", "--link", "container2:alias2", "busybox", "sh", "-c", "ping -c 1 alias1 -W 1 && ping -c 1 alias2 -W 1")
   101  	dockerCmd(c, "kill", idA)
   102  	dockerCmd(c, "kill", idB)
   103  }
   104  
   105  func (s *DockerCLILinksSuite) TestLinksInspectLinksStarted(c *testing.T) {
   106  	testRequires(c, DaemonIsLinux)
   107  	dockerCmd(c, "run", "-d", "--name", "container1", "busybox", "top")
   108  	dockerCmd(c, "run", "-d", "--name", "container2", "busybox", "top")
   109  	dockerCmd(c, "run", "-d", "--name", "testinspectlink", "--link", "container1:alias1", "--link", "container2:alias2", "busybox", "top")
   110  	links := inspectFieldJSON(c, "testinspectlink", "HostConfig.Links")
   111  
   112  	var result []string
   113  	err := json.Unmarshal([]byte(links), &result)
   114  	assert.NilError(c, err)
   115  
   116  	var expected = []string{
   117  		"/container1:/testinspectlink/alias1",
   118  		"/container2:/testinspectlink/alias2",
   119  	}
   120  	sort.Strings(result)
   121  	assert.DeepEqual(c, result, expected)
   122  }
   123  
   124  func (s *DockerCLILinksSuite) TestLinksInspectLinksStopped(c *testing.T) {
   125  	testRequires(c, DaemonIsLinux)
   126  
   127  	dockerCmd(c, "run", "-d", "--name", "container1", "busybox", "top")
   128  	dockerCmd(c, "run", "-d", "--name", "container2", "busybox", "top")
   129  	dockerCmd(c, "run", "-d", "--name", "testinspectlink", "--link", "container1:alias1", "--link", "container2:alias2", "busybox", "true")
   130  	links := inspectFieldJSON(c, "testinspectlink", "HostConfig.Links")
   131  
   132  	var result []string
   133  	err := json.Unmarshal([]byte(links), &result)
   134  	assert.NilError(c, err)
   135  
   136  	var expected = []string{
   137  		"/container1:/testinspectlink/alias1",
   138  		"/container2:/testinspectlink/alias2",
   139  	}
   140  	sort.Strings(result)
   141  	assert.DeepEqual(c, result, expected)
   142  }
   143  
   144  func (s *DockerCLILinksSuite) TestLinksNotStartedParentNotFail(c *testing.T) {
   145  	testRequires(c, DaemonIsLinux)
   146  	dockerCmd(c, "create", "--name=first", "busybox", "top")
   147  	dockerCmd(c, "create", "--name=second", "--link=first:first", "busybox", "top")
   148  	dockerCmd(c, "start", "first")
   149  }
   150  
   151  func (s *DockerCLILinksSuite) TestLinksHostsFilesInject(c *testing.T) {
   152  	testRequires(c, DaemonIsLinux)
   153  	testRequires(c, testEnv.IsLocalDaemon)
   154  
   155  	out, _ := dockerCmd(c, "run", "-itd", "--name", "one", "busybox", "top")
   156  	idOne := strings.TrimSpace(out)
   157  
   158  	out, _ = dockerCmd(c, "run", "-itd", "--name", "two", "--link", "one:onetwo", "busybox", "top")
   159  	idTwo := strings.TrimSpace(out)
   160  
   161  	assert.Assert(c, waitRun(idTwo) == nil)
   162  
   163  	readContainerFileWithExec(c, idOne, "/etc/hosts")
   164  	contentTwo := readContainerFileWithExec(c, idTwo, "/etc/hosts")
   165  	// Host is not present in updated hosts file
   166  	assert.Assert(c, strings.Contains(string(contentTwo), "onetwo"))
   167  }
   168  
   169  func (s *DockerCLILinksSuite) TestLinksUpdateOnRestart(c *testing.T) {
   170  	testRequires(c, DaemonIsLinux)
   171  	testRequires(c, testEnv.IsLocalDaemon)
   172  	dockerCmd(c, "run", "-d", "--name", "one", "busybox", "top")
   173  	out, _ := dockerCmd(c, "run", "-d", "--name", "two", "--link", "one:onetwo", "--link", "one:one", "busybox", "top")
   174  	id := strings.TrimSpace(out)
   175  
   176  	realIP := inspectField(c, "one", "NetworkSettings.Networks.bridge.IPAddress")
   177  	content := readContainerFileWithExec(c, id, "/etc/hosts")
   178  
   179  	getIP := func(hosts []byte, hostname string) string {
   180  		re := regexp.MustCompile(fmt.Sprintf(`(\S*)\t%s`, regexp.QuoteMeta(hostname)))
   181  		matches := re.FindSubmatch(hosts)
   182  		assert.Assert(c, matches != nil, "Hostname %s have no matches in hosts", hostname)
   183  		return string(matches[1])
   184  	}
   185  	ip := getIP(content, "one")
   186  	assert.Equal(c, ip, realIP)
   187  
   188  	ip = getIP(content, "onetwo")
   189  	assert.Equal(c, ip, realIP)
   190  
   191  	dockerCmd(c, "restart", "one")
   192  	realIP = inspectField(c, "one", "NetworkSettings.Networks.bridge.IPAddress")
   193  
   194  	content = readContainerFileWithExec(c, id, "/etc/hosts")
   195  	ip = getIP(content, "one")
   196  	assert.Equal(c, ip, realIP)
   197  
   198  	ip = getIP(content, "onetwo")
   199  	assert.Equal(c, ip, realIP)
   200  }
   201  
   202  func (s *DockerCLILinksSuite) TestLinksEnvs(c *testing.T) {
   203  	testRequires(c, DaemonIsLinux)
   204  	dockerCmd(c, "run", "-d", "-e", "e1=", "-e", "e2=v2", "-e", "e3=v3=v3", "--name=first", "busybox", "top")
   205  	out, _ := dockerCmd(c, "run", "--name=second", "--link=first:first", "busybox", "env")
   206  	assert.Assert(c, strings.Contains(out, "FIRST_ENV_e1=\n"))
   207  	assert.Assert(c, strings.Contains(out, "FIRST_ENV_e2=v2"))
   208  	assert.Assert(c, strings.Contains(out, "FIRST_ENV_e3=v3=v3"))
   209  }
   210  
   211  func (s *DockerCLILinksSuite) TestLinkShortDefinition(c *testing.T) {
   212  	testRequires(c, DaemonIsLinux)
   213  	out, _ := dockerCmd(c, "run", "-d", "--name", "shortlinkdef", "busybox", "top")
   214  
   215  	cid := strings.TrimSpace(out)
   216  	assert.Assert(c, waitRun(cid) == nil)
   217  
   218  	out, _ = dockerCmd(c, "run", "-d", "--name", "link2", "--link", "shortlinkdef", "busybox", "top")
   219  
   220  	cid2 := strings.TrimSpace(out)
   221  	assert.Assert(c, waitRun(cid2) == nil)
   222  
   223  	links := inspectFieldJSON(c, cid2, "HostConfig.Links")
   224  	assert.Equal(c, links, "[\"/shortlinkdef:/link2/shortlinkdef\"]")
   225  }
   226  
   227  func (s *DockerCLILinksSuite) TestLinksNetworkHostContainer(c *testing.T) {
   228  	testRequires(c, DaemonIsLinux, NotUserNamespace)
   229  	dockerCmd(c, "run", "-d", "--net", "host", "--name", "host_container", "busybox", "top")
   230  	out, _, err := dockerCmdWithError("run", "--name", "should_fail", "--link", "host_container:tester", "busybox", "true")
   231  
   232  	// Running container linking to a container with --net host should have failed
   233  	assert.Assert(c, err != nil, "out: %s", out)
   234  	// Running container linking to a container with --net host should have failed
   235  	assert.Assert(c, strings.Contains(out, runconfig.ErrConflictHostNetworkAndLinks.Error()))
   236  }
   237  
   238  func (s *DockerCLILinksSuite) TestLinksEtcHostsRegularFile(c *testing.T) {
   239  	testRequires(c, DaemonIsLinux, NotUserNamespace)
   240  	out, _ := dockerCmd(c, "run", "--net=host", "busybox", "ls", "-la", "/etc/hosts")
   241  	// /etc/hosts should be a regular file
   242  	assert.Assert(c, cmp.Regexp("^-.+\n$", out))
   243  }
   244  
   245  func (s *DockerCLILinksSuite) TestLinksMultipleWithSameName(c *testing.T) {
   246  	testRequires(c, DaemonIsLinux)
   247  	dockerCmd(c, "run", "-d", "--name=upstream-a", "busybox", "top")
   248  	dockerCmd(c, "run", "-d", "--name=upstream-b", "busybox", "top")
   249  	dockerCmd(c, "run", "--link", "upstream-a:upstream", "--link", "upstream-b:upstream", "busybox", "sh", "-c", "ping -c 1 upstream")
   250  }