diff options
author | Scott Moser <smoser@ubuntu.com> | 2012-07-11 17:00:21 -0400 |
---|---|---|
committer | Scott Moser <smoser@ubuntu.com> | 2012-07-11 17:00:21 -0400 |
commit | e90670e879cdd102e91f6b4c1909992ceb89fc7e (patch) | |
tree | 7feecaaff16fa3c33a632392d8832636fa17f0f6 /cloudinit/config/cc_write_files.py | |
parent | 3ad885991d355d1a97c7b197e471369d676715fa (diff) | |
parent | 50a5728db977ec11f3448c473a396995ea29319e (diff) | |
download | vyos-cloud-init-e90670e879cdd102e91f6b4c1909992ceb89fc7e.tar.gz vyos-cloud-init-e90670e879cdd102e91f6b4c1909992ceb89fc7e.zip |
add write-files module for "injecting" files (LP: #1012854)
This implements file writing via cloud-config. It also
* adjusts other code to have user/group parsing in util instead
of in stages.py,
* renames decomp_str to decomp_gzip since it is more meaningful when named
that (as thats all it can decompress).
LP: #1012854
Diffstat (limited to 'cloudinit/config/cc_write_files.py')
-rw-r--r-- | cloudinit/config/cc_write_files.py | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/cloudinit/config/cc_write_files.py b/cloudinit/config/cc_write_files.py new file mode 100644 index 00000000..1bfa4c25 --- /dev/null +++ b/cloudinit/config/cc_write_files.py @@ -0,0 +1,102 @@ +# vi: ts=4 expandtab +# +# Copyright (C) 2012 Yahoo! Inc. +# +# Author: Joshua Harlow <harlowja@yahoo-inc.com> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3, as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import base64 +import os + +from cloudinit import util +from cloudinit.settings import PER_INSTANCE + +frequency = PER_INSTANCE + +DEFAULT_OWNER = "root:root" +DEFAULT_PERMS = 0644 +UNKNOWN_ENC = 'text/plain' + + +def handle(name, cfg, _cloud, log, _args): + files = cfg.get('write_files') + if not files: + log.debug(("Skipping module named %s," + " no/empty 'write_files' key in configuration"), name) + return + write_files(name, files, log) + + +def canonicalize_extraction(encoding_type, log): + if not encoding_type: + encoding_type = '' + encoding_type = encoding_type.lower().strip() + if encoding_type in ['gz', 'gzip']: + return ['application/x-gzip'] + if encoding_type in ['gz+base64', 'gzip+base64', 'gz+b64', 'gzip+b64']: + return ['application/base64', 'application/x-gzip'] + # 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 encoding_type in ['b64', 'base64']: + return ['application/base64'] + if encoding_type: + log.warn("Unknown encoding type %s, assuming %s", + encoding_type, UNKNOWN_ENC) + return [UNKNOWN_ENC] + + +def write_files(name, files, log): + if not files: + return + + for (i, f_info) in enumerate(files): + path = f_info.get('path') + if not path: + log.warn("No path provided to write for entry %s in module %s", + i + 1, name) + continue + path = os.path.abspath(path) + extractions = canonicalize_extraction(f_info.get('encoding'), 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 decode_perms(perm, default, log): + try: + 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 extract_contents(contents, extraction_types): + result = str(contents) + for t in extraction_types: + if t == 'application/x-gzip': + result = util.decomp_gzip(result, quiet=False) + elif t == 'application/base64': + result = base64.b64decode(result) + elif t == UNKNOWN_ENC: + pass + return result |