From e86e6fc2219deb0bd447205e4665cce0a4f721f4 Mon Sep 17 00:00:00 2001
From: Florian Ermisch <florian.ermisch@alumni.tu-berlin.de>
Date: Fri, 24 Feb 2017 18:10:54 +0100
Subject: [PATCH] Work around missing `is mapping` on CentOS/RHEL 6

Checks for 'dict' in `x.__class__.__name__` b/c
neither `type()` nor `isinstance()` is available.
---
 salt/files/master.d/f_defaults.conf   | 11 ++++-------
 salt/files/master.d/lxc_profiles.conf |  6 ++++--
 salt/files/minion.d/f_defaults.conf   |  6 ++++--
 salt/map.jinja                        | 12 ++++++++----
 4 files changed, 20 insertions(+), 15 deletions(-)

diff --git a/salt/files/master.d/f_defaults.conf b/salt/files/master.d/f_defaults.conf
index fac82fe..36346ce 100644
--- a/salt/files/master.d/f_defaults.conf
+++ b/salt/files/master.d/f_defaults.conf
@@ -960,22 +960,19 @@ pillar_roots:
 
 {% if 'ext_pillar' in cfg_master %}
 {%- do default_keys.append('ext_pillar') %}
-{#- workaround for missing mapping test in CentOS 6, part A #}
-{%- set is_mapping = {} %}
 ext_pillar:
 {%- for pillar in cfg_master['ext_pillar'] -%}
   {%- for key in pillar -%}
     {%- if pillar[key] is string %}
   - {{ key }}: {{ pillar[key] }}
-    {#- workaround for missing mapping test in CentOS 6, part B #}
-    {%- do is_mapping.update({key: type(pillar[key]) == type({})}) %}
-    {%- elif pillar[key] is iterable and not is_mapping[key] %}
+    {#- Workaround for missing `is mapping` on CentOS 6, see #193: #}
+    {%- elif pillar[key] is iterable and 'dict' not in pillar[key].__class__.__name__ %}
   - {{ key }}:
       {%- for parameter in pillar[key] %}
     - {{ parameter }}
       {%- endfor -%}
-    {#- workaround for missing mapping test in CentOS 6, part C #}
-    {%- elif is_mapping[key] and pillar[key] is not string %}
+    {#- Workaround for missing `is mapping` on CentOS 6, see #193: #}
+    {%- elif 'dict' in pillar[key].__class__.__name__ and pillar[key] is not string %}
   - {{ key }}: 
       {%- for parameter in pillar[key] %}
       {{ parameter }}: {{pillar[key][parameter]}}
diff --git a/salt/files/master.d/lxc_profiles.conf b/salt/files/master.d/lxc_profiles.conf
index 2538848..2d453fc 100644
--- a/salt/files/master.d/lxc_profiles.conf
+++ b/salt/files/master.d/lxc_profiles.conf
@@ -12,7 +12,8 @@ lxc.container_profile:
 {%- for prof in cfg_prof %}
   {{ prof }}:
 {%- for conf in cfg_prof[prof] %}
-{%-   if cfg_prof[prof][conf] is mapping %}
+{#- Workaround for missing `is mapping` on CentOS 6, see #193 #}
+{%-   if 'dict' in cfg_prof[prof][conf].__class__.__name__ %}
     {{ conf }}:
 {%-      for opt in cfg_prof[prof][conf] %}
       {{ opt }}: {{ cfg_prof[prof][conf][opt] }}
@@ -29,7 +30,8 @@ lxc.network_profile:
 {%- for prof in cfg_net %}
   {{ prof }}:
 {%- for conf in cfg_net[prof] -%}
-{%-  if cfg_net[prof][conf] is mapping %}
+{#- Workaround for missing `is mapping` on CentOS 6, see #193 #}
+{%-  if 'dict' in cfg_net[prof][conf].__class__.__name__ %}
     {{ conf }}:
 {%-      for opt in cfg_net[prof][conf] %}
       {{ opt }}: {{ cfg_net[prof][conf][opt] }}
diff --git a/salt/files/minion.d/f_defaults.conf b/salt/files/minion.d/f_defaults.conf
index a8722cc..ae52348 100644
--- a/salt/files/minion.d/f_defaults.conf
+++ b/salt/files/minion.d/f_defaults.conf
@@ -694,12 +694,14 @@ ext_pillar:
   {%- for key in pillar -%}
     {%- if pillar[key] is string %}
   - {{ key }}: {{ pillar[key] }}
-    {%- elif pillar[key] is iterable and pillar[key] is not mapping %}
+    {#- Workaround for missing `is mapping` on CentOS 6, see #193: #}
+    {%- elif pillar[key] is iterable and 'dict' not in pillar[key].__class__.__name__ %}
   - {{ key }}:
       {%- for parameter in pillar[key] %}
     - {{ parameter }}
       {%- endfor -%}
-    {%- elif pillar[key] is mapping and pillar[key] is not string %}
+    {#- Workaround for missing `is mapping` on CentOS 6, see #193: #}
+    {%- elif 'dict' in pillar[key].__class__.__name__ and pillar[key] is not string %}
   - {{ key }}:
       {%- for parameter in pillar[key] %}
       {{ parameter }}: {{pillar[key][parameter]}}
diff --git a/salt/map.jinja b/salt/map.jinja
index 21008f2..3f7ef68 100644
--- a/salt/map.jinja
+++ b/salt/map.jinja
@@ -2,21 +2,25 @@
 # vim: ft=jinja
 
 {%- macro deep_merge(a, b) %}
+{#-     This whole `'dict' in x.__class__.__name__` mess is a 
+        workaround for the missing mapping test in CentOS 6's 
+        ancient Jinja2, see #193  #}
 {%-     for k,v in b.iteritems() %}
 {%-         if v is string or v is number %}
 {%-             do a.update({ k: v }) %}
-{%-         elif v is not mapping %}
+{%-         elif 'dict' not in v.__class__.__name__ %}
 {%-             if a[k] is not defined %}
 {%-                 do a.update({ k: v }) %}
-{%-             elif a[k] is iterable and a[k] is not mapping and a[k] is not string %}
+{%-             elif a[k] is iterable and 'dict' not in a[k].__class__.__name__ and 
+                a[k] is not string %}
 {%-                 do a.update({ k: v|list + a[k]|list}) %}
 {%-             else %}
 {%-                 do a.update({ k: v }) %}
 {%-             endif %}
-{%-         elif v is mapping %}
+{%-         elif 'dict' in v.__class__.__name__ %}
 {%-             if a[k] is not defined %}
 {%-                 do a.update({ k: v }) %}
-{%-             elif a[k] is not mapping %}
+{%-             elif 'dict' in a[k].__class__.__name__ %}
 {%-                 do a.update({ k: v }) %}
 {%-             else %}
 {%-                 do deep_merge(a[k], v) %}