diff --git a/dcr b/dcr index f5a1179..f06f1ae 100755 --- a/dcr +++ b/dcr @@ -4,6 +4,7 @@ __author__ = 'thatcher' import sys from docker_container_runner import utils from docker_container_runner.manager import Application, DockerDaemon, Hipache +import pkg_resources # part of setuptools # try: @@ -31,7 +32,7 @@ def initialize(): containers = application.get_containers() for name, container in containers.items(): - print container.status + status = container.status return application @@ -66,6 +67,8 @@ def print_usage(): options: + version: show current dcr version + Managing the containers ----------------------- @@ -88,8 +91,13 @@ def print_usage(): try: stream = open(sys.argv[1]) except: - print_usage() - sys.exit(1) + try: + if sys.argv[1] == "version": + print "dcr version: {}".format(pkg_resources.require("dcr")[0].version) + sys.exit(0) + except IndexError: + print_usage() + sys.exit(1) directives = utils.read_appconfig(sys.argv[1]) diff --git a/docker_container_runner/manager.py b/docker_container_runner/manager.py index 9277ad6..20a9466 100644 --- a/docker_container_runner/manager.py +++ b/docker_container_runner/manager.py @@ -18,16 +18,23 @@ def __init__(self, host, registry_login, ssh_user, ssh=True): except ValueError: hostname = host - self.host_name, self.host_port = hostname.split(":") - self.host = host - self.registry_login = registry_login - self.ssh_user = ssh_user - - if ssh: - forwarder = create_tunnel(self.host_name, self.host_port, ssh_user) - entrypoint = "http://{}".format(forwarder.bind_string) + if protocol == "http:": + self.host_name, self.host_port = hostname.split(":") + self.host = host + self.registry_login = registry_login + self.ssh_user = ssh_user + + if ssh: + forwarder = create_tunnel(self.host_name, self.host_port, ssh_user) + entrypoint = "http://{}".format(forwarder.bind_string) + else: + entrypoint = "http://{}:{}".format(self.host_name, self.host_port) + elif protocol == "unix:": + entrypoint = host + self.host_name = "local" else: - entrypoint = "http://{}:{}".format(self.host_name, self.host_port) + print "Docker access protocol not recognized" + sys.exit(1) self.connection = docker.Client(base_url=entrypoint, version="1.7") @@ -35,16 +42,21 @@ def login(self): """ Logs in to the registry """ + if not self.registry_login: + # sys.exit("Cannot login, no registry settings set") + print "login: No registry settings found, trying to connect anonymously" + return + try: username, password, email = self.registry_login.split(":") except BaseException as ex: - sys.exit("error parsing registry_settings: {}".format(ex)) + sys.exit("error parsing registry_settings, were they set in your environment?, {}".format(ex)) - print "trying to login to the public index using user {}".format(username) + print "login: trying to login to the public index using user {}".format(username) result = self.connection.login(username=username, password=password, email=email) - # print result + print "login: {}".format(result[u'Status']) return result @@ -76,7 +88,6 @@ def details(self): details = self.daemon.connection.inspect_container(self.config['release_name']) return details except APIError as ex: - print ex return None except ConnectionError as ex: print "Failed to connect to daemon ", ex @@ -87,33 +98,39 @@ def status(self): try: running = self.details['State']['Running'] if running: + print "status: Status of '{}' on host '{}' is running \n with ports: {}".format( + self.config['release_name'], + self.daemon.host_name, + self.details[u'NetworkSettings']['Ports'] + ) status = "running" else: + print "status: container {} on host {} is stopped".format(self.config['release_name'], self.daemon.host_name) status = "stopped" except Exception: status = "doesnotexist" + print "status: container {} on host {} does not exist".format(self.config['release_name'], self.daemon.host_name) + return status def pull(self): repository = self.config['image'] - print "starting to pull {} on {}".format(repository, self.daemon.host_name) + print "pull: Starting to pull {} on {}".format(repository, self.daemon.host_name) try: - self.daemon.login() result = self.daemon.connection.pull(repository, tag=None) - print result + print "pull: {}".format(result) + print "pull: Pull complete" return result except APIError as ex: print ex return ex - print "pull complete" - def get_image(self): return self.daemon.connection.images(name=self.config['image']) def create(self): - print "creating container on {}".format(self.daemon.host_name) + print "create: creating container on {}".format(self.daemon.host_name) try: self.daemon.connection.create_container(self.config['image'], self.config['command'], @@ -123,7 +140,7 @@ def create(self): detach=True, name=self.config['release_name']) except APIError as ex: - print "failed to create container: ", ex + print "create: failed to create container: ", ex return 1, "Failed to create container", ex @@ -131,20 +148,22 @@ def start(self): """ starts one of the containers of this application """ - print "starting container on {}".format(self.daemon.host_name) + print "start: starting container on {}".format(self.daemon.host_name) + if self.details is None: return None - if not self.details['State']['Running'] is True: - result = self.daemon.connection.start(self.config['release_name'], - port_bindings=self.config['s_ports'], - binds=self.config['binds'], - links=self.config['links']) - return result else: - return None + if not self.details['State']['Running'] is True: + result = self.daemon.connection.start(self.config['release_name'], + port_bindings=self.config['s_ports'], + binds=self.config['binds'], + links=self.config['links']) + return result + else: + return None def stop(self): - print "stopping container on {}".format(self.daemon.host_name) + print "stop: stopping container on {}".format(self.daemon.host_name) if self.details is None: return 1, "container does not exist" if not self.details['State']['Running'] is False: @@ -157,7 +176,7 @@ def remove(self): """ starts one of the containers of this application """ - print "removing container on {}".format(self.daemon.host_name) + print "remove: removing container on {}".format(self.daemon.host_name) if self.details is None: return 1, "container does not exist" elif self.details['State']['Running'] is False: @@ -201,8 +220,17 @@ def connect_gateways(self, cluster="default"): use_ssh = self.settings[cluster]['use_ssh'] ssh_user = self.settings[cluster].get('ssh_user', None) - for hipache_config in self.settings['default']['hipaches']: - hipache_host, hipache_port = hipache_config.split(':') + if os.environ["REDIS_PORT_6379_TCP_ADDR"]: + hipache_host = os.environ["REDIS_PORT_6379_TCP_ADDR"] + hipache_port = os.environ["REDIS_PORT_6379_TCP_PORT"] + self.hipaches.append(Hipache(hipache_host, int(hipache_port), ssh_user=ssh_user, use_ssh=use_ssh)) + elif 'hipaches' in self.settings['default'].keys(): + for hipache_config in self.settings['default']['hipaches']: + hipache_host, hipache_port = hipache_config.split(':') + self.hipaches.append(Hipache(hipache_host, int(hipache_port), ssh_user=ssh_user, use_ssh=use_ssh)) + else: + hipache_host = "127.0.0.1" + hipache_port = "6379" self.hipaches.append(Hipache(hipache_host, int(hipache_port), ssh_user=ssh_user, use_ssh=use_ssh)) release_name = self.config.get('release_name', None) @@ -286,10 +314,6 @@ def get_details(self): def get_status(self): status = [] for key, container in self.containers.items(): - print "container {release_name} on host {daemon}, Running={status}" \ - .format(release_name=container.config['release_name'], - daemon=container.daemon.host_name, - status=container.status) status.append(container.status) return status @@ -366,13 +390,13 @@ def unregister(self, domain, hard=False): # check length length = hipache.connection.llen(frontend) - print "setting was", hipache.connection.lrange(frontend, 0, -1) + print "unregister: setting was", hipache.connection.lrange(frontend, 0, -1) if not length > 0: - sys.exit("no backends in redis with this domain") + sys.exit("unregister: no backends in redis with this domain") elif length == 1: print hipache.connection.lrange(frontend, 0, -1) - sys.exit("domain known, but no backends present") + sys.exit("unregister: domain known, but no backends present") else: if hard is False: for backend_uri in backend_uris: @@ -381,7 +405,7 @@ def unregister(self, domain, hard=False): hipache.connection.ltrim(frontend, 0, 0) # remove all backends from this domain stored_backends = hipache.connection.lrange(frontend, 0, -1) - print "setting now", stored_backends + print "unregister: setting now", stored_backends results.append(stored_backends) return results @@ -390,7 +414,10 @@ def unregister_all(self, domain): self.unregister(domain, hard=True) def switch_backends(self, domain): + print "switch: unregistering all" self.unregister(domain, hard=True) + + print "switch: registering {}".format(domain) self.register(domain) def redis_status(self, domain): diff --git a/docker_container_runner/utils.py b/docker_container_runner/utils.py index 2daa49e..f0e9168 100644 --- a/docker_container_runner/utils.py +++ b/docker_container_runner/utils.py @@ -1,6 +1,7 @@ import yaml import sys import os +import re import bgtunnel from bgtunnel import SSHTunnelError @@ -12,7 +13,8 @@ def read_appconfig(filename): print "no filename given, or incorrect file" return err - config = yaml.load(stream) + config = yaml.load(os.path.expandvars(re.sub( + r'\%([a-zA-Z0-9\-_]+)',r'\1=$\1', stream.read()))) directives = {} @@ -124,7 +126,7 @@ def read_settings(filename='settings.yml'): print "no filename given, or incorrect file" return err - settings = yaml.load(stream) + settings = yaml.load(os.path.expandvars(stream.read())) items = settings['default'] items['registry_login'] = try_replace_vars(items.get("registry_login", None)) diff --git a/samples/test.yml b/samples/test.yml new file mode 100644 index 0000000..6df14ec --- /dev/null +++ b/samples/test.yml @@ -0,0 +1,9 @@ +test: + image: "busybox" + command: ["sleep", "100"] + env: + - "AIRFIELD_USER=admin" + - "AIRFIELD_PASS=password" +# links: ["hipache-0.1:redis"] + ports: ['100'] + release_name: "test1" diff --git a/settings.yml b/settings.yml index 2cfbebc..4222ed1 100644 --- a/settings.yml +++ b/settings.yml @@ -1,5 +1,4 @@ default: hipaches: ['blue3.koffiedik.net:6379'] - daemons: ['http://blue3.koffiedik.net:4243'] - base_domain: ['tea.project.io'] + daemons: ['http://localhost:4243'] use_ssh: False diff --git a/tests/integration_test.py b/tests/integration_test.py index 4c50f0a..3ae6467 100644 --- a/tests/integration_test.py +++ b/tests/integration_test.py @@ -76,8 +76,20 @@ def runTest(self): self.assertIn(status, acceptedValues) +class TestRunningStatus(BaseTestCase): + def runTest(self): + self.application.create_containers() + create_results = self.application.start_containers() + res = self.application.get_status() + + acceptedValues = ['stopped', 'running', 'doesnotexist'] + for status in res: + self.assertIn(status, acceptedValues) + + class TestPullContainer(BaseTestCase): def runTest(self): + login = self.application.login_registry() results = self.application.pull_image() for result in results: self.assertNotIn("Authentication is required", result) diff --git a/tests/settings.yml b/tests/settings.yml index c3200f6..479017c 100644 --- a/tests/settings.yml +++ b/tests/settings.yml @@ -1,7 +1,6 @@ default: hipaches: ['blue4.koffiedik.net:6379'] - daemons: ['blue4.koffiedik.net:4243'] + daemons: ['localhost:4243'] ssh_user: "docker" - base_domain: ['tea.project.io'] - use_ssh: True + use_ssh: False registry_login: "$REGISTRY_USER:$REGISTRY_PASS:$REGISTRY_EMAIL"