Created
June 10, 2015 22:12
-
-
Save cthiemann/220c128e298614a869f2 to your computer and use it in GitHub Desktop.
Ansible plugins for adding !platform YAML tag
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from ansible.errors import AnsibleFilterError | |
def selectby(value, keys, default=None, loop_over_seq=True, filter_seq=None): | |
if not isinstance(keys, list): | |
keys = [keys] # make sure we have a list of keys | |
keys.append(':') # append the 'default' key | |
if isinstance(value, list) and loop_over_seq: | |
# apply selectby to each value in the list and filter the results | |
return filter(filter_seq, [ selectby(v, keys, loop_over_seq=False) for v in value ]) | |
if not isinstance(value, dict): | |
# return value unmodified | |
return value | |
# if the value contains only a single key ending with a colon, | |
# that key (with the colon stripped) is used as the default value, | |
# and the value of that key is used as the lookup dictionary | |
# (i.e., 'value' can provide an override for 'default') | |
if len(value) == 1: | |
k = value.keys()[0] | |
if k[-1] == ':': | |
default = k[:-1] | |
value = value.values()[0] | |
if not isinstance(value, dict): | |
raise AnsibleFilterError('value of default override must be a dict') | |
# search for keys in dict value and return first match | |
for k in keys: | |
if k in value: | |
return value[k] | |
# none of the keys is in dict value | |
return default | |
class FilterModule(object): | |
def filters(self): | |
return dict(selectby=selectby) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
import yaml | |
from ansible.inventory.vars_plugins import noop | |
def repr_jinja(x): | |
if isinstance(x, list): | |
x = [ repr_jinja(e) for e in x ] | |
return '[' + ', '.join(x) + ']' | |
if isinstance(x, dict): | |
x = [ repr_jinja(k) + ': ' + repr_jinja(v) for (k, v) in x.iteritems() ] | |
return '{' + ', '.join(x) + '}' | |
if isinstance(x, str): | |
# FIXME: recognize escaped brackets | |
m = re.match('^(.*?){{(.*?)}}(.*)$', x) | |
if m: | |
x = '(' + m.group(2).strip() + ')' | |
if m.group(1): | |
x = repr_jinja(m.group(1)) + ' + ' + x | |
if m.group(3): | |
x = x + ' + ' + repr_jinja(m.group(3)) | |
return x | |
else: | |
return repr(x) | |
return repr(x) | |
def selectby_platform_constructor(loader, node): | |
if isinstance(node, yaml.ScalarNode): | |
return node.value # simple values don't need to be run through |selectby | |
elif isinstance(node, yaml.SequenceNode): | |
value = loader.construct_sequence(node, deep=True) | |
elif isinstance(node, yaml.MappingNode): | |
value = loader.construct_mapping(node, deep=True) | |
else: | |
raise yaml.ConstructorError('unknown node type: ' + type(node)) | |
return '{{ ' + repr_jinja(value) + '|selectby(ansible_platform) }}' | |
for loader in ['Loader', 'SafeLoader', 'CLoader', 'CSafeLoader']: | |
if hasattr(yaml, loader): | |
getattr(yaml, loader).add_constructor('!platform', selectby_platform_constructor) | |
class VarsModule(noop.VarsModule): | |
def get_host_vars(self, host, vault_password=None): | |
# inject the ansible_platform variable used by the !platform tag | |
platform = [ | |
'{{ ansible_distribution }}_{{ ansible_distribution_version }}', | |
'{{ ansible_distribution }}{{ ansible_distribution_major_version }}', | |
'd{{ ansible_distribution }}', # allow explicit matching if distro == family | |
'{{ ansible_distribution }}', | |
'f{{ ansible_os_family }}', # allow explicit matching if distro == family | |
'{{ ansible_os_family }}', | |
'default', | |
] | |
return dict(ansible_platform=platform) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment