mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-11-03 22:11:14 +02:00
docker: inject config files into containers via extra_configs
Add an `extra_configs` field (list of {target, content}) to the docker
node/template/appliance schemas. For each entry GNS3 writes `content` to a
file in the node working directory and bind-mounts it read-only at `target`
inside the container.
This lets a NOS appliance seed its startup config without rebuilding the
image: XRd points XR_FIRST_BOOT_CONFIG at an injected /firstboot.cfg, FRR at
/etc/frr/frr.conf, etc. The bind is a single-file mount applied at create
time, so it works for both the generic init.sh path and vendor nodes that
skip init.sh (console_type=docker_exec). Entries are only injected when
present, so ordinary nodes are unaffected.
The content can't go through `environment` (it is line-delimited, one var per
line), hence a dedicated field -- the same plumbing shape as extra_volumes.
This commit is contained in:
7 files changed
+98
-3
No files matched your search
@@ -69,6 +69,7 @@ def test_json(vm, compute_project):
|
||||
'console_http_path': '/',
|
||||
'extra_hosts': None,
|
||||
'extra_volumes': [],
|
||||
'extra_configs': [],
|
||||
'memory': 0,
|
||||
'cpus': 0,
|
||||
'aux': vm.aux,
|
||||
@@ -307,6 +308,44 @@ async def test_create_applies_env_host_config(compute_project, manager):
|
||||
), "GNS3_ user vars must not leak into the container environment"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_with_extra_configs(compute_project, manager):
|
||||
"""
|
||||
extra_configs entries are written to the node working directory and
|
||||
bind-mounted read-only at their target path inside the container.
|
||||
"""
|
||||
|
||||
extra_configs = [{"target": "/firstboot.cfg", "content": "username clab\n!\nend"}]
|
||||
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()), compute_project, manager, "ubuntu", extra_configs=extra_configs)
|
||||
await vm.create()
|
||||
mounts = mock.call_args[1]["data"]["HostConfig"]["Mounts"]
|
||||
injected = [m for m in mounts if m.get("Target") == "/firstboot.cfg"]
|
||||
assert len(injected) == 1
|
||||
assert injected[0]["ReadOnly"] is True
|
||||
with open(injected[0]["Source"]) as f:
|
||||
assert f.read() == "username clab\n!\nend"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_with_extra_configs_invalid_target(compute_project, manager):
|
||||
"""
|
||||
An extra_configs target that is not absolute (or contains '..') is rejected.
|
||||
"""
|
||||
|
||||
extra_configs = [{"target": "relative/path", "content": "x"}]
|
||||
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()), compute_project, manager, "ubuntu", extra_configs=extra_configs)
|
||||
with pytest.raises(DockerError):
|
||||
await vm.create()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_with_colon_in_project_name(compute_project, manager):
|
||||
|
||||
|
||||
Reference in new issue
Block a user