git: e01f202ecf93 - main - nuageinit: implement final_message support

From: Baptiste Daroussin <bapt_at_FreeBSD.org>
Date: Sat, 06 Jun 2026 06:14:20 UTC
The branch main has been updated by bapt:

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

commit e01f202ecf9344bd6658869a869f36c5b3790384
Author:     Baptiste Daroussin <bapt@FreeBSD.org>
AuthorDate: 2026-06-05 21:03:45 +0000
Commit:     Baptiste Daroussin <bapt@FreeBSD.org>
CommitDate: 2026-06-05 21:03:45 +0000

    nuageinit: implement final_message support
---
 libexec/nuageinit/nuageinit          | 25 +++++++++++++++++++++++++
 libexec/nuageinit/tests/nuageinit.sh | 16 ++++++++++++++++
 2 files changed, 41 insertions(+)

diff --git a/libexec/nuageinit/nuageinit b/libexec/nuageinit/nuageinit
index 8a9c5c022862..1391aff13bd6 100755
--- a/libexec/nuageinit/nuageinit
+++ b/libexec/nuageinit/nuageinit
@@ -784,6 +784,30 @@ local function power_state_change(obj)
 	os.execute(cmd)
 end
 
+local function get_uptime()
+	-- Get system uptime in seconds
+	local f = io.popen("sysctl -n kern.boottime 2>/dev/null")
+	local boottime = f:read("*a")
+	f:close()
+	local sec = boottime:match("sec = (%d+)")
+	if sec then
+		return os.time() - tonumber(sec)
+	end
+	return 0
+end
+
+local function final_message(obj)
+	if obj.final_message == nil then return end
+	local msg = obj.final_message
+	if type(msg) ~= "string" then
+		nuage.warn("final_message must be a string")
+		return
+	end
+	local uptime = tostring(math.floor(get_uptime()))
+	msg = msg:gsub("%$UPTIME", uptime)
+	nuage.warn(msg, false)
+end
+
 local function chpasswd(obj)
 	if obj.chpasswd == nil then return end
 	nuage.chpasswd(obj.chpasswd)
@@ -1090,6 +1114,7 @@ elseif line == "#cloud-config" then
 		users,
 		chpasswd,
 		write_files_deferred,
+		final_message,
 		power_state_change,
 	}
 
diff --git a/libexec/nuageinit/tests/nuageinit.sh b/libexec/nuageinit/tests/nuageinit.sh
index c3c75949da65..2b4d316fd5ff 100644
--- a/libexec/nuageinit/tests/nuageinit.sh
+++ b/libexec/nuageinit/tests/nuageinit.sh
@@ -46,6 +46,7 @@ atf_test_case config2_userdata_locale
 atf_test_case config2_userdata_fqdn_and_hostname
 atf_test_case config2_userdata_write_files
 atf_test_case config2_userdata_encode_base64
+atf_test_case config2_userdata_final_message
 
 setup_test_adduser()
 {
@@ -1401,6 +1402,20 @@ config2_userdata_encode_base64_body()
 	    /usr/libexec/flua -e "print(require('nuage').encode_base64(''))"
 }
 
+config2_userdata_final_message_body()
+{
+	mkdir -p media/nuageinit
+	setup_test_adduser
+	export NUAGE_RUN_TESTS=1
+	printf "{}" > media/nuageinit/meta_data.json
+	cat > media/nuageinit/user_data << 'EOF'
+#cloud-config
+final_message: "System ready after $UPTIME seconds"
+EOF
+	atf_check -e match:"System ready after [0-9]+ seconds" \
+	    /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet
+}
+
 atf_init_test_cases()
 {
 	atf_add_test_case args
@@ -1442,4 +1457,5 @@ atf_init_test_cases()
 	atf_add_test_case config2_userdata_fqdn_and_hostname
 	atf_add_test_case config2_userdata_write_files
 	atf_add_test_case config2_userdata_encode_base64
+	atf_add_test_case config2_userdata_final_message
 }