From 593645d8aa9881ca579b7c3ed32294a7caf12957 Mon Sep 17 00:00:00 2001 From: Matthew Baggett Date: Thu, 25 Jan 2024 16:54:34 +0100 Subject: [PATCH] Less disk thrashing, more pruning. --- bouncer/src/Bouncer.php | 35 +++++++++++++++++++++++++++-------- bouncer/src/Target.php | 25 +++++++++++++++++++++---- 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/bouncer/src/Bouncer.php b/bouncer/src/Bouncer.php index 4f1df75..cbc7753 100644 --- a/bouncer/src/Bouncer.php +++ b/bouncer/src/Bouncer.php @@ -585,9 +585,7 @@ class Bouncer ksort($sortedTargets); $targets = array_values($sortedTargets); - // Wipe configs and rebuild - $this->wipeNginxConfig(); - + // Re-generate nginx configs $this->logger->info('{emoji} Found {num_services} services with BOUNCER_DOMAIN set', ['emoji' => Emoji::magnifyingGlassTiltedLeft(), 'num_services' => count($targets)]); $this->generateNginxConfigs($targets); $this->generateLetsEncryptCerts($targets); @@ -716,24 +714,45 @@ class Bouncer $this->logger->info('{emoji} More than {num_max} Nginx configs generated.. Too many to show them all!', ['emoji' => Emoji::pencil(), 'num_max' => $this->getMaximumNginxConfigCreationNotices()]); } $this->logger->info('{emoji} Updated {num_created} Nginx configs, {num_changed} changed..', ['emoji' => Emoji::pencil(), 'num_created' => count($targets), 'num_changed' => count($changedTargets)]); + + $this->pruneNonExistentConfigs($targets); + } + + /** + * @param $targets Target[] + */ + protected function pruneNonExistentConfigs(array $targets): void + { + $expectedFiles = [ + 'default.conf', + ]; + foreach ($targets as $target) { + $expectedFiles = array_merge($expectedFiles, $target->getExpectedFiles()); + } + foreach ($this->configFilesystem->listContents('/') as $file) { + if (!in_array($file['path'], $expectedFiles)) { + $this->logger->info('{emoji} Removing {file}', ['emoji' => Emoji::wastebasket(), 'file' => $file['path']]); + $this->configFilesystem->delete($file['path']); + } + } } private function generateNginxConfig(Target $target): bool { $configData = $this->twig->render('NginxTemplate.twig', $target->__toArray()); $changed = false; - $configFileHash = $this->configFilesystem->fileExists($target->getFileName()) ? sha1($this->configFilesystem->read($target->getFileName())) : null; + $configFileHash = $this->configFilesystem->fileExists($target->getNginxConfigFileName()) ? sha1($this->configFilesystem->read($target->getNginxConfigFileName())) : null; if (sha1($configData) != $configFileHash) { - $this->configFilesystem->write($target->getFileName(), $configData); + $this->configFilesystem->write($target->getNginxConfigFileName(), $configData); $changed = true; } if ($target->hasAuth()) { - $authFileHash = $this->configFilesystem->fileExists($target->getAuthFileName()) ? $this->configFilesystem->read($target->getAuthFileName() . '.hash') : null; + $authFileHash = $this->configFilesystem->fileExists($target->getBasicAuthFileName()) ? $this->configFilesystem->read($target->getBasicAuthHashFileName()) : null; if ($target->getAuthHash() != $authFileHash) { - $this->configFilesystem->write($target->getAuthFileName() . '.hash', $target->getAuthHash()); - $this->configFilesystem->write($target->getAuthFileName(), $target->getAuthFileData()); + $this->configFilesystem->write($target->getBasicAuthHashFileName(), $target->getAuthHash()); + $this->configFilesystem->write($target->getBasicAuthFileName(), $target->getBasicAuthFileData()); $changed = true; } } diff --git a/bouncer/src/Target.php b/bouncer/src/Target.php index af1fce9..0949e9f 100644 --- a/bouncer/src/Target.php +++ b/bouncer/src/Target.php @@ -48,7 +48,7 @@ class Target 'allowLargePayloads' => $this->isAllowLargePayloads(), 'proxyTimeoutSeconds' => $this->getProxyTimeoutSeconds(), 'hasAuth' => $this->hasAuth(), - 'authFile' => $this->getAuthFileName(), + 'authFile' => $this->getBasicAuthFileName(), 'hasHostOverride' => $this->hasHostOverride(), 'hostOverride' => $this->getHostOverride(), ]; @@ -121,23 +121,40 @@ class Target return $this->username != null && $this->password != null; } - public function getFileName(): string + public function getNginxConfigFileName(): string { return "{$this->getName()}.conf"; } - public function getAuthFileName(): string + public function getBasicAuthFileName(): string { return "{$this->getName()}.secret"; } - public function getAuthFileData(): string + public function getBasicAuthHashFileName(): string + { + return "{$this->getBasicAuthFileName()}.hash"; + } + + public function getBasicAuthFileData(): string { $output = shell_exec(sprintf('htpasswd -nibB -C10 %s %s', $this->getUsername(), $this->getPassword())); return trim($output) . "\n"; } + /** + * Return an array of files that should exist for this target. + */ + public function getExpectedFiles(): array + { + return array_filter([ + $this->getNginxConfigFileName(), + $this->hasAuth() ? $this->getBasicAuthFileName() : null, + $this->hasAuth() ? $this->getBasicAuthHashFileName() : null, + ]); + } + public function getProxyTimeoutSeconds(): ?int { return $this->proxyTimeoutSeconds;