diff --git a/gns3server/compute/docker/docker_vm.py b/gns3server/compute/docker/docker_vm.py index ed5e0009..e59321b0 100644 --- a/gns3server/compute/docker/docker_vm.py +++ b/gns3server/compute/docker/docker_vm.py @@ -319,7 +319,7 @@ class DockerVM(BaseNode): "Volumes": {}, "Env": ["container=docker"], # Systemd compliant: https://github.com/GNS3/gns3-server/issues/573 "Cmd": [], - "Entrypoint": image_infos.get("Config", {"Entrypoint": []})["Entrypoint"] + "Entrypoint": image_infos.get("Config", {"Entrypoint": []}).get("Entrypoint") } if params["Entrypoint"] is None: @@ -330,7 +330,7 @@ class DockerVM(BaseNode): except ValueError as e: raise DockerError("Invalid start command '{}': {}".format(self._start_command, e)) if len(params["Cmd"]) == 0: - params["Cmd"] = image_infos.get("Config", {"Cmd": []})["Cmd"] + params["Cmd"] = image_infos.get("Config", {"Cmd": []}).get("Cmd") if params["Cmd"] is None: params["Cmd"] = [] if len(params["Cmd"]) == 0 and len(params["Entrypoint"]) == 0: @@ -342,6 +342,11 @@ class DockerVM(BaseNode): # Give the information to the container the list of volume path mounted params["Env"].append("GNS3_VOLUMES={}".format(":".join(self._volumes))) + # Pass user configured for image to init script + if image_infos.get("Config", {"User": ""}).get("User"): + params["User"] = "root" + params["Env"].append("GNS3_USER={}".format(image_infos.get("Config", {"User": ""})["User"])) + variables = self.project.variables if not variables: variables = [] diff --git a/gns3server/compute/docker/resources/init.sh b/gns3server/compute/docker/resources/init.sh index 54bbeefc..bc33ea1c 100755 --- a/gns3server/compute/docker/resources/init.sh +++ b/gns3server/compute/docker/resources/init.sh @@ -87,6 +87,9 @@ done ifup -a -f # continue normal docker startup -PATH="$OLD_PATH" -exec "$@" - +GNS3_CMD="PATH=$OLD_PATH exec" +while test "$#" -gt 0 ; do + GNS3_CMD="${GNS3_CMD} \"${1//\"/\\\"}\"" + shift +done +exec su ${GNS3_USER-root} -p -c "$GNS3_CMD" diff --git a/tests/compute/docker/test_docker_vm.py b/tests/compute/docker/test_docker_vm.py index 44e02577..63dcb537 100644 --- a/tests/compute/docker/test_docker_vm.py +++ b/tests/compute/docker/test_docker_vm.py @@ -415,6 +415,48 @@ def test_create_image_not_available(loop, project, manager): assert vm._cid == "e90e34656806" mock_pull.assert_called_with("ubuntu:latest") +def test_create_with_user(loop, project, manager): + + response = { + "Id": "e90e34656806", + "Warnings": [], + "Config" : { + "User" : "test", + }, + } + with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "ubuntu"}]) as mock_list_images: + with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock: + vm = DockerVM("test", str(uuid.uuid4()), project, manager, "ubuntu:latest") + loop.run_until_complete(asyncio.ensure_future(vm.create())) + mock.assert_called_with("POST", "containers/create", data={ + "Tty": True, + "OpenStdin": True, + "StdinOnce": False, + "User": "root", + "HostConfig": + { + "CapAdd": ["ALL"], + "Binds": [ + "{}:/gns3:ro".format(get_resource("compute/docker/resources")), + "{}:/gns3volumes/etc/network:rw".format(os.path.join(vm.working_dir, "etc", "network")) + ], + "Privileged": True + }, + "Volumes": {}, + "NetworkDisabled": True, + "Name": "test", + "Hostname": "test", + "Image": "ubuntu:latest", + "Env": [ + "container=docker", + "GNS3_MAX_ETHERNET=eth0", + "GNS3_VOLUMES=/etc/network", + "GNS3_USER=test" + ], + "Entrypoint": ["/gns3/init.sh"], + "Cmd": ["/bin/sh"] + }) + assert vm._cid == "e90e34656806" def test_get_container_state(loop, vm): response = {