8d419f
From db20c5cec8adf865dd47672bc091092b8cea5e0e Mon Sep 17 00:00:00 2001
8d419f
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
8d419f
Date: Thu, 10 Mar 2022 15:47:12 +0100
8d419f
Subject: [PATCH] shared/install: return failure when enablement fails, but
8d419f
 process as much as possible
8d419f
8d419f
So far we'd issue a warning (before this series, just in the logs on the server
8d419f
side, and before this commit, on stderr on the caller's side), but return
8d419f
success. It seems that successfull return was introduced by mistake in
8d419f
aa0f357fd833feecbea6c3e9be80b643e433bced (my fault :( ), which was supposed to
8d419f
be a refactoring without a functional change. I think it's better to fail,
8d419f
because if enablement fails, the user will most likely want to diagnose the
8d419f
issue.
8d419f
8d419f
Note that we still do partial enablement, as far as that is possible. So if
8d419f
e.g. we have [Install] Alias=foo.service foobar, we'll create the symlink
8d419f
'foo.service', but not 'foobar', since that's not a valid unit name. We'll
8d419f
print info about the action taken, and about 'foobar' being invalid, and return
8d419f
failure.
8d419f
8d419f
(cherry picked from commit 0d11db59825a9deee0b56fdede0602ef1c37c5c5)
8d419f
8d419f
Related: #2082131
8d419f
---
8d419f
 src/shared/install.c          | 10 +++++----
8d419f
 test/test-systemctl-enable.sh | 39 ++++++++++++++++++-----------------
8d419f
 2 files changed, 26 insertions(+), 23 deletions(-)
8d419f
8d419f
diff --git a/src/shared/install.c b/src/shared/install.c
8d419f
index 6da9ba6b0c..a541d32fb7 100644
8d419f
--- a/src/shared/install.c
8d419f
+++ b/src/shared/install.c
8d419f
@@ -1802,20 +1802,22 @@ static int install_info_symlink_alias(
8d419f
                 q = install_name_printf(scope, info, *s, info->root, &dst);
8d419f
                 if (q < 0) {
8d419f
                         unit_file_changes_add(changes, n_changes, q, *s, NULL);
8d419f
-                        return q;
8d419f
+                        r = r < 0 ? r : q;
8d419f
+                        continue;
8d419f
                 }
8d419f
 
8d419f
                 q = unit_file_verify_alias(info, dst, &dst_updated, changes, n_changes);
8d419f
-                if (q < 0)
8d419f
+                if (q < 0) {
8d419f
+                        r = r < 0 ? r : q;
8d419f
                         continue;
8d419f
+                }
8d419f
 
8d419f
                 alias_path = path_make_absolute(dst_updated ?: dst, config_path);
8d419f
                 if (!alias_path)
8d419f
                         return -ENOMEM;
8d419f
 
8d419f
                 q = create_symlink(lp, info->path, alias_path, force, changes, n_changes);
8d419f
-                if (r == 0)
8d419f
-                        r = q;
8d419f
+                r = r < 0 ? r : q;
8d419f
         }
8d419f
 
8d419f
         return r;
8d419f
diff --git a/test/test-systemctl-enable.sh b/test/test-systemctl-enable.sh
8d419f
index 8ac1342b91..32bc6e5ef7 100644
8d419f
--- a/test/test-systemctl-enable.sh
8d419f
+++ b/test/test-systemctl-enable.sh
8d419f
@@ -56,19 +56,27 @@ test ! -e "$root/etc/systemd/system/default.target.wants/test1.service"
8d419f
 test ! -e "$root/etc/systemd/system/special.target.requires/test1.service"
8d419f
 
8d419f
 : -------aliases----------------------------------------------
8d419f
-"$systemctl" --root="$root" enable test1
8d419f
-test -h "$root/etc/systemd/system/default.target.wants/test1.service"
8d419f
-test -h "$root/etc/systemd/system/special.target.requires/test1.service"
8d419f
-
8d419f
 cat >>"$root/etc/systemd/system/test1.service" <
8d419f
 Alias=test1-goodalias.service
8d419f
 Alias=test1@badalias.service
8d419f
 Alias=test1-badalias.target
8d419f
 Alias=test1-badalias.socket
8d419f
+# we have a series of good, bad, and then good again
8d419f
+Alias=test1-goodalias2.service
8d419f
 EOF
8d419f
 
8d419f
+"$systemctl" --root="$root" enable test1 && { echo "Expected failure" >&2; exit 1; }
8d419f
+test -h "$root/etc/systemd/system/default.target.wants/test1.service"
8d419f
+test -h "$root/etc/systemd/system/special.target.requires/test1.service"
8d419f
+test ! -e "$root/etc/systemd/system/test1-goodalias.service"
8d419f
+test -h "$root/etc/systemd/system/test1-goodalias.service"
8d419f
+test ! -e "$root/etc/systemd/system/test1@badalias.service"
8d419f
+test ! -e "$root/etc/systemd/system/test1-badalias.target"
8d419f
+test ! -e "$root/etc/systemd/system/test1-badalias.socket"
8d419f
+test -h "$root/etc/systemd/system/test1-goodalias2.service"
8d419f
+
8d419f
 : -------aliases in reeanble----------------------------------
8d419f
-"$systemctl" --root="$root" reenable test1
8d419f
+"$systemctl" --root="$root" reenable test1 && { echo "Expected failure" >&2; exit 1; }
8d419f
 test -h "$root/etc/systemd/system/default.target.wants/test1.service"
8d419f
 test ! -e "$root/etc/systemd/system/test1-goodalias.service"
8d419f
 test -h "$root/etc/systemd/system/test1-goodalias.service"
8d419f
@@ -328,7 +336,7 @@ Alias=link4alias.service
8d419f
 Alias=link4alias2.service
8d419f
 EOF
8d419f
 
8d419f
-"$systemctl" --root="$root" enable 'link4.service'
8d419f
+"$systemctl" --root="$root" enable 'link4.service' && { echo "Expected failure" >&2; exit 1; }
8d419f
 test ! -h "$root/etc/systemd/system/link4.service"  # this is our file
8d419f
 test ! -h "$root/etc/systemd/system/link4@.service"
8d419f
 test ! -h "$root/etc/systemd/system/link4@inst.service"
8d419f
@@ -343,18 +351,20 @@ test ! -h "$root/etc/systemd/system/link4alias.service"
8d419f
 test ! -h "$root/etc/systemd/system/link4alias2.service"
8d419f
 
8d419f
 : -------systemctl enable on path to unit file----------------
8d419f
+cat >"$root/etc/systemd/system/link4.service" <
8d419f
+[Install]
8d419f
+Alias=link4alias.service
8d419f
+Alias=link4alias2.service
8d419f
+EOF
8d419f
+
8d419f
 # Apparently this works. I'm not sure what to think.
8d419f
 "$systemctl" --root="$root" enable '/etc/systemd/system/link4.service'
8d419f
 test ! -h "$root/etc/systemd/system/link4.service"  # this is our file
8d419f
-test ! -h "$root/etc/systemd/system/link4@.service"
8d419f
-test ! -h "$root/etc/systemd/system/link4@inst.service"
8d419f
 islink "$root/etc/systemd/system/link4alias.service" "/etc/systemd/system/link4.service"
8d419f
 islink "$root/etc/systemd/system/link4alias2.service" "/etc/systemd/system/link4.service"
8d419f
 
8d419f
 "$systemctl" --root="$root" disable '/etc/systemd/system/link4.service'
8d419f
 test ! -h "$root/etc/systemd/system/link4.service"
8d419f
-test ! -h "$root/etc/systemd/system/link4@.service"
8d419f
-test ! -h "$root/etc/systemd/system/link4@inst.service"
8d419f
 test ! -h "$root/etc/systemd/system/link4alias.service"
8d419f
 test ! -h "$root/etc/systemd/system/link4alias2.service"
8d419f
 
8d419f
@@ -364,25 +374,18 @@ cat >"$root/etc/systemd/system/link5.service" <
8d419f
 [Install]
8d419f
 # FIXME: self-alias should be ignored
8d419f
 # Alias=link5.service
8d419f
-Alias=link5@.service
8d419f
-Alias=link5@inst.service
8d419f
 Alias=link5alias.service
8d419f
 Alias=link5alias2.service
8d419f
 EOF
8d419f
 
8d419f
 "$systemctl" --root="$root" enable 'link5.service'
8d419f
 test ! -h "$root/etc/systemd/system/link5.service"  # this is our file
8d419f
-test ! -h "$root/etc/systemd/system/link5@.service"
8d419f
-test ! -h "$root/etc/systemd/system/link5@inst.service"
8d419f
 # FIXME/CLARIFYME: will systemd think that link5alias2, link5alias, link5 are all aliases?
8d419f
 # https://github.com/systemd/systemd/issues/661#issuecomment-1057931149
8d419f
 islink "$root/etc/systemd/system/link5alias.service" "/etc/systemd/system/link5.service"
8d419f
 islink "$root/etc/systemd/system/link5alias2.service" "/etc/systemd/system/link5.service"
8d419f
 
8d419f
 "$systemctl" --root="$root" disable 'link5.service'
8d419f
-test ! -h "$root/etc/systemd/system/link5.service"
8d419f
-test ! -h "$root/etc/systemd/system/link5@.service"
8d419f
-test ! -h "$root/etc/systemd/system/link5@inst.service"
8d419f
 test ! -h "$root/etc/systemd/system/link5alias.service"
8d419f
 test ! -h "$root/etc/systemd/system/link5alias2.service"
8d419f
 
8d419f
@@ -528,8 +531,6 @@ check_alias % '%' && { echo "Expected failure because % is not legal in unit nam
8d419f
 
8d419f
 check_alias z 'z' && { echo "Expected failure because %z is not known" >&2; exit 1; }
8d419f
 
8d419f
-# FIXME: if there's an invalid Alias=, we shouldn't preach about empty [Install]
8d419f
-
8d419f
 # TODO: repeat the tests above for presets
8d419f
 
8d419f
 : -------SYSTEMD_OS_RELEASE relative to root------------------