From c02389c20645a55e4a6cc1d6bb0937831567e4dc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Romain=20Tarti=C3=A8re?= <romain@blogreen.org>
Date: Fri, 11 Dec 2020 13:23:50 -1000
Subject: [PATCH] (maint) Read system custom facts when running as a user

When Facter is run as a non-privileged user, the system custom facts are
not available.

Always take system custom facts into account, and if Facter is running
as a user who is not root, prepend this user custom facts directories to
the list of search directories.
---
 lib/facter/custom_facts/util/config.rb | 35 ++++++++++----------
 spec/custom_facts/util/config_spec.rb  | 44 +++++++++++++++++---------
 2 files changed, 46 insertions(+), 33 deletions(-)

diff --git a/lib/facter/custom_facts/util/config.rb b/lib/facter/custom_facts/util/config.rb
index eb4b9bca5b..aca57d7ac1 100644
--- a/lib/facter/custom_facts/util/config.rb
+++ b/lib/facter/custom_facts/util/config.rb
@@ -37,24 +37,23 @@ def self.facts_cache_dir
       end
 
       def self.setup_default_ext_facts_dirs
-        if LegacyFacter::Util::Root.root?
-          windows_dir = windows_data_dir
-          Facter::Options[:default_external_dir] = if windows_dir
-                                                     [File.join(windows_dir, 'PuppetLabs', 'facter', 'facts.d')]
-                                                   else
-                                                     [
-                                                       '/etc/puppetlabs/facter/facts.d',
-                                                       '/etc/facter/facts.d/',
-                                                       '/opt/puppetlabs/facter/facts.d'
-                                                     ]
-                                                   end
-        elsif ENV['HOME']
-          Facter::Options[:default_external_dir] =
-            [File.join(ENV['HOME'], '.facter', 'facts.d'),
-             File.join(ENV['HOME'], '.puppetlabs', 'opt', 'facter', 'facts.d')]
-        else
-          Facter::Options[:default_external_dir] = []
-        end
+        windows_dir = windows_data_dir
+        Facter::Options[:default_external_dir] = if windows_dir
+                                                   [File.join(windows_dir, 'PuppetLabs', 'facter', 'facts.d')]
+                                                 else
+                                                   [
+                                                     '/etc/puppetlabs/facter/facts.d',
+                                                     '/etc/facter/facts.d/',
+                                                     '/opt/puppetlabs/facter/facts.d'
+                                                   ]
+                                                 end
+
+        return unless !LegacyFacter::Util::Root.root? && ENV['HOME']
+
+        Facter::Options[:default_external_dir] = [
+          File.join(ENV['HOME'], '.facter', 'facts.d'),
+          File.join(ENV['HOME'], '.puppetlabs', 'opt', 'facter', 'facts.d')
+        ] + Facter::Options[:default_external_dir]
       end
 
       if LegacyFacter::Util::Config.windows?
diff --git a/spec/custom_facts/util/config_spec.rb b/spec/custom_facts/util/config_spec.rb
index fb384e2f2d..31ba1923f1 100755
--- a/spec/custom_facts/util/config_spec.rb
+++ b/spec/custom_facts/util/config_spec.rb
@@ -4,19 +4,6 @@
 describe LegacyFacter::Util::Config do
   include PuppetlabsSpec::Files
 
-  describe "ENV['HOME'] is unset", unless: LegacyFacter::Util::Root.root? do
-    around do |example|
-      Facter::Core::Execution.with_env('HOME' => nil) do
-        example.run
-      end
-    end
-
-    it 'does not set @external_facts_dirs' do
-      LegacyFacter::Util::Config.setup_default_ext_facts_dirs
-      expect(LegacyFacter::Util::Config.external_facts_dirs).to be_empty
-    end
-  end
-
   describe 'is_windows? function' do
     it "detects windows if Ruby RbConfig::CONFIG['host_os'] returns a windows OS" do
       host_os = %w[mswin win32 dos mingw cygwin]
@@ -78,12 +65,39 @@
         .to eq [File.join('C:\\Documents', 'PuppetLabs', 'facter', 'facts.d')]
     end
 
-    it "returns the old and new (AIO) paths under user's home directory when not root" do
+    it "returns the old and new (AIO) paths under user's home directory when not root on windows 2008" do
       allow(LegacyFacter::Util::Root).to receive(:root?).and_return(false)
+      allow(LegacyFacter::Util::Config).to receive(:windows?).and_return(true)
+      allow(LegacyFacter::Util::Config).to receive(:windows_data_dir).and_return('C:\\ProgramData')
+      LegacyFacter::Util::Config.setup_default_ext_facts_dirs
+      expect(LegacyFacter::Util::Config.external_facts_dirs)
+        .to eq [File.join(ENV['HOME'], '.facter', 'facts.d'),
+                File.join(ENV['HOME'], '.puppetlabs', 'opt', 'facter', 'facts.d'),
+                File.join('C:\\ProgramData', 'PuppetLabs', 'facter', 'facts.d')]
+    end
+
+    it "returns the old and new (AIO) paths under user's home directory when not root on windows 2003R2" do
+      allow(LegacyFacter::Util::Root).to receive(:root?).and_return(false)
+      allow(LegacyFacter::Util::Config).to receive(:windows?).and_return(true)
+      allow(LegacyFacter::Util::Config).to receive(:windows_data_dir).and_return('C:\\Documents')
+      LegacyFacter::Util::Config.setup_default_ext_facts_dirs
+      expect(LegacyFacter::Util::Config.external_facts_dirs)
+        .to eq [File.join(ENV['HOME'], '.facter', 'facts.d'),
+                File.join(ENV['HOME'], '.puppetlabs', 'opt', 'facter', 'facts.d'),
+                File.join('C:\\Documents', 'PuppetLabs', 'facter', 'facts.d')]
+    end
+
+    it "returns the old and new (AIO) paths under user's home directory when not root on linux" do
+      allow(LegacyFacter::Util::Root).to receive(:root?).and_return(false)
+      allow(LegacyFacter::Util::Config).to receive(:windows?).and_return(false)
+      allow(LegacyFacter::Util::Config).to receive(:windows_data_dir).and_return(nil)
       LegacyFacter::Util::Config.setup_default_ext_facts_dirs
       expect(LegacyFacter::Util::Config.external_facts_dirs)
         .to eq [File.join(ENV['HOME'], '.facter', 'facts.d'),
-                File.join(ENV['HOME'], '.puppetlabs', 'opt', 'facter', 'facts.d')]
+                File.join(ENV['HOME'], '.puppetlabs', 'opt', 'facter', 'facts.d'),
+                '/etc/puppetlabs/facter/facts.d',
+                '/etc/facter/facts.d/',
+                '/opt/puppetlabs/facter/facts.d']
     end
 
     it 'includes additional values when user appends to the list' do