feat: implement server tags management with Proxmox-style color generation and syncing
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
namespace Paymenter\Extensions\Servers\Proxmox\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Paymenter\Extensions\Servers\Proxmox\Models\Server;
|
||||
use Paymenter\Extensions\Servers\Proxmox\Proxmox;
|
||||
|
||||
class ServerTagController
|
||||
{
|
||||
/**
|
||||
* Proxmox-style tag colors
|
||||
* Based on Proxmox VE color generation for tags
|
||||
*/
|
||||
private static $proxmoxTagColors = [
|
||||
'#e74c3c', // Red
|
||||
'#e67e22', // Orange
|
||||
'#f1c40f', // Yellow
|
||||
'#2ecc71', // Green
|
||||
'#1abc9c', // Teal
|
||||
'#3498db', // Blue
|
||||
'#9b59b6', // Purple
|
||||
'#e91e63', // Pink
|
||||
'#00bcd4', // Cyan
|
||||
'#8bc34a', // Light Green
|
||||
'#ff5722', // Deep Orange
|
||||
'#607d8b', // Blue Grey
|
||||
'#795548', // Brown
|
||||
'#9e9e9e', // Grey
|
||||
'#673ab7', // Deep Purple
|
||||
'#4caf50', // Green Material
|
||||
];
|
||||
|
||||
/**
|
||||
* Generate a consistent color for a tag based on its text
|
||||
* Uses the same algorithm as Proxmox VE
|
||||
*/
|
||||
public static function generateTagColor(string $tagText): string
|
||||
{
|
||||
// Simple hash function to get a consistent color for each tag
|
||||
$hash = 0;
|
||||
for ($i = 0; $i < strlen($tagText); $i++) {
|
||||
$hash = ord($tagText[$i]) + (($hash << 5) - $hash);
|
||||
$hash = $hash & $hash; // Convert to 32-bit integer
|
||||
}
|
||||
|
||||
$index = abs($hash) % count(self::$proxmoxTagColors);
|
||||
return self::$proxmoxTagColors[$index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tags for a server
|
||||
*/
|
||||
public function show($serverId)
|
||||
{
|
||||
$server = Server::where('id', $serverId)
|
||||
->where('user_id', Auth::id())
|
||||
->firstOrFail();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'tags' => $server->tags ?? [],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update tags for a server
|
||||
*/
|
||||
public function update(Request $request, $serverId)
|
||||
{
|
||||
$request->validate([
|
||||
'tags' => 'nullable|array|max:3',
|
||||
'tags.*.text' => 'required|string|max:32|regex:/^[a-zA-Z0-9_-]+$/',
|
||||
'tags.*.color' => 'nullable|string|max:16',
|
||||
]);
|
||||
|
||||
$server = Server::where('id', $serverId)
|
||||
->where('user_id', Auth::id())
|
||||
->firstOrFail();
|
||||
|
||||
$tags = $request->input('tags', []);
|
||||
|
||||
// Limit to 3 tags
|
||||
$tags = array_slice($tags, 0, 3);
|
||||
|
||||
// Process tags and auto-generate colors if not provided
|
||||
$processedTags = [];
|
||||
foreach ($tags as $tag) {
|
||||
$text = trim($tag['text']);
|
||||
if (empty($text)) continue;
|
||||
|
||||
// Convert to lowercase and sanitize (Proxmox requires this)
|
||||
$text = strtolower(preg_replace('/[^a-zA-Z0-9_-]/', '', $text));
|
||||
if (empty($text)) continue;
|
||||
|
||||
$processedTags[] = [
|
||||
'text' => $text,
|
||||
'color' => $tag['color'] ?? self::generateTagColor($text),
|
||||
];
|
||||
}
|
||||
|
||||
// Update local database
|
||||
$server->tags = $processedTags;
|
||||
$server->save();
|
||||
|
||||
// Sync to Proxmox
|
||||
$proxmoxSuccess = $this->syncTagsToProxmox($server, $processedTags);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'tags' => $processedTags,
|
||||
'proxmox_synced' => $proxmoxSuccess,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync tags to Proxmox VM
|
||||
*/
|
||||
private function syncTagsToProxmox(Server $server, array $tags): bool
|
||||
{
|
||||
try {
|
||||
$proxmox = new Proxmox;
|
||||
|
||||
// Convert tags array to Proxmox format (semicolon-separated)
|
||||
// Proxmox stores tags as a simple semicolon-delimited string
|
||||
$tagString = implode(';', array_column($tags, 'text'));
|
||||
|
||||
// Update VM config with tags
|
||||
$proxmox->request('/nodes/' . $server->node->name . '/qemu/' . $server->vm_id . '/config', 'put', [
|
||||
'tags' => $tagString,
|
||||
]);
|
||||
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
// Log the error but don't fail the request
|
||||
\Log::error('Failed to sync tags to Proxmox for server ' . $server->id, [
|
||||
'error' => $e->getMessage(),
|
||||
'server_id' => $server->id,
|
||||
]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get available tag colors
|
||||
*/
|
||||
public function colors()
|
||||
{
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'colors' => self::$proxmoxTagColors,
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user