mirror of
https://github.com/9technologygroup/patchmon.net.git
synced 2025-11-12 18:06:39 +00:00
Compare commits
7 Commits
feature/ap
...
renovate/v
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
55cddea5c3 | ||
|
|
3f18074f01 | ||
|
|
ab700a3bc8 | ||
|
|
9857d7cdfc | ||
|
|
d7d47089b2 | ||
|
|
427743b81e | ||
|
|
a4922b4e54 |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,31 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# PatchMon Agent Installation Script
|
# PatchMon Agent Installation Script
|
||||||
# This script requires bash for full functionality
|
# POSIX-compliant shell script (works with dash, ash, bash, etc.)
|
||||||
# Usage: curl -s {PATCHMON_URL}/api/v1/hosts/install -H "X-API-ID: {API_ID}" -H "X-API-KEY: {API_KEY}" | sh
|
|
||||||
|
|
||||||
# Check if bash is available, if not try to install it (for Alpine Linux)
|
|
||||||
if ! command -v bash >/dev/null 2>&1; then
|
|
||||||
if command -v apk >/dev/null 2>&1; then
|
|
||||||
echo "Installing bash for script compatibility..."
|
|
||||||
apk add --no-cache bash >/dev/null 2>&1 || true
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# If bash is available and we're not already running in bash, switch to bash
|
|
||||||
# When piped, we can't re-execute easily, so we'll continue with sh
|
|
||||||
# but ensure bash is available for bash-specific features
|
|
||||||
if command -v bash >/dev/null 2>&1 && [ -z "${BASH_VERSION:-}" ]; then
|
|
||||||
# Check if we're being piped (stdin is not a terminal)
|
|
||||||
if [ -t 0 ]; then
|
|
||||||
# Direct execution, re-execute with bash
|
|
||||||
exec bash "$0" "$@"
|
|
||||||
exit $?
|
|
||||||
fi
|
|
||||||
# When piped, we continue with sh but bash is now available
|
|
||||||
# The script will use bash-specific features which should work if bash is installed
|
|
||||||
fi
|
|
||||||
|
|
||||||
# PatchMon Agent Installation Script
|
|
||||||
# Usage: curl -s {PATCHMON_URL}/api/v1/hosts/install -H "X-API-ID: {API_ID}" -H "X-API-KEY: {API_KEY}" | sh
|
# Usage: curl -s {PATCHMON_URL}/api/v1/hosts/install -H "X-API-ID: {API_ID}" -H "X-API-KEY: {API_KEY}" | sh
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
@@ -44,20 +19,20 @@ NC='\033[0m' # No Color
|
|||||||
|
|
||||||
# Functions
|
# Functions
|
||||||
error() {
|
error() {
|
||||||
echo -e "${RED}❌ ERROR: $1${NC}" >&2
|
printf "%b\n" "${RED}❌ ERROR: $1${NC}" >&2
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
info() {
|
info() {
|
||||||
echo -e "${BLUE}ℹ️ $1${NC}"
|
printf "%b\n" "${BLUE}ℹ️ $1${NC}"
|
||||||
}
|
}
|
||||||
|
|
||||||
success() {
|
success() {
|
||||||
echo -e "${GREEN}✅ $1${NC}"
|
printf "%b\n" "${GREEN}✅ $1${NC}"
|
||||||
}
|
}
|
||||||
|
|
||||||
warning() {
|
warning() {
|
||||||
echo -e "${YELLOW}⚠️ $1${NC}"
|
printf "%b\n" "${YELLOW}⚠️ $1${NC}"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check if running as root
|
# Check if running as root
|
||||||
@@ -75,7 +50,7 @@ verify_datetime() {
|
|||||||
|
|
||||||
# Display current datetime info
|
# Display current datetime info
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${BLUE}📅 Current System Date/Time:${NC}"
|
printf "%b\n" "${BLUE}📅 Current System Date/Time:${NC}"
|
||||||
echo " • Date/Time: $system_time"
|
echo " • Date/Time: $system_time"
|
||||||
echo " • Timezone: $timezone"
|
echo " • Timezone: $timezone"
|
||||||
echo ""
|
echo ""
|
||||||
@@ -93,20 +68,20 @@ verify_datetime() {
|
|||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${RED}❌ Date/time verification failed${NC}"
|
printf "%b\n" "${RED}❌ Date/time verification failed${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${YELLOW}💡 Please fix the date/time and re-run the installation script:${NC}"
|
printf "%b\n" "${YELLOW}💡 Please fix the date/time and re-run the installation script:${NC}"
|
||||||
echo " sudo timedatectl set-time 'YYYY-MM-DD HH:MM:SS'"
|
echo " sudo timedatectl set-time 'YYYY-MM-DD HH:MM:SS'"
|
||||||
echo " sudo timedatectl set-timezone 'America/New_York' # or your timezone"
|
echo " sudo timedatectl set-timezone 'America/New_York' # or your timezone"
|
||||||
echo " sudo timedatectl list-timezones # to see available timezones"
|
echo " sudo timedatectl list-timezones # to see available timezones"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${BLUE}ℹ️ After fixing the date/time, re-run this installation script.${NC}"
|
printf "%b\n" "${BLUE}ℹ️ After fixing the date/time, re-run this installation script.${NC}"
|
||||||
error "Installation cancelled - please fix date/time and re-run"
|
error "Installation cancelled - please fix date/time and re-run"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
else
|
else
|
||||||
# Non-interactive (piped from curl) - show warning and continue
|
# Non-interactive (piped from curl) - show warning and continue
|
||||||
echo -e "${YELLOW}⚠️ Non-interactive installation detected${NC}"
|
printf "%b\n" "${YELLOW}⚠️ Non-interactive installation detected${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Please verify the date/time shown above is correct."
|
echo "Please verify the date/time shown above is correct."
|
||||||
echo "If the date/time is incorrect, it may cause issues with:"
|
echo "If the date/time is incorrect, it may cause issues with:"
|
||||||
@@ -114,7 +89,7 @@ verify_datetime() {
|
|||||||
echo " • Scheduled updates"
|
echo " • Scheduled updates"
|
||||||
echo " • Data synchronization"
|
echo " • Data synchronization"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${GREEN}✅ Continuing with installation...${NC}"
|
printf "%b\n" "${GREEN}✅ Continuing with installation...${NC}"
|
||||||
success "✅ Date/time verification completed (assumed correct)"
|
success "✅ Date/time verification completed (assumed correct)"
|
||||||
echo ""
|
echo ""
|
||||||
fi
|
fi
|
||||||
@@ -211,17 +186,17 @@ export MACHINE_ID
|
|||||||
|
|
||||||
info "🚀 Starting PatchMon Agent Installation..."
|
info "🚀 Starting PatchMon Agent Installation..."
|
||||||
info "📋 Server: $PATCHMON_URL"
|
info "📋 Server: $PATCHMON_URL"
|
||||||
info "🔑 API ID: ${API_ID:0:16}..."
|
info "🔑 API ID: $(echo "$API_ID" | cut -c1-16)..."
|
||||||
info "🆔 Machine ID: ${MACHINE_ID:0:16}..."
|
info "🆔 Machine ID: $(echo "$MACHINE_ID" | cut -c1-16)..."
|
||||||
info "🏗️ Architecture: $ARCHITECTURE"
|
info "🏗️ Architecture: $ARCHITECTURE"
|
||||||
|
|
||||||
# Display diagnostic information
|
# Display diagnostic information
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${BLUE}🔧 Installation Diagnostics:${NC}"
|
printf "%b\n" "${BLUE}🔧 Installation Diagnostics:${NC}"
|
||||||
echo " • URL: $PATCHMON_URL"
|
echo " • URL: $PATCHMON_URL"
|
||||||
echo " • CURL FLAGS: $CURL_FLAGS"
|
echo " • CURL FLAGS: $CURL_FLAGS"
|
||||||
echo " • API ID: ${API_ID:0:16}..."
|
echo " • API ID: $(echo "$API_ID" | cut -c1-16)..."
|
||||||
echo " • API Key: ${API_KEY:0:16}..."
|
echo " • API Key: $(echo "$API_KEY" | cut -c1-16)..."
|
||||||
echo " • Architecture: $ARCHITECTURE"
|
echo " • Architecture: $ARCHITECTURE"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
@@ -236,52 +211,56 @@ command_exists() {
|
|||||||
|
|
||||||
# Function to install packages with error handling
|
# Function to install packages with error handling
|
||||||
install_apt_packages() {
|
install_apt_packages() {
|
||||||
local packages=("$@")
|
# Space-separated list of packages
|
||||||
local missing_packages=()
|
_packages="$*"
|
||||||
|
_missing_packages=""
|
||||||
|
|
||||||
# Check which packages are missing
|
# Check which packages are missing
|
||||||
for pkg in "${packages[@]}"; do
|
for pkg in $_packages; do
|
||||||
if ! command_exists "$pkg"; then
|
if ! command_exists "$pkg"; then
|
||||||
missing_packages+=("$pkg")
|
_missing_packages="$_missing_packages $pkg"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ ${#missing_packages[@]} -eq 0 ]; then
|
# Trim leading space
|
||||||
|
_missing_packages=$(echo "$_missing_packages" | sed 's/^ //')
|
||||||
|
|
||||||
|
if [ -z "$_missing_packages" ]; then
|
||||||
success "All required packages are already installed"
|
success "All required packages are already installed"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
info "Need to install: ${missing_packages[*]}"
|
info "Need to install: $_missing_packages"
|
||||||
|
|
||||||
# Build apt-get command based on force mode
|
# Build apt-get command based on force mode
|
||||||
local apt_cmd="apt-get install ${missing_packages[*]} -y"
|
_apt_cmd="apt-get install $_missing_packages -y"
|
||||||
|
|
||||||
if [ "$FORCE_INSTALL" = "true" ]; then
|
if [ "$FORCE_INSTALL" = "true" ]; then
|
||||||
info "Using force mode - bypassing broken packages..."
|
info "Using force mode - bypassing broken packages..."
|
||||||
apt_cmd="$apt_cmd -o APT::Get::Fix-Broken=false -o DPkg::Options::=\"--force-confold\" -o DPkg::Options::=\"--force-confdef\""
|
_apt_cmd="$_apt_cmd -o APT::Get::Fix-Broken=false -o DPkg::Options::=\"--force-confold\" -o DPkg::Options::=\"--force-confdef\""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Try to install packages
|
# Try to install packages
|
||||||
if eval "$apt_cmd" 2>&1 | tee /tmp/patchmon_apt_install.log; then
|
if eval "$_apt_cmd" 2>&1 | tee /tmp/patchmon_apt_install.log; then
|
||||||
success "Packages installed successfully"
|
success "Packages installed successfully"
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
warning "Package installation encountered issues, checking if required tools are available..."
|
warning "Package installation encountered issues, checking if required tools are available..."
|
||||||
|
|
||||||
# Verify critical dependencies are actually available
|
# Verify critical dependencies are actually available
|
||||||
local all_ok=true
|
_all_ok=true
|
||||||
for pkg in "${packages[@]}"; do
|
for pkg in $_packages; do
|
||||||
if ! command_exists "$pkg"; then
|
if ! command_exists "$pkg"; then
|
||||||
if [ "$FORCE_INSTALL" = "true" ]; then
|
if [ "$FORCE_INSTALL" = "true" ]; then
|
||||||
error "Critical dependency '$pkg' is not available even with --force. Please install manually."
|
error "Critical dependency '$pkg' is not available even with --force. Please install manually."
|
||||||
else
|
else
|
||||||
error "Critical dependency '$pkg' is not available. Try again with --force flag or install manually: apt-get install $pkg"
|
error "Critical dependency '$pkg' is not available. Try again with --force flag or install manually: apt-get install $pkg"
|
||||||
fi
|
fi
|
||||||
all_ok=false
|
_all_ok=false
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
if $all_ok; then
|
if $_all_ok; then
|
||||||
success "All required tools are available despite installation warnings"
|
success "All required tools are available despite installation warnings"
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
@@ -292,121 +271,133 @@ install_apt_packages() {
|
|||||||
|
|
||||||
# Function to check and install packages for yum/dnf
|
# Function to check and install packages for yum/dnf
|
||||||
install_yum_dnf_packages() {
|
install_yum_dnf_packages() {
|
||||||
local pkg_manager="$1"
|
_pkg_manager="$1"
|
||||||
shift
|
shift
|
||||||
local packages=("$@")
|
_packages="$*"
|
||||||
local missing_packages=()
|
_missing_packages=""
|
||||||
|
|
||||||
# Check which packages are missing
|
# Check which packages are missing
|
||||||
for pkg in "${packages[@]}"; do
|
for pkg in $_packages; do
|
||||||
if ! command_exists "$pkg"; then
|
if ! command_exists "$pkg"; then
|
||||||
missing_packages+=("$pkg")
|
_missing_packages="$_missing_packages $pkg"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ ${#missing_packages[@]} -eq 0 ]; then
|
# Trim leading space
|
||||||
|
_missing_packages=$(echo "$_missing_packages" | sed 's/^ //')
|
||||||
|
|
||||||
|
if [ -z "$_missing_packages" ]; then
|
||||||
success "All required packages are already installed"
|
success "All required packages are already installed"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
info "Need to install: ${missing_packages[*]}"
|
info "Need to install: $_missing_packages"
|
||||||
|
|
||||||
if [ "$pkg_manager" = "yum" ]; then
|
if [ "$_pkg_manager" = "yum" ]; then
|
||||||
yum install -y "${missing_packages[@]}"
|
yum install -y $_missing_packages
|
||||||
else
|
else
|
||||||
dnf install -y "${missing_packages[@]}"
|
dnf install -y $_missing_packages
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Function to check and install packages for zypper
|
# Function to check and install packages for zypper
|
||||||
install_zypper_packages() {
|
install_zypper_packages() {
|
||||||
local packages=("$@")
|
_packages="$*"
|
||||||
local missing_packages=()
|
_missing_packages=""
|
||||||
|
|
||||||
# Check which packages are missing
|
# Check which packages are missing
|
||||||
for pkg in "${packages[@]}"; do
|
for pkg in $_packages; do
|
||||||
if ! command_exists "$pkg"; then
|
if ! command_exists "$pkg"; then
|
||||||
missing_packages+=("$pkg")
|
_missing_packages="$_missing_packages $pkg"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ ${#missing_packages[@]} -eq 0 ]; then
|
# Trim leading space
|
||||||
|
_missing_packages=$(echo "$_missing_packages" | sed 's/^ //')
|
||||||
|
|
||||||
|
if [ -z "$_missing_packages" ]; then
|
||||||
success "All required packages are already installed"
|
success "All required packages are already installed"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
info "Need to install: ${missing_packages[*]}"
|
info "Need to install: $_missing_packages"
|
||||||
zypper install -y "${missing_packages[@]}"
|
zypper install -y $_missing_packages
|
||||||
}
|
}
|
||||||
|
|
||||||
# Function to check and install packages for pacman
|
# Function to check and install packages for pacman
|
||||||
install_pacman_packages() {
|
install_pacman_packages() {
|
||||||
local packages=("$@")
|
_packages="$*"
|
||||||
local missing_packages=()
|
_missing_packages=""
|
||||||
|
|
||||||
# Check which packages are missing
|
# Check which packages are missing
|
||||||
for pkg in "${packages[@]}"; do
|
for pkg in $_packages; do
|
||||||
if ! command_exists "$pkg"; then
|
if ! command_exists "$pkg"; then
|
||||||
missing_packages+=("$pkg")
|
_missing_packages="$_missing_packages $pkg"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ ${#missing_packages[@]} -eq 0 ]; then
|
# Trim leading space
|
||||||
|
_missing_packages=$(echo "$_missing_packages" | sed 's/^ //')
|
||||||
|
|
||||||
|
if [ -z "$_missing_packages" ]; then
|
||||||
success "All required packages are already installed"
|
success "All required packages are already installed"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
info "Need to install: ${missing_packages[*]}"
|
info "Need to install: $_missing_packages"
|
||||||
pacman -S --noconfirm "${missing_packages[@]}"
|
pacman -S --noconfirm $_missing_packages
|
||||||
}
|
}
|
||||||
|
|
||||||
# Function to check and install packages for apk
|
# Function to check and install packages for apk
|
||||||
install_apk_packages() {
|
install_apk_packages() {
|
||||||
local packages=("$@")
|
_packages="$*"
|
||||||
local missing_packages=()
|
_missing_packages=""
|
||||||
|
|
||||||
# Check which packages are missing
|
# Check which packages are missing
|
||||||
for pkg in "${packages[@]}"; do
|
for pkg in $_packages; do
|
||||||
if ! command_exists "$pkg"; then
|
if ! command_exists "$pkg"; then
|
||||||
missing_packages+=("$pkg")
|
_missing_packages="$_missing_packages $pkg"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ ${#missing_packages[@]} -eq 0 ]; then
|
# Trim leading space
|
||||||
|
_missing_packages=$(echo "$_missing_packages" | sed 's/^ //')
|
||||||
|
|
||||||
|
if [ -z "$_missing_packages" ]; then
|
||||||
success "All required packages are already installed"
|
success "All required packages are already installed"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
info "Need to install: ${missing_packages[*]}"
|
info "Need to install: $_missing_packages"
|
||||||
|
|
||||||
# Update package index before installation
|
# Update package index before installation
|
||||||
info "Updating package index..."
|
info "Updating package index..."
|
||||||
apk update -q || true
|
apk update -q || true
|
||||||
|
|
||||||
# Build apk command
|
# Build apk command
|
||||||
local apk_cmd="apk add --no-cache ${missing_packages[*]}"
|
_apk_cmd="apk add --no-cache $_missing_packages"
|
||||||
|
|
||||||
# Try to install packages
|
# Try to install packages
|
||||||
if eval "$apk_cmd" 2>&1 | tee /tmp/patchmon_apk_install.log; then
|
if eval "$_apk_cmd" 2>&1 | tee /tmp/patchmon_apk_install.log; then
|
||||||
success "Packages installed successfully"
|
success "Packages installed successfully"
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
warning "Package installation encountered issues, checking if required tools are available..."
|
warning "Package installation encountered issues, checking if required tools are available..."
|
||||||
|
|
||||||
# Verify critical dependencies are actually available
|
# Verify critical dependencies are actually available
|
||||||
local all_ok=true
|
_all_ok=true
|
||||||
for pkg in "${packages[@]}"; do
|
for pkg in $_packages; do
|
||||||
if ! command_exists "$pkg"; then
|
if ! command_exists "$pkg"; then
|
||||||
if [ "$FORCE_INSTALL" = "true" ]; then
|
if [ "$FORCE_INSTALL" = "true" ]; then
|
||||||
error "Critical dependency '$pkg' is not available even with --force. Please install manually."
|
error "Critical dependency '$pkg' is not available even with --force. Please install manually."
|
||||||
else
|
else
|
||||||
error "Critical dependency '$pkg' is not available. Try again with --force flag or install manually: apk add $pkg"
|
error "Critical dependency '$pkg' is not available. Try again with --force flag or install manually: apk add $pkg"
|
||||||
fi
|
fi
|
||||||
all_ok=false
|
_all_ok=false
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
if $all_ok; then
|
if $_all_ok; then
|
||||||
success "All required tools are available despite installation warnings"
|
success "All required tools are available despite installation warnings"
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
@@ -790,7 +781,7 @@ fi
|
|||||||
# Installation complete
|
# Installation complete
|
||||||
success "🎉 PatchMon Agent installation completed successfully!"
|
success "🎉 PatchMon Agent installation completed successfully!"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${GREEN}📋 Installation Summary:${NC}"
|
printf "%b\n" "${GREEN}📋 Installation Summary:${NC}"
|
||||||
echo " • Configuration directory: /etc/patchmon"
|
echo " • Configuration directory: /etc/patchmon"
|
||||||
echo " • Agent binary installed: /usr/local/bin/patchmon-agent"
|
echo " • Agent binary installed: /usr/local/bin/patchmon-agent"
|
||||||
echo " • Architecture: $ARCHITECTURE"
|
echo " • Architecture: $ARCHITECTURE"
|
||||||
@@ -810,16 +801,16 @@ echo " • Logs directory: /etc/patchmon/logs"
|
|||||||
MOVED_FILES=$(ls /etc/patchmon/credentials.yml.backup.* /etc/patchmon/config.yml.backup.* /usr/local/bin/patchmon-agent.backup.* /etc/patchmon/logs/patchmon-agent.log.old.* /usr/local/bin/patchmon-agent.sh.backup.* /etc/patchmon/credentials.backup.* 2>/dev/null || true)
|
MOVED_FILES=$(ls /etc/patchmon/credentials.yml.backup.* /etc/patchmon/config.yml.backup.* /usr/local/bin/patchmon-agent.backup.* /etc/patchmon/logs/patchmon-agent.log.old.* /usr/local/bin/patchmon-agent.sh.backup.* /etc/patchmon/credentials.backup.* 2>/dev/null || true)
|
||||||
if [ -n "$MOVED_FILES" ]; then
|
if [ -n "$MOVED_FILES" ]; then
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${YELLOW}📋 Files Moved for Fresh Installation:${NC}"
|
printf "%b\n" "${YELLOW}📋 Files Moved for Fresh Installation:${NC}"
|
||||||
echo "$MOVED_FILES" | while read -r moved_file; do
|
echo "$MOVED_FILES" | while read -r moved_file; do
|
||||||
echo " • $moved_file"
|
echo " • $moved_file"
|
||||||
done
|
done
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${BLUE}💡 Note: Old files are automatically cleaned up (keeping last 3)${NC}"
|
printf "%b\n" "${BLUE}💡 Note: Old files are automatically cleaned up (keeping last 3)${NC}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${BLUE}🔧 Management Commands:${NC}"
|
printf "%b\n" "${BLUE}🔧 Management Commands:${NC}"
|
||||||
echo " • Test connection: /usr/local/bin/patchmon-agent ping"
|
echo " • Test connection: /usr/local/bin/patchmon-agent ping"
|
||||||
echo " • Manual report: /usr/local/bin/patchmon-agent report"
|
echo " • Manual report: /usr/local/bin/patchmon-agent report"
|
||||||
echo " • Check status: /usr/local/bin/patchmon-agent diagnostics"
|
echo " • Check status: /usr/local/bin/patchmon-agent diagnostics"
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
#!/bin/bash
|
#!/bin/sh
|
||||||
|
|
||||||
# PatchMon Agent Removal Script
|
# PatchMon Agent Removal Script
|
||||||
# Usage: curl -s {PATCHMON_URL}/api/v1/hosts/remove | bash
|
# POSIX-compliant shell script (works with dash, ash, bash, etc.)
|
||||||
|
# Usage: curl -s {PATCHMON_URL}/api/v1/hosts/remove | sh
|
||||||
# This script completely removes PatchMon from the system
|
# This script completely removes PatchMon from the system
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
@@ -20,24 +21,24 @@ NC='\033[0m' # No Color
|
|||||||
|
|
||||||
# Functions
|
# Functions
|
||||||
error() {
|
error() {
|
||||||
echo -e "${RED}❌ ERROR: $1${NC}" >&2
|
printf "%b\n" "${RED}❌ ERROR: $1${NC}" >&2
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
info() {
|
info() {
|
||||||
echo -e "${BLUE}ℹ️ $1${NC}"
|
printf "%b\n" "${BLUE}ℹ️ $1${NC}"
|
||||||
}
|
}
|
||||||
|
|
||||||
success() {
|
success() {
|
||||||
echo -e "${GREEN}✅ $1${NC}"
|
printf "%b\n" "${GREEN}✅ $1${NC}"
|
||||||
}
|
}
|
||||||
|
|
||||||
warning() {
|
warning() {
|
||||||
echo -e "${YELLOW}⚠️ $1${NC}"
|
printf "%b\n" "${YELLOW}⚠️ $1${NC}"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check if running as root
|
# Check if running as root
|
||||||
if [[ $EUID -ne 0 ]]; then
|
if [ "$(id -u)" -ne 0 ]; then
|
||||||
error "This script must be run as root (use sudo)"
|
error "This script must be run as root (use sudo)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -67,7 +68,7 @@ fi
|
|||||||
|
|
||||||
# Step 3: Remove agent script
|
# Step 3: Remove agent script
|
||||||
info "📄 Removing agent script..."
|
info "📄 Removing agent script..."
|
||||||
if [[ -f "/usr/local/bin/patchmon-agent.sh" ]]; then
|
if [ -f "/usr/local/bin/patchmon-agent.sh" ]; then
|
||||||
warning "Removing agent script: /usr/local/bin/patchmon-agent.sh"
|
warning "Removing agent script: /usr/local/bin/patchmon-agent.sh"
|
||||||
rm -f /usr/local/bin/patchmon-agent.sh
|
rm -f /usr/local/bin/patchmon-agent.sh
|
||||||
success "Agent script removed"
|
success "Agent script removed"
|
||||||
@@ -77,7 +78,7 @@ fi
|
|||||||
|
|
||||||
# Step 4: Remove configuration directory and files
|
# Step 4: Remove configuration directory and files
|
||||||
info "📁 Removing configuration files..."
|
info "📁 Removing configuration files..."
|
||||||
if [[ -d "/etc/patchmon" ]]; then
|
if [ -d "/etc/patchmon" ]; then
|
||||||
warning "Removing configuration directory: /etc/patchmon"
|
warning "Removing configuration directory: /etc/patchmon"
|
||||||
|
|
||||||
# Show what's being removed
|
# Show what's being removed
|
||||||
@@ -95,7 +96,7 @@ fi
|
|||||||
|
|
||||||
# Step 5: Remove log files
|
# Step 5: Remove log files
|
||||||
info "📝 Removing log files..."
|
info "📝 Removing log files..."
|
||||||
if [[ -f "/var/log/patchmon-agent.log" ]]; then
|
if [ -f "/var/log/patchmon-agent.log" ]; then
|
||||||
warning "Removing log file: /var/log/patchmon-agent.log"
|
warning "Removing log file: /var/log/patchmon-agent.log"
|
||||||
rm -f /var/log/patchmon-agent.log
|
rm -f /var/log/patchmon-agent.log
|
||||||
success "Log file removed"
|
success "Log file removed"
|
||||||
@@ -109,29 +110,29 @@ BACKUP_COUNT=0
|
|||||||
|
|
||||||
# Count credential backups
|
# Count credential backups
|
||||||
CRED_BACKUPS=$(ls /etc/patchmon/credentials.backup.* 2>/dev/null | wc -l || echo "0")
|
CRED_BACKUPS=$(ls /etc/patchmon/credentials.backup.* 2>/dev/null | wc -l || echo "0")
|
||||||
if [[ $CRED_BACKUPS -gt 0 ]]; then
|
if [ "$CRED_BACKUPS" -gt 0 ]; then
|
||||||
BACKUP_COUNT=$((BACKUP_COUNT + CRED_BACKUPS))
|
BACKUP_COUNT=$((BACKUP_COUNT + CRED_BACKUPS))
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Count agent backups
|
# Count agent backups
|
||||||
AGENT_BACKUPS=$(ls /usr/local/bin/patchmon-agent.sh.backup.* 2>/dev/null | wc -l || echo "0")
|
AGENT_BACKUPS=$(ls /usr/local/bin/patchmon-agent.sh.backup.* 2>/dev/null | wc -l || echo "0")
|
||||||
if [[ $AGENT_BACKUPS -gt 0 ]]; then
|
if [ "$AGENT_BACKUPS" -gt 0 ]; then
|
||||||
BACKUP_COUNT=$((BACKUP_COUNT + AGENT_BACKUPS))
|
BACKUP_COUNT=$((BACKUP_COUNT + AGENT_BACKUPS))
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Count log backups
|
# Count log backups
|
||||||
LOG_BACKUPS=$(ls /var/log/patchmon-agent.log.old.* 2>/dev/null | wc -l || echo "0")
|
LOG_BACKUPS=$(ls /var/log/patchmon-agent.log.old.* 2>/dev/null | wc -l || echo "0")
|
||||||
if [[ $LOG_BACKUPS -gt 0 ]]; then
|
if [ "$LOG_BACKUPS" -gt 0 ]; then
|
||||||
BACKUP_COUNT=$((BACKUP_COUNT + LOG_BACKUPS))
|
BACKUP_COUNT=$((BACKUP_COUNT + LOG_BACKUPS))
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $BACKUP_COUNT -gt 0 ]]; then
|
if [ "$BACKUP_COUNT" -gt 0 ]; then
|
||||||
warning "Found $BACKUP_COUNT backup files"
|
warning "Found $BACKUP_COUNT backup files"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${YELLOW}📋 Backup files found:${NC}"
|
printf "%b\n" "${YELLOW}📋 Backup files found:${NC}"
|
||||||
|
|
||||||
# Show credential backups
|
# Show credential backups
|
||||||
if [[ $CRED_BACKUPS -gt 0 ]]; then
|
if [ "$CRED_BACKUPS" -gt 0 ]; then
|
||||||
echo " Credential backups:"
|
echo " Credential backups:"
|
||||||
ls /etc/patchmon/credentials.backup.* 2>/dev/null | while read -r file; do
|
ls /etc/patchmon/credentials.backup.* 2>/dev/null | while read -r file; do
|
||||||
echo " • $file"
|
echo " • $file"
|
||||||
@@ -139,7 +140,7 @@ if [[ $BACKUP_COUNT -gt 0 ]]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Show agent backups
|
# Show agent backups
|
||||||
if [[ $AGENT_BACKUPS -gt 0 ]]; then
|
if [ "$AGENT_BACKUPS" -gt 0 ]; then
|
||||||
echo " Agent script backups:"
|
echo " Agent script backups:"
|
||||||
ls /usr/local/bin/patchmon-agent.sh.backup.* 2>/dev/null | while read -r file; do
|
ls /usr/local/bin/patchmon-agent.sh.backup.* 2>/dev/null | while read -r file; do
|
||||||
echo " • $file"
|
echo " • $file"
|
||||||
@@ -147,7 +148,7 @@ if [[ $BACKUP_COUNT -gt 0 ]]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Show log backups
|
# Show log backups
|
||||||
if [[ $LOG_BACKUPS -gt 0 ]]; then
|
if [ "$LOG_BACKUPS" -gt 0 ]; then
|
||||||
echo " Log file backups:"
|
echo " Log file backups:"
|
||||||
ls /var/log/patchmon-agent.log.old.* 2>/dev/null | while read -r file; do
|
ls /var/log/patchmon-agent.log.old.* 2>/dev/null | while read -r file; do
|
||||||
echo " • $file"
|
echo " • $file"
|
||||||
@@ -155,8 +156,8 @@ if [[ $BACKUP_COUNT -gt 0 ]]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${BLUE}💡 Note: Backup files are preserved for safety${NC}"
|
printf "%b\n" "${BLUE}💡 Note: Backup files are preserved for safety${NC}"
|
||||||
echo -e "${BLUE}💡 You can remove them manually if not needed${NC}"
|
printf "%b\n" "${BLUE}💡 You can remove them manually if not needed${NC}"
|
||||||
else
|
else
|
||||||
info "No backup files found"
|
info "No backup files found"
|
||||||
fi
|
fi
|
||||||
@@ -165,16 +166,16 @@ fi
|
|||||||
info "📦 Checking for PatchMon-specific dependencies..."
|
info "📦 Checking for PatchMon-specific dependencies..."
|
||||||
if command -v jq >/dev/null 2>&1; then
|
if command -v jq >/dev/null 2>&1; then
|
||||||
warning "jq is installed (used by PatchMon)"
|
warning "jq is installed (used by PatchMon)"
|
||||||
echo -e "${BLUE}💡 Note: jq may be used by other applications${NC}"
|
printf "%b\n" "${BLUE}💡 Note: jq may be used by other applications${NC}"
|
||||||
echo -e "${BLUE}💡 Consider keeping it unless you're sure it's not needed${NC}"
|
printf "%b\n" "${BLUE}💡 Consider keeping it unless you're sure it's not needed${NC}"
|
||||||
else
|
else
|
||||||
info "jq not found"
|
info "jq not found"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if command -v curl >/dev/null 2>&1; then
|
if command -v curl >/dev/null 2>&1; then
|
||||||
warning "curl is installed (used by PatchMon)"
|
warning "curl is installed (used by PatchMon)"
|
||||||
echo -e "${BLUE}💡 Note: curl is commonly used by many applications${NC}"
|
printf "%b\n" "${BLUE}💡 Note: curl is commonly used by many applications${NC}"
|
||||||
echo -e "${BLUE}💡 Consider keeping it unless you're sure it's not needed${NC}"
|
printf "%b\n" "${BLUE}💡 Consider keeping it unless you're sure it's not needed${NC}"
|
||||||
else
|
else
|
||||||
info "curl not found"
|
info "curl not found"
|
||||||
fi
|
fi
|
||||||
@@ -183,15 +184,15 @@ fi
|
|||||||
info "🔍 Verifying removal..."
|
info "🔍 Verifying removal..."
|
||||||
REMAINING_FILES=0
|
REMAINING_FILES=0
|
||||||
|
|
||||||
if [[ -f "/usr/local/bin/patchmon-agent.sh" ]]; then
|
if [ -f "/usr/local/bin/patchmon-agent.sh" ]; then
|
||||||
REMAINING_FILES=$((REMAINING_FILES + 1))
|
REMAINING_FILES=$((REMAINING_FILES + 1))
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -d "/etc/patchmon" ]]; then
|
if [ -d "/etc/patchmon" ]; then
|
||||||
REMAINING_FILES=$((REMAINING_FILES + 1))
|
REMAINING_FILES=$((REMAINING_FILES + 1))
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -f "/var/log/patchmon-agent.log" ]]; then
|
if [ -f "/var/log/patchmon-agent.log" ]; then
|
||||||
REMAINING_FILES=$((REMAINING_FILES + 1))
|
REMAINING_FILES=$((REMAINING_FILES + 1))
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -199,15 +200,15 @@ if crontab -l 2>/dev/null | grep -q "patchmon-agent.sh"; then
|
|||||||
REMAINING_FILES=$((REMAINING_FILES + 1))
|
REMAINING_FILES=$((REMAINING_FILES + 1))
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $REMAINING_FILES -eq 0 ]]; then
|
if [ "$REMAINING_FILES" -eq 0 ]; then
|
||||||
success "✅ PatchMon has been completely removed from the system!"
|
success "✅ PatchMon has been completely removed from the system!"
|
||||||
else
|
else
|
||||||
warning "⚠️ Some PatchMon files may still remain ($REMAINING_FILES items)"
|
warning "⚠️ Some PatchMon files may still remain ($REMAINING_FILES items)"
|
||||||
echo -e "${BLUE}💡 You may need to remove them manually${NC}"
|
printf "%b\n" "${BLUE}💡 You may need to remove them manually${NC}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${GREEN}📋 Removal Summary:${NC}"
|
printf "%b\n" "${GREEN}📋 Removal Summary:${NC}"
|
||||||
echo " • Agent script: Removed"
|
echo " • Agent script: Removed"
|
||||||
echo " • Configuration files: Removed"
|
echo " • Configuration files: Removed"
|
||||||
echo " • Log files: Removed"
|
echo " • Log files: Removed"
|
||||||
@@ -215,7 +216,7 @@ echo " • Crontab entries: Removed"
|
|||||||
echo " • Running processes: Stopped"
|
echo " • Running processes: Stopped"
|
||||||
echo " • Backup files: Preserved (if any)"
|
echo " • Backup files: Preserved (if any)"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${BLUE}🔧 Manual cleanup (if needed):${NC}"
|
printf "%b\n" "${BLUE}🔧 Manual cleanup (if needed):${NC}"
|
||||||
echo " • Remove backup files: rm /etc/patchmon/credentials.backup.* /usr/local/bin/patchmon-agent.sh.backup.* /var/log/patchmon-agent.log.old.*"
|
echo " • Remove backup files: rm /etc/patchmon/credentials.backup.* /usr/local/bin/patchmon-agent.sh.backup.* /var/log/patchmon-agent.log.old.*"
|
||||||
echo " • Remove dependencies: apt remove jq curl (if not needed by other apps)"
|
echo " • Remove dependencies: apt remove jq curl (if not needed by other apps)"
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
@@ -567,7 +567,7 @@ router.get("/proxmox-lxc", async (req, res) => {
|
|||||||
const force_install = req.query.force === "true" || req.query.force === "1";
|
const force_install = req.query.force === "true" || req.query.force === "1";
|
||||||
|
|
||||||
// Inject the token credentials, server URL, curl flags, and force flag into the script
|
// Inject the token credentials, server URL, curl flags, and force flag into the script
|
||||||
const env_vars = `#!/bin/bash
|
const env_vars = `#!/bin/sh
|
||||||
# PatchMon Auto-Enrollment Configuration (Auto-generated)
|
# PatchMon Auto-Enrollment Configuration (Auto-generated)
|
||||||
export PATCHMON_URL="${server_url}"
|
export PATCHMON_URL="${server_url}"
|
||||||
export AUTO_ENROLLMENT_KEY="${token.token_key}"
|
export AUTO_ENROLLMENT_KEY="${token.token_key}"
|
||||||
|
|||||||
@@ -1682,7 +1682,7 @@ router.get("/install", async (req, res) => {
|
|||||||
const archExport = architecture
|
const archExport = architecture
|
||||||
? `export ARCHITECTURE="${architecture}"\n`
|
? `export ARCHITECTURE="${architecture}"\n`
|
||||||
: "";
|
: "";
|
||||||
const envVars = `#!/bin/bash
|
const envVars = `#!/bin/sh
|
||||||
export PATCHMON_URL="${serverUrl}"
|
export PATCHMON_URL="${serverUrl}"
|
||||||
export API_ID="${host.api_id}"
|
export API_ID="${host.api_id}"
|
||||||
export API_KEY="${host.api_key}"
|
export API_KEY="${host.api_key}"
|
||||||
@@ -1781,7 +1781,7 @@ router.get("/remove", async (_req, res) => {
|
|||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
|
|
||||||
// Prepend environment for CURL_FLAGS so script can use it if needed
|
// Prepend environment for CURL_FLAGS so script can use it if needed
|
||||||
const envPrefix = `#!/bin/bash\nexport CURL_FLAGS="${curlFlags}"\n\n`;
|
const envPrefix = `#!/bin/sh\nexport CURL_FLAGS="${curlFlags}"\n\n`;
|
||||||
script = script.replace(/^#!/, "#");
|
script = script.replace(/^#!/, "#");
|
||||||
script = envPrefix + script;
|
script = envPrefix + script;
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/react": "^18.3.14",
|
"@types/react": "^18.3.14",
|
||||||
"@types/react-dom": "^18.3.1",
|
"@types/react-dom": "^18.3.1",
|
||||||
"@vitejs/plugin-react": "^4.3.4",
|
"@vitejs/plugin-react": "^5.0.0",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"postcss": "^8.5.6",
|
"postcss": "^8.5.6",
|
||||||
"tailwindcss": "^3.4.17",
|
"tailwindcss": "^3.4.17",
|
||||||
|
|||||||
@@ -1817,7 +1817,7 @@ const CredentialsModal = ({ host, isOpen, onClose }) => {
|
|||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={`curl ${getCurlFlags()} ${getInstallUrl()} -H "X-API-ID: ${host.api_id}" -H "X-API-KEY: ${host.api_key}" | bash`}
|
value={`curl ${getCurlFlags()} ${getInstallUrl()} -H "X-API-ID: ${host.api_id}" -H "X-API-KEY: ${host.api_key}" | sh`}
|
||||||
readOnly
|
readOnly
|
||||||
className="flex-1 px-3 py-2 border border-primary-300 dark:border-primary-600 rounded-md bg-white dark:bg-secondary-800 text-sm font-mono text-secondary-900 dark:text-white"
|
className="flex-1 px-3 py-2 border border-primary-300 dark:border-primary-600 rounded-md bg-white dark:bg-secondary-800 text-sm font-mono text-secondary-900 dark:text-white"
|
||||||
/>
|
/>
|
||||||
@@ -1825,7 +1825,7 @@ const CredentialsModal = ({ host, isOpen, onClose }) => {
|
|||||||
type="button"
|
type="button"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
copyToClipboard(
|
copyToClipboard(
|
||||||
`curl ${getCurlFlags()} ${getInstallUrl()} -H "X-API-ID: ${host.api_id}" -H "X-API-KEY: ${host.api_key}" | bash`,
|
`curl ${getCurlFlags()} ${getInstallUrl()} -H "X-API-ID: ${host.api_id}" -H "X-API-KEY: ${host.api_key}" | sh`,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
className="btn-primary flex items-center gap-1"
|
className="btn-primary flex items-center gap-1"
|
||||||
@@ -1835,270 +1835,6 @@ const CredentialsModal = ({ host, isOpen, onClose }) => {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="bg-secondary-50 dark:bg-secondary-700 rounded-lg p-4">
|
|
||||||
<h4 className="text-sm font-medium text-secondary-900 dark:text-white mb-2">
|
|
||||||
Manual Installation
|
|
||||||
</h4>
|
|
||||||
<p className="text-sm text-secondary-600 dark:text-secondary-300 mb-3">
|
|
||||||
If you prefer to install manually, follow these steps:
|
|
||||||
</p>
|
|
||||||
<div className="space-y-3">
|
|
||||||
<div className="bg-white dark:bg-secondary-800 rounded-md p-3 border border-secondary-200 dark:border-secondary-600">
|
|
||||||
<h5 className="text-sm font-medium text-secondary-900 dark:text-white mb-2">
|
|
||||||
1. Create Configuration Directory
|
|
||||||
</h5>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
value="sudo mkdir -p /etc/patchmon"
|
|
||||||
readOnly
|
|
||||||
className="flex-1 px-3 py-2 border border-secondary-300 dark:border-secondary-600 rounded-md bg-white dark:bg-secondary-800 text-sm font-mono text-secondary-900 dark:text-white"
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() =>
|
|
||||||
copyToClipboard("sudo mkdir -p /etc/patchmon")
|
|
||||||
}
|
|
||||||
className="btn-secondary flex items-center gap-1"
|
|
||||||
>
|
|
||||||
<Copy className="h-4 w-4" />
|
|
||||||
Copy
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="bg-white dark:bg-secondary-800 rounded-md p-3 border border-secondary-200 dark:border-secondary-600">
|
|
||||||
<h5 className="text-sm font-medium text-secondary-900 dark:text-white mb-2">
|
|
||||||
2. Download and Install Agent Binary
|
|
||||||
</h5>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
value={`curl ${getCurlFlags()} -o /usr/local/bin/patchmon-agent ${serverUrl}/api/v1/hosts/agent/download?arch=${architecture} -H "X-API-ID: ${host.api_id}" -H "X-API-KEY: ${host.api_key}" && sudo chmod +x /usr/local/bin/patchmon-agent`}
|
|
||||||
readOnly
|
|
||||||
className="flex-1 px-3 py-2 border border-secondary-300 dark:border-secondary-600 rounded-md bg-white dark:bg-secondary-800 text-sm font-mono text-secondary-900 dark:text-white"
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() =>
|
|
||||||
copyToClipboard(
|
|
||||||
`curl ${getCurlFlags()} -o /usr/local/bin/patchmon-agent ${serverUrl}/api/v1/hosts/agent/download?arch=${architecture} -H "X-API-ID: ${host.api_id}" -H "X-API-KEY: ${host.api_key}" && sudo chmod +x /usr/local/bin/patchmon-agent`,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
className="btn-secondary flex items-center gap-1"
|
|
||||||
>
|
|
||||||
<Copy className="h-4 w-4" />
|
|
||||||
Copy
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="bg-white dark:bg-secondary-800 rounded-md p-3 border border-secondary-200 dark:border-secondary-600">
|
|
||||||
<h5 className="text-sm font-medium text-secondary-900 dark:text-white mb-2">
|
|
||||||
3. Configure Credentials
|
|
||||||
</h5>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
value={`sudo /usr/local/bin/patchmon-agent config set-api "${host.api_id}" "${host.api_key}" "${serverUrl}"`}
|
|
||||||
readOnly
|
|
||||||
className="flex-1 px-3 py-2 border border-secondary-300 dark:border-secondary-600 rounded-md bg-white dark:bg-secondary-800 text-sm font-mono text-secondary-900 dark:text-white"
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() =>
|
|
||||||
copyToClipboard(
|
|
||||||
`sudo /usr/local/bin/patchmon-agent config set-api "${host.api_id}" "${host.api_key}" "${serverUrl}"`,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
className="btn-secondary flex items-center gap-1"
|
|
||||||
>
|
|
||||||
<Copy className="h-4 w-4" />
|
|
||||||
Copy
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="bg-white dark:bg-secondary-800 rounded-md p-3 border border-secondary-200 dark:border-secondary-600">
|
|
||||||
<h5 className="text-sm font-medium text-secondary-900 dark:text-white mb-2">
|
|
||||||
4. Test Configuration
|
|
||||||
</h5>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
value="sudo /usr/local/bin/patchmon-agent ping"
|
|
||||||
readOnly
|
|
||||||
className="flex-1 px-3 py-2 border border-secondary-300 dark:border-secondary-600 rounded-md bg-white dark:bg-secondary-800 text-sm font-mono text-secondary-900 dark:text-white"
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() =>
|
|
||||||
copyToClipboard(
|
|
||||||
"sudo /usr/local/bin/patchmon-agent ping",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
className="btn-secondary flex items-center gap-1"
|
|
||||||
>
|
|
||||||
<Copy className="h-4 w-4" />
|
|
||||||
Copy
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="bg-white dark:bg-secondary-800 rounded-md p-3 border border-secondary-200 dark:border-secondary-600">
|
|
||||||
<h5 className="text-sm font-medium text-secondary-900 dark:text-white mb-2">
|
|
||||||
5. Send Initial Data
|
|
||||||
</h5>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
value="sudo /usr/local/bin/patchmon-agent report"
|
|
||||||
readOnly
|
|
||||||
className="flex-1 px-3 py-2 border border-secondary-300 dark:border-secondary-600 rounded-md bg-white dark:bg-secondary-800 text-sm font-mono text-secondary-900 dark:text-white"
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() =>
|
|
||||||
copyToClipboard(
|
|
||||||
"sudo /usr/local/bin/patchmon-agent report",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
className="btn-secondary flex items-center gap-1"
|
|
||||||
>
|
|
||||||
<Copy className="h-4 w-4" />
|
|
||||||
Copy
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="bg-white dark:bg-secondary-800 rounded-md p-3 border border-secondary-200 dark:border-secondary-600">
|
|
||||||
<h5 className="text-sm font-medium text-secondary-900 dark:text-white mb-2">
|
|
||||||
6. Create Systemd Service File
|
|
||||||
</h5>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
value={`sudo tee /etc/systemd/system/patchmon-agent.service > /dev/null << 'EOF'
|
|
||||||
[Unit]
|
|
||||||
Description=PatchMon Agent Service
|
|
||||||
After=network.target
|
|
||||||
Wants=network.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
User=root
|
|
||||||
ExecStart=/usr/local/bin/patchmon-agent serve
|
|
||||||
Restart=always
|
|
||||||
RestartSec=10
|
|
||||||
WorkingDirectory=/etc/patchmon
|
|
||||||
|
|
||||||
# Logging
|
|
||||||
StandardOutput=journal
|
|
||||||
StandardError=journal
|
|
||||||
SyslogIdentifier=patchmon-agent
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF`}
|
|
||||||
readOnly
|
|
||||||
className="flex-1 px-3 py-2 border border-secondary-300 dark:border-secondary-600 rounded-md bg-white dark:bg-secondary-800 text-sm font-mono text-secondary-900 dark:text-white"
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() =>
|
|
||||||
copyToClipboard(
|
|
||||||
`sudo tee /etc/systemd/system/patchmon-agent.service > /dev/null << 'EOF'
|
|
||||||
[Unit]
|
|
||||||
Description=PatchMon Agent Service
|
|
||||||
After=network.target
|
|
||||||
Wants=network.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
User=root
|
|
||||||
ExecStart=/usr/local/bin/patchmon-agent serve
|
|
||||||
Restart=always
|
|
||||||
RestartSec=10
|
|
||||||
WorkingDirectory=/etc/patchmon
|
|
||||||
|
|
||||||
# Logging
|
|
||||||
StandardOutput=journal
|
|
||||||
StandardError=journal
|
|
||||||
SyslogIdentifier=patchmon-agent
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF`,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
className="btn-secondary flex items-center gap-1"
|
|
||||||
>
|
|
||||||
<Copy className="h-4 w-4" />
|
|
||||||
Copy
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="bg-white dark:bg-secondary-800 rounded-md p-3 border border-secondary-200 dark:border-secondary-600">
|
|
||||||
<h5 className="text-sm font-medium text-secondary-900 dark:text-white mb-2">
|
|
||||||
7. Enable and Start Service
|
|
||||||
</h5>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
value="sudo systemctl daemon-reload && sudo systemctl enable patchmon-agent && sudo systemctl start patchmon-agent"
|
|
||||||
readOnly
|
|
||||||
className="flex-1 px-3 py-2 border border-secondary-300 dark:border-secondary-600 rounded-md bg-white dark:bg-secondary-800 text-sm font-mono text-secondary-900 dark:text-white"
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() =>
|
|
||||||
copyToClipboard(
|
|
||||||
"sudo systemctl daemon-reload && sudo systemctl enable patchmon-agent && sudo systemctl start patchmon-agent",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
className="btn-secondary flex items-center gap-1"
|
|
||||||
>
|
|
||||||
<Copy className="h-4 w-4" />
|
|
||||||
Copy
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<p className="text-xs text-secondary-600 dark:text-secondary-400 mt-2">
|
|
||||||
This will start the agent service and establish WebSocket
|
|
||||||
connection for real-time communication
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="bg-white dark:bg-secondary-800 rounded-md p-3 border border-secondary-200 dark:border-secondary-600">
|
|
||||||
<h5 className="text-sm font-medium text-secondary-900 dark:text-white mb-2">
|
|
||||||
8. Verify Service Status
|
|
||||||
</h5>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
value="sudo systemctl status patchmon-agent"
|
|
||||||
readOnly
|
|
||||||
className="flex-1 px-3 py-2 border border-secondary-300 dark:border-secondary-600 rounded-md bg-white dark:bg-secondary-800 text-sm font-mono text-secondary-900 dark:text-white"
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() =>
|
|
||||||
copyToClipboard("sudo systemctl status patchmon-agent")
|
|
||||||
}
|
|
||||||
className="btn-secondary flex items-center gap-1"
|
|
||||||
>
|
|
||||||
<Copy className="h-4 w-4" />
|
|
||||||
Copy
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<p className="text-xs text-secondary-600 dark:text-secondary-400 mt-2">
|
|
||||||
Check that the service is running and WebSocket connection
|
|
||||||
is established
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -1669,7 +1669,7 @@ const Integrations = () => {
|
|||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={`curl -s "${getProxmoxUrl()}" | bash`}
|
value={`curl -s "${getProxmoxUrl()}" | sh`}
|
||||||
readOnly
|
readOnly
|
||||||
className="flex-1 px-3 py-2 border border-secondary-300 dark:border-secondary-600 rounded-md bg-secondary-50 dark:bg-secondary-900 text-secondary-900 dark:text-white font-mono text-xs"
|
className="flex-1 px-3 py-2 border border-secondary-300 dark:border-secondary-600 rounded-md bg-secondary-50 dark:bg-secondary-900 text-secondary-900 dark:text-white font-mono text-xs"
|
||||||
/>
|
/>
|
||||||
@@ -1677,7 +1677,7 @@ const Integrations = () => {
|
|||||||
type="button"
|
type="button"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
copy_to_clipboard(
|
copy_to_clipboard(
|
||||||
`curl -s "${getProxmoxUrl()}" | bash`,
|
`curl -s "${getProxmoxUrl()}" | sh`,
|
||||||
"curl-command",
|
"curl-command",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
216
package-lock.json
generated
216
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "patchmon",
|
"name": "patchmon",
|
||||||
"version": "1.3.2",
|
"version": "1.3.3",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "patchmon",
|
"name": "patchmon",
|
||||||
"version": "1.3.2",
|
"version": "1.3.3",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"backend",
|
"backend",
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
},
|
},
|
||||||
"backend": {
|
"backend": {
|
||||||
"name": "patchmon-backend",
|
"name": "patchmon-backend",
|
||||||
"version": "1.3.2",
|
"version": "1.3.3",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@bull-board/api": "^6.13.1",
|
"@bull-board/api": "^6.13.1",
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
},
|
},
|
||||||
"frontend": {
|
"frontend": {
|
||||||
"name": "patchmon-frontend",
|
"name": "patchmon-frontend",
|
||||||
"version": "1.3.2",
|
"version": "1.3.3",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@dnd-kit/core": "^6.3.1",
|
"@dnd-kit/core": "^6.3.1",
|
||||||
@@ -83,7 +83,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/react": "^18.3.14",
|
"@types/react": "^18.3.14",
|
||||||
"@types/react-dom": "^18.3.1",
|
"@types/react-dom": "^18.3.1",
|
||||||
"@vitejs/plugin-react": "^4.3.4",
|
"@vitejs/plugin-react": "^5.0.0",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"postcss": "^8.5.6",
|
"postcss": "^8.5.6",
|
||||||
"tailwindcss": "^3.4.17",
|
"tailwindcss": "^3.4.17",
|
||||||
@@ -131,19 +131,22 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/core": {
|
"node_modules/@babel/core": {
|
||||||
"version": "7.28.4",
|
"version": "7.28.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz",
|
||||||
|
"integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.27.1",
|
"@babel/code-frame": "^7.27.1",
|
||||||
"@babel/generator": "^7.28.3",
|
"@babel/generator": "^7.28.5",
|
||||||
"@babel/helper-compilation-targets": "^7.27.2",
|
"@babel/helper-compilation-targets": "^7.27.2",
|
||||||
"@babel/helper-module-transforms": "^7.28.3",
|
"@babel/helper-module-transforms": "^7.28.3",
|
||||||
"@babel/helpers": "^7.28.4",
|
"@babel/helpers": "^7.28.4",
|
||||||
"@babel/parser": "^7.28.4",
|
"@babel/parser": "^7.28.5",
|
||||||
"@babel/template": "^7.27.2",
|
"@babel/template": "^7.27.2",
|
||||||
"@babel/traverse": "^7.28.4",
|
"@babel/traverse": "^7.28.5",
|
||||||
"@babel/types": "^7.28.4",
|
"@babel/types": "^7.28.5",
|
||||||
"@jridgewell/remapping": "^2.3.5",
|
"@jridgewell/remapping": "^2.3.5",
|
||||||
"convert-source-map": "^2.0.0",
|
"convert-source-map": "^2.0.0",
|
||||||
"debug": "^4.1.0",
|
"debug": "^4.1.0",
|
||||||
@@ -160,12 +163,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/generator": {
|
"node_modules/@babel/generator": {
|
||||||
"version": "7.28.3",
|
"version": "7.28.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz",
|
||||||
|
"integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/parser": "^7.28.3",
|
"@babel/parser": "^7.28.5",
|
||||||
"@babel/types": "^7.28.2",
|
"@babel/types": "^7.28.5",
|
||||||
"@jridgewell/gen-mapping": "^0.3.12",
|
"@jridgewell/gen-mapping": "^0.3.12",
|
||||||
"@jridgewell/trace-mapping": "^0.3.28",
|
"@jridgewell/trace-mapping": "^0.3.28",
|
||||||
"jsesc": "^3.0.2"
|
"jsesc": "^3.0.2"
|
||||||
@@ -242,7 +247,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/helper-validator-identifier": {
|
"node_modules/@babel/helper-validator-identifier": {
|
||||||
"version": "7.27.1",
|
"version": "7.28.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
|
||||||
|
"integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -270,11 +277,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/parser": {
|
"node_modules/@babel/parser": {
|
||||||
"version": "7.28.4",
|
"version": "7.28.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz",
|
||||||
|
"integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/types": "^7.28.4"
|
"@babel/types": "^7.28.5"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"parser": "bin/babel-parser.js"
|
"parser": "bin/babel-parser.js"
|
||||||
@@ -333,16 +342,18 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/traverse": {
|
"node_modules/@babel/traverse": {
|
||||||
"version": "7.28.4",
|
"version": "7.28.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz",
|
||||||
|
"integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.27.1",
|
"@babel/code-frame": "^7.27.1",
|
||||||
"@babel/generator": "^7.28.3",
|
"@babel/generator": "^7.28.5",
|
||||||
"@babel/helper-globals": "^7.28.0",
|
"@babel/helper-globals": "^7.28.0",
|
||||||
"@babel/parser": "^7.28.4",
|
"@babel/parser": "^7.28.5",
|
||||||
"@babel/template": "^7.27.2",
|
"@babel/template": "^7.27.2",
|
||||||
"@babel/types": "^7.28.4",
|
"@babel/types": "^7.28.5",
|
||||||
"debug": "^4.3.1"
|
"debug": "^4.3.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -350,12 +361,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/types": {
|
"node_modules/@babel/types": {
|
||||||
"version": "7.28.4",
|
"version": "7.28.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz",
|
||||||
|
"integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-string-parser": "^7.27.1",
|
"@babel/helper-string-parser": "^7.27.1",
|
||||||
"@babel/helper-validator-identifier": "^7.27.1"
|
"@babel/helper-validator-identifier": "^7.28.5"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
@@ -547,6 +560,7 @@
|
|||||||
"node_modules/@bull-board/ui": {
|
"node_modules/@bull-board/ui": {
|
||||||
"version": "6.13.1",
|
"version": "6.13.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@bull-board/api": "6.13.1"
|
"@bull-board/api": "6.13.1"
|
||||||
}
|
}
|
||||||
@@ -580,6 +594,7 @@
|
|||||||
"node_modules/@dnd-kit/core": {
|
"node_modules/@dnd-kit/core": {
|
||||||
"version": "6.3.1",
|
"version": "6.3.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@dnd-kit/accessibility": "^3.1.1",
|
"@dnd-kit/accessibility": "^3.1.1",
|
||||||
"@dnd-kit/utilities": "^3.2.2",
|
"@dnd-kit/utilities": "^3.2.2",
|
||||||
@@ -895,7 +910,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rolldown/pluginutils": {
|
"node_modules/@rolldown/pluginutils": {
|
||||||
"version": "1.0.0-beta.27",
|
"version": "1.0.0-beta.47",
|
||||||
|
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.47.tgz",
|
||||||
|
"integrity": "sha512-8QagwMH3kNCuzD8EWL8R2YPW5e4OrHNSAHRFDdmFqEwEaD/KcNKjVoumo+gP2vW5eKB2UPbM6vTYiGZX0ixLnw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
@@ -1020,6 +1037,7 @@
|
|||||||
"version": "18.3.24",
|
"version": "18.3.24",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/prop-types": "*",
|
"@types/prop-types": "*",
|
||||||
"csstype": "^3.0.2"
|
"csstype": "^3.0.2"
|
||||||
@@ -1038,19 +1056,21 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@vitejs/plugin-react": {
|
"node_modules/@vitejs/plugin-react": {
|
||||||
"version": "4.7.0",
|
"version": "5.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.1.1.tgz",
|
||||||
|
"integrity": "sha512-WQfkSw0QbQ5aJ2CHYw23ZGkqnRwqKHD/KYsMeTkZzPT4Jcf0DcBxBtwMJxnu6E7oxw5+JC6ZAiePgh28uJ1HBA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/core": "^7.28.0",
|
"@babel/core": "^7.28.5",
|
||||||
"@babel/plugin-transform-react-jsx-self": "^7.27.1",
|
"@babel/plugin-transform-react-jsx-self": "^7.27.1",
|
||||||
"@babel/plugin-transform-react-jsx-source": "^7.27.1",
|
"@babel/plugin-transform-react-jsx-source": "^7.27.1",
|
||||||
"@rolldown/pluginutils": "1.0.0-beta.27",
|
"@rolldown/pluginutils": "1.0.0-beta.47",
|
||||||
"@types/babel__core": "^7.20.5",
|
"@types/babel__core": "^7.20.5",
|
||||||
"react-refresh": "^0.17.0"
|
"react-refresh": "^0.18.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^14.18.0 || >=16.0.0"
|
"node": "^20.19.0 || >=22.12.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
|
"vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
|
||||||
@@ -1267,6 +1287,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"baseline-browser-mapping": "^2.8.3",
|
"baseline-browser-mapping": "^2.8.3",
|
||||||
"caniuse-lite": "^1.0.30001741",
|
"caniuse-lite": "^1.0.30001741",
|
||||||
@@ -1456,6 +1477,7 @@
|
|||||||
"node_modules/chart.js": {
|
"node_modules/chart.js": {
|
||||||
"version": "4.5.0",
|
"version": "4.5.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@kurkle/color": "^0.3.0"
|
"@kurkle/color": "^0.3.0"
|
||||||
},
|
},
|
||||||
@@ -2030,6 +2052,7 @@
|
|||||||
"node_modules/express": {
|
"node_modules/express": {
|
||||||
"version": "4.21.2",
|
"version": "4.21.2",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"accepts": "~1.3.8",
|
"accepts": "~1.3.8",
|
||||||
"array-flatten": "1.1.1",
|
"array-flatten": "1.1.1",
|
||||||
@@ -2795,6 +2818,76 @@
|
|||||||
"lefthook-windows-x64": "1.13.5"
|
"lefthook-windows-x64": "1.13.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/lefthook-darwin-arm64": {
|
||||||
|
"version": "1.13.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/lefthook-darwin-arm64/-/lefthook-darwin-arm64-1.13.5.tgz",
|
||||||
|
"integrity": "sha512-BYt5CnAOXasVCS6i+A4ljUo9xru/B5uMFD6EWHhs3R26jGF7mBSDxM3ErzXTUaJRTP0kQI/XBmgqBryBqoqZOQ==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/lefthook-darwin-x64": {
|
||||||
|
"version": "1.13.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/lefthook-darwin-x64/-/lefthook-darwin-x64-1.13.5.tgz",
|
||||||
|
"integrity": "sha512-ZDtLBzvI5e26C/RZ4irOHpELTd22x9lDTgF2+eCYcnrBWOkB7800V8tuAvBybsLGvg6JwKjFxn+NTRNZnCC2hw==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/lefthook-freebsd-arm64": {
|
||||||
|
"version": "1.13.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/lefthook-freebsd-arm64/-/lefthook-freebsd-arm64-1.13.5.tgz",
|
||||||
|
"integrity": "sha512-uQ/kQZSSedw74aGCpsfOPN4yVt3klg8grOP6gHQOCRUMv5oK/Lj3pe1PylpTuuhxWORWRzkauPMot26J0OZZdA==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"freebsd"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/lefthook-freebsd-x64": {
|
||||||
|
"version": "1.13.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/lefthook-freebsd-x64/-/lefthook-freebsd-x64-1.13.5.tgz",
|
||||||
|
"integrity": "sha512-6czek8XagVrI7ExURawkfrfX40Qjc/wktc8bLq/iXfRlmdvKDMrx2FrA82mDfEVCAEz+tTvkteK1TfR3icYF3Q==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"freebsd"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/lefthook-linux-arm64": {
|
||||||
|
"version": "1.13.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/lefthook-linux-arm64/-/lefthook-linux-arm64-1.13.5.tgz",
|
||||||
|
"integrity": "sha512-MjWtiuW1br+rpTtgG1KGV53mSGtL5MWQwgafYzrFleJ89fKb86F4TD/4mVNzk5thmZ+HVPZw9bRZGUHFBnNJWg==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
"node_modules/lefthook-linux-x64": {
|
"node_modules/lefthook-linux-x64": {
|
||||||
"version": "1.13.5",
|
"version": "1.13.5",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
@@ -2807,6 +2900,62 @@
|
|||||||
"linux"
|
"linux"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"node_modules/lefthook-openbsd-arm64": {
|
||||||
|
"version": "1.13.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/lefthook-openbsd-arm64/-/lefthook-openbsd-arm64-1.13.5.tgz",
|
||||||
|
"integrity": "sha512-lYXrWf0/hBrwtG8ceaHq886bcqRKh3Lfv+jZJs+ykMLB6L/kaqk8tA4V2NHWydQ5h56o45ugs/580nMz36ZdRg==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"openbsd"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/lefthook-openbsd-x64": {
|
||||||
|
"version": "1.13.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/lefthook-openbsd-x64/-/lefthook-openbsd-x64-1.13.5.tgz",
|
||||||
|
"integrity": "sha512-Ba1JrsRbfan4WKd8Q7gUhTxCUuppXzirDObd3JxpLRSLxA47yxhjMv7KByDunRDTvzTgsXoykZI6mPupkc1JiQ==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"openbsd"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/lefthook-windows-arm64": {
|
||||||
|
"version": "1.13.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/lefthook-windows-arm64/-/lefthook-windows-arm64-1.13.5.tgz",
|
||||||
|
"integrity": "sha512-Y/CpmEIb0hlFe+kTT/efWgX6+/gUTp5NItTF+gmUrY1/G/bTLIxdIRS7WpodVM0MEN24sOrQVTSi9DN9FvGoGg==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/lefthook-windows-x64": {
|
||||||
|
"version": "1.13.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/lefthook-windows-x64/-/lefthook-windows-x64-1.13.5.tgz",
|
||||||
|
"integrity": "sha512-WJBqGNBlFJnunRwy12QyaDHdGULtostPqpYSZSS4boFJDY0lP5qtz9lAGmJ49aA5GQ19jrnDjGLwVPFiwIqksQ==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
]
|
||||||
|
},
|
||||||
"node_modules/lilconfig": {
|
"node_modules/lilconfig": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
@@ -3419,6 +3568,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"nanoid": "^3.3.11",
|
"nanoid": "^3.3.11",
|
||||||
"picocolors": "^1.1.1",
|
"picocolors": "^1.1.1",
|
||||||
@@ -3548,6 +3698,7 @@
|
|||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/config": "6.16.2",
|
"@prisma/config": "6.16.2",
|
||||||
"@prisma/engines": "6.16.2"
|
"@prisma/engines": "6.16.2"
|
||||||
@@ -3737,6 +3888,7 @@
|
|||||||
"node_modules/react": {
|
"node_modules/react": {
|
||||||
"version": "18.3.1",
|
"version": "18.3.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"loose-envify": "^1.1.0"
|
"loose-envify": "^1.1.0"
|
||||||
},
|
},
|
||||||
@@ -3755,6 +3907,7 @@
|
|||||||
"node_modules/react-dom": {
|
"node_modules/react-dom": {
|
||||||
"version": "18.3.1",
|
"version": "18.3.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"loose-envify": "^1.1.0",
|
"loose-envify": "^1.1.0",
|
||||||
"scheduler": "^0.23.2"
|
"scheduler": "^0.23.2"
|
||||||
@@ -3771,7 +3924,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-refresh": {
|
"node_modules/react-refresh": {
|
||||||
"version": "0.17.0",
|
"version": "0.18.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz",
|
||||||
|
"integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -4472,6 +4627,7 @@
|
|||||||
"version": "4.0.3",
|
"version": "4.0.3",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
},
|
},
|
||||||
@@ -4624,6 +4780,7 @@
|
|||||||
"version": "7.1.7",
|
"version": "7.1.7",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.25.0",
|
"esbuild": "^0.25.0",
|
||||||
"fdir": "^6.5.0",
|
"fdir": "^6.5.0",
|
||||||
@@ -4713,6 +4870,7 @@
|
|||||||
"version": "4.0.3",
|
"version": "4.0.3",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user