CluPilotCloud/app/Services/Dns/FileHostDnsDirectory.php

70 lines
2.0 KiB
PHP

<?php
namespace App\Services\Dns;
use RuntimeException;
/**
* Writes one file per host into config('provisioning.dns.hosts_dir') — an
* /etc/hosts-format line ("<ip> <fqdn>") per entry, in the directory dnsmasq's
* --hostsdir watches via inotify (see vpn-dns in docker-compose.yml). No
* restart, no reload call: the file landing on disk IS the publish.
*
* The directory is shared with the app's own containers over a plain Docker
* volume, not SSH — unlike SshTraefikWriter, everything that touches it runs
* on the same Docker host. Left world-writable/readable (0775/0664) because
* whichever container touches it first (queue-provisioning as root in
* production, www-data under `app`) must not lock the other out.
*/
class FileHostDnsDirectory implements HostDnsDirectory
{
public function write(string $name, string $fqdn, string $ip): void
{
$this->ensureDir();
$path = $this->path($name);
if (@file_put_contents($path, "{$ip} {$fqdn}\n") === false) {
throw new RuntimeException("Could not write DNS hosts entry: {$path}");
}
@chmod($path, 0664);
}
public function remove(string $name): void
{
$path = $this->path($name);
// Nothing to do is not a failure — a host whose name was never
// written (or already removed) still has to purge cleanly.
if (is_file($path) && ! @unlink($path)) {
throw new RuntimeException("Could not remove DNS hosts entry: {$path}");
}
}
private function ensureDir(): void
{
$dir = $this->dir();
if (is_dir($dir)) {
return;
}
if (! @mkdir($dir, 0775, true) && ! is_dir($dir)) {
throw new RuntimeException("Could not create DNS hosts directory: {$dir}");
}
@chmod($dir, 0775);
}
private function path(string $name): string
{
return rtrim($this->dir(), '/')."/{$name}.hosts";
}
private function dir(): string
{
return (string) config('provisioning.dns.hosts_dir');
}
}