From c4923d1f58159088edbe35723a3d6276cdac47c5 Mon Sep 17 00:00:00 2001
From: Viranch Mehta <viranch.mehta@gmail.com>
Date: Sat, 4 Jul 2015 18:43:52 +0530
Subject: [PATCH 1/3] Use container host's IP:port if we're connected to a
 swarm master

---
 nginx.tmpl | 30 +++++++++++++++++++++++-------
 1 file changed, 23 insertions(+), 7 deletions(-)

diff --git a/nginx.tmpl b/nginx.tmpl
index 70c8ba0..8f079e4 100644
--- a/nginx.tmpl
+++ b/nginx.tmpl
@@ -44,24 +44,40 @@ upstream {{ $host }} {
 	{{ $addrLen := len $container.Addresses }}
 	{{/* If only 1 port exposed, use that */}}
 	{{ if eq $addrLen 1 }}
-		{{ with $address := index $container.Addresses 0 }}
-		   # {{$container.Name}}
-		   server {{ $address.IP }}:{{ $address.Port }};
+		{{ $address := index $container.Addresses 0 }}
+		{{/* If we got the containers from swarm and this container's port is published to host, use host IP:PORT */}}
+		{{ if and $container.Node $address.HostPort }}
+			# {{ $container.Node.Name }}/{{$container.Name}}
+			server {{ $container.Node.Address.IP }}:{{ $address.HostPort }};
+		{{/* If there is no swarm node or the port is not published on host, use container's IP:PORT */}}
+		{{ else }}
+			# {{$container.Name}}
+			server {{ $address.IP }}:{{ $address.Port }};
 		{{ end }}
 	{{/* If more than one port exposed, use the one matching VIRTUAL_PORT env var */}}
 	{{ else if $container.Env.VIRTUAL_PORT }}
 		{{ range $address := .Addresses }}
 		   {{ if eq $address.Port $container.Env.VIRTUAL_PORT }}
-		   # {{$container.Name}}
-		   server {{ $address.IP }}:{{ $address.Port }};
+			{{ if and $container.Node $address.HostPort }}
+				# {{ $container.Node.Name }}/{{$container.Name}}
+				server {{ $container.Node.Address.IP }}:{{ $address.HostPort }};
+			{{ else }}
+				# {{$container.Name}}
+				server {{ $address.IP }}:{{ $address.Port }};
+			{{ end }}
 		   {{ end }}
 		{{ end }}
 	{{/* Else default to standard web port 80 */}}
 	{{ else }}
 		{{ $address := where $container.Addresses "Port" "80" | first }}
 		{{ if $address }}
-			# {{$container.Name}}
-			server {{ $address.IP }}:80;
+			{{ if and $container.Node $address.HostPort }}
+				# {{ $container.Node.Name }}/{{$container.Name}}
+				server {{ $container.Node.Address.IP }}:{{ $address.HostPort }};
+			{{ else }}
+				# {{$container.Name}}
+				server {{ $address.IP }}:80;
+			{{ end }}
 		{{ else }}
 			# {{$container.Name}}
 			server {{ $container.IP }} down;

From 784507df1a3200ca9d4c9840e58992f45a3ee5b9 Mon Sep 17 00:00:00 2001
From: Viranch Mehta <viranch.mehta@gmail.com>
Date: Sat, 11 Jul 2015 01:19:44 +0530
Subject: [PATCH 2/3] Cascade two else blocks into one using coalesce on
 VIRTUAL_PORT and 80

This also takes care of the case when VIRTUAL_PORT is not actually
exposed.
---
 nginx.tmpl | 20 ++++----------------
 1 file changed, 4 insertions(+), 16 deletions(-)

diff --git a/nginx.tmpl b/nginx.tmpl
index 8f079e4..147ee05 100644
--- a/nginx.tmpl
+++ b/nginx.tmpl
@@ -54,29 +54,17 @@ upstream {{ $host }} {
 			# {{$container.Name}}
 			server {{ $address.IP }}:{{ $address.Port }};
 		{{ end }}
-	{{/* If more than one port exposed, use the one matching VIRTUAL_PORT env var */}}
-	{{ else if $container.Env.VIRTUAL_PORT }}
-		{{ range $address := .Addresses }}
-		   {{ if eq $address.Port $container.Env.VIRTUAL_PORT }}
-			{{ if and $container.Node $address.HostPort }}
-				# {{ $container.Node.Name }}/{{$container.Name}}
-				server {{ $container.Node.Address.IP }}:{{ $address.HostPort }};
-			{{ else }}
-				# {{$container.Name}}
-				server {{ $address.IP }}:{{ $address.Port }};
-			{{ end }}
-		   {{ end }}
-		{{ end }}
-	{{/* Else default to standard web port 80 */}}
+	{{/* If more than one port exposed, use the one matching VIRTUAL_PORT env var, falling back to standard web port 80 */}}
 	{{ else }}
-		{{ $address := where $container.Addresses "Port" "80" | first }}
+		{{ $port := coalesce $container.Env.VIRTUAL_PORT "80" }}
+		{{ $address := where $container.Addresses "Port" $port | first }}
 		{{ if $address }}
 			{{ if and $container.Node $address.HostPort }}
 				# {{ $container.Node.Name }}/{{$container.Name}}
 				server {{ $container.Node.Address.IP }}:{{ $address.HostPort }};
 			{{ else }}
 				# {{$container.Name}}
-				server {{ $address.IP }}:80;
+				server {{ $address.IP }}:{{ $address.Port }};
 			{{ end }}
 		{{ else }}
 			# {{$container.Name}}

From 4f5351265ab47111169a8f56b897bac999f86ff6 Mon Sep 17 00:00:00 2001
From: Viranch Mehta <viranch.mehta@gmail.com>
Date: Wed, 15 Jul 2015 20:51:10 +0530
Subject: [PATCH 3/3] Use define & template for re-usable blocks of upstream
 server template

---
 nginx.tmpl | 40 +++++++++++++++++++---------------------
 1 file changed, 19 insertions(+), 21 deletions(-)

diff --git a/nginx.tmpl b/nginx.tmpl
index 147ee05..92a203c 100644
--- a/nginx.tmpl
+++ b/nginx.tmpl
@@ -1,3 +1,20 @@
+{{ define "upstream" }}
+	{{ if .Address }}
+		{{/* If we got the containers from swarm and this container's port is published to host, use host IP:PORT */}}
+		{{ if and .Container.Node.ID .Address.HostPort }}
+			# {{ .Container.Node.Name }}/{{ .Container.Name }}
+			server {{ .Container.Node.Address.IP }}:{{ .Address.HostPort }};
+		{{/* If there is no swarm node or the port is not published on host, use container's IP:PORT */}}
+		{{ else }}
+			# {{ .Container.Name }}
+			server {{ .Address.IP }}:{{ .Address.Port }};
+		{{ end }}
+	{{ else }}
+		# {{ .Container.Name }}
+		server {{ .Container.IP }} down;
+	{{ end }}
+{{ end }}
+
 # If we receive X-Forwarded-Proto, pass it through; otherwise, pass along the
 # scheme used to connect to this server
 map $http_x_forwarded_proto $proxy_x_forwarded_proto {
@@ -45,31 +62,12 @@ upstream {{ $host }} {
 	{{/* If only 1 port exposed, use that */}}
 	{{ if eq $addrLen 1 }}
 		{{ $address := index $container.Addresses 0 }}
-		{{/* If we got the containers from swarm and this container's port is published to host, use host IP:PORT */}}
-		{{ if and $container.Node $address.HostPort }}
-			# {{ $container.Node.Name }}/{{$container.Name}}
-			server {{ $container.Node.Address.IP }}:{{ $address.HostPort }};
-		{{/* If there is no swarm node or the port is not published on host, use container's IP:PORT */}}
-		{{ else }}
-			# {{$container.Name}}
-			server {{ $address.IP }}:{{ $address.Port }};
-		{{ end }}
+		{{ template "upstream" (dict "Container" $container "Address" $address) }}
 	{{/* If more than one port exposed, use the one matching VIRTUAL_PORT env var, falling back to standard web port 80 */}}
 	{{ else }}
 		{{ $port := coalesce $container.Env.VIRTUAL_PORT "80" }}
 		{{ $address := where $container.Addresses "Port" $port | first }}
-		{{ if $address }}
-			{{ if and $container.Node $address.HostPort }}
-				# {{ $container.Node.Name }}/{{$container.Name}}
-				server {{ $container.Node.Address.IP }}:{{ $address.HostPort }};
-			{{ else }}
-				# {{$container.Name}}
-				server {{ $address.IP }}:{{ $address.Port }};
-			{{ end }}
-		{{ else }}
-			# {{$container.Name}}
-			server {{ $container.IP }} down;
-		{{ end }}
+		{{ template "upstream" (dict "Container" $container "Address" $address) }}
 	{{ end }}
 {{ end }}
 }