admin widget zu dokploy geswitched
This commit is contained in:
222
app/Services/Dokploy/DokployClient.php
Normal file
222
app/Services/Dokploy/DokployClient.php
Normal file
@@ -0,0 +1,222 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Dokploy;
|
||||
|
||||
use App\Models\InfrastructureActionLog;
|
||||
use Illuminate\Contracts\Auth\Authenticatable;
|
||||
use Illuminate\Http\Client\Factory as HttpFactory;
|
||||
use Illuminate\Http\Client\PendingRequest;
|
||||
use Illuminate\Http\Client\RequestException;
|
||||
use Illuminate\Http\Client\Response;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class DokployClient
|
||||
{
|
||||
public function __construct(private readonly HttpFactory $http) {}
|
||||
|
||||
public function applicationStatus(string $applicationId): array
|
||||
{
|
||||
return $this->cached($this->applicationCacheKey($applicationId), function () use ($applicationId) {
|
||||
$application = $this->get('/application.one', [
|
||||
'applicationId' => $applicationId,
|
||||
]);
|
||||
|
||||
$appName = Arr::get($application, 'appName') ?? Arr::get($application, 'name');
|
||||
$monitoring = [];
|
||||
|
||||
if ($appName) {
|
||||
$monitoring = $this->optionalGet('/application.readAppMonitoring', [
|
||||
'appName' => $appName,
|
||||
]);
|
||||
}
|
||||
|
||||
return [
|
||||
'application' => $application,
|
||||
'monitoring' => $monitoring,
|
||||
'appName' => $appName,
|
||||
];
|
||||
}, 30);
|
||||
}
|
||||
|
||||
public function recentDeployments(string $applicationId, int $limit = 5): array
|
||||
{
|
||||
return $this->cached($this->deploymentCacheKey($applicationId), function () use ($applicationId, $limit) {
|
||||
$deployments = $this->get('/deployment.all', [
|
||||
'applicationId' => $applicationId,
|
||||
]);
|
||||
|
||||
if (! is_array($deployments)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return array_slice($deployments, 0, $limit);
|
||||
}, 60);
|
||||
}
|
||||
|
||||
public function reloadApplication(string $applicationId, ?Authenticatable $actor = null): array
|
||||
{
|
||||
$status = $this->applicationStatus($applicationId);
|
||||
$appName = Arr::get($status, 'appName');
|
||||
|
||||
if (! $appName) {
|
||||
throw new \RuntimeException('Dokploy application name is required to reload the service.');
|
||||
}
|
||||
|
||||
return $this->dispatchAction(
|
||||
$applicationId,
|
||||
'reload',
|
||||
[
|
||||
'applicationId' => $applicationId,
|
||||
'appName' => $appName,
|
||||
],
|
||||
fn (array $payload) => $this->post('/application.reload', $payload),
|
||||
$actor,
|
||||
);
|
||||
}
|
||||
|
||||
public function redeployApplication(string $applicationId, ?Authenticatable $actor = null): array
|
||||
{
|
||||
return $this->dispatchAction(
|
||||
$applicationId,
|
||||
'redeploy',
|
||||
[
|
||||
'applicationId' => $applicationId,
|
||||
],
|
||||
fn (array $payload) => $this->post('/application.redeploy', $payload),
|
||||
$actor,
|
||||
);
|
||||
}
|
||||
|
||||
protected function cached(string $key, callable $callback, int $seconds): mixed
|
||||
{
|
||||
return Cache::remember($key, now()->addSeconds($seconds), $callback);
|
||||
}
|
||||
|
||||
protected function optionalGet(string $path, array $query = []): array
|
||||
{
|
||||
try {
|
||||
return $this->get($path, $query);
|
||||
} catch (\Throwable $exception) {
|
||||
Log::warning('[Dokploy] Optional GET failed', [
|
||||
'path' => $path,
|
||||
'message' => $exception->getMessage(),
|
||||
]);
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
protected function get(string $path, array $query = []): array
|
||||
{
|
||||
$response = $this->request()->get($this->normalizePath($path), $query);
|
||||
|
||||
if ($response->failed()) {
|
||||
$this->logFailure('GET', $path, $response);
|
||||
throw new RequestException($response);
|
||||
}
|
||||
|
||||
return $response->json() ?? [];
|
||||
}
|
||||
|
||||
protected function post(string $path, array $payload = []): Response
|
||||
{
|
||||
$response = $this->request()->post($this->normalizePath($path), $payload);
|
||||
|
||||
if ($response->failed()) {
|
||||
$this->logFailure('POST', $path, $response);
|
||||
throw new RequestException($response);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
protected function request(): PendingRequest
|
||||
{
|
||||
$baseUrl = config('dokploy.api.base_url');
|
||||
$token = config('dokploy.api.token');
|
||||
$timeout = config('dokploy.api.timeout', 10);
|
||||
|
||||
if (! $baseUrl || ! $token) {
|
||||
throw new \RuntimeException('Dokploy API is not configured.');
|
||||
}
|
||||
|
||||
return $this->http
|
||||
->baseUrl($baseUrl)
|
||||
->timeout($timeout)
|
||||
->acceptJson()
|
||||
->withHeaders([
|
||||
'x-api-key' => $token,
|
||||
]);
|
||||
}
|
||||
|
||||
protected function normalizePath(string $path): string
|
||||
{
|
||||
return '/'.ltrim($path, '/');
|
||||
}
|
||||
|
||||
protected function logFailure(string $method, string $path, Response $response): void
|
||||
{
|
||||
Log::error('[Dokploy] API request failed', [
|
||||
'method' => $method,
|
||||
'path' => $path,
|
||||
'status' => $response->status(),
|
||||
'body' => $response->body(),
|
||||
]);
|
||||
}
|
||||
|
||||
protected function dispatchAction(
|
||||
string $applicationId,
|
||||
string $action,
|
||||
array $payload,
|
||||
callable $callback,
|
||||
?Authenticatable $actor = null,
|
||||
): array {
|
||||
try {
|
||||
$response = $callback($payload);
|
||||
$body = $response->json() ?? [];
|
||||
$status = $response->status();
|
||||
} catch (\Throwable $exception) {
|
||||
$this->logAction($applicationId, $action, $payload, [
|
||||
'error' => $exception->getMessage(),
|
||||
], null, $actor);
|
||||
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
$this->logAction($applicationId, $action, $payload, $body, $status, $actor);
|
||||
Cache::forget($this->applicationCacheKey($applicationId));
|
||||
Cache::forget($this->deploymentCacheKey($applicationId));
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
protected function logAction(
|
||||
string $applicationId,
|
||||
string $action,
|
||||
array $payload,
|
||||
array $response,
|
||||
?int $status,
|
||||
?Authenticatable $actor = null,
|
||||
): void {
|
||||
InfrastructureActionLog::create([
|
||||
'user_id' => $actor?->getAuthIdentifier() ?? auth()->id(),
|
||||
'service_id' => $applicationId,
|
||||
'action' => $action,
|
||||
'payload' => $payload,
|
||||
'response' => $response,
|
||||
'status_code' => $status,
|
||||
]);
|
||||
}
|
||||
|
||||
protected function applicationCacheKey(string $applicationId): string
|
||||
{
|
||||
return "dokploy.application.{$applicationId}";
|
||||
}
|
||||
|
||||
protected function deploymentCacheKey(string $applicationId): string
|
||||
{
|
||||
return "dokploy.deployments.{$applicationId}";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user