73 lines
2.5 KiB
PHP
73 lines
2.5 KiB
PHP
<?php
|
|
|
|
namespace App\Console\Commands;
|
|
|
|
use App\Models\Host;
|
|
use App\Services\Dns\HetznerDnsClient;
|
|
use Illuminate\Console\Command;
|
|
use Throwable;
|
|
|
|
/**
|
|
* Cleans up host DNS records this app published in the PUBLIC Hetzner zone
|
|
* before RegisterHostDns moved to the internal vpn-dns hostsdir — a host's
|
|
* WireGuard address in public DNS hands every scanner the internal subnet.
|
|
*
|
|
* The ids are whatever is still sitting in hosts.dns_record_id (PurgeHost
|
|
* already clears this column for any host removed normally; what remains
|
|
* belongs to hosts that are still active).
|
|
*
|
|
* Never deletes anything on its own: this runs against a live DNS account, a
|
|
* migration is the wrong place to make that call unattended, and a stale id
|
|
* could by now point at a record this app no longer owns. Without --force
|
|
* this only reports what it would remove.
|
|
*/
|
|
class PruneHostDns extends Command
|
|
{
|
|
protected $signature = 'clupilot:prune-host-dns {--force : Actually delete the records}';
|
|
|
|
protected $description = 'List (and, with --force, delete) public Hetzner DNS records this app published for a host';
|
|
|
|
public function handle(HetznerDnsClient $dns): int
|
|
{
|
|
$hosts = Host::query()->whereNotNull('dns_record_id')->orderBy('name')->get();
|
|
|
|
if ($hosts->isEmpty()) {
|
|
$this->info('No host carries a public dns_record_id. Nothing to do.');
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
$force = (bool) $this->option('force');
|
|
$failed = 0;
|
|
|
|
foreach ($hosts as $host) {
|
|
$label = $host->name !== '' && $host->name !== null ? $host->name : $host->uuid;
|
|
$recordId = $host->dns_record_id;
|
|
|
|
if (! $force) {
|
|
$this->line(" would delete {$label} record={$recordId}");
|
|
|
|
continue;
|
|
}
|
|
|
|
try {
|
|
$dns->deleteRecord($recordId);
|
|
$host->update(['dns_record_id' => null]);
|
|
$this->info(" deleted {$label} record={$recordId}");
|
|
} catch (Throwable $e) {
|
|
$failed++;
|
|
$this->error(" failed {$label} record={$recordId}: {$e->getMessage()}");
|
|
}
|
|
}
|
|
|
|
if (! $force) {
|
|
$this->newLine();
|
|
$this->comment(sprintf('Dry run — %d record(s) found, nothing changed. Re-run with --force to delete.', $hosts->count()));
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
return $failed === 0 ? self::SUCCESS : self::FAILURE;
|
|
}
|
|
}
|