Improve speed of containers.list()

* Clean up code in containers.py
* Pass pylint tests
* Pass tox tests

Signed-off-by: Jhon Honce <jhonce@redhat.com>
This commit is contained in:
Jhon Honce
2018-11-19 15:39:45 -07:00
parent ea928f2de6
commit e955ff04ab

View File

@ -1,12 +1,12 @@
"""Models for manipulating containers and storage.""" """Models for manipulating containers and storage."""
import collections import collections
import functools
import getpass import getpass
import json import json
import logging import logging
import signal import signal
import time import time
from . import fold_keys
from ._containers_attach import Mixin as AttachMixin from ._containers_attach import Mixin as AttachMixin
from ._containers_start import Mixin as StartMixin from ._containers_start import Mixin as StartMixin
@ -14,25 +14,27 @@ from ._containers_start import Mixin as StartMixin
class Container(AttachMixin, StartMixin, collections.UserDict): class Container(AttachMixin, StartMixin, collections.UserDict):
"""Model for a container.""" """Model for a container."""
def __init__(self, client, id, data): def __init__(self, client, ident, data, refresh=True):
"""Construct Container Model.""" """Construct Container Model."""
super(Container, self).__init__(data) super(Container, self).__init__(data)
self._client = client self._client = client
self._id = id self._id = ident
if refresh:
with client() as podman: with client() as podman:
self._refresh(podman) self._refresh(podman)
else:
for k, v in self.data.items():
setattr(self, k, v)
if 'containerrunning' in self.data:
setattr(self, 'running', self.data['containerrunning'])
self.data['running'] = self.data['containerrunning']
assert self._id == data['id'],\ assert self._id == data['id'],\
'Requested container id({}) does not match store id({})'.format( 'Requested container id({}) does not match store id({})'.format(
self._id, data['id'] self._id, data['id']
) )
def __getitem__(self, key):
"""Get items from parent dict."""
return super().__getitem__(key)
def _refresh(self, podman, tries=1): def _refresh(self, podman, tries=1):
try: try:
ctnr = podman.GetContainer(self._id) ctnr = podman.GetContainer(self._id)
@ -71,18 +73,18 @@ class Container(AttachMixin, StartMixin, collections.UserDict):
results = podman.ListContainerChanges(self._id) results = podman.ListContainerChanges(self._id)
return results['container'] return results['container']
def kill(self, signal=signal.SIGTERM, wait=25): def kill(self, sig=signal.SIGTERM, wait=25):
"""Send signal to container. """Send signal to container.
default signal is signal.SIGTERM. default signal is signal.SIGTERM.
wait n of seconds, 0 waits forever. wait n of seconds, 0 waits forever.
""" """
with self._client() as podman: with self._client() as podman:
podman.KillContainer(self._id, signal) podman.KillContainer(self._id, sig)
timeout = time.time() + wait timeout = time.time() + wait
while True: while True:
self._refresh(podman) self._refresh(podman)
if self.status != 'running': if self.status != 'running': # pylint: disable=no-member
return self return self
if wait and timeout < time.time(): if wait and timeout < time.time():
@ -90,20 +92,11 @@ class Container(AttachMixin, StartMixin, collections.UserDict):
time.sleep(0.5) time.sleep(0.5)
def _lower_hook(self):
"""Convert all keys to lowercase."""
@functools.wraps(self._lower_hook)
def wrapped(input_):
return {k.lower(): v for (k, v) in input_.items()}
return wrapped
def inspect(self): def inspect(self):
"""Retrieve details about containers.""" """Retrieve details about containers."""
with self._client() as podman: with self._client() as podman:
results = podman.InspectContainer(self._id) results = podman.InspectContainer(self._id)
obj = json.loads(results['container'], object_hook=self._lower_hook()) obj = json.loads(results['container'], object_hook=fold_keys())
return collections.namedtuple('ContainerInspect', obj.keys())(**obj) return collections.namedtuple('ContainerInspect', obj.keys())(**obj)
def export(self, target): def export(self, target):
@ -121,7 +114,7 @@ class Container(AttachMixin, StartMixin, collections.UserDict):
changes=[], changes=[],
message='', message='',
pause=True, pause=True,
**kwargs): **kwargs): # pylint: disable=unused-argument
"""Create image from container. """Create image from container.
All changes overwrite existing values. All changes overwrite existing values.
@ -175,7 +168,7 @@ class Container(AttachMixin, StartMixin, collections.UserDict):
podman.RestartContainer(self._id, timeout) podman.RestartContainer(self._id, timeout)
return self._refresh(podman) return self._refresh(podman)
def rename(self, target): def rename(self, target): # pylint: disable=unused-argument
"""Rename container, return id on success.""" """Rename container, return id on success."""
with self._client() as podman: with self._client() as podman:
# TODO: Need arguments # TODO: Need arguments
@ -183,7 +176,7 @@ class Container(AttachMixin, StartMixin, collections.UserDict):
# TODO: fixup objects cached information # TODO: fixup objects cached information
return results['container'] return results['container']
def resize_tty(self, width, height): def resize_tty(self, width, height): # pylint: disable=unused-argument
"""Resize container tty.""" """Resize container tty."""
with self._client() as podman: with self._client() as podman:
# TODO: magic re: attach(), arguments # TODO: magic re: attach(), arguments
@ -201,7 +194,8 @@ class Container(AttachMixin, StartMixin, collections.UserDict):
podman.UnpauseContainer(self._id) podman.UnpauseContainer(self._id)
return self._refresh(podman) return self._refresh(podman)
def update_container(self, *args, **kwargs): def update_container(self, *args, **kwargs): \
# pylint: disable=unused-argument
"""TODO: Update container..., return id on success.""" """TODO: Update container..., return id on success."""
with self._client() as podman: with self._client() as podman:
podman.UpdateContainer() podman.UpdateContainer()
@ -220,7 +214,7 @@ class Container(AttachMixin, StartMixin, collections.UserDict):
obj = results['container'] obj = results['container']
return collections.namedtuple('StatDetail', obj.keys())(**obj) return collections.namedtuple('StatDetail', obj.keys())(**obj)
def logs(self, *args, **kwargs): def logs(self, *args, **kwargs): # pylint: disable=unused-argument
"""Retrieve container logs.""" """Retrieve container logs."""
with self._client() as podman: with self._client() as podman:
results = podman.GetContainerLogs(self._id) results = podman.GetContainerLogs(self._id)
@ -239,7 +233,7 @@ class Containers():
with self._client() as podman: with self._client() as podman:
results = podman.ListContainers() results = podman.ListContainers()
for cntr in results['containers']: for cntr in results['containers']:
yield Container(self._client, cntr['id'], cntr) yield Container(self._client, cntr['id'], cntr, refresh=False)
def delete_stopped(self): def delete_stopped(self):
"""Delete all stopped containers.""" """Delete all stopped containers."""