Skip to content

Commit

Permalink
Add support for another approach to load group_vars (#42)
Browse files Browse the repository at this point in the history
* Add support for another approach to load group_vars from external repository and not from group_vars.

* change merge_dict_vars to cluster_vars_format. add Readme to action plugins

* add default to cluster_vars_format|default('native')

Co-authored-by: Taras Nychko <[email protected]>
  • Loading branch information
timota and timota authored Mar 18, 2020
1 parent 4b2c4ca commit 27e132e
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 2 deletions.
33 changes: 33 additions & 0 deletions _dependencies/action_plugins/README_merge_vars.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
### Action Plugin Merge_Vars

this plugin similar to `include_vars`, but designed to merge all the variables(including dicts) in the files specified by from rather than replacing(default ansible behaviour for dicts).

This plugin is designed to support the inclusion of DRY application configuration within ansible vars. For example, if you have multiple porjects (foo, bar), and multiple environments (dev, qa, prod), and some vars are shared at various levels (project, or environment), and you want to keep your configuration DRY.

Example:

```
environment/
└── aws
├── cbe
│ └── clusterid
│ ├── app_vars.yml
│ ├── cluster.yml
│ └── dev_metadata.yml
└── dev.yml
```
#### How to use:
```
- name: Merge dict
merge_vars:
ignore_missing_files: True
from:
- "test1.yml"
- "test2.yml"
```
where,
ignore_missing_files if false - raise an error, default behaviour
from - list of files to be merged - order matters.
78 changes: 78 additions & 0 deletions _dependencies/action_plugins/merge_vars.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

from ansible.errors import AnsibleError
from ansible.plugins.action import ActionBase
from ansible.utils.vars import merge_hash
from ansible.module_utils._text import to_native, to_text
from os import path, listdir

class ActionModule(ActionBase):

VALID_ARGUMENTS = [ 'from', 'ignore_missing_files' ]

def run(self, tmp=None, task_vars=None):

if task_vars is None:
task_vars = dict()

for arg in self._task.args:
if not arg in self.VALID_ARGUMENTS:
raise AnsibleError('%s is not a valid option in merge_vars' % arg)

self.ignore_missing_files = self._task.args.get('ignore_missing_files', False)

self.show_content = True;
self._task.action = 'include_vars';

failed = False

files = []
for source in self._task.args['from']:
if path.isfile(source):
files.append(source)
elif not path.isfile(source) and self.ignore_missing_files:
continue
elif path.isdir(source):
dirfiles = [path.join(source, filename) for filename in listdir(source)]
dirfiles.sort()
files.append(dirfiles)
elif not path.isdir(source) and self.ignore_missing_files:
continue
else:
failed = True
err_msg = to_native('%s does not exist' % source)
break

data = {}
if not failed:
for filename in files:
try:
data = merge_hash(data, self._load_from_file(filename))

except AnsibleError as e:
failed = True
err_msg = to_native(e)

result = super(ActionModule, self).run(task_vars=task_vars)

if failed:
result['failed'] = failed
result['message'] = err_msg

result['ansible_included_var_files'] = files
result['ansible_facts'] = data
result['_ansible_no_log'] = not self.show_content

return result

def _load_from_file(self, filename):
# this is the approach used by include_vars in order to get the show_content
# value based on whether decryption occured. load_from_file does not return
# that value.
# https://github.com/ansible/ansible/blob/v2.7.5/lib/ansible/plugins/action/include_vars.py#L236-L240
b_data, show_content = self._loader._get_file_contents(filename)
data = to_text(b_data, errors='surrogate_or_strict')

self.show_content = show_content
return self._loader.load(data, file_name=filename, show_content=show_content) or {}
16 changes: 14 additions & 2 deletions _dependencies/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
---

- name: Force include of group_vars on localhost (no inventory yet, so cannot import automatically)
include_vars: { dir: "{{ playbook_dir }}/group_vars/{{ clusterid }}" }
- block:
- name: Force include of group_vars on localhost (no inventory yet, so cannot import automatically)
include_vars: { dir: "{{ playbook_dir }}/group_vars/{{ clusterid }}" }
when:
- cluster_vars_format|default('native') == 'native'

- name: Merge dict from different configuration files
merge_vars:
ignore_missing_files: True
from: "{{ merge_dict_vars_list }}"
when:
- cluster_vars_format|default('native') == 'tiered'
- merge_dict_vars_list is defined and merge_dict_vars_list | length > 0

tags: clusterverse_clean,clusterverse_create,clusterverse_dynamic_inventory,clusterverse_config,clusterverse_readiness

- name: Preflight check
Expand Down

0 comments on commit 27e132e

Please sign in to comment.