From 1f00d0c2cfeda690060522ac9da0b41a6b6a434c Mon Sep 17 00:00:00 2001 From: Michael Mol Date: Mon, 12 Jun 2017 17:30:22 -0400 Subject: [PATCH 1/6] Add flexjoin macro The flexjoin() macro simplifies support for mergable and composable structures. All three of these data structures will result in the string 'a s d f'. The third structure, using dicts, also supports pillar merging. - 'a s d f' - [ a, s, d, f] - { a: ~, s: ~, d: ~, f: ~} --- .../default/etc/zabbix/zabbix_agentd.conf.jinja | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/zabbix/files/default/etc/zabbix/zabbix_agentd.conf.jinja b/zabbix/files/default/etc/zabbix/zabbix_agentd.conf.jinja index a71f338e..d27e9772 100644 --- a/zabbix/files/default/etc/zabbix/zabbix_agentd.conf.jinja +++ b/zabbix/files/default/etc/zabbix/zabbix_agentd.conf.jinja @@ -1,4 +1,17 @@ {% from "zabbix/map.jinja" import zabbix with context -%} +{# Consider a value, keep a string, join a list, or join a dict's sorted keys -#} +{% macro flexjoin(srcval, sep=' ') -%} + {# If it's a simple value, emit it. -#} + {% if srcval is string or srcval is number -%} + {{ srcval -}} + {# If it's a dict, take the keys (for pillar merging), sort them (for stability), flexjoin them. -#} + {% elif srcval is mapping -%} + {{ flexjoin( srcval.keys()|sort, sep) -}} + {# If it's a list, join it. -#} + {% else -%} + {{ srcval|join(sep) -}} + {% endif -%} +{% endmacro -%} {% set settings = salt['pillar.get']('zabbix-agent', {}) -%} # Managed by saltstack # do not edit this file. From 37ed26ed2822c45b5442b8e5088384028cee110c Mon Sep 17 00:00:00 2001 From: Michael Mol Date: Mon, 12 Jun 2017 18:01:23 -0400 Subject: [PATCH 2/6] Support pillar merging for simple cases Certain configuration items, such as server andserveractive, are comma-delimited lists. The ordering is unimportant, so we can use flexjoin() to join our input data. We can then compose our input data from merged pillars. --- zabbix/files/default/etc/zabbix/zabbix_agentd.conf.jinja | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zabbix/files/default/etc/zabbix/zabbix_agentd.conf.jinja b/zabbix/files/default/etc/zabbix/zabbix_agentd.conf.jinja index d27e9772..6f10d1c8 100644 --- a/zabbix/files/default/etc/zabbix/zabbix_agentd.conf.jinja +++ b/zabbix/files/default/etc/zabbix/zabbix_agentd.conf.jinja @@ -93,7 +93,7 @@ # Incoming connections will be accepted only from the hosts listed here. # If IPv6 support is enabled then '127.0.0.1', '::127.0.0.1', '::ffff:127.0.0.1' are treated equally. # -Server={{ settings.get('server', ['localhost'])|join(',') }} +Server={{ flexjoin(settings.get('server', ['localhost']), ',') }} ### Option: ListenPort # Agent will listen on this port for connections from the server. @@ -104,7 +104,7 @@ Server={{ settings.get('server', ['localhost'])|join(',') }} # List of comma delimited IP addresses that the agent should listen on. # First IP address is sent to Zabbix server if connecting to it to retrieve list of active checks. # -{% if settings.get('listenip', false) %}ListenIP={{ settings.get('listenip') }}{% endif %} +{% if settings.get('listenip', false) %}ListenIP={{ flexjoin(settings.get('listenip'), ',') }}{% endif %} ### Option: StartAgents # Number of pre-forked instances of zabbix_agentd that process passive checks. @@ -122,7 +122,7 @@ Server={{ settings.get('server', ['localhost'])|join(',') }} # If this parameter is not specified, active checks are disabled. # Example: ServerActive=127.0.0.1:20051,zabbix.domain,[::1]:30051,::1,[12fc::1] # -{% if settings.get('serveractive', false) %}ServerActive={{ settings.get('serveractive')|join(',') }}{% endif %} +{% if settings.get('serveractive', false) %}ServerActive={{ flexjoin(settings.get('serveractive'), ',') }}{% endif %} ### Option: Hostname # Unique, case sensitive hostname. From c3564a0917db54e791869ce2e1765adfeb034635 Mon Sep 17 00:00:00 2001 From: Michael Mol Date: Mon, 12 Jun 2017 19:16:14 -0400 Subject: [PATCH 3/6] Add flexcall macro The flexcall() macro permits whole-line merged configuration items by calling a macro for each key in a dict, or by calling a macro for each item in a list. These two inputs are equivalent: - {a: ~, b: ~, c: ~} - [a, b, c] Example usage: {% call(element) flexcall( mydata ) -%} Here is an element from input: {{ element }} {% endcall -%} Example output: Here is an element from input: a Here is an element from input: b Here is an element from input: c --- .../default/etc/zabbix/zabbix_agentd.conf.jinja | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/zabbix/files/default/etc/zabbix/zabbix_agentd.conf.jinja b/zabbix/files/default/etc/zabbix/zabbix_agentd.conf.jinja index 6f10d1c8..b0f9e039 100644 --- a/zabbix/files/default/etc/zabbix/zabbix_agentd.conf.jinja +++ b/zabbix/files/default/etc/zabbix/zabbix_agentd.conf.jinja @@ -12,6 +12,21 @@ {{ srcval|join(sep) -}} {% endif -%} {% endmacro -%} + +{# Consider a value, iterate callback over a list or a dict's sorted keys. -#} +{% macro flexcall(srcval) -%} + {# If srcval is a dict, take the keys (for pillar mergin), sort them (for stability), iterate. -#} + {% if srcval is mapping -%} + {% for val in srcval.keys()|sort -%} + {{ caller(val) -}} + {% endfor -%} + {# If it's just a list, call back for each item in the list. -#} + {% else -%} + {% for val in srcval -%} + {{ caller(val) -}} + {% endfor -%} + {% endif -%} +{% endmacro -%} {% set settings = salt['pillar.get']('zabbix-agent', {}) -%} # Managed by saltstack # do not edit this file. From 424fabfd78f8f796092a6e29f58ab26feec7187b Mon Sep 17 00:00:00 2001 From: Michael Mol Date: Wed, 14 Jun 2017 15:45:54 -0400 Subject: [PATCH 4/6] Support pillar merging of UserParameters Support pillar merging of UserParameters via flexcall --- zabbix/files/default/etc/zabbix/zabbix_agentd.conf.jinja | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zabbix/files/default/etc/zabbix/zabbix_agentd.conf.jinja b/zabbix/files/default/etc/zabbix/zabbix_agentd.conf.jinja index b0f9e039..723f3fd7 100644 --- a/zabbix/files/default/etc/zabbix/zabbix_agentd.conf.jinja +++ b/zabbix/files/default/etc/zabbix/zabbix_agentd.conf.jinja @@ -253,9 +253,9 @@ Hostname={{ settings.get('hostname', salt['grains.get']('id')) }} # Format: UserParameter=, # See 'zabbix_agentd' directory for examples. # -{% for userparameter in settings.get('userparameters', []) -%} +{% call(userparameter) flexcall(settings.get('userparameters', [])) -%} UserParameter={{ userparameter }} -{% endfor -%} +{% endcall -%} ####### LOADABLE MODULES ####### {% if zabbix.version_repo >= '2.4' -%} From 86da726e8c19098082f1c21133fa29fa66f7c6a3 Mon Sep 17 00:00:00 2001 From: Michael Mol Date: Wed, 14 Jun 2017 15:55:44 -0400 Subject: [PATCH 5/6] Support pillar merging for per-line cases Use flexcall to support pillar merging for LoadModule and UserParameter lines. --- zabbix/files/default/etc/zabbix/zabbix_agentd.conf.jinja | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zabbix/files/default/etc/zabbix/zabbix_agentd.conf.jinja b/zabbix/files/default/etc/zabbix/zabbix_agentd.conf.jinja index 723f3fd7..02b84096 100644 --- a/zabbix/files/default/etc/zabbix/zabbix_agentd.conf.jinja +++ b/zabbix/files/default/etc/zabbix/zabbix_agentd.conf.jinja @@ -272,9 +272,9 @@ UserParameter={{ userparameter }} # The modules must be located in directory specified by LoadModulePath. # It is allowed to include multiple LoadModule parameters. # -{% for loadmodule in settings.get('loadmodules', []) -%} +{% call(loadmodule) flexcall(settings.get('loadmodules', [])) -%} LoadModule={{ loadmodule }} -{% endfor -%} +{% endcall -%} {% if zabbix.version_repo >= '3.0' -%} ####### TLS-RELATED PARAMETERS ####### From 95783f98c635bac3e0ecdd7eb84009962e7de11a Mon Sep 17 00:00:00 2001 From: Michael Mol Date: Thu, 15 Jun 2017 11:08:18 -0400 Subject: [PATCH 6/6] Be specific about flexcall list case Verify it's actually a list, so NoneTypes etc can't worm their way in. --- zabbix/files/default/etc/zabbix/zabbix_agentd.conf.jinja | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zabbix/files/default/etc/zabbix/zabbix_agentd.conf.jinja b/zabbix/files/default/etc/zabbix/zabbix_agentd.conf.jinja index 02b84096..1e816888 100644 --- a/zabbix/files/default/etc/zabbix/zabbix_agentd.conf.jinja +++ b/zabbix/files/default/etc/zabbix/zabbix_agentd.conf.jinja @@ -21,7 +21,7 @@ {{ caller(val) -}} {% endfor -%} {# If it's just a list, call back for each item in the list. -#} - {% else -%} + {% elif srcval is iterable and srcval is not string -%} {% for val in srcval -%} {{ caller(val) -}} {% endfor -%}