Add support to directly set content in copy module

This commit is contained in:
Patrick Pelletier 2013-03-04 11:32:25 -05:00 committed by Michael DeHaan
parent 4da04b2176
commit c7c7a63ee5
2 changed files with 37 additions and 5 deletions

View file

@ -22,6 +22,7 @@ from ansible import errors
from ansible.runner.return_data import ReturnData from ansible.runner.return_data import ReturnData
import base64 import base64
import stat import stat
import tempfile
class ActionModule(object): class ActionModule(object):
@ -37,10 +38,14 @@ class ActionModule(object):
options.update(complex_args) options.update(complex_args)
options.update(utils.parse_kv(module_args)) options.update(utils.parse_kv(module_args))
source = options.get('src', None) source = options.get('src', None)
content = options.get('content', None)
dest = options.get('dest', None) dest = options.get('dest', None)
if (source is None and not 'first_available_file' in inject) or dest is None: if (source is None and content is None and not 'first_available_file' in inject) or dest is None:
result=dict(failed=True, msg="src and dest are required") result=dict(failed=True, msg="src or content and dest are required")
return ReturnData(conn=conn, result=result)
elif (source is not None or 'first_available_file' in inject) and content is not None:
result=dict(failed=True, msg="src and content are mutually exclusive")
return ReturnData(conn=conn, result=result) return ReturnData(conn=conn, result=result)
# if we have first_available_file in our vars # if we have first_available_file in our vars
@ -57,6 +62,17 @@ class ActionModule(object):
if not found: if not found:
results=dict(failed=True, msg="could not find src in first_available_file list") results=dict(failed=True, msg="could not find src in first_available_file list")
return ReturnData(conn=conn, result=results) return ReturnData(conn=conn, result=results)
elif content is not None:
fd, tmp_content = tempfile.mkstemp()
f = os.fdopen(fd, 'w')
try:
f.write(content)
except Exception, err:
os.remove(tmp_content)
result = dict(failed=True, msg="could not write content temp file: %s" % err)
return ReturnData(conn=conn, result=result)
f.close()
source = tmp_content
else: else:
source = utils.template(self.runner.basedir, source, inject) source = utils.template(self.runner.basedir, source, inject)
source = utils.path_dwim(self.runner.basedir, source) source = utils.path_dwim(self.runner.basedir, source)
@ -73,6 +89,10 @@ class ActionModule(object):
remote_md5 = self.runner._remote_md5(conn, tmp, dest) remote_md5 = self.runner._remote_md5(conn, tmp, dest)
if remote_md5 == '3': if remote_md5 == '3':
# Destination is a directory # Destination is a directory
if content is not None:
os.remove(tmp_content)
result = dict(failed=True, msg="can not use content with a dir as dest")
return ReturnData(conn=conn, result=result)
dest = os.path.join(dest, os.path.basename(source)) dest = os.path.join(dest, os.path.basename(source))
remote_md5 = self.runner._remote_md5(conn, tmp, dest) remote_md5 = self.runner._remote_md5(conn, tmp, dest)
@ -85,11 +105,15 @@ class ActionModule(object):
diff = {} diff = {}
if self.runner.check: if self.runner.check:
if content is not None:
os.remove(tmp_content)
return ReturnData(conn=conn, result=dict(changed=True), diff=diff) return ReturnData(conn=conn, result=dict(changed=True), diff=diff)
# transfer the file to a remote tmp location # transfer the file to a remote tmp location
tmp_src = tmp + os.path.basename(source) tmp_src = tmp + os.path.basename(source)
conn.put_file(source, tmp_src) conn.put_file(source, tmp_src)
if content is not None:
os.remove(tmp_content)
# fix file permissions when the copy is done as a different user # fix file permissions when the copy is done as a different user
if self.runner.sudo and self.runner.sudo_user != 'root': if self.runner.sudo and self.runner.sudo_user != 'root':
self.runner._low_level_exec_command(conn, "chmod a+r %s" % tmp_src, tmp) self.runner._low_level_exec_command(conn, "chmod a+r %s" % tmp_src, tmp)
@ -102,6 +126,8 @@ class ActionModule(object):
# no need to transfer the file, already correct md5, but still need to call # no need to transfer the file, already correct md5, but still need to call
# the file module in case we want to change attributes # the file module in case we want to change attributes
if content is not None:
os.remove(tmp_content)
tmp_src = tmp + os.path.basename(source) tmp_src = tmp + os.path.basename(source)
module_args = "%s src=%s" % (module_args, tmp_src) module_args = "%s src=%s" % (module_args, tmp_src)
if self.runner.check: if self.runner.check:

View file

@ -31,10 +31,15 @@ description:
options: options:
src: src:
description: description:
- Local path to a file to copy to the remote server; can be absolute or relative. - Local path to a file to copy to the remote server; can be absolute or relative. Mutually exclusive with content.
required: true required: false
default: null default: null
aliases: [] aliases: []
content:
description:
- Creates and/or set content of a file on the remote server. Mutually exclusive with content.
required: false
default: null
dest: dest:
description: description:
- Remote absolute path where the file should be copied to. - Remote absolute path where the file should be copied to.
@ -76,7 +81,8 @@ def main():
module = AnsibleModule( module = AnsibleModule(
# not checking because of daisy chain to file module # not checking because of daisy chain to file module
argument_spec = dict( argument_spec = dict(
src=dict(required=True), src=dict(required=False),
content=dict(required=False),
dest=dict(required=True), dest=dict(required=True),
backup=dict(default=False, type='bool'), backup=dict(default=False, type='bool'),
force = dict(default='yes', aliases=['thirsty'], type='bool'), force = dict(default='yes', aliases=['thirsty'], type='bool'),