From 53ba2cd353f79444f6e6c68850566fb38264f472 Mon Sep 17 00:00:00 2001 From: nervo Date: Fri, 25 Sep 2020 16:28:06 +0200 Subject: [PATCH] [All] Handle "ignore" state in exclusive templates --- CHANGELOG.md | 2 + README.md | 10 +- lookup_plugins/manala_templates_exclusive.py | 20 ++- templates/{ => config}/_macros.j2 | 0 templates/configs/_macros.j2 | 137 +++++++++++++++++++ tests/0300_configs.goss.yml | 52 ++++--- tests/0300_configs.yml | 54 +++++--- tests/templates/bar.j2 | 1 - tests/templates/configs/bar.j2 | 1 + tests/templates/configs/foo.j2 | 1 + 10 files changed, 234 insertions(+), 44 deletions(-) rename templates/{ => config}/_macros.j2 (100%) create mode 100644 templates/configs/_macros.j2 delete mode 100644 tests/templates/bar.j2 create mode 100644 tests/templates/configs/bar.j2 create mode 100644 tests/templates/configs/foo.j2 diff --git a/CHANGELOG.md b/CHANGELOG.md index 86655d3..2e9cecc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Added +- Configs can be individually ignored ## [2.0.4] - 2020-08-26 ### Fixed diff --git a/README.md b/README.md index cec896d..7617caa 100644 --- a/README.md +++ b/README.md @@ -132,8 +132,12 @@ manala_supervisor_configs: - environment: FOO: bar BAR: 12 - - file: bar.conf - state: absent + # Ensure config is absent + - file: absent.conf + state: absent # "present" by default + # Ignore config + - file: ignore.conf + state: ignore ``` Raw content @@ -141,7 +145,7 @@ Raw content ```yaml manala_supervisor_configs: - file: bar.conf - content: | + config: | [program:example] command=/usr/bin/example --loglevel=%(ENV_LOGLEVEL)s ``` diff --git a/lookup_plugins/manala_templates_exclusive.py b/lookup_plugins/manala_templates_exclusive.py index d9a515e..8cb5145 100644 --- a/lookup_plugins/manala_templates_exclusive.py +++ b/lookup_plugins/manala_templates_exclusive.py @@ -3,9 +3,11 @@ from ansible.plugins.lookup import LookupBase from ansible.errors import AnsibleError +from ansible.module_utils._text import to_text import os + class LookupModule(LookupBase): def run(self, terms, variables=None, **kwargs): @@ -14,10 +16,13 @@ def run(self, terms, variables=None, **kwargs): wantstate = kwargs.pop('wantstate', None) - templates = self._flatten(terms[0]) + if wantstate and wantstate not in ['present', 'absent']: + raise AnsibleError('Expect a wanstate of "present" or "absent" but was "%s"' % to_text(wantstate)) + + templates = self._flatten(terms[0]) exclusives = self._flatten(terms[1]) - dir = terms[2] - template = terms[3] + dir = terms[2] + template = terms[3] itemDefault = { 'state': 'present', @@ -39,7 +44,7 @@ def run(self, terms, variables=None, **kwargs): # Must be a dict if not isinstance(template, dict): - raise AnsibleError('Expect a dict') + raise AnsibleError('Expect a dict but was a %s' % type(template)) # Check file key if 'file' not in template: @@ -47,6 +52,13 @@ def run(self, terms, variables=None, **kwargs): item = itemDefault.copy() item.update(template) + + if item['state'] not in ['present', 'absent', 'ignore']: + raise AnsibleError('Expect a state of "present", "absent" or "ignore" but was "%s"' % to_text(item['state'])) + + if item['state'] == 'ignore': + continue + item.update({ 'file': os.path.join(dir, item['file']) }) diff --git a/templates/_macros.j2 b/templates/config/_macros.j2 similarity index 100% rename from templates/_macros.j2 rename to templates/config/_macros.j2 diff --git a/templates/configs/_macros.j2 b/templates/configs/_macros.j2 new file mode 100644 index 0000000..e022d7f --- /dev/null +++ b/templates/configs/_macros.j2 @@ -0,0 +1,137 @@ +{#- Deprecated -#} +{%- macro config(parameters, exclusions = [], indent = 0) -%} + {%- for parameter in parameters -%} + {%- if parameter is string or parameter is number -%} + {{ parameter }}{{ '\n' }} + {%- elif parameter is mapping -%} + {%- for parameter_key, parameter_value in parameter.items() -%} + {%- if parameter_key not in exclusions -%} + {{ _config_parameter(parameter_key, parameter_value, indent) }}{{ '\n' }} + {%- endif -%} + {%- endfor -%} + {%- endif -%} + {%- endfor -%} +{%- endmacro -%} + +{#- Deprecated -#} +{%- macro config_row(parameters, key, default, indent = 0, placeholder = false) -%} + {%- set vars = {'values': []} -%} + {%- for parameter in parameters -%} + {%- if parameter is mapping -%} + {%- for parameter_key, parameter_value in parameter.items() -%} + {%- if parameter_key == key -%} + {%- if vars.update({'values': vars['values'] + [parameter_value]}) -%}{%- endif -%} + {%- endif -%} + {%- endfor -%} + {%- endif -%} + {%- endfor -%} + {%- if vars['values']|length -%} + {%- for value in vars['values'] -%} + {{ _config_parameter(key, value, indent) }}{% if not loop.last %}{{ '\n' }}{% endif %} + {%- endfor -%} + {%- else -%} + {%- if placeholder -%} + {{ default }} + {%- else -%} + {%- for value in (default if (default is sequence and default is not string) else [default]) -%} + {{ _config_parameter(key, value, indent) }}{% if not loop.last %}{{ '\n' }}{% endif %} + {%- endfor -%} + {%- endif -%} + {%- endif -%} +{%- endmacro -%} + +{#- Deprecated -#} +{%- macro config_row_sequence(parameters, key, default, indent = 0, placeholder = false) -%} + {%- set vars = {'values': []} -%} + {%- for parameter in parameters -%} + {%- if parameter is mapping -%} + {%- for parameter_key, parameter_value in parameter.items() -%} + {%- if parameter_key == key -%} + {%- if vars.update({'values': vars['values'] + [parameter_value]}) -%}{%- endif -%} + {%- endif -%} + {%- endfor -%} + {%- endif -%} + {%- endfor -%} + {%- if vars['values']|length -%} + {%- for value in vars['values'] -%} + {{ _config_parameter_sequence(key, value, indent) }}{% if not loop.last %}{{ '\n' }}{% endif %} + {%- endfor -%} + {%- else -%} + {%- if placeholder -%} + {{ default }} + {%- else -%} + {%- for value in (default if (default is sequence and default is not string) else [default]) -%} + {{ _config_parameter_sequence(key, value, indent) }}{% if not loop.last %}{{ '\n' }}{% endif %} + {%- endfor -%} + {%- endif -%} + {%- endif -%} +{%- endmacro -%} + +{#- Deprecated -#} +{%- macro _config_parameter(key, value, indent = 0) -%} + {%- if value is sequence and value is not string -%} + [{{ key }}]{{ '\n' }}{{ config(value, []) }} + {%- else -%} + {{ _config_parameter_key(key)|indent(indent, true) }}={{ _config_parameter_value(value) }} + {%- endif -%} +{%- endmacro -%} + +{#- Deprecated -#} +{%- macro _config_parameter_sequence(key, values, indent = 0) -%} + {{ _config_parameter_key(key)|indent(indent, true) }}= + {%- for key, value in values.items() -%} + {{ key }}="{{ value }}"{% if not loop.last %},{% endif %} + {%- endfor -%} +{%- endmacro -%} + +{#- Deprecated -#} +{%- macro _config_parameter_key(key) -%} + {{ key }} +{%- endmacro -%} + +{#- Deprecated -#} +{%- macro _config_parameter_value(value) -%} + {%- if value is sameas none -%} + {%- elif value is sameas true -%} + true + {%- elif value is sameas false -%} + false + {%- elif value is string -%} + {{ value }} + {%- elif value is number -%} + {{ value }} + {%- endif -%} +{%- endmacro -%} + +{%- macro config_sections(sections, excludes = []) -%} + {%- for section, parameters in sections|dictsort -%} + {%- if section not in excludes -%} +[{{ section }}] +{{- config_parameters(parameters) }}{{ '\n\n' }} + {%- endif -%} + {%- endfor -%} +{%- endmacro -%} + +{%- macro config_parameters(parameters, excludes = []) -%} + {%- for key, value in parameters|dictsort -%} + {%- if key not in excludes -%} +{{ '\n' }}{{ config_parameter(key, value) }} + {%- endif -%} + {%- endfor -%} +{%- endmacro -%} + +{%- macro config_parameter(key, value, whitespace= False) -%} + {{ key }}{{ whitespace|ternary(' = ', '=') }}{% if value is sameas true -%} + true + {%- elif value is sameas false -%} + false + {%- elif value is mapping -%} + {%- for k, v in value|dictsort -%} + {{ k }}="{{ v }}"{% if not loop.last %},{% endif %} + {%- endfor -%} + {%- elif value is iterable and value is not string -%} + {{ value | join(',') }} + {%- else -%} + {{ value }} + {%- endif -%} +{%- endmacro -%} diff --git a/tests/0300_configs.goss.yml b/tests/0300_configs.goss.yml index 27d90c6..1bb9f22 100644 --- a/tests/0300_configs.goss.yml +++ b/tests/0300_configs.goss.yml @@ -3,6 +3,12 @@ # Default {{ if has "default" .Vars.tags }} file: + tmp/configs/default: + exists: true + filetype: directory + owner: root + group: root + mode: "0755" tmp/configs/default/foo.conf: exists: true filetype: file @@ -37,30 +43,32 @@ file: - "command=/bin/bar" - "[group:foo]" - "programs=foo,bar" - tmp/configs/default/foo_template_inet_http_server.conf: + tmp/configs/default/foo_content.conf: exists: true filetype: file owner: root group: root mode: "0644" contains: - - "[inet_http_server]" - - "port=0.0.0.1:9001" - - "username=foo" - tmp/configs/default/foo_template_deprecated.conf: + - "[program:foo]" + - "command=/bin/foo" + - "priority=123" + - "autostart=true" + - "stopsignal=HUP" + - 'environment=BAR="123",FOO="bar"' + - "[program:bar]" + - "command=/bin/bar" + - "[group:foo]" + - "programs=foo,bar" + tmp/configs/default/foo_template.conf: exists: true filetype: file owner: root group: root mode: "0644" contains: - - "[program:foo]" - - "command=cat" - - "priority=123" - - "autostart=true" - - "stopsignal=HUP" - - 'environment=FOO="bar",BAR="123"' - tmp/configs/default/foo_content.conf: + - "Config foo" + tmp/configs/default/foo_template_deprecated.conf: exists: true filetype: file owner: root @@ -68,7 +76,11 @@ file: mode: "0644" contains: - "[program:foo]" - - "command=/bin/foo" + - "command=cat" + - "priority=123" + - "autostart=true" + - "stopsignal=HUP" + - 'environment=FOO="bar",BAR="123"' tmp/configs/default/bar.conf: exists: true filetype: file @@ -99,6 +111,11 @@ file: group: root mode: "0644" size: 1 + tmp/configs/state/qux.conf: + exists: true + filetype: file + tmp/configs/state/quux.conf: + exists: false {{ end }} # Defaults @@ -111,8 +128,7 @@ file: group: root mode: "0644" contains: - - "[inet_http_server]" - - "port=0.0.0.0:9001" + - "Config foo" tmp/configs/defaults/bar.conf: exists: true filetype: file @@ -120,7 +136,7 @@ file: group: root mode: "0644" contains: - - "Bar" + - "Config bar" {{ end }} # Exclusive @@ -137,4 +153,8 @@ file: size: 1 tmp/configs/exclusive/baz.conf: exists: false + tmp/configs/exclusive/qux.conf: + exists: false + tmp/configs/exclusive/quux.conf: + exists: false {{ end }} diff --git a/tests/0300_configs.yml b/tests/0300_configs.yml index 2eec700..b836d2c 100644 --- a/tests/0300_configs.yml +++ b/tests/0300_configs.yml @@ -49,11 +49,26 @@ - command: /bin/bar - group:foo: - programs: foo,bar - - file: foo_template_inet_http_server.conf - template: configs/inet_http_server.j2 - config: - port: 0.0.0.1:9001 - username: foo + - file: foo_content.conf + config: | + [program:foo] + command=/bin/foo + priority=123 + autostart=true + stopsignal=HUP + environment=BAR="123",FOO="bar" + + [program:bar] + command=/bin/bar + + [group:foo] + programs=foo,bar + - file: bar.conf + state: present + - file: baz.conf + state: absent + - file: foo_template.conf + template: configs/foo.j2 - file: foo_template_deprecated.conf template: configs/app_program.dev.j2 config: @@ -65,14 +80,6 @@ - environment: FOO: bar BAR: 123 - - file: foo_content.conf - config: | - [program:foo] - command=/bin/foo - - file: bar.conf - state: present - - file: baz.conf - state: absent always: - name: Goss command: > @@ -86,8 +93,9 @@ state: "{{ item }}" loop: [absent, directory] - file: - path: tmp/configs/state/bar.conf + path: tmp/configs/state/{{ item }}.conf state: touch + loop: [bar, qux] - import_role: name: manala.supervisor vars: @@ -98,6 +106,10 @@ state: absent - file: baz.conf state: present + - file: qux.conf + state: ignore + - file: quux.conf + state: ignore always: - name: Goss command: > @@ -114,13 +126,11 @@ vars: manala_supervisor_configs_dir: tmp/configs/defaults manala_supervisor_configs_defaults: - template: configs/inet_http_server.j2 + template: configs/foo.j2 manala_supervisor_configs: - file: foo.conf - config: - port: 0.0.0.0:9001 - file: bar.conf - template: bar.j2 + template: configs/bar.j2 always: - name: Goss command: > @@ -134,9 +144,9 @@ state: "{{ item }}" loop: [absent, directory] - file: - path: tmp/configs/exclusive/{{ item }} + path: tmp/configs/exclusive/{{ item }}.conf state: touch - loop: [foo.conf, bar.conf, baz.conf] + loop: [foo, bar, baz, qux] - import_role: name: manala.supervisor vars: @@ -144,6 +154,10 @@ manala_supervisor_configs_exclusive: true manala_supervisor_configs: - file: bar.conf + - file: qux.conf + state: ignore + - file: quux.conf + state: ignore always: - name: Goss command: > diff --git a/tests/templates/bar.j2 b/tests/templates/bar.j2 deleted file mode 100644 index ebd7525..0000000 --- a/tests/templates/bar.j2 +++ /dev/null @@ -1 +0,0 @@ -Bar diff --git a/tests/templates/configs/bar.j2 b/tests/templates/configs/bar.j2 new file mode 100644 index 0000000..01af335 --- /dev/null +++ b/tests/templates/configs/bar.j2 @@ -0,0 +1 @@ +Config bar diff --git a/tests/templates/configs/foo.j2 b/tests/templates/configs/foo.j2 new file mode 100644 index 0000000..88a54bf --- /dev/null +++ b/tests/templates/configs/foo.j2 @@ -0,0 +1 @@ +Config foo