feat: Update 7 files
This commit is contained in:
@@ -3,10 +3,12 @@ set -uo pipefail
|
||||
|
||||
# all_status.sh - Get status and ports for all services on this server
|
||||
#
|
||||
# Usage: all_status.sh
|
||||
# Usage: all_status.sh [EXPECTED_AGENT_HASH]
|
||||
#
|
||||
# Output: JSON object with status and ports for each service
|
||||
# {
|
||||
# "agent_hash": "hash-of-remote-agent",
|
||||
# "agent_match": true|false,
|
||||
# "services": [
|
||||
# {
|
||||
# "name": "service-name",
|
||||
@@ -24,6 +26,17 @@ DROPSHELL_DIR="$(dirname "${AGENT_PATH}")"
|
||||
|
||||
SERVICES_DIR="${DROPSHELL_DIR}/services"
|
||||
|
||||
# -- Get agent hash --
|
||||
EXPECTED_HASH="${1:-}"
|
||||
LOCAL_HASH=""
|
||||
AGENT_MATCH="true"
|
||||
if [[ -f "${AGENT_PATH}/agent.hash" ]]; then
|
||||
LOCAL_HASH=$(cat "${AGENT_PATH}/agent.hash" | tr -d '[:space:]')
|
||||
fi
|
||||
if [[ -n "${EXPECTED_HASH}" && "${LOCAL_HASH}" != "${EXPECTED_HASH}" ]]; then
|
||||
AGENT_MATCH="false"
|
||||
fi
|
||||
|
||||
# -- Helper to escape JSON strings --
|
||||
json_escape() {
|
||||
local str="$1"
|
||||
@@ -37,7 +50,11 @@ json_escape() {
|
||||
}
|
||||
|
||||
# -- Start JSON output --
|
||||
echo -n '{"services":['
|
||||
echo -n '{"agent_hash":"'
|
||||
json_escape "$LOCAL_HASH"
|
||||
echo -n '","agent_match":'
|
||||
echo -n "$AGENT_MATCH"
|
||||
echo -n ',"services":['
|
||||
|
||||
first=true
|
||||
|
||||
|
||||
@@ -38,6 +38,24 @@ if [[ ! -f "${AGENT_PATH}/common.sh" ]]; then
|
||||
fi
|
||||
source "${AGENT_PATH}/common.sh"
|
||||
|
||||
# -- Check agent hash (if AGENT_HASH is provided by dropshell) --
|
||||
# Exit code 199 = agent mismatch (special code for dropshell to detect)
|
||||
if [[ -n "${AGENT_HASH:-}" ]]; then
|
||||
LOCAL_HASH_FILE="${AGENT_PATH}/agent.hash"
|
||||
if [[ -f "${LOCAL_HASH_FILE}" ]]; then
|
||||
LOCAL_HASH=$(cat "${LOCAL_HASH_FILE}" | tr -d '[:space:]')
|
||||
EXPECTED_HASH=$(echo "${AGENT_HASH}" | tr -d '[:space:]')
|
||||
if [[ "${LOCAL_HASH}" != "${EXPECTED_HASH}" ]]; then
|
||||
echo "AGENT_MISMATCH:${EXPECTED_HASH}:${LOCAL_HASH}" >&2
|
||||
exit 199
|
||||
fi
|
||||
else
|
||||
# No local hash file - agent is outdated (pre-hash version)
|
||||
echo "AGENT_MISMATCH:${AGENT_HASH}:no_hash_file" >&2
|
||||
exit 199
|
||||
fi
|
||||
fi
|
||||
|
||||
# -- Validate arguments --
|
||||
if [[ $# -lt 2 ]]; then
|
||||
echo "Usage: ds_run.sh SERVICE COMMAND [args...]" >&2
|
||||
|
||||
@@ -21,6 +21,13 @@ chmod +x "${TEMP_DIR}/dehydrate"
|
||||
# Ensure autogen directory exists
|
||||
mkdir -p "${SCRIPT_DIR}/src/autogen"
|
||||
|
||||
# Generate agent hash BEFORE dehydration
|
||||
# Hash all files in agent-remote (excluding agent.hash itself) to create a content fingerprint
|
||||
echo "Generating agent hash..."
|
||||
AGENT_HASH=$(find "${SCRIPT_DIR}/agent-remote" -type f ! -name 'agent.hash' -exec sha256sum {} \; | sort | sha256sum | cut -d' ' -f1)
|
||||
echo "${AGENT_HASH}" > "${SCRIPT_DIR}/agent-remote/agent.hash"
|
||||
echo "Agent hash: ${AGENT_HASH}"
|
||||
|
||||
# Run dehydrate from temp location
|
||||
echo "Running dehydrate from temporary location"
|
||||
"${TEMP_DIR}/dehydrate" "${SCRIPT_DIR}/agent-remote" "${SCRIPT_DIR}/src/autogen"
|
||||
|
||||
@@ -171,6 +171,13 @@ namespace dropshell
|
||||
// Run all_status.sh on the remote server to get all service statuses in one call
|
||||
std::string agent_path = remotepath(server_name, user).agent();
|
||||
std::string script_path = agent_path + "/all_status.sh";
|
||||
|
||||
// Pass expected agent hash as argument for version checking
|
||||
std::string expected_hash = get_local_agent_hash();
|
||||
if (!expected_hash.empty()) {
|
||||
script_path += " " + expected_hash;
|
||||
}
|
||||
|
||||
std::string output;
|
||||
|
||||
sCommand cmd(agent_path, script_path, {});
|
||||
@@ -185,6 +192,17 @@ namespace dropshell
|
||||
try {
|
||||
nlohmann::json json_response = nlohmann::json::parse(output);
|
||||
|
||||
// Check agent hash match
|
||||
if (json_response.contains("agent_match") && json_response["agent_match"].is_boolean()) {
|
||||
if (!json_response["agent_match"].get<bool>()) {
|
||||
std::string remote_hash = json_response.contains("agent_hash") ?
|
||||
json_response["agent_hash"].get<std::string>() : "unknown";
|
||||
warning << "Agent mismatch on " << server_name << " (remote: " << remote_hash.substr(0, 8)
|
||||
<< "..., expected: " << expected_hash.substr(0, 8) << "...)" << std::endl;
|
||||
warning << "Run 'ds install " << server_name << "' to update the agent" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (!json_response.contains("services") || !json_response["services"].is_array()) {
|
||||
debug << "Invalid JSON response from all_status.sh" << std::endl;
|
||||
return status;
|
||||
|
||||
@@ -312,6 +312,11 @@ namespace dropshell
|
||||
if (!scommand.has_value())
|
||||
return false;
|
||||
|
||||
// Add agent hash for version checking on remote
|
||||
std::string agent_hash = get_local_agent_hash();
|
||||
if (!agent_hash.empty())
|
||||
scommand->add_env_var("AGENT_HASH", agent_hash);
|
||||
|
||||
// add the extra env vars to the command
|
||||
for (const auto &[key, value] : extra_env_vars)
|
||||
scommand->add_env_var(key, value);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "output.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
|
||||
@@ -37,8 +38,31 @@ namespace dropshell
|
||||
return localpath::agent_local() + "/bb64";
|
||||
}
|
||||
|
||||
std::string agent_hash()
|
||||
{
|
||||
return localpath::agent_remote() + "/agent.hash";
|
||||
}
|
||||
|
||||
} // namespace localfile
|
||||
|
||||
std::string get_local_agent_hash()
|
||||
{
|
||||
std::string hash_file = localfile::agent_hash();
|
||||
if (!std::filesystem::exists(hash_file))
|
||||
return "";
|
||||
|
||||
std::ifstream f(hash_file);
|
||||
if (!f.is_open())
|
||||
return "";
|
||||
|
||||
std::string hash;
|
||||
std::getline(f, hash);
|
||||
// Trim whitespace
|
||||
hash.erase(0, hash.find_first_not_of(" \t\n\r"));
|
||||
hash.erase(hash.find_last_not_of(" \t\n\r") + 1);
|
||||
return hash;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
|
||||
namespace localpath
|
||||
|
||||
@@ -56,8 +56,12 @@ namespace dropshell {
|
||||
std::string server_json(const std::string &server_name);
|
||||
std::string service_env(const std::string &server_name, const std::string &service_name);
|
||||
std::string bb64();
|
||||
std::string agent_hash(); // Returns path to agent.hash file
|
||||
} // namespace localfile
|
||||
|
||||
// Get the content of the local agent hash (empty string if not found)
|
||||
std::string get_local_agent_hash();
|
||||
|
||||
namespace localpath {
|
||||
std::string dropshell_dir();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user