Add ngx_http_limit_conn_module functionality

Add posibility to limit the number of connections per the defined key

Change-Id: Ic05f9c4a4904ea4293889bc3d88d0122525df1b0
Related-Prod: PROD-24400
diff --git a/README.rst b/README.rst
index 0e04cf8..6e28916 100644
--- a/README.rst
+++ b/README.rst
@@ -415,6 +415,42 @@
                   enabled: true
 
 
+Use `ngx_http_limit_conn_module` module that is used to set the shared memory
+zone and the maximum allowed number of connections for a given key value.
+The `limit_conn_module` might be configured globally or applied to specific
+nginx site.
+
+.. code-block:: yaml
+
+    nginx:
+      server:
+        limit_conn_module:
+          limit_conn_zone:
+            global_limit_conn_zone:
+              key: 'binary_remote_addr'
+              size: 10m
+          limit_conn_status: 503
+          limit_conn:
+             global_limit_conn_zone:
+               connection: 50
+               enabled: true
+
+
+To apply connection limiting to particular site only `limit_conn` should be
+applied on site level, for example:
+
+.. code-block:: yaml
+
+    nginx:
+      server:
+        site:
+          nginx_proxy_openstack_web:
+            limit_conn_module:
+              limit_conn:
+                global_limit_conn_zone:
+                  connections: 25
+                  enabled: true
+
 Gitlab server with user for basic auth:
 
 .. code-block:: yaml
diff --git a/nginx/files/_limit_conn_module.conf b/nginx/files/_limit_conn_module.conf
new file mode 100644
index 0000000..4250415
--- /dev/null
+++ b/nginx/files/_limit_conn_module.conf
@@ -0,0 +1,19 @@
+{%- for _item,_value in _data.get('limit_conn_zone', {}).iteritems() %}
+  {%- if _value.get('enabled', 'True') %}
+limit_conn_zone ${{ _value.key }} zone={{ _value.get('name', _item) }}:{{ _value.size}};
+  {%- endif %}
+{%- endfor %}
+
+{%- for _item,_value in _data.get('limit_conn', {}).iteritems() %}
+  {%- if _value.get('enabled', 'True') %}
+limit_conn {{ _value.get('name', _item) }} {{ _value.get('connections', '50') }};
+  {%- endif %}
+{%- endfor %}
+
+{%- if _data.limit_conn_status is defined %}
+limit_conn_status {{ _data.limit_conn_status }};
+{%- endif %}
+
+{%- if _data.limit_conn_log_level is defined %}
+limit_conn_log_level {{ _data.limit_conn_log_level }};
+{% endif %}
diff --git a/nginx/files/nginx.conf b/nginx/files/nginx.conf
index 5a15b4a..9429740 100644
--- a/nginx/files/nginx.conf
+++ b/nginx/files/nginx.conf
@@ -84,6 +84,11 @@
    {%- include "nginx/files/_limit_req_module.conf" %}
 {%- endif %}
 
+{%- if server.limit_conn_module is defined %}
+ {%- set _data = server.limit_conn_module %}
+   {%- include "nginx/files/_limit_conn_module.conf" %}
+{%- endif %}
+
         include /etc/nginx/conf.d/*.conf;
         include /etc/nginx/sites-enabled/*.conf;
 
diff --git a/nginx/files/proxy.conf b/nginx/files/proxy.conf
index 2353c93..ca69367 100644
--- a/nginx/files/proxy.conf
+++ b/nginx/files/proxy.conf
@@ -133,8 +133,14 @@
         {%- include "nginx/files/_limit_req_module.conf" %}
       {%- endif %}
 
+      {%- if site.limit_conn_module is defined %}
+        {%- set _data = site.limit_conn_module %}
+        {%- include "nginx/files/_limit_conn_module.conf" %}
+      {%- endif %}
+
       {# The approach below is deprecated, as it was limited funtionality #}
       {# compare to flexibility that nginx provide. site:limit_req_module:limit_req shall be used instead. #}
+
       {%- if site.get('limit', {}).get('enabled', False) %}
       limit_req zone={{ site_name }}{% if site.limit.get('burst', False) %} burst={{ site.limit.burst }}{% endif %}{% if site.limit.get('nodelay', False) %} nodelay{% endif %};
       {%-   for subfilter_name, subfilter in site.limit.get('subfilters', {}).items() %}
diff --git a/tests/pillar/proxy_rate_limit.sls b/tests/pillar/proxy_rate_limit.sls
index 7dc7156..7cebd59 100644
--- a/tests/pillar/proxy_rate_limit.sls
+++ b/tests/pillar/proxy_rate_limit.sls
@@ -42,6 +42,21 @@
           size: 10m
           rate: '1r/s'
       limit_req_status: 503
+    limit_conn_module:
+      limit_conn_zone:
+        global_limit_conn_zone:
+          key: 'binary_remote_addr'
+          size: 20m
+          enabled: true
+        openstack_web_conn_zone:
+          key: 'binary_remote_addr'
+          size: 10m
+          enabled: true
+      limit_conn:
+        global_limit_conn_zone:
+          connections: 100
+          enabled: true
+      limit_conn_status: 503
     site:
       nginx_proxy_site01:
         enabled: true
@@ -59,3 +74,9 @@
              global_limit_zone:
                burst: 5
                enabled: true
+        limit_conn_module:
+          limit_conn:
+            openstack_web_conn_zone:
+              connections: 50
+              enabled: true
+          limit_conn_status: 503