From 72f765880f0bc624fb3d63bd751fd38abc91f1f9 Mon Sep 17 00:00:00 2001
From: Thomas Bellman <bellman@nsc.liu.se>
Date: Fri, 19 Jul 2024 19:52:48 +0200
Subject: [PATCH] ini_file: Allow a "global" section without header.

Some INI-style files can have a "global properties", variable settings
that come first in the file before any section header.  Here we add
support in the ini_file definition for generating such settings, by
putting them in a section named "" (the empty string).  So for example

    cfgfile::ini_file {
        '/etc/smurf.ini':
            settings => {
                'smurfs' => { 'colour' => 'blue', },
                '' => { 'creator' => 'Pierre', },
            };
    }

will generate a file with the content

    creator = Pierre

    [smurfs]
    colour = blue
---
 manifests/ini_file.pp  | 11 ++++++++++-
 templates/ini_file.erb | 11 +++++++++--
 2 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/manifests/ini_file.pp b/manifests/ini_file.pp
index 5eaa5a3..d0d93ba 100644
--- a/manifests/ini_file.pp
+++ b/manifests/ini_file.pp
@@ -12,6 +12,9 @@
  *  - settings	Hash of hashes for the settings in the INI file.  The outer
  *		hash names the sections, and the inner hashes contain the
  *		settings within each section.
+ *		   A section with the empty string ("") as name creates a
+ *		"global" section placed first in the file with no section
+ *		header.
  *
  *  - kvsep	Separator between the name and value for settings, normally
  *              an equal sign (=), but some INI-style files use colon (:),
@@ -40,17 +43,23 @@
  *
  *     {
  *         'smurfs' => { 'colour' => 'blue', 'population' => 99, },
- *         'gargamel' => { 'pet' => 'Azrael', }
+ *         'gargamel' => { 'pet' => 'Azrael', },
+ *         '' => { 'creator' => 'Pierre', 'country' => 'BE', },
  *     }
  *
  * creates a file with the contents
  *
+ *     country = BE
+ *     creator = Pierre
+ *
  *     [gargamel]
  *     pet = Azrael
  *
  *     [smurfs]
  *     colour = blue
  *     population = 99
+ *
+ * Note in particular the header-less "global" section first in the file.
  */
 
 define cfgfile::ini_file(
diff --git a/templates/ini_file.erb b/templates/ini_file.erb
index 0c5d6f4..96f148d 100644
--- a/templates/ini_file.erb
+++ b/templates/ini_file.erb
@@ -4,9 +4,12 @@
  #
 -%>
 <%
-    # Sort sections named "default" (case in-sensitive) before others
+    # Sort sections named "default" (case in-sensitive) and empty string
+    # ("global" section) before others.  Empty string will always be sorted
+    # first, which is required for the "global" section, as such a section
+    # will not have a header.
     sorted_sections = @settings.keys().select { |k|
-       k.downcase() == 'default'
+       k == '' or k.downcase() == 'default'
     }.sort()
     sorted_sections += @settings.keys().reject { |k|
        sorted_sections.include?(k)
@@ -18,7 +21,11 @@
     sorted_sections.each do |section_name|
        section_vars = @settings[section_name]
 -%>
+<%    # Empty section name is "global" section without section header
+      if section_name != ''
+-%>
 [<%= section_name %>]
+<%    end -%>
 <%
       # Find longest name, but only among those max 22 characters long
       shortnames = section_vars.keys().select { |name| name.length() <= 22 }
-- 
GitLab