CluPilotCloud/app/Provisioning/Steps/Customer/ConfigureDnsAndTls.php

68 lines
2.4 KiB
PHP

<?php
namespace App\Provisioning\Steps\Customer;
use App\Models\ProvisioningRun;
use App\Provisioning\StepResult;
use App\Services\Dns\HetznerDnsClient;
use App\Services\Traefik\TraefikWriter;
class ConfigureDnsAndTls extends CustomerStep
{
public function __construct(
private HetznerDnsClient $dns,
private TraefikWriter $traefik,
) {}
public function key(): string
{
return 'configure_dns_and_tls';
}
public function maxDuration(): int
{
// Above the 840s cert own-deadline below, so the step's own fail fires first.
return 960;
}
public function execute(ProvisioningRun $run): StepResult
{
$instance = $this->instance($run);
$host = $instance->host;
$fqdn = $instance->subdomain.'.'.config('provisioning.dns.zone');
// DNS — provider upsert is idempotent; the local row uses firstOrCreate on
// the record id and is written BEFORE the breadcrumb (the short-circuit guard).
if (! $this->hasResource($run, 'dns_record_id')) {
$recordId = $this->dns->upsertRecord($fqdn, 'A', $host->public_ip);
$instance->dnsRecords()->firstOrCreate(
['record_id' => $recordId],
['provider' => 'hetzner', 'fqdn' => $fqdn, 'type' => 'A', 'value' => $host->public_ip],
);
$this->recordResource($run, $host, 'dns_record_id', $recordId);
}
// Traefik file-provider route, written on the serving host (DNS points at
// it) and pointing at the guest VM.
if (! $instance->route_written) {
$trafficHost = $host->wg_ip ?? $host->public_ip;
$backend = $instance->guest_ip ?: $host->public_ip;
$this->traefik->write($trafficHost, $instance->subdomain, $backend);
$instance->update(['route_written' => true]);
}
// TLS via HTTP-01 — poll until the certificate is served.
if (! $instance->cert_ok) {
if ($this->traefik->certReachable($fqdn)) {
$instance->update(['cert_ok' => true]);
} elseif ($run->started_at !== null && $run->started_at->copy()->addSeconds(840)->isPast()) {
return StepResult::fail('cert_timeout');
} else {
return StepResult::poll(20, 'waiting for certificate');
}
}
return StepResult::advance();
}
}