From 1338e039cd51a0e9846e31a5da8886a195d7ede2 Mon Sep 17 00:00:00 2001
From: Alexander Fisher <alex@linfratech.co.uk>
Date: Thu, 27 Apr 2023 21:37:36 +0100
Subject: [PATCH] Add `include_legacy_facts` setting

When set to false (the default for Puppet 8+), all legacy facts are
pruned before the catalog is compiled.
---
 .rubocop_todo.yml                |  21 ++---
 lib/rspec-puppet.rb              |   1 +
 lib/rspec-puppet/adapters.rb     |   6 +-
 lib/rspec-puppet/legacy_facts.rb | 132 +++++++++++++++++++++++++++++++
 lib/rspec-puppet/support.rb      |   7 +-
 5 files changed, 150 insertions(+), 17 deletions(-)
 create mode 100644 lib/rspec-puppet/legacy_facts.rb

diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index c31caeacc..dde1edd37 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -1,18 +1,11 @@
 # This configuration was generated by
 # `rubocop --auto-gen-config`
-# on 2023-04-11 21:10:40 UTC using RuboCop version 1.50.0.
+# on 2023-04-27 23:06:14 UTC using RuboCop version 1.50.2.
 # The point is for the user to remove these configuration records
 # one by one as the offenses are removed from the code base.
 # Note that changes in the inspected code, or installation of new
 # versions of RuboCop, may require this file to be generated again.
 
-# Offense count: 1
-# Configuration parameters: Severity, Include.
-# Include: **/*.gemspec
-Gemspec/RequiredRubyVersion:
-  Exclude:
-    - 'rspec-puppet.gemspec'
-
 # Offense count: 3
 # Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches.
 Lint/DuplicateBranch:
@@ -90,15 +83,15 @@ Metrics/ClassLength:
 Metrics/CyclomaticComplexity:
   Max: 18
 
-# Offense count: 53
+# Offense count: 55
 # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
 Metrics/MethodLength:
-  Max: 37
+  Max: 84
 
-# Offense count: 2
+# Offense count: 3
 # Configuration parameters: CountComments, CountAsOne.
 Metrics/ModuleLength:
-  Max: 425
+  Max: 427
 
 # Offense count: 2
 # Configuration parameters: CountKeywordArgs, MaxOptionalParameters.
@@ -255,7 +248,7 @@ RSpec/MultipleDescribes:
     - 'spec/unit/adapters_spec.rb'
     - 'spec/unit/monkey_patches_spec.rb'
 
-# Offense count: 44
+# Offense count: 46
 RSpec/MultipleExpectations:
   Max: 8
 
@@ -399,7 +392,7 @@ Style/StringConcatenation:
     - 'lib/rspec-puppet/matchers/compile.rb'
     - 'lib/rspec-puppet/support.rb'
 
-# Offense count: 28
+# Offense count: 29
 # This cop supports safe autocorrection (--autocorrect).
 # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns.
 # URISchemes: http, https
diff --git a/lib/rspec-puppet.rb b/lib/rspec-puppet.rb
index 887eb1075..d293f7021 100644
--- a/lib/rspec-puppet.rb
+++ b/lib/rspec-puppet.rb
@@ -62,6 +62,7 @@ def self.current_example
   c.add_setting :fixture_hiera_configs, default: {}
   c.add_setting :use_fixture_spec_hiera, default: false
   c.add_setting :fallback_to_default_hiera, default: true
+  c.add_setting :include_legacy_facts, default: Gem::Version.new(Puppet::PUPPETVERSION) < Gem::Version.new('8.0.0')
 
   c.instance_eval do
     def trusted_server_facts
diff --git a/lib/rspec-puppet/adapters.rb b/lib/rspec-puppet/adapters.rb
index d2f9d711f..40ef4c4b0 100644
--- a/lib/rspec-puppet/adapters.rb
+++ b/lib/rspec-puppet/adapters.rb
@@ -173,7 +173,8 @@ def settings_map
           %i[environmentpath environmentpath],
           %i[hiera_config hiera_config],
           %i[strict_variables strict_variables],
-          %i[manifest manifest]
+          %i[manifest manifest],
+          %i[include_legacy_facts include_legacy_facts]
         )
       end
 
@@ -270,7 +271,8 @@ def setup_puppet(example_group)
       def settings_map
         super.push(
           %i[basemodulepath basemodulepath],
-          %i[vendormoduledir vendormoduledir]
+          %i[vendormoduledir vendormoduledir],
+          %i[include_legacy_facts include_legacy_facts]
         )
       end
 
diff --git a/lib/rspec-puppet/legacy_facts.rb b/lib/rspec-puppet/legacy_facts.rb
new file mode 100644
index 000000000..7f4431aaa
--- /dev/null
+++ b/lib/rspec-puppet/legacy_facts.rb
@@ -0,0 +1,132 @@
+# frozen_string_literal: true
+
+module RspecPuppet
+  # This module contains lists of all legacy facts
+  module LegacyFacts
+    # Used to determine if a fact is a legacy fact or not
+    #
+    # @return [Boolean] Is the fact a legacy fact
+    # @param [String] fact Fact name
+    def self.legacy_fact?(fact)
+      legacy_facts.include?(fact.to_sym) or fact.match(Regexp.union(legacy_fact_regexes))
+    end
+
+    # @api private
+    def self.legacy_fact_regexes
+      [
+        /\Ablockdevice_(?<devicename>.+)_model\Z/,
+        /\Ablockdevice_(?<devicename>.+)_size\Z/,
+        /\Ablockdevice_(?<devicename>.+)_vendor\Z/,
+        /\Aipaddress6_(?<interface>.+)\Z/,
+        /\Aipaddress_(?<interface>.+)\Z/,
+        /\Amacaddress_(?<interface>.+)\Z/,
+        /\Amtu_(?<interface>.+)\Z/,
+        /\Anetmask6_(?<interface>.+)\Z/,
+        /\Anetmask_(?<interface>.+)\Z/,
+        /\Anetwork6_(?<interface>.+)\Z/,
+        /\Anetwork_(?<interface>.+)\Z/,
+        /\Ascope6_(?<interface>.+)\Z/,
+        /\Aldom_(?<name>.+)\Z/,
+        /\Aprocessor\d+\Z/,
+        /\Asp_(?<name>.+)\Z/,
+        /\Assh(?<algorithm>.+)key\Z/,
+        /\Asshfp_(?<algorithm>.+)\Z/,
+        /\Azone_(?<name>.+)_brand\Z/,
+        /\Azone_(?<name>.+)_id\Z/,
+        /\Azone_(?<name>.+)_iptype\Z/,
+        /\Azone_(?<name>.+)_name\Z/,
+        /\Azone_(?<name>.+)_path\Z/,
+        /\Azone_(?<name>.+)_status\Z/,
+        /\Azone_(?<name>.+)_uuid\Z/
+      ]
+    end
+
+    # @api private
+    def self.legacy_facts
+      %i[
+        architecture
+        augeasversion
+        blockdevices
+        bios_release_date
+        bios_vendor
+        bios_version
+        boardassettag
+        boardmanufacturer
+        boardproductname
+        boardserialnumber
+        chassisassettag
+        chassistype
+        dhcp_servers
+        domain
+        fqdn
+        gid
+        hardwareisa
+        hardwaremodel
+        hostname
+        id
+        interfaces
+        ipaddress
+        ipaddress6
+        lsbdistcodename
+        lsbdistdescription
+        lsbdistid
+        lsbdistrelease
+        lsbmajdistrelease
+        lsbminordistrelease
+        lsbrelease
+        macaddress
+        macosx_buildversion
+        macosx_productname
+        macosx_productversion
+        macosx_productversion_major
+        macosx_productversion_minor
+        macosx_productversion_patch
+        manufacturer
+        memoryfree
+        memoryfree_mb
+        memorysize
+        memorysize_mb
+        netmask
+        netmask6
+        network
+        network6
+        operatingsystem
+        operatingsystemmajrelease
+        operatingsystemrelease
+        osfamily
+        physicalprocessorcount
+        processorcount
+        productname
+        rubyplatform
+        rubysitedir
+        rubyversion
+        scope6
+        selinux
+        selinux_config_mode
+        selinux_config_policy
+        selinux_current_mode
+        selinux_enforced
+        selinux_policyversion
+        serialnumber
+        swapencrypted
+        swapfree
+        swapfree_mb
+        swapsize
+        swapsize_mb
+        windows_edition_id
+        windows_installation_type
+        windows_product_name
+        windows_release_id
+        system32
+        uptime
+        uptime_days
+        uptime_hours
+        uptime_seconds
+        uuid
+        xendomains
+        zonename
+        zones
+      ]
+    end
+  end
+end
diff --git a/lib/rspec-puppet/support.rb b/lib/rspec-puppet/support.rb
index ec7ef5947..436b0e111 100644
--- a/lib/rspec-puppet/support.rb
+++ b/lib/rspec-puppet/support.rb
@@ -4,6 +4,7 @@
 require 'rspec-puppet/adapters'
 require 'rspec-puppet/raw_string'
 require 'rspec-puppet/sensitive'
+require 'rspec-puppet/legacy_facts'
 
 module RSpec::Puppet
   module Support
@@ -284,7 +285,11 @@ def facts_hash(node)
 
       # Facter currently supports lower case facts.  Bug FACT-777 has been submitted to support case sensitive
       # facts.
-      result_facts.transform_keys(&:downcase)
+      result_facts.transform_keys!(&:downcase)
+
+      # Prune legacy facts wherever they came from (rspec-puppet, rspec-puppet-facts, default_facts etc.)
+      result_facts.delete_if { |fact, _value| RspecPuppet::LegacyFacts.legacy_fact?(fact) } unless RSpec.configuration.include_legacy_facts
+      result_facts
     end
 
     def node_params_hash