mirror of
https://github.com/9technologygroup/patchmon.net.git
synced 2025-10-22 23:32:03 +00:00
Improved detection logic and upgrade mechanism using intermeditary script
This commit is contained in:
@@ -80,171 +80,6 @@ load_legacy_credentials() {
|
||||
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() {
|
||||
@@ -274,74 +109,6 @@ remove_cron_entries() {
|
||||
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)
|
||||
cleanup_legacy_files() {
|
||||
@@ -376,11 +143,10 @@ show_migration_summary() {
|
||||
echo "✅ Successfully migrated from bash agent to Go agent"
|
||||
echo ""
|
||||
echo "What was done:"
|
||||
echo " • Converted credentials to YAML format"
|
||||
echo " • Created Go agent configuration"
|
||||
echo " • Downloaded and installed Go agent binary"
|
||||
echo " • Installed and started systemd service"
|
||||
echo " • Verified service is running and connected"
|
||||
echo " • Loaded legacy credentials"
|
||||
echo " • Downloaded and ran PatchMon install script"
|
||||
echo " • Installed Go agent binary and systemd service"
|
||||
echo " • Verified service is running"
|
||||
echo " • Removed legacy cron entries"
|
||||
echo " • Cleaned up legacy files"
|
||||
echo ""
|
||||
@@ -466,50 +232,53 @@ perform_migration() {
|
||||
# Load legacy credentials
|
||||
load_legacy_credentials
|
||||
|
||||
# Convert credentials
|
||||
convert_credentials_to_yaml
|
||||
# Set environment variables for install script
|
||||
export API_ID="$API_ID"
|
||||
export API_KEY="$API_KEY"
|
||||
export PATCHMON_URL="$PATCHMON_SERVER"
|
||||
|
||||
# Create Go agent config
|
||||
create_go_agent_config
|
||||
# Detect architecture
|
||||
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
|
||||
local temp_binary=$(download_go_agent)
|
||||
info "Downloading and running PatchMon install script..."
|
||||
|
||||
# Install Go agent binary and service
|
||||
install_go_agent "$temp_binary"
|
||||
|
||||
# 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"
|
||||
# Download and run the install script
|
||||
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
|
||||
|
||||
# Remove cron entries
|
||||
remove_cron_entries
|
||||
success "PatchMon Go agent installed successfully"
|
||||
|
||||
# Clean up legacy files
|
||||
cleanup_legacy_files
|
||||
# Wait a moment for service to start
|
||||
sleep 3
|
||||
|
||||
# Clean up temporary directory
|
||||
cleanup_temp_directory
|
||||
|
||||
# Show summary
|
||||
show_migration_summary
|
||||
|
||||
# Run post-migration verification
|
||||
post_migration_check
|
||||
|
||||
success "Migration completed successfully!"
|
||||
# Test if the service is running
|
||||
if systemctl is-active --quiet patchmon-agent.service; then
|
||||
success "PatchMon agent service is running"
|
||||
|
||||
# Clean up legacy files
|
||||
remove_cron_entries
|
||||
cleanup_legacy_files
|
||||
|
||||
# Show summary
|
||||
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
|
||||
warning "Go agent verification failed - skipping cleanup to preserve legacy files"
|
||||
warning "You may need to manually clean up legacy files after fixing the Go agent"
|
||||
|
||||
# Show summary anyway
|
||||
show_migration_summary
|
||||
error "Failed to install PatchMon Go agent"
|
||||
fi
|
||||
|
||||
# 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");
|
||||
|
||||
// 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 =
|
||||
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.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
|
||||
router.get("/agent/version", async (_req, res) => {
|
||||
try {
|
||||
|
Reference in New Issue
Block a user