1
0

docker_client_test.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. from __future__ import absolute_import
  2. from __future__ import unicode_literals
  3. import os
  4. import platform
  5. import ssl
  6. import docker
  7. import pytest
  8. import compose
  9. from compose.cli import errors
  10. from compose.cli.docker_client import docker_client
  11. from compose.cli.docker_client import get_tls_version
  12. from compose.cli.docker_client import tls_config_from_options
  13. from tests import mock
  14. from tests import unittest
  15. class DockerClientTestCase(unittest.TestCase):
  16. def test_docker_client_no_home(self):
  17. with mock.patch.dict(os.environ):
  18. del os.environ['HOME']
  19. docker_client(os.environ)
  20. @mock.patch.dict(os.environ)
  21. def test_docker_client_with_custom_timeout(self):
  22. os.environ['COMPOSE_HTTP_TIMEOUT'] = '123'
  23. client = docker_client(os.environ)
  24. assert client.timeout == 123
  25. @mock.patch.dict(os.environ)
  26. def test_custom_timeout_error(self):
  27. os.environ['COMPOSE_HTTP_TIMEOUT'] = '123'
  28. client = docker_client(os.environ)
  29. with mock.patch('compose.cli.errors.log') as fake_log:
  30. with pytest.raises(errors.ConnectionError):
  31. with errors.handle_connection_errors(client):
  32. raise errors.RequestsConnectionError(
  33. errors.ReadTimeoutError(None, None, None))
  34. assert fake_log.error.call_count == 1
  35. assert '123' in fake_log.error.call_args[0][0]
  36. with mock.patch('compose.cli.errors.log') as fake_log:
  37. with pytest.raises(errors.ConnectionError):
  38. with errors.handle_connection_errors(client):
  39. raise errors.ReadTimeout()
  40. assert fake_log.error.call_count == 1
  41. assert '123' in fake_log.error.call_args[0][0]
  42. def test_user_agent(self):
  43. client = docker_client(os.environ)
  44. expected = "docker-compose/{0} docker-py/{1} {2}/{3}".format(
  45. compose.__version__,
  46. docker.__version__,
  47. platform.system(),
  48. platform.release()
  49. )
  50. assert client.headers['User-Agent'] == expected
  51. class TLSConfigTestCase(unittest.TestCase):
  52. ca_cert = 'tests/fixtures/tls/ca.pem'
  53. client_cert = 'tests/fixtures/tls/cert.pem'
  54. key = 'tests/fixtures/tls/key.key'
  55. def test_simple_tls(self):
  56. options = {'--tls': True}
  57. result = tls_config_from_options(options)
  58. assert result is True
  59. def test_tls_ca_cert(self):
  60. options = {
  61. '--tlscacert': self.ca_cert, '--tlsverify': True
  62. }
  63. result = tls_config_from_options(options)
  64. assert isinstance(result, docker.tls.TLSConfig)
  65. assert result.ca_cert == options['--tlscacert']
  66. assert result.verify is True
  67. def test_tls_ca_cert_explicit(self):
  68. options = {
  69. '--tlscacert': self.ca_cert, '--tls': True,
  70. '--tlsverify': True
  71. }
  72. result = tls_config_from_options(options)
  73. assert isinstance(result, docker.tls.TLSConfig)
  74. assert result.ca_cert == options['--tlscacert']
  75. assert result.verify is True
  76. def test_tls_client_cert(self):
  77. options = {
  78. '--tlscert': self.client_cert, '--tlskey': self.key
  79. }
  80. result = tls_config_from_options(options)
  81. assert isinstance(result, docker.tls.TLSConfig)
  82. assert result.cert == (options['--tlscert'], options['--tlskey'])
  83. def test_tls_client_cert_explicit(self):
  84. options = {
  85. '--tlscert': self.client_cert, '--tlskey': self.key,
  86. '--tls': True
  87. }
  88. result = tls_config_from_options(options)
  89. assert isinstance(result, docker.tls.TLSConfig)
  90. assert result.cert == (options['--tlscert'], options['--tlskey'])
  91. def test_tls_client_and_ca(self):
  92. options = {
  93. '--tlscert': self.client_cert, '--tlskey': self.key,
  94. '--tlsverify': True, '--tlscacert': self.ca_cert
  95. }
  96. result = tls_config_from_options(options)
  97. assert isinstance(result, docker.tls.TLSConfig)
  98. assert result.cert == (options['--tlscert'], options['--tlskey'])
  99. assert result.ca_cert == options['--tlscacert']
  100. assert result.verify is True
  101. def test_tls_client_and_ca_explicit(self):
  102. options = {
  103. '--tlscert': self.client_cert, '--tlskey': self.key,
  104. '--tlsverify': True, '--tlscacert': self.ca_cert,
  105. '--tls': True
  106. }
  107. result = tls_config_from_options(options)
  108. assert isinstance(result, docker.tls.TLSConfig)
  109. assert result.cert == (options['--tlscert'], options['--tlskey'])
  110. assert result.ca_cert == options['--tlscacert']
  111. assert result.verify is True
  112. def test_tls_client_missing_key(self):
  113. options = {'--tlscert': self.client_cert}
  114. with pytest.raises(docker.errors.TLSParameterError):
  115. tls_config_from_options(options)
  116. options = {'--tlskey': self.key}
  117. with pytest.raises(docker.errors.TLSParameterError):
  118. tls_config_from_options(options)
  119. def test_assert_hostname_explicit_skip(self):
  120. options = {'--tlscacert': self.ca_cert, '--skip-hostname-check': True}
  121. result = tls_config_from_options(options)
  122. assert isinstance(result, docker.tls.TLSConfig)
  123. assert result.assert_hostname is False
  124. def test_tls_client_and_ca_quoted_paths(self):
  125. options = {
  126. '--tlscacert': '"{0}"'.format(self.ca_cert),
  127. '--tlscert': '"{0}"'.format(self.client_cert),
  128. '--tlskey': '"{0}"'.format(self.key),
  129. '--tlsverify': True
  130. }
  131. result = tls_config_from_options(options)
  132. assert isinstance(result, docker.tls.TLSConfig)
  133. assert result.cert == (self.client_cert, self.key)
  134. assert result.ca_cert == self.ca_cert
  135. assert result.verify is True
  136. def test_tls_simple_with_tls_version(self):
  137. tls_version = 'TLSv1'
  138. options = {'--tls': True}
  139. environment = {'COMPOSE_TLS_VERSION': tls_version}
  140. result = tls_config_from_options(options, environment)
  141. assert isinstance(result, docker.tls.TLSConfig)
  142. assert result.ssl_version == ssl.PROTOCOL_TLSv1
  143. class TestGetTlsVersion(object):
  144. def test_get_tls_version_default(self):
  145. environment = {}
  146. assert get_tls_version(environment) is None
  147. @pytest.mark.skipif(not hasattr(ssl, 'PROTOCOL_TLSv1_2'), reason='TLS v1.2 unsupported')
  148. def test_get_tls_version_upgrade(self):
  149. environment = {'COMPOSE_TLS_VERSION': 'TLSv1_2'}
  150. assert get_tls_version(environment) == ssl.PROTOCOL_TLSv1_2
  151. def test_get_tls_version_unavailable(self):
  152. environment = {'COMPOSE_TLS_VERSION': 'TLSv5_5'}
  153. with mock.patch('compose.cli.docker_client.log') as mock_log:
  154. tls_version = get_tls_version(environment)
  155. mock_log.warn.assert_called_once_with(mock.ANY)
  156. assert tls_version is None