From eb939e7765f490529aade46e38ee0f85d8a911dd Mon Sep 17 00:00:00 2001 From: Joshua Harlow Date: Wed, 11 Jul 2012 11:20:24 -0700 Subject: Adjust the decoding of the files that are given so that a canonicalize happens first, which will examine the incoming encoding, and decide the neccasary decoding types needed to get the final resultant string and then use these normalized decoding types to actually do the final decode. Also change the name of the config key that is looked up to 'write_files' since 'files' is pretty generic and could have clashes with other modules. Add an example that shows how to use this in the different encoding formats that are supported. --- doc/examples/cloud-config-write-files.txt | 32 +++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 doc/examples/cloud-config-write-files.txt (limited to 'doc/examples/cloud-config-write-files.txt') 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 + -- cgit v1.2.3 From 50a5728db977ec11f3448c473a396995ea29319e Mon Sep 17 00:00:00 2001 From: Joshua Harlow Date: Wed, 11 Jul 2012 13:02:24 -0700 Subject: Update the write files with the new content/compression handling. Adjust the examples file to reflect this. --- cloudinit/config/cc_write_files.py | 64 +++++++++++++++---------------- doc/examples/cloud-config-write-files.txt | 27 +++++++------ 2 files changed, 48 insertions(+), 43 deletions(-) (limited to 'doc/examples/cloud-config-write-files.txt') diff --git a/cloudinit/config/cc_write_files.py b/cloudinit/config/cc_write_files.py index ed2abe9e..061b9810 100644 --- a/cloudinit/config/cc_write_files.py +++ b/cloudinit/config/cc_write_files.py @@ -24,6 +24,7 @@ from cloudinit.settings import PER_INSTANCE frequency = PER_INSTANCE +DEFAULT_OWNER = "root:root" DEFAULT_PERMS = 0644 UNKNOWN_ENC = 'text/plain' @@ -37,26 +38,23 @@ 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? +def canonicalize_extraction(compression_type, log): + if not compression_type: + compression_type = '' + compression_type = compression_type.lower().strip() + if compression_type in ['gz', 'gzip']: return ['application/x-gzip'] - if enc in ['gz+base64', 'gzip+base64', 'gz+b64', 'gzip+b64']: + if compression_type in ['gz+base64', 'gzip+base64', 'gz+b64', 'gzip+b64']: return ['application/base64', 'application/x-gzip'] - if enc in ['base64', 'b64']: + # Yaml already encodes binary data as base64 if it is given to the + # yaml file as binary, so those will be automatically decoded for you. + # But the above b64 is just for people that are more 'comfortable' + # specifing it manually (which might be a possiblity) + if compression_type in ['b64', 'base64']: return ['application/base64'] - if enc in ['base32', 'b32']: - return ['application/base32'] - if enc in ['base16', 'b16']: - return ['application/base16'] + if compression_type: + log.warn("Unknown compression type %s, assuming %s", + compression_type, UNKNOWN_ENC) return [UNKNOWN_ENC] @@ -71,32 +69,34 @@ def write_files(name, files, log): i + 1, name) continue path = os.path.abspath(path) - 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) + extractions = canonicalize_extraction(f_info.get('compression'), log) + contents = extract_contents(f_info.get('content', ''), extractions) + (u, g) = util.extract_usergroup(f_info.get('owner', DEFAULT_OWNER)) + perms = decode_perms(f_info.get('permissions'), DEFAULT_PERMS, log) util.write_file(path, contents, mode=perms) util.chownbyname(path, u, g) -def safe_int(text, default): +def decode_perms(perm, default, log): try: - return int(text) + if isinstance(perm, (int, long, float)): + # Just 'downcast' it (if a float) + return int(perm) + else: + # Force to string and try octal conversion + return int(str(perm), 8) except (TypeError, ValueError): + log.warn("Undecodable permissions %s, assuming %s", perm, default) return default -def decode_contents(contents, decodings): +def extract_contents(contents, extraction_types): result = str(contents) - for enc in decodings: - if enc == 'application/x-gzip': + for t in extraction_types: + if t == 'application/x-gzip': result = util.decomp_gzip(result, quiet=False) - elif enc == 'application/base64': + elif t == '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: + elif t == UNKNOWN_ENC: pass return result diff --git a/doc/examples/cloud-config-write-files.txt b/doc/examples/cloud-config-write-files.txt index fb0c1541..09ec12c2 100644 --- a/doc/examples/cloud-config-write-files.txt +++ b/doc/examples/cloud-config-write-files.txt @@ -9,9 +9,11 @@ # Note: Content strings here are truncated for example purposes. # write_files: -- content: CiMgVGhpcyBmaWxlIGNvbnRyb2xzIHRoZSBzdGF0ZSBvZiBTRUxpbnV4IG9u..... - encoding: b64 +- compression: b64 + content: CiMgVGhpcyBmaWxlIGNvbnRyb2xzIHRoZSBzdGF0ZSBvZiBTRUxpbnV4... + owner: root:root path: /etc/sysconfig/selinux + perms: '0644' - content: ' # My new /etc/sysconfig/samba file @@ -20,13 +22,16 @@ write_files: ' 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 +- content: !!binary | + f0VMRgIBAQAAAAAAAAAAAAIAPgABAAAAwARAAAAAAABAAAAAAAAAAJAVAAAAAAAAAAAAAEAAOAAI + AEAAHgAdAAYAAAAFAAAAQAAAAAAAAABAAEAAAAAAAEAAQAAAAAAAwAEAAAAAAADAAQAAAAAAAAgA + AAAAAAAAAwAAAAQAAAAAAgAAAAAAAAACQAAAAAAAAAJAAAAAAAAcAAAAAAAAABwAAAAAAAAAAQAA + .... + path: /bin/arch + perms: '0555' +- compression: gzip + content: !!binary | + H4sIAIDb/U8C/1NW1E/KzNMvzuBKTc7IV8hIzcnJVyjPL8pJ4QIA6N+MVxsAAAA= + path: /usr/bin/hello + perms: '0755' -- cgit v1.2.3