service_test.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. from __future__ import unicode_literals
  2. from __future__ import absolute_import
  3. import os
  4. from .. import unittest
  5. import mock
  6. import docker
  7. from fig import Service
  8. from fig.service import (
  9. ConfigError,
  10. split_port,
  11. parse_volume_spec,
  12. build_volume_binding,
  13. )
  14. class ServiceTest(unittest.TestCase):
  15. def setUp(self):
  16. self.mock_client = mock.create_autospec(docker.Client)
  17. def test_name_validations(self):
  18. self.assertRaises(ConfigError, lambda: Service(name=''))
  19. self.assertRaises(ConfigError, lambda: Service(name=' '))
  20. self.assertRaises(ConfigError, lambda: Service(name='/'))
  21. self.assertRaises(ConfigError, lambda: Service(name='!'))
  22. self.assertRaises(ConfigError, lambda: Service(name='\xe2'))
  23. self.assertRaises(ConfigError, lambda: Service(name='_'))
  24. self.assertRaises(ConfigError, lambda: Service(name='____'))
  25. self.assertRaises(ConfigError, lambda: Service(name='foo_bar'))
  26. self.assertRaises(ConfigError, lambda: Service(name='__foo_bar__'))
  27. Service('a')
  28. Service('foo')
  29. def test_project_validation(self):
  30. self.assertRaises(ConfigError, lambda: Service(name='foo', project='_'))
  31. Service(name='foo', project='bar')
  32. def test_config_validation(self):
  33. self.assertRaises(ConfigError, lambda: Service(name='foo', port=['8000']))
  34. Service(name='foo', ports=['8000'])
  35. def test_split_port_with_host_ip(self):
  36. internal_port, external_port = split_port("127.0.0.1:1000:2000")
  37. self.assertEqual(internal_port, "2000")
  38. self.assertEqual(external_port, ("127.0.0.1", "1000"))
  39. def test_split_port_with_protocol(self):
  40. internal_port, external_port = split_port("127.0.0.1:1000:2000/udp")
  41. self.assertEqual(internal_port, "2000/udp")
  42. self.assertEqual(external_port, ("127.0.0.1", "1000"))
  43. def test_split_port_with_host_ip_no_port(self):
  44. internal_port, external_port = split_port("127.0.0.1::2000")
  45. self.assertEqual(internal_port, "2000")
  46. self.assertEqual(external_port, ("127.0.0.1", None))
  47. def test_split_port_with_host_port(self):
  48. internal_port, external_port = split_port("1000:2000")
  49. self.assertEqual(internal_port, "2000")
  50. self.assertEqual(external_port, "1000")
  51. def test_split_port_no_host_port(self):
  52. internal_port, external_port = split_port("2000")
  53. self.assertEqual(internal_port, "2000")
  54. self.assertEqual(external_port, None)
  55. def test_split_port_invalid(self):
  56. with self.assertRaises(ConfigError):
  57. split_port("0.0.0.0:1000:2000:tcp")
  58. def test_split_domainname_none(self):
  59. service = Service('foo', hostname='name', client=self.mock_client)
  60. self.mock_client.containers.return_value = []
  61. opts = service._get_container_create_options({})
  62. self.assertEqual(opts['hostname'], 'name', 'hostname')
  63. self.assertFalse('domainname' in opts, 'domainname')
  64. def test_split_domainname_fqdn(self):
  65. service = Service('foo',
  66. hostname='name.domain.tld',
  67. client=self.mock_client)
  68. self.mock_client.containers.return_value = []
  69. opts = service._get_container_create_options({})
  70. self.assertEqual(opts['hostname'], 'name', 'hostname')
  71. self.assertEqual(opts['domainname'], 'domain.tld', 'domainname')
  72. def test_split_domainname_both(self):
  73. service = Service('foo',
  74. hostname='name',
  75. domainname='domain.tld',
  76. client=self.mock_client)
  77. self.mock_client.containers.return_value = []
  78. opts = service._get_container_create_options({})
  79. self.assertEqual(opts['hostname'], 'name', 'hostname')
  80. self.assertEqual(opts['domainname'], 'domain.tld', 'domainname')
  81. def test_split_domainname_weird(self):
  82. service = Service('foo',
  83. hostname='name.sub',
  84. domainname='domain.tld',
  85. client=self.mock_client)
  86. self.mock_client.containers.return_value = []
  87. opts = service._get_container_create_options({})
  88. self.assertEqual(opts['hostname'], 'name.sub', 'hostname')
  89. self.assertEqual(opts['domainname'], 'domain.tld', 'domainname')
  90. def test_get_container_not_found(self):
  91. mock_client = mock.create_autospec(docker.Client)
  92. mock_client.containers.return_value = []
  93. service = Service('foo', client=mock_client)
  94. self.assertRaises(ValueError, service.get_container)
  95. @mock.patch('fig.service.Container', autospec=True)
  96. def test_get_container(self, mock_container_class):
  97. mock_client = mock.create_autospec(docker.Client)
  98. container_dict = dict(Name='default_foo_2')
  99. mock_client.containers.return_value = [container_dict]
  100. service = Service('foo', client=mock_client)
  101. container = service.get_container(number=2)
  102. self.assertEqual(container, mock_container_class.from_ps.return_value)
  103. mock_container_class.from_ps.assert_called_once_with(
  104. mock_client, container_dict)
  105. class ServiceVolumesTest(unittest.TestCase):
  106. def test_parse_volume_spec_only_one_path(self):
  107. spec = parse_volume_spec('/the/volume')
  108. self.assertEqual(spec, (None, '/the/volume', 'rw'))
  109. def test_parse_volume_spec_internal_and_external(self):
  110. spec = parse_volume_spec('external:interval')
  111. self.assertEqual(spec, ('external', 'interval', 'rw'))
  112. def test_parse_volume_spec_with_mode(self):
  113. spec = parse_volume_spec('external:interval:ro')
  114. self.assertEqual(spec, ('external', 'interval', 'ro'))
  115. def test_parse_volume_spec_too_many_parts(self):
  116. with self.assertRaises(ConfigError):
  117. parse_volume_spec('one:two:three:four')
  118. def test_parse_volume_bad_mode(self):
  119. with self.assertRaises(ConfigError):
  120. parse_volume_spec('one:two:notrw')
  121. def test_build_volume_binding(self):
  122. binding = build_volume_binding(parse_volume_spec('/outside:/inside'))
  123. self.assertEqual(
  124. binding,
  125. ('/outside', dict(bind='/inside', ro=False)))
  126. @mock.patch.dict(os.environ)
  127. def test_build_volume_binding_with_environ(self):
  128. os.environ['VOLUME_PATH'] = '/opt'
  129. binding = build_volume_binding(parse_volume_spec('${VOLUME_PATH}:/opt'))
  130. self.assertEqual(binding, ('/opt', dict(bind='/opt', ro=False)))
  131. @mock.patch.dict(os.environ)
  132. def test_building_volume_binding_with_home(self):
  133. os.environ['HOME'] = '/home/user'
  134. binding = build_volume_binding(parse_volume_spec('~:/home/user'))
  135. self.assertEqual(
  136. binding,
  137. ('/home/user', dict(bind='/home/user', ro=False)))