64 lines
2.4 KiB
PHP
64 lines
2.4 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Dns;
|
|
|
|
use App\Models\DnsRecord;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Throwable;
|
|
|
|
/**
|
|
* Record ids from the OLD Hetzner DNS API, brought across where that is
|
|
* possible — and left alone where it is not.
|
|
*
|
|
* The cloud API addresses an RRSet by `{name}/{type}`; the old one issued an
|
|
* opaque id like `rec-abc123`. Every id this installation stored before the
|
|
* move is of the old shape, and nothing in the new client can address one.
|
|
*
|
|
* I got this wrong in the first pass. I counted the rows on the DEVELOPMENT
|
|
* database — hosts, dns_records and run_resources, all empty — and wrote that
|
|
* into RrsetId as though it settled the question. It settles nothing: the live
|
|
* server is a different installation with its own rows, and a format change
|
|
* across a schema is not made safe by one machine happening to be empty.
|
|
* (Codex review 2026-07-31, P1.)
|
|
*
|
|
* What can be converted: `dns_records` carries `fqdn` and `type` beside the id,
|
|
* so the RRSet name follows exactly. What cannot: `hosts.dns_record_id` (only a
|
|
* short name is stored, never the fqdn that was published) and the
|
|
* `dns_record_id` run resources (an id and nothing else). Those are handled at
|
|
* the other end — HttpHetznerDnsClient::deleteRecord() lets a legacy id pass
|
|
* with a loud log instead of throwing, so a purge completes rather than dying
|
|
* on the same row for ever.
|
|
*
|
|
* Guessing is deliberately not done. A record whose fqdn is not inside the
|
|
* configured zone is left untouched: it was never something this client could
|
|
* have written, and inventing a name for it would publish a deletion against
|
|
* whatever happens to carry that name today.
|
|
*/
|
|
class LegacyRecordIds
|
|
{
|
|
/** @return int how many rows were rewritten */
|
|
public function migrate(): int
|
|
{
|
|
$rewritten = 0;
|
|
|
|
foreach (DnsRecord::query()->get() as $record) {
|
|
if (str_contains((string) $record->record_id, '/')) {
|
|
continue;
|
|
}
|
|
|
|
try {
|
|
$id = RrsetId::for((string) $record->fqdn, (string) $record->type);
|
|
} catch (Throwable) {
|
|
// Outside the configured zone, or no zone configured at all.
|
|
// Left exactly as it is — see the class comment.
|
|
continue;
|
|
}
|
|
|
|
$record->update(['record_id' => $id]);
|
|
$rewritten++;
|
|
}
|
|
|
|
return $rewritten;
|
|
}
|
|
}
|