From 8d84834db6f2bf16474161cff358496d76923801 Mon Sep 17 00:00:00 2001
From: Adam Dej <dejko.a@gmail.com>
Date: Wed, 11 Jul 2018 15:53:23 +0200
Subject: [PATCH 1/3] __systemd_unit: manpage clarifications

Clarify that this type only operates on units in /etc/systemd/system.
Also, when state=present, it is not always true that the type is
"installed, enabled and started"
---
 cdist/conf/type/__systemd_unit/man.rst | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/cdist/conf/type/__systemd_unit/man.rst b/cdist/conf/type/__systemd_unit/man.rst
index 88da6b30..5d68b253 100644
--- a/cdist/conf/type/__systemd_unit/man.rst
+++ b/cdist/conf/type/__systemd_unit/man.rst
@@ -9,9 +9,10 @@ cdist-type__systemd_unit - Install a systemd unit
 DESCRIPTION
 -----------
 
-This type can install, enable and start a systemd unit. This is particularly
-useful on systems which take advantage of systemd heavily (e.g., CoreOS). For
-more information about systemd units, see SYSTEMD.UNIT(5).
+This type manages systemd units in ``/etc/systemd/system/``. It can install,
+enable and start a systemd unit. This is particularly useful on systems which
+take advantage of systemd heavily (e.g., CoreOS). For more information about
+systemd units, see SYSTEMD.UNIT(5).
 
 REQUIRED PARAMETERS
 -------------------
@@ -37,7 +38,7 @@ state
     'present' or 'absent', defaults to 'present' where:
 
     present
-        the unit is installed, enabled and started
+        the unit is installed
     absent
         the unit is stopped, disabled and uninstalled
 

From 37b37f6e66d1d2d85b3eb2178787aec03221d2a6 Mon Sep 17 00:00:00 2001
From: Adam Dej <dejko.a@gmail.com>
Date: Wed, 11 Jul 2018 15:58:41 +0200
Subject: [PATCH 2/3] __systemd_unit: fix crash when transitioning to
 state=absent

This type tried to disable an unit after it has removed it, which
failed. Now the removal happens in gencode-remote, after the unit has
been stopped and disabled.
---
 cdist/conf/type/__systemd_unit/gencode-remote | 2 ++
 cdist/conf/type/__systemd_unit/manifest       | 4 +++-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/cdist/conf/type/__systemd_unit/gencode-remote b/cdist/conf/type/__systemd_unit/gencode-remote
index c608d9b3..9c64b6c4 100644
--- a/cdist/conf/type/__systemd_unit/gencode-remote
+++ b/cdist/conf/type/__systemd_unit/gencode-remote
@@ -25,6 +25,8 @@ current_enablement_state=$(cat "${__object}/explorer/enablement-state")
 if [ "${state}" = "absent" ]; then
     if [ ! -z "${current_enablement_state}" ]; then
         echo "systemctl --now disable ${name}"
+        echo "rm -f /etc/systemd/system/${name}"
+        echo "systemctl daemon-reload"
     fi
 
     exit 0
diff --git a/cdist/conf/type/__systemd_unit/manifest b/cdist/conf/type/__systemd_unit/manifest
index 8b136605..7739c3d8 100644
--- a/cdist/conf/type/__systemd_unit/manifest
+++ b/cdist/conf/type/__systemd_unit/manifest
@@ -30,7 +30,9 @@ name="${__object_id}"
 source=$(cat "${__object}/parameter/source")
 state=$(cat "${__object}/parameter/state")
 
-if [ -z "${source}" ] && [ "${state}" != "absent" ]; then
+# The unit must be disabled before removing its unit file. The unit file is
+# therefore removed by gencode-remote of this type, not here.
+if [ -z "${source}" ] || [ "${state}" = "absent" ]; then
     exit 0
 fi
 

From 43982f821f6cae64a99673cf9541b5b0b0a940c1 Mon Sep 17 00:00:00 2001
From: Adam Dej <dejko.a@gmail.com>
Date: Wed, 11 Jul 2018 13:00:41 +0200
Subject: [PATCH 3/3] __systemd_unit: add support for masking units

---
 cdist/conf/type/__systemd_unit/gencode-remote | 17 ++++++++++++++---
 cdist/conf/type/__systemd_unit/man.rst        | 12 ++++++++----
 cdist/conf/type/__systemd_unit/manifest       | 12 +++++++++++-
 3 files changed, 33 insertions(+), 8 deletions(-)

diff --git a/cdist/conf/type/__systemd_unit/gencode-remote b/cdist/conf/type/__systemd_unit/gencode-remote
index 9c64b6c4..60486c52 100644
--- a/cdist/conf/type/__systemd_unit/gencode-remote
+++ b/cdist/conf/type/__systemd_unit/gencode-remote
@@ -33,16 +33,24 @@ if [ "${state}" = "absent" ]; then
 fi
 
 unit_status=$(cat "${__object}/explorer/unit-status")
+desired_enablement_state=$(cat "${__object}/parameter/enablement-state")
+
+if [ "${current_enablement_state}" = "masked" ] && \
+    [ "${desired_enablement_state}" != "masked" ]; then
+    echo "systemctl unmask ${name}"
+fi
 
 if [ -f "${__object}/parameter/restart" ]; then
-    if grep -q "^__file/etc/systemd/system/${name}" "${__messages_in}" || \
+    if [ "${desired_enablement_state}" = "masked" ]; then
+        if [ "${unit_status}" = "active" ]; then
+            echo "systemctl stop ${name}"
+        fi
+    elif grep -q "^__file/etc/systemd/system/${name}" "${__messages_in}" || \
         [ "${unit_status}" != "active" ]; then
         echo "systemctl restart ${name} || true"
     fi
 fi
 
-desired_enablement_state=$(cat "${__object}/parameter/enablement-state")
-
 if [ "${current_enablement_state}" = "${desired_enablement_state}" ]; then
     exit 0
 fi
@@ -58,6 +66,9 @@ case "${desired_enablement_state}" in
     disabled)
         echo "systemctl disable ${name}"
     ;;
+    masked)
+        echo "systemctl mask ${name}"
+    ;;
     *)
         echo "Unsupported unit status: ${desired_enablement_state}" >&2
         exit 1
diff --git a/cdist/conf/type/__systemd_unit/man.rst b/cdist/conf/type/__systemd_unit/man.rst
index 5d68b253..25a4e501 100644
--- a/cdist/conf/type/__systemd_unit/man.rst
+++ b/cdist/conf/type/__systemd_unit/man.rst
@@ -23,12 +23,14 @@ OPTIONAL PARAMETERS
 -------------------
 
 enablement-state
-    'enabled' or 'disabled', where:
+    'enabled', 'disabled' or 'masked', where:
 
     enabled
         enables the unit
     disabled
         disables the unit
+    masked
+        masks the unit
 
 source
     Path to the config file. If source is '-' (dash), take what was written to
@@ -38,15 +40,17 @@ state
     'present' or 'absent', defaults to 'present' where:
 
     present
-        the unit is installed
+        the unit (or its mask) is installed
     absent
-        the unit is stopped, disabled and uninstalled
+        The unit is stopped, disabled and uninstalled. If the unit was masked,
+        the mask is removed.
 
 BOOLEAN PARAMETERS
 ------------------
 
 restart
-    Restart the unit on unit file change or when the unit is inactive.
+    Start the unit if it was inactive. Restart the unit if the unit file
+    changed. Stop the unit if new ``enablement-state`` is ``masked``.
 
 MESSAGES
 --------
diff --git a/cdist/conf/type/__systemd_unit/manifest b/cdist/conf/type/__systemd_unit/manifest
index 7739c3d8..688a00b1 100644
--- a/cdist/conf/type/__systemd_unit/manifest
+++ b/cdist/conf/type/__systemd_unit/manifest
@@ -29,6 +29,7 @@ fi
 name="${__object_id}"
 source=$(cat "${__object}/parameter/source")
 state=$(cat "${__object}/parameter/state")
+enablement_state=$(cat "${__object}/parameter/enablement-state")
 
 # The unit must be disabled before removing its unit file. The unit file is
 # therefore removed by gencode-remote of this type, not here.
@@ -41,8 +42,17 @@ if [ "${source}" = "-" ]; then
     source="${__object}/stdin"
 fi
 
+unitfile_state="${state}"
+if [ "${enablement_state}" = "masked" ]; then
+    # Masking creates a symlink from /etc/systemd/system/<unit> to /dev/null.
+    # This process fails with "Failed to execute operation: Invalid argument"
+    # if file /etc/systemd/system/<unit> already exists. We must therefore
+    # remove it.
+    unitfile_state="absent"
+fi
+
 __config_file "/etc/systemd/system/${name}" \
     --mode 644 \
     --onchange "systemctl daemon-reload" \
     --source "${source}" \
-    --state "${state}"
+    --state "${unitfile_state}"