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)
This commit is contained in:
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user