status === 'cancellation_scheduled' && $instance->service_ends_at !== null && $instance->service_ends_at->lessThanOrEqualTo($at ?? now()); } /** * Tear the address down and mark the instance ended. * * Re-entrant: removing a router file that is not there is `rm -f`, a record * id that has already been deleted is deleted again for nothing, and an * instance already marked `ended` is returned false straight away. A DNS * failure is deliberately not swallowed — the record id survives on its row, * so a retry can finish the job, and a provider that is permanently broken * becomes a visible failure rather than a silent leak. * * @return bool whether this call was the one that ended it */ public function __invoke(Instance $instance): bool { if (! $this->hasEnded($instance)) { return false; } $host = $instance->host; if ($host !== null) { // The host that actually serves the traffic — DNS points at it, and // it is where ConfigureDnsAndTls wrote the file in the first place. $this->traefik->remove($host->wg_ip ?? $host->public_ip, $instance->subdomain); } else { // No host left to reach: the router file went with the machine it // lived on. Said out loud rather than passed over, because it means // this teardown is only doing half of what it usually does. Log::warning('Ending an instance whose host is gone — no router to remove.', [ 'instance' => $instance->uuid, ]); } foreach ($instance->dnsRecords()->get() as $record) { $this->dns->deleteRecord($record->record_id); $record->delete(); } $instance->update([ 'status' => 'ended', // The address state has to go with the address. Left as it was, a // later run would read `route_written` plus a matching hostname list // and decide there was nothing to write — so an instance that was // ever revived would be announced and routed nowhere. 'route_written' => false, 'routed_hostnames' => null, 'routed_backend' => null, 'cert_ok' => false, 'domain_cert_ok' => false, ]); Log::info('Instance service ended; address withdrawn.', [ 'instance' => $instance->uuid, 'subdomain' => $instance->subdomain, 'service_ended_at' => $instance->service_ends_at?->toIso8601String(), ]); return true; } }