From nobody Sat Jun 6 06:14:21 2026 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4gXSgf3w27z6g4pM for ; Sat, 06 Jun 2026 06:14:22 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R13" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4gXSgd4K8Cz3T61 for ; Sat, 06 Jun 2026 06:14:21 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1780726461; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=kl4plYgy9NrOBwCRuCAbsA8wjPvptUA60xsEJrJRAjM=; b=uKx8unxzU0kZRPhmi+yv4nkN3HLhY05I9kOvLeE+jLp73Wd9plpUeu6np0e95/xcQ1zjfE CBo507EPOcDlUpXEIP+C+OcBB1bLSUsAfMWzhPixZMbjNDrgDn4JpDVxFmHBr9LHf01tch qTQpT9YBR8nrgNOvaot9wnYUGqk9v2kVkD8ygEXfcqPGvf6OVMs9S5K1M4zuNqd5kxP/Ti ziqc8qNP9VHTNrUPlmzA+/fueNOk4HGWlZIqNKK0uaAUFLcK6Mt3hYM13QhUjwp30UOOy/ 8TkinTuB9C4x04rJhk+k10yhRWD3pZOq0wH0/icef0Aw9dR99lDRWkYi3bMrJA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1780726461; a=rsa-sha256; cv=none; b=A9L25sl2XMDSMnHnRk2SS91kIbyVK1HmyIyjUbjwlYs5RxkcpXObHOwHNI764CnjXnM6V7 F9HfCD+F6BFxaYCCXk2ZoW3RPdNqnq5de++y5AAFALa86btgpDmlMqby74658siD1JfW38 uMxE4HXxpU9GlxDrQ10SW7WoUGJLc72MyIhd9UwxT4oAx6a0GQdxe2b9cLYhKiHqdk+Xgg wsaUNjcEoAzbXRRw2538Q7mn1d7Q9hXMbmbSvNzPhg9vRzii3IhgZTh5bnBgP6mbI4EtrA YtGsJPdCxAAZGZsWhhRBNOS8FF/2H0l2SL+EtQfJ3vCyKIOEXAL80wCH4PquHw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1780726461; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=kl4plYgy9NrOBwCRuCAbsA8wjPvptUA60xsEJrJRAjM=; b=mmttJahwVQuTaajmqCeUSWnD2ZdymtZQs/n5HlQuu2uAocFRjSCNMosh4IMzEHnYxE4ym5 JjfD0sFSV8mAnS4sn1v/F4wqs9NyrZEQcOMR/0DpLzV6KJrxNW9enQSplrl+FynWcdG39c kTCzXrAsiDJYfO068TkUSoqBHIQGJzwFwtV1mZf4novywMuFZbevl3whGDHeS/C8ZrGmj3 3vjEye9QHqWCYAmZy2INj2bX5GaOcab49vxQ5f0kByazTzI2fsFP5uJPMo/RREo5gtFCgL 9LYG0NOrlVkD5hYFHAsMlThflTd4Y/E5iD3Y1jo5x6yX7XqeJ/5h+C2+Yf02EQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4gXSgd3FWLz13ZY for ; Sat, 06 Jun 2026 06:14:21 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 270d3 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Sat, 06 Jun 2026 06:14:21 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Baptiste Daroussin Subject: git: 58653bf4d0fb - main - nuageinit: implement phone_home support List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: bapt X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 58653bf4d0fb8ccd5de146d671ec101a1df0ede0 Auto-Submitted: auto-generated Date: Sat, 06 Jun 2026 06:14:21 +0000 Message-Id: <6a23babd.270d3.43bd1e84@gitrepo.freebsd.org> The branch main has been updated by bapt: URL: https://cgit.FreeBSD.org/src/commit/?id=58653bf4d0fb8ccd5de146d671ec101a1df0ede0 commit 58653bf4d0fb8ccd5de146d671ec101a1df0ede0 Author: Baptiste Daroussin AuthorDate: 2026-06-05 21:28:25 +0000 Commit: Baptiste Daroussin CommitDate: 2026-06-05 21:28:25 +0000 nuageinit: implement phone_home support Posts instance data (hostname, instance_id, public keys) to a URL using fetch(1). Supports: - url: target URL - post: list of data items to send, or 'all' - tries: number of retry attempts (default 1) --- libexec/nuageinit/nuageinit | 91 +++++++++++++++++++++++++++++++++++- libexec/nuageinit/tests/nuageinit.sh | 33 +++++++++++++ 2 files changed, 122 insertions(+), 2 deletions(-) diff --git a/libexec/nuageinit/nuageinit b/libexec/nuageinit/nuageinit index 1391aff13bd6..8e207cae0a15 100755 --- a/libexec/nuageinit/nuageinit +++ b/libexec/nuageinit/nuageinit @@ -808,6 +808,79 @@ local function final_message(obj) nuage.warn(msg, false) end +local function phone_home(obj, metadata) + if obj.phone_home == nil then return end + local ph = obj.phone_home + if type(ph) ~= "table" then + nuage.warn("phone_home must be an object") + return + end + if not ph.url then + nuage.warn("phone_home.url is required") + return + end + local url = ph.url + local tries = ph.tries or 1 + if type(tries) ~= "number" or tries < 1 then + tries = 1 + end + + -- Collect data to post + local data = {} + local post = ph.post + if post == "all" then + post = {"pub_key_rsa", "pub_key_ecdsa", "pub_key_ed25519", + "instance_id", "hostname", "fqdn"} + end + if type(post) == "table" then + for _, key in ipairs(post) do + if key == "hostname" then + if metadata.hostname then + table.insert(data, "hostname=" .. metadata.hostname) + end + elseif key == "fqdn" then + if metadata.hostname then + table.insert(data, "fqdn=" .. metadata.hostname) + end + elseif key == "instance_id" then + if metadata.uuid then + table.insert(data, "instance_id=" .. metadata.uuid) + end + elseif key:match("^pub_key_") then + local algo = key:match("^pub_key_(.+)$") + if metadata.public_keys then + for _, k in ipairs(metadata.public_keys) do + if algo == "rsa" and k:match("^ssh%-rsa ") then + table.insert(data, key .. "=" .. nuage.encode_base64(k)) + elseif algo == "ecdsa" and k:match("^ecdsa%-") then + table.insert(data, key .. "=" .. nuage.encode_base64(k)) + elseif algo == "ed25519" and k:match("^ssh%-ed25519 ") then + table.insert(data, key .. "=" .. nuage.encode_base64(k)) + end + end + end + end + end + end + local post_data = table.concat(data, "&") + local cmd = "fetch -q -o /dev/null --post-data " .. nuage.shell_escape(post_data) + cmd = cmd .. " " .. nuage.shell_escape(url) + + if os.getenv("NUAGE_RUN_TESTS") then + print(cmd) + return + end + for i = 1, tries do + if os.execute(cmd) then + break + end + if i < tries then + -- wait 1 second before retrying + os.execute("sleep 1") + end + end +end + local function chpasswd(obj) if obj.chpasswd == nil then return end nuage.chpasswd(obj.chpasswd) @@ -973,10 +1046,23 @@ local function load_metadata(citype) nuage.err("error parsing nocloud meta-data") end return obj - elseif citype ~= "postnet" then + elseif citype == "postnet" then + -- reload metadata: try config-2 format first, then nocloud + local parser = ucl.parser() + local res, err = parser:parse_file(ni_path .. "/meta_data.json") + if res then + return parser:get_object() + end + local f = io.open(ni_path .. "/meta-data") + if f then + local obj = yaml.load(f:read("*a")) + f:close() + if obj then return obj end + end + return {} + else nuage.err("Unknown cloud init type: " .. citype) end - return {} end local function load_userdata() @@ -1114,6 +1200,7 @@ elseif line == "#cloud-config" then users, chpasswd, write_files_deferred, + phone_home, final_message, power_state_change, } diff --git a/libexec/nuageinit/tests/nuageinit.sh b/libexec/nuageinit/tests/nuageinit.sh index 2b4d316fd5ff..b225289718e6 100644 --- a/libexec/nuageinit/tests/nuageinit.sh +++ b/libexec/nuageinit/tests/nuageinit.sh @@ -47,6 +47,7 @@ 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 +atf_test_case config2_userdata_phone_home setup_test_adduser() { @@ -1416,6 +1417,37 @@ EOF /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet } +config2_userdata_phone_home_body() +{ + mkdir -p media/nuageinit + setup_test_adduser + export NUAGE_RUN_TESTS=1 + printf '{"hostname": "myhost", "uuid": "abc-123", "public_keys": ["ssh-rsa AAAAB...", "ssh-ed25519 AAAAC..."]}' > media/nuageinit/meta_data.json + cat > media/nuageinit/user_data << 'EOF' +#cloud-config +phone_home: + url: "http://example.com/endpoint" + post: + - hostname + - instance_id + tries: 1 +EOF + atf_check -o match:"fetch -q -o /dev/null --post-data 'hostname=myhost&instance_id=abc-123' 'http://example.com/endpoint'" \ + /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet + + # Test "all" post + printf '{"hostname": "myhost"}' > media/nuageinit/meta_data.json + cat > media/nuageinit/user_data << 'EOF' +#cloud-config +phone_home: + url: "http://example.com/endpoint" + post: all + tries: 1 +EOF + atf_check -o match:"fetch -q -o /dev/null --post-data 'hostname=myhost&fqdn=myhost' 'http://example.com/endpoint'" \ + /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet +} + atf_init_test_cases() { atf_add_test_case args @@ -1458,4 +1490,5 @@ atf_init_test_cases() atf_add_test_case config2_userdata_write_files atf_add_test_case config2_userdata_encode_base64 atf_add_test_case config2_userdata_final_message + atf_add_test_case config2_userdata_phone_home }