mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-07-26 14:41:23 -07:00
Save the transfer of the module file for new style modules, because we can inject the arguments into the modules.
Module consumers using the API don't have to know how this works. base64 stuff is only there because escaping a docstring inside a docstring was a bit of a challenge :)
This commit is contained in:
parent
f8520750cb
commit
ec12cc4154
3 changed files with 52 additions and 46 deletions
|
@ -16,11 +16,14 @@
|
|||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
REPLACER = "#<<INCLUDE_ANSIBLE_MODULE_COMMON>>"
|
||||
REPLACER_ARGS = "<<INCLUDE_ANSIBLE_MODULE_ARGS>>"
|
||||
|
||||
MODULE_COMMON = """
|
||||
|
||||
# == BEGIN DYNAMICALLY INSERTED CODE ==
|
||||
|
||||
MODULE_ARGS = "<<INCLUDE_ANSIBLE_MODULE_ARGS>>"
|
||||
|
||||
# ansible modules can be written in any language. To simplify
|
||||
# development of Python modules, the functions available here
|
||||
# can be inserted in any module source automatically by including
|
||||
|
@ -32,6 +35,7 @@ try:
|
|||
import json
|
||||
except ImportError:
|
||||
import simplejson as json
|
||||
import base64
|
||||
import os
|
||||
import re
|
||||
import shlex
|
||||
|
@ -109,11 +113,7 @@ class AnsibleModule(object):
|
|||
|
||||
def _load_params(self):
|
||||
''' read the input and return a dictionary and the arguments string '''
|
||||
if len(sys.argv) == 2 and os.path.exists(sys.argv[1]):
|
||||
argfile = sys.argv[1]
|
||||
args = open(argfile, 'r').read()
|
||||
else:
|
||||
args = ' '.join(sys.argv[1:])
|
||||
args = base64.b64decode(MODULE_ARGS)
|
||||
items = shlex.split(args)
|
||||
params = {}
|
||||
for x in items:
|
||||
|
|
|
@ -182,12 +182,12 @@ class Runner(object):
|
|||
|
||||
# *****************************************************
|
||||
|
||||
def _transfer_module(self, conn, tmp, module, inject):
|
||||
''' transfers a module file to the remote side to execute it, but does not execute it yet '''
|
||||
|
||||
outpath = self._copy_module(conn, tmp, module, inject)
|
||||
self._low_level_exec_command(conn, "chmod +x %s" % outpath, tmp)
|
||||
return outpath
|
||||
#def _transfer_module(self, conn, tmp, module, inject):
|
||||
# ''' transfers a module file to the remote side to execute it, but does not execute it yet '''
|
||||
#
|
||||
# outpath = self._copy_module(conn, tmp, module, inject)
|
||||
# self._low_level_exec_command(conn, "chmod +x %s" % outpath, tmp)
|
||||
# return outpath
|
||||
|
||||
# *****************************************************
|
||||
|
||||
|
@ -212,7 +212,7 @@ class Runner(object):
|
|||
|
||||
# *****************************************************
|
||||
|
||||
def _execute_module(self, conn, tmp, remote_module_path, args,
|
||||
def _execute_module(self, conn, tmp, module_name, args,
|
||||
async_jid=None, async_module=None, async_limit=None, inject=None):
|
||||
|
||||
''' runs a module that has already been transferred '''
|
||||
|
@ -220,13 +220,22 @@ class Runner(object):
|
|||
if type(args) == dict:
|
||||
args = utils.jsonify(args,format=True)
|
||||
|
||||
args = utils.template(args, inject)
|
||||
(remote_module_path, is_new_style) = self._copy_module(conn, tmp, module_name, inject)
|
||||
self._low_level_exec_command(conn, "chmod +x %s" % remote_module_path, tmp)
|
||||
|
||||
argsfile = self._transfer_str(conn, tmp, 'arguments', args)
|
||||
if async_jid is None:
|
||||
cmd = "%s %s" % (remote_module_path, argsfile)
|
||||
cmd = ""
|
||||
if not is_new_style:
|
||||
args = utils.template(args, inject)
|
||||
argsfile = self._transfer_str(conn, tmp, 'arguments', args)
|
||||
if async_jid is None:
|
||||
cmd = "%s %s" % (remote_module_path, argsfile)
|
||||
else:
|
||||
cmd = " ".join([str(x) for x in [remote_module_path, async_jid, async_limit, async_module, argsfile]])
|
||||
else:
|
||||
cmd = " ".join([str(x) for x in [remote_module_path, async_jid, async_limit, async_module, argsfile]])
|
||||
if async_jid is None:
|
||||
cmd = "%s" % (remote_module_path)
|
||||
else:
|
||||
cmd = " ".join([str(x) for x in [remote_module_path, async_jid, async_limit, async_module]])
|
||||
|
||||
res = self._low_level_exec_command(conn, cmd, tmp, sudoable=True)
|
||||
return ReturnData(host=conn.host, result=res)
|
||||
|
@ -249,8 +258,7 @@ class Runner(object):
|
|||
module_name = 'command'
|
||||
self.module_args += " #USE_SHELL"
|
||||
|
||||
module = self._transfer_module(conn, tmp, module_name, inject)
|
||||
exec_rc = self._execute_module(conn, tmp, module, self.module_args, inject=inject)
|
||||
exec_rc = self._execute_module(conn, tmp, module_name, self.module_args, inject=inject)
|
||||
if exec_rc.is_successful():
|
||||
self.setup_cache[conn.host].update(exec_rc.result.get('ansible_facts', {}))
|
||||
return exec_rc
|
||||
|
@ -266,11 +274,8 @@ class Runner(object):
|
|||
module_name = 'command'
|
||||
module_args += " #USE_SHELL"
|
||||
|
||||
async = self._transfer_module(conn, tmp, 'async_wrapper', inject)
|
||||
module = self._transfer_module(conn, tmp, module_name, inject)
|
||||
|
||||
return self._execute_module(conn, tmp, async, module_args,
|
||||
async_module=module,
|
||||
return self._execute_module(conn, tmp, 'async', module_args,
|
||||
async_module=module_name,
|
||||
async_jid=self.generated_jid,
|
||||
async_limit=self.background,
|
||||
inject=inject
|
||||
|
@ -319,13 +324,9 @@ class Runner(object):
|
|||
tmp_src = tmp + source.split('/')[-1]
|
||||
conn.put_file(source, tmp_src)
|
||||
|
||||
# install the copy module
|
||||
self.module_name = 'copy'
|
||||
module = self._transfer_module(conn, tmp, 'copy', inject)
|
||||
|
||||
# run the copy module
|
||||
args = "src=%s dest=%s" % (tmp_src, dest)
|
||||
return self._execute_module(conn, tmp, module, args, inject=inject).daisychain('file')
|
||||
return self._execute_module(conn, tmp, 'copy', args, inject=inject).daisychain('file')
|
||||
|
||||
else:
|
||||
# no need to transfer the file, already correct md5
|
||||
|
@ -421,9 +422,6 @@ class Runner(object):
|
|||
|
||||
source = utils.template(source, inject)
|
||||
|
||||
# install the template module
|
||||
copy_module = self._transfer_module(conn, tmp, 'copy', inject)
|
||||
|
||||
# template the source data locally & transfer
|
||||
try:
|
||||
resultant = utils.template_from_file(self.basedir, source, inject)
|
||||
|
@ -434,17 +432,20 @@ class Runner(object):
|
|||
|
||||
# run the copy module, queue the file module
|
||||
args = "src=%s dest=%s" % (xfered, dest)
|
||||
return self._execute_module(conn, tmp, copy_module, args, inject=inject).daisychain('file')
|
||||
return self._execute_module(conn, tmp, 'copy', args, inject=inject).daisychain('file')
|
||||
|
||||
# *****************************************************
|
||||
|
||||
def _execute_assemble(self, conn, tmp, inject=None):
|
||||
''' handler for assemble operations '''
|
||||
|
||||
# FIXME: once assemble is ported over to the use the new common logic, this method
|
||||
# will be unneccessary as it can decide to daisychain via it's own module returns.
|
||||
# and this function can be deleted.
|
||||
|
||||
module_name = 'assemble'
|
||||
options = utils.parse_kv(self.module_args)
|
||||
module = self._transfer_module(conn, tmp, module_name, inject)
|
||||
return self._execute_module(conn, tmp, module, self.module_args, inject=inject).daisychain('file')
|
||||
return self._execute_module(conn, tmp, 'inject', self.module_args, inject=inject).daisychain('file')
|
||||
|
||||
# *****************************************************
|
||||
|
||||
|
@ -670,10 +671,15 @@ class Runner(object):
|
|||
out_path = os.path.join(tmp, module)
|
||||
|
||||
module_data = ""
|
||||
is_new_style=False
|
||||
with open(in_path) as f:
|
||||
module_data = f.read()
|
||||
if module_common.REPLACER in module_data:
|
||||
is_new_style=True
|
||||
module_data = module_data.replace(module_common.REPLACER, module_common.MODULE_COMMON)
|
||||
|
||||
encoded_args = base64.b64encode(self.module_args)
|
||||
module_data = module_data.replace(module_common.REPLACER_ARGS, encoded_args)
|
||||
|
||||
# use the correct python interpreter for the host
|
||||
if 'ansible_python_interpreter' in inject:
|
||||
interpreter = inject['ansible_python_interpreter']
|
||||
|
@ -683,7 +689,7 @@ class Runner(object):
|
|||
module_data = "\n".join(module_lines)
|
||||
|
||||
self._transfer_str(conn, tmp, module, module_data)
|
||||
return out_path
|
||||
return (out_path, is_new_style)
|
||||
|
||||
# *****************************************************
|
||||
|
||||
|
|
18
library/ping
18
library/ping
|
@ -17,15 +17,15 @@
|
|||
# You should have received a copy of the GNU General Public License
|
||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
try:
|
||||
import json
|
||||
except ImportError:
|
||||
import simplejson as json
|
||||
import base64
|
||||
|
||||
import os
|
||||
import syslog
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec = dict()
|
||||
)
|
||||
module.exit_json(ping='pong')
|
||||
|
||||
syslog.openlog('ansible-%s' % os.path.basename(__file__))
|
||||
syslog.syslog(syslog.LOG_NOTICE, 'Invoked as-is')
|
||||
# this is magic, see lib/ansible/module_common.py
|
||||
#<<INCLUDE_ANSIBLE_MODULE_COMMON>>
|
||||
main()
|
||||
|
||||
print json.dumps({ "ping" : "pong" })
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue