Do less work during integration testing.

Signed-off-by: Daniel Nephin <dnephin@gmail.com>
This commit is contained in:
Daniel Nephin 2014-08-24 14:55:38 -04:00
parent 6b221d5687
commit e0b0801e87
3 changed files with 34 additions and 30 deletions

View File

@ -1,11 +1,13 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from __future__ import absolute_import from __future__ import absolute_import
from collections import namedtuple from collections import namedtuple
from docker.errors import APIError
import logging import logging
import re import re
import os import os
import sys import sys
from docker.errors import APIError
from .container import Container from .container import Container
from .progress_stream import stream_output, StreamOutputError from .progress_stream import stream_output, StreamOutputError
@ -43,6 +45,9 @@ class ConfigError(ValueError):
VolumeSpec = namedtuple('VolumeSpec', 'external internal mode') VolumeSpec = namedtuple('VolumeSpec', 'external internal mode')
ServiceName = namedtuple('ServiceName', 'project service number')
class Service(object): class Service(object):
def __init__(self, name, client=None, project='default', links=None, volumes_from=None, **options): def __init__(self, name, client=None, project='default', links=None, volumes_from=None, **options):
if not re.match('^%s+$' % VALID_NAME_CHARS, name): if not re.match('^%s+$' % VALID_NAME_CHARS, name):
@ -185,8 +190,8 @@ class Service(object):
""" """
containers = self.containers(stopped=True) containers = self.containers(stopped=True)
if len(containers) == 0: if not containers:
log.info("Creating %s..." % self.next_container_name()) log.info("Creating %s..." % self._next_container_name(containers))
container = self.create_container(**override_options) container = self.create_container(**override_options)
self.start_container(container) self.start_container(container)
return [(None, container)] return [(None, container)]
@ -264,7 +269,7 @@ class Service(object):
containers = self.containers(stopped=True) containers = self.containers(stopped=True)
if not containers: if not containers:
log.info("Creating %s..." % self.next_container_name()) log.info("Creating %s..." % self._next_container_name(containers))
new_container = self.create_container() new_container = self.create_container()
return [self.start_container(new_container)] return [self.start_container(new_container)]
else: else:
@ -273,19 +278,15 @@ class Service(object):
def get_linked_names(self): def get_linked_names(self):
return [s.name for (s, _) in self.links] return [s.name for (s, _) in self.links]
def next_container_name(self, one_off=False): def _next_container_name(self, all_containers, one_off=False):
bits = [self.project, self.name] bits = [self.project, self.name]
if one_off: if one_off:
bits.append('run') bits.append('run')
return '_'.join(bits + [str(self.next_container_number(one_off=one_off))]) return '_'.join(bits + [str(self._next_container_number(all_containers))])
def next_container_number(self, one_off=False): def _next_container_number(self, all_containers):
numbers = [parse_name(c.name)[2] for c in self.containers(stopped=True, one_off=one_off)] numbers = [parse_name(c.name).number for c in all_containers]
return 1 if not numbers else max(numbers) + 1
if len(numbers) == 0:
return 1
else:
return max(numbers) + 1
def _get_links(self, link_to_self): def _get_links(self, link_to_self):
links = [] links = []
@ -319,7 +320,9 @@ class Service(object):
container_options = dict((k, self.options[k]) for k in DOCKER_CONFIG_KEYS if k in self.options) container_options = dict((k, self.options[k]) for k in DOCKER_CONFIG_KEYS if k in self.options)
container_options.update(override_options) container_options.update(override_options)
container_options['name'] = self.next_container_name(one_off) container_options['name'] = self._next_container_name(
self.containers(stopped=True, one_off=one_off),
one_off)
# If a qualified hostname was given, split it into an # If a qualified hostname was given, split it into an
# unqualified hostname and a domainname unless domainname # unqualified hostname and a domainname unless domainname
@ -424,10 +427,10 @@ def is_valid_name(name, one_off=False):
return match.group(3) is None return match.group(3) is None
def parse_name(name, one_off=False): def parse_name(name):
match = NAME_RE.match(name) match = NAME_RE.match(name)
(project, service_name, _, suffix) = match.groups() (project, service_name, _, suffix) = match.groups()
return (project, service_name, int(suffix)) return ServiceName(project, service_name, int(suffix))
def get_container_name(container): def get_container_name(container):

View File

@ -10,7 +10,6 @@ class DockerClientTestCase(unittest.TestCase):
@classmethod @classmethod
def setUpClass(cls): def setUpClass(cls):
cls.client = Client(docker_url()) cls.client = Client(docker_url())
cls.client.pull('busybox', tag='latest')
def setUp(self): def setUp(self):
for c in self.client.containers(all=True): for c in self.client.containers(all=True):

View File

@ -17,6 +17,10 @@ from fig.service import (
class ServiceTest(unittest.TestCase): class ServiceTest(unittest.TestCase):
def setUp(self):
self.mock_client = mock.create_autospec(docker.Client)
def test_name_validations(self): def test_name_validations(self):
self.assertRaises(ConfigError, lambda: Service(name='')) self.assertRaises(ConfigError, lambda: Service(name=''))
@ -70,29 +74,27 @@ class ServiceTest(unittest.TestCase):
split_port("0.0.0.0:1000:2000:tcp") split_port("0.0.0.0:1000:2000:tcp")
def test_split_domainname_none(self): def test_split_domainname_none(self):
service = Service('foo', service = Service('foo', hostname='name', client=self.mock_client)
hostname = 'name', self.mock_client.containers.return_value = []
)
service.next_container_name = lambda x: 'foo'
opts = service._get_container_create_options({}) opts = service._get_container_create_options({})
self.assertEqual(opts['hostname'], 'name', 'hostname') self.assertEqual(opts['hostname'], 'name', 'hostname')
self.assertFalse('domainname' in opts, 'domainname') self.assertFalse('domainname' in opts, 'domainname')
def test_split_domainname_fqdn(self): def test_split_domainname_fqdn(self):
service = Service('foo', service = Service('foo',
hostname = 'name.domain.tld', hostname='name.domain.tld',
) client=self.mock_client)
service.next_container_name = lambda x: 'foo' self.mock_client.containers.return_value = []
opts = service._get_container_create_options({}) opts = service._get_container_create_options({})
self.assertEqual(opts['hostname'], 'name', 'hostname') self.assertEqual(opts['hostname'], 'name', 'hostname')
self.assertEqual(opts['domainname'], 'domain.tld', 'domainname') self.assertEqual(opts['domainname'], 'domain.tld', 'domainname')
def test_split_domainname_both(self): def test_split_domainname_both(self):
service = Service('foo', service = Service('foo',
hostname = 'name', hostname='name',
domainname = 'domain.tld', domainname='domain.tld',
) client=self.mock_client)
service.next_container_name = lambda x: 'foo' self.mock_client.containers.return_value = []
opts = service._get_container_create_options({}) opts = service._get_container_create_options({})
self.assertEqual(opts['hostname'], 'name', 'hostname') self.assertEqual(opts['hostname'], 'name', 'hostname')
self.assertEqual(opts['domainname'], 'domain.tld', 'domainname') self.assertEqual(opts['domainname'], 'domain.tld', 'domainname')
@ -101,8 +103,8 @@ class ServiceTest(unittest.TestCase):
service = Service('foo', service = Service('foo',
hostname='name.sub', hostname='name.sub',
domainname='domain.tld', domainname='domain.tld',
) client=self.mock_client)
service.next_container_name = lambda x: 'foo' self.mock_client.containers.return_value = []
opts = service._get_container_create_options({}) opts = service._get_container_create_options({})
self.assertEqual(opts['hostname'], 'name.sub', 'hostname') self.assertEqual(opts['hostname'], 'name.sub', 'hostname')
self.assertEqual(opts['domainname'], 'domain.tld', 'domainname') self.assertEqual(opts['domainname'], 'domain.tld', 'domainname')