from abc import ABCMeta, abstractmethod from collections import namedtuple from six import add_metaclass Command = namedtuple('Command', ['command']) # NOTE: FileCopy is done via `scp`, instead of `ssh` which is how Command is run. FileCopy = namedtuple('FileCopy', ['source', 'destination']) @add_metaclass(ABCMeta) class Client(object): """ Client defines the interface for all clients being tested. """ @abstractmethod def setup_client(self, registry_host, verify_tls): """ Returns the commands necessary to setup the client inside the VM. """ @abstractmethod def populate_test_image(self, registry_host, namespace, name): """ Returns the commands necessary to populate the test image. """ @abstractmethod def print_version(self): """ Returns the commands necessary to print the version of the client. """ @abstractmethod def login(self, registry_host, username, password): """ Returns the commands necessary to login. """ @abstractmethod def push(self, registry_host, namespace, name): """ Returns the commands necessary to test pushing. """ @abstractmethod def pre_pull_cleanup(self, registry_host, namespace, name): """ Returns the commands necessary to cleanup before pulling. """ @abstractmethod def pull(self, registry_host, namespace, name): """ Returns the commands necessary to test pulling. """ @abstractmethod def verify(self, registry_host, namespace, name): """ Returns the commands necessary to verify the pulled image. """ class DockerClient(Client): def __init__(self, requires_v1=False, requires_email=False): self.requires_v1 = requires_v1 self.requires_email = requires_email def setup_client(self, registry_host, verify_tls): if not verify_tls: cp_command = ('sudo cp /home/core/50-insecure-registry.conf ' + '/etc/systemd/system/docker.service.d/50-insecure-registry.conf') yield Command('sudo mkdir -p /etc/systemd/system/docker.service.d/') yield FileCopy('50-insecure-registry.conf', '/home/core') yield Command(cp_command) yield Command('sudo systemctl daemon-reload') yield FileCopy('Dockerfile.test', '/home/core/Dockerfile') def populate_test_image(self, registry_host, namespace, name): if self.requires_v1: # These versions of Docker don't support the new TLS cert on quay.io, so we need to pull # from v1.quay.io and then retag so the build works. yield Command('docker pull v1.quay.io/quay/busybox') yield Command('docker tag v1.quay.io/quay/busybox quay.io/quay/busybox') yield Command('docker build -t %s/%s/%s .' % (registry_host, namespace, name)) def print_version(self): yield Command('docker version') def login(self, registry_host, username, password): email_param = "" if self.requires_email: # cli will block forever if email is not set for version under 1.10.3 email_param = "--email=none " yield Command('docker login --username=%s --password=%s %s %s' % (username, password, email_param, registry_host)) def push(self, registry_host, namespace, name): yield Command('docker push %s/%s/%s' % (registry_host, namespace, name)) def pre_pull_cleanup(self, registry_host, namespace, name): prefix = 'v1.' if self.requires_v1 else '' yield Command('docker rmi -f %s/%s/%s' % (registry_host, namespace, name)) yield Command('docker rmi -f %squay.io/quay/busybox' % prefix) def pull(self, registry_host, namespace, name): yield Command('docker pull %s/%s/%s' % (registry_host, namespace, name)) def verify(self, registry_host, namespace, name): yield Command('docker run %s/%s/%s echo testfile' % (registry_host, namespace, name)) class PodmanClient(Client): def __init__(self): self.verify_tls = False def setup_client(self, registry_host, verify_tls): yield FileCopy('Dockerfile.test', '/home/vagrant/Dockerfile') self.verify_tls = verify_tls def populate_test_image(self, registry_host, namespace, name): yield Command('sudo podman build -t %s/%s/%s /home/vagrant/' % (registry_host, namespace, name)) def print_version(self): yield Command('sudo podman version') def login(self, registry_host, username, password): yield Command('sudo podman login --tls-verify=%s --username=%s --password=%s %s' % (self.verify_tls, username, password, registry_host)) def push(self, registry_host, namespace, name): yield Command('sudo podman push --tls-verify=%s %s/%s/%s' % (self.verify_tls, registry_host, namespace, name)) def pre_pull_cleanup(self, registry_host, namespace, name): yield Command('sudo podman rmi -f %s/%s/%s' % (registry_host, namespace, name)) yield Command('sudo podman rmi -f quay.io/quay/busybox') def pull(self, registry_host, namespace, name): yield Command('sudo podman pull --tls-verify=%s %s/%s/%s' % (self.verify_tls, registry_host, namespace, name)) def verify(self, registry_host, namespace, name): yield Command('sudo podman run %s/%s/%s echo testfile' % (registry_host, namespace, name))