Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
e688c09
Bump requests dependency in requirements.txt (CVE-2018-18074)
shin- Oct 29, 2018
b36124d
Merge pull request #2161 from docker/bump_requests
shin- Oct 30, 2018
a3111d9
Add xfail to ignore 18.09 beta bug
shin- Nov 1, 2018
dd7386d
Update version detection script for CI
shin- Nov 1, 2018
479f13e
Add paramiko requirement for SSH transport
shin- Nov 1, 2018
338dfb0
Add support for SSH protocol in base_url
shin- Nov 1, 2018
f4e9a1d
Remove misleading fileno method from NpipeSocket class
shin- Nov 1, 2018
1df021e
Update tests for ssh protocol compatibility
shin- Nov 1, 2018
94aa9a8
Update tests to properly dispose of client instances in tearDown
shin- Nov 1, 2018
6bfe200
Clear error for cancellable streams over SSH
shin- Nov 1, 2018
f302756
Rewrite utils.parse_host to detect more invalid addresses.
shin- Nov 1, 2018
490b2db
Add a missing space in a log message
adamtheturtle Nov 5, 2018
c9bee77
Merge pull request #2168 from adamtheturtle/patch-1
shin- Nov 5, 2018
7252086
Merge pull request #2165 from docker/ssh_protocol_support
shin- Nov 6, 2018
e237c0e
Add named parameter to image.save to identify which repository name t…
shin- Nov 6, 2018
5467658
Merge pull request #2169 from docker/2124-image-save-with-name
shin- Nov 8, 2018
9987c1b
Fix docs examples to work with Python 3
shin- Nov 8, 2018
1d124a1
Improve ulimits documentation
shin- Nov 8, 2018
d5bc46a
Improved LogConfig documentation
shin- Nov 9, 2018
6064947
Update links docs and fix bug in normalize_links
shin- Nov 9, 2018
6bfe4c9
Document attr caching for Container objects
shin- Nov 9, 2018
b927a5f
Fix incorrect return info for inspect_service
shin- Nov 9, 2018
89ee08f
Disallow incompatible combination stats(decode=True, stream=False)
shin- Nov 9, 2018
f83fe7c
Properly convert non-string filters to expected string format
shin- Nov 9, 2018
cebdee4
Add doc example for get_archive
shin- Nov 9, 2018
852d79b
Fix file mode in image.save examples
shin- Nov 9, 2018
35b9460
Remove prematurely committed file
shin- Nov 9, 2018
302cb78
Merge pull request #2172 from docker/fix_docs
shin- Nov 9, 2018
f7a1052
Fix versions script to accept versions without -ce suffix
shin- Nov 9, 2018
47c10aa
tests: fix failure due to pytest deprecation
little-dude Nov 22, 2018
493d7f0
tests: bump pytest-timeout
little-dude Nov 22, 2018
3fca75f
Fixes return value models.containers.Container.exec_run.__doc__
funkyfuture Nov 27, 2018
f3231a1
Merge pull request #2178 from little-dude/fix_deprecation
shin- Nov 27, 2018
1146301
Correctly handle longpath prefix in process_dockerfile when joining p…
shin- Nov 27, 2018
e1e4048
Merge pull request #2183 from docker/c6356-longpath-prefix
shin- Nov 27, 2018
5f157bb
implement stream demultiplexing for exec commands
little-dude Oct 8, 2018
a74d546
Fix pulling images with `stream=True`
adw1n Sep 3, 2018
c53423f
Update DockerClient.images.pull to always stream response
shin- Nov 28, 2018
042a0e5
Merge pull request #2186 from docker/adw1n-i2116
shin- Nov 28, 2018
6540900
add tests for _read_from_socket
little-dude Nov 28, 2018
76447d0
tests various exec_create/exec_start combinations
little-dude Nov 28, 2018
80e862a
Merge branch 'release'
shin- Nov 28, 2018
9a67e20
Next dev version
shin- Nov 28, 2018
41c0eb7
fix exec_start() documentation
little-dude Nov 28, 2018
7b3b83d
fix exec api inconsistency
little-dude Nov 28, 2018
bc5d7c8
Modernize auth management
shin- Nov 29, 2018
01ccaa6
Make AuthConfig a dict subclass for backward-compatibility
shin- Nov 30, 2018
bef10ec
Add credstore_env to all load_config calls
shin- Nov 30, 2018
cc38efa
Add some credHelpers tests
shin- Nov 30, 2018
6663881
Merge pull request #2181 from funkyfuture/exec_run_docs
shin- Nov 30, 2018
ee6ec4c
Merge branch 'master' of https://github.com/little-dude/docker-py int…
shin- Nov 30, 2018
b2ad302
Fix test names
shin- Nov 30, 2018
16c2809
Move exec_run example to user guides section of docs
shin- Nov 30, 2018
b72fb1e
Merge branch 'little-dude-master'
shin- Nov 30, 2018
c344660
Merge pull request #2188 from docker/c6374-credhelpers
shin- Nov 30, 2018
bc84ed1
Fix empty authconfig detection
shin- Nov 30, 2018
5c74846
Merge pull request #2192 from docker/authconfig_fix
shin- Dec 1, 2018
3381f7b
Update setup.py for modern pypi / setuptools
shin- Dec 1, 2018
1125004
Merge pull request #2193 from docker/update_setup_py
shin- Dec 1, 2018
1bc5783
Prevent untracked files in releases
shin- Dec 7, 2018
9223655
Merge pull request #2196 from docker/2194-clean-release
shin- Dec 8, 2018
e15db4c
Improve handling of placement preferences; improve docs
shin- Dec 8, 2018
b297b83
Dynamically retrieve version information for generated docs
shin- Dec 8, 2018
a207122
Update Jenkinsfile version map
shin- Dec 8, 2018
f39b1df
Merge pull request #2198 from docker/update_versionmap
shin- Dec 11, 2018
d77d425
Merge pull request #2197 from docker/2185-placement-prefs
shin- Dec 11, 2018
543d83c
Fixed a typo in the configs api doc
maxbischoff Dec 14, 2018
7911c54
Merge pull request #2204 from MaxBischoff/typo-fix
shin- Dec 14, 2018
341e258
Fix DeprecationWarning: invalid escape sequence in services.py
BoboTiG Dec 20, 2018
e99ce1e
Fix DeprecationWarning: invalid escape sequence in ports.py
BoboTiG Dec 20, 2018
60ffeed
Merge pull request #2208 from BoboTiG/patch-2
shin- Dec 27, 2018
3151b0e
Merge pull request #2207 from BoboTiG/patch-1
shin- Dec 27, 2018
3cda1e8
Make swarm.init() return value match documentation
shin- Dec 28, 2018
5fc7f62
Merge pull request #2213 from docker/2210-swarm-init-return
shin- Dec 29, 2018
72f4f52
Update test dependencies to latest version, fix some flake8 errors
shin- Jan 9, 2019
4ca4e94
Merge pull request #2218 from docker/fix_test_deps
shin- Jan 9, 2019
bfdd0a8
add support for proxies
little-dude Dec 12, 2018
6e22789
tests: remove outdated code
little-dude Dec 12, 2018
545adc2
add unit tests for ProxyConfig
little-dude Dec 12, 2018
4f79ba1
make the integration tests more verbose
little-dude Dec 12, 2018
0d37390
add integration tests for proxy support
little-dude Dec 12, 2018
708ef6d
Revert "make the integration tests more verbose"
little-dude Dec 15, 2018
9146dd5
code style improvement
little-dude Dec 15, 2018
f97f713
refactor ProxyConfig
little-dude Dec 15, 2018
73c17f8
fix typo in docstring
little-dude Dec 15, 2018
2c4a865
By default, disable proxy support
little-dude Dec 15, 2018
6969e8b
handle url-based proxy configurations
little-dude Dec 17, 2018
65bebc0
Style fixes and removed some unused code
shin- Jan 9, 2019
5455c04
Merge pull request #2219 from docker/2199-proxy-support
shin- Jan 9, 2019
219c521
Regression 443 test: relax status-code check
thaJeztah Jan 8, 2019
1073b73
Merge pull request #2216 from thaJeztah/fix_status_code_check
shin- Jan 9, 2019
a579e9e
Remove use_config_proxy from exec. Add use_config_proxy docs to Docke…
shin- Jan 9, 2019
55a62c2
Merge pull request #2221 from docker/proxy_env_fixes
shin- Jan 9, 2019
e6783d8
Bump 3.7.0
Jan 10, 2019
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
9 changes: 6 additions & 3 deletions Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,13 @@ def getDockerVersions = { ->
}

def getAPIVersion = { engineVersion ->
def versionMap = ['17.06': '1.30', '17.12': '1.35', '18.02': '1.36', '18.03': '1.37']
def versionMap = [
'17.06': '1.30', '17.12': '1.35', '18.02': '1.36', '18.03': '1.37',
'18.06': '1.38', '18.09': '1.39'
]
def result = versionMap[engineVersion.substring(0, 5)]
if (!result) {
return '1.37'
return '1.39'
}
return result
}
Expand Down Expand Up @@ -88,7 +91,7 @@ def runTests = { Map settings ->
--network ${testNetwork} \\
--volumes-from ${dindContainerName} \\
${testImage} \\
py.test -v -rxs tests/integration
py.test -v -rxs --cov=docker tests/
"""
} finally {
sh """
Expand Down
54 changes: 23 additions & 31 deletions docker/api/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ def build(self, path=None, tag=None, quiet=False, fileobj=None,
forcerm=False, dockerfile=None, container_limits=None,
decode=False, buildargs=None, gzip=False, shmsize=None,
labels=None, cache_from=None, target=None, network_mode=None,
squash=None, extra_hosts=None, platform=None, isolation=None):
squash=None, extra_hosts=None, platform=None, isolation=None,
use_config_proxy=False):
"""
Similar to the ``docker build`` command. Either ``path`` or ``fileobj``
needs to be set. ``path`` can be a local path (to a directory
Expand Down Expand Up @@ -103,6 +104,10 @@ def build(self, path=None, tag=None, quiet=False, fileobj=None,
platform (str): Platform in the format ``os[/arch[/variant]]``
isolation (str): Isolation technology used during build.
Default: `None`.
use_config_proxy (bool): If ``True``, and if the docker client
configuration file (``~/.docker/config.json`` by default)
contains a proxy configuration, the corresponding environment
variables will be set in the container being built.

Returns:
A generator for the build output.
Expand Down Expand Up @@ -168,6 +173,10 @@ def build(self, path=None, tag=None, quiet=False, fileobj=None,
}
params.update(container_limits)

if use_config_proxy:
proxy_args = self._proxy_configs.get_environment()
for k, v in proxy_args.items():
buildargs.setdefault(k, v)
if buildargs:
params.update({'buildargs': json.dumps(buildargs)})

Expand Down Expand Up @@ -286,48 +295,31 @@ def _set_auth_headers(self, headers):

# If we don't have any auth data so far, try reloading the config
# file one more time in case anything showed up in there.
if not self._auth_configs:
if not self._auth_configs or self._auth_configs.is_empty:
log.debug("No auth config in memory - loading from filesystem")
self._auth_configs = auth.load_config()
self._auth_configs = auth.load_config(
credstore_env=self.credstore_env
)

# Send the full auth configuration (if any exists), since the build
# could use any (or all) of the registries.
if self._auth_configs:
auth_cfgs = self._auth_configs
auth_data = {}
if auth_cfgs.get('credsStore'):
# Using a credentials store, we need to retrieve the
# credentials for each registry listed in the config.json file
# Matches CLI behavior: https://github.com/docker/docker/blob/
# 67b85f9d26f1b0b2b240f2d794748fac0f45243c/cliconfig/
# credentials/native_store.go#L68-L83
for registry in auth_cfgs.get('auths', {}).keys():
auth_data[registry] = auth.resolve_authconfig(
auth_cfgs, registry,
credstore_env=self.credstore_env,
)
else:
for registry in auth_cfgs.get('credHelpers', {}).keys():
auth_data[registry] = auth.resolve_authconfig(
auth_cfgs, registry,
credstore_env=self.credstore_env
)
for registry, creds in auth_cfgs.get('auths', {}).items():
if registry not in auth_data:
auth_data[registry] = creds
# See https://github.com/docker/docker-py/issues/1683
if auth.INDEX_NAME in auth_data:
auth_data[auth.INDEX_URL] = auth_data[auth.INDEX_NAME]
auth_data = self._auth_configs.get_all_credentials()

# See https://github.com/docker/docker-py/issues/1683
if auth.INDEX_URL not in auth_data and auth.INDEX_URL in auth_data:
auth_data[auth.INDEX_URL] = auth_data.get(auth.INDEX_NAME, {})

log.debug(
'Sending auth config ({0})'.format(
', '.join(repr(k) for k in auth_data.keys())
)
)

headers['X-Registry-Config'] = auth.encode_header(
auth_data
)
if auth_data:
headers['X-Registry-Config'] = auth.encode_header(
auth_data
)
else:
log.debug('No auth config found')

Expand Down
34 changes: 25 additions & 9 deletions docker/api/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@
from ..tls import TLSConfig
from ..transport import SSLAdapter, UnixAdapter
from ..utils import utils, check_resource, update_headers, config
from ..utils.socket import frames_iter, socket_raw_iter
from ..utils.socket import frames_iter, consume_socket_output, demux_adaptor
from ..utils.json_stream import json_stream
from ..utils.proxy import ProxyConfig
try:
from ..transport import NpipeAdapter
except ImportError:
Expand Down Expand Up @@ -114,8 +115,17 @@ def __init__(self, base_url=None, version=None,
self.headers['User-Agent'] = user_agent

self._general_configs = config.load_general_config()

proxy_config = self._general_configs.get('proxies', {})
try:
proxies = proxy_config[base_url]
except KeyError:
proxies = proxy_config.get('default', {})

self._proxy_configs = ProxyConfig.from_dict(proxies)

self._auth_configs = auth.load_config(
config_dict=self._general_configs
config_dict=self._general_configs, credstore_env=credstore_env,
)
self.credstore_env = credstore_env

Expand Down Expand Up @@ -381,19 +391,23 @@ def _stream_raw_result(self, response, chunk_size=1, decode=True):
for out in response.iter_content(chunk_size, decode):
yield out

def _read_from_socket(self, response, stream, tty=False):
def _read_from_socket(self, response, stream, tty=True, demux=False):
socket = self._get_raw_response_socket(response)

gen = None
if tty is False:
gen = frames_iter(socket)
gen = frames_iter(socket, tty)

if demux:
# The generator will output tuples (stdout, stderr)
gen = (demux_adaptor(*frame) for frame in gen)
else:
gen = socket_raw_iter(socket)
# The generator will output strings
gen = (data for (_, data) in gen)

if stream:
return gen
else:
return six.binary_type().join(gen)
# Wait for all the frames, concatenate them, and return the result
return consume_socket_output(gen, demux=demux)

def _disable_socket_timeout(self, socket):
""" Depending on the combination of python version and whether we're
Expand Down Expand Up @@ -476,4 +490,6 @@ def reload_config(self, dockercfg_path=None):
Returns:
None
"""
self._auth_configs = auth.load_config(dockercfg_path)
self._auth_configs = auth.load_config(
dockercfg_path, credstore_env=self.credstore_env
)
2 changes: 1 addition & 1 deletion docker/api/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def inspect_config(self, id):
Retrieve config metadata
Args:
id (string): Full ID of the config to remove
id (string): Full ID of the config to inspect
Returns (dict): A dictionary of metadata
Expand Down
28 changes: 22 additions & 6 deletions docker/api/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
class ContainerApiMixin(object):
@utils.check_resource('container')
def attach(self, container, stdout=True, stderr=True,
stream=False, logs=False):
stream=False, logs=False, demux=False):
"""
Attach to a container.

Expand All @@ -28,11 +28,15 @@ def attach(self, container, stdout=True, stderr=True,
stream (bool): Return container output progressively as an iterator
of strings, rather than a single string.
logs (bool): Include the container's previous output.
demux (bool): Keep stdout and stderr separate.

Returns:
By default, the container's output as a single string.
By default, the container's output as a single string (two if
``demux=True``: one for stdout and one for stderr).

If ``stream=True``, an iterator of output strings.
If ``stream=True``, an iterator of output strings. If
``demux=True``, two iterators are returned: one for stdout and one
for stderr.

Raises:
:py:class:`docker.errors.APIError`
Expand All @@ -54,8 +58,7 @@ def attach(self, container, stdout=True, stderr=True,
response = self._post(u, headers=headers, params=params, stream=True)

output = self._read_from_socket(
response, stream, self._check_is_tty(container)
)
response, stream, self._check_is_tty(container), demux=demux)

if stream:
return CancellableStream(output, response)
Expand Down Expand Up @@ -218,7 +221,8 @@ def create_container(self, image, command=None, hostname=None, user=None,
working_dir=None, domainname=None, host_config=None,
mac_address=None, labels=None, stop_signal=None,
networking_config=None, healthcheck=None,
stop_timeout=None, runtime=None):
stop_timeout=None, runtime=None,
use_config_proxy=False):
"""
Creates a container. Parameters are similar to those for the ``docker
run`` command except it doesn't support the attach options (``-a``).
Expand Down Expand Up @@ -387,6 +391,10 @@ def create_container(self, image, command=None, hostname=None, user=None,
runtime (str): Runtime to use with this container.
healthcheck (dict): Specify a test to perform to check that the
container is healthy.
use_config_proxy (bool): If ``True``, and if the docker client
configuration file (``~/.docker/config.json`` by default)
contains a proxy configuration, the corresponding environment
variables will be set in the container being created.

Returns:
A dictionary with an image 'Id' key and a 'Warnings' key.
Expand All @@ -400,6 +408,14 @@ def create_container(self, image, command=None, hostname=None, user=None,
if isinstance(volumes, six.string_types):
volumes = [volumes, ]

if isinstance(environment, dict):
environment = utils.utils.format_environment(environment)

if use_config_proxy:
environment = self._proxy_configs.inject_proxy_environment(
environment
)

config = self.create_container_config(
image, command, hostname, user, detach, stdin_open, tty,
ports, environment, volumes,
Expand Down
26 changes: 13 additions & 13 deletions docker/api/daemon.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ def events(self, since=None, until=None, filters=None, decode=None):

Example:

>>> for event in client.events()
... print event
>>> for event in client.events(decode=True)
... print(event)
{u'from': u'image/with:tag',
u'id': u'container-id',
u'status': u'start',
Expand All @@ -54,7 +54,7 @@ def events(self, since=None, until=None, filters=None, decode=None):

>>> events = client.events()
>>> for event in events:
... print event
... print(event)
>>> # and cancel from another thread
>>> events.close()
"""
Expand Down Expand Up @@ -124,13 +124,15 @@ def login(self, username, password=None, email=None, registry=None,
# If dockercfg_path is passed check to see if the config file exists,
# if so load that config.
if dockercfg_path and os.path.exists(dockercfg_path):
self._auth_configs = auth.load_config(dockercfg_path)
elif not self._auth_configs:
self._auth_configs = auth.load_config()

authcfg = auth.resolve_authconfig(
self._auth_configs, registry, credstore_env=self.credstore_env,
)
self._auth_configs = auth.load_config(
dockercfg_path, credstore_env=self.credstore_env
)
elif not self._auth_configs or self._auth_configs.is_empty:
self._auth_configs = auth.load_config(
credstore_env=self.credstore_env
)

authcfg = self._auth_configs.resolve_authconfig(registry)
# If we found an existing auth config for this registry and username
# combination, we can return it immediately unless reauth is requested.
if authcfg and authcfg.get('username', None) == username \
Expand All @@ -146,9 +148,7 @@ def login(self, username, password=None, email=None, registry=None,

response = self._post_json(self._url('/auth'), data=req_data)
if response.status_code == 200:
if 'auths' not in self._auth_configs:
self._auth_configs['auths'] = {}
self._auth_configs['auths'][registry or auth.INDEX_NAME] = req_data
self._auth_configs.add_auth(registry or auth.INDEX_NAME, req_data)
return self._result(response, json=True)

def ping(self):
Expand Down
13 changes: 8 additions & 5 deletions docker/api/exec_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ def exec_resize(self, exec_id, height=None, width=None):

@utils.check_resource('exec_id')
def exec_start(self, exec_id, detach=False, tty=False, stream=False,
socket=False):
socket=False, demux=False):
"""
Start a previously set up exec instance.

Expand All @@ -130,11 +130,14 @@ def exec_start(self, exec_id, detach=False, tty=False, stream=False,
stream (bool): Stream response data. Default: False
socket (bool): Return the connection socket to allow custom
read/write operations.
demux (bool): Return stdout and stderr separately

Returns:
(generator or str): If ``stream=True``, a generator yielding
response chunks. If ``socket=True``, a socket object for the
connection. A string containing response data otherwise.

(generator or str or tuple): If ``stream=True``, a generator
yielding response chunks. If ``socket=True``, a socket object for
the connection. A string containing response data otherwise. If
``demux=True``, stdout and stderr are separated.

Raises:
:py:class:`docker.errors.APIError`
Expand Down Expand Up @@ -162,4 +165,4 @@ def exec_start(self, exec_id, detach=False, tty=False, stream=False,
return self._result(res)
if socket:
return self._get_raw_response_socket(res)
return self._read_from_socket(res, stream, tty)
return self._read_from_socket(res, stream, tty=tty, demux=demux)
16 changes: 8 additions & 8 deletions docker/api/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -353,8 +353,8 @@ def pull(self, repository, tag=None, stream=False, auth_config=None,

Example:

>>> for line in cli.pull('busybox', stream=True):
... print(json.dumps(json.loads(line), indent=4))
>>> for line in cli.pull('busybox', stream=True, decode=True):
... print(json.dumps(line, indent=4))
{
"status": "Pulling image (latest) from busybox",
"progressDetail": {},
Expand Down Expand Up @@ -429,12 +429,12 @@ def push(self, repository, tag=None, stream=False, auth_config=None,
If the server returns an error.

Example:
>>> for line in cli.push('yourname/app', stream=True):
... print line
{"status":"Pushing repository yourname/app (1 tags)"}
{"status":"Pushing","progressDetail":{},"id":"511136ea3c5a"}
{"status":"Image already pushed, skipping","progressDetail":{},
"id":"511136ea3c5a"}
>>> for line in cli.push('yourname/app', stream=True, decode=True):
... print(line)
{'status': 'Pushing repository yourname/app (1 tags)'}
{'status': 'Pushing','progressDetail': {}, 'id': '511136ea3c5a'}
{'status': 'Image already pushed, skipping', 'progressDetail':{},
'id': '511136ea3c5a'}
...

"""
Expand Down
Loading