mirror of
https://github.com/9technologygroup/patchmon.net.git
synced 2025-11-04 14:03:17 +00:00
Addded better Go agent upgradation support
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -123,35 +123,97 @@ router.get("/agent/download", async (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Version check endpoint for agents
|
// Version check endpoint for agents
|
||||||
router.get("/agent/version", async (_req, res) => {
|
router.get("/agent/version", async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const fs = require("node:fs");
|
const fs = require("node:fs");
|
||||||
const path = require("node:path");
|
const path = require("node:path");
|
||||||
|
const { exec } = require("node:child_process");
|
||||||
|
const { promisify } = require("node:util");
|
||||||
|
const execAsync = promisify(exec);
|
||||||
|
|
||||||
// Read version directly from agent script file
|
// Get architecture parameter (default to amd64 for Go agents)
|
||||||
const agentPath = path.join(__dirname, "../../../agents/patchmon-agent.sh");
|
const architecture = req.query.arch || "amd64";
|
||||||
|
const agentType = req.query.type || "go"; // "go" or "legacy"
|
||||||
|
|
||||||
if (!fs.existsSync(agentPath)) {
|
if (agentType === "legacy") {
|
||||||
return res.status(404).json({ error: "Agent script not found" });
|
// Legacy agent version check (bash script)
|
||||||
|
const agentPath = path.join(
|
||||||
|
__dirname,
|
||||||
|
"../../../agents/patchmon-agent.sh",
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!fs.existsSync(agentPath)) {
|
||||||
|
return res.status(404).json({ error: "Legacy agent script not found" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const scriptContent = fs.readFileSync(agentPath, "utf8");
|
||||||
|
const versionMatch = scriptContent.match(/AGENT_VERSION="([^"]+)"/);
|
||||||
|
|
||||||
|
if (!versionMatch) {
|
||||||
|
return res
|
||||||
|
.status(500)
|
||||||
|
.json({ error: "Could not extract version from agent script" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentVersion = versionMatch[1];
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
currentVersion: currentVersion,
|
||||||
|
downloadUrl: `/api/v1/hosts/agent/download`,
|
||||||
|
releaseNotes: `PatchMon Agent v${currentVersion}`,
|
||||||
|
minServerVersion: null,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Go agent version check (binary)
|
||||||
|
const binaryName = `patchmon-agent-linux-${architecture}`;
|
||||||
|
const binaryPath = path.join(__dirname, "../../../agents", binaryName);
|
||||||
|
|
||||||
|
if (!fs.existsSync(binaryPath)) {
|
||||||
|
return res.status(404).json({
|
||||||
|
error: `Go agent binary not found for architecture: ${architecture}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute the binary to get its version
|
||||||
|
try {
|
||||||
|
const { stdout } = await execAsync(`${binaryPath} --help`, {
|
||||||
|
timeout: 10000,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Parse version from help output (e.g., "PatchMon Agent v1.3.1")
|
||||||
|
const versionMatch = stdout.match(
|
||||||
|
/PatchMon Agent v([0-9]+\.[0-9]+\.[0-9]+)/i,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!versionMatch) {
|
||||||
|
return res.status(500).json({
|
||||||
|
error: "Could not extract version from agent binary",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const serverVersion = versionMatch[1];
|
||||||
|
const agentVersion = req.query.currentVersion || serverVersion;
|
||||||
|
|
||||||
|
// Simple version comparison (assuming semantic versioning)
|
||||||
|
const hasUpdate = agentVersion !== serverVersion;
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
currentVersion: agentVersion,
|
||||||
|
latestVersion: serverVersion,
|
||||||
|
hasUpdate: hasUpdate,
|
||||||
|
downloadUrl: `/api/v1/hosts/agent/download?arch=${architecture}`,
|
||||||
|
releaseNotes: `PatchMon Agent v${serverVersion}`,
|
||||||
|
minServerVersion: null,
|
||||||
|
architecture: architecture,
|
||||||
|
agentType: "go",
|
||||||
|
});
|
||||||
|
} catch (execError) {
|
||||||
|
console.error("Failed to execute agent binary:", execError.message);
|
||||||
|
return res.status(500).json({
|
||||||
|
error: "Failed to get version from agent binary",
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const scriptContent = fs.readFileSync(agentPath, "utf8");
|
|
||||||
const versionMatch = scriptContent.match(/AGENT_VERSION="([^"]+)"/);
|
|
||||||
|
|
||||||
if (!versionMatch) {
|
|
||||||
return res
|
|
||||||
.status(500)
|
|
||||||
.json({ error: "Could not extract version from agent script" });
|
|
||||||
}
|
|
||||||
|
|
||||||
const currentVersion = versionMatch[1];
|
|
||||||
|
|
||||||
res.json({
|
|
||||||
currentVersion: currentVersion,
|
|
||||||
downloadUrl: `/api/v1/hosts/agent/download`,
|
|
||||||
releaseNotes: `PatchMon Agent v${currentVersion}`,
|
|
||||||
minServerVersion: null,
|
|
||||||
});
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Version check error:", error);
|
console.error("Version check error:", error);
|
||||||
res.status(500).json({ error: "Failed to get agent version" });
|
res.status(500).json({ error: "Failed to get agent version" });
|
||||||
|
|||||||
@@ -410,11 +410,26 @@ class AgentVersionService {
|
|||||||
async getVersionInfo() {
|
async getVersionInfo() {
|
||||||
let hasUpdate = false;
|
let hasUpdate = false;
|
||||||
let updateStatus = "unknown";
|
let updateStatus = "unknown";
|
||||||
|
let effectiveLatestVersion = this.currentVersion; // Always use local version if available
|
||||||
|
|
||||||
if (this.currentVersion && this.latestVersion) {
|
// If we have a local version, use it as the latest regardless of GitHub
|
||||||
|
if (this.currentVersion) {
|
||||||
|
effectiveLatestVersion = this.currentVersion;
|
||||||
|
console.log(
|
||||||
|
`🔄 Using local agent version ${this.currentVersion} as latest`,
|
||||||
|
);
|
||||||
|
} else if (this.latestVersion) {
|
||||||
|
// Fallback to GitHub version only if no local version
|
||||||
|
effectiveLatestVersion = this.latestVersion;
|
||||||
|
console.log(
|
||||||
|
`🔄 No local version found, using GitHub version ${this.latestVersion}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.currentVersion && effectiveLatestVersion) {
|
||||||
const comparison = compareVersions(
|
const comparison = compareVersions(
|
||||||
this.currentVersion,
|
this.currentVersion,
|
||||||
this.latestVersion,
|
effectiveLatestVersion,
|
||||||
);
|
);
|
||||||
if (comparison < 0) {
|
if (comparison < 0) {
|
||||||
hasUpdate = true;
|
hasUpdate = true;
|
||||||
@@ -426,25 +441,25 @@ class AgentVersionService {
|
|||||||
hasUpdate = false;
|
hasUpdate = false;
|
||||||
updateStatus = "up-to-date";
|
updateStatus = "up-to-date";
|
||||||
}
|
}
|
||||||
} else if (this.latestVersion && !this.currentVersion) {
|
} else if (effectiveLatestVersion && !this.currentVersion) {
|
||||||
hasUpdate = true;
|
hasUpdate = true;
|
||||||
updateStatus = "no-agent";
|
updateStatus = "no-agent";
|
||||||
} else if (this.currentVersion && !this.latestVersion) {
|
} else if (this.currentVersion && !effectiveLatestVersion) {
|
||||||
// We have a current version but no latest version (GitHub API unavailable)
|
// We have a current version but no latest version (GitHub API unavailable)
|
||||||
hasUpdate = false;
|
hasUpdate = false;
|
||||||
updateStatus = "github-unavailable";
|
updateStatus = "github-unavailable";
|
||||||
} else if (!this.currentVersion && !this.latestVersion) {
|
} else if (!this.currentVersion && !effectiveLatestVersion) {
|
||||||
updateStatus = "no-data";
|
updateStatus = "no-data";
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
currentVersion: this.currentVersion,
|
currentVersion: this.currentVersion,
|
||||||
latestVersion: this.latestVersion,
|
latestVersion: effectiveLatestVersion,
|
||||||
hasUpdate: hasUpdate,
|
hasUpdate: hasUpdate,
|
||||||
updateStatus: updateStatus,
|
updateStatus: updateStatus,
|
||||||
lastChecked: this.lastChecked,
|
lastChecked: this.lastChecked,
|
||||||
supportedArchitectures: this.supportedArchitectures,
|
supportedArchitectures: this.supportedArchitectures,
|
||||||
status: this.latestVersion ? "ready" : "no-releases",
|
status: effectiveLatestVersion ? "ready" : "no-releases",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -511,6 +526,32 @@ class AgentVersionService {
|
|||||||
|
|
||||||
async getBinaryInfo(version, architecture) {
|
async getBinaryInfo(version, architecture) {
|
||||||
try {
|
try {
|
||||||
|
// Always use local version if it matches the requested version
|
||||||
|
if (version === this.currentVersion && this.currentVersion) {
|
||||||
|
const binaryPath = await this.getBinaryPath(
|
||||||
|
this.currentVersion,
|
||||||
|
architecture,
|
||||||
|
);
|
||||||
|
const stats = await fs.stat(binaryPath);
|
||||||
|
|
||||||
|
// Calculate file hash
|
||||||
|
const fileBuffer = await fs.readFile(binaryPath);
|
||||||
|
const hash = crypto
|
||||||
|
.createHash("sha256")
|
||||||
|
.update(fileBuffer)
|
||||||
|
.digest("hex");
|
||||||
|
|
||||||
|
return {
|
||||||
|
version: this.currentVersion,
|
||||||
|
architecture,
|
||||||
|
size: stats.size,
|
||||||
|
hash,
|
||||||
|
lastModified: stats.mtime,
|
||||||
|
path: binaryPath,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// For other versions, try to find them in the agents folder
|
||||||
const binaryPath = await this.getBinaryPath(version, architecture);
|
const binaryPath = await this.getBinaryPath(version, architecture);
|
||||||
const stats = await fs.stat(binaryPath);
|
const stats = await fs.stat(binaryPath);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user