Browse Source

Merge pull request #851 from aanand/swarm-names

Handle Swarm-style prefixed container names
Aanand Prasad 10 years ago
parent
commit
7be8b4c06d
4 changed files with 58 additions and 17 deletions
  1. 12 3
      fig/container.py
  2. 1 13
      fig/service.py
  3. 13 1
      tests/unit/container_test.py
  4. 32 0
      tests/unit/service_test.py

+ 12 - 3
fig/container.py

@@ -22,10 +22,8 @@ class Container(object):
         new_dictionary = {
             'Id': dictionary['Id'],
             'Image': dictionary['Image'],
+            'Name': '/' + get_container_name(dictionary),
         }
-        for name in dictionary.get('Names', []):
-            if len(name.split('/')) == 2:
-                new_dictionary['Name'] = name
         return cls(client, new_dictionary, **kwargs)
 
     @classmethod
@@ -170,3 +168,14 @@ class Container(object):
         if type(self) != type(other):
             return False
         return self.id == other.id
+
+
+def get_container_name(container):
+    if not container.get('Name') and not container.get('Names'):
+        return None
+    # inspect
+    if 'Name' in container:
+        return container['Name']
+    # ps
+    shortest_name = min(container['Names'], key=lambda n: len(n.split('/')))
+    return shortest_name.split('/')[-1]

+ 1 - 13
fig/service.py

@@ -9,7 +9,7 @@ import sys
 
 from docker.errors import APIError
 
-from .container import Container
+from .container import Container, get_container_name
 from .progress_stream import stream_output, StreamOutputError
 
 log = logging.getLogger(__name__)
@@ -538,18 +538,6 @@ def parse_name(name):
     return ServiceName(project, service_name, int(suffix))
 
 
-def get_container_name(container):
-    if not container.get('Name') and not container.get('Names'):
-        return None
-    # inspect
-    if 'Name' in container:
-        return container['Name']
-    # ps
-    for name in container['Names']:
-        if len(name.split('/')) == 2:
-            return name[1:]
-
-
 def parse_restart_spec(restart_config):
     if not restart_config:
         return None

+ 13 - 1
tests/unit/container_test.py

@@ -20,7 +20,7 @@ class ContainerTest(unittest.TestCase):
             "Ports": None,
             "SizeRw": 0,
             "SizeRootFs": 0,
-            "Names": ["/figtest_db_1"],
+            "Names": ["/figtest_db_1", "/figtest_web_1/db"],
             "NetworkSettings": {
                 "Ports": {},
             },
@@ -36,6 +36,18 @@ class ContainerTest(unittest.TestCase):
             "Name": "/figtest_db_1",
         })
 
+    def test_from_ps_prefixed(self):
+        self.container_dict['Names'] = ['/swarm-host-1' + n for n in self.container_dict['Names']]
+
+        container = Container.from_ps(None,
+                                      self.container_dict,
+                                      has_been_inspected=True)
+        self.assertEqual(container.dictionary, {
+            "Id": "abc",
+            "Image":"busybox:latest",
+            "Name": "/figtest_db_1",
+        })
+
     def test_environment(self):
         container = Container(None, {
             'Id': 'abc',

+ 32 - 0
tests/unit/service_test.py

@@ -17,6 +17,7 @@ from fig.service import (
     parse_volume_spec,
     build_volume_binding,
     APIError,
+    get_container_name,
     parse_repository_tag,
 )
 
@@ -49,6 +50,37 @@ class ServiceTest(unittest.TestCase):
         self.assertRaises(ConfigError, lambda: Service(name='foo', port=['8000']))
         Service(name='foo', ports=['8000'])
 
+    def test_get_container_name(self):
+        self.assertIsNone(get_container_name({}))
+        self.assertEqual(get_container_name({'Name': 'myproject_db_1'}), 'myproject_db_1')
+        self.assertEqual(get_container_name({'Names': ['/myproject_db_1', '/myproject_web_1/db']}), 'myproject_db_1')
+        self.assertEqual(get_container_name({'Names': ['/swarm-host-1/myproject_db_1', '/swarm-host-1/myproject_web_1/db']}), 'myproject_db_1')
+
+    def test_containers(self):
+        service = Service('db', client=self.mock_client, project='myproject')
+
+        self.mock_client.containers.return_value = []
+        self.assertEqual(service.containers(), [])
+
+        self.mock_client.containers.return_value = [
+            {'Image': 'busybox', 'Id': 'OUT_1', 'Names': ['/myproject', '/foo/bar']},
+            {'Image': 'busybox', 'Id': 'OUT_2', 'Names': ['/myproject_db']},
+            {'Image': 'busybox', 'Id': 'OUT_3', 'Names': ['/db_1']},
+            {'Image': 'busybox', 'Id': 'IN_1', 'Names': ['/myproject_db_1', '/myproject_web_1/db']},
+        ]
+        self.assertEqual([c.id for c in service.containers()], ['IN_1'])
+
+    def test_containers_prefixed(self):
+        service = Service('db', client=self.mock_client, project='myproject')
+
+        self.mock_client.containers.return_value = [
+            {'Image': 'busybox', 'Id': 'OUT_1', 'Names': ['/swarm-host-1/myproject', '/swarm-host-1/foo/bar']},
+            {'Image': 'busybox', 'Id': 'OUT_2', 'Names': ['/swarm-host-1/myproject_db']},
+            {'Image': 'busybox', 'Id': 'OUT_3', 'Names': ['/swarm-host-1/db_1']},
+            {'Image': 'busybox', 'Id': 'IN_1', 'Names': ['/swarm-host-1/myproject_db_1', '/swarm-host-1/myproject_web_1/db']},
+        ]
+        self.assertEqual([c.id for c in service.containers()], ['IN_1'])
+
     def test_get_volumes_from_container(self):
         container_id = 'aabbccddee'
         service = Service(