Presenting stream feature for nginx. TCP/UDP port proxy/balancing

With this patchset you will be able to set up tcp or udp proxy.

Change-Id: Ie88870d8ce7dc230ee895aaa6aa57c098f622186
diff --git a/README.rst b/README.rst
index 371e458..222dc69 100644
--- a/README.rst
+++ b/README.rst
@@ -74,6 +74,32 @@
               name: gitlab.domain.com
               port: 80
 
+Simple TCP/UDP proxy
+
+.. code-block:: yaml
+
+    nginx:
+      server:
+        stream:
+          rabbitmq:
+            host:
+              port: 5672
+            backend:
+              server1:
+                address: 10.10.10.113
+                port: 5672
+                least_conn: true
+                hash: "$remote_addr consistent"
+          unbound:
+            host:
+              bind: 127.0.0.1
+              port: 53
+              protocol: udp
+            backend:
+              server1:
+                address: 10.10.10.113
+                port: 5353
+
 Simple HTTP proxy
 
 .. code-block:: yaml
diff --git a/nginx/files/nginx.conf b/nginx/files/nginx.conf
index 856adab..130e664 100644
--- a/nginx/files/nginx.conf
+++ b/nginx/files/nginx.conf
@@ -75,6 +75,10 @@
         include /etc/nginx/sites-enabled/*.conf;
 }
 
+{% if server.stream is defined %}
+## Streams
+include /etc/nginx/stream.conf;
+{% endif %}
 
 #mail {
 #       # See sample authentication script at:
diff --git a/nginx/files/stream.conf b/nginx/files/stream.conf
new file mode 100644
index 0000000..0f7ef00
--- /dev/null
+++ b/nginx/files/stream.conf
@@ -0,0 +1,31 @@
+{%- from "nginx/map.jinja" import server with context -%}
+stream {
+  {% for stream_name, stream_item in server.stream.iteritems() %}
+  upstream {{ stream_name }}_upstream {
+  {%- if stream_item.least_conn is defined %}
+    least_conn;
+  {%- endif %}
+  {%- if stream_item.least_time is defined %}
+    least_time {{ stream_item.get('least_time', 'connect') }};
+  {%- endif %}
+  {%- if stream_item.hash is defined %}
+    hash {{ stream_item.get('hash', '$remote_addr') }};
+  {%- endif %}
+  {% for backend_name, backend_item in stream_item.get('backend', {}).iteritems() %}
+    server {{ backend_item.get('address', '127.0.0.1') }}:{{ backend_item.get('port', '31337') }} {{ backend_item.get('opts', '') }};
+  {%- endfor %}
+
+  }
+  {% set host = stream_item.get('host', {}) %}
+  server {
+    {% if host.bind is defined %}
+    listen {{ host.get('bind') }}:{{ host.get('port', '31337') }} {{ host.get('protocol', '') }};
+    {%- else %}
+    listen {{ host.get('port', '31337') }} {{ host.get('protocol', '') }};
+    {%- endif %}
+
+    proxy_pass {{ stream_name }}_upstream;
+
+  }
+  {% endfor %}
+}
diff --git a/nginx/server.sls b/nginx/server.sls
index fb7587a..1ca2788 100644
--- a/nginx/server.sls
+++ b/nginx/server.sls
@@ -34,6 +34,17 @@
   - watch_in:
     - service: nginx_service
 
+{%- if server.stream is defined %}
+/etc/nginx/stream.conf:
+  file.managed:
+  - source: salt://nginx/files/stream.conf
+  - template: jinja
+  - require:
+    - pkg: nginx_packages
+  - watch_in:
+    - service: nginx_service
+{%- endif %}
+
 nginx_service:
   service.running:
   - name: {{ server.service }}
diff --git a/tests/pillar/proxy.sls b/tests/pillar/proxy.sls
index 6a1a2c2..934c4e6 100644
--- a/tests/pillar/proxy.sls
+++ b/tests/pillar/proxy.sls
@@ -3,6 +3,23 @@
     enabled: true
 nginx:
   server:
+    stream:
+      rabbitmq:
+        host:
+          port: 5672
+        backend:
+          server1:
+            address: 10.10.10.113
+            port: 5672
+      unbound:
+        host:
+          bind: 127.0.0.1
+          port: 53
+          protocol: udp
+        backend:
+          server1:
+            address: 10.10.10.114
+            port: 5353
     enabled: true
     extras: false
     bind: