Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
hubboss / boss / hosts.py
Size: Mime:
import docker
import re
from docker.errors import APIError
from contextlib import contextmanager

from . import utils
from . import container as container_module

class Host(utils.NiceRepr):
    def __init__(self, name, base_url, tls, environment=None, ip=None):
        self.name = name
        self.base_url = base_url

        # tls setting should be 'false' if not True or
        # TLSConfig instance
        if not tls:
            tls = bool(tls)

        self.tls = tls
        self.ip = ip
        self.environment = environment

    def to_dict(self):
        return dict(
            name=self.name,
            base_url=self.base_url,
            ip=self.ip,
            environment=self.environment,
            tls=False if not self.tls else self.tls_to_dict(self.tls)
        )

    def tls_to_dict(cls, tls):
        return dict(
            client_cert=tls.cert,
            verify=tls.verify,
            ssl_version=tls.ssl_version,
            assert_hostname=tls.assert_hostname,
            assert_fingerprint=tls.assert_fingerprint
        )

    @classmethod
    def from_dict(cls, d):
        if d.get('tls'):
            d['tls'] = docker.tls.TLSConfig(**d['tls'])

        return cls(**d)

    def get_cli_config(self):
        fmt_string = '-H "{tcp_url}"'

        if self.tls:
            fmt_string += (
                ' --tlsverify=false'
                # '--tlscacert={}'
                ' --tlscert={tls_cert}'
                ' --tlskey={tls_key}'
            )

        return fmt_string.format(
            tcp_url=self.tcp_url,
            tls_cert=self.tls.cert[0] if self.tls else None,
            tls_key=self.tls.cert[1] if self.tls else None,
        )

    @property
    def tcp_url(self):
        if not self.tls:
            proto = 'http'
        else:
            proto = 'https'

        return self.base_url.replace(proto, 'tcp')

    @contextmanager
    def _client(self):
        """
        Defer creating the client till it's actually needed, then cache it so we
        don't have to keep setting it.
        """
        if not hasattr(self, 'client'):
            setattr(self, 'client', self._create_client(self.base_url, self.tls))
        yield

    def _create_client(self, base_url, tls):
        return docker.Client(base_url=base_url, tls=tls)

    @property
    def version(self):
        if not hasattr(self, '_version'):
            setattr(self, '_version', self._get_version_info())
        return self._version

    def _get_version_info(self):
        with self._client():
            return self.client.version()

    @property
    def docker_version(self):
        return "{} {}".format(self.version['Version'], self.version['GoVersion'])

    @property
    def os_info(self):
        return "{} {} {}".format(
            self.version.get('KernelVersion', 'Unknown Kernel'),
            self.version.get('Arch', 'Unknown Arch'),
            self.version.get('Os', 'Unknown Os')
        )

    @property
    def containers(self):
        return self.get_containers()

    def get_containers(self, grep=None, show_all=False, show_restart=False):
        containers = []

        with self._client():
            client_containers = self.client.containers(all=show_all)

        if grep is not None:
            grep_regex = re.compile(grep)
            filtered_containers = []
            for container in client_containers:
                for name in container['Names']:
                    if grep_regex.search(name) is not None:
                        filtered_containers.append(container)

            client_containers = filtered_containers

        for container in client_containers:
            containers.append(container_module.Container(
                host=self.base_url,
                config=self.tls,
                show_restart=show_restart,
                **dict((key.lower(), value) for key, value in container.iteritems())
            ))
        return containers

    def __str__(self):
        host_header = (u"Host: {0} at {1: <16} DockerVersion: {2: <23} Host Version: {3}"
                       u"".format(self.name, self.base_url, self.docker_version, self.os_info))

        ps_header = u"{0: <13} {1: <8} {2: <38} {3: <60} {4: <20} {5: <30}".format(
            u'Container id', u'Restart', u'Image Name', u'Container Name', u'Status', u'Ports')

        return "{}\n{}".format(host_header, ps_header)

    def build(self, path, tag, rm=True):
        with self._client():
            return self.client.build(path=path, rm=rm, tag=tag)

    def images(self, name=None):
        with self._client():
            return self.client.images(name)

    def push(self, repository, tag, stream=True):
        with self._client():
            return self.client.push(repository=repository, tag=tag, stream=stream)

    def pull(self, repository, tag='latest', stream=True, insecure_registry=False):
        print "Pulling {}:{} to {}".format(repository, tag, self.base_url)
        with self._client():
            return self.client.pull(repository=repository, tag=tag, stream=stream, insecure_registry=insecure_registry)

    def remove_containers(self, container_ids, force):
        ret = []
        with self._client():
            for c_id in container_ids:
                try:
                    self.client.remove_container(c_id, force=force)
                except Exception as e:
                    print('Failed to remove container {} on {}: {}'.format(c_id, self.base_url, e.message))
                    continue
                ret.append('Container {} removed from {}\n'.format(c_id, self.base_url))
        return ret

    def stop_containers(self, container_ids):
        ret = []
        with self._client():
            for c_id in container_ids:
                try:
                    self.client.stop(c_id)
                except Exception as e:
                    print('Failed to stop container {} on {}: {}'.format(c_id, self.base_url, e.message))
                    continue
                ret.append('Container {} stopped on {}\n'.format(c_id, self.base_url))

        return ret

    def start_containers(self, container_ids):
        ret = []
        with self._client():
            for c_id in container_ids:
                try:
                    self.client.start(c_id)
                except Exception as e:
                    print('Failed to start container {} on {}: {}'.format(c_id, self.base_url, e.message))
                    continue
                ret.append('Container {} started on {}\n'.format(c_id, self.base_url))
        return ret

    def restart_containers(self, container_ids):
        ret = []
        with self._client():
            for c_id in container_ids:
                try:
                    self.client.restart(c_id)
                except Exception as e:
                    print('Failed to restart container {} on {}: {}'.format(c_id, self.base_url, e.message))
                    continue
                ret.append('Container {} restarted on {}\n'.format(c_id, self.base_url))
        return ret

    def container_logs(self, container_ids):
        ret = []
        with self._client():
            for c_id in container_ids:
                try:
                    ret.append(self.client.logs(c_id, stream=False))
                except Exception as e:
                    print e.message
                    continue
        return ret

    def create_container(
        self, image, command=None, hostname=None, user=None,
        detach=True, stdin_open=False, tty=False,
        mem_limit=None, ports=None, environment=None, dns=None,
        volumes=None, volumes_from=None,
        network_disabled=False, name=None, entrypoint=None,
        cpu_shares=None, working_dir=None, domainname=None,
        memswap_limit=None, cpuset=None, host_config=None
    ):
        try:
            with self._client():
                return self.client.create_container(
                    image, command, hostname, user,
                    detach, stdin_open, tty,
                    mem_limit, ports, environment, dns,
                    volumes, volumes_from,
                    network_disabled, name, entrypoint,
                    cpu_shares, working_dir, domainname,
                    memswap_limit, cpuset, host_config)
        except APIError as e:
            print e
            return e

    def wait(self, container, timeout=None):
        with self._client():
            return self.client.wait(container, timeout)