Compare commits

..

11 Commits
0.2.1 ... 0.2.2

Author SHA1 Message Date
Ben Firshman
d368e2fca9 Ship 0.2.2 2014-02-17 21:37:31 +00:00
Ben Firshman
b9c8e3e057 Fix scale not binding ports 2014-02-17 21:33:05 +00:00
Ben Firshman
5d4210ceb3 Fix tests when there is an image with int tag 2014-02-17 21:32:48 +00:00
Ben Firshman
4a6897ef3b Merge pull request #91 from barnybug/master
Implement topological sort using Cormen/Tarjan algorithm to handle a->b->c dependencies and detect a->b->c->a cycles.
2014-02-12 19:39:08 +00:00
Aanand Prasad
fbff8983e4 Merge pull request #83 from dustinlacewell/print-logs-during-attach
Tell fig up to print logs before attaching
2014-02-12 11:35:24 -08:00
Barnaby Gray
6431d52a2e Implement topological sort using Cormen/Tarjan algorithm to handle a->b->c dependencies and detect a->b->c->a cycles. 2014-02-12 09:09:55 +00:00
Aanand Prasad
7faba11245 Merge pull request #87 from orchardup/stop-projects-in-reverse-order-to-starting
Stop projects in reverse order to starting
2014-02-09 16:22:05 -08:00
Ben Firshman
4723345473 Stop projects in reverse order to starting 2014-02-09 16:01:13 -08:00
Ben Firshman
b310516ba7 Merge pull request #86 from orchardup/update-to-docker-0.8.0
Test Docker 0.8.0 on Travis
2014-02-08 03:41:03 +00:00
Ben Firshman
049a10136c Test Docker 0.8.0 on Travis 2014-02-07 10:35:18 -08:00
Dustin Lacewell
511a9beede Tell fig up to print logs before attaching 2014-02-05 17:19:18 -08:00
10 changed files with 95 additions and 31 deletions

View File

@@ -4,6 +4,9 @@ python:
- '2.7'
- '3.2'
- '3.3'
env:
- DOCKER_VERSION=0.7.6
- DOCKER_VERSION=0.8.0
matrix:
allow_failures:
- python: '3.2'

View File

@@ -1,6 +1,16 @@
Change log
==========
0.2.2 (2014-02-17)
------------------
- Resolve dependencies using Cormen/Tarjan topological sort
- Fix `fig up` not printing log output
- Stop containers in reverse order to starting
- Fix scale command not binding ports
Thanks to @barnybug and @dustinlacewell for their work on this release.
0.2.1 (2014-02-04)
------------------

View File

@@ -1,4 +1,4 @@
from __future__ import unicode_literals
from .service import Service
__version__ = '0.2.1'
__version__ = '0.2.2'

View File

@@ -289,7 +289,7 @@ class TopLevelCommand(Command):
if not detached:
to_attach = [c for (s, c) in new]
print("Attaching to", list_containers(to_attach))
log_printer = LogPrinter(to_attach)
log_printer = LogPrinter(to_attach, attach_params={"logs": True})
for (service, container) in new:
service.start_container(container)

View File

@@ -7,31 +7,30 @@ log = logging.getLogger(__name__)
def sort_service_dicts(services):
# Get all services that are dependant on another.
dependent_services = [s for s in services if s.get('links')]
flatten_links = sum([s['links'] for s in dependent_services], [])
# Get all services that are not linked to and don't link to others.
non_dependent_sevices = [s for s in services if s['name'] not in flatten_links and not s.get('links')]
# Topological sort (Cormen/Tarjan algorithm).
unmarked = services[:]
temporary_marked = set()
sorted_services = []
# Topological sort.
while dependent_services:
n = dependent_services.pop()
# Check if a service is dependent on itself, if so raise an error.
if n['name'] in n.get('links', []):
raise DependencyError('A service can not link to itself: %s' % n['name'])
sorted_services.append(n)
for l in n['links']:
# Get the linked service.
linked_service = next(s for s in services if l == s['name'])
# Check that there isn't a circular import between services.
if n['name'] in linked_service.get('links', []):
raise DependencyError('Circular import between %s and %s' % (n['name'], linked_service['name']))
# Check the linked service has no links and is not already in the
# sorted service list.
if not linked_service.get('links') and linked_service not in sorted_services:
sorted_services.insert(0, linked_service)
return non_dependent_sevices + sorted_services
def visit(n):
if n['name'] in temporary_marked:
if n['name'] in n.get('links', []):
raise DependencyError('A service can not link to itself: %s' % n['name'])
else:
raise DependencyError('Circular import between %s' % ' and '.join(temporary_marked))
if n in unmarked:
temporary_marked.add(n['name'])
dependents = [m for m in services if n['name'] in m.get('links', [])]
for m in dependents:
visit(m)
temporary_marked.remove(n['name'])
unmarked.remove(n)
sorted_services.insert(0, n)
while unmarked:
visit(unmarked[-1])
return sorted_services
class Project(object):
"""
@@ -116,11 +115,11 @@ class Project(object):
service.start(**options)
def stop(self, service_names=None, **options):
for service in self.get_services(service_names):
for service in reversed(self.get_services(service_names)):
service.stop(**options)
def kill(self, service_names=None, **options):
for service in self.get_services(service_names):
for service in reversed(self.get_services(service_names)):
service.kill(**options)
def build(self, service_names=None, **options):
@@ -156,4 +155,4 @@ class DependencyError(Exception):
self.msg = msg
def __str__(self):
return self.msg
return self.msg

View File

@@ -111,7 +111,7 @@ class Service(object):
while len(running_containers) < desired_num:
c = stopped_containers.pop(0)
log.info("Starting %s..." % c.name)
c.start()
self.start_container(c)
running_containers.append(c)

View File

@@ -7,7 +7,7 @@ sudo sh -c "echo deb http://get.docker.io/ubuntu docker main > /etc/apt/sources.
sudo apt-get update
echo exit 101 | sudo tee /usr/sbin/policy-rc.d
sudo chmod +x /usr/sbin/policy-rc.d
sudo apt-get install -qy slirp lxc lxc-docker-0.7.5
sudo apt-get install -qy slirp lxc lxc-docker-$DOCKER_VERSION
git clone git://github.com/jpetazzo/sekexe
python setup.py install
pip install -r requirements-dev.txt

View File

@@ -229,5 +229,12 @@ class ServiceTest(DockerClientTestCase):
service = self.create_service('web', ports=['8000:8000'])
self.assertRaises(CannotBeScaledError, lambda: service.scale(1))
def test_scale_sets_ports(self):
service = self.create_service('web', ports=['8000'])
service.scale(2)
containers = service.containers()
self.assertEqual(len(containers), 2)
for container in containers:
self.assertEqual(list(container.inspect()['HostConfig']['PortBindings'].keys()), ['8000/tcp'])

View File

@@ -44,6 +44,27 @@ class SortServiceTest(unittest.TestCase):
self.assertEqual(sorted_services[1]['name'], 'postgres')
self.assertEqual(sorted_services[2]['name'], 'web')
def test_sort_service_dicts_3(self):
services = [
{
'name': 'child'
},
{
'name': 'parent',
'links': ['child']
},
{
'links': ['parent'],
'name': 'grandparent'
},
]
sorted_services = sort_service_dicts(services)
self.assertEqual(len(sorted_services), 3)
self.assertEqual(sorted_services[0]['name'], 'child')
self.assertEqual(sorted_services[1]['name'], 'parent')
self.assertEqual(sorted_services[2]['name'], 'grandparent')
def test_sort_service_dicts_circular_imports(self):
services = [
{
@@ -87,6 +108,30 @@ class SortServiceTest(unittest.TestCase):
else:
self.fail('Should have thrown an DependencyError')
def test_sort_service_dicts_circular_imports_3(self):
services = [
{
'links': ['b'],
'name': 'a'
},
{
'name': 'b',
'links': ['c']
},
{
'name': 'c',
'links': ['a']
}
]
try:
sort_service_dicts(services)
except DependencyError as e:
self.assertIn('a', e.msg)
self.assertIn('b', e.msg)
else:
self.fail('Should have thrown an DependencyError')
def test_sort_service_dicts_self_imports(self):
services = [
{

View File

@@ -18,7 +18,7 @@ class DockerClientTestCase(unittest.TestCase):
self.client.kill(c['Id'])
self.client.remove_container(c['Id'])
for i in self.client.images():
if 'figtest' in i['Tag']:
if isinstance(i['Tag'], basestring) and 'figtest' in i['Tag']:
self.client.remove_image(i)
def create_service(self, name, **kwargs):