mirror of https://github.com/docker/docker-py.git
Remove support to pre python 3.6
Signed-off-by: Ulysses Souza <ulyssessouza@gmail.com>
This commit is contained in:
parent
31775a1532
commit
c8fba210a2
|
@ -8,7 +8,7 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
max-parallel: 1
|
max-parallel: 1
|
||||||
matrix:
|
matrix:
|
||||||
python-version: [2.7, 3.5, 3.6, 3.7, 3.8, 3.9]
|
python-version: [3.6, 3.7, 3.8, 3.9]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
@ -18,8 +18,8 @@ jobs:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python3 -m pip install --upgrade pip
|
||||||
pip install -r test-requirements.txt -r requirements.txt
|
pip3 install -r test-requirements.txt -r requirements.txt
|
||||||
- name: Test with pytest
|
- name: Test with pytest
|
||||||
run: |
|
run: |
|
||||||
docker logout
|
docker logout
|
||||||
|
|
|
@ -4,7 +4,7 @@ sphinx:
|
||||||
configuration: docs/conf.py
|
configuration: docs/conf.py
|
||||||
|
|
||||||
python:
|
python:
|
||||||
version: 3.5
|
version: 3.6
|
||||||
install:
|
install:
|
||||||
- requirements: docs-requirements.txt
|
- requirements: docs-requirements.txt
|
||||||
- requirements: requirements.txt
|
- requirements: requirements.txt
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
ARG PYTHON_VERSION=2.7
|
ARG PYTHON_VERSION=3.7
|
||||||
|
|
||||||
FROM python:${PYTHON_VERSION}
|
FROM python:${PYTHON_VERSION}
|
||||||
|
|
||||||
# Add SSH keys and set permissions
|
|
||||||
COPY tests/ssh-keys /root/.ssh
|
|
||||||
RUN chmod -R 600 /root/.ssh
|
|
||||||
|
|
||||||
RUN mkdir /src
|
RUN mkdir /src
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
|
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
ARG PYTHON_VERSION=3.7
|
|
||||||
|
|
||||||
FROM python:${PYTHON_VERSION}
|
|
||||||
|
|
||||||
RUN mkdir /src
|
|
||||||
WORKDIR /src
|
|
||||||
|
|
||||||
COPY requirements.txt /src/requirements.txt
|
|
||||||
RUN pip install -r requirements.txt
|
|
||||||
|
|
||||||
COPY test-requirements.txt /src/test-requirements.txt
|
|
||||||
RUN pip install -r test-requirements.txt
|
|
||||||
|
|
||||||
COPY . /src
|
|
||||||
RUN pip install .
|
|
|
@ -1,7 +1,6 @@
|
||||||
#!groovy
|
#!groovy
|
||||||
|
|
||||||
def imageNameBase = "dockerpinata/docker-py"
|
def imageNameBase = "dockerpinata/docker-py"
|
||||||
def imageNamePy2
|
|
||||||
def imageNamePy3
|
def imageNamePy3
|
||||||
def imageDindSSH
|
def imageDindSSH
|
||||||
def images = [:]
|
def images = [:]
|
||||||
|
@ -22,12 +21,10 @@ def buildImages = { ->
|
||||||
stage("build image") {
|
stage("build image") {
|
||||||
checkout(scm)
|
checkout(scm)
|
||||||
|
|
||||||
imageNamePy2 = "${imageNameBase}:py2-${gitCommit()}"
|
|
||||||
imageNamePy3 = "${imageNameBase}:py3-${gitCommit()}"
|
imageNamePy3 = "${imageNameBase}:py3-${gitCommit()}"
|
||||||
imageDindSSH = "${imageNameBase}:sshdind-${gitCommit()}"
|
imageDindSSH = "${imageNameBase}:sshdind-${gitCommit()}"
|
||||||
withDockerRegistry(credentialsId:'dockerbuildbot-index.docker.io') {
|
withDockerRegistry(credentialsId:'dockerbuildbot-index.docker.io') {
|
||||||
buildImage(imageDindSSH, "-f tests/Dockerfile-ssh-dind .", "")
|
buildImage(imageDindSSH, "-f tests/Dockerfile-ssh-dind .", "")
|
||||||
buildImage(imageNamePy2, "-f tests/Dockerfile --build-arg PYTHON_VERSION=2.7 .", "py2.7")
|
|
||||||
buildImage(imageNamePy3, "-f tests/Dockerfile --build-arg PYTHON_VERSION=3.7 .", "py3.7")
|
buildImage(imageNamePy3, "-f tests/Dockerfile --build-arg PYTHON_VERSION=3.7 .", "py3.7")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,7 +70,7 @@ def runTests = { Map settings ->
|
||||||
throw new Exception("Need Docker version to test, e.g.: `runTests(dockerVersion: '19.03.12')`")
|
throw new Exception("Need Docker version to test, e.g.: `runTests(dockerVersion: '19.03.12')`")
|
||||||
}
|
}
|
||||||
if (!pythonVersion) {
|
if (!pythonVersion) {
|
||||||
throw new Exception("Need Python version being tested, e.g.: `runTests(pythonVersion: 'py2.7')`")
|
throw new Exception("Need Python version being tested, e.g.: `runTests(pythonVersion: 'py3.7')`")
|
||||||
}
|
}
|
||||||
|
|
||||||
{ ->
|
{ ->
|
||||||
|
|
50
Makefile
50
Makefile
|
@ -6,13 +6,9 @@ all: test
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
-docker rm -f dpy-dind-py2 dpy-dind-py3 dpy-dind-certs dpy-dind-ssl
|
-docker rm -f dpy-dind-py3 dpy-dind-certs dpy-dind-ssl
|
||||||
find -name "__pycache__" | xargs rm -rf
|
find -name "__pycache__" | xargs rm -rf
|
||||||
|
|
||||||
.PHONY: build
|
|
||||||
build:
|
|
||||||
docker build -t docker-sdk-python -f tests/Dockerfile --build-arg PYTHON_VERSION=2.7 --build-arg APT_MIRROR .
|
|
||||||
|
|
||||||
.PHONY: build-dind-ssh
|
.PHONY: build-dind-ssh
|
||||||
build-dind-ssh:
|
build-dind-ssh:
|
||||||
docker build -t docker-dind-ssh -f tests/Dockerfile-ssh-dind --build-arg ENGINE_VERSION=${TEST_ENGINE_VERSION} --build-arg API_VERSION=${TEST_API_VERSION} --build-arg APT_MIRROR .
|
docker build -t docker-dind-ssh -f tests/Dockerfile-ssh-dind --build-arg ENGINE_VERSION=${TEST_ENGINE_VERSION} --build-arg API_VERSION=${TEST_API_VERSION} --build-arg APT_MIRROR .
|
||||||
|
@ -30,20 +26,12 @@ build-dind-certs:
|
||||||
docker build -t dpy-dind-certs -f tests/Dockerfile-dind-certs .
|
docker build -t dpy-dind-certs -f tests/Dockerfile-dind-certs .
|
||||||
|
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
test: flake8 unit-test unit-test-py3 integration-dind integration-dind-ssl
|
test: flake8 unit-test-py3 integration-dind integration-dind-ssl
|
||||||
|
|
||||||
.PHONY: unit-test
|
|
||||||
unit-test: build
|
|
||||||
docker run -t --rm docker-sdk-python py.test tests/unit
|
|
||||||
|
|
||||||
.PHONY: unit-test-py3
|
.PHONY: unit-test-py3
|
||||||
unit-test-py3: build-py3
|
unit-test-py3: build-py3
|
||||||
docker run -t --rm docker-sdk-python3 py.test tests/unit
|
docker run -t --rm docker-sdk-python3 py.test tests/unit
|
||||||
|
|
||||||
.PHONY: integration-test
|
|
||||||
integration-test: build
|
|
||||||
docker run -t --rm -v /var/run/docker.sock:/var/run/docker.sock docker-sdk-python py.test -v tests/integration/${file}
|
|
||||||
|
|
||||||
.PHONY: integration-test-py3
|
.PHONY: integration-test-py3
|
||||||
integration-test-py3: build-py3
|
integration-test-py3: build-py3
|
||||||
docker run -t --rm -v /var/run/docker.sock:/var/run/docker.sock docker-sdk-python3 py.test -v tests/integration/${file}
|
docker run -t --rm -v /var/run/docker.sock:/var/run/docker.sock docker-sdk-python3 py.test -v tests/integration/${file}
|
||||||
|
@ -53,16 +41,7 @@ setup-network:
|
||||||
docker network inspect dpy-tests || docker network create dpy-tests
|
docker network inspect dpy-tests || docker network create dpy-tests
|
||||||
|
|
||||||
.PHONY: integration-dind
|
.PHONY: integration-dind
|
||||||
integration-dind: integration-dind-py2 integration-dind-py3
|
integration-dind: integration-dind-py3
|
||||||
|
|
||||||
.PHONY: integration-dind-py2
|
|
||||||
integration-dind-py2: build setup-network
|
|
||||||
docker rm -vf dpy-dind-py2 || :
|
|
||||||
docker run -d --network dpy-tests --name dpy-dind-py2 --privileged\
|
|
||||||
docker:${TEST_ENGINE_VERSION}-dind dockerd -H tcp://0.0.0.0:2375 --experimental
|
|
||||||
docker run -t --rm --env="DOCKER_HOST=tcp://dpy-dind-py2:2375" --env="DOCKER_TEST_API_VERSION=${TEST_API_VERSION}"\
|
|
||||||
--network dpy-tests docker-sdk-python py.test tests/integration/${file}
|
|
||||||
docker rm -vf dpy-dind-py2
|
|
||||||
|
|
||||||
.PHONY: integration-dind-py3
|
.PHONY: integration-dind-py3
|
||||||
integration-dind-py3: build-py3 setup-network
|
integration-dind-py3: build-py3 setup-network
|
||||||
|
@ -73,16 +52,6 @@ integration-dind-py3: build-py3 setup-network
|
||||||
--network dpy-tests docker-sdk-python3 py.test tests/integration/${file}
|
--network dpy-tests docker-sdk-python3 py.test tests/integration/${file}
|
||||||
docker rm -vf dpy-dind-py3
|
docker rm -vf dpy-dind-py3
|
||||||
|
|
||||||
.PHONY: integration-ssh-py2
|
|
||||||
integration-ssh-py2: build-dind-ssh build setup-network
|
|
||||||
docker rm -vf dpy-dind-py2 || :
|
|
||||||
docker run -d --network dpy-tests --name dpy-dind-py2 --privileged\
|
|
||||||
docker-dind-ssh dockerd --experimental
|
|
||||||
# start SSH daemon
|
|
||||||
docker exec dpy-dind-py2 sh -c "/usr/sbin/sshd"
|
|
||||||
docker run -t --rm --env="DOCKER_HOST=ssh://dpy-dind-py2" --env="DOCKER_TEST_API_VERSION=${TEST_API_VERSION}"\
|
|
||||||
--network dpy-tests docker-sdk-python py.test tests/ssh/${file}
|
|
||||||
docker rm -vf dpy-dind-py2
|
|
||||||
|
|
||||||
.PHONY: integration-ssh-py3
|
.PHONY: integration-ssh-py3
|
||||||
integration-ssh-py3: build-dind-ssh build-py3 setup-network
|
integration-ssh-py3: build-dind-ssh build-py3 setup-network
|
||||||
|
@ -97,7 +66,7 @@ integration-ssh-py3: build-dind-ssh build-py3 setup-network
|
||||||
|
|
||||||
|
|
||||||
.PHONY: integration-dind-ssl
|
.PHONY: integration-dind-ssl
|
||||||
integration-dind-ssl: build-dind-certs build build-py3
|
integration-dind-ssl: build-dind-certs build-py3
|
||||||
docker rm -vf dpy-dind-certs dpy-dind-ssl || :
|
docker rm -vf dpy-dind-certs dpy-dind-ssl || :
|
||||||
docker run -d --name dpy-dind-certs dpy-dind-certs
|
docker run -d --name dpy-dind-certs dpy-dind-certs
|
||||||
docker run -d --env="DOCKER_HOST=tcp://localhost:2375" --env="DOCKER_TLS_VERIFY=1"\
|
docker run -d --env="DOCKER_HOST=tcp://localhost:2375" --env="DOCKER_TLS_VERIFY=1"\
|
||||||
|
@ -106,22 +75,19 @@ integration-dind-ssl: build-dind-certs build build-py3
|
||||||
docker:${TEST_ENGINE_VERSION}-dind\
|
docker:${TEST_ENGINE_VERSION}-dind\
|
||||||
dockerd --tlsverify --tlscacert=/certs/ca.pem --tlscert=/certs/server-cert.pem\
|
dockerd --tlsverify --tlscacert=/certs/ca.pem --tlscert=/certs/server-cert.pem\
|
||||||
--tlskey=/certs/server-key.pem -H tcp://0.0.0.0:2375 --experimental
|
--tlskey=/certs/server-key.pem -H tcp://0.0.0.0:2375 --experimental
|
||||||
docker run -t --rm --volumes-from dpy-dind-ssl --env="DOCKER_HOST=tcp://docker:2375"\
|
|
||||||
--env="DOCKER_TLS_VERIFY=1" --env="DOCKER_CERT_PATH=/certs" --env="DOCKER_TEST_API_VERSION=${TEST_API_VERSION}"\
|
|
||||||
--network dpy-tests docker-sdk-python py.test tests/integration/${file}
|
|
||||||
docker run -t --rm --volumes-from dpy-dind-ssl --env="DOCKER_HOST=tcp://docker:2375"\
|
docker run -t --rm --volumes-from dpy-dind-ssl --env="DOCKER_HOST=tcp://docker:2375"\
|
||||||
--env="DOCKER_TLS_VERIFY=1" --env="DOCKER_CERT_PATH=/certs" --env="DOCKER_TEST_API_VERSION=${TEST_API_VERSION}"\
|
--env="DOCKER_TLS_VERIFY=1" --env="DOCKER_CERT_PATH=/certs" --env="DOCKER_TEST_API_VERSION=${TEST_API_VERSION}"\
|
||||||
--network dpy-tests docker-sdk-python3 py.test tests/integration/${file}
|
--network dpy-tests docker-sdk-python3 py.test tests/integration/${file}
|
||||||
docker rm -vf dpy-dind-ssl dpy-dind-certs
|
docker rm -vf dpy-dind-ssl dpy-dind-certs
|
||||||
|
|
||||||
.PHONY: flake8
|
.PHONY: flake8
|
||||||
flake8: build
|
flake8: build-py3
|
||||||
docker run -t --rm docker-sdk-python flake8 docker tests
|
docker run -t --rm docker-sdk-python3 flake8 docker tests
|
||||||
|
|
||||||
.PHONY: docs
|
.PHONY: docs
|
||||||
docs: build-docs
|
docs: build-docs
|
||||||
docker run --rm -t -v `pwd`:/src docker-sdk-python-docs sphinx-build docs docs/_build
|
docker run --rm -t -v `pwd`:/src docker-sdk-python-docs sphinx-build docs docs/_build
|
||||||
|
|
||||||
.PHONY: shell
|
.PHONY: shell
|
||||||
shell: build
|
shell: build-py3
|
||||||
docker run -it -v /var/run/docker.sock:/var/run/docker.sock docker-sdk-python python
|
docker run -it -v /var/run/docker.sock:/var/run/docker.sock docker-sdk-python3 python
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import json
|
import json
|
||||||
import struct
|
import struct
|
||||||
|
import urllib
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
import requests.exceptions
|
import requests.exceptions
|
||||||
import six
|
|
||||||
import websocket
|
import websocket
|
||||||
|
|
||||||
from .. import auth
|
from .. import auth
|
||||||
|
@ -192,12 +192,12 @@ class APIClient(
|
||||||
# version detection needs to be after unix adapter mounting
|
# version detection needs to be after unix adapter mounting
|
||||||
if version is None or (isinstance(
|
if version is None or (isinstance(
|
||||||
version,
|
version,
|
||||||
six.string_types
|
str
|
||||||
) and version.lower() == 'auto'):
|
) and version.lower() == 'auto'):
|
||||||
self._version = self._retrieve_server_version()
|
self._version = self._retrieve_server_version()
|
||||||
else:
|
else:
|
||||||
self._version = version
|
self._version = version
|
||||||
if not isinstance(self._version, six.string_types):
|
if not isinstance(self._version, str):
|
||||||
raise DockerException(
|
raise DockerException(
|
||||||
'Version parameter must be a string or None. Found {0}'.format(
|
'Version parameter must be a string or None. Found {0}'.format(
|
||||||
type(version).__name__
|
type(version).__name__
|
||||||
|
@ -246,13 +246,13 @@ class APIClient(
|
||||||
|
|
||||||
def _url(self, pathfmt, *args, **kwargs):
|
def _url(self, pathfmt, *args, **kwargs):
|
||||||
for arg in args:
|
for arg in args:
|
||||||
if not isinstance(arg, six.string_types):
|
if not isinstance(arg, str):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
'Expected a string but found {0} ({1}) '
|
'Expected a string but found {0} ({1}) '
|
||||||
'instead'.format(arg, type(arg))
|
'instead'.format(arg, type(arg))
|
||||||
)
|
)
|
||||||
|
|
||||||
quote_f = partial(six.moves.urllib.parse.quote, safe="/:")
|
quote_f = partial(urllib.parse.quote, safe="/:")
|
||||||
args = map(quote_f, args)
|
args = map(quote_f, args)
|
||||||
|
|
||||||
if kwargs.get('versioned_api', True):
|
if kwargs.get('versioned_api', True):
|
||||||
|
@ -284,7 +284,7 @@ class APIClient(
|
||||||
# so we do this disgusting thing here.
|
# so we do this disgusting thing here.
|
||||||
data2 = {}
|
data2 = {}
|
||||||
if data is not None and isinstance(data, dict):
|
if data is not None and isinstance(data, dict):
|
||||||
for k, v in six.iteritems(data):
|
for k, v in iter(data.items()):
|
||||||
if v is not None:
|
if v is not None:
|
||||||
data2[k] = v
|
data2[k] = v
|
||||||
elif data is not None:
|
elif data is not None:
|
||||||
|
@ -320,12 +320,10 @@ class APIClient(
|
||||||
sock = response.raw._fp.fp.raw.sock
|
sock = response.raw._fp.fp.raw.sock
|
||||||
elif self.base_url.startswith('http+docker://ssh'):
|
elif self.base_url.startswith('http+docker://ssh'):
|
||||||
sock = response.raw._fp.fp.channel
|
sock = response.raw._fp.fp.channel
|
||||||
elif six.PY3:
|
else:
|
||||||
sock = response.raw._fp.fp.raw
|
sock = response.raw._fp.fp.raw
|
||||||
if self.base_url.startswith("https://"):
|
if self.base_url.startswith("https://"):
|
||||||
sock = sock._sock
|
sock = sock._sock
|
||||||
else:
|
|
||||||
sock = response.raw._fp.fp._sock
|
|
||||||
try:
|
try:
|
||||||
# Keep a reference to the response to stop it being garbage
|
# Keep a reference to the response to stop it being garbage
|
||||||
# collected. If the response is garbage collected, it will
|
# collected. If the response is garbage collected, it will
|
||||||
|
@ -465,7 +463,7 @@ class APIClient(
|
||||||
self._result(res, binary=True)
|
self._result(res, binary=True)
|
||||||
|
|
||||||
self._raise_for_status(res)
|
self._raise_for_status(res)
|
||||||
sep = six.binary_type()
|
sep = b''
|
||||||
if stream:
|
if stream:
|
||||||
return self._multiplexed_response_stream_helper(res)
|
return self._multiplexed_response_stream_helper(res)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -11,6 +11,7 @@ from docker.context.config import get_context_host
|
||||||
|
|
||||||
class Context:
|
class Context:
|
||||||
"""A context."""
|
"""A context."""
|
||||||
|
|
||||||
def __init__(self, name, orchestrator=None, host=None, endpoints=None,
|
def __init__(self, name, orchestrator=None, host=None, endpoints=None,
|
||||||
tls=False):
|
tls=False):
|
||||||
if not name:
|
if not name:
|
||||||
|
@ -128,9 +129,9 @@ class Context:
|
||||||
key = os.path.join(tls_dir, endpoint, filename)
|
key = os.path.join(tls_dir, endpoint, filename)
|
||||||
if all([ca_cert, cert, key]):
|
if all([ca_cert, cert, key]):
|
||||||
verify = None
|
verify = None
|
||||||
if endpoint == "docker":
|
if endpoint == "docker" and not self.endpoints["docker"].get(
|
||||||
if not self.endpoints["docker"].get("SkipTLSVerify", False):
|
"SkipTLSVerify", False):
|
||||||
verify = True
|
verify = True
|
||||||
certs[endpoint] = TLSConfig(
|
certs[endpoint] = TLSConfig(
|
||||||
client_cert=(cert, key), ca_cert=ca_cert, verify=verify)
|
client_cert=(cert, key), ca_cert=ca_cert, verify=verify)
|
||||||
self.tls_cfg = certs
|
self.tls_cfg = certs
|
||||||
|
|
|
@ -53,7 +53,7 @@ class SSHSocket(socket.socket):
|
||||||
signal.signal(signal.SIGINT, signal.SIG_IGN)
|
signal.signal(signal.SIGINT, signal.SIG_IGN)
|
||||||
preexec_func = f
|
preexec_func = f
|
||||||
|
|
||||||
env = dict(os.environ)
|
env = dict(os.environ)
|
||||||
|
|
||||||
# drop LD_LIBRARY_PATH and SSL_CERT_FILE
|
# drop LD_LIBRARY_PATH and SSL_CERT_FILE
|
||||||
env.pop('LD_LIBRARY_PATH', None)
|
env.pop('LD_LIBRARY_PATH', None)
|
||||||
|
@ -65,7 +65,7 @@ class SSHSocket(socket.socket):
|
||||||
shell=True,
|
shell=True,
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stdin=subprocess.PIPE,
|
stdin=subprocess.PIPE,
|
||||||
preexec_fn=preexec_func)
|
preexec_fn=None if constants.IS_WINDOWS_PLATFORM else preexec_func)
|
||||||
|
|
||||||
def _write(self, data):
|
def _write(self, data):
|
||||||
if not self.proc or self.proc.stdin.closed:
|
if not self.proc or self.proc.stdin.closed:
|
||||||
|
|
|
@ -7,8 +7,6 @@ import string
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from distutils.version import StrictVersion
|
from distutils.version import StrictVersion
|
||||||
|
|
||||||
import six
|
|
||||||
|
|
||||||
from .. import errors
|
from .. import errors
|
||||||
from .. import tls
|
from .. import tls
|
||||||
from ..constants import DEFAULT_HTTP_HOST
|
from ..constants import DEFAULT_HTTP_HOST
|
||||||
|
@ -16,11 +14,7 @@ from ..constants import DEFAULT_UNIX_SOCKET
|
||||||
from ..constants import DEFAULT_NPIPE
|
from ..constants import DEFAULT_NPIPE
|
||||||
from ..constants import BYTE_UNITS
|
from ..constants import BYTE_UNITS
|
||||||
|
|
||||||
if six.PY2:
|
from urllib.parse import splitnport, urlparse
|
||||||
from urllib import splitnport
|
|
||||||
from urlparse import urlparse
|
|
||||||
else:
|
|
||||||
from urllib.parse import splitnport, urlparse
|
|
||||||
|
|
||||||
|
|
||||||
def create_ipam_pool(*args, **kwargs):
|
def create_ipam_pool(*args, **kwargs):
|
||||||
|
@ -39,8 +33,7 @@ def create_ipam_config(*args, **kwargs):
|
||||||
|
|
||||||
def decode_json_header(header):
|
def decode_json_header(header):
|
||||||
data = base64.b64decode(header)
|
data = base64.b64decode(header)
|
||||||
if six.PY3:
|
data = data.decode('utf-8')
|
||||||
data = data.decode('utf-8')
|
|
||||||
return json.loads(data)
|
return json.loads(data)
|
||||||
|
|
||||||
|
|
||||||
|
@ -80,7 +73,7 @@ def _convert_port_binding(binding):
|
||||||
if len(binding) == 2:
|
if len(binding) == 2:
|
||||||
result['HostPort'] = binding[1]
|
result['HostPort'] = binding[1]
|
||||||
result['HostIp'] = binding[0]
|
result['HostIp'] = binding[0]
|
||||||
elif isinstance(binding[0], six.string_types):
|
elif isinstance(binding[0], str):
|
||||||
result['HostIp'] = binding[0]
|
result['HostIp'] = binding[0]
|
||||||
else:
|
else:
|
||||||
result['HostPort'] = binding[0]
|
result['HostPort'] = binding[0]
|
||||||
|
@ -104,7 +97,7 @@ def _convert_port_binding(binding):
|
||||||
|
|
||||||
def convert_port_bindings(port_bindings):
|
def convert_port_bindings(port_bindings):
|
||||||
result = {}
|
result = {}
|
||||||
for k, v in six.iteritems(port_bindings):
|
for k, v in iter(port_bindings.items()):
|
||||||
key = str(k)
|
key = str(k)
|
||||||
if '/' not in key:
|
if '/' not in key:
|
||||||
key += '/tcp'
|
key += '/tcp'
|
||||||
|
@ -121,7 +114,7 @@ def convert_volume_binds(binds):
|
||||||
|
|
||||||
result = []
|
result = []
|
||||||
for k, v in binds.items():
|
for k, v in binds.items():
|
||||||
if isinstance(k, six.binary_type):
|
if isinstance(k, bytes):
|
||||||
k = k.decode('utf-8')
|
k = k.decode('utf-8')
|
||||||
|
|
||||||
if isinstance(v, dict):
|
if isinstance(v, dict):
|
||||||
|
@ -132,7 +125,7 @@ def convert_volume_binds(binds):
|
||||||
)
|
)
|
||||||
|
|
||||||
bind = v['bind']
|
bind = v['bind']
|
||||||
if isinstance(bind, six.binary_type):
|
if isinstance(bind, bytes):
|
||||||
bind = bind.decode('utf-8')
|
bind = bind.decode('utf-8')
|
||||||
|
|
||||||
if 'ro' in v:
|
if 'ro' in v:
|
||||||
|
@ -143,13 +136,13 @@ def convert_volume_binds(binds):
|
||||||
mode = 'rw'
|
mode = 'rw'
|
||||||
|
|
||||||
result.append(
|
result.append(
|
||||||
six.text_type('{0}:{1}:{2}').format(k, bind, mode)
|
str('{0}:{1}:{2}').format(k, bind, mode)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if isinstance(v, six.binary_type):
|
if isinstance(v, bytes):
|
||||||
v = v.decode('utf-8')
|
v = v.decode('utf-8')
|
||||||
result.append(
|
result.append(
|
||||||
six.text_type('{0}:{1}:rw').format(k, v)
|
str('{0}:{1}:rw').format(k, v)
|
||||||
)
|
)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@ -166,7 +159,7 @@ def convert_tmpfs_mounts(tmpfs):
|
||||||
|
|
||||||
result = {}
|
result = {}
|
||||||
for mount in tmpfs:
|
for mount in tmpfs:
|
||||||
if isinstance(mount, six.string_types):
|
if isinstance(mount, str):
|
||||||
if ":" in mount:
|
if ":" in mount:
|
||||||
name, options = mount.split(":", 1)
|
name, options = mount.split(":", 1)
|
||||||
else:
|
else:
|
||||||
|
@ -191,7 +184,7 @@ def convert_service_networks(networks):
|
||||||
|
|
||||||
result = []
|
result = []
|
||||||
for n in networks:
|
for n in networks:
|
||||||
if isinstance(n, six.string_types):
|
if isinstance(n, str):
|
||||||
n = {'Target': n}
|
n = {'Target': n}
|
||||||
result.append(n)
|
result.append(n)
|
||||||
return result
|
return result
|
||||||
|
@ -302,7 +295,7 @@ def parse_devices(devices):
|
||||||
if isinstance(device, dict):
|
if isinstance(device, dict):
|
||||||
device_list.append(device)
|
device_list.append(device)
|
||||||
continue
|
continue
|
||||||
if not isinstance(device, six.string_types):
|
if not isinstance(device, str):
|
||||||
raise errors.DockerException(
|
raise errors.DockerException(
|
||||||
'Invalid device type {0}'.format(type(device))
|
'Invalid device type {0}'.format(type(device))
|
||||||
)
|
)
|
||||||
|
@ -372,13 +365,13 @@ def kwargs_from_env(ssl_version=None, assert_hostname=None, environment=None):
|
||||||
|
|
||||||
def convert_filters(filters):
|
def convert_filters(filters):
|
||||||
result = {}
|
result = {}
|
||||||
for k, v in six.iteritems(filters):
|
for k, v in iter(filters.items()):
|
||||||
if isinstance(v, bool):
|
if isinstance(v, bool):
|
||||||
v = 'true' if v else 'false'
|
v = 'true' if v else 'false'
|
||||||
if not isinstance(v, list):
|
if not isinstance(v, list):
|
||||||
v = [v, ]
|
v = [v, ]
|
||||||
result[k] = [
|
result[k] = [
|
||||||
str(item) if not isinstance(item, six.string_types) else item
|
str(item) if not isinstance(item, str) else item
|
||||||
for item in v
|
for item in v
|
||||||
]
|
]
|
||||||
return json.dumps(result)
|
return json.dumps(result)
|
||||||
|
@ -391,7 +384,7 @@ def datetime_to_timestamp(dt):
|
||||||
|
|
||||||
|
|
||||||
def parse_bytes(s):
|
def parse_bytes(s):
|
||||||
if isinstance(s, six.integer_types + (float,)):
|
if isinstance(s, (int, float,)):
|
||||||
return s
|
return s
|
||||||
if len(s) == 0:
|
if len(s) == 0:
|
||||||
return 0
|
return 0
|
||||||
|
@ -433,7 +426,7 @@ def parse_bytes(s):
|
||||||
|
|
||||||
def normalize_links(links):
|
def normalize_links(links):
|
||||||
if isinstance(links, dict):
|
if isinstance(links, dict):
|
||||||
links = six.iteritems(links)
|
links = iter(links.items())
|
||||||
|
|
||||||
return ['{0}:{1}'.format(k, v) if v else k for k, v in sorted(links)]
|
return ['{0}:{1}'.format(k, v) if v else k for k, v in sorted(links)]
|
||||||
|
|
||||||
|
@ -468,8 +461,6 @@ def parse_env_file(env_file):
|
||||||
|
|
||||||
|
|
||||||
def split_command(command):
|
def split_command(command):
|
||||||
if six.PY2 and not isinstance(command, six.binary_type):
|
|
||||||
command = command.encode('utf-8')
|
|
||||||
return shlex.split(command)
|
return shlex.split(command)
|
||||||
|
|
||||||
|
|
||||||
|
@ -477,22 +468,22 @@ def format_environment(environment):
|
||||||
def format_env(key, value):
|
def format_env(key, value):
|
||||||
if value is None:
|
if value is None:
|
||||||
return key
|
return key
|
||||||
if isinstance(value, six.binary_type):
|
if isinstance(value, bytes):
|
||||||
value = value.decode('utf-8')
|
value = value.decode('utf-8')
|
||||||
|
|
||||||
return u'{key}={value}'.format(key=key, value=value)
|
return u'{key}={value}'.format(key=key, value=value)
|
||||||
return [format_env(*var) for var in six.iteritems(environment)]
|
return [format_env(*var) for var in iter(environment.items())]
|
||||||
|
|
||||||
|
|
||||||
def format_extra_hosts(extra_hosts, task=False):
|
def format_extra_hosts(extra_hosts, task=False):
|
||||||
# Use format dictated by Swarm API if container is part of a task
|
# Use format dictated by Swarm API if container is part of a task
|
||||||
if task:
|
if task:
|
||||||
return [
|
return [
|
||||||
'{} {}'.format(v, k) for k, v in sorted(six.iteritems(extra_hosts))
|
'{} {}'.format(v, k) for k, v in sorted(iter(extra_hosts.items()))
|
||||||
]
|
]
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'{}:{}'.format(k, v) for k, v in sorted(six.iteritems(extra_hosts))
|
'{}:{}'.format(k, v) for k, v in sorted(iter(extra_hosts.items()))
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,5 @@ pyOpenSSL==18.0.0
|
||||||
pyparsing==2.2.0
|
pyparsing==2.2.0
|
||||||
pywin32==227; sys_platform == 'win32'
|
pywin32==227; sys_platform == 'win32'
|
||||||
requests==2.20.0
|
requests==2.20.0
|
||||||
six==1.10.0
|
|
||||||
urllib3==1.24.3
|
urllib3==1.24.3
|
||||||
websocket-client==0.56.0
|
websocket-client==0.56.0
|
||||||
|
|
12
setup.py
12
setup.py
|
@ -11,18 +11,11 @@ ROOT_DIR = os.path.dirname(__file__)
|
||||||
SOURCE_DIR = os.path.join(ROOT_DIR)
|
SOURCE_DIR = os.path.join(ROOT_DIR)
|
||||||
|
|
||||||
requirements = [
|
requirements = [
|
||||||
'six >= 1.4.0',
|
|
||||||
'websocket-client >= 0.32.0',
|
'websocket-client >= 0.32.0',
|
||||||
'requests >= 2.14.2, != 2.18.0',
|
'requests >= 2.14.2, != 2.18.0',
|
||||||
]
|
]
|
||||||
|
|
||||||
extras_require = {
|
extras_require = {
|
||||||
':python_version < "3.5"': 'backports.ssl_match_hostname >= 3.5',
|
|
||||||
# While not imported explicitly, the ipaddress module is required for
|
|
||||||
# ssl_match_hostname to verify hosts match with certificates via
|
|
||||||
# ServerAltname: https://pypi.python.org/pypi/backports.ssl_match_hostname
|
|
||||||
':python_version < "3.3"': 'ipaddress >= 1.0.16',
|
|
||||||
|
|
||||||
# win32 APIs if on Windows (required for npipe support)
|
# win32 APIs if on Windows (required for npipe support)
|
||||||
':sys_platform == "win32"': 'pywin32==227',
|
':sys_platform == "win32"': 'pywin32==227',
|
||||||
|
|
||||||
|
@ -69,7 +62,7 @@ setup(
|
||||||
install_requires=requirements,
|
install_requires=requirements,
|
||||||
tests_require=test_requirements,
|
tests_require=test_requirements,
|
||||||
extras_require=extras_require,
|
extras_require=extras_require,
|
||||||
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*',
|
python_requires='>=3.6',
|
||||||
zip_safe=False,
|
zip_safe=False,
|
||||||
test_suite='tests',
|
test_suite='tests',
|
||||||
classifiers=[
|
classifiers=[
|
||||||
|
@ -78,10 +71,7 @@ setup(
|
||||||
'Intended Audience :: Developers',
|
'Intended Audience :: Developers',
|
||||||
'Operating System :: OS Independent',
|
'Operating System :: OS Independent',
|
||||||
'Programming Language :: Python',
|
'Programming Language :: Python',
|
||||||
'Programming Language :: Python :: 2',
|
|
||||||
'Programming Language :: Python :: 2.7',
|
|
||||||
'Programming Language :: Python :: 3',
|
'Programming Language :: Python :: 3',
|
||||||
'Programming Language :: Python :: 3.5',
|
|
||||||
'Programming Language :: Python :: 3.6',
|
'Programming Language :: Python :: 3.6',
|
||||||
'Programming Language :: Python :: 3.7',
|
'Programming Language :: Python :: 3.7',
|
||||||
'Programming Language :: Python :: 3.8',
|
'Programming Language :: Python :: 3.8',
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
setuptools==44.0.0 # last version with python 2.7 support
|
setuptools==54.1.1
|
||||||
coverage==4.5.2
|
coverage==4.5.2
|
||||||
flake8==3.6.0
|
flake8==3.6.0
|
||||||
mock==1.0.1
|
mock==1.0.1
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
ARG PYTHON_VERSION=2.7
|
ARG PYTHON_VERSION=3.6
|
||||||
|
|
||||||
FROM python:${PYTHON_VERSION}
|
FROM python:${PYTHON_VERSION}
|
||||||
RUN mkdir /tmp/certs
|
RUN mkdir /tmp/certs
|
||||||
|
|
|
@ -7,7 +7,6 @@ from datetime import datetime
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
import requests
|
import requests
|
||||||
import six
|
|
||||||
|
|
||||||
import docker
|
import docker
|
||||||
from .. import helpers
|
from .. import helpers
|
||||||
|
@ -35,7 +34,7 @@ class ListContainersTest(BaseAPIIntegrationTest):
|
||||||
assert len(retrieved) == 1
|
assert len(retrieved) == 1
|
||||||
retrieved = retrieved[0]
|
retrieved = retrieved[0]
|
||||||
assert 'Command' in retrieved
|
assert 'Command' in retrieved
|
||||||
assert retrieved['Command'] == six.text_type('true')
|
assert retrieved['Command'] == str('true')
|
||||||
assert 'Image' in retrieved
|
assert 'Image' in retrieved
|
||||||
assert re.search(r'alpine:.*', retrieved['Image'])
|
assert re.search(r'alpine:.*', retrieved['Image'])
|
||||||
assert 'Status' in retrieved
|
assert 'Status' in retrieved
|
||||||
|
@ -104,9 +103,7 @@ class CreateContainerTest(BaseAPIIntegrationTest):
|
||||||
self.client.start(container3_id)
|
self.client.start(container3_id)
|
||||||
assert self.client.wait(container3_id)['StatusCode'] == 0
|
assert self.client.wait(container3_id)['StatusCode'] == 0
|
||||||
|
|
||||||
logs = self.client.logs(container3_id)
|
logs = self.client.logs(container3_id).decode('utf-8')
|
||||||
if six.PY3:
|
|
||||||
logs = logs.decode('utf-8')
|
|
||||||
assert '{0}_NAME='.format(link_env_prefix1) in logs
|
assert '{0}_NAME='.format(link_env_prefix1) in logs
|
||||||
assert '{0}_ENV_FOO=1'.format(link_env_prefix1) in logs
|
assert '{0}_ENV_FOO=1'.format(link_env_prefix1) in logs
|
||||||
assert '{0}_NAME='.format(link_env_prefix2) in logs
|
assert '{0}_NAME='.format(link_env_prefix2) in logs
|
||||||
|
@ -227,9 +224,7 @@ class CreateContainerTest(BaseAPIIntegrationTest):
|
||||||
self.client.start(container)
|
self.client.start(container)
|
||||||
self.client.wait(container)
|
self.client.wait(container)
|
||||||
|
|
||||||
logs = self.client.logs(container)
|
logs = self.client.logs(container).decode('utf-8')
|
||||||
if six.PY3:
|
|
||||||
logs = logs.decode('utf-8')
|
|
||||||
groups = logs.strip().split(' ')
|
groups = logs.strip().split(' ')
|
||||||
assert '1000' in groups
|
assert '1000' in groups
|
||||||
assert '1001' in groups
|
assert '1001' in groups
|
||||||
|
@ -244,9 +239,7 @@ class CreateContainerTest(BaseAPIIntegrationTest):
|
||||||
self.client.start(container)
|
self.client.start(container)
|
||||||
self.client.wait(container)
|
self.client.wait(container)
|
||||||
|
|
||||||
logs = self.client.logs(container)
|
logs = self.client.logs(container).decode('utf-8')
|
||||||
if six.PY3:
|
|
||||||
logs = logs.decode('utf-8')
|
|
||||||
|
|
||||||
groups = logs.strip().split(' ')
|
groups = logs.strip().split(' ')
|
||||||
assert '1000' in groups
|
assert '1000' in groups
|
||||||
|
@ -515,10 +508,7 @@ class VolumeBindTest(BaseAPIIntegrationTest):
|
||||||
TEST_IMG,
|
TEST_IMG,
|
||||||
['ls', self.mount_dest],
|
['ls', self.mount_dest],
|
||||||
)
|
)
|
||||||
logs = self.client.logs(container)
|
logs = self.client.logs(container).decode('utf-8')
|
||||||
|
|
||||||
if six.PY3:
|
|
||||||
logs = logs.decode('utf-8')
|
|
||||||
assert self.filename in logs
|
assert self.filename in logs
|
||||||
inspect_data = self.client.inspect_container(container)
|
inspect_data = self.client.inspect_container(container)
|
||||||
self.check_container_data(inspect_data, True)
|
self.check_container_data(inspect_data, True)
|
||||||
|
@ -534,10 +524,8 @@ class VolumeBindTest(BaseAPIIntegrationTest):
|
||||||
TEST_IMG,
|
TEST_IMG,
|
||||||
['ls', self.mount_dest],
|
['ls', self.mount_dest],
|
||||||
)
|
)
|
||||||
logs = self.client.logs(container)
|
logs = self.client.logs(container).decode('utf-8')
|
||||||
|
|
||||||
if six.PY3:
|
|
||||||
logs = logs.decode('utf-8')
|
|
||||||
assert self.filename in logs
|
assert self.filename in logs
|
||||||
|
|
||||||
inspect_data = self.client.inspect_container(container)
|
inspect_data = self.client.inspect_container(container)
|
||||||
|
@ -554,9 +542,7 @@ class VolumeBindTest(BaseAPIIntegrationTest):
|
||||||
host_config=host_config
|
host_config=host_config
|
||||||
)
|
)
|
||||||
assert container
|
assert container
|
||||||
logs = self.client.logs(container)
|
logs = self.client.logs(container).decode('utf-8')
|
||||||
if six.PY3:
|
|
||||||
logs = logs.decode('utf-8')
|
|
||||||
assert self.filename in logs
|
assert self.filename in logs
|
||||||
inspect_data = self.client.inspect_container(container)
|
inspect_data = self.client.inspect_container(container)
|
||||||
self.check_container_data(inspect_data, True)
|
self.check_container_data(inspect_data, True)
|
||||||
|
@ -573,9 +559,7 @@ class VolumeBindTest(BaseAPIIntegrationTest):
|
||||||
host_config=host_config
|
host_config=host_config
|
||||||
)
|
)
|
||||||
assert container
|
assert container
|
||||||
logs = self.client.logs(container)
|
logs = self.client.logs(container).decode('utf-8')
|
||||||
if six.PY3:
|
|
||||||
logs = logs.decode('utf-8')
|
|
||||||
assert self.filename in logs
|
assert self.filename in logs
|
||||||
inspect_data = self.client.inspect_container(container)
|
inspect_data = self.client.inspect_container(container)
|
||||||
self.check_container_data(inspect_data, False)
|
self.check_container_data(inspect_data, False)
|
||||||
|
@ -645,9 +629,8 @@ class ArchiveTest(BaseAPIIntegrationTest):
|
||||||
for d in strm:
|
for d in strm:
|
||||||
destination.write(d)
|
destination.write(d)
|
||||||
destination.seek(0)
|
destination.seek(0)
|
||||||
retrieved_data = helpers.untar_file(destination, 'data.txt')
|
retrieved_data = helpers.untar_file(destination, 'data.txt')\
|
||||||
if six.PY3:
|
.decode('utf-8')
|
||||||
retrieved_data = retrieved_data.decode('utf-8')
|
|
||||||
assert data == retrieved_data.strip()
|
assert data == retrieved_data.strip()
|
||||||
|
|
||||||
def test_get_file_stat_from_container(self):
|
def test_get_file_stat_from_container(self):
|
||||||
|
@ -683,9 +666,6 @@ class ArchiveTest(BaseAPIIntegrationTest):
|
||||||
self.client.start(ctnr)
|
self.client.start(ctnr)
|
||||||
self.client.wait(ctnr)
|
self.client.wait(ctnr)
|
||||||
logs = self.client.logs(ctnr)
|
logs = self.client.logs(ctnr)
|
||||||
if six.PY3:
|
|
||||||
logs = logs.decode('utf-8')
|
|
||||||
data = data.decode('utf-8')
|
|
||||||
assert logs.strip() == data
|
assert logs.strip() == data
|
||||||
|
|
||||||
def test_copy_directory_to_container(self):
|
def test_copy_directory_to_container(self):
|
||||||
|
@ -700,9 +680,7 @@ class ArchiveTest(BaseAPIIntegrationTest):
|
||||||
self.client.put_archive(ctnr, '/vol1', test_tar)
|
self.client.put_archive(ctnr, '/vol1', test_tar)
|
||||||
self.client.start(ctnr)
|
self.client.start(ctnr)
|
||||||
self.client.wait(ctnr)
|
self.client.wait(ctnr)
|
||||||
logs = self.client.logs(ctnr)
|
logs = self.client.logs(ctnr).decode('utf-8')
|
||||||
if six.PY3:
|
|
||||||
logs = logs.decode('utf-8')
|
|
||||||
results = logs.strip().split()
|
results = logs.strip().split()
|
||||||
assert 'a.py' in results
|
assert 'a.py' in results
|
||||||
assert 'b.py' in results
|
assert 'b.py' in results
|
||||||
|
@ -861,7 +839,7 @@ Line2'''
|
||||||
id = container['Id']
|
id = container['Id']
|
||||||
self.tmp_containers.append(id)
|
self.tmp_containers.append(id)
|
||||||
self.client.start(id)
|
self.client.start(id)
|
||||||
logs = six.binary_type()
|
logs = b''
|
||||||
for chunk in self.client.logs(id, stream=True, follow=True):
|
for chunk in self.client.logs(id, stream=True, follow=True):
|
||||||
logs += chunk
|
logs += chunk
|
||||||
|
|
||||||
|
@ -881,7 +859,7 @@ Line2'''
|
||||||
id = container['Id']
|
id = container['Id']
|
||||||
self.tmp_containers.append(id)
|
self.tmp_containers.append(id)
|
||||||
self.client.start(id)
|
self.client.start(id)
|
||||||
logs = six.binary_type()
|
logs = b''
|
||||||
|
|
||||||
generator = self.client.logs(id, stream=True, follow=True)
|
generator = self.client.logs(id, stream=True, follow=True)
|
||||||
threading.Timer(1, generator.close).start()
|
threading.Timer(1, generator.close).start()
|
||||||
|
|
|
@ -7,9 +7,8 @@ import tempfile
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
import six
|
from http.server import SimpleHTTPRequestHandler
|
||||||
from six.moves import BaseHTTPServer
|
import socketserver
|
||||||
from six.moves import socketserver
|
|
||||||
|
|
||||||
|
|
||||||
import docker
|
import docker
|
||||||
|
@ -33,7 +32,7 @@ class ListImagesTest(BaseAPIIntegrationTest):
|
||||||
|
|
||||||
def test_images_quiet(self):
|
def test_images_quiet(self):
|
||||||
res1 = self.client.images(quiet=True)
|
res1 = self.client.images(quiet=True)
|
||||||
assert type(res1[0]) == six.text_type
|
assert type(res1[0]) == str
|
||||||
|
|
||||||
|
|
||||||
class PullImageTest(BaseAPIIntegrationTest):
|
class PullImageTest(BaseAPIIntegrationTest):
|
||||||
|
@ -44,7 +43,7 @@ class PullImageTest(BaseAPIIntegrationTest):
|
||||||
pass
|
pass
|
||||||
res = self.client.pull('hello-world')
|
res = self.client.pull('hello-world')
|
||||||
self.tmp_imgs.append('hello-world')
|
self.tmp_imgs.append('hello-world')
|
||||||
assert type(res) == six.text_type
|
assert type(res) == str
|
||||||
assert len(self.client.images('hello-world')) >= 1
|
assert len(self.client.images('hello-world')) >= 1
|
||||||
img_info = self.client.inspect_image('hello-world')
|
img_info = self.client.inspect_image('hello-world')
|
||||||
assert 'Id' in img_info
|
assert 'Id' in img_info
|
||||||
|
@ -273,7 +272,7 @@ class ImportImageTest(BaseAPIIntegrationTest):
|
||||||
def temporary_http_file_server(self, stream):
|
def temporary_http_file_server(self, stream):
|
||||||
'''Serve data from an IO stream over HTTP.'''
|
'''Serve data from an IO stream over HTTP.'''
|
||||||
|
|
||||||
class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
|
class Handler(SimpleHTTPRequestHandler):
|
||||||
def do_GET(self):
|
def do_GET(self):
|
||||||
self.send_response(200)
|
self.send_response(200)
|
||||||
self.send_header('Content-Type', 'application/x-tar')
|
self.send_header('Content-Type', 'application/x-tar')
|
||||||
|
|
|
@ -5,7 +5,6 @@ import time
|
||||||
|
|
||||||
import docker
|
import docker
|
||||||
import pytest
|
import pytest
|
||||||
import six
|
|
||||||
|
|
||||||
from ..helpers import (
|
from ..helpers import (
|
||||||
force_leave_swarm, requires_api_version, requires_experimental
|
force_leave_swarm, requires_api_version, requires_experimental
|
||||||
|
@ -150,7 +149,7 @@ class ServiceTest(BaseAPIIntegrationTest):
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
if six.PY3:
|
if log_line is not None:
|
||||||
log_line = log_line.decode('utf-8')
|
log_line = log_line.decode('utf-8')
|
||||||
assert 'hello\n' in log_line
|
assert 'hello\n' in log_line
|
||||||
|
|
||||||
|
|
|
@ -2,31 +2,38 @@ import unittest
|
||||||
import docker
|
import docker
|
||||||
from docker.transport.sshconn import SSHSocket
|
from docker.transport.sshconn import SSHSocket
|
||||||
|
|
||||||
|
|
||||||
class SSHAdapterTest(unittest.TestCase):
|
class SSHAdapterTest(unittest.TestCase):
|
||||||
def test_ssh_hostname_prefix_trim(self):
|
@staticmethod
|
||||||
conn = docker.transport.SSHHTTPAdapter(base_url="ssh://user@hostname:1234", shell_out=True)
|
def test_ssh_hostname_prefix_trim():
|
||||||
|
conn = docker.transport.SSHHTTPAdapter(
|
||||||
|
base_url="ssh://user@hostname:1234", shell_out=True)
|
||||||
assert conn.ssh_host == "user@hostname:1234"
|
assert conn.ssh_host == "user@hostname:1234"
|
||||||
|
|
||||||
def test_ssh_parse_url(self):
|
@staticmethod
|
||||||
|
def test_ssh_parse_url():
|
||||||
c = SSHSocket(host="user@hostname:1234")
|
c = SSHSocket(host="user@hostname:1234")
|
||||||
assert c.host == "hostname"
|
assert c.host == "hostname"
|
||||||
assert c.port == "1234"
|
assert c.port == "1234"
|
||||||
assert c.user == "user"
|
assert c.user == "user"
|
||||||
|
|
||||||
def test_ssh_parse_hostname_only(self):
|
@staticmethod
|
||||||
|
def test_ssh_parse_hostname_only():
|
||||||
c = SSHSocket(host="hostname")
|
c = SSHSocket(host="hostname")
|
||||||
assert c.host == "hostname"
|
assert c.host == "hostname"
|
||||||
assert c.port == None
|
assert c.port is None
|
||||||
assert c.user == None
|
assert c.user is None
|
||||||
|
|
||||||
def test_ssh_parse_user_and_hostname(self):
|
@staticmethod
|
||||||
|
def test_ssh_parse_user_and_hostname():
|
||||||
c = SSHSocket(host="user@hostname")
|
c = SSHSocket(host="user@hostname")
|
||||||
assert c.host == "hostname"
|
assert c.host == "hostname"
|
||||||
assert c.port == None
|
assert c.port is None
|
||||||
assert c.user == "user"
|
assert c.user == "user"
|
||||||
|
|
||||||
def test_ssh_parse_hostname_and_port(self):
|
@staticmethod
|
||||||
|
def test_ssh_parse_hostname_and_port():
|
||||||
c = SSHSocket(host="hostname:22")
|
c = SSHSocket(host="hostname:22")
|
||||||
assert c.host == "hostname"
|
assert c.host == "hostname"
|
||||||
assert c.port == "22"
|
assert c.port == "22"
|
||||||
assert c.user == None
|
assert c.user is None
|
||||||
|
|
Loading…
Reference in New Issue