Repository: ansible/ansible
Pull request: docker_image_info: improve docs
##### SUMMARY
Fixes #60605. Improves docs on return value and how to check for local image existence.

##### ISSUE TYPE
- Docs Pull Request

##### COMPONENT NAME
docker_image_info


Problem statement:
docker_image_info does not pull image automatically
<!--- Verify first that your issue is not already reported on GitHub -->
<!--- Also test if the latest release and devel branch are affected too -->
<!--- Complete *all* sections as described, this form is processed automatically -->

##### SUMMARY
<!--- Explain the problem briefly below -->
When using ~~docker_container_info~~ docker_image_info - if the image has not been pulled previously, it doesn't return anything (empty images) - although the run is successful.

It returns "images: []"

##### ISSUE TYPE
- Bug Report

##### COMPONENT NAME
<!--- Write the short name of the module, plugin, task or feature below, use your best guess if unsure -->
docker_image_info

##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes -->
```paste below
ansible 2.8.3
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.6/site-packages/ansible
  executable location = /usr/local/bin/ansible
  python version = 3.6.8 (default, Apr 25 2019, 21:02:35) [GCC 4.8.5 20150623 (Red Hat 4.8.5-36)]
```

##### CONFIGURATION
<!--- Paste verbatim output from "ansible-config dump --only-changed" between quotes -->
```paste below
empty
```

##### OS / ENVIRONMENT
<!--- Provide all relevant information below, e.g. target OS versions, network device firmware, etc. -->
CentOS 7.6

##### STEPS TO REPRODUCE
<!--- Describe exactly how to reproduce the problem, using a minimal test-case -->
Run the following playbook (without first pulling the image) - it will return images: [], but after pulling the image either by docker pull or or docker_container module - it works.

<!--- Paste example playbooks or commands between quotes below -->
```yaml
---
- hosts: localhost
  tasks:
  - name: Fetch info
    docker_image_info:
      name: kolla/ubuntu-source-fluentd:master
    register: fluentd_info

  - name: Print info
    debug:
      var: fluentd_info
```

<!--- HINT: You can paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- Describe what you expected to happen when running the steps above -->
If Docker image is not known to Docker engine - it should automatically pull the image.
Of course the output should be all Docker image info - not empty images: []

At least if this is correct behaviour - it should at least fail printing out that the Docker image is unknown/unpulled/anything.

##### ACTUAL RESULTS
<!--- Describe what actually happened. If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes -->
```paste below
TASK [common : Fetch fluentd image labels] *************************************
task path: /home/zuul/src/opendev.org/openstack/kolla-ansible/ansible/roles/common/tasks/config.yml:15
Using module file /usr/lib/python2.7/site-packages/ansible/modules/cloud/docker/docker_image_facts.py
<23.253.156.234> ESTABLISH SSH CONNECTION FOR USER: kolla
<23.253.156.234> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o 'IdentityFile="/home/zuul/.ssh/id_rsa_kolla"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=kolla -o ConnectTimeout=10 -o ControlPath=/home/zuul/.ansible/cp/32d0df4699 23.253.156.234 '/bin/sh -c '"'"'echo ~kolla && sleep 0'"'"''
<23.253.156.234> (0, '/home/kolla\n', '')
<23.253.156.234> ESTABLISH SSH CONNECTION FOR USER: kolla
<23.253.156.234> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o 'IdentityFile="/home/zuul/.ssh/id_rsa_kolla"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=kolla -o ConnectTimeout=10 -o ControlPath=/home/zuul/.ansible/cp/32d0df4699 23.253.156.234 '/bin/sh -c '"'"'( umask 77 && mkdir -p "` echo /home/kolla/.ansible/tmp/ansible-tmp-1565804195.42-162435853764977 `" && echo ansible-tmp-1565804195.42-162435853764977="` echo /home/kolla/.ansible/tmp/ansible-tmp-1565804195.42-162435853764977 `" ) && sleep 0'"'"''
<23.253.156.234> (0, 'ansible-tmp-1565804195.42-162435853764977=/home/kolla/.ansible/tmp/ansible-tmp-1565804195.42-162435853764977\n', '')
<23.253.156.234> PUT /home/zuul/.ansible/tmp/ansible-local-25260JN6G05/tmpWgzb8R TO /home/kolla/.ansible/tmp/ansible-tmp-1565804195.42-162435853764977/docker_image_facts.py
<23.253.156.234> SSH: EXEC sftp -b - -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o 'IdentityFile="/home/zuul/.ssh/id_rsa_kolla"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=kolla -o ConnectTimeout=10 -o ControlPath=/home/zuul/.ansible/cp/32d0df4699 '[23.253.156.234]'
<23.253.156.234> (0, 'sftp> put /home/zuul/.ansible/tmp/ansible-local-25260JN6G05/tmpWgzb8R /home/kolla/.ansible/tmp/ansible-tmp-1565804195.42-162435853764977/docker_image_facts.py\n', '')
<23.253.156.234> ESTABLISH SSH CONNECTION FOR USER: kolla
<23.253.156.234> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o 'IdentityFile="/home/zuul/.ssh/id_rsa_kolla"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=kolla -o ConnectTimeout=10 -o ControlPath=/home/zuul/.ansible/cp/32d0df4699 23.253.156.234 '/bin/sh -c '"'"'chmod u+x /home/kolla/.ansible/tmp/ansible-tmp-1565804195.42-162435853764977/ /home/kolla/.ansible/tmp/ansible-tmp-1565804195.42-162435853764977/docker_image_facts.py && sleep 0'"'"''
<23.253.156.234> (0, '', '')
<23.253.156.234> ESTABLISH SSH CONNECTION FOR USER: kolla
<23.253.156.234> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o 'IdentityFile="/home/zuul/.ssh/id_rsa_kolla"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=kolla -o ConnectTimeout=10 -o ControlPath=/home/zuul/.ansible/cp/32d0df4699 -tt 23.253.156.234 '/bin/sh -c '"'"'/usr/bin/python /home/kolla/.ansible/tmp/ansible-tmp-1565804195.42-162435853764977/docker_image_facts.py && sleep 0'"'"''
<23.253.156.234> (0, '\r\n{"images": [], "invocation": {"module_args": {"filter_logger": false, "tls": null, "cacert_path": null, "name": ["10.208.193.113:4000/lokolla/centos-source-fluentd:change_676413"], "ssl_version": null, "tls_hostname": null, "docker_host": null, "tls_verify": null, "key_path": null, "timeout": null, "debug": false, "cert_path": null, "api_version": null}}, "changed": false}\r\n', 'Shared connection to 23.253.156.234 closed.\r\n')
<23.253.156.234> ESTABLISH SSH CONNECTION FOR USER: kolla
<23.253.156.234> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o 'IdentityFile="/home/zuul/.ssh/id_rsa_kolla"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=kolla -o ConnectTimeout=10 -o ControlPath=/home/zuul/.ansible/cp/32d0df4699 23.253.156.234 '/bin/sh -c '"'"'rm -f -r /home/kolla/.ansible/tmp/ansible-tmp-1565804195.42-162435853764977/ > /dev/null 2>&1 && sleep 0'"'"''
<23.253.156.234> (0, '', '')
ok: [primary] => {
    "changed": false, 
    "images": [], 
    "invocation": {
        "module_args": {
            "api_version": null, 
            "cacert_path": null, 
            "cert_path": null, 
            "debug": false, 
            "docker_host": null, 
            "filter_logger": false, 
            "key_path": null, 
            "name": [
                "10.208.193.113:4000/lokolla/centos-source-fluentd:change_676413"
            ], 
            "ssl_version": null, 
            "timeout": null, 
            "tls": null, 
            "tls_hostname": null, 
            "tls_verify": null
        }
    }
}
```

Hints from issue discussion:
Files identified in the description:
* [`lib/ansible/modules/cloud/docker/docker_container_info.py`](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/cloud/docker/docker_container_info.py)

If these files are inaccurate, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
cc @DBendit @WojciechowskiPiotr @akshay196 @danihodovic @dariko @felixfontein @jwitko @kassiansun @tbouvet
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
This issue seems to be about `docker_image_info`, not about `docker_container_info`, right?

Anyway, also for `docker_image_info`, this is not a bug, but the intended behavior. If you want to pull the image, or make sure it is pulled, use the `docker_image` module. The `docker_image_info` is an info module, and it is not supposed to change something. So pulling is out of question.

Also, by returning an empty list `[]`, it is telling you that it couldn't find the image (locally). Otherwise, the list would not be empty.
cc @DBendit @WojciechowskiPiotr @akshay196 @danihodovic @dariko @felixfontein @jwitko @kassiansun @tbouvet
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
Correct, docker_image_info.
Ok - if that’s the intended behaviour - please update the docs - because it doesn’t say what does it mean, when Ansible prints an empty variable :-)

Commit message: Improve example.

Patch to review:
diff --git a/lib/ansible/modules/cloud/docker/docker_image_info.py b/lib/ansible/modules/cloud/docker/docker_image_info.py
index c1027162d5c1c3..dab9d19abb67b4 100644
--- a/lib/ansible/modules/cloud/docker/docker_image_info.py
+++ b/lib/ansible/modules/cloud/docker/docker_image_info.py
@@ -22,6 +22,11 @@
 
 description:
      - Provide one or more image names, and the module will inspect each, returning an array of inspection results.
+     - Non-existing images will not be added to the result list. I.e. if you want to check whether an image exists
+       locally, you can call the module with this image, and check whether the result list is empty (image does not
+       exist) or has one element (the image exists locally).
+     - The module will not attempt to pull images from registries. Use M(docker_image) with I(source) set to O(pull)
+       to ensure an image is pulled.
 
 notes:
      - This module was called C(docker_image_facts) before Ansible 2.8. The usage did not change.
@@ -49,7 +54,6 @@
 '''
 
 EXAMPLES = '''
-
 - name: Inspect a single image
   docker_image_info:
     name: pacur/centos-7
@@ -59,13 +63,21 @@
     name:
       - pacur/centos-7
       - sinatra
+  register: result
+
+- name: Make sure that both images pacur/centos-7 and sinatra exist locally
+  assert:
+    that:
+      - result.images | length == 2
 '''
 
 RETURN = '''
 images:
-    description: Facts for the selected images.
+    description:
+      - Inspection results for the selected images.
+      - The list only contains inspection results of images existing locally.
     returned: always
-    type: dict
+    type: list
     sample: [
         {
             "Architecture": "amd64",


Code review comments:
diff_hunk: @@ -22,6 +22,11 @@
 
 description:
      - Provide one or more image names, and the module will inspect each, returning an array of inspection results.
+     - Non-existing images will not be added to the result list. I.e. if you want to check whether an image exists
+       locally, you can call the module with this image, and check whether the result list is empty (image does not
+       exist) or has one element (the image exists locally).
+     - The module will not attempt to pull images from registries. Use M(docker_image) with I(source) set to O(pull)
path: lib/ansible/modules/cloud/docker/docker_image_info.py
text: @user1:
O() doesn't exist right? Typo?
https://docs.ansible.com/ansible/latest/dev_guide/developing_modules_documenting.html#linking-within-module-documentation

@author:
Typo indeed! Should have been `C(...)`. Thanks for spotting!