mirror of https://github.com/docker/docker-py.git
Private images support in create_service / update_service
Refactor auth header computation Add tasks methods and documentation. Signed-off-by: Joffrey F <joffrey@docker.com>
This commit is contained in:
parent
7d5a1eeb7a
commit
775b581c04
|
|
@ -166,28 +166,10 @@ class ImageApiMixin(object):
|
||||||
headers = {}
|
headers = {}
|
||||||
|
|
||||||
if utils.compare_version('1.5', self._version) >= 0:
|
if utils.compare_version('1.5', self._version) >= 0:
|
||||||
# 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 auth_config is None:
|
if auth_config is None:
|
||||||
log.debug('Looking for auth config')
|
header = auth.get_config_header(self, registry)
|
||||||
if not self._auth_configs:
|
if header:
|
||||||
log.debug(
|
headers['X-Registry-Auth'] = header
|
||||||
"No auth config in memory - loading from filesystem"
|
|
||||||
)
|
|
||||||
self._auth_configs = auth.load_config()
|
|
||||||
authcfg = auth.resolve_authconfig(self._auth_configs, registry)
|
|
||||||
# Do not fail here if no authentication exists for this
|
|
||||||
# specific registry as we can have a readonly pull. Just
|
|
||||||
# put the header if we can.
|
|
||||||
if authcfg:
|
|
||||||
log.debug('Found auth config')
|
|
||||||
# auth_config needs to be a dict in the format used by
|
|
||||||
# auth.py username , password, serveraddress, email
|
|
||||||
headers['X-Registry-Auth'] = auth.encode_header(
|
|
||||||
authcfg
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
log.debug('No auth config found')
|
|
||||||
else:
|
else:
|
||||||
log.debug('Sending supplied auth config')
|
log.debug('Sending supplied auth config')
|
||||||
headers['X-Registry-Auth'] = auth.encode_header(auth_config)
|
headers['X-Registry-Auth'] = auth.encode_header(auth_config)
|
||||||
|
|
@ -222,21 +204,10 @@ class ImageApiMixin(object):
|
||||||
headers = {}
|
headers = {}
|
||||||
|
|
||||||
if utils.compare_version('1.5', self._version) >= 0:
|
if utils.compare_version('1.5', self._version) >= 0:
|
||||||
# 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 auth_config is None:
|
if auth_config is None:
|
||||||
log.debug('Looking for auth config')
|
header = auth.get_config_header(self, registry)
|
||||||
if not self._auth_configs:
|
if header:
|
||||||
log.debug(
|
headers['X-Registry-Auth'] = header
|
||||||
"No auth config in memory - loading from filesystem"
|
|
||||||
)
|
|
||||||
self._auth_configs = auth.load_config()
|
|
||||||
authcfg = auth.resolve_authconfig(self._auth_configs, registry)
|
|
||||||
# Do not fail here if no authentication exists for this
|
|
||||||
# specific registry as we can have a readonly pull. Just
|
|
||||||
# put the header if we can.
|
|
||||||
if authcfg:
|
|
||||||
headers['X-Registry-Auth'] = auth.encode_header(authcfg)
|
|
||||||
else:
|
else:
|
||||||
log.debug('Sending supplied auth config')
|
log.debug('Sending supplied auth config')
|
||||||
headers['X-Registry-Auth'] = auth.encode_header(auth_config)
|
headers['X-Registry-Auth'] = auth.encode_header(auth_config)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
|
from .. import errors
|
||||||
from .. import utils
|
from .. import utils
|
||||||
|
from ..auth import auth
|
||||||
|
|
||||||
|
|
||||||
class ServiceApiMixin(object):
|
class ServiceApiMixin(object):
|
||||||
|
|
@ -8,6 +10,16 @@ class ServiceApiMixin(object):
|
||||||
update_config=None, networks=None, endpoint_config=None
|
update_config=None, networks=None, endpoint_config=None
|
||||||
):
|
):
|
||||||
url = self._url('/services/create')
|
url = self._url('/services/create')
|
||||||
|
headers = {}
|
||||||
|
image = task_template.get('ContainerSpec', {}).get('Image', None)
|
||||||
|
if image is None:
|
||||||
|
raise errors.DockerException(
|
||||||
|
'Missing mandatory Image key in ContainerSpec'
|
||||||
|
)
|
||||||
|
registry, repo_name = auth.resolve_repository_name(image)
|
||||||
|
auth_header = auth.get_config_header(self, registry)
|
||||||
|
if auth_header:
|
||||||
|
headers['X-Registry-Auth'] = auth_header
|
||||||
data = {
|
data = {
|
||||||
'Name': name,
|
'Name': name,
|
||||||
'Labels': labels,
|
'Labels': labels,
|
||||||
|
|
@ -17,7 +29,9 @@ class ServiceApiMixin(object):
|
||||||
'Networks': networks,
|
'Networks': networks,
|
||||||
'Endpoint': endpoint_config
|
'Endpoint': endpoint_config
|
||||||
}
|
}
|
||||||
return self._result(self._post_json(url, data=data), True)
|
return self._result(
|
||||||
|
self._post_json(url, data=data, headers=headers), True
|
||||||
|
)
|
||||||
|
|
||||||
@utils.minimum_version('1.24')
|
@utils.minimum_version('1.24')
|
||||||
@utils.check_resource
|
@utils.check_resource
|
||||||
|
|
@ -25,6 +39,12 @@ class ServiceApiMixin(object):
|
||||||
url = self._url('/services/{0}', service)
|
url = self._url('/services/{0}', service)
|
||||||
return self._result(self._get(url), True)
|
return self._result(self._get(url), True)
|
||||||
|
|
||||||
|
@utils.minimum_version('1.24')
|
||||||
|
@utils.check_resource
|
||||||
|
def inspect_task(self, task):
|
||||||
|
url = self._url('/tasks/{0}', task)
|
||||||
|
return self._result(self._get(url), True)
|
||||||
|
|
||||||
@utils.minimum_version('1.24')
|
@utils.minimum_version('1.24')
|
||||||
@utils.check_resource
|
@utils.check_resource
|
||||||
def remove_service(self, service):
|
def remove_service(self, service):
|
||||||
|
|
@ -41,6 +61,14 @@ class ServiceApiMixin(object):
|
||||||
url = self._url('/services')
|
url = self._url('/services')
|
||||||
return self._result(self._get(url, params=params), True)
|
return self._result(self._get(url, params=params), True)
|
||||||
|
|
||||||
|
@utils.minimum_version('1.24')
|
||||||
|
def tasks(self, filters=None):
|
||||||
|
params = {
|
||||||
|
'filters': utils.convert_filters(filters) if filters else None
|
||||||
|
}
|
||||||
|
url = self._url('/tasks')
|
||||||
|
return self._result(self._get(url, params=params), True)
|
||||||
|
|
||||||
@utils.minimum_version('1.24')
|
@utils.minimum_version('1.24')
|
||||||
@utils.check_resource
|
@utils.check_resource
|
||||||
def update_service(self, service, version, task_template=None, name=None,
|
def update_service(self, service, version, task_template=None, name=None,
|
||||||
|
|
@ -48,6 +76,7 @@ class ServiceApiMixin(object):
|
||||||
networks=None, endpoint_config=None):
|
networks=None, endpoint_config=None):
|
||||||
url = self._url('/services/{0}/update', service)
|
url = self._url('/services/{0}/update', service)
|
||||||
data = {}
|
data = {}
|
||||||
|
headers = {}
|
||||||
if name is not None:
|
if name is not None:
|
||||||
data['Name'] = name
|
data['Name'] = name
|
||||||
if labels is not None:
|
if labels is not None:
|
||||||
|
|
@ -55,6 +84,12 @@ class ServiceApiMixin(object):
|
||||||
if mode is not None:
|
if mode is not None:
|
||||||
data['Mode'] = mode
|
data['Mode'] = mode
|
||||||
if task_template is not None:
|
if task_template is not None:
|
||||||
|
image = task_template.get('ContainerSpec', {}).get('Image', None)
|
||||||
|
if image is not None:
|
||||||
|
registry, repo_name = auth.resolve_repository_name(image)
|
||||||
|
auth_header = auth.get_config_header(self, registry)
|
||||||
|
if auth_header:
|
||||||
|
headers['X-Registry-Auth'] = auth_header
|
||||||
data['TaskTemplate'] = task_template
|
data['TaskTemplate'] = task_template
|
||||||
if update_config is not None:
|
if update_config is not None:
|
||||||
data['UpdateConfig'] = update_config
|
data['UpdateConfig'] = update_config
|
||||||
|
|
@ -63,6 +98,8 @@ class ServiceApiMixin(object):
|
||||||
if endpoint_config is not None:
|
if endpoint_config is not None:
|
||||||
data['Endpoint'] = endpoint_config
|
data['Endpoint'] = endpoint_config
|
||||||
|
|
||||||
resp = self._post_json(url, data=data, params={'version': version})
|
resp = self._post_json(
|
||||||
|
url, data=data, params={'version': version}, headers=headers
|
||||||
|
)
|
||||||
self._raise_for_status(resp)
|
self._raise_for_status(resp)
|
||||||
return True
|
return True
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,26 @@ def resolve_index_name(index_name):
|
||||||
return index_name
|
return index_name
|
||||||
|
|
||||||
|
|
||||||
|
def get_config_header(client, registry):
|
||||||
|
log.debug('Looking for auth config')
|
||||||
|
if not client._auth_configs:
|
||||||
|
log.debug(
|
||||||
|
"No auth config in memory - loading from filesystem"
|
||||||
|
)
|
||||||
|
client._auth_configs = load_config()
|
||||||
|
authcfg = resolve_authconfig(client._auth_configs, registry)
|
||||||
|
# Do not fail here if no authentication exists for this
|
||||||
|
# specific registry as we can have a readonly pull. Just
|
||||||
|
# put the header if we can.
|
||||||
|
if authcfg:
|
||||||
|
log.debug('Found auth config')
|
||||||
|
# auth_config needs to be a dict in the format used by
|
||||||
|
# auth.py username , password, serveraddress, email
|
||||||
|
return encode_header(authcfg)
|
||||||
|
log.debug('No auth config found')
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def split_repo_name(repo_name):
|
def split_repo_name(repo_name):
|
||||||
parts = repo_name.split('/', 1)
|
parts = repo_name.split('/', 1)
|
||||||
if len(parts) == 1 or (
|
if len(parts) == 1 or (
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,12 @@ class TaskTemplate(dict):
|
||||||
class ContainerSpec(dict):
|
class ContainerSpec(dict):
|
||||||
def __init__(self, image, command=None, args=None, env=None, workdir=None,
|
def __init__(self, image, command=None, args=None, env=None, workdir=None,
|
||||||
user=None, labels=None, mounts=None, stop_grace_period=None):
|
user=None, labels=None, mounts=None, stop_grace_period=None):
|
||||||
|
from ..utils import split_command # FIXME: circular import
|
||||||
|
|
||||||
self['Image'] = image
|
self['Image'] = image
|
||||||
|
|
||||||
|
if isinstance(command, six.string_types):
|
||||||
|
command = split_command(command)
|
||||||
self['Command'] = command
|
self['Command'] = command
|
||||||
self['Args'] = args
|
self['Args'] = args
|
||||||
|
|
||||||
|
|
|
||||||
21
docs/api.md
21
docs/api.md
|
|
@ -666,6 +666,16 @@ Create a service, similar to the `docker service create` command. See the
|
||||||
Retrieve information about the current Swarm.
|
Retrieve information about the current Swarm.
|
||||||
See the [Swarm documentation](swarm.md#clientinspect_swarm).
|
See the [Swarm documentation](swarm.md#clientinspect_swarm).
|
||||||
|
|
||||||
|
## inspect_task
|
||||||
|
|
||||||
|
Retrieve information about a task.
|
||||||
|
|
||||||
|
**Params**:
|
||||||
|
|
||||||
|
* task (str): Task identifier
|
||||||
|
|
||||||
|
**Returns** (dict): Task information dictionary
|
||||||
|
|
||||||
## inspect_volume
|
## inspect_volume
|
||||||
|
|
||||||
Retrieve volume info by name.
|
Retrieve volume info by name.
|
||||||
|
|
@ -1055,6 +1065,17 @@ Tag an image into a repository. Identical to the `docker tag` command.
|
||||||
|
|
||||||
**Returns** (bool): True if successful
|
**Returns** (bool): True if successful
|
||||||
|
|
||||||
|
## tasks
|
||||||
|
|
||||||
|
Retrieve a list of tasks.
|
||||||
|
|
||||||
|
**Params**:
|
||||||
|
|
||||||
|
* filters (dict): A map of filters to process on the tasks list. Valid filters:
|
||||||
|
`id`, `name`, `service`, `node`, `label` and `desired-state`.
|
||||||
|
|
||||||
|
**Returns** (list): List of task dictionaries.
|
||||||
|
|
||||||
## top
|
## top
|
||||||
Display the running processes of a container.
|
Display the running processes of a container.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import random
|
import random
|
||||||
|
|
||||||
import docker
|
import docker
|
||||||
# import pytest
|
|
||||||
|
|
||||||
from ..base import requires_api_version
|
from ..base import requires_api_version
|
||||||
from .. import helpers
|
from .. import helpers
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue