From bdce45ad55394a098c9b60bf53e729a4a5de271d Mon Sep 17 00:00:00 2001
From: Thomas Bellman <bellman@nsc.liu.se>
Date: Mon, 14 Apr 2014 16:25:35 +0200
Subject: [PATCH] New definition apache::named_vhost.

This definition manages named virtual hosts and their configuration.
---
 manifests/named_vhost.pp       | 69 ++++++++++++++++++++++++++++++++++
 templates/named_vhost.conf.erb | 66 ++++++++++++++++++++++++++++++++
 2 files changed, 135 insertions(+)
 create mode 100644 manifests/named_vhost.pp
 create mode 100644 templates/named_vhost.conf.erb

diff --git a/manifests/named_vhost.pp b/manifests/named_vhost.pp
new file mode 100644
index 0000000..d660788
--- /dev/null
+++ b/manifests/named_vhost.pp
@@ -0,0 +1,69 @@
+# Copyright (C) 2014 Thomas Bellman.
+# Licensed under the GNU LGPL v3+; see the README file for more information.
+
+
+import "nsc-puppet-utils"
+
+
+/*
+ * Configure a named virtual host in Apache httpd.
+ *
+ * Parameters:
+ *
+ *  - urls
+ *    Specifies one or more addresses that this virtual host handles, i.e.
+ *    which 'Listen' directives apply to it, on the format of URLs, in the
+ *    same format as apache::listen does.  Listen directives must however
+ *    be configured separately; this definition does not do that for you.
+ *    This parameter can be either a single URL, or a list of URLs.
+ *
+ *  - servernames
+ *    Which hostnames in URLs this virtual host applies to.  Translates
+ *    into 'ServerName' and 'ServerAlias' directives.  Defaults to the
+ *    hostnames (before resolving) in the 'urls' parameter if not specified.
+ *
+ *  - documentroot
+ *    The document root for the virtual host.  Optional (Apache will by
+ *    default inherit this setting from the server-global setting).
+ *
+ *  - config
+ *    Configuration directives to put inside the virtual host declaration.
+ *    A string, or list of strings that will be concatenated with newlines
+ *    between them.  This will be surrounded by a '<VirtualHost>' container
+ *    with 'NameVirtualHost' directives, and 'ServerName', 'ServerAlias'
+ *    and optionally 'DocumentRoot' directives inside.
+ *
+ *  - ensure
+ *    One of 'present' (the default) or 'absent'.
+ */
+
+# Note: it might be tempting to let $urls default to "http://${name}/",
+# but we do not want to guess the protocol, or imply a preference of
+# e.g. http over https.
+
+define apache::named_vhost($urls, $servernames=[],
+			   $documentroot='', $config=undef,
+			   $ensure='present')
+{
+    include apache
+
+    case $ensure
+    {
+	'present': {
+	    apache::include_file {
+		"vhost-${name}":
+		    content => template('apache/named_vhost.conf.erb'),
+		    ensure => present;
+	    }
+	}
+	'absent': {
+	    apache::include_file {
+		"vhost-${name}":
+		    ensure => absent;
+	    }
+	}
+	default: {
+	    fail("Apache::Vhost[${title}]: Bad parameter ensure: ${ensure}")
+	}
+    }
+}
diff --git a/templates/named_vhost.conf.erb b/templates/named_vhost.conf.erb
new file mode 100644
index 0000000..add9d12
--- /dev/null
+++ b/templates/named_vhost.conf.erb
@@ -0,0 +1,66 @@
+<%
+    server_names = []
+    server_addrs = []
+    [@urls].flatten.sort.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
+	server_names << host + ':' + port
+	server_addrs << addr + ':' + port
+    }
+    if @servernames != []
+	server_names = @servernames
+    end
+    server_addrs.sort!.uniq!
+-%>
+<%
+##    cfg = []
+##    cfg << 'ServerName ' + server_names[0]
+##    cfg += server_names[1..-1].collect { |aliasname|
+##	'ServerAlias ' + aliasname
+##    }
+##    if @documentroot && @documentroot != ''
+##	cfg << 'DocumentRoot ' + @documentroot
+##    end
+-%>
+<% server_addrs.each do |addr| -%>
+NameVirtualHost <%= addr %>
+<% end -%>
+<VirtualHost <%= server_addrs.join(' ') %>>
+
+    ServerName <%= server_names[0] %>
+<% server_names[1..-1].each do |aliasname| -%>
+    ServerAlias <%= aliasname %>
+<% end -%>
+<% if @documentroot && @documentroot != '' -%>
+    DocumentRoot  <%= @documentroot %>
+<% end -%>
+
+<%= [@config].flatten.join("\n").gsub(/^./, '    \&') %>
+
+</VirtualHost>
-- 
GitLab