From 6173383e88e3d814a9737d04bec54b9ab9286b3d Mon Sep 17 00:00:00 2001
From: Thomas Bellman <bellman@nsc.liu.se>
Date: Mon, 14 Apr 2014 10:37:34 +0200
Subject: [PATCH] New definition apache::listen for managing Listen directives.

---
 manifests/listen.pp  | 58 ++++++++++++++++++++++++++++++++++++++++++++
 templates/listen.erb | 38 +++++++++++++++++++++++++++++
 2 files changed, 96 insertions(+)
 create mode 100644 manifests/listen.pp
 create mode 100644 templates/listen.erb

diff --git a/manifests/listen.pp b/manifests/listen.pp
new file mode 100644
index 0000000..95d0283
--- /dev/null
+++ b/manifests/listen.pp
@@ -0,0 +1,58 @@
+# Copyright (C) 2014 Thomas Bellman.
+# Licensed under the GNU LGPL v3+; see the README file for more information.
+
+
+import "nsc-puppet-utils"
+
+
+/*
+ * Configure Apache to listen on a set of addresses/ports/protocols.
+ *
+ * The addresses, ports and protocols to listen on is specified as a
+ * list of URLs (without any path components).  Host names in the URL
+ * will be resolved to IP addressess before being given to Apache.  The
+ * port to listen on will be determined based on the protocol, unless
+ * specified explicitly.
+ *
+ * Some examples:
+ *
+ *  - http://www.example.com/	Protocol HTTP, address www.example.com, port 80
+ *				The domain name (www.example.com) will be
+ *				resolved to an IP address at compile time.
+ *   ftp://[::1]:4711/		FTP, IPv6 address ::1, port 4711
+ *   https://*:8443/		HTTPS, INADDR_ANY, port 8443
+ *   https://[www1]/		HTTP, address "www1", port 80
+ *				The address "www1" will _not_ be resolved to
+ *				an IP address.
+ *
+ * Note that it is not possible to listen to the same address/port
+ * combination more than once, so named virtual hosts need to coordinate
+ * the set of listening addresses between themselves.  This is not
+ * enforced by this definition, but by Apache.
+ */
+
+define apache::listen($urls)
+{
+    include apache::listen::no_global_listen
+
+    apache::include_file {
+	"_Listen_${name}":
+	    content => template('apache/listen.erb');
+    }
+}
+
+
+/*
+ * Internal helper class for apache::listen.
+ */
+class apache::listen::no_global_listen
+{
+    include apache
+
+    comment_lines {
+	'apache::listen::no_global_listen':
+	    file => $apache::configfile,
+	    pattern => '^\s*Listen(\s|$).*$',
+	    comment => '##--';
+    }
+}
diff --git a/templates/listen.erb b/templates/listen.erb
new file mode 100644
index 0000000..a418737
--- /dev/null
+++ b/templates/listen.erb
@@ -0,0 +1,38 @@
+<%
+    listen_on = []
+    [@urls].flatten.sort.uniq.each { |u|
+	u =~ /^([a-z]*):\/\/([^:\/]+|\[[^\[\]]+\])(:([0-9]+))?\/?$/
+	(schema,host,port) = $1,$2,$4
+	if host == ''
+	    host = @name
+	end
+	if host == '*'
+	    addr = host
+	elsif host =~ /^\[[0-9a-f:]*:[0-9a-f:]*\]$/
+	    addr = host    # IPv6 numeric address "[0000:1111::eeee:ffff]"
+	elsif host =~ /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/
+	    addr = host    # IPv4 numeric address "111.222.333.444"
+	elsif host =~ /^\[(.+)\]$/
+	    # Hostname within brackets "[www.example.com]", not to be resolved
+	    host = addr = $1
+	else
+	    addr = scope.function_resolve_ipnets([host, 'failerrors'])
+	end
+	if port == nil
+	    if schema == 'http'
+		port = '80'
+	    elsif schema == 'https'
+		port = '443'
+	    elsif schema == 'ftp'
+		port = '21'
+	    else
+		raise(Puppet::Error, "Unknown URL schema and no port: #{u}")
+	    end
+	end
+	listen_on << addr + ':' + port + ' ' + schema
+    }
+    listen_on.sort!.uniq!
+-%>
+<% listen_on.each do |listen_spec| -%>
+Listen <%= listen_spec %>
+<% end -%>
-- 
GitLab