legacy_test.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. import unittest
  2. from docker.errors import APIError
  3. from mock import Mock
  4. from .testcases import DockerClientTestCase
  5. from compose import legacy
  6. from compose.project import Project
  7. class UtilitiesTestCase(unittest.TestCase):
  8. def test_has_container(self):
  9. self.assertTrue(
  10. legacy.has_container("composetest", "web", "composetest_web_1", one_off=False),
  11. )
  12. self.assertFalse(
  13. legacy.has_container("composetest", "web", "composetest_web_run_1", one_off=False),
  14. )
  15. def test_has_container_one_off(self):
  16. self.assertFalse(
  17. legacy.has_container("composetest", "web", "composetest_web_1", one_off=True),
  18. )
  19. self.assertTrue(
  20. legacy.has_container("composetest", "web", "composetest_web_run_1", one_off=True),
  21. )
  22. def test_has_container_different_project(self):
  23. self.assertFalse(
  24. legacy.has_container("composetest", "web", "otherapp_web_1", one_off=False),
  25. )
  26. self.assertFalse(
  27. legacy.has_container("composetest", "web", "otherapp_web_run_1", one_off=True),
  28. )
  29. def test_has_container_different_service(self):
  30. self.assertFalse(
  31. legacy.has_container("composetest", "web", "composetest_db_1", one_off=False),
  32. )
  33. self.assertFalse(
  34. legacy.has_container("composetest", "web", "composetest_db_run_1", one_off=True),
  35. )
  36. def test_is_valid_name(self):
  37. self.assertTrue(
  38. legacy.is_valid_name("composetest_web_1", one_off=False),
  39. )
  40. self.assertFalse(
  41. legacy.is_valid_name("composetest_web_run_1", one_off=False),
  42. )
  43. def test_is_valid_name_one_off(self):
  44. self.assertFalse(
  45. legacy.is_valid_name("composetest_web_1", one_off=True),
  46. )
  47. self.assertTrue(
  48. legacy.is_valid_name("composetest_web_run_1", one_off=True),
  49. )
  50. def test_is_valid_name_invalid(self):
  51. self.assertFalse(
  52. legacy.is_valid_name("foo"),
  53. )
  54. self.assertFalse(
  55. legacy.is_valid_name("composetest_web_lol_1", one_off=True),
  56. )
  57. def test_get_legacy_containers(self):
  58. client = Mock()
  59. client.containers.return_value = [
  60. {
  61. "Id": "abc123",
  62. "Image": "def456",
  63. "Name": "composetest_web_1",
  64. "Labels": None,
  65. },
  66. {
  67. "Id": "ghi789",
  68. "Image": "def456",
  69. "Name": None,
  70. "Labels": None,
  71. },
  72. {
  73. "Id": "jkl012",
  74. "Image": "def456",
  75. "Labels": None,
  76. },
  77. ]
  78. containers = legacy.get_legacy_containers(client, "composetest", ["web"])
  79. self.assertEqual(len(containers), 1)
  80. self.assertEqual(containers[0].id, 'abc123')
  81. class LegacyTestCase(DockerClientTestCase):
  82. def setUp(self):
  83. super(LegacyTestCase, self).setUp()
  84. self.containers = []
  85. db = self.create_service('db')
  86. web = self.create_service('web', links=[(db, 'db')])
  87. nginx = self.create_service('nginx', links=[(web, 'web')])
  88. self.services = [db, web, nginx]
  89. self.project = Project('composetest', self.services, self.client)
  90. # Create a legacy container for each service
  91. for service in self.services:
  92. service.ensure_image_exists()
  93. container = self.client.create_container(
  94. name='{}_{}_1'.format(self.project.name, service.name),
  95. **service.options
  96. )
  97. self.client.start(container)
  98. self.containers.append(container)
  99. # Create a single one-off legacy container
  100. self.containers.append(self.client.create_container(
  101. name='{}_{}_run_1'.format(self.project.name, db.name),
  102. **self.services[0].options
  103. ))
  104. def tearDown(self):
  105. super(LegacyTestCase, self).tearDown()
  106. for container in self.containers:
  107. try:
  108. self.client.kill(container)
  109. except APIError:
  110. pass
  111. try:
  112. self.client.remove_container(container)
  113. except APIError:
  114. pass
  115. def get_legacy_containers(self, **kwargs):
  116. return legacy.get_legacy_containers(
  117. self.client,
  118. self.project.name,
  119. [s.name for s in self.services],
  120. **kwargs
  121. )
  122. def test_get_legacy_container_names(self):
  123. self.assertEqual(len(self.get_legacy_containers()), len(self.services))
  124. def test_get_legacy_container_names_one_off(self):
  125. self.assertEqual(len(self.get_legacy_containers(one_off=True)), 1)
  126. def test_migration_to_labels(self):
  127. # Trying to get the container list raises an exception
  128. with self.assertRaises(legacy.LegacyContainersError) as cm:
  129. self.project.containers(stopped=True)
  130. self.assertEqual(
  131. set(cm.exception.names),
  132. set(['composetest_db_1', 'composetest_web_1', 'composetest_nginx_1']),
  133. )
  134. self.assertEqual(
  135. set(cm.exception.one_off_names),
  136. set(['composetest_db_run_1']),
  137. )
  138. # Migrate the containers
  139. legacy.migrate_project_to_labels(self.project)
  140. # Getting the list no longer raises an exception
  141. containers = self.project.containers(stopped=True)
  142. self.assertEqual(len(containers), len(self.services))
  143. def test_migration_one_off(self):
  144. # We've already migrated
  145. legacy.migrate_project_to_labels(self.project)
  146. # Trying to create a one-off container results in a Docker API error
  147. with self.assertRaises(APIError) as cm:
  148. self.project.get_service('db').create_container(one_off=True)
  149. # Checking for legacy one-off containers raises an exception
  150. with self.assertRaises(legacy.LegacyOneOffContainersError) as cm:
  151. legacy.check_for_legacy_containers(
  152. self.client,
  153. self.project.name,
  154. ['db'],
  155. allow_one_off=False,
  156. )
  157. self.assertEqual(
  158. set(cm.exception.one_off_names),
  159. set(['composetest_db_run_1']),
  160. )
  161. # Remove the old one-off container
  162. c = self.client.inspect_container('composetest_db_run_1')
  163. self.client.remove_container(c)
  164. # Checking no longer raises an exception
  165. legacy.check_for_legacy_containers(
  166. self.client,
  167. self.project.name,
  168. ['db'],
  169. allow_one_off=False,
  170. )
  171. # Creating a one-off container no longer results in an API error
  172. self.project.get_service('db').create_container(one_off=True)
  173. self.assertIsInstance(self.client.inspect_container('composetest_db_run_1'), dict)