From 3ed702176c2ae5a0e76b84e800267a5944823bd0 Mon Sep 17 00:00:00 2001
From: Thomas Bellman <bellman@nsc.liu.se>
Date: Fri, 3 May 2024 14:02:47 +0200
Subject: [PATCH] Allow multiple listen on same address.

Apache httpd does not allow you to listen on the same address/port
more than once, which makes abstracting virtual hosts a bit more
cumbersome, as you need to keep track of and listen on addresses
separately from each virtual host.  We here abstract away that, and
allow users to use apache::listen on the same URL multiple times.
Duplicates will then be removed before Apache httpd gets to see the
list of Listen directives.

The implementation now uses concat::file to manage a single include
file containing all the Listen directives, instead of including one
file for each apache::listen resource.  To create a list of unique
Listen directives, we use the 'filter' parameter of concat::file,
running 'sort | uniq'.
---
 manifests/listen.pp | 49 +++++++++++++++++++++++++++++++--------------
 1 file changed, 34 insertions(+), 15 deletions(-)

diff --git a/manifests/listen.pp b/manifests/listen.pp
index ef97c26..d93c652 100644
--- a/manifests/listen.pp
+++ b/manifests/listen.pp
@@ -22,16 +22,13 @@
  *				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.
+ * It is permitted to listen to the same address/port combination more
+ * than once using this definition.  Duplicates will be removed from the
+ * combined list of Listen directives generated before Apache httpd gets
+ * to see them.  (This is a new behaviour of this definition since 2024.)
  *
  * To stop listening on a set of URLs, specify the 'ensure' parameter
- * with the value 'absent'.  If you just remove the apache::listen
- * resource, the include file containing the Listen directives will be
- * removed, but there will still be an Include directive referencing it,
- * and Apache httpd will refuse to start!
+ * with the value 'absent'.
  */
 
 define apache::listen(
@@ -39,7 +36,7 @@ define apache::listen(
 	$ensure = 'present',
 )
 {
-    include apache::listen::no_global_listen
+    include apache::listen::common
 
     case $ensure
     {
@@ -47,15 +44,15 @@ define apache::listen(
 	    if ($urls == false) {
 		fail("Apache::Listen[${title}]: Bad urls parameter, ${urls}")
 	    }
-	    apache::include_file {
-		"_Listen_${name}":
+	    concat::part {
+		"${apache::listen::common::listen_cfgfile}/${name}":
 		    ensure => $ensure,
 		    content => template('apache/listen.erb');
 	    }
 	}
 	'absent': {
-	    apache::include_file {
-		"_Listen_${name}":
+	    concat::part {
+		"${apache::listen::common::listen_cfgfile}/${name}":
 		    ensure => $ensure;
 	    }
 	}
@@ -66,18 +63,40 @@ define apache::listen(
 }
 
 
+
 /*
  * Internal helper class for apache::listen.
  */
-class apache::listen::no_global_listen
+class apache::listen::common
 {
     include apache
+    $listen_cfgfile = "${apache::configdir}/_Listen.conf"
 
     cfgfile::comment_lines {
 	'apache::listen::no_global_listen':
 	    file => $apache::configfile,
 	    pattern => '^\s*Listen(\s|$).*$',
 	    comment => '##--',
-	    require => Class[apache::base];
+	    require => Class[apache::base],
+	    notify => Class[apache::service];
+    }
+    concat::file {
+	$listen_cfgfile:
+	    owner => 'root', group => 'root', mode => '0444',
+            filter => 'sort | uniq',
+	    before => Apache::Include_file['_Listen'],
+	    notify => Class[apache::service];
+    }
+    apache::include_file {
+	'_Listen':
+	    ensure => 'onlyinclude';
+    }
+    delete_lines {
+	# Remove remains of old implementation
+	'apache::listen::common::single_listen_file':
+	    file => $apache::configfile,
+	    pattern => "\s*Include\s+conf\\.d/_Listen_.*\\.conf\s*$",
+	    require => Class[apache::base],
+	    notify => Class[apache::service];
     }
 }
-- 
GitLab