We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Docker shell module failed in the latest sonic-mgmt
<!--
If you are reporting a new issue, make sure that we do not have any duplicates
already open. You can ensure this by searching the issue list for this
repository. If there is a duplicate, please close your issue and add a comment
to the existing issue instead.

If you suspect your issue is a bug, please edit your issue description to
include the BUG REPORT INFORMATION shown below. If you fail to provide this
information within 7 days, we cannot debug your issue and will close it. We
will, however, reopen it if you later provide the information.

For more information about reporting issues, see
https://github.com/Azure/SONiC/wiki#report-issues

---------------------------------------------------
GENERAL SUPPORT INFORMATION
---------------------------------------------------

The GitHub issue tracker is for bug reports and feature requests.
General support can be found at the following locations:

- SONiC Support Forums - https://groups.google.com/forum/#!forum/sonicproject

---------------------------------------------------
BUG REPORT INFORMATION
---------------------------------------------------
Use the commands below to provide key information from your environment:
You do NOT have to include this information if this is a FEATURE REQUEST
-->

**Description**
The task with sell type docker always fails on the latest sonic-mgmt, example:
```
- name: Gather information from lldp
  lldp:
  vars:
    ansible_shell_type: docker
    ansible_python_interpreter: docker exec -i lldp python
```

<!--
Briefly describe the problem you are having in a few paragraphs.
-->

**Steps to reproduce the issue:**
1. run dip_sip or lag_2 CT 
2.
3.

**Describe the results you received:**
```
TASK [test : Gathering peer VM information from lldp] **************************
task path: /var/user/jenkins/bfn-sonic-mgmt/ansible/roles/test/tasks/lag_2.yml:26
Thursday 28 November 2019  10:28:47 +0000 (0:00:00.263)       0:00:26.753 ***** 
The full traceback is:
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/ansible/executor/task_executor.py", line 145, in run
    res = self._execute()
  File "/usr/local/lib/python2.7/dist-packages/ansible/executor/task_executor.py", line 612, in _execute
    self._set_connection_options(variables, templar)
  File "/usr/local/lib/python2.7/dist-packages/ansible/executor/task_executor.py", line 1012, in _set_connection_options
    self._set_plugin_options('shell', final_vars, templar, task_keys)
  File "/usr/local/lib/python2.7/dist-packages/ansible/executor/task_executor.py", line 978, in _set_plugin_options
    plugin.set_options(task_keys=task_keys, var_options=options)
  File "/usr/local/lib/python2.7/dist-packages/ansible/plugins/shell/__init__.py", line 70, in set_options
    env = self.get_option('environment')
  File "/usr/local/lib/python2.7/dist-packages/ansible/plugins/__init__.py", line 60, in get_option
    raise KeyError(to_native(e))
KeyError: 'Requested entry (plugin_type: shell plugin: docker setting: environment ) was not defined in configuration.'

fatal: [cab18-2-dut]: FAILED! => {
    "msg": "Unexpected failure during module execution.", 
    "stdout": ""
}

```

**Describe the results you expected:**


**Additional information you deem important:**
<!--
software/ASIC/Hardware Flatform version and info
-->
    **Output of `show version`:**

    ```
SONiC Software Version: SONiC.HEAD.488-dirty-20191127.082217
Distribution: Debian 9.11
Kernel: 4.9.0-9-2-amd64
Build commit: 7622a30d
Build date: Wed Nov 27 11:15:51 UTC 2019
Built by: johnar@jenkins-worker-11

    ```

    **Attach debug file `sudo generate_dump`:**

    ```
    (paste your output here)
    ```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `ansible/shell_plugins/docker.py`
Content:
```
1 from __future__ import (absolute_import, division)
2 __metaclass__ = type
3 
4 import os
5 import re
6 import pipes
7 import ansible.constants as C
8 import time
9 import random
10 import shlex
11 import getopt
12 from ansible.module_utils.six import text_type
13 from ansible.plugins.shell.sh import ShellModule as sh
14 from ansible.errors import AnsibleError, AnsibleConnectionFailure, AnsibleFileNotFound
15 
16 class ShellModule(sh):
17 
18     def __init__(self, *args, **kwargs):
19         super(ShellModule, self).__init__(*args, **kwargs)
20         self.dtemps = []
21 
22     def join_path(self, *args):
23         ## HACK! HACK! HACK!
24         ## We observe the interactions between ShellModule and ActionModule, and
25         ## find the temporary directories Ansible created on remote machine. So we
26         ## collect them and copied to docker container in build_module_command
27         if len(args) >= 2 and (args[0].startswith('/home/') or args[0].startswith('/root/'))  and args[1] == '':
28             self.dtemps.append(args[0])
29 
30         return super(ShellModule, self).join_path(*args)
31 
32     def build_module_command(self, env_string, shebang, cmd, arg_path=None, rm_tmp=None):
33         # assert(self.container_name)
34         argv = shlex.split(shebang.replace("#!", ""))
35         assert(argv[0] == 'docker')
36         assert(argv[1] == 'exec')
37         opts, args = getopt.getopt(argv[2:], 'i')
38         self.container_name = args[0]
39 
40         # Inject environment variable before python in the shebang string
41         assert(args[1].endswith('python'))
42         args[1] = 'env {0} {1}'.format(env_string, args[1])
43         argv_env = argv[0:2] + [o for opt in opts for o in opt] + args
44         shebang_env = ' '.join(argv_env)
45 
46         ## Note: Docker cp behavior
47         ##   DEST_PATH exists and is a directory
48         ##   SRC_PATH does end with /.
49         ##     the content of the source directory is copied into this directory
50         ## Ref: https://docs.docker.com/engine/reference/commandline/cp/
51         pre = ''.join('docker exec {1} mkdir -p {0}; docker cp {0}/. {1}:{0}; '
52             .format(dtemp, self.container_name) for dtemp in self.dtemps)
53 
54         if rm_tmp:
55             post = ''.join('docker exec {1} rm -rf {0}; '
56                 .format(dtemp, self.container_name) for dtemp in self.dtemps)
57         else:
58             post = ''
59 
60         return pre + super(ShellModule, self).build_module_command('', shebang_env, cmd, arg_path, rm_tmp) + '; ' + post
61 
62     def checksum(self, path, python_interp):
63         """
64         Return the command to calculate the checksum for the file in ansible controlled machine
65         Arguments:
66           path:
67             the file path
68           python_interp:
69             the path for the python interpreter
70         Example:
71           path:
72             /zebra.conf
73           python_interp:
74             docker exec -i debian python
75           cmd:
76             rc=flag; [ -r /zebra.conf ] || rc=2; [ -f /zebra.conf ] || rc=1; [ -d /zebra.conf ] && rc=3; python -V 2>/dev/null || rc=4; [ x"$rc" != "xflag" ] && echo "${rc}  "/zebra.conf && exit 0; (python -c '...' 2>/dev/null)  || (echo '0  '/zebra.conf)
77           returns:
78             docker exec -i debian  sh -c "rc=flag; [ -r /zebra.conf ] || rc=2; [ -f /zebra.conf ] || rc=1; [ -d /zebra.conf ] && rc=3; python -V 2>/dev/null || rc=4; [ x\"\$rc\" != \"xflag\" ] && echo \"\${rc}  \"/zebra.conf && exit 0; (python -c '...' 2>/dev/null) || (echo '0  '/zebra.conf)"
79         """
80         ## Super class implements this function by sh commands and python scripts
81         ## If python_interp is modified to 'docker CONTAINER python', it will only influence the python
82         ## script part in super class. Instead we should influence both
83         simple_interp = 'python'
84         assert(python_interp.startswith('docker exec '))
85         assert(python_interp.endswith(' ' + simple_interp))
86 
87         docker_prefix = re.sub(simple_interp, '', python_interp)
88         cmd = super(ShellModule, self).checksum(path, simple_interp)
89         ## Escape the cmd:
90         ##   " --> \"
91         cmd_escaped = cmd.replace('"', '\\"')
92         ##   $ --> \$
93         cmd_escaped = cmd_escaped.replace('$', '\\$')
94         return '%s sh -c "%s"' % (docker_prefix, cmd_escaped)
95
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/ansible/shell_plugins/docker.py b/ansible/shell_plugins/docker.py
--- a/ansible/shell_plugins/docker.py
+++ b/ansible/shell_plugins/docker.py
@@ -1,6 +1,17 @@
 from __future__ import (absolute_import, division)
 __metaclass__ = type
 
+DOCUMENTATION = '''
+name: docker
+plugin_type: shell
+short_description: "docker shell plugin"
+version_added: historical
+description:
+  - This module allows you to execute commands directly in docker on the remote host
+extends_documentation_fragment:
+  - shell_common
+'''
+
 import os
 import re
 import pipes
@@ -29,7 +40,24 @@
 
         return super(ShellModule, self).join_path(*args)
 
-    def build_module_command(self, env_string, shebang, cmd, arg_path=None, rm_tmp=None):
+    def remove(self, path, recurse=False):
+        argv = self.get_option('ansible_python_interpreter').split()
+        assert(argv[0] == 'docker')
+        assert(argv[1] == 'exec')
+        opts, args = getopt.getopt(argv[2:], 'i')
+        self.container_name = args[0]
+
+        remove_files_on_host_cmd = super(ShellModule, self).remove(path, recurse)
+
+        cmd = remove_files_on_host_cmd + "; docker exec -i "
+        cmd += self.container_name + " rm -f "
+        if recurse:
+            cmd += '-r '
+        cmd += " ".join(self.dtemps)
+
+        return cmd
+
+    def build_module_command(self, env_string, shebang, cmd, arg_path=None):
         # assert(self.container_name)
         argv = shlex.split(shebang.replace("#!", ""))
         assert(argv[0] == 'docker')
@@ -51,13 +79,7 @@
         pre = ''.join('docker exec {1} mkdir -p {0}; docker cp {0}/. {1}:{0}; '
             .format(dtemp, self.container_name) for dtemp in self.dtemps)
 
-        if rm_tmp:
-            post = ''.join('docker exec {1} rm -rf {0}; '
-                .format(dtemp, self.container_name) for dtemp in self.dtemps)
-        else:
-            post = ''
-
-        return pre + super(ShellModule, self).build_module_command('', shebang_env, cmd, arg_path, rm_tmp) + '; ' + post
+        return pre + super(ShellModule, self).build_module_command('', shebang_env, cmd, arg_path)
 
     def checksum(self, path, python_interp):
         """

{"golden_diff": "diff --git a/ansible/shell_plugins/docker.py b/ansible/shell_plugins/docker.py\n--- a/ansible/shell_plugins/docker.py\n+++ b/ansible/shell_plugins/docker.py\n@@ -1,6 +1,17 @@\n from __future__ import (absolute_import, division)\n __metaclass__ = type\n \n+DOCUMENTATION = '''\n+name: docker\n+plugin_type: shell\n+short_description: \"docker shell plugin\"\n+version_added: historical\n+description:\n+  - This module allows you to execute commands directly in docker on the remote host\n+extends_documentation_fragment:\n+  - shell_common\n+'''\n+\n import os\n import re\n import pipes\n@@ -29,7 +40,24 @@\n \n         return super(ShellModule, self).join_path(*args)\n \n-    def build_module_command(self, env_string, shebang, cmd, arg_path=None, rm_tmp=None):\n+    def remove(self, path, recurse=False):\n+        argv = self.get_option('ansible_python_interpreter').split()\n+        assert(argv[0] == 'docker')\n+        assert(argv[1] == 'exec')\n+        opts, args = getopt.getopt(argv[2:], 'i')\n+        self.container_name = args[0]\n+\n+        remove_files_on_host_cmd = super(ShellModule, self).remove(path, recurse)\n+\n+        cmd = remove_files_on_host_cmd + \"; docker exec -i \"\n+        cmd += self.container_name + \" rm -f \"\n+        if recurse:\n+            cmd += '-r '\n+        cmd += \" \".join(self.dtemps)\n+\n+        return cmd\n+\n+    def build_module_command(self, env_string, shebang, cmd, arg_path=None):\n         # assert(self.container_name)\n         argv = shlex.split(shebang.replace(\"#!\", \"\"))\n         assert(argv[0] == 'docker')\n@@ -51,13 +79,7 @@\n         pre = ''.join('docker exec {1} mkdir -p {0}; docker cp {0}/. {1}:{0}; '\n             .format(dtemp, self.container_name) for dtemp in self.dtemps)\n \n-        if rm_tmp:\n-            post = ''.join('docker exec {1} rm -rf {0}; '\n-                .format(dtemp, self.container_name) for dtemp in self.dtemps)\n-        else:\n-            post = ''\n-\n-        return pre + super(ShellModule, self).build_module_command('', shebang_env, cmd, arg_path, rm_tmp) + '; ' + post\n+        return pre + super(ShellModule, self).build_module_command('', shebang_env, cmd, arg_path)\n \n     def checksum(self, path, python_interp):\n         \"\"\"\n", "issue": "Docker shell module failed in the latest sonic-mgmt\n<!--\r\nIf you are reporting a new issue, make sure that we do not have any duplicates\r\nalready open. You can ensure this by searching the issue list for this\r\nrepository. If there is a duplicate, please close your issue and add a comment\r\nto the existing issue instead.\r\n\r\nIf you suspect your issue is a bug, please edit your issue description to\r\ninclude the BUG REPORT INFORMATION shown below. If you fail to provide this\r\ninformation within 7 days, we cannot debug your issue and will close it. We\r\nwill, however, reopen it if you later provide the information.\r\n\r\nFor more information about reporting issues, see\r\nhttps://github.com/Azure/SONiC/wiki#report-issues\r\n\r\n---------------------------------------------------\r\nGENERAL SUPPORT INFORMATION\r\n---------------------------------------------------\r\n\r\nThe GitHub issue tracker is for bug reports and feature requests.\r\nGeneral support can be found at the following locations:\r\n\r\n- SONiC Support Forums - https://groups.google.com/forum/#!forum/sonicproject\r\n\r\n---------------------------------------------------\r\nBUG REPORT INFORMATION\r\n---------------------------------------------------\r\nUse the commands below to provide key information from your environment:\r\nYou do NOT have to include this information if this is a FEATURE REQUEST\r\n-->\r\n\r\n**Description**\r\nThe task with sell type docker always fails on the latest sonic-mgmt, example:\r\n```\r\n- name: Gather information from lldp\r\n  lldp:\r\n  vars:\r\n    ansible_shell_type: docker\r\n    ansible_python_interpreter: docker exec -i lldp python\r\n```\r\n\r\n<!--\r\nBriefly describe the problem you are having in a few paragraphs.\r\n-->\r\n\r\n**Steps to reproduce the issue:**\r\n1. run dip_sip or lag_2 CT \r\n2.\r\n3.\r\n\r\n**Describe the results you received:**\r\n```\r\nTASK [test : Gathering peer VM information from lldp] **************************\r\ntask path: /var/user/jenkins/bfn-sonic-mgmt/ansible/roles/test/tasks/lag_2.yml:26\r\nThursday 28 November 2019  10:28:47 +0000 (0:00:00.263)       0:00:26.753 ***** \r\nThe full traceback is:\r\nTraceback (most recent call last):\r\n  File \"/usr/local/lib/python2.7/dist-packages/ansible/executor/task_executor.py\", line 145, in run\r\n    res = self._execute()\r\n  File \"/usr/local/lib/python2.7/dist-packages/ansible/executor/task_executor.py\", line 612, in _execute\r\n    self._set_connection_options(variables, templar)\r\n  File \"/usr/local/lib/python2.7/dist-packages/ansible/executor/task_executor.py\", line 1012, in _set_connection_options\r\n    self._set_plugin_options('shell', final_vars, templar, task_keys)\r\n  File \"/usr/local/lib/python2.7/dist-packages/ansible/executor/task_executor.py\", line 978, in _set_plugin_options\r\n    plugin.set_options(task_keys=task_keys, var_options=options)\r\n  File \"/usr/local/lib/python2.7/dist-packages/ansible/plugins/shell/__init__.py\", line 70, in set_options\r\n    env = self.get_option('environment')\r\n  File \"/usr/local/lib/python2.7/dist-packages/ansible/plugins/__init__.py\", line 60, in get_option\r\n    raise KeyError(to_native(e))\r\nKeyError: 'Requested entry (plugin_type: shell plugin: docker setting: environment ) was not defined in configuration.'\r\n\r\nfatal: [cab18-2-dut]: FAILED! => {\r\n    \"msg\": \"Unexpected failure during module execution.\", \r\n    \"stdout\": \"\"\r\n}\r\n\r\n```\r\n\r\n**Describe the results you expected:**\r\n\r\n\r\n**Additional information you deem important:**\r\n<!--\r\nsoftware/ASIC/Hardware Flatform version and info\r\n-->\r\n    **Output of `show version`:**\r\n\r\n    ```\r\nSONiC Software Version: SONiC.HEAD.488-dirty-20191127.082217\r\nDistribution: Debian 9.11\r\nKernel: 4.9.0-9-2-amd64\r\nBuild commit: 7622a30d\r\nBuild date: Wed Nov 27 11:15:51 UTC 2019\r\nBuilt by: johnar@jenkins-worker-11\r\n\r\n    ```\r\n\r\n    **Attach debug file `sudo generate_dump`:**\r\n\r\n    ```\r\n    (paste your output here)\r\n    ```\r\n\n", "before_files": [{"content": "from __future__ import (absolute_import, division)\n__metaclass__ = type\n\nimport os\nimport re\nimport pipes\nimport ansible.constants as C\nimport time\nimport random\nimport shlex\nimport getopt\nfrom ansible.module_utils.six import text_type\nfrom ansible.plugins.shell.sh import ShellModule as sh\nfrom ansible.errors import AnsibleError, AnsibleConnectionFailure, AnsibleFileNotFound\n\nclass ShellModule(sh):\n\n    def __init__(self, *args, **kwargs):\n        super(ShellModule, self).__init__(*args, **kwargs)\n        self.dtemps = []\n\n    def join_path(self, *args):\n        ## HACK! HACK! HACK!\n        ## We observe the interactions between ShellModule and ActionModule, and\n        ## find the temporary directories Ansible created on remote machine. So we\n        ## collect them and copied to docker container in build_module_command\n        if len(args) >= 2 and (args[0].startswith('/home/') or args[0].startswith('/root/'))  and args[1] == '':\n            self.dtemps.append(args[0])\n\n        return super(ShellModule, self).join_path(*args)\n\n    def build_module_command(self, env_string, shebang, cmd, arg_path=None, rm_tmp=None):\n        # assert(self.container_name)\n        argv = shlex.split(shebang.replace(\"#!\", \"\"))\n        assert(argv[0] == 'docker')\n        assert(argv[1] == 'exec')\n        opts, args = getopt.getopt(argv[2:], 'i')\n        self.container_name = args[0]\n\n        # Inject environment variable before python in the shebang string\n        assert(args[1].endswith('python'))\n        args[1] = 'env {0} {1}'.format(env_string, args[1])\n        argv_env = argv[0:2] + [o for opt in opts for o in opt] + args\n        shebang_env = ' '.join(argv_env)\n\n        ## Note: Docker cp behavior\n        ##   DEST_PATH exists and is a directory\n        ##   SRC_PATH does end with /.\n        ##     the content of the source directory is copied into this directory\n        ## Ref: https://docs.docker.com/engine/reference/commandline/cp/\n        pre = ''.join('docker exec {1} mkdir -p {0}; docker cp {0}/. {1}:{0}; '\n            .format(dtemp, self.container_name) for dtemp in self.dtemps)\n\n        if rm_tmp:\n            post = ''.join('docker exec {1} rm -rf {0}; '\n                .format(dtemp, self.container_name) for dtemp in self.dtemps)\n        else:\n            post = ''\n\n        return pre + super(ShellModule, self).build_module_command('', shebang_env, cmd, arg_path, rm_tmp) + '; ' + post\n\n    def checksum(self, path, python_interp):\n        \"\"\"\n        Return the command to calculate the checksum for the file in ansible controlled machine\n        Arguments:\n          path:\n            the file path\n          python_interp:\n            the path for the python interpreter\n        Example:\n          path:\n            /zebra.conf\n          python_interp:\n            docker exec -i debian python\n          cmd:\n            rc=flag; [ -r /zebra.conf ] || rc=2; [ -f /zebra.conf ] || rc=1; [ -d /zebra.conf ] && rc=3; python -V 2>/dev/null || rc=4; [ x\"$rc\" != \"xflag\" ] && echo \"${rc}  \"/zebra.conf && exit 0; (python -c '...' 2>/dev/null)  || (echo '0  '/zebra.conf)\n          returns:\n            docker exec -i debian  sh -c \"rc=flag; [ -r /zebra.conf ] || rc=2; [ -f /zebra.conf ] || rc=1; [ -d /zebra.conf ] && rc=3; python -V 2>/dev/null || rc=4; [ x\\\"\\$rc\\\" != \\\"xflag\\\" ] && echo \\\"\\${rc}  \\\"/zebra.conf && exit 0; (python -c '...' 2>/dev/null) || (echo '0  '/zebra.conf)\"\n        \"\"\"\n        ## Super class implements this function by sh commands and python scripts\n        ## If python_interp is modified to 'docker CONTAINER python', it will only influence the python\n        ## script part in super class. Instead we should influence both\n        simple_interp = 'python'\n        assert(python_interp.startswith('docker exec '))\n        assert(python_interp.endswith(' ' + simple_interp))\n\n        docker_prefix = re.sub(simple_interp, '', python_interp)\n        cmd = super(ShellModule, self).checksum(path, simple_interp)\n        ## Escape the cmd:\n        ##   \" --> \\\"\n        cmd_escaped = cmd.replace('\"', '\\\\\"')\n        ##   $ --> \\$\n        cmd_escaped = cmd_escaped.replace('$', '\\\\$')\n        return '%s sh -c \"%s\"' % (docker_prefix, cmd_escaped)\n", "path": "ansible/shell_plugins/docker.py"}], "after_files": [{"content": "from __future__ import (absolute_import, division)\n__metaclass__ = type\n\nDOCUMENTATION = '''\nname: docker\nplugin_type: shell\nshort_description: \"docker shell plugin\"\nversion_added: historical\ndescription:\n  - This module allows you to execute commands directly in docker on the remote host\nextends_documentation_fragment:\n  - shell_common\n'''\n\nimport os\nimport re\nimport pipes\nimport ansible.constants as C\nimport time\nimport random\nimport shlex\nimport getopt\nfrom ansible.module_utils.six import text_type\nfrom ansible.plugins.shell.sh import ShellModule as sh\nfrom ansible.errors import AnsibleError, AnsibleConnectionFailure, AnsibleFileNotFound\n\nclass ShellModule(sh):\n\n    def __init__(self, *args, **kwargs):\n        super(ShellModule, self).__init__(*args, **kwargs)\n        self.dtemps = []\n\n    def join_path(self, *args):\n        ## HACK! HACK! HACK!\n        ## We observe the interactions between ShellModule and ActionModule, and\n        ## find the temporary directories Ansible created on remote machine. So we\n        ## collect them and copied to docker container in build_module_command\n        if len(args) >= 2 and (args[0].startswith('/home/') or args[0].startswith('/root/'))  and args[1] == '':\n            self.dtemps.append(args[0])\n\n        return super(ShellModule, self).join_path(*args)\n\n    def remove(self, path, recurse=False):\n        argv = self.get_option('ansible_python_interpreter').split()\n        assert(argv[0] == 'docker')\n        assert(argv[1] == 'exec')\n        opts, args = getopt.getopt(argv[2:], 'i')\n        self.container_name = args[0]\n\n        remove_files_on_host_cmd = super(ShellModule, self).remove(path, recurse)\n\n        cmd = remove_files_on_host_cmd + \"; docker exec -i \"\n        cmd += self.container_name + \" rm -f \"\n        if recurse:\n            cmd += '-r '\n        cmd += \" \".join(self.dtemps)\n\n        return cmd\n\n    def build_module_command(self, env_string, shebang, cmd, arg_path=None):\n        # assert(self.container_name)\n        argv = shlex.split(shebang.replace(\"#!\", \"\"))\n        assert(argv[0] == 'docker')\n        assert(argv[1] == 'exec')\n        opts, args = getopt.getopt(argv[2:], 'i')\n        self.container_name = args[0]\n\n        # Inject environment variable before python in the shebang string\n        assert(args[1].endswith('python'))\n        args[1] = 'env {0} {1}'.format(env_string, args[1])\n        argv_env = argv[0:2] + [o for opt in opts for o in opt] + args\n        shebang_env = ' '.join(argv_env)\n\n        ## Note: Docker cp behavior\n        ##   DEST_PATH exists and is a directory\n        ##   SRC_PATH does end with /.\n        ##     the content of the source directory is copied into this directory\n        ## Ref: https://docs.docker.com/engine/reference/commandline/cp/\n        pre = ''.join('docker exec {1} mkdir -p {0}; docker cp {0}/. {1}:{0}; '\n            .format(dtemp, self.container_name) for dtemp in self.dtemps)\n\n        return pre + super(ShellModule, self).build_module_command('', shebang_env, cmd, arg_path)\n\n    def checksum(self, path, python_interp):\n        \"\"\"\n        Return the command to calculate the checksum for the file in ansible controlled machine\n        Arguments:\n          path:\n            the file path\n          python_interp:\n            the path for the python interpreter\n        Example:\n          path:\n            /zebra.conf\n          python_interp:\n            docker exec -i debian python\n          cmd:\n            rc=flag; [ -r /zebra.conf ] || rc=2; [ -f /zebra.conf ] || rc=1; [ -d /zebra.conf ] && rc=3; python -V 2>/dev/null || rc=4; [ x\"$rc\" != \"xflag\" ] && echo \"${rc}  \"/zebra.conf && exit 0; (python -c '...' 2>/dev/null)  || (echo '0  '/zebra.conf)\n          returns:\n            docker exec -i debian  sh -c \"rc=flag; [ -r /zebra.conf ] || rc=2; [ -f /zebra.conf ] || rc=1; [ -d /zebra.conf ] && rc=3; python -V 2>/dev/null || rc=4; [ x\\\"\\$rc\\\" != \\\"xflag\\\" ] && echo \\\"\\${rc}  \\\"/zebra.conf && exit 0; (python -c '...' 2>/dev/null) || (echo '0  '/zebra.conf)\"\n        \"\"\"\n        ## Super class implements this function by sh commands and python scripts\n        ## If python_interp is modified to 'docker CONTAINER python', it will only influence the python\n        ## script part in super class. Instead we should influence both\n        simple_interp = 'python'\n        assert(python_interp.startswith('docker exec '))\n        assert(python_interp.endswith(' ' + simple_interp))\n\n        docker_prefix = re.sub(simple_interp, '', python_interp)\n        cmd = super(ShellModule, self).checksum(path, simple_interp)\n        ## Escape the cmd:\n        ##   \" --> \\\"\n        cmd_escaped = cmd.replace('\"', '\\\\\"')\n        ##   $ --> \\$\n        cmd_escaped = cmd_escaped.replace('$', '\\\\$')\n        return '%s sh -c \"%s\"' % (docker_prefix, cmd_escaped)\n", "path": "ansible/shell_plugins/docker.py"}]}