Testing OpenStack upgrades
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

190 lines
6.4 KiB

"""Models for manipulating images in/to/from storage."""
from __future__ import absolute_import
import collections
import copy
import json
import logging
from . import ConfigDict, flatten, fold_keys
from .containers import Container
class Image(collections.UserDict):
"""Model for an Image."""
def __init__(self, client, id, data):
"""Construct Image Model."""
# pylint: disable=redefined-builtin
super().__init__(data)
for k, v in data.items():
setattr(self, k, v)
self._id = id
self._client = client
assert self._id == data['id'],\
'Requested image id({}) does not match store id({})'.format(
self._id, data['id']
)
@staticmethod
def _split_token(values=None, sep='='):
if not values:
return {}
return {k: v1 for k, v1 in (v0.split(sep, 1) for v0 in values)}
def create(self, *_args, **kwargs):
"""Create container from image.
Pulls defaults from image.inspect()
"""
details = self.inspect()
config = ConfigDict(image_id=self._id, **kwargs)
config['command'] = details.config.get('cmd')
config['env'] = self._split_token(details.config.get('env'))
config['image'] = copy.deepcopy(details.repotags[0])
config['labels'] = copy.deepcopy(details.labels)
# TODO: Are these settings still required?
config['net_mode'] = 'bridge'
config['network'] = 'bridge'
config['args'] = flatten([config['image'], config['command']])
logging.debug('Image %s: create config: %s', self._id, config)
with self._client() as podman:
id_ = podman.CreateContainer(config)['container']
cntr = podman.GetContainer(id_)
return Container(self._client, id_, cntr['container'])
container = create
def export(self, dest, compressed=False):
"""Write image to dest, return id on success."""
with self._client() as podman:
results = podman.ExportImage(self._id, dest, compressed)
return results['image']
def history(self):
"""Retrieve image history."""
with self._client() as podman:
for r in podman.HistoryImage(self._id)['history']:
yield collections.namedtuple('HistoryDetail', r.keys())(**r)
def inspect(self):
"""Retrieve details about image."""
with self._client() as podman:
results = podman.InspectImage(self._id)
obj = json.loads(results['image'], object_hook=fold_keys())
return collections.namedtuple('ImageInspect', obj.keys())(**obj)
def push(self,
target,
compress=False,
manifest_format="",
remove_signatures=False,
sign_by=""):
"""Copy image to target, return id on success."""
with self._client() as podman:
results = podman.PushImage(self._id, target, compress,
manifest_format, remove_signatures,
sign_by)
return results['reply']['id']
def remove(self, force=False):
"""Delete image, return id on success.
force=True, stop any running containers using image.
"""
with self._client() as podman:
results = podman.RemoveImage(self._id, force)
return results['image']
def tag(self, tag):
"""Tag image."""
with self._client() as podman:
results = podman.TagImage(self._id, tag)
return results['image']
class Images():
"""Model for Images collection."""
def __init__(self, client):
"""Construct model for Images collection."""
self._client = client
def list(self):
"""List all images in the libpod image store."""
with self._client() as podman:
results = podman.ListImages()
for img in results['images']:
yield Image(self._client, img['id'], img)
def build(self, dockerfile=None, tags=None, **kwargs):
"""Build container from image.
See podman-build.1.md for kwargs details.
"""
if dockerfile is None:
raise ValueError('"dockerfile" is a required argument.')
if not hasattr(dockerfile, '__iter__'):
raise ValueError('"dockerfile" is required to be an iter.')
if tags is None:
raise ValueError('"tags" is a required argument.')
if not hasattr(tags, '__iter__'):
raise ValueError('"tags" is required to be an iter.')
config = ConfigDict(dockerfile=dockerfile, tags=tags, **kwargs)
with self._client() as podman:
result = podman.BuildImage(config)
return self.get(result['image']['id']), \
(line for line in result['image']['logs'])
def delete_unused(self):
"""Delete Images not associated with a container."""
with self._client() as podman:
results = podman.DeleteUnusedImages()
return results['images']
def import_image(self, source, reference, message='', changes=None):
"""Read image tarball from source and save in image store."""
with self._client() as podman:
results = podman.ImportImage(source, reference, message, changes)
return results['image']
def pull(self, source):
"""Copy image from registry to image store."""
with self._client() as podman:
results = podman.PullImage(source)
return results['reply']['id']
def search(self,
id_,
limit=25,
is_official=None,
is_automated=None,
star_count=None):
"""Search registries for id."""
constraints = {}
if is_official is not None:
constraints['is_official'] = is_official
if is_automated is not None:
constraints['is_automated'] = is_automated
if star_count is not None:
constraints['star_count'] = star_count
with self._client() as podman:
results = podman.SearchImages(id_, limit, constraints)
for img in results['results']:
yield collections.namedtuple('ImageSearch', img.keys())(**img)
def get(self, id_):
"""Get Image from id."""
with self._client() as podman:
result = podman.GetImage(id_)
return Image(self._client, result['image']['id'], result['image'])