diff --git a/REFERENCE.md b/REFERENCE.md
index d53700d9..dbf6342e 100644
--- a/REFERENCE.md
+++ b/REFERENCE.md
@@ -102,6 +102,7 @@ The following parameters are available in the `systemd` class:
* [`use_stub_resolver`](#-systemd--use_stub_resolver)
* [`manage_networkd`](#-systemd--manage_networkd)
* [`networkd_ensure`](#-systemd--networkd_ensure)
+* [`networkd_package`](#-systemd--networkd_package)
* [`manage_timesyncd`](#-systemd--manage_timesyncd)
* [`timesyncd_ensure`](#-systemd--timesyncd_ensure)
* [`timesyncd_package`](#-systemd--timesyncd_package)
@@ -330,6 +331,14 @@ The state that the ``networkd`` service should be in
Default value: `'running'`
+##### `networkd_package`
+
+Data type: `Optional[String[1]]`
+
+Name of the package required for systemd-networkd, if any
+
+Default value: `undef`
+
##### `manage_timesyncd`
Data type: `Boolean`
diff --git a/data/RedHat-7.yaml b/data/RedHat-family-7.yaml
similarity index 100%
rename from data/RedHat-7.yaml
rename to data/RedHat-family-7.yaml
diff --git a/data/RedHat-8.yaml b/data/RedHat-family-8.yaml
similarity index 100%
rename from data/RedHat-8.yaml
rename to data/RedHat-family-8.yaml
diff --git a/data/RedHat-9.yaml b/data/RedHat-family-9.yaml
similarity index 100%
rename from data/RedHat-9.yaml
rename to data/RedHat-family-9.yaml
diff --git a/data/RedHat-family.yaml b/data/RedHat-family.yaml
new file mode 100644
index 00000000..be4865fa
--- /dev/null
+++ b/data/RedHat-family.yaml
@@ -0,0 +1,2 @@
+---
+systemd::networkd_package: systemd-networkd
diff --git a/hiera.yaml b/hiera.yaml
index 218dcc6b..82e59168 100644
--- a/hiera.yaml
+++ b/hiera.yaml
@@ -9,6 +9,8 @@ hierarchy:
- name: 'Distribution Name'
path: '%{facts.os.name}.yaml'
- name: 'OS Family Major Version'
- path: '%{facts.os.family}-%{facts.os.release.major}.yaml'
+ path: '%{facts.os.family}-family-%{facts.os.release.major}.yaml'
+ - name: 'OS Family'
+ path: '%{facts.os.family}-family.yaml'
- name: 'common'
path: 'common.yaml'
diff --git a/manifests/init.pp b/manifests/init.pp
index e6bf30a6..5c77850a 100644
--- a/manifests/init.pp
+++ b/manifests/init.pp
@@ -83,6 +83,9 @@
# @param networkd_ensure
# The state that the ``networkd`` service should be in
#
+# @param networkd_package
+# Name of the package required for systemd-networkd, if any
+#
# @param manage_timesyncd
# Manage the systemd timesyncd daemon
#
@@ -205,6 +208,7 @@
Boolean $use_stub_resolver = false,
Boolean $manage_networkd = false,
Enum['stopped','running'] $networkd_ensure = 'running',
+ Optional[String[1]] $networkd_package = undef,
Boolean $manage_timesyncd = false,
Enum['stopped','running'] $timesyncd_ensure = 'running',
Optional[String[1]] $timesyncd_package = undef,
@@ -285,6 +289,7 @@
if $manage_networkd and $facts['systemd_internal_services'] and $facts['systemd_internal_services']['systemd-networkd.service'] {
contain systemd::networkd
+ Class['systemd::install'] -> Class['systemd::networkd']
}
if $manage_timesyncd and $facts['systemd_internal_services'] and $facts['systemd_internal_services']['systemd-timesyncd.service'] {
diff --git a/manifests/install.pp b/manifests/install.pp
index 7227cb4e..efbd0c83 100644
--- a/manifests/install.pp
+++ b/manifests/install.pp
@@ -2,6 +2,12 @@
# @api private
#
class systemd::install {
+ if $systemd::manage_networkd and $systemd::networkd_package {
+ package { $systemd::networkd_package:
+ ensure => present,
+ }
+ }
+
if $systemd::manage_resolved and $systemd::resolved_package {
package { $systemd::resolved_package:
ensure => present,
diff --git a/spec/acceptance/networkd_spec.rb b/spec/acceptance/networkd_spec.rb
new file mode 100644
index 00000000..75546b50
--- /dev/null
+++ b/spec/acceptance/networkd_spec.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+require 'spec_helper_acceptance'
+
+describe 'systemd with manage_networkd true' do
+ has_package = fact('os.family') == 'RedHat'
+
+ # On Enterprise Linux 8 & 9 the package is shipped in EPEL
+ before { install_package(default, 'epel-release') if has_package && %w[8 9].include?(fact('os.release.major')) }
+
+ context 'configure systemd-networkd' do
+ let(:manifest) do
+ <<~PUPPET
+ class { 'systemd':
+ manage_networkd => true,
+ }
+ PUPPET
+ end
+
+ it 'works idempotently with no errors' do
+ apply_manifest(manifest, catch_failures: true)
+ # Package systemd-networkd needs to be installed before fact $facts['internal_services'] is set
+ apply_manifest(manifest, catch_failures: true) if has_package
+ apply_manifest(manifest, catch_changes: true)
+ end
+
+ describe service('systemd-networkd') do
+ it { is_expected.to be_running }
+ it { is_expected.to be_enabled }
+ end
+
+ it { expect(package('systemd-networkd')).to be_installed } if has_package
+ end
+
+ context 'configure systemd stopped' do
+ let(:manifest) do
+ <<~PUPPET
+ class { 'systemd':
+ manage_networkd => true,
+ networkd_ensure => 'stopped',
+ }
+ PUPPET
+ end
+
+ it 'works idempotently with no errors' do
+ apply_manifest(manifest, catch_failures: true)
+ apply_manifest(manifest, catch_changes: true)
+ end
+
+ describe service('systemd-networkd') do
+ it { is_expected.not_to be_running }
+ it { is_expected.not_to be_enabled }
+ end
+ end
+end
diff --git a/spec/classes/init_spec.rb b/spec/classes/init_spec.rb
index 0c847003..4344ffa2 100644
--- a/spec/classes/init_spec.rb
+++ b/spec/classes/init_spec.rb
@@ -17,6 +17,7 @@
it { is_expected.not_to create_service('systemd-resolved') }
it { is_expected.not_to create_service('systemd-networkd') }
it { is_expected.not_to create_service('systemd-timesyncd') }
+ it { is_expected.not_to contain_package('systemd-networkd') }
it { is_expected.not_to contain_package('systemd-timesyncd') }
it { is_expected.not_to contain_package('systemd-resolved') }
it { is_expected.not_to contain_class('systemd::coredump') }
@@ -39,6 +40,12 @@
it { is_expected.to create_service('systemd-networkd').with_enable(true) }
it { is_expected.not_to contain_file('/etc/systemd/network') }
+ if facts[:os]['family'] == 'RedHat'
+ it { is_expected.to contain_package('systemd-networkd') }
+ else
+ it { is_expected.not_to contain_package('systemd-networkd') }
+ end
+
case [facts[:os]['family'], facts[:os]['release']['major']]
when %w[RedHat 7], %w[RedHat 9]
it { is_expected.to contain_package('systemd-resolved') }