summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Coca <brian.coca+git@gmail.com>2016-03-08 10:17:36 -0500
committerBrian Coca <brian.coca+git@gmail.com>2016-03-08 12:51:23 -0500
commite83db3634e2ac42e8d6a8d86de6c9f1285dab615 (patch)
treee03f6888392c77c582cce259397b60f676a70506
parent79888f32d12aff1d23764d5560d67ceba0336bd2 (diff)
downloadansible-modules-core-e83db3634e2ac42e8d6a8d86de6c9f1285dab615.tar.gz
fixes to assemble
now uses atomic move to avoid data corruption correclty cleans up temp files in every case returns backup_file info if needed validate validate before temp file gets created backup AFTER validate
-rw-r--r--files/assemble.py52
1 files changed, 35 insertions, 17 deletions
diff --git a/files/assemble.py b/files/assemble.py
index a996fe44..6ac138af 100644
--- a/files/assemble.py
+++ b/files/assemble.py
@@ -20,7 +20,6 @@
import os
import os.path
-import shutil
import tempfile
import re
@@ -152,6 +151,16 @@ def assemble_from_fragments(src_path, delimiter=None, compiled_regexp=None, igno
tmp.close()
return temp_path
+def cleanup(path, result=None):
+ # cleanup just in case
+ if os.path.exists(path):
+ try:
+ os.remove(path)
+ except (IOError, OSError), e:
+ # don't error on possible race conditions, but keep warning
+ if result is not None:
+ result['warnings'] = ['Unable to remove temp file (%s): %s' % (path, str(e))]
+
# ==============================================================
# main
@@ -173,7 +182,6 @@ def main():
)
changed = False
- path_md5 = None # Deprecated
path_hash = None
dest_hash = None
src = os.path.expanduser(module.params['src'])
@@ -185,6 +193,7 @@ def main():
ignore_hidden = module.params['ignore_hidden']
validate = module.params.get('validate', None)
+ result = dict(src=src, dest=dest)
if not os.path.exists(src):
module.fail_json(msg="Source (%s) does not exist" % src)
@@ -197,37 +206,46 @@ def main():
except re.error, e:
module.fail_json(msg="Invalid Regexp (%s) in \"%s\"" % (e, regexp))
+ if validate and "%s" not in validate:
+ module.fail_json(msg="validate must contain %%s: %s" % validate)
+
path = assemble_from_fragments(src, delimiter, compiled_regexp, ignore_hidden)
path_hash = module.sha1(path)
+ result['checksum'] = path_hash
+
+ # Backwards compat. This won't return data if FIPS mode is active
+ try:
+ pathmd5 = module.md5(path)
+ except ValueError:
+ pathmd5 = None
+ result['md5sum'] = pathmd5
if os.path.exists(dest):
dest_hash = module.sha1(dest)
if path_hash != dest_hash:
- if backup and dest_hash is not None:
- module.backup_local(dest)
if validate:
- if "%s" not in validate:
- module.fail_json(msg="validate must contain %%s: %s" % validate)
(rc, out, err) = module.run_command(validate % path)
+ result['validation'] = dict(rc=rc, stdout=out, stderr=err)
if rc != 0:
- module.fail_json(msg="failed to validate: rc:%s error:%s" % (rc, err))
+ cleanup(path)
+ result['msg'] = "failed to validate: rc:%s error:%s" % (rc, err)
+ module.fail_json(result)
+ if backup and dest_hash is not None:
+ result['backup_file'] = module.backup_local(dest)
- shutil.copy(path, dest)
+ module.atomic_move(path, dest)
changed = True
- # Backwards compat. This won't return data if FIPS mode is active
- try:
- pathmd5 = module.md5(path)
- except ValueError:
- pathmd5 = None
-
- os.remove(path)
+ cleanup(path, result)
+ # handle file permissions
file_args = module.load_file_common_arguments(module.params)
- changed = module.set_fs_attributes_if_different(file_args, changed)
+ result['changed'] = module.set_fs_attributes_if_different(file_args, changed)
+
# Mission complete
- module.exit_json(src=src, dest=dest, md5sum=pathmd5, checksum=path_hash, changed=changed, msg="OK")
+ result['msg'] = "OK"
+ module.exit_json(result)
# import module snippets
from ansible.module_utils.basic import *