129 lines
3.6 KiB
PHP
129 lines
3.6 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Registries;
|
|
|
|
use App\Enums\RegistryType;
|
|
use App\Models\Registry;
|
|
use App\Models\Server;
|
|
use Illuminate\Support\Facades\Http;
|
|
|
|
class ManagedRegistryHealth
|
|
{
|
|
public function check(Registry $registry): bool
|
|
{
|
|
if ($registry->type !== RegistryType::MANAGED) {
|
|
return true;
|
|
}
|
|
|
|
$message = $this->configurationBlocker($registry);
|
|
|
|
if ($message !== null) {
|
|
$registry->markUnhealthy($message);
|
|
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
$response = Http::timeout(5)->get('https://'.$registry->url.'/v2/');
|
|
} catch (\Throwable $exception) {
|
|
$registry->markUnhealthy('Registry URL is not reachable over HTTPS: '.$exception->getMessage());
|
|
|
|
return false;
|
|
}
|
|
|
|
if (! in_array($response->status(), [200, 401], true)) {
|
|
$registry->markUnhealthy('Registry HTTPS check returned HTTP '.$response->status().'.');
|
|
|
|
return false;
|
|
}
|
|
|
|
$checks = $registry->readiness_checks ?? [];
|
|
$checks['control_https'] = 'passed';
|
|
|
|
$registry->forceFill([
|
|
'readiness_checks' => $checks,
|
|
])->save();
|
|
|
|
if ($this->readinessChecksPassed($registry->refresh())) {
|
|
$registry->markHealthy('Registry HTTPS endpoint and smoke checks passed.');
|
|
|
|
return true;
|
|
}
|
|
|
|
$registry->markUnhealthy('Registry HTTPS endpoint is reachable, but smoke checks have not all passed.');
|
|
|
|
return false;
|
|
}
|
|
|
|
public function readinessBlocker(Registry $registry): ?string
|
|
{
|
|
if ($registry->type !== RegistryType::MANAGED) {
|
|
return null;
|
|
}
|
|
|
|
$message = $this->configurationBlocker($registry);
|
|
|
|
if ($message !== null) {
|
|
return $message;
|
|
}
|
|
|
|
if ($registry->ready_at === null || $registry->health_status !== 'healthy') {
|
|
return 'Managed registry has not passed readiness checks.';
|
|
}
|
|
|
|
if (! $this->readinessChecksPassed($registry)) {
|
|
return 'Managed registry smoke checks have not all passed.';
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private function configurationBlocker(Registry $registry): ?string
|
|
{
|
|
if (! $registry->url) {
|
|
return 'Managed registry URL is not configured.';
|
|
}
|
|
|
|
if (! str_contains((string) $registry->url, '.')) {
|
|
return 'Managed registry must use a resolvable HTTPS hostname.';
|
|
}
|
|
|
|
$credentials = $registry->credentials ?? [];
|
|
|
|
foreach (['build_username', 'build_password', 'runtime_username', 'runtime_password'] as $key) {
|
|
if (blank($credentials[$key] ?? null)) {
|
|
return 'Managed registry credentials are incomplete.';
|
|
}
|
|
}
|
|
|
|
$controlServer = $registry->controlServer;
|
|
|
|
if (! $controlServer instanceof Server) {
|
|
return 'A control/build server is required for managed registry builds.';
|
|
}
|
|
|
|
if (! $controlServer->build_enabled) {
|
|
return 'The managed registry control server is not build-enabled.';
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private function readinessChecksPassed(Registry $registry): bool
|
|
{
|
|
$checks = $registry->readiness_checks ?? [];
|
|
|
|
if ($checks === []) {
|
|
return false;
|
|
}
|
|
|
|
foreach (['control_https', 'build_push'] as $requiredCheck) {
|
|
if (! array_key_exists($requiredCheck, $checks)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return collect($checks)->every(fn (mixed $status): bool => $status === 'passed');
|
|
}
|
|
}
|