mirror of
https://github.com/9technologygroup/patchmon.net.git
synced 2025-10-23 07:42:05 +00:00
Improved detection logic and upgrade mechanism using intermeditary script
This commit is contained in:
@@ -80,171 +80,6 @@ load_legacy_credentials() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Convert legacy credentials to YAML format
|
|
||||||
convert_credentials_to_yaml() {
|
|
||||||
local yaml_file="/etc/patchmon/credentials.yml"
|
|
||||||
|
|
||||||
info "Converting credentials to YAML format..."
|
|
||||||
|
|
||||||
cat > "$yaml_file" << EOF
|
|
||||||
api_id: "$API_ID"
|
|
||||||
api_key: "$API_KEY"
|
|
||||||
EOF
|
|
||||||
|
|
||||||
chmod 600 "$yaml_file"
|
|
||||||
success "Credentials converted to YAML format"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Create Go agent configuration
|
|
||||||
create_go_agent_config() {
|
|
||||||
local config_file="/etc/patchmon/config.yml"
|
|
||||||
|
|
||||||
info "Creating Go agent configuration..."
|
|
||||||
|
|
||||||
cat > "$config_file" << EOF
|
|
||||||
patchmon_server: "$PATCHMON_SERVER"
|
|
||||||
api_version: "$API_VERSION"
|
|
||||||
credentials_file: "/etc/patchmon/credentials.yml"
|
|
||||||
log_file: "/etc/patchmon/logs/patchmon-agent.log"
|
|
||||||
log_level: "info"
|
|
||||||
EOF
|
|
||||||
|
|
||||||
chmod 644 "$config_file"
|
|
||||||
success "Go agent configuration created"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Download Go agent binary
|
|
||||||
download_go_agent() {
|
|
||||||
local arch=$(uname -m)
|
|
||||||
local goos="linux"
|
|
||||||
local goarch=""
|
|
||||||
|
|
||||||
# Map architecture
|
|
||||||
case "$arch" in
|
|
||||||
"x86_64")
|
|
||||||
goarch="amd64"
|
|
||||||
;;
|
|
||||||
"i386"|"i686")
|
|
||||||
goarch="386"
|
|
||||||
;;
|
|
||||||
"aarch64"|"arm64")
|
|
||||||
goarch="arm64"
|
|
||||||
;;
|
|
||||||
"armv7l"|"armv6l"|"armv5l")
|
|
||||||
goarch="arm"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
error "Unsupported architecture: $arch"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
local download_url="$PATCHMON_SERVER/api/$API_VERSION/hosts/agent/go-binary?arch=$goarch"
|
|
||||||
local temp_dir="/etc/patchmon/tmp"
|
|
||||||
local temp_binary="$temp_dir/patchmon-agent-new"
|
|
||||||
|
|
||||||
# Create temp directory if it doesn't exist
|
|
||||||
mkdir -p "$temp_dir"
|
|
||||||
|
|
||||||
info "Downloading Go agent binary for $goos-$goarch..."
|
|
||||||
|
|
||||||
# Download with API credentials
|
|
||||||
if curl $CURL_FLAGS -H "X-API-ID: $API_ID" -H "X-API-KEY: $API_KEY" \
|
|
||||||
-o "$temp_binary" "$download_url"; then
|
|
||||||
|
|
||||||
# Verify binary - check if it's a valid executable
|
|
||||||
chmod +x "$temp_binary"
|
|
||||||
|
|
||||||
# Check if file exists and is executable
|
|
||||||
if [[ -f "$temp_binary" ]] && [[ -x "$temp_binary" ]]; then
|
|
||||||
success "Go agent binary downloaded successfully"
|
|
||||||
echo "$temp_binary"
|
|
||||||
else
|
|
||||||
# Try to get more info about the file
|
|
||||||
local file_output=$(file "$temp_binary" 2>/dev/null || echo "unknown")
|
|
||||||
rm -f "$temp_binary" # Clean up failed download
|
|
||||||
error "Downloaded file is not executable. File info: $file_output"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
rm -f "$temp_binary" # Clean up failed download
|
|
||||||
error "Failed to download Go agent binary"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Install Go agent binary and service
|
|
||||||
install_go_agent() {
|
|
||||||
local temp_binary="$1"
|
|
||||||
local install_path="/usr/local/bin/patchmon-agent"
|
|
||||||
|
|
||||||
# Check if temp_binary is provided and exists
|
|
||||||
if [[ -z "$temp_binary" ]] || [[ ! -f "$temp_binary" ]]; then
|
|
||||||
error "No valid binary provided for installation"
|
|
||||||
fi
|
|
||||||
|
|
||||||
info "Installing Go agent binary..."
|
|
||||||
|
|
||||||
# Create backup of current script if it exists
|
|
||||||
if [[ -f "/usr/local/bin/patchmon-agent.sh" ]]; then
|
|
||||||
local backup_path="/usr/local/bin/patchmon-agent.sh.backup.$(date +%Y%m%d_%H%M%S)"
|
|
||||||
cp "/usr/local/bin/patchmon-agent.sh" "$backup_path"
|
|
||||||
info "Backed up legacy script to: $backup_path"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Install new binary
|
|
||||||
mv "$temp_binary" "$install_path"
|
|
||||||
success "Go agent binary installed to: $install_path"
|
|
||||||
|
|
||||||
# Clean up the temporary file (it's now moved, so this is just safety)
|
|
||||||
rm -f "$temp_binary"
|
|
||||||
|
|
||||||
# Install and start systemd service
|
|
||||||
install_systemd_service
|
|
||||||
}
|
|
||||||
|
|
||||||
# Install and start systemd service
|
|
||||||
install_systemd_service() {
|
|
||||||
info "Installing systemd service..."
|
|
||||||
|
|
||||||
# Create systemd service file
|
|
||||||
cat > /etc/systemd/system/patchmon-agent.service << EOF
|
|
||||||
[Unit]
|
|
||||||
Description=PatchMon Agent
|
|
||||||
After=network.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
User=root
|
|
||||||
ExecStart=/usr/local/bin/patchmon-agent serve
|
|
||||||
Restart=always
|
|
||||||
RestartSec=5
|
|
||||||
StandardOutput=journal
|
|
||||||
StandardError=journal
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# Reload systemd and enable service
|
|
||||||
systemctl daemon-reload
|
|
||||||
systemctl enable patchmon-agent.service
|
|
||||||
|
|
||||||
# Start the service
|
|
||||||
info "Starting PatchMon agent service..."
|
|
||||||
if systemctl start patchmon-agent.service; then
|
|
||||||
success "PatchMon agent service started successfully"
|
|
||||||
|
|
||||||
# Wait a moment for service to start
|
|
||||||
sleep 3
|
|
||||||
|
|
||||||
# Check if service is running
|
|
||||||
if systemctl is-active --quiet patchmon-agent.service; then
|
|
||||||
success "PatchMon agent service is running"
|
|
||||||
else
|
|
||||||
warning "PatchMon agent service failed to start"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
warning "Failed to start PatchMon agent service"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Remove cron entries
|
# Remove cron entries
|
||||||
remove_cron_entries() {
|
remove_cron_entries() {
|
||||||
@@ -274,74 +109,6 @@ remove_cron_entries() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Configure Go agent
|
|
||||||
configure_go_agent() {
|
|
||||||
info "Configuring Go agent..."
|
|
||||||
|
|
||||||
# Create necessary directories
|
|
||||||
mkdir -p /etc/patchmon/logs
|
|
||||||
|
|
||||||
# Check if the Go agent binary exists
|
|
||||||
if [[ ! -f "/usr/local/bin/patchmon-agent" ]]; then
|
|
||||||
warning "Go agent binary not found at /usr/local/bin/patchmon-agent"
|
|
||||||
warning "Configuration files were created manually"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Configure credentials
|
|
||||||
if ! /usr/local/bin/patchmon-agent config set-credentials "$API_ID" "$API_KEY"; then
|
|
||||||
warning "Failed to configure credentials via CLI, but files were created manually"
|
|
||||||
fi
|
|
||||||
|
|
||||||
success "Go agent configured"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Test Go agent
|
|
||||||
test_go_agent() {
|
|
||||||
info "Testing Go agent..."
|
|
||||||
|
|
||||||
# Check if the Go agent binary exists
|
|
||||||
if [[ ! -f "/usr/local/bin/patchmon-agent" ]]; then
|
|
||||||
warning "Go agent binary not found - skipping tests"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Wait a bit for service to fully start
|
|
||||||
sleep 2
|
|
||||||
|
|
||||||
# Test service status
|
|
||||||
if systemctl is-active --quiet patchmon-agent.service; then
|
|
||||||
success "PatchMon agent service is running"
|
|
||||||
else
|
|
||||||
warning "PatchMon agent service is not running"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Test configuration
|
|
||||||
if /usr/local/bin/patchmon-agent config show >/dev/null 2>&1; then
|
|
||||||
success "Go agent configuration test passed"
|
|
||||||
else
|
|
||||||
warning "Go agent configuration test failed, but continuing..."
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Test connectivity (ping test)
|
|
||||||
info "Testing connectivity to PatchMon server..."
|
|
||||||
if /usr/local/bin/patchmon-agent ping >/dev/null 2>&1; then
|
|
||||||
success "Go agent connectivity test passed - server is reachable"
|
|
||||||
else
|
|
||||||
warning "Go agent connectivity test failed - server may be unreachable"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Clean up temporary directory
|
|
||||||
cleanup_temp_directory() {
|
|
||||||
info "Cleaning up temporary files..."
|
|
||||||
|
|
||||||
local temp_dir="/etc/patchmon/tmp"
|
|
||||||
if [[ -d "$temp_dir" ]]; then
|
|
||||||
rm -rf "$temp_dir"
|
|
||||||
success "Temporary directory cleaned up"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Clean up legacy files (only after successful verification)
|
# Clean up legacy files (only after successful verification)
|
||||||
cleanup_legacy_files() {
|
cleanup_legacy_files() {
|
||||||
@@ -376,11 +143,10 @@ show_migration_summary() {
|
|||||||
echo "✅ Successfully migrated from bash agent to Go agent"
|
echo "✅ Successfully migrated from bash agent to Go agent"
|
||||||
echo ""
|
echo ""
|
||||||
echo "What was done:"
|
echo "What was done:"
|
||||||
echo " • Converted credentials to YAML format"
|
echo " • Loaded legacy credentials"
|
||||||
echo " • Created Go agent configuration"
|
echo " • Downloaded and ran PatchMon install script"
|
||||||
echo " • Downloaded and installed Go agent binary"
|
echo " • Installed Go agent binary and systemd service"
|
||||||
echo " • Installed and started systemd service"
|
echo " • Verified service is running"
|
||||||
echo " • Verified service is running and connected"
|
|
||||||
echo " • Removed legacy cron entries"
|
echo " • Removed legacy cron entries"
|
||||||
echo " • Cleaned up legacy files"
|
echo " • Cleaned up legacy files"
|
||||||
echo ""
|
echo ""
|
||||||
@@ -466,50 +232,53 @@ perform_migration() {
|
|||||||
# Load legacy credentials
|
# Load legacy credentials
|
||||||
load_legacy_credentials
|
load_legacy_credentials
|
||||||
|
|
||||||
# Convert credentials
|
# Set environment variables for install script
|
||||||
convert_credentials_to_yaml
|
export API_ID="$API_ID"
|
||||||
|
export API_KEY="$API_KEY"
|
||||||
|
export PATCHMON_URL="$PATCHMON_SERVER"
|
||||||
|
|
||||||
# Create Go agent config
|
# Detect architecture
|
||||||
create_go_agent_config
|
local arch=$(uname -m)
|
||||||
|
local goarch=""
|
||||||
|
case "$arch" in
|
||||||
|
"x86_64") goarch="amd64" ;;
|
||||||
|
"i386"|"i686") goarch="386" ;;
|
||||||
|
"aarch64"|"arm64") goarch="arm64" ;;
|
||||||
|
"armv7l"|"armv6l"|"armv5l") goarch="arm" ;;
|
||||||
|
*) error "Unsupported architecture: $arch" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
# Download Go agent
|
info "Downloading and running PatchMon install script..."
|
||||||
local temp_binary=$(download_go_agent)
|
|
||||||
|
|
||||||
# Install Go agent binary and service
|
# Download and run the install script
|
||||||
install_go_agent "$temp_binary"
|
if curl $CURL_FLAGS -H "X-API-ID: $API_ID" -H "X-API-KEY: $API_KEY" \
|
||||||
|
"$PATCHMON_SERVER/api/v1/hosts/install?arch=$goarch" | bash; then
|
||||||
# Configure Go agent
|
|
||||||
configure_go_agent
|
|
||||||
|
|
||||||
# Test Go agent (including service and connectivity)
|
|
||||||
test_go_agent
|
|
||||||
|
|
||||||
# Only proceed with cleanup if tests pass
|
|
||||||
if systemctl is-active --quiet patchmon-agent.service && /usr/local/bin/patchmon-agent ping >/dev/null 2>&1; then
|
|
||||||
success "Go agent is running and connected - proceeding with cleanup"
|
|
||||||
|
|
||||||
# Remove cron entries
|
success "PatchMon Go agent installed successfully"
|
||||||
remove_cron_entries
|
|
||||||
|
|
||||||
# Clean up legacy files
|
# Wait a moment for service to start
|
||||||
cleanup_legacy_files
|
sleep 3
|
||||||
|
|
||||||
# Clean up temporary directory
|
# Test if the service is running
|
||||||
cleanup_temp_directory
|
if systemctl is-active --quiet patchmon-agent.service; then
|
||||||
|
success "PatchMon agent service is running"
|
||||||
# Show summary
|
|
||||||
show_migration_summary
|
# Clean up legacy files
|
||||||
|
remove_cron_entries
|
||||||
# Run post-migration verification
|
cleanup_legacy_files
|
||||||
post_migration_check
|
|
||||||
|
# Show summary
|
||||||
success "Migration completed successfully!"
|
show_migration_summary
|
||||||
|
post_migration_check
|
||||||
|
|
||||||
|
success "Migration completed successfully!"
|
||||||
|
else
|
||||||
|
warning "PatchMon agent service failed to start"
|
||||||
|
warning "Legacy files preserved for debugging"
|
||||||
|
show_migration_summary
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
warning "Go agent verification failed - skipping cleanup to preserve legacy files"
|
error "Failed to install PatchMon Go agent"
|
||||||
warning "You may need to manually clean up legacy files after fixing the Go agent"
|
|
||||||
|
|
||||||
# Show summary anyway
|
|
||||||
show_migration_summary
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Exit here to prevent the legacy script from continuing
|
# Exit here to prevent the legacy script from continuing
|
||||||
|
@@ -38,10 +38,11 @@ router.get("/agent/download", async (req, res) => {
|
|||||||
const path = require("node:path");
|
const path = require("node:path");
|
||||||
|
|
||||||
// Check if this is a legacy agent (bash script) requesting update
|
// Check if this is a legacy agent (bash script) requesting update
|
||||||
// Legacy agents will have agent_version < 1.3.0
|
// Legacy agents will have agent_version < 1.2.9 (excluding 1.2.9 itself)
|
||||||
const isLegacyAgent =
|
const isLegacyAgent =
|
||||||
host.agent_version &&
|
host.agent_version &&
|
||||||
(host.agent_version.startsWith("1.2.") ||
|
((host.agent_version.startsWith("1.2.") &&
|
||||||
|
host.agent_version !== "1.2.9") ||
|
||||||
host.agent_version.startsWith("1.1.") ||
|
host.agent_version.startsWith("1.1.") ||
|
||||||
host.agent_version.startsWith("1.0."));
|
host.agent_version.startsWith("1.0."));
|
||||||
|
|
||||||
@@ -118,72 +119,6 @@ router.get("/agent/download", async (req, res) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Endpoint to download Go agent binary (for migration script)
|
|
||||||
router.get("/agent/go-binary", async (req, res) => {
|
|
||||||
try {
|
|
||||||
// Verify API credentials
|
|
||||||
const apiId = req.headers["x-api-id"];
|
|
||||||
const apiKey = req.headers["x-api-key"];
|
|
||||||
|
|
||||||
if (!apiId || !apiKey) {
|
|
||||||
return res.status(401).json({ error: "API credentials required" });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate API credentials
|
|
||||||
const host = await prisma.hosts.findUnique({
|
|
||||||
where: { api_id: apiId },
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!host || host.api_key !== apiKey) {
|
|
||||||
return res.status(401).json({ error: "Invalid API credentials" });
|
|
||||||
}
|
|
||||||
|
|
||||||
const fs = require("node:fs");
|
|
||||||
const path = require("node:path");
|
|
||||||
|
|
||||||
// Get architecture parameter (default to amd64)
|
|
||||||
const architecture = req.query.arch || "amd64";
|
|
||||||
|
|
||||||
// Validate architecture
|
|
||||||
const validArchitectures = ["amd64", "386", "arm64", "arm"];
|
|
||||||
if (!validArchitectures.includes(architecture)) {
|
|
||||||
return res.status(400).json({
|
|
||||||
error: "Invalid architecture. Must be one of: amd64, 386, arm64, arm",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const binaryName = `patchmon-agent-linux-${architecture}`;
|
|
||||||
const binaryPath = path.join(__dirname, "../../../agents", binaryName);
|
|
||||||
|
|
||||||
if (!fs.existsSync(binaryPath)) {
|
|
||||||
return res.status(404).json({
|
|
||||||
error: `Agent binary not found for architecture: ${architecture}`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set appropriate headers for binary download
|
|
||||||
res.setHeader("Content-Type", "application/octet-stream");
|
|
||||||
res.setHeader(
|
|
||||||
"Content-Disposition",
|
|
||||||
`attachment; filename="${binaryName}"`,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Stream the binary file
|
|
||||||
const fileStream = fs.createReadStream(binaryPath);
|
|
||||||
fileStream.pipe(res);
|
|
||||||
|
|
||||||
fileStream.on("error", (error) => {
|
|
||||||
console.error("Binary stream error:", error);
|
|
||||||
if (!res.headersSent) {
|
|
||||||
res.status(500).json({ error: "Failed to stream agent binary" });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Go binary download error:", error);
|
|
||||||
res.status(500).json({ error: "Failed to serve Go agent binary" });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Version check endpoint for agents
|
// Version check endpoint for agents
|
||||||
router.get("/agent/version", async (_req, res) => {
|
router.get("/agent/version", async (_req, res) => {
|
||||||
try {
|
try {
|
||||||
|
Reference in New Issue
Block a user