Skip to content

Commit

Permalink
Support network scoped service aliases
Browse files Browse the repository at this point in the history
Signed-off-by: Songmin Li <[email protected]>
  • Loading branch information
lisongmin committed Dec 19, 2024
1 parent 4a232f5 commit b74007d
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 157 deletions.
1 change: 1 addition & 0 deletions newsfragments/network-scoped-aliases.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Support network scoped service aliases.
77 changes: 28 additions & 49 deletions podman_compose.py
Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,7 @@ async def assert_cnt_nets(compose, cnt):
net = cnt.get("network_mode")
if net and not net.startswith("bridge"):
return

cnt_nets = cnt.get("networks")
if cnt_nets and isinstance(cnt_nets, dict):
cnt_nets = list(cnt_nets.keys())
Expand Down Expand Up @@ -910,12 +911,9 @@ def get_net_args_from_network_mode(compose, cnt):
aliases_on_container = [service_name]
if cnt.get("_aliases"):
aliases_on_container.extend(cnt.get("_aliases"))
net_args.append("--network=bridge")
mac_address = cnt.get("mac_address")
if mac_address:
net_args.append(f"--mac-address={mac_address}")
for alias in aliases_on_container:
net_args.extend([f"--network-alias={alias}"])
net_options = [f"alias={alias}" for alias in aliases_on_container]
net = f"{net}," if ":" in net else f"{net}:"
net_args.append(f"--network={net}{'.'.join(net_options)}")
else:
log.fatal("unknown network_mode [%s]", net)
sys.exit(1)
Expand All @@ -937,29 +935,16 @@ def get_net_args_from_networks(compose, cnt):
service_name = cnt["service_name"]

aliases_on_container = [service_name]
# NOTE: from podman manpage:
# NOTE: A container will only have access to aliases on the first network
# that it joins. This is a limitation that will be removed in a later
# release.
aliases_on_container.extend(cnt.get("_aliases", []))
aliases_on_net = []

# TODO: add support for per-interface aliases
# See https://docs.docker.com/compose/compose-file/compose-file-v3/#aliases
# Even though podman accepts network-specific aliases (e.g., --network=bridge:alias=foo,
# podman currently ignores this if a per-container network-alias is set; as pdoman-compose
# always sets a network-alias to the container name, is currently doesn't make sense to
# implement this.

multiple_nets = cnt.get("networks", {})
if not multiple_nets:
if not compose.default_net:
# The bridge mode in podman is using the `podman` network.
# It seems weird, but we should keep this behavior to avoid
# breaking changes.
net_args.append("--network=bridge")
if mac_address:
net_args.append(f"--mac-address={mac_address}")
net_args.extend([f"--network-alias={alias}" for alias in aliases_on_container])
net_options = [f"alias={alias}" for alias in aliases_on_container]
net_args.append(f"--network=bridge:{'.'.join(net_options)}")
return net_args

multiple_nets = {compose.default_net: {}}
Expand All @@ -984,17 +969,17 @@ def get_net_args_from_networks(compose, cnt):
)

for net_, net_config_ in multiple_nets.items():
net_desc = compose.networks[net_] or {}
net_desc = compose.networks.get(net_) or {}
is_ext = net_desc.get("external")
ext_desc = is_ext if isinstance(is_ext, str) else {}
default_net_name = default_network_name_for_project(compose, net_, is_ext)
net_name = ext_desc.get("name") or net_desc.get("name") or default_net_name

ipv4 = net_config_.get("ipv4_address")
ipv6 = net_config_.get("ipv6_address")
# custom extension; not supported by docker-compose v3

mac = net_config_.get("x-podman.mac_address")
aliases_on_net = norm_as_list(net_config_.get("aliases", []))
aliases_on_net = net_config_.get("aliases")

# if a mac_address was specified on the container level, apply it to the first network
# This works for Python > 3.6, because dict insert ordering is preserved, so we are
Expand All @@ -1004,30 +989,24 @@ def get_net_args_from_networks(compose, cnt):
mac = mac_address
mac_address = None

if len(multiple_nets) == 1:
net_args.append(f"--network={net_name}")
if ipv4:
net_args.append(f"--ip={ipv4}")
if ipv6:
net_args.append(f"--ip6={ipv6}")
if mac:
net_args.append(f"--mac-address={mac}")
net_options = []
if ipv4:
net_options.append(f"ip={ipv4}")
if ipv6:
net_options.append(f"ip6={ipv6}")
if mac:
net_options.append(f"mac={mac}")

# Container level service aliases
net_options.extend([f"alias={alias}" for alias in aliases_on_container])
# network level service aliases
if aliases_on_net:
net_options.extend([f"alias={alias}" for alias in aliases_on_net])

if net_options:
net_args.append(f"--network={net_name}:" + ",".join(net_options))
else:
net_options = []
if ipv4:
net_options.append(f"ip={ipv4}")
if ipv6:
net_options.append(f"ip={ipv6}")
if mac:
net_options.append(f"mac={mac}")

if net_options:
net_args.append(f"--network={net_name}:" + ",".join(net_options))
else:
net_args.append(f"--network={net_name}")

net_args.extend([f"--network-alias={alias}" for alias in aliases_on_container])
net_args.extend([f"--network-alias={alias}" for alias in aliases_on_net])
net_args.append(f"--network={net_name}")

return net_args

Expand Down Expand Up @@ -3487,7 +3466,7 @@ def compose_logs_parse(parser):
parser.add_argument("-t", "--timestamps", action="store_true", help="Show timestamps.")
parser.add_argument(
"--tail",
help="Number of lines to show from the end of the logs for each " "container.",
help="Number of lines to show from the end of the logs for each container.",
type=str,
default="all",
)
Expand Down
66 changes: 22 additions & 44 deletions tests/unit/test_container_to_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@ async def test_minimal(self):
[
"--name=project_name_service_name1",
"-d",
"--network=bridge",
"--network-alias=service_name",
"--network=bridge:alias=service_name",
"busybox",
],
)
Expand All @@ -69,8 +68,7 @@ async def test_runtime(self):
[
"--name=project_name_service_name1",
"-d",
"--network=bridge",
"--network-alias=service_name",
"--network=bridge:alias=service_name",
"--runtime",
"runsc",
"busybox",
Expand All @@ -92,8 +90,7 @@ async def test_sysctl_list(self):
[
"--name=project_name_service_name1",
"-d",
"--network=bridge",
"--network-alias=service_name",
"--network=bridge:alias=service_name",
"--sysctl",
"net.core.somaxconn=1024",
"--sysctl",
Expand All @@ -117,8 +114,7 @@ async def test_sysctl_map(self):
[
"--name=project_name_service_name1",
"-d",
"--network=bridge",
"--network-alias=service_name",
"--network=bridge:alias=service_name",
"--sysctl",
"net.core.somaxconn=1024",
"--sysctl",
Expand Down Expand Up @@ -149,8 +145,7 @@ async def test_pid(self):
[
"--name=project_name_service_name1",
"-d",
"--network=bridge",
"--network-alias=service_name",
"--network=bridge:alias=service_name",
"--pid",
"host",
"busybox",
Expand All @@ -170,8 +165,7 @@ async def test_http_proxy(self):
"--name=project_name_service_name1",
"-d",
"--http-proxy=false",
"--network=bridge",
"--network-alias=service_name",
"--network=bridge:alias=service_name",
"busybox",
],
)
Expand All @@ -197,8 +191,7 @@ async def test_uidmaps_extension(self):
[
"--name=project_name_service_name1",
"-d",
"--network=bridge",
"--network-alias=service_name",
"--network=bridge:alias=service_name",
'--uidmap',
'1000:1000:1',
'--uidmap',
Expand All @@ -219,8 +212,7 @@ async def test_gidmaps_extension(self):
[
"--name=project_name_service_name1",
"-d",
"--network=bridge",
"--network-alias=service_name",
"--network=bridge:alias=service_name",
'--gidmap',
'1000:1000:1',
'--gidmap',
Expand All @@ -242,8 +234,7 @@ async def test_rootfs_extension(self):
[
"--name=project_name_service_name1",
"-d",
"--network=bridge",
"--network-alias=service_name",
"--network=bridge:alias=service_name",
"--rootfs",
"/path/to/rootfs",
],
Expand All @@ -261,8 +252,7 @@ async def test_no_hosts_extension(self):
[
"--name=project_name_service_name1",
"-d",
"--network=bridge",
"--network-alias=service_name",
"--network=bridge:alias=service_name",
"--no-hosts",
"busybox",
],
Expand All @@ -287,8 +277,7 @@ async def test_env_file_str(self):
"ZZVAR2=podman-rocks-124",
"-e",
"ZZVAR3=podman-rocks-125",
"--network=bridge",
"--network-alias=service_name",
"--network=bridge:alias=service_name",
"busybox",
],
)
Expand Down Expand Up @@ -321,8 +310,7 @@ async def test_env_file_str_array_one_path(self):
"ZZVAR2=podman-rocks-124",
"-e",
"ZZVAR3=podman-rocks-125",
"--network=bridge",
"--network-alias=service_name",
"--network=bridge:alias=service_name",
"busybox",
],
)
Expand Down Expand Up @@ -351,8 +339,7 @@ async def test_env_file_str_array_two_paths(self):
"ZZVAR1=podman-rocks-223",
"-e",
"ZZVAR2=podman-rocks-224",
"--network=bridge",
"--network-alias=service_name",
"--network=bridge:alias=service_name",
"busybox",
],
)
Expand All @@ -376,8 +363,7 @@ async def test_env_file_obj_required(self):
"ZZVAR2=podman-rocks-124",
"-e",
"ZZVAR3=podman-rocks-125",
"--network=bridge",
"--network-alias=service_name",
"--network=bridge:alias=service_name",
"busybox",
],
)
Expand All @@ -403,8 +389,7 @@ async def test_env_file_obj_optional(self):
[
"--name=project_name_service_name1",
"-d",
"--network=bridge",
"--network-alias=service_name",
"--network=bridge:alias=service_name",
"busybox",
],
)
Expand All @@ -428,8 +413,7 @@ async def test_gpu_count_all(self):
[
"--name=project_name_service_name1",
"-d",
"--network=bridge",
"--network-alias=service_name",
"--network=bridge:alias=service_name",
"--device",
"nvidia.com/gpu=all",
"--security-opt=label=disable",
Expand Down Expand Up @@ -463,8 +447,7 @@ async def test_gpu_count_specific(self):
[
"--name=project_name_service_name1",
"-d",
"--network=bridge",
"--network-alias=service_name",
"--network=bridge:alias=service_name",
"--device",
"nvidia.com/gpu=0",
"--device",
Expand Down Expand Up @@ -500,8 +483,7 @@ async def test_gpu_device_ids_all(self):
[
"--name=project_name_service_name1",
"-d",
"--network=bridge",
"--network-alias=service_name",
"--network=bridge:alias=service_name",
"--device",
"nvidia.com/gpu=all",
"--security-opt=label=disable",
Expand Down Expand Up @@ -535,8 +517,7 @@ async def test_gpu_device_ids_specific(self):
[
"--name=project_name_service_name1",
"-d",
"--network=bridge",
"--network-alias=service_name",
"--network=bridge:alias=service_name",
"--device",
"nvidia.com/gpu=1",
"--device",
Expand Down Expand Up @@ -581,8 +562,7 @@ async def test_selinux_volume(self, prefer_volume, selinux_type, expected_additi
"--name=project_name_service_name1",
"-d",
*expected_additional_args,
"--network=bridge",
"--network-alias=service_name",
"--network=bridge:alias=service_name",
"busybox",
],
)
Expand All @@ -606,8 +586,7 @@ async def test_network_default_name(self, name, is_compat, project_name, expecte
[
"--name=project_name_service_name1",
"-d",
f"--network={expected_network_name}",
"--network-alias=service_name",
f"--network={expected_network_name}:alias=service_name",
"busybox",
],
)
Expand All @@ -629,8 +608,7 @@ async def test_device(self):
"/dev/ttyS0",
"--device-cgroup-rule",
"c 100:200 rwm",
"--network=bridge",
"--network-alias=service_name",
"--network=bridge:alias=service_name",
"busybox",
],
)
Loading

0 comments on commit b74007d

Please sign in to comment.