diff --git a/python_on_whales/components/network/cli_wrapper.py b/python_on_whales/components/network/cli_wrapper.py index 64dd22ef..ae2bc254 100644 --- a/python_on_whales/components/network/cli_wrapper.py +++ b/python_on_whales/components/network/cli_wrapper.py @@ -15,6 +15,7 @@ NetworkInspectResult, NetworkIPAM, ) +from python_on_whales.exceptions import NoSuchNetwork from python_on_whales.utils import format_mapping_for_cli, run, to_list @@ -104,6 +105,13 @@ def config_only(self) -> bool: def __repr__(self): return f"python_on_whales.Network(id='{self.id[:12]}', name={self.name})" + def exists(self) -> bool: + """Returns `True` if the network exists and `False` if it doesn't exist. + + If it doesn't exist, that most likely means it was removed. + """ + return NetworkCLI(self.client_config).exists(self.id) + def remove(self) -> None: """Removes this Docker network. @@ -209,6 +217,22 @@ def disconnect( full_cmd += [network, container] run(full_cmd) + def exists( + self, + network: ValidNetwork, + ) -> bool: + """Check if a network exists + + Parameters: + network: The name of the network. + """ + try: + self.inspect(str(network)) + except NoSuchNetwork: + return False + else: + return True + @overload def inspect(self, x: str) -> Network: ... diff --git a/python_on_whales/exceptions.py b/python_on_whales/exceptions.py index c4c91009..6d40c17f 100644 --- a/python_on_whales/exceptions.py +++ b/python_on_whales/exceptions.py @@ -49,6 +49,10 @@ class NoSuchImage(DockerException): pass +class NoSuchNetwork(DockerException): + pass + + class NoSuchPod(DockerException): pass diff --git a/python_on_whales/utils.py b/python_on_whales/utils.py index feef71a5..2524d4e7 100644 --- a/python_on_whales/utils.py +++ b/python_on_whales/utils.py @@ -28,6 +28,7 @@ DockerException, NoSuchContainer, NoSuchImage, + NoSuchNetwork, NoSuchPod, NoSuchService, NoSuchVolume, @@ -218,6 +219,13 @@ def run( completed_process.stdout, completed_process.stderr, ) + if "network" in decoded_stderr and "not found" in decoded_stderr: + raise NoSuchNetwork( + args, + completed_process.returncode, + completed_process.stdout, + completed_process.stderr, + ) raise DockerException( args, diff --git a/tests/python_on_whales/components/test_network.py b/tests/python_on_whales/components/test_network.py index 45681492..e7804a81 100644 --- a/tests/python_on_whales/components/test_network.py +++ b/tests/python_on_whales/components/test_network.py @@ -78,3 +78,17 @@ def test_swarm_service_create(docker_client: DockerClient): "busybox", ["sleep", "infinity"], network=my_net.name ): assert len(my_net.containers) == 2 # 1 container + 1 endpoint + + +@pytest.mark.parametrize("ctr_client", ["docker", "podman"], indirect=True) +def test_network_exists(ctr_client: DockerClient): + network_name = random_name() + assert not ctr_client.network.exists(network_name) + with ctr_client.network.create(network_name) as network: + assert ctr_client.network.exists(network_name) + assert ctr_client.network.exists(network) + assert network.exists() + + # Outside with clause, network should be removed and no longer exist + assert not ctr_client.network.exists(network) + assert not network.exists()