Files
keystone/app/Services/Registries/ManagedRegistryHealth.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');
}
}