diff --git a/docker/api/client.py b/docker/api/client.py index de106c554..499a7c785 100644 --- a/docker/api/client.py +++ b/docker/api/client.py @@ -6,7 +6,6 @@ import requests import requests.adapters import requests.exceptions -import websocket from .. import auth from ..constants import (DEFAULT_NUM_POOLS, DEFAULT_NUM_POOLS_SSH, @@ -310,7 +309,16 @@ def _attach_websocket(self, container, params=None): return self._create_websocket_connection(full_url) def _create_websocket_connection(self, url): - return websocket.create_connection(url) + try: + import websocket + return websocket.create_connection(url) + except ImportError as ie: + raise DockerException( + 'The `websocket-client` library is required ' + 'for using websocket connections. ' + 'You can install the `docker` library ' + 'with the [websocket] extra to install it.' + ) from ie def _get_raw_response_socket(self, response): self._raise_for_status(response) diff --git a/setup.py b/setup.py index 34c2c2522..d63cbe0a1 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,6 @@ 'packaging >= 14.0', 'requests >= 2.26.0', 'urllib3 >= 1.26.0', - 'websocket-client >= 0.32.0', ] extras_require = { @@ -27,6 +26,9 @@ # Only required when connecting using the ssh:// protocol 'ssh': ['paramiko>=2.4.3'], + + # Only required when using websockets + 'websockets': ['websocket-client >= 1.3.0'], } with open('./test-requirements.txt') as test_reqs_txt: diff --git a/tests/integration/models_containers_test.py b/tests/integration/models_containers_test.py index 8fde851a6..219b9a4cb 100644 --- a/tests/integration/models_containers_test.py +++ b/tests/integration/models_containers_test.py @@ -157,7 +157,7 @@ def test_run_with_networking_config_with_undeclared_network(self): ), } - with pytest.raises(docker.errors.APIError) as e: + with pytest.raises(docker.errors.APIError): container = client.containers.run( 'alpine', 'echo hello world', network=net_name, networking_config=networking_config, diff --git a/tests/unit/models_containers_test.py b/tests/unit/models_containers_test.py index bd3092b67..05005815f 100644 --- a/tests/unit/models_containers_test.py +++ b/tests/unit/models_containers_test.py @@ -41,77 +41,73 @@ def test_create_container_args(self): ) } - create_kwargs = _create_container_args(dict( - image='alpine', - command='echo hello world', - blkio_weight_device=[{'Path': 'foo', 'Weight': 3}], - blkio_weight=2, - cap_add=['foo'], - cap_drop=['bar'], - cgroup_parent='foobar', - cgroupns='host', - cpu_period=1, - cpu_quota=2, - cpu_shares=5, - cpuset_cpus='0-3', - detach=False, - device_read_bps=[{'Path': 'foo', 'Rate': 3}], - device_read_iops=[{'Path': 'foo', 'Rate': 3}], - device_write_bps=[{'Path': 'foo', 'Rate': 3}], - device_write_iops=[{'Path': 'foo', 'Rate': 3}], - devices=['/dev/sda:/dev/xvda:rwm'], - dns=['8.8.8.8'], - domainname='example.com', - dns_opt=['foo'], - dns_search=['example.com'], - entrypoint='/bin/sh', - environment={'FOO': 'BAR'}, - extra_hosts={'foo': '1.2.3.4'}, - group_add=['blah'], - ipc_mode='foo', - kernel_memory=123, - labels={'key': 'value'}, - links={'foo': 'bar'}, - log_config={'Type': 'json-file', 'Config': {}}, - lxc_conf={'foo': 'bar'}, - healthcheck={'test': 'true'}, - hostname='somehost', - mac_address='abc123', - mem_limit=123, - mem_reservation=123, - mem_swappiness=2, - memswap_limit=456, - name='somename', - network_disabled=False, - network='foo', - networking_config=networking_config, - oom_kill_disable=True, - oom_score_adj=5, - pid_mode='host', - pids_limit=500, - platform='linux', - ports={ - 1111: 4567, - 2222: None - }, - privileged=True, - publish_all_ports=True, - read_only=True, - restart_policy={'Name': 'always'}, - security_opt=['blah'], - shm_size=123, - stdin_open=True, - stop_signal=9, - sysctls={'foo': 'bar'}, - tmpfs={'/blah': ''}, - tty=True, - ulimits=[{"Name": "nofile", "Soft": 1024, "Hard": 2048}], - user='bob', - userns_mode='host', - uts_mode='host', - version=DEFAULT_DOCKER_API_VERSION, - volume_driver='some_driver', - volumes=[ + create_kwargs = _create_container_args({ + 'image': 'alpine', + 'command': 'echo hello world', + 'blkio_weight_device': [{'Path': 'foo', 'Weight': 3}], + 'blkio_weight': 2, + 'cap_add': ['foo'], + 'cap_drop': ['bar'], + 'cgroup_parent': 'foobar', + 'cgroupns': 'host', + 'cpu_period': 1, + 'cpu_quota': 2, + 'cpu_shares': 5, + 'cpuset_cpus': '0-3', + 'detach': False, + 'device_read_bps': [{'Path': 'foo', 'Rate': 3}], + 'device_read_iops': [{'Path': 'foo', 'Rate': 3}], + 'device_write_bps': [{'Path': 'foo', 'Rate': 3}], + 'device_write_iops': [{'Path': 'foo', 'Rate': 3}], + 'devices': ['/dev/sda:/dev/xvda:rwm'], + 'dns': ['8.8.8.8'], + 'domainname': 'example.com', + 'dns_opt': ['foo'], + 'dns_search': ['example.com'], + 'entrypoint': '/bin/sh', + 'environment': {'FOO': 'BAR'}, + 'extra_hosts': {'foo': '1.2.3.4'}, + 'group_add': ['blah'], + 'ipc_mode': 'foo', + 'kernel_memory': 123, + 'labels': {'key': 'value'}, + 'links': {'foo': 'bar'}, + 'log_config': {'Type': 'json-file', 'Config': {}}, + 'lxc_conf': {'foo': 'bar'}, + 'healthcheck': {'test': 'true'}, + 'hostname': 'somehost', + 'mac_address': 'abc123', + 'mem_limit': 123, + 'mem_reservation': 123, + 'mem_swappiness': 2, + 'memswap_limit': 456, + 'name': 'somename', + 'network_disabled': False, + 'network': 'foo', + 'networking_config': networking_config, + 'oom_kill_disable': True, + 'oom_score_adj': 5, + 'pid_mode': 'host', + 'pids_limit': 500, + 'platform': 'linux', + 'ports': {1111: 4567, 2222: None}, + 'privileged': True, + 'publish_all_ports': True, + 'read_only': True, + 'restart_policy': {'Name': 'always'}, + 'security_opt': ['blah'], + 'shm_size': 123, + 'stdin_open': True, + 'stop_signal': 9, + 'sysctls': {'foo': 'bar'}, + 'tmpfs': {'/blah': ''}, + 'tty': True, + 'ulimits': [{"Name": "nofile", "Soft": 1024, "Hard": 2048}], + 'user': 'bob', + 'userns_mode': 'host', + 'uts_mode': 'host', + 'version': DEFAULT_DOCKER_API_VERSION, + 'volume_driver': 'some_driver', 'volumes': [ '/home/user1/:/mnt/vol2', '/var/www:/mnt/vol1:ro', 'volumename:/mnt/vol3r', @@ -119,18 +115,18 @@ def test_create_container_args(self): '/anothervolumewithnohostpath:ro', 'C:\\windows\\path:D:\\hello\\world:rw' ], - volumes_from=['container'], - working_dir='/code' - )) + 'volumes_from': ['container'], + 'working_dir': '/code', + }) - expected = dict( - image='alpine', - command='echo hello world', - domainname='example.com', - detach=False, - entrypoint='/bin/sh', - environment={'FOO': 'BAR'}, - host_config={ + expected = { + 'image': 'alpine', + 'command': 'echo hello world', + 'domainname': 'example.com', + 'detach': False, + 'entrypoint': '/bin/sh', + 'environment': {'FOO': 'BAR'}, + 'host_config': { 'Binds': [ '/home/user1/:/mnt/vol2', '/var/www:/mnt/vol1:ro', @@ -153,9 +149,13 @@ def test_create_container_args(self): 'CpuQuota': 2, 'CpuShares': 5, 'CpusetCpus': '0-3', - 'Devices': [{'PathOnHost': '/dev/sda', - 'CgroupPermissions': 'rwm', - 'PathInContainer': '/dev/xvda'}], + 'Devices': [ + { + 'PathOnHost': '/dev/sda', + 'CgroupPermissions': 'rwm', + 'PathInContainer': '/dev/xvda', + }, + ], 'Dns': ['8.8.8.8'], 'DnsOptions': ['foo'], 'DnsSearch': ['example.com'], @@ -187,28 +187,35 @@ def test_create_container_args(self): 'ShmSize': 123, 'Sysctls': {'foo': 'bar'}, 'Tmpfs': {'/blah': ''}, - 'Ulimits': [{"Name": "nofile", "Soft": 1024, "Hard": 2048}], + 'Ulimits': [ + {"Name": "nofile", "Soft": 1024, "Hard": 2048}, + ], 'UsernsMode': 'host', 'UTSMode': 'host', 'VolumeDriver': 'some_driver', 'VolumesFrom': ['container'], }, - healthcheck={'test': 'true'}, - hostname='somehost', - labels={'key': 'value'}, - mac_address='abc123', - name='somename', - network_disabled=False, - networking_config={'EndpointsConfig': { - 'foo': {'Aliases': ['test'], 'DriverOpts': {'key1': 'a'}}} + 'healthcheck': {'test': 'true'}, + 'hostname': 'somehost', + 'labels': {'key': 'value'}, + 'mac_address': 'abc123', + 'name': 'somename', + 'network_disabled': False, + 'networking_config': { + 'EndpointsConfig': { + 'foo': { + 'Aliases': ['test'], + 'DriverOpts': {'key1': 'a'}, + }, + } }, - platform='linux', - ports=[('1111', 'tcp'), ('2222', 'tcp')], - stdin_open=True, - stop_signal=9, - tty=True, - user='bob', - volumes=[ + 'platform': 'linux', + 'ports': [('1111', 'tcp'), ('2222', 'tcp')], + 'stdin_open': True, + 'stop_signal': 9, + 'tty': True, + 'user': 'bob', + 'volumes': [ '/mnt/vol2', '/mnt/vol1', '/mnt/vol3r', @@ -216,8 +223,8 @@ def test_create_container_args(self): '/anothervolumewithnohostpath', 'D:\\hello\\world' ], - working_dir='/code' - ) + 'working_dir': '/code', + } assert create_kwargs == expected