diff --git a/cdist/conf/type/__bridge/files/backends/ifcfg/manifest b/cdist/conf/type/__bridge/files/backends/ifcfg/manifest
new file mode 100755
index 00000000..6f863c14
--- /dev/null
+++ b/cdist/conf/type/__bridge/files/backends/ifcfg/manifest
@@ -0,0 +1,108 @@
+#!/bin/sh -e
+# -*- mode: sh; indent-tabs-mode: t -*-
+#
+# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see .
+#
+
+os=$(cat "${__global:?}/explorer/os")
+
+case $os
+in
+ (centos|redhat|scientific)
+ systype=redhat
+ ;;
+ (suse)
+ systype=suse
+ set -- "$@" --extra-config BRIDGE=yes
+ ;;
+ (*)
+ printf "Your operating system (%s) is currently not supported by %s's ifcfg backend.\n" "${os}" "${__type##*/}" >&2
+ printf "Please contribute an implementation for it if you can.\n" >&2
+ exit 1
+ ;;
+esac
+
+bridge_ports= # space-separated list
+bridge_stp='off'
+
+cd "${__object:?}/parameter"
+for param in *
+do
+ case ${param}
+ in
+ (bootproto)
+ bootproto=$(cat "${__object:?}/parameter/bootproto")
+ set -- "$@" --bootproto "${bootproto}"
+ ;;
+ (hotplug)
+ echo '--hotplug is not (yet) supported by the ifcfg backend.' >&2
+ exit 1
+ ;;
+ (port)
+ case ${systype}
+ in
+ (redhat)
+ # TOOD
+ ;;
+ (suse)
+ bridge_ports=$(
+ while read -r _port
+ do
+ test -z "$(echo "${_port}" | tr -d 'A-Za-z0-9')" || {
+ printf 'Invalid bridge port name: %s\n' "${_port}" >&2
+ exit 1
+ }
+ printf ' %s' "${_port}"
+ done <"${__object:?}/parameter/port"
+ )
+ bridge_ports=${bridge_ports# }
+ ;;
+ esac
+ ;;
+ (stp)
+ bridge_stp='on'
+ ;;
+ (onboot)
+ # boolean parameters
+ set -- "$@" --"${param}"
+ ;;
+ (*)
+ set -- "$@" --"${param}" "$(cat "${__object:?}/parameter/${param}")"
+ ;;
+ esac
+done
+
+# Set bridge ports
+set -- "$@" --extra-config "BRIDGE_PORTS='${bridge_ports}'"
+
+# Set boolean options
+case $systype
+in
+ (redhat)
+ set -- "$@" --extra-config "STP=${bridge_stp}"
+ test "${bridge_stp}" = 'on' || set -- "$@" --extra-config DELAY=0
+ ;;
+ (suse)
+ set -- "$@" --extra-config "BRIDGE_STP=${bridge_stp}"
+ test "${bridge_stp}" = 'on' \
+ || set -- "$@" --extra-config BRIDGE_FORWARDDELAY=0
+ ;;
+esac
+
+# Instantiate backend type
+__interface_ifcfg "${__object_id:?}" --type Bridge "$@"
diff --git a/cdist/conf/type/__bridge/files/backends/ifupdown.d/manifest b/cdist/conf/type/__bridge/files/backends/ifupdown.d/manifest
new file mode 100755
index 00000000..f29b883a
--- /dev/null
+++ b/cdist/conf/type/__bridge/files/backends/ifupdown.d/manifest
@@ -0,0 +1,98 @@
+#!/bin/sh -e
+# -*- mode: sh; indent-tabs-mode: t -*-
+#
+# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see .
+#
+
+__package_apt bridge-utils
+export require=__package_apt/bridge-utils
+
+bridge_ports='none' # space-separated list
+bridge_stp='off'
+enable_hotplug=no
+
+cd "${__object:?}/parameter"
+for param in *
+do
+ case ${param}
+ in
+ (bootproto)
+ bootproto=$(cat "${__object:?}/parameter/bootproto")
+ set -- "$@" --bootproto "${bootproto}"
+
+ case ${bootproto}
+ in
+ (manual)
+ # if set to manual, there is nothing to wait for…
+ set -- "$@" --extra-config 'bridge_maxwait 0'
+ ;;
+ esac
+ ;;
+ (hotplug)
+ # N.B.: This option must be equal for all configured bridges,
+ # or cdist will error.
+ # This is a limitation of the bridge-utils package.
+ enable_hotplug=yes
+ ;;
+ (port)
+ bridge_ports=$(
+ while read -r _port
+ do
+ test -z "$(echo "${_port}" | tr -d 'A-Za-z0-9')" || {
+ printf 'Invalid bridge port name: %s\n' "${_port}" >&2
+ exit 1
+ }
+
+ printf ' %s' "${_port}"
+ done <"${__object:?}/parameter/port"
+ )
+ bridge_ports=${bridge_ports# }
+ ;;
+ (stp)
+ bridge_stp='on'
+ ;;
+ (onboot)
+ # boolean parameters
+ set -- "$@" --"${param}"
+ ;;
+ (*)
+ set -- "$@" --"${param}" "$(cat "${__object:?}/parameter/${param}")"
+ ;;
+ esac
+done
+
+
+# Set bridge ports
+set -- "$@" --extra-config "bridge_ports ${bridge_ports}"
+
+# Set boolean options
+set -- "$@" --extra-config "bridge_stp ${bridge_stp}"
+test "${bridge_stp}" = 'on' || set -- "$@" --extra-config 'bridge_fd 0'
+
+__key_value /etc/default/bridge-utils:BRIDGE_HOTPLUG --state present \
+ --file /etc/default/bridge-utils --key BRIDGE_HOTPLUG \
+ --delimiter = --exact_delimiter \
+ --value "${enable_hotplug}"
+
+
+# Instantiate backend type
+if test -s "${__object:?}/stdin"
+then
+ exec <"${__object:?}/stdin"
+fi
+__interface "${__object_id:?}" --type ifupdown.d "$@"
diff --git a/cdist/conf/type/__bridge/gencode-remote b/cdist/conf/type/__bridge/gencode-remote
new file mode 100755
index 00000000..77ad9d25
--- /dev/null
+++ b/cdist/conf/type/__bridge/gencode-remote
@@ -0,0 +1,20 @@
+#!/bin/sh -e
+#
+# 2020 Dennis Camera (dennis.camera@ssrq-sds-fds.ch)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see .
+#
+
diff --git a/cdist/conf/type/__bridge/man.rst b/cdist/conf/type/__bridge/man.rst
new file mode 100644
index 00000000..bffe088b
--- /dev/null
+++ b/cdist/conf/type/__bridge/man.rst
@@ -0,0 +1,106 @@
+cdist-type__bridge(7)
+=====================
+
+NAME
+----
+cdist-type__bridge - Manage network bridges
+
+
+DESCRIPTION
+-----------
+This cdist type allows you to manage virtual Ethernet bridges on the target.
+It acts as a wrapper around cdist-type__interface(7) to provide more convenient
+access to bridge-specific parameters.
+Only TCP/IP is supported. For other protocol stacks, use the specific types for
+your OS.
+
+
+REQUIRED PARAMETERS
+-------------------
+port
+ A port (interface) to be part of the bridge.
+ This parameter can be used multiple times, to add more than one port to the
+ bridge.
+ The ports should not be defined as __interfaces.
+
+
+OPTIONAL PARAMETERS
+-------------------
+address
+ The IP address (in CIDR notation) to assign to the network interface.
+ Can be repeated to assign multiple IP addresses.
+bootproto
+ The boot protocol to use.
+
+ Acceptable values are ``dhcp``, ``static``, ``manual``.
+ Defaults to ``manual``.
+comment
+ A comment to be stored in the configuration file.
+extra-config
+ Other options to be passed to the implementation type verbatim.
+ Using this option makes the configuration non-portable to other backends.
+ If this option is used extensively, it is recommended to use the respective
+ backend type directly.
+gateway
+ The default gateway to assign to this interface (optional).
+name
+ The name of the logical network device to configure.
+ Defaults to ``__object_id``.
+onchange
+ The action to perform if the interface configuration has changed.
+
+ Available options are:
+
+ leave (default)
+ Do nothing.
+ up
+ Bring the interface up if it is down.
+ down
+ Bring the interface down if it is up.
+ refresh
+ Refresh the interface (down && up).
+state
+ ``present`` or ``absent``, defaults to ``present``.
+type
+ The backend to use to store the interface configuration.
+ Default is to auto detect.
+
+
+BOOLEAN PARAMETERS
+------------------
+onboot
+ Bring the interface up on boot.
+ Otherwise, it has to be manually brought up using OS utilities
+ (e.g. ifup\ (8)).
+hotplug
+ | Allow hotplugging the ports on this bridge.
+ | N.B.: Some backends might not support this.
+stp
+ Enable the Spanning Tree Protocol (STP) on this bridge.
+
+
+EXAMPLES
+--------
+
+.. code-block:: sh
+
+ # Create a bridge br0 comprised of eth0 and eth1 that is brought up on boot.
+ __bridge br0 --onboot --port eth0 --port eth1
+
+
+SEE ALSO
+--------
+:strong:`cdist-type__interface`\ (7)
+
+
+AUTHORS
+-------
+Dennis Camera
+
+
+COPYING
+-------
+Copyright \(C) 2020 Dennis Camera. You can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
diff --git a/cdist/conf/type/__bridge/manifest b/cdist/conf/type/__bridge/manifest
new file mode 100755
index 00000000..755a09bc
--- /dev/null
+++ b/cdist/conf/type/__bridge/manifest
@@ -0,0 +1,54 @@
+#!/bin/sh -e
+#
+# 2020 Dennis Camera (dennis.camera@ssrq-sds-fds.ch)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see .
+#
+
+
+os=$(cat "${__global:?}/explorer/os")
+
+case $os
+in
+ (debian)
+ os_major=$(grep -o '^[0-9][0-9]*' "${__global:?}/explorer/os_version")
+ test "${os_major}" -ge 7 \
+ || die 'Debian versions older than 7 (wheezy) are not supported'
+
+ impl_type=ifupdown.d
+ ;;
+ (devuan)
+ impl_type=ifupdown.d
+ ;;
+ (centos|redhat|scientific|suse)
+ impl_type=ifcfg
+ ;;
+ (*)
+ printf "Your operating system (%s) is currently not supported by this type (%s)\n" "${os}" "${__type##*/}" >&2
+ printf "Please contribute an implementation for it if you can.\n" >&2
+ exit 1
+ ;;
+esac
+
+# Hand over to backend-specific implementation
+manifest_file="${__type:?}/files/backends/${impl_type}/manifest"
+test -x "${manifest_file}" || {
+ printf 'Unknown type: %s\n' "${impl_type}" >&2
+ exit 1
+}
+
+# Run backend-specific script
+exec "${manifest_file}"
diff --git a/cdist/conf/type/__bridge/parameter/boolean b/cdist/conf/type/__bridge/parameter/boolean
new file mode 100644
index 00000000..0d323712
--- /dev/null
+++ b/cdist/conf/type/__bridge/parameter/boolean
@@ -0,0 +1,3 @@
+hotplug
+onboot
+stp
diff --git a/cdist/conf/type/__bridge/parameter/default/bootproto b/cdist/conf/type/__bridge/parameter/default/bootproto
new file mode 100644
index 00000000..2905494b
--- /dev/null
+++ b/cdist/conf/type/__bridge/parameter/default/bootproto
@@ -0,0 +1 @@
+manual
diff --git a/cdist/conf/type/__bridge/parameter/default/onchange b/cdist/conf/type/__bridge/parameter/default/onchange
new file mode 100644
index 00000000..e8f9c907
--- /dev/null
+++ b/cdist/conf/type/__bridge/parameter/default/onchange
@@ -0,0 +1 @@
+leave
diff --git a/cdist/conf/type/__bridge/parameter/default/state b/cdist/conf/type/__bridge/parameter/default/state
new file mode 100644
index 00000000..e7f6134f
--- /dev/null
+++ b/cdist/conf/type/__bridge/parameter/default/state
@@ -0,0 +1 @@
+present
diff --git a/cdist/conf/type/__bridge/parameter/optional b/cdist/conf/type/__bridge/parameter/optional
new file mode 100644
index 00000000..16ae6fba
--- /dev/null
+++ b/cdist/conf/type/__bridge/parameter/optional
@@ -0,0 +1,7 @@
+bootproto
+comment
+gateway
+name
+onchange
+state
+type
diff --git a/cdist/conf/type/__bridge/parameter/optional_multiple b/cdist/conf/type/__bridge/parameter/optional_multiple
new file mode 100644
index 00000000..d54585d1
--- /dev/null
+++ b/cdist/conf/type/__bridge/parameter/optional_multiple
@@ -0,0 +1,3 @@
+address
+extra-config
+port
diff --git a/cdist/conf/type/__interface/explorer/has_networkctl b/cdist/conf/type/__interface/explorer/has_networkctl
new file mode 100755
index 00000000..dd247ae8
--- /dev/null
+++ b/cdist/conf/type/__interface/explorer/has_networkctl
@@ -0,0 +1,24 @@
+#!/bin/sh -e
+#
+# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see .
+#
+#
+# Check whether system has networkctl.
+#
+
+command -v networkctl 2>/dev/null || true
diff --git a/cdist/conf/type/__interface/files/backends/ifcfg/manifest b/cdist/conf/type/__interface/files/backends/ifcfg/manifest
new file mode 100755
index 00000000..a4b6dbdf
--- /dev/null
+++ b/cdist/conf/type/__interface/files/backends/ifcfg/manifest
@@ -0,0 +1,105 @@
+#!/bin/sh -e
+# -*- mode: sh; indent-tabs-mode: t -*-
+#
+# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see .
+#
+
+opt_format() {
+ printf '%s="%s"\n' "${1:?'option name missing'}" "${2:?'option value missing'}"
+}
+
+opt_from_param() {
+ # Only first line will be read.
+ opt_format \
+ "${1:?'option name missing'}" \
+ "$(head -n 1 "${__object:?}/parameter/${2:?'parameter name missing'}")"
+}
+
+
+set -- --state "$(cat "${__object:?}/parameter/state")" --family inet
+
+# Boolean flags
+if test -f "${__object:?}/parameter/onboot"
+then
+ set -- "$@" --onboot
+fi
+if test -f "${__object:?}/parameter/hotplug"
+then
+ set -- "$@" --hotplug
+fi
+
+
+if test -f "${__object:?}/parameter/name"
+then
+ set -- "$@" --name "$(cat "${__object:?}/parameter/name")"
+fi
+
+
+# Generate appropriate parameters based on bootproto
+bootproto=$(cat "${__object:?}/parameter/bootproto")
+case $bootproto
+in
+ (dhcp)
+ set -- "$@" --bootproto dhcp
+ ;;
+ (static)
+ set -- "$@" --bootproto static
+
+ if test -s "${__object:?}/parameter/address"
+ then
+ while read -r _addr
+ do
+ set -- "$@" --address "${_addr}"
+ done <"${__object:?}/parameter/address"
+ unset _addr
+ fi
+
+ if test -s "${__object:?}/parameter/gateway"
+ then
+ set -- "$@" --option "$(opt_from_param GATEWAY gateway)"
+ fi
+ ;;
+ (manual)
+ set -- "$@" --bootproto none
+ ;;
+ (*)
+ exit 1
+ ;;
+esac
+
+if test -s "${__object:?}/parameter/comment"
+then
+ set -- "$@" --comment "$(cat "${__object:?}/parameter/comment")"
+fi
+
+if test -s "${__object:?}/parameter/onchange"
+then
+ set -- "$@" --onchange "$(cat "${__object:?}/parameter/onchange")"
+fi
+
+if test -s "${__object:?}/parameter/extra-config"
+then
+ while read -r _opt
+ do
+ set -- "$@" --option "${_opt}"
+ done <"${__object:?}/parameter/extra-config"
+ unset _opt
+fi
+
+# Instantiate backend type
+__interface_ifcfg "${__object_id:?}" "$@"
diff --git a/cdist/conf/type/__interface/files/backends/ifupdown.d/manifest b/cdist/conf/type/__interface/files/backends/ifupdown.d/manifest
new file mode 100755
index 00000000..bbdca8bb
--- /dev/null
+++ b/cdist/conf/type/__interface/files/backends/ifupdown.d/manifest
@@ -0,0 +1,109 @@
+#!/bin/sh -e
+# -*- mode: sh; indent-tabs-mode: t -*-
+#
+# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see .
+#
+
+opt_format() {
+ printf '%s %s\n' "${1:?'option name missing'}" "${2:?'option value missing'}"
+}
+
+opt_from_param() {
+ # Only first line will be read.
+ opt_format \
+ "${1:?'option name missing'}" \
+ "$(head -n 1 "${__object:?}/parameter/${2:?'parameter name missing'}")"
+}
+
+
+set -- --state "$(cat "${__object:?}/parameter/state")" --family inet
+
+# Boolean flags
+if test -f "${__object:?}/parameter/onboot"
+then
+ set -- "$@" --auto
+fi
+if test -f "${__object:?}/parameter/hotplug"
+then
+ set -- "$@" --hotplug
+fi
+
+
+if test -f "${__object:?}/parameter/name"
+then
+ set -- "$@" --name "$(cat "${__object:?}/parameter/name")"
+fi
+
+
+# Generate appropriate parameters based on bootproto
+bootproto=$(cat "${__object:?}/parameter/bootproto")
+case $bootproto
+in
+ (dhcp)
+ set -- "$@" --method dhcp
+ ;;
+ (static)
+ set -- "$@" --method static
+
+ if test -s "${__object:?}/parameter/address"
+ then
+ while read -r _value
+ do
+ set -- "$@" --option "$(opt_format address "${_value}")"
+ done <"${__object:?}/parameter/address"
+ unset _value
+ fi
+
+ if test -s "${__object:?}/parameter/gateway"
+ then
+ set -- "$@" --option "$(opt_from_param gateway gateway)"
+ fi
+ ;;
+ (manual)
+ set -- "$@" --method manual
+ ;;
+ (*)
+ exit 1
+ ;;
+esac
+
+if test -s "${__object:?}/parameter/comment"
+then
+ set -- "$@" --comment "$(cat "${__object:?}/parameter/comment")"
+fi
+
+if test -s "${__object:?}/parameter/onchange"
+then
+ set -- "$@" --onchange "$(cat "${__object:?}/parameter/onchange")"
+fi
+
+if test -s "${__object:?}/parameter/extra-config"
+then
+ while read -r _opt
+ do
+ set -- "$@" --option "${_opt}"
+ done <"${__object:?}/parameter/extra-config"
+ unset _opt
+fi
+
+# Instantiate backend type
+if test -s "${__object:?}/stdin"
+then
+ exec <"${__object:?}/stdin"
+fi
+__interface_ifupdown.d "${__object_id:?}" "$@"
diff --git a/cdist/conf/type/__interface/files/backends/systemd/manifest b/cdist/conf/type/__interface/files/backends/systemd/manifest
new file mode 100755
index 00000000..2e86ee4e
--- /dev/null
+++ b/cdist/conf/type/__interface/files/backends/systemd/manifest
@@ -0,0 +1,117 @@
+#!/bin/sh -e
+# -*- mode: sh; indent-tabs-mode: t -*-
+#
+# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see .
+#
+
+opt_format() {
+ printf '%s=%s\n' "${1:?'option name missing'}" "${2:?'option value missing'}"
+}
+
+opt_from_param() {
+ # Only first line will be read.
+ opt_format \
+ "${1:?'option name missing'}" \
+ "$(head -n 1 "${__object:?}/parameter/${2:?'parameter name missing'}")"
+}
+
+
+set -- --state "$(cat "${__object:?}/parameter/state")"
+
+# Boolean flags
+test -f "${__object:?}/parameter/onboot" || {
+ echo "WARNING: ${__type##*/}: The systemd backend only supports --onboot." >&2
+}
+test -f "${__object:?}/parameter/hotplug" || {
+ echo "WARNING: ${__type##*/}: The systemd backend only supports --hotplug." >&2
+}
+
+
+if test -f "${__object:?}/parameter/name"
+then
+ set -- "$@" --name "$(cat "${__object:?}/parameter/name")"
+fi
+
+
+# Generate appropriate parameters based on bootproto
+bootproto=$(cat "${__object:?}/parameter/bootproto")
+case $bootproto
+in
+ (dhcp*)
+ if test "${bootproto}" = dhcp
+ then
+ set -- "$@" --option "$(opt_format Network.DHCP yes)"
+ # TODO: Implement IPv6 support
+ # else
+ # set -- "$@" --option "$(opt_format Network.DHCP "${bootproto}")"
+ fi
+ ;;
+ (static)
+ set -- "$@" --option 'Network.DHCP=false'
+
+ if test -s "${__object:?}/parameter/address"
+ then
+ while read -r _value
+ do
+ set -- "$@" --option "$(opt_format Network.Address "${_value}")"
+ done <"${__object:?}/parameter/address"
+ unset _value
+ fi
+
+ if test -s "${__object:?}/parameter/gateway"
+ then
+ set -- "$@" --option "$(opt_from_param Network.Gateway gateway)"
+ fi
+ ;;
+ (manual)
+ set -- "$@" --option 'Network.DHCP=false'
+ ;;
+ (*)
+ exit 1
+ ;;
+esac
+
+if test -s "${__object:?}/parameter/comment"
+then
+ set -- "$@" --option "$(opt_from_param Network.Description comment)"
+fi
+
+case $(cat "${__object:?}/parameter/onchange")
+in
+ (leave)
+ ;;
+ (refresh)
+ set -- "$@" --auto-reload
+ ;;
+ (*)
+ echo 'The --onchange parameter for type systemd only accepts "leave" or "refresh".' >&2
+ echo 'systemd-networkd automatically reconfigures all interfaces.' >&2
+ exit 1
+esac
+
+if test -s "${__object:?}/parameter/extra-config"
+then
+ while read -r _opt
+ do
+ set -- "$@" --option "${_opt}"
+ done <"${__object:?}/parameter/extra-config"
+ unset _opt
+fi
+
+# Instantiate backend type
+__systemd_networkd_network "${__object_id:?}" "$@"
diff --git a/cdist/conf/type/__interface/files/backends/uci/manifest b/cdist/conf/type/__interface/files/backends/uci/manifest
new file mode 100755
index 00000000..21c1bd7e
--- /dev/null
+++ b/cdist/conf/type/__interface/files/backends/uci/manifest
@@ -0,0 +1,132 @@
+#!/bin/sh -e
+# -*- mode: sh; indent-tabs-mode: t -*-
+#
+# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see .
+#
+
+opt_format() {
+ printf "%s='%s'\\n" "${1:?'option name missing'}" "${2:?'option value missing'}"
+}
+
+opt_from_param() {
+ # Only first line will be read.
+ opt_format \
+ "${1:?'option name missing'}" \
+ "$(head -n 1 "${__object:?}/parameter/${2:?'parameter name missing'}")"
+}
+
+onchange_action=$(cat "${__object:?}/parameter/onchange")
+state=$(cat "${__object:?}/parameter/state")
+
+obj_name="network.${__object_id:?}"
+
+onchange_action() {
+ case $onchange_action
+ in
+ (refresh)
+ printf "ifup '%s'\n" "${__object_id:?}"
+ ;;
+ (up)
+ # shellcheck disable=SC2016
+ echo 'isifup()(up=0; . /usr/share/libubox/jshn.sh && json_load "$(ifstatus "$1")" && json_get_var up up; return $((!up)))'
+ printf "isifup '%s' || ifup '%s'\n" "${__object_id:?}" "${__object_id:?}"
+ ;;
+ (down)
+ printf "ifdown '%s'\n" "${__object_id:?}"
+ ;;
+ (leave)
+ # ignore
+ ;;
+ (*)
+ printf 'Invalid --onchange: %s\n' "${onchange_action}" >&2
+ exit 1
+ ;;
+ esac
+}
+
+
+set -- --state "${state}" --transaction "${obj_name}"
+
+if test -s "${__object:?}/parameter/comment"
+then
+ set -- "$@" --option "$(opt_from_param _comment comment)"
+fi
+
+if test -f "${__object:?}/parameter/name"
+then
+ set -- "$@" --option "$(opt_from_param ifname name)"
+else
+ set -- "$@" --option "$(opt_format ifname "${__object_id:?}")"
+fi
+
+set -- "$@" --option "$(opt_format auto "$(
+ ! test -f "${__object:?}/parameter/onboot"; echo $?)")"
+set -- "$@" --option "$(opt_format force_link "$(
+ test -f "${__object:?}/parameter/hotplug"; echo $?)")"
+
+# Generate appropriate parameters based on bootproto
+bootproto=$(cat "${__object:?}/parameter/bootproto")
+case $bootproto
+in
+ (dhcp)
+ set -- "$@" --option "$(opt_format proto dhcp)"
+ ;;
+ (static)
+ set -- "$@" --option "$(opt_format proto static)"
+
+ if test -s "${__object:?}/parameter/address"
+ then
+ while read -r _value
+ do
+ set -- "$@" --option "$(opt_format ipaddr "${_value}")"
+ done <"${__object:?}/parameter/address"
+ unset _value
+ fi
+
+ if test -s "${__object:?}/parameter/gateway"
+ then
+ set -- "$@" --option "$(opt_from_param gateway gateway)"
+ fi
+ ;;
+ (manual)
+ set -- "$@" --option "$(opt_format proto static)"
+ ;;
+ (*)
+ exit 1
+ ;;
+esac
+
+if test -s "${__object:?}/parameter/extra-config"
+then
+ while read -r _opt
+ do
+ set -- "$@" --option "${_opt}"
+ done <"${__object:?}/parameter/extra-config"
+ unset _opt
+fi
+
+# Instantiate backend type
+__uci_section "${obj_name}" --type network.interface "$@"
+
+if test -s "${__object:?}/parameter/onchange"
+then
+ require=__uci_commit/"${obj_name}" \
+ __check_messages "interface_${__object_id:?}_onchange" \
+ --pattern "^__uci_commit/network.${__object_id:?}:" \
+ --execute "$(onchange_action)"
+fi
diff --git a/cdist/conf/type/__interface/man.rst b/cdist/conf/type/__interface/man.rst
new file mode 100644
index 00000000..de71c438
--- /dev/null
+++ b/cdist/conf/type/__interface/man.rst
@@ -0,0 +1,90 @@
+cdist-type__interface(7)
+========================
+
+NAME
+----
+cdist-type__interface - Manage network interfaces
+
+
+DESCRIPTION
+-----------
+This cdist type allows you to manage network interfaces on the target.
+It dispatches the actual work to the interface management system specific types.
+Only TCP/IP is supported. For other protocol stacks, use the specific types for
+your OS.
+
+
+REQUIRED PARAMETERS
+-------------------
+None.
+
+
+OPTIONAL PARAMETERS
+-------------------
+address
+ The IP address (in CIDR notation) to assign to the network interface.
+ Can be repeated to assign multiple IP addresses.
+bootproto
+ The boot protocol to use.
+ Acceptable values are ``dhcp``, ``static``, ``manual``.
+ Defaults to ``dhcp``.
+comment
+ A comment to be stored in the configuration file.
+extra-config
+ Other options to be passed to the implementation type verbatim.
+ Using this option makes the configuration non-portable to other backends.
+ If this option is used extensively, it is recommended to use the respective
+ backend type directly.
+gateway
+ The default gateway to assign to this interface (optional).
+name
+ The name of the physical or logical network device to configure.
+ Defaults to ``__object_id``.
+onchange
+ The action to perform if the interface configuration has changed.
+
+ Available options are:
+
+ leave (default)
+ Do nothing.
+ up
+ Bring the interface up if it is down.
+ down
+ Bring the interface down if it is up.
+ refresh
+ Refresh the interface (down && up).
+state
+ ``present`` or ``absent``, defaults to ``present``.
+type
+ The backend to use to store the interface configuration.
+ Default is to auto detect.
+
+
+BOOLEAN PARAMETERS
+------------------
+onboot
+ Whether to bring the interface up on boot
+hotplug
+ Allow/disallow hotplug support for this interface
+
+
+EXAMPLES
+--------
+
+.. code-block:: sh
+
+ # TODO
+ __interface
+
+
+AUTHORS
+-------
+Dennis Camera
+
+
+COPYING
+-------
+Copyright \(C) 2020 Dennis Camera. You can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
diff --git a/cdist/conf/type/__interface/manifest b/cdist/conf/type/__interface/manifest
new file mode 100755
index 00000000..73727a2a
--- /dev/null
+++ b/cdist/conf/type/__interface/manifest
@@ -0,0 +1,94 @@
+#!/bin/sh -e
+# -*- mode: sh; indent-tabs-mode: t -*-
+#
+# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see .
+#
+
+die() { echo "$*" >&2; exit 1; }
+dief() {
+ #shellcheck disable=SC2059
+ die "$(printf "$@")"
+}
+invalid_param() { die "$@"; }
+invalid_paramf() { dief "$@"; }
+
+
+os=$(cat "${__global:?}/explorer/os")
+
+# Check parameters
+bootproto=$(cat "${__object:?}/parameter/bootproto")
+case $bootproto
+in
+ (dhcp)
+ # Check parameters
+ ! test -f "${__object:?}/parameter/address" \
+ || invalid_param '--address is invalid for --bootproto dhcp'
+ ! test -f "${__object:?}/parameter/gateway" \
+ || invalid_param '--gateway is invalid for --bootproto dhcp'
+ ;;
+ (static)
+ # TODO
+ ;;
+ (manual)
+ # TODO
+ ;;
+ (*)
+ invalid_paramf 'Unknown --bootproto: %s\n' "${bootproto}"
+ ;;
+esac
+
+if test -f "${__object:?}/parameter/type"
+then
+ impl_type=$(cat "${__object:?}/parameter/type")
+else
+ # Guess the type based on the operating system
+ case $os
+ in
+ (debian)
+ os_major=$(grep -o '^[0-9][0-9]*' "${__global:?}/explorer/os_version")
+ test "${os_major}" -ge 7 \
+ || die 'Debian versions older than 7 (wheezy) are not supported'
+
+ impl_type=ifupdown.d
+ ;;
+ (devuan)
+ impl_type=ifupdown.d
+ ;;
+ (centos|redhat|scientific|suse)
+ impl_type=ifcfg
+ ;;
+ (openwrt)
+ impl_type=uci
+ ;;
+ (*)
+ if test -s "${__object:?}/explorer/has_networkctl"
+ then
+ impl_type=systemd
+ else
+ dief "Don't know how to manage interfaces on: %s\n" "${os}"
+ fi
+ ;;
+ esac
+fi
+
+# Hand over to backend-specific implementation
+manifest_file="${__type:?}/files/backends/${impl_type}/manifest"
+test -x "${manifest_file}" || dief 'Unknown type: %s\n' "${impl_type}"
+
+# Run backend-specific script
+exec "${manifest_file}"
diff --git a/cdist/conf/type/__interface/parameter/boolean b/cdist/conf/type/__interface/parameter/boolean
new file mode 100644
index 00000000..2b6d0a3b
--- /dev/null
+++ b/cdist/conf/type/__interface/parameter/boolean
@@ -0,0 +1,2 @@
+hotplug
+onboot
diff --git a/cdist/conf/type/__interface/parameter/default/bootproto b/cdist/conf/type/__interface/parameter/default/bootproto
new file mode 100644
index 00000000..72ab18f1
--- /dev/null
+++ b/cdist/conf/type/__interface/parameter/default/bootproto
@@ -0,0 +1 @@
+dhcp
diff --git a/cdist/conf/type/__interface/parameter/default/onchange b/cdist/conf/type/__interface/parameter/default/onchange
new file mode 100644
index 00000000..e8f9c907
--- /dev/null
+++ b/cdist/conf/type/__interface/parameter/default/onchange
@@ -0,0 +1 @@
+leave
diff --git a/cdist/conf/type/__interface/parameter/default/state b/cdist/conf/type/__interface/parameter/default/state
new file mode 100644
index 00000000..e7f6134f
--- /dev/null
+++ b/cdist/conf/type/__interface/parameter/default/state
@@ -0,0 +1 @@
+present
diff --git a/cdist/conf/type/__interface/parameter/optional b/cdist/conf/type/__interface/parameter/optional
new file mode 100644
index 00000000..16ae6fba
--- /dev/null
+++ b/cdist/conf/type/__interface/parameter/optional
@@ -0,0 +1,7 @@
+bootproto
+comment
+gateway
+name
+onchange
+state
+type
diff --git a/cdist/conf/type/__interface/parameter/optional_multiple b/cdist/conf/type/__interface/parameter/optional_multiple
new file mode 100644
index 00000000..5bb11f03
--- /dev/null
+++ b/cdist/conf/type/__interface/parameter/optional_multiple
@@ -0,0 +1,2 @@
+address
+extra-config
diff --git a/cdist/conf/type/__interface_ifcfg/man.rst b/cdist/conf/type/__interface_ifcfg/man.rst
new file mode 100644
index 00000000..54fc76b7
--- /dev/null
+++ b/cdist/conf/type/__interface_ifcfg/man.rst
@@ -0,0 +1,72 @@
+cdist-type__interface_ifcfg(7)
+===============================
+
+NAME
+----
+cdist-type__interface_ifcfg - Manage network interfaces using ifcfg network
+scripts.
+
+
+DESCRIPTION
+-----------
+This type allows to configure network interfaces using the ifcfg network scripts
+on RedHat and SuSE distributions.
+
+
+REQUIRED PARAMETERS
+-------------------
+bootproto
+ ...
+type
+ The type of the interface, e.g. ``Ethernet``, ``Bridge``, ``Dummy``,
+ ``Loopback``.
+ Defaults to ``Ethernet``.
+
+
+OPTIONAL PARAMETERS
+-------------------
+address
+
+comment
+ If supplied, the value will be inserted at the top of the configuration file
+ as a comment.
+option
+ ...
+ Can be used multiple times.
+
+
+BOOLEAN PARAMETERS
+------------------
+onboot
+
+hotplug
+
+
+
+EXAMPLES
+--------
+
+.. code-block:: sh
+
+ # TODO
+ __interface_ifcfg ...
+
+
+SEE ALSO
+--------
+:strong:`cdist-type__interface`\ (7)
+
+
+AUTHORS
+-------
+Steven Armstrong
+Dennis Camera
+
+
+COPYING
+-------
+Copyright \(C) 2014--2020 Steven Armstrong and Dennis Camera.
+
+You can redistribute it and/or modify it under the terms of the
+GNU General Public License as published by the Free Software Foundation,
+either version 3 of the License, or (at your option) any later version.
diff --git a/cdist/conf/type/__interface_ifcfg/manifest b/cdist/conf/type/__interface_ifcfg/manifest
new file mode 100755
index 00000000..a0bc0c16
--- /dev/null
+++ b/cdist/conf/type/__interface_ifcfg/manifest
@@ -0,0 +1,257 @@
+#!/bin/sh -e
+#
+# 2014 Steven Armstrong (steven-cdist at armstrong.cc)
+# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see .
+#
+
+yesno() { test $? -eq 0 && echo yes || echo no; }
+opt_format() {
+ printf '%s="%s"\n' "${1:?'option name missing'}" "${2:?'option value missing'}"
+}
+prefix2subnet() {
+ python3 -c 'for addr in __import__("sys").argv[1:]: print(__import__("ipaddress").ip_network(addr, strict=False).netmask)' "$@"
+}
+param2var() {
+ echo "${1:?'param name missing'}" | tr '[:lower:]-' '[:upper:]_'
+}
+ipversion() {
+ python3 -c 'for addr in __import__("sys").argv[1:]: print(__import__("ipaddress").ip_address(addr).version)' "$@"
+}
+
+os=$(cat "${__global:?}/explorer/os")
+
+case $os
+in
+ (centos|redhat|scientific)
+ NETWORK_SCRIPTS_DIR='/etc/sysconfig/network-scripts'
+ systype=redhat
+ ;;
+ (suse)
+ NETWORK_SCRIPTS_DIR='/etc/sysconfig/network'
+ systype=suse
+ ;;
+ (*)
+ printf "Your operating system (%s) is currently not supported by this type (%s)\n" "${os}" "${__type##*/}" >&2
+ printf "Please contribute an implementation for it if you can.\n" >&2
+ exit 1
+ ;;
+esac
+
+if test -s "${__object:?}/parameter/name"
+then
+ name=$(cat "${__object:?}/parameter/name")
+else
+ name=${__object_id:?}
+fi
+state_should=$(cat "${__object:?}/parameter/state")
+bootproto=$(cat "${__object:?}/parameter/bootproto")
+onchange=$(cat "${__object:?}/parameter/onchange")
+iftype=$(cat "${__object:?}/parameter/type")
+
+ifcfg_file="${NETWORK_SCRIPTS_DIR:?}/ifcfg-${__object_id:?}"
+
+
+onchange_action() {
+ case $onchange
+ in
+ (refresh)
+ printf "ifdown '%s' || true ; ifup '%s'\n" "${name}" "${name}"
+ ;;
+ (up)
+ printf "ifup '%s'\n" "${name}"
+ ;;
+ (down)
+ printf "ifdown '%s' || true\n" "${name}"
+ ;;
+ (leave)
+ # ignore
+ ;;
+ (*)
+ printf 'Invalid --onchange: %s\n' "${onchange}" >&2
+ exit 1
+ ;;
+ esac
+}
+
+
+{
+ cat <<-EOF
+ # Created by cdist ${__type##*/}
+ # Do not change. Changes will be overwritten.
+ #
+
+ EOF
+
+ if test -f "${__object:?}/parameter/comment"
+ then
+ awk '{ print "# " $0 }' <"${__object:?}/parameter/comment"
+ echo
+ fi
+
+ opt_format DEVICE "${name}"
+ opt_format NM_CONTROLLED no
+
+ case $systype
+ in
+ (redhat)
+ opt_format TYPE "${iftype}"
+
+ for _param in onboot hotplug
+ do
+ _key=$(param2var "${_param}")
+ opt_format "${_key}" "$(test -f "${__object}/parameter/${_param}" | yesno)"
+ done
+ unset _param _key
+ ;;
+ (suse)
+ iftype=$(echo "${iftype}" | tr '[:upper:]' '[:lower:]')
+ if test "${iftype}" = 'loopback' -o "${iftype}" = 'dummy'
+ then
+ # Only use INTERFACETYPE for lo/dummy.
+ # cf. /usr/share/YaST2/modules/NetworkInterfaces.rb
+ opt_format INTERFACETYPE "${iftype}"
+ fi
+
+ _startmode=manual
+
+ if test -f "${__object:?}/parameter/onboot"
+ then
+ _startmode=auto
+ fi
+ if test -f "${__object:?}/parameter/hotplug"
+ then
+ _startmode=ifplugd
+ fi
+
+ opt_format STARTMODE "${_startmode}"
+ ;;
+ esac
+
+ ignored_parameters=
+
+ # manually_handled_parameters are handled in their own code block, not by
+ # the generic accumulator
+ manually_handled_parameters='bootproto comment extra-config hotplug name onboot onchange state'
+
+ case $bootproto
+ in
+ (dhcp)
+ opt_format BOOTPROTO dhcp
+ ignored_parameters='address broadcast gateway'
+ ;;
+ (static|none)
+ opt_format BOOTPROTO none
+ ;;
+ (*)
+ printf 'Invalid --bootproto: %s\n' "${bootproto}" >&2
+ exit 1
+ ;;
+ esac
+
+ _bonding_opts=
+
+ for _param in "${__object:?}"/parameter/*
+ do
+ _key=$(param2var "${_param}")
+
+ echo "${ignored_parameters}" | grep -q -w "${_param}" && continue
+ echo "${manually_handled_parameters}" | grep -q -w "${_param}" && continue
+
+ case $_param
+ in
+ (bond-master)
+ opt_format SLAVE yes
+ opt_format MASTER "$(cat "${__object:?}/parameter/${_param}")"
+ ;;
+ (bond-*)
+ _key=$(echo "${_param#bond-}" | tr '-' '_')
+ _value=$(cat "${__object:?}/parameter/${_param}")
+
+ if test "${_key}" = 'arp_ip_target'
+ then
+ _value=$(echo "${_value}" | awk -v RS= -v FS='\n' -v OFS=',' '$1=$1')
+ fi
+
+ _bonding_opts="${_bonding_opts} $(opt_format "${_key}" "${_value}")"
+ ;;
+ (*)
+ case $_param
+ in
+ (address)
+ n=0
+ case $systype
+ in
+ (redhat)
+ # the fucked-up config
+ while read -r _addr
+ do
+ if test "$(ipversion "${_addr}")" -eq 6
+ then
+ if ! ${_ipv6_enabled:-false}
+ then
+ opt_format IPV6INIT yes
+ opt_format IPV6ADDR "${_addr}"
+ _ipv6_enabled=true
+ else
+ _ipv6_sec="${_ipv6_sec} ${_addr}"
+ fi
+ else
+ opt_format "IPADDR${n}" "${_addr%%/*}"
+ opt_format "NETMASK${n}" "$(prefix2subnet "${_addr##*/}")"
+ : $((n+=1))
+ fi
+ done
+
+ if test -n "${_ipv6_sec}"
+ then
+ opt_format IPV6ADDR_SECONDARIES "${_ipv6_sec# }"
+ fi
+ unset _ipv6_enabled _ipv6_sec
+ ;;
+ (suse)
+ # the sane config
+ while read -r _addr
+ do
+ opt_format "IPADDR${n}" "${_addr}"
+ : $((n+=1))
+ done
+ ;;
+ esac <"${__object:?}/parameter/address"
+ unset n _addr
+ ;;
+ (*)
+ opt_format "${_key}" "$(cat "${__object:?}/parameter/${_param}")"
+ ;;
+ esac
+ ;;
+ esac
+ done
+
+ if test -n "${_bonding_opts}"
+ then
+ # strip leading space
+ opt_format BONDING_OPTS "${_bonding_opts# }"
+ fi
+
+ if test -f "${__object:?}/parameter/extra-config"
+ then
+ cat "${__object:?}/parameter/extra-config"
+ fi
+} | __file "${ifcfg_file}" \
+ --state "${state_should}" --owner root --group root --mode 0644 \
+ --onchange "$(onchange_action)" --source -
diff --git a/cdist/conf/type/__interface_ifcfg/parameter/boolean b/cdist/conf/type/__interface_ifcfg/parameter/boolean
new file mode 100644
index 00000000..14b5e789
--- /dev/null
+++ b/cdist/conf/type/__interface_ifcfg/parameter/boolean
@@ -0,0 +1,2 @@
+onboot
+hotplug
diff --git a/cdist/conf/type/__interface_ifcfg/parameter/default/onchange b/cdist/conf/type/__interface_ifcfg/parameter/default/onchange
new file mode 100644
index 00000000..e8f9c907
--- /dev/null
+++ b/cdist/conf/type/__interface_ifcfg/parameter/default/onchange
@@ -0,0 +1 @@
+leave
diff --git a/cdist/conf/type/__interface_ifcfg/parameter/default/state b/cdist/conf/type/__interface_ifcfg/parameter/default/state
new file mode 100644
index 00000000..e7f6134f
--- /dev/null
+++ b/cdist/conf/type/__interface_ifcfg/parameter/default/state
@@ -0,0 +1 @@
+present
diff --git a/cdist/conf/type/__interface_ifcfg/parameter/default/type b/cdist/conf/type/__interface_ifcfg/parameter/default/type
new file mode 100644
index 00000000..8942065e
--- /dev/null
+++ b/cdist/conf/type/__interface_ifcfg/parameter/default/type
@@ -0,0 +1 @@
+Ethernet
diff --git a/cdist/conf/type/__interface_ifcfg/parameter/optional b/cdist/conf/type/__interface_ifcfg/parameter/optional
new file mode 100644
index 00000000..f8e8477d
--- /dev/null
+++ b/cdist/conf/type/__interface_ifcfg/parameter/optional
@@ -0,0 +1,4 @@
+comment
+name
+onchange
+state
diff --git a/cdist/conf/type/__interface_ifcfg/parameter/required b/cdist/conf/type/__interface_ifcfg/parameter/required
new file mode 100644
index 00000000..8df5eed7
--- /dev/null
+++ b/cdist/conf/type/__interface_ifcfg/parameter/required
@@ -0,0 +1,2 @@
+bootproto
+type
diff --git a/cdist/conf/type/__interface_ifupdown.d/files/interfaces b/cdist/conf/type/__interface_ifupdown.d/files/interfaces
new file mode 100644
index 00000000..084df231
--- /dev/null
+++ b/cdist/conf/type/__interface_ifupdown.d/files/interfaces
@@ -0,0 +1,11 @@
+# Managed by cdist
+# Changes will be overwritten.
+
+# This file describes the network interfaces available on your system
+# and how to activate them. For more information, see interfaces(5).
+
+source /etc/network/interfaces.d/*
+
+# The loopback network interface
+auto lo
+iface lo inet loopback
diff --git a/cdist/conf/type/__interface_ifupdown.d/man.rst b/cdist/conf/type/__interface_ifupdown.d/man.rst
new file mode 100644
index 00000000..205c6d64
--- /dev/null
+++ b/cdist/conf/type/__interface_ifupdown.d/man.rst
@@ -0,0 +1,114 @@
+cdist-type__interface_ifupdown.d(7)
+===================================
+
+NAME
+----
+cdist-type__interface_ifupdown.d - Manage network interfaces using ifupdown
+using the interfaces.d directory
+
+
+DESCRIPTION
+-----------
+This space intentionally left blank.
+
+NOTE: Only interfaces declared by cdist are removed when using --state absent.
+ Moreover, the interface declaration is identified by the object_id,
+ not by the interface's IP address or the like.
+
+REQUIRED PARAMETERS
+-------------------
+family
+ The name of the address family that the interface uses.
+ Available options are: 'inet', 'ipx', 'inet6', 'can'.
+method
+ The name of the method used to configure the interface.
+ Available options depend on the address family and are, for
+ inet:
+ 'loopback', 'static', 'manual', 'dhcp', 'bootp', 'tunnel', 'ppp',
+ 'wvdial', and 'ip4ll'.
+ ipx:
+ 'static', and 'dynamic'.
+ inet6:
+ 'auto', 'loopback', 'static', 'manual', 'dhcp', 'v4tunnel', '6to4'.
+ can:
+ 'static'.
+
+
+OPTIONAL PARAMETERS
+-------------------
+name
+ The name of the logical interface to configure (usually equivalent to the
+ physical interface).
+ Defaults to __object_id.
+comment
+ If supplied, the value will be inserted at the top of the configuration file
+ as a comment.
+ If comment is '-', what was written to stdin is used as the comment.
+rename
+ If supplied, the given interface renaming spefication will be added to the
+ config file.
+ This option can e.g. be used to generate predictable interface names based
+ on the interface's MAC address.
+state
+ Either present or absent. Defaults to present.
+option
+ Option that is added to the generated interface configuration verbatim.
+ Can be used multiple times so add more than one option.
+onchange
+ The action to perform if the interface configuration has changed.
+ Available options are:
+ leave (default)
+ Do nothing.
+ up
+ Bring the interface up if it is down.
+ down
+ Bring the interface down if it is up.
+ refresh
+ Refresh the interface (down && up).
+
+
+BOOLEAN PARAMETERS
+------------------
+auto
+ If supplied, the interface will be marked "auto" and brought up during boot.
+hotplug
+ Allow hotplug support for this interface.
+ The interface will be brought up when udev detects it, this can be during
+ boot or later.
+no-auto-down
+ If supplied, the interface will not be brought down by the command
+ "ifdown -a".
+no-scripts
+ If supplied, scripts in '/etc/network/if-*.d/' will not be run when this
+ interface is brought up or down.
+
+
+EXAMPLES
+--------
+
+.. code-block:: sh
+
+ # Configure interface eth0 to use DHCP.
+ __interface_ifupdown.d eth0 --family inet --method dhcp
+
+ # Rename interface with MAC 00:11:22:33:44:55 to eth1 and use DHCP.
+ __interface_ifupdown.d eth1 --rename mac/00:11:22:33:44:55=eth1 \
+ --family inet --method dhcp
+
+
+SEE ALSO
+--------
+:strong:`interfaces`\ (5)
+
+
+AUTHORS
+-------
+Dennis Camera
+
+
+COPYING
+-------
+Copyright \(C) 2020 Dennis Camera. You can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
diff --git a/cdist/conf/type/__interface_ifupdown.d/manifest b/cdist/conf/type/__interface_ifupdown.d/manifest
new file mode 100755
index 00000000..d37bc30b
--- /dev/null
+++ b/cdist/conf/type/__interface_ifupdown.d/manifest
@@ -0,0 +1,184 @@
+#!/bin/sh -e
+#
+# 2020-2021 Dennis Camera (dennis.camera@ssrq-sds-fds.ch)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see .
+#
+
+INTERFACES_FILE=/etc/network/interfaces
+INTERFACES_D_PATH=/etc/network/interfaces.d
+
+os=$(cat "${__global}/explorer/os")
+
+if test -s "${__object}/parameter/name"
+then
+ name=$(cat "${__object}/parameter/name")
+else
+ name=$__object_id
+fi
+onchange_action=$(cat "${__object}/parameter/onchange")
+state=$(cat "${__object}/parameter/state")
+
+# NOTE: No file ending is used not to break the source-directory stanza
+# (if used and at least for normal interface names)
+iface_file="${INTERFACES_D_PATH}/${__object_id}"
+
+onchange_action() {
+ case $onchange_action
+ in
+ (refresh)
+ printf "ifdown --force '%s' ; ifup '%s'\n" "${name}" "${name}"
+ ;;
+ (up)
+ printf "ifup '%s'\n" "${name}"
+ ;;
+ (down)
+ printf "ifdown --force '%s'\n" "${name}"
+ ;;
+ (leave)
+ # ignore
+ ;;
+ (*)
+ printf 'Invalid --onchange: %s\n' "${onchange_action}" >&2
+ exit 1
+ ;;
+ esac
+}
+
+
+case $os
+in
+ (debian)
+ os_major=$(grep -o '^[0-9][0-9]*' "${__global}/explorer/os_version")
+ if test "${os_major}" -lt 7
+ then
+ # Old versions do not support "source"
+ printf 'Debian versions older than 7 (wheezy) are not supported by this type (%s)\n' "${__type##*/}" >&2
+ exit 1
+ fi
+
+ if test "${state}" = 'present'
+ then
+ __package ifupdown --state present
+ export require=__package/ifupdown
+ fi
+ ;;
+ (devuan)
+ if test "${state}" = 'present'
+ then
+ __package ifupdown --state present
+ export require=__package/ifupdown
+ fi
+ ;;
+ (*)
+ printf 'Your operating system (%s) is currently not supported by this type (%s)\n' "$os" "${__type##*/}" >&2
+ printf "Please contribute an implementation for it if you can.\n" >&2
+ exit 1
+ ;;
+esac
+
+case $state
+in
+ (present)
+ if test "${IFUPDOWND_LEAVE_EXISTING_CONFIG:-0}" -eq 0
+ then
+ # The /etc/network/interfaces file is overwritten with a basic example.
+ __file "${INTERFACES_FILE}" --state present --owner root --mode 0644 \
+ --source "${__type}/files/interfaces"
+ export require="__file${INTERFACES_FILE}"
+ else
+ # If state is present and IFUPDOWND_LEAVE_EXISTING_CONFIG is set,
+ # ensure that the interfaces.d directory is sourced in the main
+ # interfaces file, being as minimally invasive as possible.
+ __line "${INTERFACES_FILE}:source_interfaces.d" --state present \
+ --file "${INTERFACES_FILE}" \
+ --before '^#?[:blank:]*(auto|no-auto-down|no-scripts|allow-|iface|mapping|rename|source|source-directory)|^#[[:blank:]]*The .* interface$' \
+ --line "source ${INTERFACES_D_PATH}/*"
+ export require="__line${INTERFACES_FILE}:source_interfaces.d"
+ fi
+
+ __directory "${INTERFACES_D_PATH}" --state pre-exists \
+ --owner root --mode 0755
+ export require="__directory/${INTERFACES_D_PATH}"
+
+ # Construct interface config file
+ (
+ cat <<-EOF
+ # Managed by cdist (${__type##*/})
+ # Do not change. Changes will be overwritten.
+
+ EOF
+
+ if test -s "${__object}/parameter/comment"
+ then
+ # Prefix lines with # and append trailing empty line.
+ # shellcheck disable=SC2016
+ {
+ if test "$(cat "${__object}/parameter/comment")" = '-'
+ then
+ cat "${__object}/stdin"
+ else
+ cat "${__object}/parameter/comment"
+ fi
+ } | sed -e 's/^/# /;$G'
+ fi
+
+ # Put together rename line
+ if test -s "${__object}/parameter/rename"
+ then
+ printf 'rename %s\n' "$(cat "${__object}/parameter/rename")"
+ fi
+
+ # Put together the "allow" lines (these are the line(s) usually
+ # preceeding the iface line in the config).
+ if test -f "${__object}/parameter/auto"
+ then
+ printf 'auto %s\n' "${name}"
+ fi
+ if test -f "${__object}/parameter/hotplug"
+ then
+ printf 'allow-hotplug %s\n' "${name}"
+ fi
+ if test -f "${__object}/parameter/no-auto-down"
+ then
+ printf 'no-auto-down %s\n' "${name}"
+ fi
+ if test -f "${__object}/parameter/no-scripts"
+ then
+ printf 'no-scripts %s\n' "${name}"
+ fi
+
+ addrfam=$(cat "${__object}/parameter/family")
+ method=$(cat "${__object}/parameter/method")
+ printf 'iface %s %s %s\n' "${name}" "${addrfam}" "${method}"
+
+ while read -r _opt
+ do
+ printf '\t%s\n' "${_opt}"
+ done <"${__object}/parameter/option"
+ unset _opt
+ ) | __file "${iface_file}" --state present --owner root --mode 0644 \
+ --onchange "$(onchange_action)" --source -
+ ;;
+ (absent)
+ __file "${iface_file}" --state absent \
+ --onchange "$(onchange_action)"
+ ;;
+ (*)
+ printf 'Invalid --state: %s\n' "${state}" >&2
+ exit 1
+ ;;
+esac
diff --git a/cdist/conf/type/__interface_ifupdown.d/parameter/boolean b/cdist/conf/type/__interface_ifupdown.d/parameter/boolean
new file mode 100644
index 00000000..211dcf33
--- /dev/null
+++ b/cdist/conf/type/__interface_ifupdown.d/parameter/boolean
@@ -0,0 +1,4 @@
+auto
+hotplug
+no-auto-down
+no-scripts
diff --git a/cdist/conf/type/__interface_ifupdown.d/parameter/default/onchange b/cdist/conf/type/__interface_ifupdown.d/parameter/default/onchange
new file mode 100644
index 00000000..e8f9c907
--- /dev/null
+++ b/cdist/conf/type/__interface_ifupdown.d/parameter/default/onchange
@@ -0,0 +1 @@
+leave
diff --git a/cdist/conf/type/__interface_ifupdown.d/parameter/default/state b/cdist/conf/type/__interface_ifupdown.d/parameter/default/state
new file mode 100644
index 00000000..e7f6134f
--- /dev/null
+++ b/cdist/conf/type/__interface_ifupdown.d/parameter/default/state
@@ -0,0 +1 @@
+present
diff --git a/cdist/conf/type/__interface_ifupdown.d/parameter/optional b/cdist/conf/type/__interface_ifupdown.d/parameter/optional
new file mode 100644
index 00000000..70b22b74
--- /dev/null
+++ b/cdist/conf/type/__interface_ifupdown.d/parameter/optional
@@ -0,0 +1,5 @@
+comment
+name
+rename
+state
+onchange
diff --git a/cdist/conf/type/__interface_ifupdown.d/parameter/optional_multiple b/cdist/conf/type/__interface_ifupdown.d/parameter/optional_multiple
new file mode 100644
index 00000000..01925a15
--- /dev/null
+++ b/cdist/conf/type/__interface_ifupdown.d/parameter/optional_multiple
@@ -0,0 +1 @@
+option
diff --git a/cdist/conf/type/__interface_ifupdown.d/parameter/required b/cdist/conf/type/__interface_ifupdown.d/parameter/required
new file mode 100644
index 00000000..32c70451
--- /dev/null
+++ b/cdist/conf/type/__interface_ifupdown.d/parameter/required
@@ -0,0 +1,2 @@
+family
+method
diff --git a/cdist/conf/type/__systemd_networkd_network/explorer/networkctl_bin b/cdist/conf/type/__systemd_networkd_network/explorer/networkctl_bin
new file mode 100755
index 00000000..e2cf8409
--- /dev/null
+++ b/cdist/conf/type/__systemd_networkd_network/explorer/networkctl_bin
@@ -0,0 +1,24 @@
+#!/bin/sh -e
+#
+# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see .
+#
+#
+# Prints the path of networkctl if found on the target system.
+#
+
+command -v networkctl 2>/dev/null || true
diff --git a/cdist/conf/type/__systemd_networkd_network/explorer/state b/cdist/conf/type/__systemd_networkd_network/explorer/state
new file mode 100755
index 00000000..6c225e4e
--- /dev/null
+++ b/cdist/conf/type/__systemd_networkd_network/explorer/state
@@ -0,0 +1,60 @@
+#!/bin/sh -e
+#
+# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see .
+#
+#
+# Check whether a configuration for the interface already exists with the same
+# name already exists.
+# The output will be "exists" followed by the config file path on the next line,
+# or "absent"
+# In case networkctl cannot be found, the output will be "error".
+#
+
+networkctl_bin=$("${__type_explorer:?}/networkctl_bin")
+
+test -x "${networkctl_bin}" || { echo error; exit 0; }
+
+if test -f "${__object:?}/parameter/name"
+then
+ name=$(cat "${__object:?}/parameter/name")
+else
+ name=${__object_id:?}
+fi
+
+if "${networkctl_bin}" --no-pager --no-legend list "${name}" >/dev/null 2>&1
+then
+ echo exists
+
+ "${networkctl_bin}" --no-pager --no-legend status "${name}" \
+ | awk -F ': ' -v ifname="${name}" '
+ BEGIN {
+ # header line
+ getline
+ # · N: en...
+ if (index($2, ifname) != 1 || substr($2, length(ifname) + 1) !~ /^[[:blank:]]*$/)
+ exit
+ }
+ !$0 { exit } # skip journal lines
+ /^[[:blank:]]*Network File:/ {
+ sub(/[[:blank:]]*$/, "", $2)
+ print $2
+ }' \
+ | grep -ixvF 'n/a' || true # networkctl prints "n/a" if iface is unmanaged
+else
+ echo absent
+fi
diff --git a/cdist/conf/type/__systemd_networkd_network/man.rst b/cdist/conf/type/__systemd_networkd_network/man.rst
new file mode 100644
index 00000000..3cc999fe
--- /dev/null
+++ b/cdist/conf/type/__systemd_networkd_network/man.rst
@@ -0,0 +1,69 @@
+cdist-type__systemd_networkd_network(7)
+=======================================
+
+NAME
+----
+cdist-type__systemd_networkd_network - Manage network configuration using
+systemd-networkd.
+
+
+DESCRIPTION
+-----------
+This space intentionally left blank.
+
+
+REQUIRED PARAMETERS
+-------------------
+None.
+
+
+OPTIONAL PARAMETERS
+-------------------
+match
+ Match directives can be used to filter the interfaces to which this
+ configuration applies. This paramter can be used multiple times.
+ The value will be copied to the [Match] section of the config file verbatim.
+ Defaults to: "Name={interface name}"
+name
+ The name of the interface to configure.
+option
+ ...
+priority
+ The "priority" of this configuration. It is used as a prefix to the
+ configuration file name.
+ Defaults to 10.
+state
+ Either ``present`` or ``absent``. Defaults to ``present``.
+
+
+BOOLEAN PARAMETERS
+------------------
+auto-reload
+ Automatically apply new config after changes have been written.
+
+
+EXAMPLES
+--------
+
+.. code-block:: sh
+
+ # TODO
+ __systemd_networkd_network
+
+
+SEE ALSO
+--------
+:strong:`systemd.network`\ (5)
+
+
+AUTHORS
+-------
+Dennis Camera
+
+
+COPYING
+-------
+Copyright \(C) 2020 Dennis Camera. You can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
diff --git a/cdist/conf/type/__systemd_networkd_network/manifest b/cdist/conf/type/__systemd_networkd_network/manifest
new file mode 100755
index 00000000..ab4da92e
--- /dev/null
+++ b/cdist/conf/type/__systemd_networkd_network/manifest
@@ -0,0 +1,121 @@
+#!/bin/sh -e
+#
+# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see .
+#
+
+CONFIG_FILE_PATH='/etc/systemd/network'
+
+networkctl_bin=$(cat "${__object:?}/explorer/networkctl_bin")
+
+test -n "${networkctl_bin}" || {
+ printf 'This system is not supported by this type (%s).' "${__type##*/}" >&2
+ printf ' The networkctl tool could not be found.\n' >&2
+ exit 1
+}
+
+{
+ # shellcheck disable=SC2034
+ read -r state_is
+ read -r config_is || true
+} <"${__object:?}/explorer/state"
+
+if test -f "${__object:?}/parameter/name"
+then
+ name=$(cat "${__object:?}/parameter/name")
+else
+ name=${__object_id:?}
+fi
+
+priority=$(cat "${__object:?}/parameter/priority")
+state_should=$(cat "${__object:?}/parameter/state")
+
+config_file=$(printf '%s/%02u-%s.network' "${CONFIG_FILE_PATH}" "${priority}" "${__object_id:?}")
+
+if test -f "${__object:?}/parameter/auto-reload"
+then
+ reload_cmd="${networkctl_bin} reload"
+else
+ reload_cmd=
+fi
+
+gen_conf() {
+ echo '[Match]'
+
+ if test -s "${__object:?}/parameter/match"
+ then
+ cat "${__object:?}/parameter/match"
+ else
+ # By default match against the interface name
+ printf 'Name=%s\n' "${name}"
+ fi
+
+ {
+ grep -e '^Network\.' "${__object:?}/parameter/option"
+
+ grep -v -e '^\(Match\|Network\)\.' "${__object:?}/parameter/option" \
+ | sort -t . -k 1
+ } | while read -r _option
+ do
+ _section=${_option%%.*}
+
+ if test "${_cur_section}" != "${_section}"
+ then
+ # new section
+ printf '\n[%s]\n' "${_section}"
+ _cur_section=$_section
+ fi
+
+ echo "${_option#*.}"
+ done
+}
+
+
+if test -n "${config_is}" -a "${config_is}" != "${config_file}"
+then
+ # Check if only the priority has changed!
+ # We cannot in all cases delete the old config file as it might be a default
+ # config.
+ if test "$(dirname "${config_file}")" = "$(dirname "${config_is}")" \
+ && test "$(basename "${config_is}" | sed -e 's/^[0-9]*//')" \
+ = "$(basename "${config_file}" | sed -e 's/^[0-9]*//')"
+ then
+ # Remove old config, but do not reload, yet.
+ # reload will be done after new config file has been written…
+ require="__file${config_file}" __file "${config_is}" --state absent
+ fi
+fi
+
+
+case $state_should
+in
+ (present)
+ __directory "${CONFIG_FILE_PATH}" --state pre-exists
+ export require=__directory"${CONFIG_FILE_PATH}"
+
+ gen_conf | __file "${config_file}" --state "${state_should}" \
+ --owner 0 --mode 0644 --source - \
+ --onchange "${reload_cmd}"
+ ;;
+ (absent)
+ __file "${config_file}" --state absent \
+ --onchange "${reload_cmd}"
+ ;;
+ (*)
+ printf 'Invalid --state: %s\n' "${state_should}"
+ ;;
+esac
diff --git a/cdist/conf/type/__systemd_networkd_network/parameter/boolean b/cdist/conf/type/__systemd_networkd_network/parameter/boolean
new file mode 100644
index 00000000..ae36618d
--- /dev/null
+++ b/cdist/conf/type/__systemd_networkd_network/parameter/boolean
@@ -0,0 +1 @@
+auto-reload
diff --git a/cdist/conf/type/__systemd_networkd_network/parameter/default/priority b/cdist/conf/type/__systemd_networkd_network/parameter/default/priority
new file mode 100644
index 00000000..f599e28b
--- /dev/null
+++ b/cdist/conf/type/__systemd_networkd_network/parameter/default/priority
@@ -0,0 +1 @@
+10
diff --git a/cdist/conf/type/__systemd_networkd_network/parameter/default/state b/cdist/conf/type/__systemd_networkd_network/parameter/default/state
new file mode 100644
index 00000000..e7f6134f
--- /dev/null
+++ b/cdist/conf/type/__systemd_networkd_network/parameter/default/state
@@ -0,0 +1 @@
+present
diff --git a/cdist/conf/type/__systemd_networkd_network/parameter/optional b/cdist/conf/type/__systemd_networkd_network/parameter/optional
new file mode 100644
index 00000000..685217c5
--- /dev/null
+++ b/cdist/conf/type/__systemd_networkd_network/parameter/optional
@@ -0,0 +1,3 @@
+name
+priority
+state
diff --git a/cdist/conf/type/__systemd_networkd_network/parameter/optional_multiple b/cdist/conf/type/__systemd_networkd_network/parameter/optional_multiple
new file mode 100644
index 00000000..ec20610b
--- /dev/null
+++ b/cdist/conf/type/__systemd_networkd_network/parameter/optional_multiple
@@ -0,0 +1,2 @@
+match
+option