Skip to content

Commit

Permalink
Ad a way to remove dashes in default network names
Browse files Browse the repository at this point in the history
This is the behavior exhibited by docker compose. The network names are
user-visible through external networks, so previously anyone who
migrated from docker-compose needed to change their configuration. Now
it is possible to select compatibility via a flag in x-podman global
dictionary.

Signed-off-by: Povilas Kanapickas <[email protected]>
  • Loading branch information
p12tic committed Jul 6, 2024
1 parent 67c5352 commit 2d2097c
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 14 deletions.
17 changes: 17 additions & 0 deletions docs/Extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,23 @@ The options to the network modes are passed to the `--network` option of the `po
as-is.


## Compatibility of default network names between docker-compose and podman-compose

Current versions of podman-compose may produce different default external network names than
docker-compose under certain conditions. Specifically, docker-compose removes dashes (`-` character)
from project name.

To enable compatibility between docker-compose and podman-compose, specify
`default_net_name_compat: true` under global `x-podman` key:

```
x-podman:
default_net_name_compat: true
```

By default `default_net_name_compat` is `false`. This will change to `true` at some point and the
setting will be removed.

## Custom pods management

Podman-compose can have containers in pods. This can be controlled by extension key x-podman in_pod.
Expand Down
1 change: 1 addition & 0 deletions newsfragments/default_net_name_compat.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added a way to get compatibility of default network names with docker compose. This is selected by setting `default_net_name_compat: true` on `x-podman` global dictionary.
32 changes: 19 additions & 13 deletions podman_compose.py
Original file line number Diff line number Diff line change
Expand Up @@ -336,9 +336,21 @@ def norm_ulimit(inner_value):
return inner_value


def default_network_name_for_project(proj_name, net, is_ext):
# docker-compose removes dashes from project name when building network name
return net if is_ext else f"{proj_name}_{net}"
def get_global_x_podman_value(compose, key, default_value=None):
extension_dict = compose.get("x-podman", None)
if extension_dict is None:
return default_value
return extension_dict.get("default_net_name_compat", default_value)


def default_network_name_for_project(compose, proj_name, net, is_ext):
if is_ext:
return net

default_net_name_compat = get_global_x_podman_value(compose, "default_net_name_compat", False)
if default_net_name_compat is True:
return f"{proj_name.replace('-', '')}_{net}"
return f"{proj_name}_{net}"


# def tr_identity(project_name, given_containers):
Expand Down Expand Up @@ -850,7 +862,7 @@ async def assert_cnt_nets(compose, cnt):
net_desc = nets[net] or {}
is_ext = net_desc.get("external", None)
ext_desc = is_ext if is_dict(is_ext) else {}
default_net_name = default_network_name_for_project(proj_name, net, is_ext)
default_net_name = default_network_name_for_project(compose, proj_name, net, is_ext)
net_name = ext_desc.get("name", None) or net_desc.get("name", None) or default_net_name
try:
await compose.podman.output([], "network", ["exists", net_name])
Expand Down Expand Up @@ -939,7 +951,7 @@ def get_net_args(compose, cnt):
net_desc = nets[net] or {}
is_ext = net_desc.get("external", None)
ext_desc = is_ext if is_dict(is_ext) else {}
default_net_name = default_network_name_for_project(proj_name, net, is_ext)
default_net_name = default_network_name_for_project(compose, proj_name, net, is_ext)
net_name = ext_desc.get("name", None) or net_desc.get("name", None) or default_net_name
net_names.append(net_name)
net_names_str = ",".join(net_names)
Expand Down Expand Up @@ -975,7 +987,7 @@ def get_net_args(compose, cnt):
net_desc = nets[net_] or {}
is_ext = net_desc.get("external", None)
ext_desc = is_ext if is_dict(is_ext) else {}
default_net_name = default_network_name_for_project(proj_name, net_, is_ext)
default_net_name = default_network_name_for_project(compose, proj_name, net_, is_ext)
net_name = ext_desc.get("name", None) or net_desc.get("name", None) or default_net_name

ipv4 = net_config_.get("ipv4_address", None)
Expand Down Expand Up @@ -1747,13 +1759,7 @@ async def run(self):

def resolve_in_pod(self, compose):
if self.global_args.in_pod_bool is None:
extension_dict = compose.get("x-podman", None)
if extension_dict is not None:
in_pod_value = extension_dict.get("in_pod", None)
if in_pod_value is not None:
self.global_args.in_pod_bool = in_pod_value
else:
self.global_args.in_pod_bool = True
self.global_args.in_pod_bool = get_global_x_podman_value(compose, "in_pod", True)
# otherwise use `in_pod` value provided by command line
return self.global_args.in_pod_bool

Expand Down
35 changes: 34 additions & 1 deletion tests/unit/test_container_to_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,23 @@
from podman_compose import container_to_args


def create_compose_mock(project_name="test_project_name"):
def create_compose_mock(project_name="test_project_name", extra_args=None):
compose = mock.Mock()
compose.project_name = project_name
compose.dirname = "test_dirname"
compose.container_names_by_service.get = mock.Mock(return_value=None)
compose.prefer_volume_over_mount = False
compose.default_net = None
compose.networks = {}

if extra_args is None:
extra_args = {}
compose.get = mock.Mock(side_effect=lambda key, default: extra_args.get(key, default))

async def podman_output(*args, **kwargs):
pass

compose.podman.output = mock.Mock(side_effect=podman_output)
return compose


Expand Down Expand Up @@ -561,3 +570,27 @@ async def test_selinux_volume(self, prefer_volume, selinux_type, expected_additi
"busybox",
],
)

@parameterized.expand([
("not_compat", False, "test_project_name", "test_project_name_network1"),
("compat_no_dash", True, "test_project_name", "test_project_name_network1"),
("compat_dash", True, "test_project-name", "test_projectname_network1"),
])
async def test_network_default_name(self, name, is_compat, project_name, expected_network_name):
c = create_compose_mock(project_name, {"x-podman": {"default_net_name_compat": is_compat}})
c.networks = {'network1': {}}

cnt = get_minimal_container()
cnt['networks'] = ['network1']

args = await container_to_args(c, cnt)
self.assertEqual(
args,
[
"--name=project_name_service_name1",
"-d",
f"--network={expected_network_name}",
"--network-alias=service_name",
"busybox",
],
)

0 comments on commit 2d2097c

Please sign in to comment.