git: f27b5d04f4df - stable/14 - nuageinit: runcmd should also be executed late

From: Baptiste Daroussin <bapt_at_FreeBSD.org>
Date: Mon, 23 Jun 2025 07:44:14 UTC
The branch stable/14 has been updated by bapt:

URL: https://cgit.FreeBSD.org/src/commit/?id=f27b5d04f4df8556908e9af8db28460ac4536a9f

commit f27b5d04f4df8556908e9af8db28460ac4536a9f
Author:     Baptiste Daroussin <bapt@FreeBSD.org>
AuthorDate: 2025-06-10 09:28:49 +0000
Commit:     Baptiste Daroussin <bapt@FreeBSD.org>
CommitDate: 2025-06-23 07:43:12 +0000

    nuageinit: runcmd should also be executed late
    
    Execute the runcmd specified in cloudinit at the same moment as the
    user_data script aka late in the boot process, to respect cloudinit
    specifications
    
    (cherry picked from commit 8feca60d6ee983ef3c81903675b4d9c3218c7e7a)
---
 libexec/nuageinit/nuageinit                | 13 ++++++++++---
 libexec/nuageinit/tests/nuageinit.sh       | 12 +++++++-----
 libexec/rc/rc.d/nuageinit_user_data_script |  4 ++++
 3 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/libexec/nuageinit/nuageinit b/libexec/nuageinit/nuageinit
index f2f15f0d36f0..cd5912c54975 100755
--- a/libexec/nuageinit/nuageinit
+++ b/libexec/nuageinit/nuageinit
@@ -379,11 +379,18 @@ if line == "#cloud-config" then
 		nuage.chpasswd(obj.chpasswd)
 	end
 	if obj.runcmd then
+		f = nil
 		for _, c in ipairs(obj.runcmd) do
-			if not os.execute(c) then
-				nuage.warn("Failed to execute '" .. c .. "'")
-				-- execute the next command anyway --
+			if f == nil then
+				nuage.mkdir_p(root .. "/var/cache/nuageinit")
+				f = assert(io.open(root .. "/var/cache/nuageinit/runcmds", "w"))
+				f:write("#!/bin/sh\n")
 			end
+			f:write(c .. "\n")
+		end
+		if f ~= nil then
+			f:close()
+			sys_stat.chmod(root .. "/var/cache/nuageinit/runcmds", 493)
 		end
 	end
 	if obj.packages then
diff --git a/libexec/nuageinit/tests/nuageinit.sh b/libexec/nuageinit/tests/nuageinit.sh
index be8b186d933b..3d0033a648de 100644
--- a/libexec/nuageinit/tests/nuageinit.sh
+++ b/libexec/nuageinit/tests/nuageinit.sh
@@ -728,18 +728,20 @@ runcmd:
   - plop
 EOF
 	chmod 755 "${PWD}"/media/nuageinit/user_data
-	atf_check -s exit:0 -e inline:"sh: plop: not found\nnuageinit: Failed to execute 'plop'\n" /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
+	atf_check -s exit:0 /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
+	test -f var/cache/nuageinit/runcmds || atf_fail "File not created"
+	test -x var/cache/nuageinit/runcmds || atf_fail "Missing execution permission"
+	atf_check -o inline:"#!/bin/sh\nplop\n" cat var/cache/nuageinit/runcmds
 
 	cat > media/nuageinit/user_data << 'EOF'
 #cloud-config
 runcmd:
-  - echo "yeah!" > "${PWD}"/media/nuageinit/runcmd_echo
-  - uname -s > "${PWD}"/media/nuageinit/runcmd_uname
+  - echo "yeah!"
+  - uname -s
 EOF
 	chmod 755 "${PWD}"/media/nuageinit/user_data
 	atf_check /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
-	atf_check -s exit:0 -o inline:"yeah!\n" cat "${PWD}"/media/nuageinit/runcmd_echo
-	atf_check -s exit:0 -o inline:"FreeBSD\n" cat "${PWD}"/media/nuageinit/runcmd_uname
+	atf_check -o inline:"#!/bin/sh\necho \"yeah!\"\nuname -s\n" cat var/cache/nuageinit/runcmds
 }
 
 config2_userdata_packages_head()
diff --git a/libexec/rc/rc.d/nuageinit_user_data_script b/libexec/rc/rc.d/nuageinit_user_data_script
index 94d5d008a7fc..97ccc45f8658 100755
--- a/libexec/rc/rc.d/nuageinit_user_data_script
+++ b/libexec/rc/rc.d/nuageinit_user_data_script
@@ -15,6 +15,10 @@ rcvar="nuageinit_enable"
 
 execute_user_data_script()
 {
+	if [ -x /var/cache/nuageinit/runcmds ]; then
+		echo "Executing 'runcmd'" | tee -e /var/log/nuageinit.log
+		/var/cache/nuageinit/runcmds 2>&1 | tee -a /var/log/nuageinit.log
+	fi
 	test -x /var/cache/nuageinit/user_data || return
 	echo "Executing user_data script" | tee -a /var/log/nuageinnit.log
 	/var/cache/nuageinit/user_data 2>&1 | tee -a /var/log/nuageinit.log