Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump 4.2.1 #2580

Merged
merged 9 commits into from
Jun 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def buildImages = { ->
}

def getDockerVersions = { ->
def dockerVersions = ["17.06.2-ce"]
def dockerVersions = ["19.03.5"]
wrappedNode(label: "ubuntu && !zfs && amd64") {
def result = sh(script: """docker run --rm \\
--entrypoint=python \\
Expand All @@ -46,8 +46,6 @@ def getDockerVersions = { ->

def getAPIVersion = { engineVersion ->
def versionMap = [
'17.06': '1.30',
'18.03': '1.37',
'18.09': '1.39',
'19.03': '1.40'
]
Expand Down Expand Up @@ -84,7 +82,7 @@ def runTests = { Map settings ->
try {
sh """docker network create ${testNetwork}"""
sh """docker run -d --name ${dindContainerName} -v /tmp --privileged --network ${testNetwork} \\
dockerswarm/dind:${dockerVersion} dockerd -H tcp://0.0.0.0:2375
docker:${dockerVersion}-dind dockerd -H tcp://0.0.0.0:2375
"""
sh """docker run \\
--name ${testContainerName} \\
Expand Down
8 changes: 4 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ 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}

TEST_API_VERSION ?= 1.35
TEST_ENGINE_VERSION ?= 18.09.5
TEST_ENGINE_VERSION ?= 19.03.5

.PHONY: setup-network
setup-network:
Expand All @@ -55,7 +55,7 @@ integration-dind: integration-dind-py2 integration-dind-py3
integration-dind-py2: build setup-network
docker rm -vf dpy-dind-py2 || :
docker run -d --network dpy-tests --name dpy-dind-py2 --privileged\
dockerswarm/dind:${TEST_ENGINE_VERSION} dockerd -H tcp://0.0.0.0:2375 --experimental
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
docker rm -vf dpy-dind-py2
Expand All @@ -64,7 +64,7 @@ integration-dind-py2: build setup-network
integration-dind-py3: build-py3 setup-network
docker rm -vf dpy-dind-py3 || :
docker run -d --network dpy-tests --name dpy-dind-py3 --privileged\
dockerswarm/dind:${TEST_ENGINE_VERSION} dockerd -H tcp://0.0.0.0:2375 --experimental
docker:${TEST_ENGINE_VERSION}-dind dockerd -H tcp://0.0.0.0:2375 --experimental
docker run -t --rm --env="DOCKER_HOST=tcp://dpy-dind-py3:2375" --env="DOCKER_TEST_API_VERSION=${TEST_API_VERSION}"\
--network dpy-tests docker-sdk-python3 py.test tests/integration
docker rm -vf dpy-dind-py3
Expand All @@ -76,7 +76,7 @@ integration-dind-ssl: build-dind-certs build build-py3
docker run -d --env="DOCKER_HOST=tcp://localhost:2375" --env="DOCKER_TLS_VERIFY=1"\
--env="DOCKER_CERT_PATH=/certs" --volumes-from dpy-dind-certs --name dpy-dind-ssl\
--network dpy-tests --network-alias docker -v /tmp --privileged\
dockerswarm/dind:${TEST_ENGINE_VERSION}\
docker:${TEST_ENGINE_VERSION}-dind\
dockerd --tlsverify --tlscacert=/certs/ca.pem --tlscert=/certs/server-cert.pem\
--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"\
Expand Down
16 changes: 7 additions & 9 deletions docker/context/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ class ContextAPI(object):
Contains methods for context management:
create, list, remove, get, inspect.
"""
DEFAULT_CONTEXT = Context("default")
DEFAULT_CONTEXT = Context("default", "swarm")

@classmethod
def create_context(
cls, name, orchestrator="swarm", host=None, tls_cfg=None,
cls, name, orchestrator=None, host=None, tls_cfg=None,
default_namespace=None, skip_tls_verify=False):
"""Creates a new context.
Returns:
Expand All @@ -38,9 +38,7 @@ def create_context(
>>> print(ctx.Metadata)
{
"Name": "test",
"Metadata": {
"StackOrchestrator": "swarm"
},
"Metadata": {},
"Endpoints": {
"docker": {
"Host": "unix:///var/run/docker.sock",
Expand All @@ -57,7 +55,9 @@ def create_context(
ctx = Context.load_context(name)
if ctx:
raise errors.ContextAlreadyExists(name)
endpoint = "docker" if orchestrator == "swarm" else orchestrator
endpoint = "docker"
if orchestrator and orchestrator != "swarm":
endpoint = orchestrator
ctx = Context(name, orchestrator)
ctx.set_endpoint(
endpoint, host, tls_cfg,
Expand All @@ -79,9 +79,7 @@ def get_context(cls, name=None):
>>> print(ctx.Metadata)
{
"Name": "test",
"Metadata": {
"StackOrchestrator": "swarm"
},
"Metadata": {},
"Endpoints": {
"docker": {
"Host": "unix:///var/run/docker.sock",
Expand Down
4 changes: 2 additions & 2 deletions docker/context/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ def get_tls_dir(name=None, endpoint=""):
return os.path.join(context_dir, "tls")


def get_context_host(path=None):
host = utils.parse_host(path, IS_WINDOWS_PLATFORM)
def get_context_host(path=None, tls=False):
host = utils.parse_host(path, IS_WINDOWS_PLATFORM, tls)
if host == DEFAULT_UNIX_SOCKET:
# remove http+ from default docker socket url
return host.strip("http+")
Expand Down
25 changes: 14 additions & 11 deletions docker/context/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,20 @@

class Context:
"""A context."""
def __init__(self, name, orchestrator="swarm", host=None, endpoints=None):
def __init__(self, name, orchestrator=None, host=None, endpoints=None,
tls=False):
if not name:
raise Exception("Name not provided")
self.name = name
self.orchestrator = orchestrator
if not endpoints:
default_endpoint = "docker" if (
orchestrator == "swarm"
not orchestrator or orchestrator == "swarm"
) else orchestrator
self.endpoints = {
default_endpoint: {
"Host": get_context_host(host),
"SkipTLSVerify": False
"Host": get_context_host(host, tls),
"SkipTLSVerify": not tls
}
}
else:
Expand All @@ -44,7 +45,7 @@ def set_endpoint(
self, name="docker", host=None, tls_cfg=None,
skip_tls_verify=False, def_namespace=None):
self.endpoints[name] = {
"Host": get_context_host(host),
"Host": get_context_host(host, not skip_tls_verify),
"SkipTLSVerify": skip_tls_verify
}
if def_namespace:
Expand Down Expand Up @@ -84,7 +85,8 @@ def _load_meta(cls, name):
context {} : {}""".format(name, e))

return (
metadata["Name"], metadata["Metadata"]["StackOrchestrator"],
metadata["Name"],
metadata["Metadata"].get("StackOrchestrator", None),
metadata["Endpoints"])
return None, None, None

Expand Down Expand Up @@ -161,7 +163,7 @@ def Name(self):

@property
def Host(self):
if self.orchestrator == "swarm":
if not self.orchestrator or self.orchestrator == "swarm":
return self.endpoints["docker"]["Host"]
return self.endpoints[self.orchestrator]["Host"]

Expand All @@ -171,18 +173,19 @@ def Orchestrator(self):

@property
def Metadata(self):
meta = {}
if self.orchestrator:
meta = {"StackOrchestrator": self.orchestrator}
return {
"Name": self.name,
"Metadata": {
"StackOrchestrator": self.orchestrator
},
"Metadata": meta,
"Endpoints": self.endpoints
}

@property
def TLSConfig(self):
key = self.orchestrator
if key == "swarm":
if not key or key == "swarm":
key = "docker"
if key in self.tls_cfg.keys():
return self.tls_cfg[key]
Expand Down
2 changes: 1 addition & 1 deletion docker/version.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
version = "4.2.0"
version = "4.2.1"
version_info = tuple([int(d) for d in version.split("-")[0].split(".")])
10 changes: 10 additions & 0 deletions docs/change-log.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
Change log
==========

4.2.1
-----

[List of PRs / issues for this release](https://github.com/docker/docker-py/milestone/65?closed=1)

### Features

- Add option on when to use `tls` on Context constructor
- Make context orchestrator field optional

4.2.0
-----

Expand Down
24 changes: 13 additions & 11 deletions tests/integration/api_container_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,11 +273,14 @@ def test_valid_log_driver_and_log_opt(self):

def test_invalid_log_driver_raises_exception(self):
log_config = docker.types.LogConfig(
type='asdf-nope',
type='asdf',
config={}
)

expected_msg = "logger: no log driver named 'asdf-nope' is registered"
expected_msgs = [
"logger: no log driver named 'asdf' is registered",
"looking up logging plugin asdf: plugin \"asdf\" not found",
]
with pytest.raises(docker.errors.APIError) as excinfo:
# raises an internal server error 500
container = self.client.create_container(
Expand All @@ -287,7 +290,7 @@ def test_invalid_log_driver_raises_exception(self):
)
self.client.start(container)

assert excinfo.value.explanation == expected_msg
assert excinfo.value.explanation in expected_msgs

def test_valid_no_log_driver_specified(self):
log_config = docker.types.LogConfig(
Expand Down Expand Up @@ -1102,6 +1105,8 @@ def test_port(self):


class ContainerTopTest(BaseAPIIntegrationTest):
@pytest.mark.xfail(reason='Output of docker top depends on host distro, '
'and is not formalized.')
def test_top(self):
container = self.client.create_container(
TEST_IMG, ['sleep', '60']
Expand All @@ -1112,28 +1117,25 @@ def test_top(self):
self.client.start(container)
res = self.client.top(container)
if not IS_WINDOWS_PLATFORM:
assert res['Titles'] == [
'UID', 'PID', 'PPID', 'C', 'STIME', 'TTY', 'TIME', 'CMD'
]
assert res['Titles'] == [u'PID', u'USER', u'TIME', u'COMMAND']
assert len(res['Processes']) == 1
assert res['Processes'][0][-1] == 'sleep 60'
self.client.kill(container)

@pytest.mark.skipif(
IS_WINDOWS_PLATFORM, reason='No psargs support on windows'
)
@pytest.mark.xfail(reason='Output of docker top depends on host distro, '
'and is not formalized.')
def test_top_with_psargs(self):
container = self.client.create_container(
TEST_IMG, ['sleep', '60'])

self.tmp_containers.append(container)

self.client.start(container)
res = self.client.top(container, 'waux')
assert res['Titles'] == [
'USER', 'PID', '%CPU', '%MEM', 'VSZ', 'RSS',
'TTY', 'STAT', 'START', 'TIME', 'COMMAND'
]
res = self.client.top(container, '-eopid,user')
assert res['Titles'] == [u'PID', u'USER']
assert len(res['Processes']) == 1
assert res['Processes'][0][10] == 'sleep 60'

Expand Down
7 changes: 7 additions & 0 deletions tests/integration/context_api_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,10 @@ def test_context_remove(self):
ContextAPI.remove_context("test")
with pytest.raises(errors.ContextNotFound):
ContextAPI.inspect_context("test")

def test_load_context_without_orchestrator(self):
ContextAPI.create_context("test")
ctx = ContextAPI.get_context("test")
assert ctx
assert ctx.Name == "test"
assert ctx.Orchestrator is None
4 changes: 4 additions & 0 deletions tests/unit/context_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ def test_default_in_context_list(self):
def test_get_current_context(self):
assert ContextAPI.get_current_context().Name == "default"

def test_https_host(self):
c = Context("test", host="tcp://testdomain:8080", tls=True)
assert c.Host == "https://testdomain:8080"

def test_context_inspect_without_params(self):
ctx = ContextAPI.inspect_context()
assert ctx["Name"] == "default"
Expand Down