|
Packit Service |
a04d08 |
# Copyright (C) 2012 Yahoo! Inc.
|
|
Packit Service |
a04d08 |
#
|
|
Packit Service |
a04d08 |
# Author: Joshua Harlow <harlowja@yahoo-inc.com>
|
|
Packit Service |
a04d08 |
#
|
|
Packit Service |
a04d08 |
# This file is part of cloud-init. See LICENSE file for license information.
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
import pipes
|
|
Packit Service |
a04d08 |
import re
|
|
Packit Service |
9bfd13 |
from io import StringIO
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# This library is used to parse/write
|
|
Packit Service |
a04d08 |
# out the various sysconfig files edited (best attempt effort)
|
|
Packit Service |
a04d08 |
#
|
|
Packit Service |
a04d08 |
# It has to be slightly modified though
|
|
Packit Service |
a04d08 |
# to ensure that all values are quoted/unquoted correctly
|
|
Packit Service |
a04d08 |
# since these configs are usually sourced into
|
|
Packit Service |
a04d08 |
# bash scripts...
|
|
Packit Service |
a04d08 |
import configobj
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# See: http://pubs.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap08.html
|
|
Packit Service |
a04d08 |
# or look at the 'param_expand()' function in the subst.c file in the bash
|
|
Packit Service |
a04d08 |
# source tarball...
|
|
Packit Service |
a04d08 |
SHELL_VAR_RULE = r'[a-zA-Z_]+[a-zA-Z0-9_]*'
|
|
Packit Service |
a04d08 |
SHELL_VAR_REGEXES = [
|
|
Packit Service |
a04d08 |
# Basic variables
|
|
Packit Service |
a04d08 |
re.compile(r"\$" + SHELL_VAR_RULE),
|
|
Packit Service |
a04d08 |
# Things like $?, $0, $-, $@
|
|
Packit Service |
a04d08 |
re.compile(r"\$[0-9#\?\-@\*]"),
|
|
Packit Service |
a04d08 |
# Things like ${blah:1} - but this one
|
|
Packit Service |
a04d08 |
# gets very complex so just try the
|
|
Packit Service |
a04d08 |
# simple path
|
|
Packit Service |
a04d08 |
re.compile(r"\$\{.+\}"),
|
|
Packit Service |
a04d08 |
]
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def _contains_shell_variable(text):
|
|
Packit Service |
a04d08 |
for r in SHELL_VAR_REGEXES:
|
|
Packit Service |
a04d08 |
if r.search(text):
|
|
Packit Service |
a04d08 |
return True
|
|
Packit Service |
a04d08 |
return False
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
class SysConf(configobj.ConfigObj):
|
|
Packit Service |
a04d08 |
"""A configobj.ConfigObj subclass specialised for sysconfig files.
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
:param contents:
|
|
Packit Service |
a04d08 |
The sysconfig file to parse, in a format accepted by
|
|
Packit Service |
a04d08 |
``configobj.ConfigObj.__init__`` (i.e. "a filename, file like object,
|
|
Packit Service |
a04d08 |
or list of lines").
|
|
Packit Service |
a04d08 |
"""
|
|
Packit Service |
a04d08 |
def __init__(self, contents):
|
|
Packit Service |
a04d08 |
configobj.ConfigObj.__init__(self, contents,
|
|
Packit Service |
a04d08 |
interpolation=False,
|
|
Packit Service |
a04d08 |
write_empty_values=True)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def __str__(self):
|
|
Packit Service |
a04d08 |
contents = self.write()
|
|
Packit Service |
a04d08 |
out_contents = StringIO()
|
|
Packit Service |
a04d08 |
if isinstance(contents, (list, tuple)):
|
|
Packit Service |
a04d08 |
out_contents.write("\n".join(contents))
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
out_contents.write(str(contents))
|
|
Packit Service |
a04d08 |
return out_contents.getvalue()
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def _quote(self, value, multiline=False):
|
|
Packit Service |
9bfd13 |
if not isinstance(value, str):
|
|
Packit Service |
a04d08 |
raise ValueError('Value "%s" is not a string' % (value))
|
|
Packit Service |
a04d08 |
if len(value) == 0:
|
|
Packit Service |
a04d08 |
return ''
|
|
Packit Service |
a04d08 |
quot_func = None
|
|
Packit Service |
a04d08 |
if value[0] in ['"', "'"] and value[-1] in ['"', "'"]:
|
|
Packit Service |
a04d08 |
if len(value) == 1:
|
|
Packit Service |
a04d08 |
quot_func = (lambda x: self._get_single_quote(x) % x)
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
# Quote whitespace if it isn't the start + end of a shell command
|
|
Packit Service |
a04d08 |
if value.strip().startswith("$(") and value.strip().endswith(")"):
|
|
Packit Service |
a04d08 |
pass
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
if re.search(r"[\t\r\n ]", value):
|
|
Packit Service |
a04d08 |
if _contains_shell_variable(value):
|
|
Packit Service |
a04d08 |
# If it contains shell variables then we likely want to
|
|
Packit Service |
a04d08 |
# leave it alone since the pipes.quote function likes
|
|
Packit Service |
a04d08 |
# to use single quotes which won't get expanded...
|
|
Packit Service |
a04d08 |
if re.search(r"[\n\"']", value):
|
|
Packit Service |
a04d08 |
quot_func = (lambda x:
|
|
Packit Service |
a04d08 |
self._get_triple_quote(x) % x)
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
quot_func = (lambda x:
|
|
Packit Service |
a04d08 |
self._get_single_quote(x) % x)
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
quot_func = pipes.quote
|
|
Packit Service |
a04d08 |
if not quot_func:
|
|
Packit Service |
a04d08 |
return value
|
|
Packit Service |
a04d08 |
return quot_func(value)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def _write_line(self, indent_string, entry, this_entry, comment):
|
|
Packit Service |
a04d08 |
# Ensure it is formatted fine for
|
|
Packit Service |
a04d08 |
# how these sysconfig scripts are used
|
|
Packit Service |
a04d08 |
val = self._decode_element(self._quote(this_entry))
|
|
Packit Service |
a04d08 |
key = self._decode_element(self._quote(entry))
|
|
Packit Service |
a04d08 |
cmnt = self._decode_element(comment)
|
|
Packit Service |
a04d08 |
return '%s%s%s%s%s' % (indent_string,
|
|
Packit Service |
a04d08 |
key,
|
|
Packit Service |
a04d08 |
self._a_to_u('='),
|
|
Packit Service |
a04d08 |
val,
|
|
Packit Service |
a04d08 |
cmnt)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# vi: ts=4 expandtab
|