When pulling an image using Docker 1.8, it seems the output
JSON stream has an empty dict at the very end. This causes
ansible to fail when pulling an image, as it's expecting a
status message in that dict which it uses to determine whether
it had to download the image or not. As a bit of an ugly hack
for that which remains backward compatible, try the last item
in the stream, and if it's an empty dict, take the last-but-one
item instead.
The strip() is needed as the exact value appears to be '{}/r/n';
we could just match that, but it seems like the kind of thing
where maybe it'd happen to just be '{}/n' or '{}' or something
in some cases, so let's just use strip() in case.
A recent change [1] in docker between v1.8.2 and v1.8.3 changed what
is returned in the json when inspecting an image. Five variables which
could have been expected before will now be omited when empty. Only
one of those variables is being addressed in the docker, ExposedPorts.
Unfortunately there was also no API version change on this so this
can't be easily corrected with pinning the API to the older version.
This does a get() which will return None if the variable is not in the
dict formed from the json that was returned. Everything else works the
same way.
[1] 9098628b29
Before this patch:
- Command was matched if 'Command' field of docker-py
representation of Docker container ends with 'command' passed
to Ansible docker module by user.
- That can give false positives and false negatives.
- For example:
a) If 'command' was set up with more than one spaces,
like 'command=sleep 123', it would be never matched again
with a container(s) launched by this task.
Because after launching, command would be normalized and
appear, in docker-py API call, just as 'sleep 123' - with one
space. This is false negative case.
b) If 'entrypoint + command = command', for example
'sleep + 123 = sleep 123', module would give false positive
match.
This patch fixes it, by making matching more explicit - against
'Config'->Cmd' field of 'docker inspect' output, provided by docker-py
API and with proper normalization of user input by splitting it to
tokens with 'shlex.split()'.
this to determine the location of the Memory value depending on the version used.
In v1.18 and earlier it was ['Config']['Memory'], but in v1.19 it
changed to ['HostConfig']['Memory'].
This is mlosev's patch (from #1208), rebased against devel as of
2790af2. It resolves#1707, which was caused by an API incompatibility
between the docker module and server API version 1.19.
There was a catch-all `except` statement in `create_containers`:
try:
containers = do_create(count, params)
except:
self.pull_image()
containers = do_create(count, params)
This would mask a variety of errors that should be exposed, including
API compatability errors (as in #1707) and common Python exceptions (KeyError, ValueError, etc) that could result from errors in the code.
This change makes the `except` statement more specific, and only attempts to pull the image and start a container if the original create attempt failed due to a 404 error from the docker API.
The `docker` Python module only accepts `None` or `'host'` as arguments.
This makes it difficult to conditionally set the `pid` attribute using
standard Ansible syntax.
This change converts any value that evaluates as boolean `False` to
`None`, which includes empty strings:
pid:
As well as an explicit `false`:
pid: false
This permits the following to work as intended:
- hosts: localhost
tasks:
- name: starting container
docker:
docker_api_version: 1.18
image: larsks/mini-httpd
name: web
pid: "{{ container_pid|default('') }}"
If `container_pid` is set to `host` somewhere, this will create a
Docker container with `pid=host`; otherwise, this will create a
container with normal isolated pid namespace.
If `docker.__version__` contains non-digit characters, such as:
>>> import docker
>>> docker.__version__
'1.4.0-dev'
Then `get_docker_py_versioninfo` will fail with:
ValueError: invalid literal for int() with base 10: '0-de'
This patch corrects the parsing of the version string so that
`get_docker_py_versioninfo` in this example would return:
(1, 4, 0, '-dev')
port mapping with this module only works for ports that are exposed either in the Dockerfile or via an additional arguments. This is different from the command line docker client, that is willing to also map ports that are not exposed.
This comments makes the behaviour more obvious.
By default docker-py uses latest version of Docker API. This is not
always desireable, and this patch adds option to specify version, that
should be used.
* Fix docs to specify when python2.6+ is required (due to a library
dep). This helps us know when it is okay to use python2.6+ syntax in
the file.
* remove BabyJson returns. See #1211 This commit fixes all but the
openstack modules.
* Use if __name__ == '__main__' to only run the main part of the module
if the module is run as a program. This allows for the potential to
unittest the code later.
This will account for settings that are provided by the hierarchy of
Dockerfiles used to construct your image, rather than only accounting
for settings provided to the module directly.
Organize each state into a distinct function for readability and composability.
Rework `present` to create but not start containers. Add a `restarted` state
to unconditionally restart a container and a `reloaded` state to restart a
container if and only if its configuration is incorrect. Store our most recent
knowledge about container states in a ContainerSet object. Improve the value
registered by this task to include not only the inspect data from any changed
containers, but also action counters in their native form, a summary message
for all actions taken, and a `reload_reasons` key to store a human-readable
diagnostic to determine why each container was reloaded.
This allows setting the pid namespace for a container. Currently only
the 'host' pid namespace is supported.
This requires Docker 1.4.1 and docker-py 1.0.0
Don't pass the volumes_from argument to the Docker create_container method.
If the volumes_from argument is passed to the create_container method, Docker
raises the following exception:
docker.errors.DockerException: 'volumes_from' parameter has no effect on
create_container(). It has been moved to start()
If bind-volumes are submitted to docker >= 1.4.0 with the volumes set in addition to the binds, docker will create a regular volume and not bind-mount the specified path.
Starting from docker-py>=0.5.0 it is impossible to work with private registries based on HTTP.
So we need additional parameter to allow pull from insecure registry
Related to ansible/ansible#9111
Since 0.11 Docker supports different networking modes (see docker run
--net). This commit add support for that to the ansible docker module.
This depends on
2d58351164
The JSON the Docker API returns includes the container's ENTRYPOINT value (if it has one) with the 'Command' value. So instead of checking if `container['Command'] == module.params['command']`, we just check that `container['Command'].endswith(module.params['command'])` so the entrypoint won't affect a container being properly classified as matching the module params or not.
Also I refactored a super-long `if` statement into some temporary variables - I did it to help me figure out what was going wrong, and then it makes the code more readable so I kept it.
As part of being updated for the 1.10 API, a couple of parameters were passed to the docker.client.start() command that it doesn't accept. This caused the module to error out if it tried to start any Docker containers. This removes those parameters so the module works again.
The new present state just makes sure that a container exists, not that
it's running, although it get started one creation.
This is very useful for data volumes. This also changes the old
present, now running (default) state to only create the container if
it's not found, otherwise it just get started.
See also discussion on mailinglist:
https://groups.google.com/forum/#!topic/ansible-devel/jB84gdhPzLQ
This closes#6395