Unhardcodig HORIZON_CONFIG dictionary

The patch makes possible to change parameters inside
HORIZON_CONFIG along with password_validator and password_validator_help.

Change-Id: I9df6ab83181429ee6303bba987e7387dd0c9d953
Related-PROD: PROD-27459
diff --git a/README.rst b/README.rst
index a79e1f3..bd06ba5 100644
--- a/README.rst
+++ b/README.rst
@@ -55,6 +55,30 @@
         default_dashboard: 'admin'
         help_url: 'http://doc.domain.com'
 
+Dashboard settings with HORIZON_CONFIG dictionary:
+
+.. code-block:: yaml
+
+    horizon:
+      server:
+        enabled: true
+        horizon_config:
+          user_home: "openstack_dashboard.views.get_user_home"
+          ajax_queue_limit: 10
+          auto_fade_alerts:
+            delay: 3000
+            fade_duration: 1500
+            types:
+              - alert-success
+              - alert-info
+          help_url: "http://docs.openstack.org"
+          modal_backdrop: "static"
+          disable_password_reveal: True
+          password_validator:
+            regex: "^.{8,18}$"
+            help_text: "Password must be between 8 and 18 characters."
+            password_autocomplete: "off"
+
 Horizon with policy files metadata. With source mine you can obtain real
 time policy file state from targeted node (OpenStack control node),
 provided you have policy file published to specified grain key. Source
diff --git a/horizon/files/horizon_settings/_horizon_config.py b/horizon/files/horizon_settings/_horizon_config.py
index fcd6503..c032c2d 100644
--- a/horizon/files/horizon_settings/_horizon_config.py
+++ b/horizon/files/horizon_settings/_horizon_config.py
@@ -1,23 +1,36 @@
+{%- from "horizon/map.jinja" import server with context %}
+
 {#- TODO (msenin): replace this construction on iteration by pillar data #}
 
-{%- set _horizon_config = app.get('horizon_config', {}) %}
+{%- if server.app is defined %}
+{%- set app = salt['pillar.get']('horizon:server:app:'+app_name) %}
+{%- else %}
+{%- set app = salt['pillar.get']('horizon:server') %}
+{%- endif %}
 
+{%- set _data = app.get('horizon_config', {}) %}
 
 HORIZON_CONFIG = {
-    'user_home': 'openstack_dashboard.views.get_user_home',
-    'ajax_queue_limit': 10,
+    'user_home': {{ _data.get('user_home', 'openstack_dashboard.views.get_user_home') | yaml_squote }},
+    'ajax_queue_limit': {{ _data.get('ajax_queue_limit', 10) }},
     'auto_fade_alerts': {
-        'delay': 3000,
-        'fade_duration': 1500,
-        'types': ['alert-success', 'alert-info']
+        'delay': {{ _data.get('auto_fade_alerts', {}).get('delay', 3000) }},
+        'fade_duration': {{ _data.get('auto_fade_alerts', {}).get('fade_duration', 1500) }},
+        'types': {{ _data.get('auto_fade_alerts', {}).get('types', ['alert-success', 'alert-info']) }}
     },
-    'help_url': "http://docs.openstack.org",
+    'help_url': "{{ _data.get('help_url', 'http://docs.openstack.org') }}",
     'exceptions': {'recoverable': exceptions.RECOVERABLE,
                    'not_found': exceptions.NOT_FOUND,
                    'unauthorized': exceptions.UNAUTHORIZED},
-    'modal_backdrop': 'static',
+    'modal_backdrop': {{ _data.get('modal_backdrop', 'static') | yaml_squote }},
     'angular_modules': [],
     'js_files': [],
     'js_spec_files': [],
-    'password_autocomplete': "{{ _horizon_config.get('password_autocomplete', 'on') }}"
+    'disable_password_reveal': {{ _data.get('disable_password_reveal', True) }},
+  {%- if _data.password_validator is defined %}
+    'password_validator': {'regex': {{ _data.password_validator.get('regex') | yaml_squote }},
+                           'help_text': {{ _data.password_validator.get('help_text') | yaml_squote }} },
+  {%- endif %}
+    'password_autocomplete': {{ _data.get('password_autocomplete', 'off') | yaml_squote }}
 }
+
diff --git a/horizon/files/local_settings/mitaka_settings.py b/horizon/files/local_settings/mitaka_settings.py
index d161c42..fa17beb 100644
--- a/horizon/files/local_settings/mitaka_settings.py
+++ b/horizon/files/local_settings/mitaka_settings.py
@@ -12,25 +12,8 @@
 {%- set app = salt['pillar.get']('horizon:server') %}
 {%- endif %}
 
-HORIZON_CONFIG = {
-    'user_home': 'openstack_dashboard.views.get_user_home',
-    'ajax_queue_limit': 10,
-    'auto_fade_alerts': {
-        'delay': 3000,
-        'fade_duration': 1500,
-        'types': ['alert-success', 'alert-info']
-    },
-    'help_url': "{{ app.get('help_url', 'http://docs.openstack.org') }}",
-    'exceptions': {'recoverable': exceptions.RECOVERABLE,
-                   'not_found': exceptions.NOT_FOUND,
-                   'unauthorized': exceptions.UNAUTHORIZED},
-    'modal_backdrop': 'static',
-    'angular_modules': [],
-    'js_files': [],
-    'js_spec_files': [],
-    'disable_password_reveal': True,
-    'password_autocomplete': 'off'
-}
+{%- include "horizon/files/horizon_settings/_horizon_config.py" %}
+
 {%- if app.themes is defined %}
 # 'key', 'label', 'path'
 {%- set theme_dir = app.themes.get('directory', 'themes') %}
diff --git a/horizon/files/local_settings/newton_settings.py b/horizon/files/local_settings/newton_settings.py
index d161c42..fa17beb 100644
--- a/horizon/files/local_settings/newton_settings.py
+++ b/horizon/files/local_settings/newton_settings.py
@@ -12,25 +12,8 @@
 {%- set app = salt['pillar.get']('horizon:server') %}
 {%- endif %}
 
-HORIZON_CONFIG = {
-    'user_home': 'openstack_dashboard.views.get_user_home',
-    'ajax_queue_limit': 10,
-    'auto_fade_alerts': {
-        'delay': 3000,
-        'fade_duration': 1500,
-        'types': ['alert-success', 'alert-info']
-    },
-    'help_url': "{{ app.get('help_url', 'http://docs.openstack.org') }}",
-    'exceptions': {'recoverable': exceptions.RECOVERABLE,
-                   'not_found': exceptions.NOT_FOUND,
-                   'unauthorized': exceptions.UNAUTHORIZED},
-    'modal_backdrop': 'static',
-    'angular_modules': [],
-    'js_files': [],
-    'js_spec_files': [],
-    'disable_password_reveal': True,
-    'password_autocomplete': 'off'
-}
+{%- include "horizon/files/horizon_settings/_horizon_config.py" %}
+
 {%- if app.themes is defined %}
 # 'key', 'label', 'path'
 {%- set theme_dir = app.themes.get('directory', 'themes') %}
diff --git a/horizon/files/local_settings/ocata_settings.py b/horizon/files/local_settings/ocata_settings.py
index ab19ac6..79597d8 100644
--- a/horizon/files/local_settings/ocata_settings.py
+++ b/horizon/files/local_settings/ocata_settings.py
@@ -12,25 +12,7 @@
 {%- set app = salt['pillar.get']('horizon:server') %}
 {%- endif %}
 
-HORIZON_CONFIG = {
-    'user_home': 'openstack_dashboard.views.get_user_home',
-    'ajax_queue_limit': 10,
-    'auto_fade_alerts': {
-        'delay': 3000,
-        'fade_duration': 1500,
-        'types': ['alert-success', 'alert-info']
-    },
-    'help_url': "{{ app.get('help_url', 'http://docs.openstack.org') }}",
-    'exceptions': {'recoverable': exceptions.RECOVERABLE,
-                   'not_found': exceptions.NOT_FOUND,
-                   'unauthorized': exceptions.UNAUTHORIZED},
-    'modal_backdrop': 'static',
-    'angular_modules': [],
-    'js_files': [],
-    'js_spec_files': [],
-    'disable_password_reveal': True,
-    'password_autocomplete': 'off'
-}
+{%- include "horizon/files/horizon_settings/_horizon_config.py" %}
 
 {%- if app.themes is defined %}
 # 'key', 'label', 'path'
diff --git a/horizon/files/local_settings/queens_settings.py b/horizon/files/local_settings/queens_settings.py
index b1e647f..79597d8 100644
--- a/horizon/files/local_settings/queens_settings.py
+++ b/horizon/files/local_settings/queens_settings.py
@@ -12,25 +12,8 @@
 {%- set app = salt['pillar.get']('horizon:server') %}
 {%- endif %}
 
-HORIZON_CONFIG = {
-    'user_home': 'openstack_dashboard.views.get_user_home',
-    'ajax_queue_limit': 10,
-    'auto_fade_alerts': {
-        'delay': 3000,
-        'fade_duration': 1500,
-        'types': ['alert-success', 'alert-info']
-    },
-    'help_url': "{{ app.get('help_url', 'http://docs.openstack.org') }}",
-    'exceptions': {'recoverable': exceptions.RECOVERABLE,
-                   'not_found': exceptions.NOT_FOUND,
-                   'unauthorized': exceptions.UNAUTHORIZED},
-    'modal_backdrop': 'static',
-    'angular_modules': [],
-    'js_files': [],
-    'js_spec_files': [],
-    'disable_password_reveal': True,
-    'password_autocomplete': 'off'
-}
+{%- include "horizon/files/horizon_settings/_horizon_config.py" %}
+
 {%- if app.themes is defined %}
 # 'key', 'label', 'path'
 {%- set theme_dir = app.themes.get('directory', 'themes') %}
diff --git a/horizon/files/local_settings/rocky_settings.py b/horizon/files/local_settings/rocky_settings.py
index b1e647f..79597d8 100644
--- a/horizon/files/local_settings/rocky_settings.py
+++ b/horizon/files/local_settings/rocky_settings.py
@@ -12,25 +12,8 @@
 {%- set app = salt['pillar.get']('horizon:server') %}
 {%- endif %}
 
-HORIZON_CONFIG = {
-    'user_home': 'openstack_dashboard.views.get_user_home',
-    'ajax_queue_limit': 10,
-    'auto_fade_alerts': {
-        'delay': 3000,
-        'fade_duration': 1500,
-        'types': ['alert-success', 'alert-info']
-    },
-    'help_url': "{{ app.get('help_url', 'http://docs.openstack.org') }}",
-    'exceptions': {'recoverable': exceptions.RECOVERABLE,
-                   'not_found': exceptions.NOT_FOUND,
-                   'unauthorized': exceptions.UNAUTHORIZED},
-    'modal_backdrop': 'static',
-    'angular_modules': [],
-    'js_files': [],
-    'js_spec_files': [],
-    'disable_password_reveal': True,
-    'password_autocomplete': 'off'
-}
+{%- include "horizon/files/horizon_settings/_horizon_config.py" %}
+
 {%- if app.themes is defined %}
 # 'key', 'label', 'path'
 {%- set theme_dir = app.themes.get('directory', 'themes') %}