Loading behave_utils/docker.py +27 −20 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ from typing import Any from typing import Iterable from typing import Iterator from typing import MutableMapping from typing import NewType from typing import Tuple from typing import TypeVar from typing import Union Loading @@ -54,6 +55,8 @@ from .utils import wait LOCALHOST = ipaddress.IPv4Address(0x7f000001) ShaID = NewType("ShaID", str) MountPath = Union[PathLike[bytes], PathLike[str]] HostMount = tuple[MountPath, MountPath] NamedMount = tuple[str, MountPath] Loading Loading @@ -150,20 +153,20 @@ class Item: A mix-in for Docker items that can be inspected """ def __init__(self, ident: str): self._id = ident def __init__(self, reference: str): self.reference = reference def get_id(self) -> str: def get_id(self) -> ShaID: """ Return an identifier for the Docker item """ return self._id return self.inspect().path("$.Id", str, ShaID) def inspect(self) -> JSONObject: """ Get the result of inspecting the Docker item """ with Popen([DOCKER, 'inspect', self.get_id()], stdout=PIPE) as proc: with Popen([DOCKER, 'inspect', self.reference], stdout=PIPE) as proc: assert proc.stdout is not None results = json.load(proc.stdout) assert isinstance(results, list) Loading @@ -176,11 +179,11 @@ class Image(Item): Docker image items """ _cache = dict[str, str]() _cache = dict[str, ShaID]() T = TypeVar('T', bound='Image') def __init__(self, iid: str): def __init__(self, iid: ShaID): self.iid = iid @classmethod Loading @@ -196,7 +199,7 @@ class Image(Item): *(f"--build-arg={arg}={val}" for arg, val in build_args.items() if val is not None), ] docker(*cmd, DOCKER_BUILDKIT='1') iid = docker_output(*cmd, '-q', DOCKER_BUILDKIT='1') iid = ShaID(docker_output(*cmd, '-q', DOCKER_BUILDKIT='1')) return cls(iid) @classmethod Loading @@ -212,16 +215,16 @@ class Image(Item): return cls(iid) @classmethod def _process_image(cls, reference: str) -> str: def _process_image(cls, reference: str) -> ShaID: report = Item(reference).inspect() iid = report.path("$.Id", str) iid = report.path("$.Id", str, ShaID) cls._cache.update( ((tag, iid) for tag in report.path("$.RepoTags", list[str])), reference=iid, ) return iid def get_id(self) -> str: def get_id(self) -> ShaID: """ Return an identifier for the Docker Image """ Loading Loading @@ -264,7 +267,7 @@ class Container(Item): self.privileged = privileged self.publish = publish self.networks = dict[Network, Tuple[str, ...]]() self.cid: str|None = None self.cid: ShaID|None = None if network: self.connect(network, *self.DEFAULT_ALIASES) Loading Loading @@ -309,7 +312,7 @@ class Container(Item): and details.path('$.State.Running', bool) ) def get_id(self) -> str: def get_id(self) -> ShaID: """ Return an identifier for the Docker Container """ Loading Loading @@ -346,7 +349,9 @@ class Container(Item): else: opts.append(b"--network=none") self.cid = docker_output(b"container", b"create", *opts, self.image.iid, *self.cmd) self.cid = ShaID( docker_output(b"container", b"create", *opts, self.image.iid, *self.cmd), ) assert self.cid # Disconnect the "none" network specified as the starting network Loading Loading @@ -485,7 +490,7 @@ class Network(Item): def __init__(self, name: str|None = None) -> None: self._name = name or f"br{token_hex(6)}" self._nid: str|None = None self._nid: ShaID|None = None self._assigned = set[ipaddress.IPv4Address]() def __str__(self) -> str: Loading Loading @@ -517,7 +522,7 @@ class Network(Item): """ return self._name def get_id(self) -> str: def get_id(self) -> ShaID: """ Return an identifier for the Docker Network """ Loading @@ -533,9 +538,11 @@ class Network(Item): subnet = self.get_free_subnet() gateway = next(subnet.hosts()) try: self._nid = docker_output( self._nid = ShaID( docker_output( b"network", b"create", self._name, f"--subnet={subnet}", f"--gateway={gateway}", ), ) except CalledProcessError: data = exec_io( Loading @@ -544,7 +551,7 @@ class Network(Item): ) if len(data) == 0: raise self._nid = data.path("$[0].Id", str) self._nid = data.path("$[0].Id", str, ShaID) self._assigned.update( data.path( "$[0].IPAM.Config[*].Gateway", Loading Loading
behave_utils/docker.py +27 −20 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ from typing import Any from typing import Iterable from typing import Iterator from typing import MutableMapping from typing import NewType from typing import Tuple from typing import TypeVar from typing import Union Loading @@ -54,6 +55,8 @@ from .utils import wait LOCALHOST = ipaddress.IPv4Address(0x7f000001) ShaID = NewType("ShaID", str) MountPath = Union[PathLike[bytes], PathLike[str]] HostMount = tuple[MountPath, MountPath] NamedMount = tuple[str, MountPath] Loading Loading @@ -150,20 +153,20 @@ class Item: A mix-in for Docker items that can be inspected """ def __init__(self, ident: str): self._id = ident def __init__(self, reference: str): self.reference = reference def get_id(self) -> str: def get_id(self) -> ShaID: """ Return an identifier for the Docker item """ return self._id return self.inspect().path("$.Id", str, ShaID) def inspect(self) -> JSONObject: """ Get the result of inspecting the Docker item """ with Popen([DOCKER, 'inspect', self.get_id()], stdout=PIPE) as proc: with Popen([DOCKER, 'inspect', self.reference], stdout=PIPE) as proc: assert proc.stdout is not None results = json.load(proc.stdout) assert isinstance(results, list) Loading @@ -176,11 +179,11 @@ class Image(Item): Docker image items """ _cache = dict[str, str]() _cache = dict[str, ShaID]() T = TypeVar('T', bound='Image') def __init__(self, iid: str): def __init__(self, iid: ShaID): self.iid = iid @classmethod Loading @@ -196,7 +199,7 @@ class Image(Item): *(f"--build-arg={arg}={val}" for arg, val in build_args.items() if val is not None), ] docker(*cmd, DOCKER_BUILDKIT='1') iid = docker_output(*cmd, '-q', DOCKER_BUILDKIT='1') iid = ShaID(docker_output(*cmd, '-q', DOCKER_BUILDKIT='1')) return cls(iid) @classmethod Loading @@ -212,16 +215,16 @@ class Image(Item): return cls(iid) @classmethod def _process_image(cls, reference: str) -> str: def _process_image(cls, reference: str) -> ShaID: report = Item(reference).inspect() iid = report.path("$.Id", str) iid = report.path("$.Id", str, ShaID) cls._cache.update( ((tag, iid) for tag in report.path("$.RepoTags", list[str])), reference=iid, ) return iid def get_id(self) -> str: def get_id(self) -> ShaID: """ Return an identifier for the Docker Image """ Loading Loading @@ -264,7 +267,7 @@ class Container(Item): self.privileged = privileged self.publish = publish self.networks = dict[Network, Tuple[str, ...]]() self.cid: str|None = None self.cid: ShaID|None = None if network: self.connect(network, *self.DEFAULT_ALIASES) Loading Loading @@ -309,7 +312,7 @@ class Container(Item): and details.path('$.State.Running', bool) ) def get_id(self) -> str: def get_id(self) -> ShaID: """ Return an identifier for the Docker Container """ Loading Loading @@ -346,7 +349,9 @@ class Container(Item): else: opts.append(b"--network=none") self.cid = docker_output(b"container", b"create", *opts, self.image.iid, *self.cmd) self.cid = ShaID( docker_output(b"container", b"create", *opts, self.image.iid, *self.cmd), ) assert self.cid # Disconnect the "none" network specified as the starting network Loading Loading @@ -485,7 +490,7 @@ class Network(Item): def __init__(self, name: str|None = None) -> None: self._name = name or f"br{token_hex(6)}" self._nid: str|None = None self._nid: ShaID|None = None self._assigned = set[ipaddress.IPv4Address]() def __str__(self) -> str: Loading Loading @@ -517,7 +522,7 @@ class Network(Item): """ return self._name def get_id(self) -> str: def get_id(self) -> ShaID: """ Return an identifier for the Docker Network """ Loading @@ -533,9 +538,11 @@ class Network(Item): subnet = self.get_free_subnet() gateway = next(subnet.hosts()) try: self._nid = docker_output( self._nid = ShaID( docker_output( b"network", b"create", self._name, f"--subnet={subnet}", f"--gateway={gateway}", ), ) except CalledProcessError: data = exec_io( Loading @@ -544,7 +551,7 @@ class Network(Item): ) if len(data) == 0: raise self._nid = data.path("$[0].Id", str) self._nid = data.path("$[0].Id", str, ShaID) self._assigned.update( data.path( "$[0].IPAM.Config[*].Gateway", Loading