diff options
-rw-r--r-- | cloudinit/config/cc_write_files.py | 49 | ||||
-rw-r--r-- | doc/examples/cloud-config-write-files.txt | 32 |
2 files changed, 73 insertions, 8 deletions
diff --git a/cloudinit/config/cc_write_files.py b/cloudinit/config/cc_write_files.py index 683eac27..9e8f63a5 100644 --- a/cloudinit/config/cc_write_files.py +++ b/cloudinit/config/cc_write_files.py @@ -25,10 +25,11 @@ from cloudinit.settings import PER_INSTANCE frequency = PER_INSTANCE DEFAULT_PERMS = 0644 +UNKNOWN_ENC = 'text/plain' def handle(name, cfg, _cloud, log, _args): - files = cfg.get('files') + files = cfg.get('write_files') if not files: log.debug(("Skipping module named %s," " no/empty 'files' key in configuration"), name) @@ -36,6 +37,29 @@ def handle(name, cfg, _cloud, log, _args): write_files(name, files, log) +def canonicalize_decoding(enc): + if not enc: + enc = '' + enc = enc.lower().strip() + # Translate to a mime-type (or set of) that will be understood + # when decoding (for now we only support a limited set of known mime-types) + # See: http://tiny.cc/m4kahw + # See: http://www.iana.org/assignments/media-types/index.html + if enc in ['gz', 'gzip']: + # Should we assume that this is 'always' base64? + # Someone might of got lucky and not had to encode it? + return ['application/x-gzip'] + if enc in ['gz+base64', 'gzip+base64', 'gz+b64', 'gzip+b64']: + return ['application/base64', 'application/x-gzip'] + if enc in ['base64', 'b64']: + return ['application/base64'] + if enc in ['base32', 'b32']: + return ['application/base32'] + if enc in ['base16', 'b16']: + return ['application/base16'] + return [UNKNOWN_ENC] + + def write_files(name, files, log): if not files: return @@ -47,8 +71,8 @@ def write_files(name, files, log): i + 1, name) continue path = os.path.abspath(path) - contents = decode_string(f_info.get('content', ''), - f_info.get('compression')) + decodings = canonicalize_decoding(f_info.get('encoding')) + contents = decode_contents(f_info.get('content', ''), decodings) (u, g) = util.extract_usergroup(f_info.get('owner')) perms = safe_int(f_info.get('permissions'), DEFAULT_PERMS) util.write_file(path, contents, mode=perms) @@ -62,8 +86,17 @@ def safe_int(text, default): return default -def decode_string(contents, content_type): - if util.is_true(content_type, addons=['gzip', 'gz']): - contents_dec = base64.b64decode(contents) - contents = util.decomp_gzip(contents_dec, quiet=False) - return contents +def decode_contents(contents, decodings): + result = str(contents) + for enc in decodings: + if enc == 'application/x-gzip': + result = util.decomp_gzip(result, quiet=False) + elif enc == 'application/base64': + result = base64.b64decode(result) + elif enc == 'application/base32': + result = base64.b32decode(result) + elif enc == 'application/base16': + result = base64.b16decode(result) + elif enc == UNKNOWN_ENC: + pass + return result diff --git a/doc/examples/cloud-config-write-files.txt b/doc/examples/cloud-config-write-files.txt new file mode 100644 index 00000000..fb0c1541 --- /dev/null +++ b/doc/examples/cloud-config-write-files.txt @@ -0,0 +1,32 @@ +#cloud-config +# vim: syntax=yaml +# +# This is the configuration syntax that the write_files module +# will know how to understand, it can be given b64, b32, b16, or +# gz (or gz+b64) encoded strings which will be decoded accordingly +# and then written to the path that is provided. +# +# Note: Content strings here are truncated for example purposes. +# +write_files: +- content: CiMgVGhpcyBmaWxlIGNvbnRyb2xzIHRoZSBzdGF0ZSBvZiBTRUxpbnV4IG9u..... + encoding: b64 + path: /etc/sysconfig/selinux +- content: ' + + # My new /etc/sysconfig/samba file + + SMBDOPTIONS="-D" + + ' + path: /etc/sysconfig/samba +- content: H4sIADXC/U8C/+1Yf2wbVx1/d7YT122TQEMpadS6kgOZqL30J+..... + encoding: gz+b64 + path: /usr/bin/uptime +- content: BIRSAU3FOR2GS3THOMQGM33SEB2GQZJAINJE6TRAMRQWK3LPNYXAU=== + encoding: b32 + path: /etc/sysconfig/crond +- content: 0A232053657474696E677320666F7220746865204E4653206461656D6F6E2E0A + encoding: b16 + path: /etc/sysconfig/nfs + |