diff --git a/.gitignore b/.gitignore
index 88b73b3647b69b149f784f7314b2a0526b2bcda4..3bc579c8797d8387b1fdce6eb122dcf3593bd394 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,7 +16,7 @@
 /log/
 /pkg/
 /spec/fixtures/manifests/
-/spec/fixtures/modules/
+/spec/fixtures/modules/*
 /tmp/
 /vendor/
 /convert_report.txt
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 572181adcd78c1271f0bfb5079c865da2518c046..eb10a4fa5688f52406c8115bc4546cc345915220 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -5,73 +5,77 @@ stages:
   - acceptance
   - release
 
-default:
+.in-acceptance-only-matrix:
+  parallel:
+    matrix:
+      - RUBY_VERSION: ['3.2.0']
+        PUPPET_GEM_VERSION: ['~> 7']
+        PUPPET_COLLECTION: ['7']
+        DISTRIB: ['ubuntu2004-64','ubuntu2204-64']
+
+.common-matrix:
+  parallel:
+    matrix:
+      - RUBY_VERSION: ['3.2.0']
+        PUPPET_GEM_VERSION: ['~> 7']
+  image: ruby:${RUBY_VERSION}
   cache:
     paths:
       - vendor/bundle
-
-  before_script: &before_script
-    - bundle -v
-    - rm Gemfile.lock || true
-    - "# Update system gems if requested. This is useful to temporarily workaround troubles in the test runner"
-    - "# Set `rubygems_version` in the .sync.yml to set a value"
-    - "# Ignore exit code of SIGPIPE'd yes to not fail with shell's pipefail set"
-    - '[ -z "$RUBYGEMS_VERSION" ] || (yes || true) | gem update --system $RUBYGEMS_VERSION'
+  before_script:
+    - rm -f Gemfile.lock || true
+    - ruby --version
     - gem --version
     - bundle -v
-    - bundle install --without system_tests --path vendor/bundle --jobs $(nproc)
+    - bundle config set --local path 'vendor/bundle'
+    - bundle config set --local without 'system_tests'
+    - bundle config set --local jobs $(nproc)
+    - bundle install
+    - bundle clean
+    - bundle env
 
-validate lint check rubocop-Ruby 2.7.5-Puppet ~> 7:
+
+syntax:
+  extends: .common-matrix
   stage: syntax
-  image: ruby:2.7.5
   script:
-  - bundle exec rake validate lint check rubocop
-  variables:
-    PUPPET_GEM_VERSION: "~> 7"
-parallel_spec-Ruby 2.7.5-Puppet ~> 7:
+    - bundle exec rake syntax lint metadata_lint check:symlinks check:git_ignore check:dot_underscore check:test_file rubocop
+
+unit:
+  needs:
+    - syntax
+  extends: .common-matrix
   stage: unit
-  image: ruby:2.7.5
   script:
-  - bundle exec rake parallel_spec
-  variables:
-    PUPPET_GEM_VERSION: "~> 7"
-acceptance with puppet7 ubuntu2004:
+    - bundle exec rake parallel_spec
+
+acceptance:
   needs:
-  - parallel_spec-Ruby 2.7.5-Puppet ~> 7
+    - unit
+  extends:
+    - .common-matrix
+    - .in-acceptance-only-matrix
   stage: acceptance
   variables:
-    RBENV_VERSION: 2.7.5
+    RBENV_VERSION: ${RUBY_VERSION}
     PUPPET_INSTALL_TYPE: agent
     BEAKER_IS_PE: 'no'
-    BEAKER_PUPPET_COLLECTION: puppet7
+    BEAKER_PUPPET_COLLECTION: puppet${PUPPET_COLLECTION}
     BEAKER_debug: 'true'
-    BEAKER_setfile: ubuntu2004-64
+    BEAKER_setfile: ${DISTRIB}
     BEAKER_HYPERVISOR: docker
   script:
   - bundle exec rake beaker
   tags:
-  - puppet-tests
-acceptance with puppet7 ubuntu2204:
+  - beaker-acceptance
+
+release:
   needs:
-  - parallel_spec-Ruby 2.7.5-Puppet ~> 7
-  stage: acceptance
-  variables:
-    RBENV_VERSION: 2.7.5
-    PUPPET_INSTALL_TYPE: agent
-    BEAKER_IS_PE: 'no'
-    BEAKER_PUPPET_COLLECTION: puppet7
-    BEAKER_debug: 'true'
-    BEAKER_setfile: ubuntu2204-64
-    BEAKER_HYPERVISOR: docker
-  script:
-  - bundle exec rake beaker
-  tags:
-  - puppet-tests
-module release:
+    - acceptance
   stage: release
-  image: ruby:2.7.5
+  image: ruby:3.2.0
   variables:
-    PUPPET_GEM_VERSION: "~> 7.14"
+    PUPPET_GEM_VERSION: "~> 7"
     BLACKSMITH_FORGE_USERNAME: "$BLACKSMITH_FORGE_USERNAME"
     BLACKSMITH_FORGE_API_KEY: "$BLACKSMITH_FORGE_API_KEY"
   script:
@@ -85,4 +89,3 @@ module release:
     paths:
     - pkg/
     expire_in: 6 weeks
-
diff --git a/.pdkignore b/.pdkignore
index c538bea8bd4d700fc03fcc537bbd98868c004c0d..862847a72cba4311bc27e97b35fc93238c84fbdd 100644
--- a/.pdkignore
+++ b/.pdkignore
@@ -16,7 +16,7 @@
 /log/
 /pkg/
 /spec/fixtures/manifests/
-/spec/fixtures/modules/
+/spec/fixtures/modules/*
 /tmp/
 /vendor/
 /convert_report.txt
@@ -26,20 +26,17 @@
 .envrc
 /inventory.yaml
 /spec/fixtures/litmus_inventory.yaml
-/appveyor.yml
-/.editorconfig
 /.fixtures.yml
 /Gemfile
 /.gitattributes
+/.github/
 /.gitignore
-/.gitlab-ci.yml
 /.pdkignore
 /.puppet-lint.rc
 /Rakefile
 /rakelib/
 /.rspec
-/.rubocop.yml
-/.travis.yml
+/..yml
 /.yardopts
 /spec/
 /.vscode/
diff --git a/.rubocop.yml b/.rubocop.yml
index 31e8248ff813e956702d5c67844aeb0e2affc917..21b82b99b8ed1e2fb1ae4fc9a08d9aeb91054a33 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -3,8 +3,9 @@ require:
 - rubocop-performance
 - rubocop-rspec
 AllCops:
+  NewCops: enable
   DisplayCopNames: true
-  TargetRubyVersion: '2.5'
+  TargetRubyVersion: '2.6'
   Include:
   - "**/*.rb"
   Exclude:
@@ -111,8 +112,14 @@ Style/MethodCalledOnDoEndBlock:
   Enabled: true
 Style/StringMethods:
   Enabled: true
+Bundler/GemFilename:
+  Enabled: false
 Bundler/InsecureProtocolSource:
   Enabled: false
+Capybara/CurrentPathExpectation:
+  Enabled: false
+Capybara/VisibilityMatcher:
+  Enabled: false
 Gemspec/DuplicatedAssignment:
   Enabled: false
 Gemspec/OrderedDependencies:
@@ -287,11 +294,9 @@ Performance/UriDefaultParser:
   Enabled: false
 RSpec/Be:
   Enabled: false
-RSpec/Capybara/CurrentPathExpectation:
-  Enabled: false
 RSpec/Capybara/FeatureMethods:
   Enabled: false
-RSpec/Capybara/VisibilityMatcher:
+RSpec/ContainExactly:
   Enabled: false
 RSpec/ContextMethod:
   Enabled: false
@@ -331,6 +336,8 @@ RSpec/LeakyConstantDeclaration:
   Enabled: false
 RSpec/LetBeforeExamples:
   Enabled: false
+RSpec/MatchArray:
+  Enabled: false
 RSpec/MissingExampleGroupArgument:
   Enabled: false
 RSpec/MultipleExpectations:
@@ -373,8 +380,6 @@ Style/AccessModifierDeclarations:
   Enabled: false
 Style/AccessorGrouping:
   Enabled: false
-Style/AsciiComments:
-  Enabled: false
 Style/BisectedAttrAccessor:
   Enabled: false
 Style/CaseLikeIf:
@@ -485,35 +490,241 @@ Style/TrailingMethodEndStatement:
   Enabled: false
 Style/UnpackFirst:
   Enabled: false
+Capybara/MatchStyle:
+  Enabled: false
+Capybara/NegationMatcher:
+  Enabled: false
+Capybara/SpecificActions:
+  Enabled: false
+Capybara/SpecificFinders:
+  Enabled: false
+Capybara/SpecificMatcher:
+  Enabled: false
+Gemspec/DeprecatedAttributeAssignment:
+  Enabled: false
+Gemspec/DevelopmentDependencies:
+  Enabled: false
+Gemspec/RequireMFA:
+  Enabled: false
+Layout/LineContinuationLeadingSpace:
+  Enabled: false
+Layout/LineContinuationSpacing:
+  Enabled: false
+Layout/LineEndStringConcatenationIndentation:
+  Enabled: false
+Layout/SpaceBeforeBrackets:
+  Enabled: false
+Lint/AmbiguousAssignment:
+  Enabled: false
+Lint/AmbiguousOperatorPrecedence:
+  Enabled: false
+Lint/AmbiguousRange:
+  Enabled: false
+Lint/ConstantOverwrittenInRescue:
+  Enabled: false
+Lint/DeprecatedConstants:
+  Enabled: false
 Lint/DuplicateBranch:
   Enabled: false
+Lint/DuplicateMagicComment:
+  Enabled: false
+Lint/DuplicateMatchPattern:
+  Enabled: false
 Lint/DuplicateRegexpCharacterClassElement:
   Enabled: false
 Lint/EmptyBlock:
   Enabled: false
 Lint/EmptyClass:
   Enabled: false
+Lint/EmptyInPattern:
+  Enabled: false
+Lint/IncompatibleIoSelectWithFiberScheduler:
+  Enabled: false
+Lint/LambdaWithoutLiteralBlock:
+  Enabled: false
 Lint/NoReturnInBeginEndBlocks:
   Enabled: false
+Lint/NonAtomicFileOperation:
+  Enabled: false
+Lint/NumberedParameterAssignment:
+  Enabled: false
+Lint/OrAssignmentToConstant:
+  Enabled: false
+Lint/RedundantDirGlobSort:
+  Enabled: false
+Lint/RefinementImportMethods:
+  Enabled: false
+Lint/RequireRangeParentheses:
+  Enabled: false
+Lint/RequireRelativeSelfPath:
+  Enabled: false
+Lint/SymbolConversion:
+  Enabled: false
 Lint/ToEnumArguments:
   Enabled: false
+Lint/TripleQuotes:
+  Enabled: false
 Lint/UnexpectedBlockArity:
   Enabled: false
 Lint/UnmodifiedReduceAccumulator:
   Enabled: false
+Lint/UselessRescue:
+  Enabled: false
+Lint/UselessRuby2Keywords:
+  Enabled: false
+Metrics/CollectionLiteralLength:
+  Enabled: false
+Naming/BlockForwarding:
+  Enabled: false
 Performance/CollectionLiteralInLoop:
   Enabled: false
+Performance/ConcurrentMonotonicTime:
+  Enabled: false
+Performance/MapCompact:
+  Enabled: false
+Performance/RedundantEqualityComparisonBlock:
+  Enabled: false
+Performance/RedundantSplitRegexpArgument:
+  Enabled: false
+Performance/StringIdentifierArgument:
+  Enabled: false
+RSpec/BeEq:
+  Enabled: false
+RSpec/BeNil:
+  Enabled: false
+RSpec/ChangeByZero:
+  Enabled: false
+RSpec/ClassCheck:
+  Enabled: false
+RSpec/DuplicatedMetadata:
+  Enabled: false
+RSpec/ExcessiveDocstringSpacing:
+  Enabled: false
+RSpec/FactoryBot/ConsistentParenthesesStyle:
+  Enabled: false
+RSpec/FactoryBot/FactoryNameStyle:
+  Enabled: false
+RSpec/FactoryBot/SyntaxMethods:
+  Enabled: false
+RSpec/IdenticalEqualityAssertion:
+  Enabled: false
+RSpec/NoExpectationExample:
+  Enabled: false
+RSpec/PendingWithoutReason:
+  Enabled: false
+RSpec/Rails/AvoidSetupHook:
+  Enabled: false
+RSpec/Rails/HaveHttpStatus:
+  Enabled: false
+RSpec/Rails/InferredSpecType:
+  Enabled: false
+RSpec/Rails/MinitestAssertions:
+  Enabled: false
+RSpec/Rails/TravelAround:
+  Enabled: false
+RSpec/RedundantAround:
+  Enabled: false
+RSpec/SkipBlockInsideExample:
+  Enabled: false
+RSpec/SortMetadata:
+  Enabled: false
+RSpec/SubjectDeclaration:
+  Enabled: false
+RSpec/VerifiedDoubleReference:
+  Enabled: false
+Security/CompoundHash:
+  Enabled: false
+Security/IoMethods:
+  Enabled: false
 Style/ArgumentsForwarding:
   Enabled: false
+Style/ArrayIntersect:
+  Enabled: false
 Style/CollectionCompact:
   Enabled: false
+Style/ComparableClamp:
+  Enabled: false
+Style/ConcatArrayLiterals:
+  Enabled: false
+Style/DataInheritance:
+  Enabled: false
+Style/DirEmpty:
+  Enabled: false
 Style/DocumentDynamicEvalDefinition:
   Enabled: false
+Style/EmptyHeredoc:
+  Enabled: false
+Style/EndlessMethod:
+  Enabled: false
+Style/EnvHome:
+  Enabled: false
+Style/FetchEnvVar:
+  Enabled: false
+Style/FileEmpty:
+  Enabled: false
+Style/FileRead:
+  Enabled: false
+Style/FileWrite:
+  Enabled: false
+Style/HashConversion:
+  Enabled: false
+Style/HashExcept:
+  Enabled: false
+Style/IfWithBooleanLiteralBranches:
+  Enabled: false
+Style/InPatternThen:
+  Enabled: false
+Style/MagicCommentFormat:
+  Enabled: false
+Style/MapCompactWithConditionalBlock:
+  Enabled: false
+Style/MapToHash:
+  Enabled: false
+Style/MapToSet:
+  Enabled: false
+Style/MinMaxComparison:
+  Enabled: false
+Style/MultilineInPatternThen:
+  Enabled: false
 Style/NegatedIfElseCondition:
   Enabled: false
+Style/NestedFileDirname:
+  Enabled: false
 Style/NilLambda:
   Enabled: false
+Style/NumberedParameters:
+  Enabled: false
+Style/NumberedParametersLimit:
+  Enabled: false
+Style/ObjectThen:
+  Enabled: false
+Style/OpenStructUse:
+  Enabled: false
+Style/OperatorMethodCall:
+  Enabled: false
+Style/QuotedSymbols:
+  Enabled: false
 Style/RedundantArgument:
   Enabled: false
+Style/RedundantConstantBase:
+  Enabled: false
+Style/RedundantDoubleSplatHashBraces:
+  Enabled: false
+Style/RedundantEach:
+  Enabled: false
+Style/RedundantHeredocDelimiterQuotes:
+  Enabled: false
+Style/RedundantInitialize:
+  Enabled: false
+Style/RedundantLineContinuation:
+  Enabled: false
+Style/RedundantSelfAssignmentBranch:
+  Enabled: false
+Style/RedundantStringEscape:
+  Enabled: false
+Style/SelectByRegexp:
+  Enabled: false
+Style/StringChars:
+  Enabled: false
 Style/SwapValues:
   Enabled: false
diff --git a/.sync.yml b/.sync.yml
index 4fa29d6b5d17f7f3ac63c5bb1675c89824454566..aebf062ca4ca1586fdd597439a5624534ab2bdca 100644
--- a/.sync.yml
+++ b/.sync.yml
@@ -1,4 +1,6 @@
 ---
+.yardopts:
+  delete: true
 .travis.yml:
   delete: true
 appveyor.yml:
@@ -8,85 +10,8 @@ appveyor.yml:
     - .devcontainer/
     - .vscode/
     - .yardopts
-
 .gitlab-ci.yml:
-  override: true
-  custom:
-    cache:
-      paths:
-        - vendor/bundle
-    bundler_args: '--without system_tests --path vendor/bundle --jobs $(nproc)'
-    custom_stages:
-      - syntax
-      - unit
-      - acceptance
-      - release
-    custom_jobs:
-      validate lint check rubocop-Ruby 2.7.5-Puppet ~> 7:
-        stage: syntax
-        image: ruby:2.7.5
-        script:
-          - bundle exec rake validate lint check rubocop
-        variables:
-          PUPPET_GEM_VERSION: '~> 7'
-      parallel_spec-Ruby 2.7.5-Puppet ~> 7:
-        stage: unit
-        image: ruby:2.7.5
-        script:
-          - bundle exec rake parallel_spec
-        variables:
-          PUPPET_GEM_VERSION: '~> 7'
-
-      acceptance with puppet7 ubuntu2004:
-        needs:
-          - parallel_spec-Ruby 2.7.5-Puppet ~> 7
-        stage: acceptance
-        variables:
-          RBENV_VERSION: '2.7.5'
-          PUPPET_INSTALL_TYPE: 'agent'
-          BEAKER_IS_PE: 'no'
-          BEAKER_PUPPET_COLLECTION: 'puppet7'
-          BEAKER_debug: 'true'
-          BEAKER_setfile: 'ubuntu2004-64'
-          BEAKER_HYPERVISOR: 'docker'
-        script:
-          - bundle exec rake beaker
-        tags:
-          - puppet-tests
-      acceptance with puppet7 ubuntu2204:
-        needs:
-          - parallel_spec-Ruby 2.7.5-Puppet ~> 7
-        stage: acceptance
-        variables:
-          RBENV_VERSION: '2.7.5'
-          PUPPET_INSTALL_TYPE: 'agent'
-          BEAKER_IS_PE: 'no'
-          BEAKER_PUPPET_COLLECTION: 'puppet7'
-          BEAKER_debug: 'true'
-          BEAKER_setfile: 'ubuntu2204-64'
-          BEAKER_HYPERVISOR: 'docker'
-        script:
-          - bundle exec rake beaker
-        tags:
-          - puppet-tests
-      module release:
-        stage: release
-        image: ruby:2.7.5
-        variables:
-          PUPPET_GEM_VERSION: '~> 7.14'
-          BLACKSMITH_FORGE_USERNAME: '$BLACKSMITH_FORGE_USERNAME'
-          BLACKSMITH_FORGE_API_KEY: '$BLACKSMITH_FORGE_API_KEY'
-        script:
-          - bundle exec puppet strings generate --format markdown --out REFERENCE.md
-          - bundle exec rake module:push
-        only:
-          - tags
-        except:
-          - branches
-        artifacts:
-          paths:
-            - pkg/
-          expire_in: 6 weeks
+  unmanaged: true
 
 Gemfile:
   required:
@@ -97,10 +22,11 @@ Gemfile:
       - gem: 'beaker-puppet_install_helper'
       - gem: 'beaker-module_install_helper'
       - gem: 'pdk'
-        version: '<= 2.5.0'
-      - gem: 'puppet-strings'
-        version: '<= 2.8.0'
+        version: '3.2.0'
 
+Rakefile:
+  requires:
+    - 'beaker-rspec/rake_task'
 
 spec/spec_helper.rb:
   mock_with: ':rspec'
diff --git a/Gemfile b/Gemfile
index f16e6e4c840596d7940d211efffa995ddc7dada7..3ef8bb54dd6c7674ae2b2fc59f93ea4dc4efb640 100644
--- a/Gemfile
+++ b/Gemfile
@@ -13,29 +13,42 @@ def location_for(place_or_version, fake_version = nil)
   end
 end
 
-ruby_version_segments = Gem::Version.new(RUBY_VERSION.dup).segments
-minor_version = ruby_version_segments[0..1].join('.')
-
 group :development do
-  gem "json", '= 2.0.4',                                         require: false if Gem::Requirement.create('~> 2.4.2').satisfied_by?(Gem::Version.new(RUBY_VERSION.dup))
-  gem "json", '= 2.1.0',                                         require: false if Gem::Requirement.create(['>= 2.5.0', '< 2.7.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup))
-  gem "json", '= 2.3.0',                                         require: false if Gem::Requirement.create(['>= 2.7.0', '< 2.8.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup))
-  gem "puppet-module-posix-default-r#{minor_version}", '~> 1.0', require: false, platforms: [:ruby]
-  gem "puppet-module-posix-dev-r#{minor_version}", '~> 1.0',     require: false, platforms: [:ruby]
-  gem "puppet-module-win-default-r#{minor_version}", '~> 1.0',   require: false, platforms: [:mswin, :mingw, :x64_mingw]
-  gem "puppet-module-win-dev-r#{minor_version}", '~> 1.0',       require: false, platforms: [:mswin, :mingw, :x64_mingw]
-  gem "voxpupuli-puppet-lint-plugins", '>= 3.0',                 require: false
-  gem "beaker-rspec",                                            require: false
-  gem "beaker-puppet",                                           require: false
-  gem "beaker-docker",                                           require: false
-  gem "beaker-puppet_install_helper",                            require: false
-  gem "beaker-module_install_helper",                            require: false
-  gem "pdk", '<= 2.5.0',                                         require: false
-  gem "puppet-strings", '<= 2.8.0',                              require: false
+  gem "json", '= 2.1.0',                         require: false if Gem::Requirement.create(['>= 2.5.0', '< 2.7.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup))
+  gem "json", '= 2.3.0',                         require: false if Gem::Requirement.create(['>= 2.7.0', '< 3.0.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup))
+  gem "json", '= 2.5.1',                         require: false if Gem::Requirement.create(['>= 3.0.0', '< 3.0.5']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup))
+  gem "json", '= 2.6.1',                         require: false if Gem::Requirement.create(['>= 3.1.0', '< 3.1.3']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup))
+  gem "json", '= 2.6.3',                         require: false if Gem::Requirement.create(['>= 3.2.0', '< 4.0.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup))
+  gem "racc", '~> 1.4.0',                        require: false if Gem::Requirement.create(['>= 2.7.0', '< 3.0.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup))
+  gem "deep_merge", '~> 1.0',                    require: false
+  gem "voxpupuli-puppet-lint-plugins", '~> 5.0', require: false
+  gem "facterdb", '~> 1.18',                     require: false
+  gem "metadata-json-lint", '~> 4.0',            require: false
+  gem "rspec-puppet-facts", '~> 3.0',            require: false
+  gem "dependency_checker", '~> 1.0.0',          require: false
+  gem "parallel_tests", '= 3.12.1',              require: false
+  gem "pry", '~> 0.10',                          require: false
+  gem "simplecov-console", '~> 0.9',             require: false
+  gem "puppet-debugger", '~> 1.0',               require: false
+  gem "rubocop", '~> 1.50.0',                    require: false
+  gem "rubocop-performance", '= 1.16.0',         require: false
+  gem "rubocop-rspec", '= 2.19.0',               require: false
+  gem "rb-readline", '= 0.5.5',                  require: false, platforms: [:mswin, :mingw, :x64_mingw]
+  gem "beaker-rspec",                            require: false
+  gem "beaker-puppet",                           require: false
+  gem "beaker-docker",                           require: false
+  gem "beaker-puppet_install_helper",            require: false
+  gem "beaker-module_install_helper",            require: false
+  gem "pdk", '3.2.0',                            require: false
+end
+group :development, :release_prep do
+  gem "puppet-strings", '~> 4.0',         require: false
+  gem "puppetlabs_spec_helper", '~> 7.0', require: false
 end
 group :system_tests do
-  gem "puppet-module-posix-system-r#{minor_version}", '~> 1.0', require: false, platforms: [:ruby]
-  gem "puppet-module-win-system-r#{minor_version}", '~> 1.0',   require: false, platforms: [:mswin, :mingw, :x64_mingw]
+  gem "puppet_litmus", '~> 1.0',   require: false, platforms: [:ruby, :x64_mingw]
+  gem "CFPropertyList", '< 3.0.7', require: false, platforms: [:mswin, :mingw, :x64_mingw]
+  gem "serverspec", '~> 2.41',     require: false
 end
 
 puppet_version = ENV['PUPPET_GEM_VERSION']
diff --git a/Rakefile b/Rakefile
index 0f8754eb61e400db1d117cad5026f06d3ba6ff89..b4eb85703c7db096b3f6e40c86eae5d1cfc3e137 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,89 +1,10 @@
 # frozen_string_literal: true
 
 require 'bundler'
-require 'puppet_litmus/rake_tasks' if Bundler.rubygems.find_name('puppet_litmus').any?
+require 'puppet_litmus/rake_tasks' if Gem.loaded_specs.key? 'puppet_litmus'
 require 'puppetlabs_spec_helper/rake_tasks'
 require 'puppet-syntax/tasks/puppet-syntax'
-require 'puppet_blacksmith/rake_tasks' if Bundler.rubygems.find_name('puppet-blacksmith').any?
-require 'github_changelog_generator/task' if Bundler.rubygems.find_name('github_changelog_generator').any?
-require 'puppet-strings/tasks' if Bundler.rubygems.find_name('puppet-strings').any?
-
-def changelog_user
-  return unless Rake.application.top_level_tasks.include? "changelog"
-  returnVal = nil || JSON.load(File.read('metadata.json'))['author']
-  raise "unable to find the changelog_user in .sync.yml, or the author in metadata.json" if returnVal.nil?
-  puts "GitHubChangelogGenerator user:#{returnVal}"
-  returnVal
-end
-
-def changelog_project
-  return unless Rake.application.top_level_tasks.include? "changelog"
-
-  returnVal = nil
-  returnVal ||= begin
-    metadata_source = JSON.load(File.read('metadata.json'))['source']
-    metadata_source_match = metadata_source && metadata_source.match(%r{.*\/([^\/]*?)(?:\.git)?\Z})
-
-    metadata_source_match && metadata_source_match[1]
-  end
-
-  raise "unable to find the changelog_project in .sync.yml or calculate it from the source in metadata.json" if returnVal.nil?
-
-  puts "GitHubChangelogGenerator project:#{returnVal}"
-  returnVal
-end
-
-def changelog_future_release
-  return unless Rake.application.top_level_tasks.include? "changelog"
-  returnVal = "v%s" % JSON.load(File.read('metadata.json'))['version']
-  raise "unable to find the future_release (version) in metadata.json" if returnVal.nil?
-  puts "GitHubChangelogGenerator future_release:#{returnVal}"
-  returnVal
-end
+require 'puppet-strings/tasks' if Gem.loaded_specs.key? 'puppet-strings'
+require 'beaker-rspec/rake_task'
 
 PuppetLint.configuration.send('disable_relative')
-
-
-if Bundler.rubygems.find_name('github_changelog_generator').any?
-  GitHubChangelogGenerator::RakeTask.new :changelog do |config|
-    raise "Set CHANGELOG_GITHUB_TOKEN environment variable eg 'export CHANGELOG_GITHUB_TOKEN=valid_token_here'" if Rake.application.top_level_tasks.include? "changelog" and ENV['CHANGELOG_GITHUB_TOKEN'].nil?
-    config.user = "#{changelog_user}"
-    config.project = "#{changelog_project}"
-    config.future_release = "#{changelog_future_release}"
-    config.exclude_labels = ['maintenance']
-    config.header = "# Change log\n\nAll notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org)."
-    config.add_pr_wo_labels = true
-    config.issues = false
-    config.merge_prefix = "### UNCATEGORIZED PRS; LABEL THEM ON GITHUB"
-    config.configure_sections = {
-      "Changed" => {
-        "prefix" => "### Changed",
-        "labels" => ["backwards-incompatible"],
-      },
-      "Added" => {
-        "prefix" => "### Added",
-        "labels" => ["enhancement", "feature"],
-      },
-      "Fixed" => {
-        "prefix" => "### Fixed",
-        "labels" => ["bug", "documentation", "bugfix"],
-      },
-    }
-  end
-else
-  desc 'Generate a Changelog from GitHub'
-  task :changelog do
-    raise <<EOM
-The changelog tasks depends on recent features of the github_changelog_generator gem.
-Please manually add it to your .sync.yml for now, and run `pdk update`:
----
-Gemfile:
-  optional:
-    ':development':
-      - gem: 'github_changelog_generator'
-        version: '~> 1.15'
-        condition: "Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.3.0')"
-EOM
-  end
-end
-
diff --git a/metadata.json b/metadata.json
index feb32b9049224a459c225d9ba33017208b03cacc..e7e2982be96db7b1e0242023710394332c9ecf5b 100644
--- a/metadata.json
+++ b/metadata.json
@@ -44,7 +44,7 @@
     "pki",
     "cfssl"
   ],
-  "pdk-version": "2.5.0",
-  "template-url": "https://github.com/puppetlabs/pdk-templates#2.5.0",
-  "template-ref": "tags/2.5.0-0-g369d483"
+  "pdk-version": "3.2.0",
+  "template-url": "https://github.com/puppetlabs/pdk-templates#3.2.0",
+  "template-ref": "tags/3.2.0-0-gb257ef1"
 }
diff --git a/spec/acceptance/cfssl_spec.rb b/spec/acceptance/cfssl_spec.rb
index f2d13961426be6a47b1d8e96f3f4682c739a4824..981a578c37e9d10dc9ddd3d6c1e5c188a3eeeb4b 100644
--- a/spec/acceptance/cfssl_spec.rb
+++ b/spec/acceptance/cfssl_spec.rb
@@ -16,12 +16,10 @@ describe 'cfssl' do
     end
 
     describe command('openssl x509 -in /etc/cfssl/ca/EXEMPLEROOTCA.pem -text -noout') do
-      # rubocop:disable RSpec/RepeatedDescription
       its(:stdout) { is_expected.to match %r{Certificate:} }
       its(:stdout) { is_expected.to match %r{Issuer: C = FR, L = MONTPELLIER, O = EXEMPLE ORG, CN = EXEMPLE ROOT CA} }
       its(:stdout) { is_expected.to match %r{Subject: C = FR, L = MONTPELLIER, O = EXEMPLE ORG, CN = EXEMPLE ROOT CA} }
       its(:stdout) { is_expected.to match %r{CA:TRUE} }
-      # rubocop:enable RSpec/RepeatedDescription
     end
   end
 
@@ -38,12 +36,10 @@ describe 'cfssl' do
     end
 
     describe command('openssl x509 -in /etc/cfssl/ca/EXEMPLEROOTCA.pem -text -noout') do
-      # rubocop:disable RSpec/RepeatedDescription
       its(:stdout) { is_expected.to match %r{Certificate:} }
       its(:stdout) { is_expected.to match %r{Issuer: C = FR, L = MONTPELLIER, O = EXEMPLE ORG, CN = EXEMPLE ROOT CA} }
       its(:stdout) { is_expected.to match %r{Subject: C = FR, L = MONTPELLIER, O = EXEMPLE ORG, CN = EXEMPLE ROOT CA} }
       its(:stdout) { is_expected.to match %r{CA:TRUE} }
-      # rubocop:enable RSpec/RepeatedDescription
     end
   end
 
@@ -79,7 +75,6 @@ describe 'cfssl' do
     end
 
     describe command('openssl x509 -in /etc/cfssl/ca/MYEXEMPLEROOTCA.pem -text -noout') do
-      # rubocop:disable RSpec/RepeatedDescription
       its(:stdout) { is_expected.to match %r{Certificate:} }
       its(:stdout) { is_expected.to match %r{Issuer: C = FR, L = MONTPELLIER, O = MYEXEMPLE ORG, CN = MYEXEMPLE ROOT CA} }
       its(:stdout) { is_expected.to match %r{Subject: C = FR, L = MONTPELLIER, O = MYEXEMPLE ORG, CN = MYEXEMPLE ROOT CA} }
@@ -90,7 +85,6 @@ describe 'cfssl' do
       its(:stdout) { is_expected.to match %r{Certificate Revocation List } }
       its(:stdout) { is_expected.to match %r{Issuer: C = FR, L = MONTPELLIER, O = MYEXEMPLE ORG, CN = MYEXEMPLE ROOT CA} }
       its(:stdout) { is_expected.to match %r{No Revoked Certificates} }
-      # rubocop:enable RSpec/RepeatedDescription
     end
   end
 
@@ -142,7 +136,6 @@ describe 'cfssl' do
       its(:stdout) { is_expected.to match %r{BEGIN CERTIFICATE} }
     end
 
-    # rubocop:disable RSpec/RepeatedDescription
     describe command('openssl x509 -in /etc/cfssl/ca/MYEXEMPLEINTERMDIATECA.pem -text -noout') do
       its(:stdout) { is_expected.to match %r{Certificate:} }
       its(:stdout) { is_expected.to match %r{Issuer: C = FR, L = MONTPELLIER, O = MYEXEMPLE ORG, CN = MYEXEMPLE ROOT CA} }
@@ -168,6 +161,5 @@ describe 'cfssl' do
       its(:stdout) { is_expected.to match %r{Issuer: C = FR, L = MONTPELLIER, O = MYEXEMPLE ORG, CN = MYEXEMPLE INTERMDIATE CA} }
       its(:stdout) { is_expected.to match %r{No Revoked Certificates} }
     end
-    # rubocop:enable RSpec/RepeatedDescription
   end
 end
diff --git a/spec/default_facts.yml b/spec/default_facts.yml
index f777abfc9905202e7ccf5b5fcc76b9b4c59a39fb..3346c394df5a06fba389c76f1e2ccbb04c77ee6c 100644
--- a/spec/default_facts.yml
+++ b/spec/default_facts.yml
@@ -2,7 +2,8 @@
 #
 # Facts specified here will override the values provided by rspec-puppet-facts.
 ---
-ipaddress: "172.16.254.254"
-ipaddress6: "FE80:0000:0000:0000:AAAA:AAAA:AAAA"
+networking:
+  ip: "172.16.254.254"
+  ip6: "FE80:0000:0000:0000:AAAA:AAAA:AAAA"
+  mac: "AA:AA:AA:AA:AA:AA"
 is_pe: false
-macaddress: "AA:AA:AA:AA:AA:AA"
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 9b1fa6f264d1019af8007726d2df751a5716ffce..ae7c1f6818a0b8febab42ad06aa40c0b13c7acf2 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -25,15 +25,16 @@ default_fact_files.each do |f|
   next unless File.exist?(f) && File.readable?(f) && File.size?(f)
 
   begin
-    default_facts.merge!(YAML.safe_load(File.read(f), [], [], true))
-  rescue => e
+    require 'deep_merge'
+    default_facts.deep_merge!(YAML.safe_load(File.read(f), permitted_classes: [], permitted_symbols: [], aliases: true))
+  rescue StandardError => e
     RSpec.configuration.reporter.message "WARNING: Unable to load #{f}: #{e}"
   end
 end
 
 # read default_facts and merge them over what is provided by facterdb
 default_facts.each do |fact, value|
-  add_custom_fact fact, value
+  add_custom_fact fact, value, merge_facts: true
 end
 
 RSpec.configure do |c|
@@ -46,6 +47,7 @@ RSpec.configure do |c|
   end
   c.filter_run_excluding(bolt: true) unless ENV['GEM_BOLT']
   c.after(:suite) do
+    RSpec::Puppet::Coverage.report!(0)
   end
 
   # Filter backtrace noise