mirror of
https://github.com/9technologygroup/patchmon.net.git
synced 2025-11-06 06:53:24 +00:00
Add force flag to bypass broken packages upon installation
This commit is contained in:
@@ -33,6 +33,7 @@ HOST_PREFIX="${HOST_PREFIX:-}"
|
|||||||
SKIP_STOPPED="${SKIP_STOPPED:-true}"
|
SKIP_STOPPED="${SKIP_STOPPED:-true}"
|
||||||
PARALLEL_INSTALL="${PARALLEL_INSTALL:-false}"
|
PARALLEL_INSTALL="${PARALLEL_INSTALL:-false}"
|
||||||
MAX_PARALLEL="${MAX_PARALLEL:-5}"
|
MAX_PARALLEL="${MAX_PARALLEL:-5}"
|
||||||
|
FORCE_INSTALL="${FORCE_INSTALL:-false}"
|
||||||
|
|
||||||
# ===== COLOR OUTPUT =====
|
# ===== COLOR OUTPUT =====
|
||||||
RED='\033[0;31m'
|
RED='\033[0;31m'
|
||||||
@@ -243,6 +244,13 @@ while IFS= read -r line; do
|
|||||||
# Install PatchMon agent in container
|
# Install PatchMon agent in container
|
||||||
info " Installing PatchMon agent..."
|
info " Installing PatchMon agent..."
|
||||||
|
|
||||||
|
# Build install URL with force flag if enabled
|
||||||
|
install_url="$PATCHMON_URL/api/v1/hosts/install"
|
||||||
|
if [[ "$FORCE_INSTALL" == "true" ]]; then
|
||||||
|
install_url="$install_url?force=true"
|
||||||
|
info " Using force mode - will bypass broken packages"
|
||||||
|
fi
|
||||||
|
|
||||||
# Reset exit code for this container
|
# Reset exit code for this container
|
||||||
install_exit_code=0
|
install_exit_code=0
|
||||||
|
|
||||||
@@ -253,7 +261,7 @@ while IFS= read -r line; do
|
|||||||
-H \"X-API-ID: $api_id\" \
|
-H \"X-API-ID: $api_id\" \
|
||||||
-H \"X-API-KEY: $api_key\" \
|
-H \"X-API-KEY: $api_key\" \
|
||||||
-o patchmon-install.sh \
|
-o patchmon-install.sh \
|
||||||
'$PATCHMON_URL/api/v1/hosts/install' && \
|
'$install_url' && \
|
||||||
bash patchmon-install.sh && \
|
bash patchmon-install.sh && \
|
||||||
rm -f patchmon-install.sh
|
rm -f patchmon-install.sh
|
||||||
" 2>&1 </dev/null) || install_exit_code=$?
|
" 2>&1 </dev/null) || install_exit_code=$?
|
||||||
|
|||||||
@@ -480,13 +480,17 @@ router.get("/proxmox-lxc", async (req, res) => {
|
|||||||
}
|
}
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
|
|
||||||
// Inject the token credentials, server URL, and curl flags into the script
|
// Check for --force parameter
|
||||||
|
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
|
||||||
const env_vars = `#!/bin/bash
|
const env_vars = `#!/bin/bash
|
||||||
# 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}"
|
||||||
export AUTO_ENROLLMENT_SECRET="${token_secret}"
|
export AUTO_ENROLLMENT_SECRET="${token_secret}"
|
||||||
export CURL_FLAGS="${curl_flags}"
|
export CURL_FLAGS="${curl_flags}"
|
||||||
|
export FORCE_INSTALL="${force_install ? "true" : "false"}"
|
||||||
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ const HostDetail = () => {
|
|||||||
const [showDeleteModal, setShowDeleteModal] = useState(false);
|
const [showDeleteModal, setShowDeleteModal] = useState(false);
|
||||||
const [showAllUpdates, setShowAllUpdates] = useState(false);
|
const [showAllUpdates, setShowAllUpdates] = useState(false);
|
||||||
const [activeTab, setActiveTab] = useState("host");
|
const [activeTab, setActiveTab] = useState("host");
|
||||||
|
const [forceInstall, setForceInstall] = useState(false);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: host,
|
data: host,
|
||||||
@@ -1083,6 +1084,7 @@ const HostDetail = () => {
|
|||||||
const CredentialsModal = ({ host, isOpen, onClose }) => {
|
const CredentialsModal = ({ host, isOpen, onClose }) => {
|
||||||
const [showApiKey, setShowApiKey] = useState(false);
|
const [showApiKey, setShowApiKey] = useState(false);
|
||||||
const [activeTab, setActiveTab] = useState("quick-install");
|
const [activeTab, setActiveTab] = useState("quick-install");
|
||||||
|
const [forceInstall, setForceInstall] = useState(false);
|
||||||
const apiIdInputId = useId();
|
const apiIdInputId = useId();
|
||||||
const apiKeyInputId = useId();
|
const apiKeyInputId = useId();
|
||||||
|
|
||||||
@@ -1104,6 +1106,12 @@ const CredentialsModal = ({ host, isOpen, onClose }) => {
|
|||||||
return settings?.ignore_ssl_self_signed ? "-sk" : "-s";
|
return settings?.ignore_ssl_self_signed ? "-sk" : "-s";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Helper function to build installation URL with optional force flag
|
||||||
|
const getInstallUrl = () => {
|
||||||
|
const baseUrl = `${serverUrl}/api/v1/hosts/install`;
|
||||||
|
return forceInstall ? `${baseUrl}?force=true` : baseUrl;
|
||||||
|
};
|
||||||
|
|
||||||
const copyToClipboard = async (text) => {
|
const copyToClipboard = async (text) => {
|
||||||
try {
|
try {
|
||||||
// Try modern clipboard API first
|
// Try modern clipboard API first
|
||||||
@@ -1197,10 +1205,30 @@ const CredentialsModal = ({ host, isOpen, onClose }) => {
|
|||||||
Copy and run this command on the target host to securely install
|
Copy and run this command on the target host to securely install
|
||||||
and configure the PatchMon agent:
|
and configure the PatchMon agent:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
{/* Force Install Toggle */}
|
||||||
|
<div className="mb-3">
|
||||||
|
<label className="flex items-center gap-2 text-sm">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={forceInstall}
|
||||||
|
onChange={(e) => setForceInstall(e.target.checked)}
|
||||||
|
className="rounded border-secondary-300 dark:border-secondary-600 text-primary-600 focus:ring-primary-500 dark:focus:ring-primary-400 dark:bg-secondary-700"
|
||||||
|
/>
|
||||||
|
<span className="text-primary-800 dark:text-primary-200">
|
||||||
|
Force install (bypass broken packages)
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<p className="text-xs text-primary-600 dark:text-primary-400 mt-1">
|
||||||
|
Enable this if the target host has broken packages
|
||||||
|
(CloudPanel, WHM, etc.) that block apt-get operations
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={`curl ${getCurlFlags()} ${serverUrl}/api/v1/hosts/install -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}" | bash`}
|
||||||
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"
|
||||||
/>
|
/>
|
||||||
@@ -1208,7 +1236,7 @@ const CredentialsModal = ({ host, isOpen, onClose }) => {
|
|||||||
type="button"
|
type="button"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
copyToClipboard(
|
copyToClipboard(
|
||||||
`curl ${getCurlFlags()} ${serverUrl}/api/v1/hosts/install -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}" | bash`,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
className="btn-primary flex items-center gap-1"
|
className="btn-primary flex items-center gap-1"
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ const Integrations = () => {
|
|||||||
const [new_token, setNewToken] = useState(null);
|
const [new_token, setNewToken] = useState(null);
|
||||||
const [show_secret, setShowSecret] = useState(false);
|
const [show_secret, setShowSecret] = useState(false);
|
||||||
const [server_url, setServerUrl] = useState("");
|
const [server_url, setServerUrl] = useState("");
|
||||||
|
const [force_proxmox_install, setForceProxmoxInstall] = useState(false);
|
||||||
|
|
||||||
// Form state
|
// Form state
|
||||||
const [form_data, setFormData] = useState({
|
const [form_data, setFormData] = useState({
|
||||||
@@ -34,6 +35,12 @@ const Integrations = () => {
|
|||||||
|
|
||||||
const [copy_success, setCopySuccess] = useState({});
|
const [copy_success, setCopySuccess] = useState({});
|
||||||
|
|
||||||
|
// Helper function to build Proxmox enrollment URL with optional force flag
|
||||||
|
const getProxmoxUrl = () => {
|
||||||
|
const baseUrl = `${server_url}/api/v1/auto-enrollment/proxmox-lxc?token_key=${new_token.token_key}&token_secret=${new_token.token_secret}`;
|
||||||
|
return force_proxmox_install ? `${baseUrl}&force=true` : baseUrl;
|
||||||
|
};
|
||||||
|
|
||||||
const handleTabChange = (tabName) => {
|
const handleTabChange = (tabName) => {
|
||||||
setActiveTab(tabName);
|
setActiveTab(tabName);
|
||||||
};
|
};
|
||||||
@@ -664,10 +671,32 @@ const Integrations = () => {
|
|||||||
Run this command on your Proxmox host to download and
|
Run this command on your Proxmox host to download and
|
||||||
execute the enrollment script:
|
execute the enrollment script:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
{/* Force Install Toggle */}
|
||||||
|
<div className="mb-3">
|
||||||
|
<label className="flex items-center gap-2 text-sm">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={force_proxmox_install}
|
||||||
|
onChange={(e) =>
|
||||||
|
setForceProxmoxInstall(e.target.checked)
|
||||||
|
}
|
||||||
|
className="rounded border-secondary-300 dark:border-secondary-600 text-primary-600 focus:ring-primary-500 dark:focus:ring-primary-400 dark:bg-secondary-700"
|
||||||
|
/>
|
||||||
|
<span className="text-secondary-800 dark:text-secondary-200">
|
||||||
|
Force install (bypass broken packages in containers)
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<p className="text-xs text-secondary-600 dark:text-secondary-400 mt-1">
|
||||||
|
Enable this if your LXC containers have broken packages
|
||||||
|
(CloudPanel, WHM, etc.) that block apt-get operations
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={`curl -s "${server_url}/api/v1/auto-enrollment/proxmox-lxc?token_key=${new_token.token_key}&token_secret=${new_token.token_secret}" | bash`}
|
value={`curl -s "${getProxmoxUrl()}" | bash`}
|
||||||
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"
|
||||||
/>
|
/>
|
||||||
@@ -675,7 +704,7 @@ const Integrations = () => {
|
|||||||
type="button"
|
type="button"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
copy_to_clipboard(
|
copy_to_clipboard(
|
||||||
`curl -s "${server_url}/api/v1/auto-enrollment/proxmox-lxc?token_key=${new_token.token_key}&token_secret=${new_token.token_secret}" | bash`,
|
`curl -s "${getProxmoxUrl()}" | bash`,
|
||||||
"curl-command",
|
"curl-command",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user