diff --git a/gns3server/compute/docker/docker_vm.py b/gns3server/compute/docker/docker_vm.py index 4ba038b3..6b7c3c7f 100644 --- a/gns3server/compute/docker/docker_vm.py +++ b/gns3server/compute/docker/docker_vm.py @@ -337,11 +337,10 @@ class DockerVM(BaseNode): params["Env"].append("DISPLAY=:{}".format(self._display)) params["HostConfig"]["Binds"].append("/tmp/.X11-unix/:/tmp/.X11-unix/") - if self._extra_hosts is not None and self._extra_hosts.strip() != "": - params["HostConfig"]["ExtraHosts"] = [h.strip() - for h in self._extra_hosts.split("\n") - if h.strip() != "" ] - + if self._extra_hosts: + extra_hosts = self._format_extra_hosts(self._extra_hosts) + if extra_hosts: + params["Env"].append("GNS3_EXTRA_HOSTS={}".format(extra_hosts)) result = yield from self.manager.query("POST", "containers/create", data=params) self._cid = result['Id'] @@ -349,6 +348,20 @@ class DockerVM(BaseNode): name=self._name, id=self._id)) return True + def _format_extra_hosts(self, extra_hosts): + lines = [h.strip() for h in self._extra_hosts.split("\n") if h.strip() != ""] + hosts = [] + try: + for host in lines: + hostname, ip = host.split(":") + hostname = hostname.strip() + ip = ip.strip() + if hostname and ip: + hosts.append((hostname, ip)) + except ValueError: + raise DockerError("Can't apply `ExtraHosts`, wrong format: {}".format(extra_hosts)) + return "\n".join(["{}\t{}".format(h[1], h[0]) for h in hosts]) + @asyncio.coroutine def update(self): """ diff --git a/gns3server/compute/docker/resources/init.sh b/gns3server/compute/docker/resources/init.sh index ee98bebd..9c317559 100755 --- a/gns3server/compute/docker/resources/init.sh +++ b/gns3server/compute/docker/resources/init.sh @@ -60,6 +60,14 @@ ff02::1 ip6-allnodes ff02::2 ip6-allrouters __EOF__ +# imitate docker's `ExtraHosts` behaviour +sed -i '/GNS3_EXTRA_HOSTS_START/,/GNS3_EXTRA_HOSTS_END/d' /etc/hosts +[ -n "$GNS3_EXTRA_HOSTS" ] && cat >> /etc/hosts << __EOF__ +# GNS3_EXTRA_HOSTS_START +$GNS3_EXTRA_HOSTS +# GNS3_EXTRA_HOSTS_END +__EOF__ + # configure loopback interface ip link set dev lo up diff --git a/tests/compute/docker/test_docker_vm.py b/tests/compute/docker/test_docker_vm.py index 60487ff6..8360b2ff 100644 --- a/tests/compute/docker/test_docker_vm.py +++ b/tests/compute/docker/test_docker_vm.py @@ -61,6 +61,7 @@ def test_json(vm, project): 'console_resolution': '1024x768', 'console_http_port': 80, 'console_http_path': '/', + 'extra_hosts': None, 'aux': vm.aux, 'start_command': vm.start_command, 'environment': vm.environment, @@ -210,20 +211,46 @@ def test_create_with_extra_hosts(loop, project, manager): "Warnings": [] } - with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "ubuntu"}]) as mock_list_images: + with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "ubuntu"}]): with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock: vm = DockerVM("test", str(uuid.uuid4()), project, manager, "ubuntu", extra_hosts=extra_hosts) - vm._start_vnc = MagicMock() - vm._display = 42 loop.run_until_complete(asyncio.async(vm.create())) called_kwargs = mock.call_args[1] - assert called_kwargs["data"]["HostConfig"]["ExtraHosts"] == [ - "test:199.199.199.1", - "test2:199.199.199.1" - ] + assert "GNS3_EXTRA_HOSTS=199.199.199.1\ttest\n199.199.199.1\ttest2" in called_kwargs["data"]["Env"] assert vm._extra_hosts == extra_hosts +def test_create_with_extra_hosts_wrong_format(loop, project, manager): + extra_hosts = "test" + + response = { + "Id": "e90e34656806", + "Warnings": [] + } + + with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "ubuntu"}]): + with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response): + vm = DockerVM("test", str(uuid.uuid4()), project, manager, "ubuntu", extra_hosts=extra_hosts) + with pytest.raises(DockerError): + loop.run_until_complete(asyncio.async(vm.create())) + + +def test_create_with_empty_extra_hosts(loop, project, manager): + extra_hosts = "test:\n" + + response = { + "Id": "e90e34656806", + "Warnings": [] + } + + with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "ubuntu"}]): + with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock: + vm = DockerVM("test", str(uuid.uuid4()), project, manager, "ubuntu", extra_hosts=extra_hosts) + loop.run_until_complete(asyncio.async(vm.create())) + called_kwargs = mock.call_args[1] + assert len([ e for e in called_kwargs["data"]["Env"] if "GNS3_EXTRA_HOSTS" in e]) == 0 + + def test_create_start_cmd(loop, project, manager): response = {