legacy_test.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. import unittest
  2. from mock import Mock
  3. from docker.errors import APIError
  4. from compose import legacy
  5. from compose.project import Project
  6. from .testcases import DockerClientTestCase
  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_no_labels(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. containers = list(legacy.get_legacy_containers(
  68. client, "composetest", ["web"]))
  69. self.assertEqual(len(containers), 1)
  70. class LegacyTestCase(DockerClientTestCase):
  71. def setUp(self):
  72. super(LegacyTestCase, self).setUp()
  73. self.containers = []
  74. db = self.create_service('db')
  75. web = self.create_service('web', links=[(db, 'db')])
  76. nginx = self.create_service('nginx', links=[(web, 'web')])
  77. self.services = [db, web, nginx]
  78. self.project = Project('composetest', self.services, self.client)
  79. # Create a legacy container for each service
  80. for service in self.services:
  81. service.ensure_image_exists()
  82. container = self.client.create_container(
  83. name='{}_{}_1'.format(self.project.name, service.name),
  84. **service.options
  85. )
  86. self.client.start(container)
  87. self.containers.append(container)
  88. # Create a single one-off legacy container
  89. self.containers.append(self.client.create_container(
  90. name='{}_{}_run_1'.format(self.project.name, db.name),
  91. **self.services[0].options
  92. ))
  93. def tearDown(self):
  94. super(LegacyTestCase, self).tearDown()
  95. for container in self.containers:
  96. try:
  97. self.client.kill(container)
  98. except APIError:
  99. pass
  100. try:
  101. self.client.remove_container(container)
  102. except APIError:
  103. pass
  104. def get_legacy_containers(self, **kwargs):
  105. return legacy.get_legacy_containers(
  106. self.client,
  107. self.project.name,
  108. [s.name for s in self.services],
  109. **kwargs
  110. )
  111. def test_get_legacy_container_names(self):
  112. self.assertEqual(len(self.get_legacy_containers()), len(self.services))
  113. def test_get_legacy_container_names_one_off(self):
  114. self.assertEqual(len(self.get_legacy_containers(one_off=True)), 1)
  115. def test_migration_to_labels(self):
  116. # Trying to get the container list raises an exception
  117. with self.assertRaises(legacy.LegacyContainersError) as cm:
  118. self.project.containers(stopped=True)
  119. self.assertEqual(
  120. set(cm.exception.names),
  121. set(['composetest_db_1', 'composetest_web_1', 'composetest_nginx_1']),
  122. )
  123. self.assertEqual(
  124. set(cm.exception.one_off_names),
  125. set(['composetest_db_run_1']),
  126. )
  127. # Migrate the containers
  128. legacy.migrate_project_to_labels(self.project)
  129. # Getting the list no longer raises an exception
  130. containers = self.project.containers(stopped=True)
  131. self.assertEqual(len(containers), len(self.services))
  132. def test_migration_one_off(self):
  133. # We've already migrated
  134. legacy.migrate_project_to_labels(self.project)
  135. # Trying to create a one-off container results in a Docker API error
  136. with self.assertRaises(APIError) as cm:
  137. self.project.get_service('db').create_container(one_off=True)
  138. # Checking for legacy one-off containers raises an exception
  139. with self.assertRaises(legacy.LegacyOneOffContainersError) as cm:
  140. legacy.check_for_legacy_containers(
  141. self.client,
  142. self.project.name,
  143. ['db'],
  144. allow_one_off=False,
  145. )
  146. self.assertEqual(
  147. set(cm.exception.one_off_names),
  148. set(['composetest_db_run_1']),
  149. )
  150. # Remove the old one-off container
  151. c = self.client.inspect_container('composetest_db_run_1')
  152. self.client.remove_container(c)
  153. # Checking no longer raises an exception
  154. legacy.check_for_legacy_containers(
  155. self.client,
  156. self.project.name,
  157. ['db'],
  158. allow_one_off=False,
  159. )
  160. # Creating a one-off container no longer results in an API error
  161. self.project.get_service('db').create_container(one_off=True)
  162. self.assertIsInstance(self.client.inspect_container('composetest_db_run_1'), dict)