mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-07-25 22:30:22 -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/>.
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
REPLACER = "#<<INCLUDE_ANSIBLE_MODULE_COMMON>>"
|
REPLACER = "#<<INCLUDE_ANSIBLE_MODULE_COMMON>>"
|
||||||
|
REPLACER_ARGS = "<<INCLUDE_ANSIBLE_MODULE_ARGS>>"
|
||||||
|
|
||||||
MODULE_COMMON = """
|
MODULE_COMMON = """
|
||||||
|
|
||||||
# == BEGIN DYNAMICALLY INSERTED CODE ==
|
# == BEGIN DYNAMICALLY INSERTED CODE ==
|
||||||
|
|
||||||
|
MODULE_ARGS = "<<INCLUDE_ANSIBLE_MODULE_ARGS>>"
|
||||||
|
|
||||||
# ansible modules can be written in any language. To simplify
|
# ansible modules can be written in any language. To simplify
|
||||||
# development of Python modules, the functions available here
|
# development of Python modules, the functions available here
|
||||||
# can be inserted in any module source automatically by including
|
# can be inserted in any module source automatically by including
|
||||||
|
@ -32,6 +35,7 @@ try:
|
||||||
import json
|
import json
|
||||||
except ImportError:
|
except ImportError:
|
||||||
import simplejson as json
|
import simplejson as json
|
||||||
|
import base64
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import shlex
|
import shlex
|
||||||
|
@ -109,11 +113,7 @@ class AnsibleModule(object):
|
||||||
|
|
||||||
def _load_params(self):
|
def _load_params(self):
|
||||||
''' read the input and return a dictionary and the arguments string '''
|
''' read the input and return a dictionary and the arguments string '''
|
||||||
if len(sys.argv) == 2 and os.path.exists(sys.argv[1]):
|
args = base64.b64decode(MODULE_ARGS)
|
||||||
argfile = sys.argv[1]
|
|
||||||
args = open(argfile, 'r').read()
|
|
||||||
else:
|
|
||||||
args = ' '.join(sys.argv[1:])
|
|
||||||
items = shlex.split(args)
|
items = shlex.split(args)
|
||||||
params = {}
|
params = {}
|
||||||
for x in items:
|
for x in items:
|
||||||
|
|
|
@ -182,12 +182,12 @@ class Runner(object):
|
||||||
|
|
||||||
# *****************************************************
|
# *****************************************************
|
||||||
|
|
||||||
def _transfer_module(self, conn, tmp, module, inject):
|
#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 '''
|
# ''' 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)
|
# outpath = self._copy_module(conn, tmp, module, inject)
|
||||||
self._low_level_exec_command(conn, "chmod +x %s" % outpath, tmp)
|
# self._low_level_exec_command(conn, "chmod +x %s" % outpath, tmp)
|
||||||
return outpath
|
# 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):
|
async_jid=None, async_module=None, async_limit=None, inject=None):
|
||||||
|
|
||||||
''' runs a module that has already been transferred '''
|
''' runs a module that has already been transferred '''
|
||||||
|
@ -220,13 +220,22 @@ class Runner(object):
|
||||||
if type(args) == dict:
|
if type(args) == dict:
|
||||||
args = utils.jsonify(args,format=True)
|
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)
|
cmd = ""
|
||||||
if async_jid is None:
|
if not is_new_style:
|
||||||
cmd = "%s %s" % (remote_module_path, argsfile)
|
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:
|
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)
|
res = self._low_level_exec_command(conn, cmd, tmp, sudoable=True)
|
||||||
return ReturnData(host=conn.host, result=res)
|
return ReturnData(host=conn.host, result=res)
|
||||||
|
@ -249,8 +258,7 @@ class Runner(object):
|
||||||
module_name = 'command'
|
module_name = 'command'
|
||||||
self.module_args += " #USE_SHELL"
|
self.module_args += " #USE_SHELL"
|
||||||
|
|
||||||
module = self._transfer_module(conn, tmp, module_name, inject)
|
exec_rc = self._execute_module(conn, tmp, module_name, self.module_args, inject=inject)
|
||||||
exec_rc = self._execute_module(conn, tmp, module, self.module_args, inject=inject)
|
|
||||||
if exec_rc.is_successful():
|
if exec_rc.is_successful():
|
||||||
self.setup_cache[conn.host].update(exec_rc.result.get('ansible_facts', {}))
|
self.setup_cache[conn.host].update(exec_rc.result.get('ansible_facts', {}))
|
||||||
return exec_rc
|
return exec_rc
|
||||||
|
@ -266,11 +274,8 @@ class Runner(object):
|
||||||
module_name = 'command'
|
module_name = 'command'
|
||||||
module_args += " #USE_SHELL"
|
module_args += " #USE_SHELL"
|
||||||
|
|
||||||
async = self._transfer_module(conn, tmp, 'async_wrapper', inject)
|
return self._execute_module(conn, tmp, 'async', module_args,
|
||||||
module = self._transfer_module(conn, tmp, module_name, inject)
|
async_module=module_name,
|
||||||
|
|
||||||
return self._execute_module(conn, tmp, async, module_args,
|
|
||||||
async_module=module,
|
|
||||||
async_jid=self.generated_jid,
|
async_jid=self.generated_jid,
|
||||||
async_limit=self.background,
|
async_limit=self.background,
|
||||||
inject=inject
|
inject=inject
|
||||||
|
@ -319,13 +324,9 @@ class Runner(object):
|
||||||
tmp_src = tmp + source.split('/')[-1]
|
tmp_src = tmp + source.split('/')[-1]
|
||||||
conn.put_file(source, tmp_src)
|
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
|
# run the copy module
|
||||||
args = "src=%s dest=%s" % (tmp_src, dest)
|
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:
|
else:
|
||||||
# no need to transfer the file, already correct md5
|
# no need to transfer the file, already correct md5
|
||||||
|
@ -421,9 +422,6 @@ class Runner(object):
|
||||||
|
|
||||||
source = utils.template(source, inject)
|
source = utils.template(source, inject)
|
||||||
|
|
||||||
# install the template module
|
|
||||||
copy_module = self._transfer_module(conn, tmp, 'copy', inject)
|
|
||||||
|
|
||||||
# template the source data locally & transfer
|
# template the source data locally & transfer
|
||||||
try:
|
try:
|
||||||
resultant = utils.template_from_file(self.basedir, source, inject)
|
resultant = utils.template_from_file(self.basedir, source, inject)
|
||||||
|
@ -434,17 +432,20 @@ class Runner(object):
|
||||||
|
|
||||||
# run the copy module, queue the file module
|
# run the copy module, queue the file module
|
||||||
args = "src=%s dest=%s" % (xfered, dest)
|
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):
|
def _execute_assemble(self, conn, tmp, inject=None):
|
||||||
''' handler for assemble operations '''
|
''' 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'
|
module_name = 'assemble'
|
||||||
options = utils.parse_kv(self.module_args)
|
options = utils.parse_kv(self.module_args)
|
||||||
module = self._transfer_module(conn, tmp, module_name, inject)
|
return self._execute_module(conn, tmp, 'inject', self.module_args, inject=inject).daisychain('file')
|
||||||
return self._execute_module(conn, tmp, module, self.module_args, inject=inject).daisychain('file')
|
|
||||||
|
|
||||||
# *****************************************************
|
# *****************************************************
|
||||||
|
|
||||||
|
@ -670,10 +671,15 @@ class Runner(object):
|
||||||
out_path = os.path.join(tmp, module)
|
out_path = os.path.join(tmp, module)
|
||||||
|
|
||||||
module_data = ""
|
module_data = ""
|
||||||
|
is_new_style=False
|
||||||
with open(in_path) as f:
|
with open(in_path) as f:
|
||||||
module_data = f.read()
|
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)
|
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
|
# use the correct python interpreter for the host
|
||||||
if 'ansible_python_interpreter' in inject:
|
if 'ansible_python_interpreter' in inject:
|
||||||
interpreter = inject['ansible_python_interpreter']
|
interpreter = inject['ansible_python_interpreter']
|
||||||
|
@ -683,7 +689,7 @@ class Runner(object):
|
||||||
module_data = "\n".join(module_lines)
|
module_data = "\n".join(module_lines)
|
||||||
|
|
||||||
self._transfer_str(conn, tmp, module, module_data)
|
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
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
try:
|
import base64
|
||||||
import json
|
|
||||||
except ImportError:
|
|
||||||
import simplejson as json
|
|
||||||
|
|
||||||
import os
|
def main():
|
||||||
import syslog
|
module = AnsibleModule(
|
||||||
|
argument_spec = dict()
|
||||||
|
)
|
||||||
|
module.exit_json(ping='pong')
|
||||||
|
|
||||||
syslog.openlog('ansible-%s' % os.path.basename(__file__))
|
# this is magic, see lib/ansible/module_common.py
|
||||||
syslog.syslog(syslog.LOG_NOTICE, 'Invoked as-is')
|
#<<INCLUDE_ANSIBLE_MODULE_COMMON>>
|
||||||
|
main()
|
||||||
|
|
||||||
print json.dumps({ "ping" : "pong" })
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue