Merge pull request #14 from jebas/master

Creates a human readable, tested, config file that fixes issue #12
This commit is contained in:
Seth House 2017-01-30 19:53:34 -07:00 committed by GitHub
commit 869b54d3be
6 changed files with 173 additions and 50 deletions

View File

@ -0,0 +1,42 @@
{%- set key = 0 -%}
{%- set value = 1 -%}
{%- set carryovers = ['real_server', 'virtual_server', 'virtual_server_group',
'vrrp_instance', 'vrrp_script', 'vrrp_sync_group'] -%}
{%- macro keepalived_config(data, carryover='', recurse=-1, indent=0) -%}
{%- set recurse = recurse + 1 -%}
{%- if data is none -%}
{{- '\n' -}}
{%- elif data is string or data is number -%}
{{- data|string|indent(indent, True) }}{{ '\n' -}}
{%- else -%}
{%- if recurse > 0 -%}
{{- '{\n' -}}
{%- set indent = indent + 2 -%}
{%- endif -%}
{%- if data is mapping -%}
{%- for item in data|dictsort -%}
{%- if item[key] in carryovers -%}
{{- keepalived_config(item[value], carryover=item[key], indent=indent) -}}
{%- else -%}
{%- set carryIndent = indent -%}
{%- set forwardIndent = indent -%}
{%- if carryover -%}
{{- carryover|indent(indent, True) }}{{ ' ' -}}
{%- set carryIndent = 0 -%}
{%- endif -%}
{%- if item[value] is string or item[value] is not iterable -%}
{%- set forwardIndent = 0 -%}
{%- endif -%}
{{- item[key]|indent(carryIndent, True) }} {{ keepalived_config(item[value], recurse=recurse, indent=forwardIndent) -}}
{%- endif -%}
{%- endfor -%}
{%- else -%}
{%- for item in data -%}
{{- keepalived_config(item, indent=indent) -}}
{%- endfor -%}
{%- endif -%}
{%- if recurse > 0 -%}
{{- '}'|indent(indent - 2, True) -}}{{ '\n' }}
{%- endif -%}
{%- endif -%}
{%- endmacro -%}

View File

@ -6,58 +6,10 @@
# Any changes will be overwritten. # Any changes will be overwritten.
{{ '\n' }} {{ '\n' }}
{# {%- import 'keepalived/templates/config.jinja' as config -%}
Macro Explanation:
This is a recursive macro that takes the type of entry and determines how
it is suppose to appear in the configuration file. Strings and numbers
are just written out. Lists and hashes are placed inside if couple of
parenthesis. It also takes into account the special groupings like
vrrp_instance and virtual_server. Any additional data from a list or a
hash is then processed by calling the macro again.
Forced carriage returns and use of jinja's indent are only there to make
the final file more human readable. They serve no other function.
#}
{%- import_yaml 'keepalived/defaults.yaml' as keepalived_defaults -%} {%- import_yaml 'keepalived/defaults.yaml' as keepalived_defaults -%}
{%- set keepalived_final_values = salt.pillar.get( {%- set keepalived_final_values = salt.pillar.get(
'keepalived', 'keepalived',
default=keepalived_defaults, default=keepalived_defaults,
merge=True) -%} merge=True) -%}
{{ config.keepalived_config(keepalived_final_values) }}
{%- set groupings = ['vrrp_script', 'vrrp_sync_group', 'vrrp_instance',
'virtual_server_group', 'virtual_server', 'real_server'] -%}
{%- macro config_entries(data, indents, carryover='') -%}
{%- if data is string or data is number -%}
{{- data|string|indent(indents, True) }}{{ '\n' -}}
{%- elif data is none -%}
{{- '\n' -}}
{%- else -%}
{%- if indents != 0 and not carryover -%}
{{- " {\n" -}}
{%- endif -%}
{%- if data is mapping -%}
{%- for entry in data|dictsort -%}
{%- if entry[0] in groupings -%}
{{- config_entries(entry[1], indents, carryover=entry[0]) -}}
{%- else -%}
{%- if carryover -%}
{{- carryover|indent(indents, True) }}{{ ' ' }}
{%- endif -%}
{{- entry[0]|indent(indents, True) }}
{{- config_entries(entry[1], indents + 2) -}}
{%- endif -%}
{%- endfor -%}
{%- else -%}
{%- for entry in data -%}
{{- config_entries(entry, indents) -}}
{%- endfor -%}
{%- endif -%}
{%- if indents != 0 and not carryover -%}
{{- '}'|indent(indents - 2, True) }}{{ '\n' }}
{%- endif -%}
{%- endif -%}
{%- endmacro -%}
{{ config_entries(keepalived_final_values, 0) }}

View File

@ -0,0 +1,2 @@
{% import 'config.jinja' as config %}
{{ config.keepalived_config(testdata) }}

View File

@ -1,6 +1,15 @@
# #
# Example pillar configuration # Example pillar configuration
# #
# Boolean entries must be placed stored as strings, otherwise it will show
# up as 1 or 0 in the config file.
#
# Anything that needs to be in quotes in the configuration file needs to
# be escaped in the yaml file. Otherwise the quotes will not appear in
# the config file.
#
# When order is important, put the entries into a yaml array or list. This
# could be used to place vrrp_script before vrrp_instance entries.
# The following would generate the example file in RedHat based systems. # The following would generate the example file in RedHat based systems.

0
test/__init__.py Normal file
View File

118
test/test_keepalived_config.py Executable file
View File

@ -0,0 +1,118 @@
#!/usr/bin/python
import os, unittest
from jinja2 import Environment, FileSystemLoader
class TestKeepalivedConfiguration(unittest.TestCase):
def setUp(self):
self.t_dir = os.path.abspath(os.path.join(
os.path.dirname(__file__),
os.pardir,
'keepalived',
'templates'))
self.t_conf = Environment(loader=FileSystemLoader(self.t_dir),
trim_blocks=True)
def renderTest(self, data, result):
holder = self.t_conf.get_template('test_config.jinja').render(testdata=data)
output = repr(holder) + ' did not equal ' + repr(result)
self.assertEqual(holder, result, output)
def test_string(self):
testdata = 'stuff'
result = 'stuff\n'
self.renderTest(testdata, result)
def test_number(self):
testdata = 3
result = '3\n'
self.renderTest(testdata, result)
def test_null(self):
testdata = None
result = '\n'
self.renderTest(testdata, result)
def test_key_value_pair(self):
testdata = {'flintstone': 'fred'}
result = 'flintstone fred\n'
self.renderTest(testdata, result)
def test_key_array_pair(self):
testdata = {'flintstone': ['fred', 'wilma', 'pebbles']}
result = 'flintstone {\n fred\n wilma\n pebbles\n}\n'
self.renderTest(testdata, result)
def test_key_hash_pair(self):
testdata = {'friends': {'rubble': 'barney'}}
result = 'friends {\n rubble barney\n}\n'
self.renderTest(testdata, result)
def test_key_ordered_hashs(self):
testdata = {'friends': {'fred': 'flintstone', 'barney': 'rubble', 'wilma': 'flintstone', 'betty': 'rubble'}}
result = 'friends {\n barney rubble\n betty rubble\n fred flintstone\n wilma flintstone\n}\n'
self.renderTest(testdata, result)
def test_ordered_hashes(self):
testdata = [{'fred': 'flintstone'}, {'wilma': 'flintstone'}, {'barney': 'rubble'}, {'betty': 'rubble'}]
result = 'fred flintstone\nwilma flintstone\nbarney rubble\nbetty rubble\n'
self.renderTest(testdata, result)
def test_carryover(self):
testdata = {'vrrp_script': {'gizmo': {'fred': 'flintstone', 'barney': 'rubble'}}}
result = 'vrrp_script gizmo {\n barney rubble\n fred flintstone\n}\n'
self.renderTest(testdata, result)
def test_carryover_contains_arry(self):
testdata = {'vrrp_script': {'gizmo': [{'fred': 'flintstone'}, {'barney': 'rubble'}]}}
result = 'vrrp_script gizmo {\n fred flintstone\n barney rubble\n}\n'
self.renderTest(testdata, result)
def test_carryover_vrrp_instance(self):
testdata = {'vrrp_instance': {'gizmo': {'fred': 'flintstone', 'barney': 'rubble'}}}
result = 'vrrp_instance gizmo {\n barney rubble\n fred flintstone\n}\n'
self.renderTest(testdata, result)
def test_carryovers_in_an_array(self):
testdata = [{'vrrp_script': {'gizmo': {'running': 'dumdums'}}}, {'vrrp_instance': {'dumdums': {'fred': 'flintstone'}}}]
result = 'vrrp_script gizmo {\n running dumdums\n}\nvrrp_instance dumdums {\n fred flintstone\n}\n'
self.renderTest(testdata, result)
def test_carryover_vrrp_sync_group(self):
testdata = {'vrrp_sync_group': {'gizmo': {'fred': 'flintstone', 'barney': 'rubble'}}}
result = 'vrrp_sync_group gizmo {\n barney rubble\n fred flintstone\n}\n'
self.renderTest(testdata, result)
def test_carryover_virtual_server_group(self):
testdata = {'virtual_server_group': {'gizmo': {'fred': 'flintstone', 'barney': 'rubble'}}}
result = 'virtual_server_group gizmo {\n barney rubble\n fred flintstone\n}\n'
self.renderTest(testdata, result)
def test_carryover_virtual_server(self):
testdata = {'virtual_server': {'gizmo': {'fred': 'flintstone', 'barney': 'rubble'}}}
result = 'virtual_server gizmo {\n barney rubble\n fred flintstone\n}\n'
self.renderTest(testdata, result)
def test_carryover_real_server(self):
testdata = {'real_server': {'gizmo': {'fred': 'flintstone', 'barney': 'rubble'}}}
result = 'real_server gizmo {\n barney rubble\n fred flintstone\n}\n'
self.renderTest(testdata, result)
def test_carryover_within_carryover(self):
testdata = {'virtual_server': {'gizmo': {'real_server': {'dumdums': {'fred': 'flintstone', 'barney': 'rubble'}}}}}
result = 'virtual_server gizmo {\n real_server dumdums {\n barney rubble\n fred flintstone\n }\n}\n'
self.renderTest(testdata, result)
def test_indent_nested_hashes(self):
testdata = {'flintstone': {'fred': {'role': {'family': 'father'}}}}
result = 'flintstone {\n fred {\n role {\n family father\n }\n }\n}\n'
self.renderTest(testdata, result)
def test_indent_carryover_with_nested_hashes(self):
testdata = {'real_server': {'gizmo': {'another': 'day', 'dumdums': {'fred': 'flintstone', 'barney': 'rubble'}}}}
result = 'real_server gizmo {\n another day\n dumdums {\n barney rubble\n fred flintstone\n }\n}\n'
self.renderTest(testdata, result)
if __name__ == '__main__':
unittest.main()