summaryrefslogtreecommitdiff
path: root/cloudinit/mergers
diff options
context:
space:
mode:
authorJoshua Harlow <harlowja@gmail.com>2012-11-22 19:45:43 -0800
committerJoshua Harlow <harlowja@gmail.com>2012-11-22 19:45:43 -0800
commit3941466b3e065c9ce7bb7500e41f464993861672 (patch)
tree152ff7635217238d1ee562fd72df688c4c924599 /cloudinit/mergers
parent180e83b20aa02dc9df903fa7e31121dd49a49b3a (diff)
downloadcloud-init-git-3941466b3e065c9ce7bb7500e41f464993861672.tar.gz
Allow mergers to take options.
Diffstat (limited to 'cloudinit/mergers')
-rw-r--r--cloudinit/mergers/__init__.py37
-rw-r--r--cloudinit/mergers/dict.py11
-rw-r--r--cloudinit/mergers/list.py29
-rw-r--r--cloudinit/mergers/str.py12
4 files changed, 59 insertions, 30 deletions
diff --git a/cloudinit/mergers/__init__.py b/cloudinit/mergers/__init__.py
index b3e728b0..20658edc 100644
--- a/cloudinit/mergers/__init__.py
+++ b/cloudinit/mergers/__init__.py
@@ -16,11 +16,14 @@
# 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 re
from cloudinit import importer
from cloudinit import log as logging
from cloudinit import util
+NAME_MTCH = re.compile(r"(^[a-zA-Z_][A-Za-z0-9_]*)\((.*?)\)$")
+
LOG = logging.getLogger(__name__)
@@ -71,10 +74,8 @@ def _extract_merger_names(merge_how):
names = []
for m_name in merge_how.split("+"):
# Canonicalize the name (so that it can be found
- # even when users alter it in various ways...
+ # even when users alter it in various ways)
m_name = m_name.lower().strip()
- m_name = m_name.replace(" ", "_")
- m_name = m_name.replace("\t", "_")
m_name = m_name.replace("-", "_")
if not m_name:
continue
@@ -82,23 +83,29 @@ def _extract_merger_names(merge_how):
return names
-def construct(merge_how, default_classes=None):
- mergers = []
- merger_classes = []
- root = LookupMerger(mergers)
- for m_name in _extract_merger_names(merge_how):
+def construct(merge_how):
+ mergers_to_be = []
+ for name in _extract_merger_names(merge_how):
+ match = NAME_MTCH.match(name)
+ if not match:
+ msg = "Matcher identifer '%s' is not in the right format" % (name)
+ raise ValueError(msg)
+ (m_name, m_ops) = match.groups()
+ m_ops = m_ops.strip().split(",")
+ m_ops = [m.strip().lower() for m in m_ops if m.strip()]
merger_locs = importer.find_module(m_name,
[__name__],
['Merger'])
if not merger_locs:
- msg = "Could not find merger named %s" % (m_name)
+ msg = "Could not find merger named '%s'" % (m_name)
raise ImportError(msg)
else:
mod = importer.import_module(merger_locs[0])
- cls = getattr(mod, 'Merger')
- merger_classes.append(cls)
- if not merger_classes and default_classes:
- merger_classes = default_classes
- for m_class in merger_classes:
- mergers.append(m_class(root))
+ mod_attr = getattr(mod, 'Merger')
+ mergers_to_be.append((mod_attr, m_ops))
+ # Now form them...
+ mergers = []
+ root = LookupMerger(mergers)
+ for (attr, opts) in mergers_to_be:
+ mergers.append(attr(root, opts))
return root \ No newline at end of file
diff --git a/cloudinit/mergers/dict.py b/cloudinit/mergers/dict.py
index a0ffaa33..e7073bd9 100644
--- a/cloudinit/mergers/dict.py
+++ b/cloudinit/mergers/dict.py
@@ -18,8 +18,12 @@
class Merger(object):
- def __init__(self, merger):
+ def __init__(self, merger, opts):
self._merger = merger
+ self._overwrite = 'overwrite' in opts
+
+ if opts and opts.lower().find("overwrite") != -1:
+ self._overwrite = True
def _on_dict(self, value, merge_with):
if not isinstance(merge_with, (dict)):
@@ -27,7 +31,10 @@ class Merger(object):
merged = dict(value)
for (k, v) in merge_with.items():
if k in merged:
- merged[k] = self._merger.merge(merged[k], v)
+ if not self._overwrite:
+ merged[k] = self._merger.merge(merged[k], v)
+ else:
+ merged[k] = v
else:
merged[k] = v
return merged
diff --git a/cloudinit/mergers/list.py b/cloudinit/mergers/list.py
index ad1b9793..0c65d053 100644
--- a/cloudinit/mergers/list.py
+++ b/cloudinit/mergers/list.py
@@ -18,8 +18,10 @@
class Merger(object):
- def __init__(self, merger):
+ def __init__(self, merger, opts):
self._merger = merger
+ self._discard_non = 'discard_non_list' in opts
+ self._append = 'append' in opts
def _on_tuple(self, value, merge_with):
return self._on_list(list(value), merge_with)
@@ -27,15 +29,22 @@ class Merger(object):
def _on_list(self, value, merge_with):
if isinstance(merge_with, (tuple, list)):
new_value = list(value)
- for m_v in merge_with:
- m_am = 0
- for (i, o_v) in enumerate(new_value):
- if m_v == o_v:
- new_value[i] = self._merger.merge(o_v, m_v)
- m_am += 1
- if m_am == 0:
- new_value.append(m_v)
+ if self._append:
+ new_value.extend(merge_with)
+ else:
+ # Merge instead
+ for m_v in merge_with:
+ m_am = 0
+ for (i, o_v) in enumerate(new_value):
+ if m_v == o_v:
+ new_value[i] = self._merger.merge(o_v, m_v)
+ m_am += 1
+ if m_am == 0:
+ new_value.append(m_v)
else:
new_value = list(value)
- new_value.append(merge_with)
+ if self._discard_non:
+ pass
+ else:
+ new_value.append(merge_with)
return new_value
diff --git a/cloudinit/mergers/str.py b/cloudinit/mergers/str.py
index 7c3fa585..14bc46ec 100644
--- a/cloudinit/mergers/str.py
+++ b/cloudinit/mergers/str.py
@@ -18,11 +18,17 @@
class Merger(object):
- def __init__(self, merger):
- pass
+ def __init__(self, merger, opts):
+ self._append = 'append' in opts
def _on_unicode(self, value, merge_with):
return self._on_str(value, merge_with)
def _on_str(self, value, merge_with):
- return value
+ if not self._append:
+ return value
+ else:
+ if isinstance(value, (unicode)):
+ return value + unicode(merge_with)
+ else:
+ return value + str(merge_with)