From 85fa3b7842815c649760ce0c8176f7cacdcfd608 Mon Sep 17 00:00:00 2001 From: Thorsten Klein Date: Fri, 21 Aug 2026 14:45:32 +0200 Subject: [PATCH] fix(k8s): check daemon reachability by deploy id MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Four call sites always ran the Docker ping: ExAppsPageService, Settings\Admin, and the two DaemonConfigController endpoints behind the admin UI's connection checks. On a kubernetes-install daemon that probes a Docker Engine path HaRP does not serve, and it blocks until cURL times out rather than failing fast — so a healthy daemon reads as unreachable, the ExApp deploy button stays disabled and "Check Connection" reports failure. Mirrors the dispatch SetupChecks\DaemonCheck already does. --- lib/Controller/DaemonConfigController.php | 19 +++++++++++++------ lib/Service/ExAppsPageService.php | 19 +++++++++++++++---- lib/Settings/Admin.php | 22 +++++++++++++++++----- 3 files changed, 45 insertions(+), 15 deletions(-) diff --git a/lib/Controller/DaemonConfigController.php b/lib/Controller/DaemonConfigController.php index e85bd3223..e65647e95 100644 --- a/lib/Controller/DaemonConfigController.php +++ b/lib/Controller/DaemonConfigController.php @@ -12,6 +12,7 @@ use OCA\AppAPI\AppInfo\Application; use OCA\AppAPI\Db\DaemonConfig; use OCA\AppAPI\DeployActions\DockerActions; +use OCA\AppAPI\DeployActions\KubernetesActions; use OCA\AppAPI\ResponseDefinitions; use OCA\AppAPI\Service\AppAPIService; use OCA\AppAPI\Service\DaemonConfigService; @@ -41,6 +42,7 @@ public function __construct( private readonly IAppConfig $appConfig, private readonly DaemonConfigService $daemonConfigService, private readonly DockerActions $dockerActions, + private readonly KubernetesActions $kubernetesActions, private readonly AppAPIService $service, private readonly ExAppService $exAppService, private readonly IL10N $l10n, @@ -171,10 +173,8 @@ public function unregisterDaemonConfig(string $name): Response { */ public function verifyDaemonConnection(string $name): Response { $daemonConfig = $this->daemonConfigService->getDaemonConfigByName($name); - $this->dockerActions->initGuzzleClient($daemonConfig); - $dockerDaemonAccessible = $this->dockerActions->ping($this->dockerActions->buildDockerUrl($daemonConfig)); return new JSONResponse([ - 'success' => $dockerDaemonAccessible, + 'success' => $this->daemonAccessible($daemonConfig), ]); } @@ -219,13 +219,20 @@ public function checkDaemonConnection(array $daemonParams): Response { 'host' => $daemonParams['host'], 'deploy_config' => $daemonParams['deploy_config'], ]); - $this->dockerActions->initGuzzleClient($daemonConfig); - $dockerDaemonAccessible = $this->dockerActions->ping($this->dockerActions->buildDockerUrl($daemonConfig)); return new JSONResponse([ - 'success' => $dockerDaemonAccessible, + 'success' => $this->daemonAccessible($daemonConfig), ]); } + private function daemonAccessible(DaemonConfig $daemonConfig): bool { + if ($daemonConfig->getAcceptsDeployId() === KubernetesActions::DEPLOY_ID) { + $this->kubernetesActions->initGuzzleClient($daemonConfig); + return $this->kubernetesActions->ping($daemonConfig) === ''; + } + $this->dockerActions->initGuzzleClient($daemonConfig); + return $this->dockerActions->ping($this->dockerActions->buildDockerUrl($daemonConfig)); + } + /** * Start a test deployment on a deploy daemon * diff --git a/lib/Service/ExAppsPageService.php b/lib/Service/ExAppsPageService.php index 74fbd3b1e..a5b487cea 100644 --- a/lib/Service/ExAppsPageService.php +++ b/lib/Service/ExAppsPageService.php @@ -10,6 +10,7 @@ namespace OCA\AppAPI\Service; use OCA\AppAPI\DeployActions\DockerActions; +use OCA\AppAPI\DeployActions\KubernetesActions; use OCA\AppAPI\Fetcher\ExAppFetcher; use OCP\App\IAppManager; use OCP\AppFramework\Services\IInitialState; @@ -23,6 +24,7 @@ public function __construct( private ExAppFetcher $exAppFetcher, private DaemonConfigService $daemonConfigService, private DockerActions $dockerActions, + private KubernetesActions $kubernetesActions, private IAppConfig $appConfig, private IAppManager $appManager, private LoggerInterface $logger, @@ -50,10 +52,19 @@ public function provideAppApiState(IInitialState $initialState): void { if ($daemonConfig !== null) { $defaultDaemonConfig = $daemonConfig->jsonSerialize(); unset($defaultDaemonConfig['deploy_config']['haproxy_password']); - $this->dockerActions->initGuzzleClient($daemonConfig); - $daemonConfigAccessible = $this->dockerActions->ping($this->dockerActions->buildDockerUrl($daemonConfig)); - if (!$daemonConfigAccessible) { - $this->logger->warning(sprintf('Deploy daemon "%s" is not accessible by Nextcloud. Please check its configuration', $daemonConfig->getName())); + if ($daemonConfig->getAcceptsDeployId() === KubernetesActions::DEPLOY_ID) { + $this->kubernetesActions->initGuzzleClient($daemonConfig); + $pingError = $this->kubernetesActions->ping($daemonConfig); + $daemonConfigAccessible = $pingError === ''; + if (!$daemonConfigAccessible) { + $this->logger->warning(sprintf('Deploy daemon "%s" is not accessible by Nextcloud: %s', $daemonConfig->getName(), $pingError)); + } + } else { + $this->dockerActions->initGuzzleClient($daemonConfig); + $daemonConfigAccessible = $this->dockerActions->ping($this->dockerActions->buildDockerUrl($daemonConfig)); + if (!$daemonConfigAccessible) { + $this->logger->warning(sprintf('Deploy daemon "%s" is not accessible by Nextcloud. Please check its configuration', $daemonConfig->getName())); + } } } } diff --git a/lib/Settings/Admin.php b/lib/Settings/Admin.php index 676a3005b..df1e52403 100644 --- a/lib/Settings/Admin.php +++ b/lib/Settings/Admin.php @@ -11,6 +11,7 @@ use OCA\AppAPI\AppInfo\Application; use OCA\AppAPI\DeployActions\DockerActions; +use OCA\AppAPI\DeployActions\KubernetesActions; use OCA\AppAPI\Service\DaemonConfigService; use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Services\IInitialState; @@ -25,6 +26,7 @@ public function __construct( private DaemonConfigService $daemonConfigService, private IAppConfig $appConfig, private DockerActions $dockerActions, + private KubernetesActions $kubernetesActions, private LoggerInterface $logger, ) { } @@ -41,11 +43,21 @@ public function getForm(): TemplateResponse { if ($defaultDaemonConfigName !== '') { $daemonConfig = $this->daemonConfigService->getDaemonConfigByName($defaultDaemonConfigName); if ($daemonConfig !== null) { - $this->dockerActions->initGuzzleClient($daemonConfig); - $daemonConfigAccessible = $this->dockerActions->ping($this->dockerActions->buildDockerUrl($daemonConfig)); - $adminInitialData['daemon_config_accessible'] = $daemonConfigAccessible; - if (!$daemonConfigAccessible) { - $this->logger->error(sprintf('Deploy daemon "%s" is not accessible by Nextcloud. Please check its configuration', $daemonConfig->getName())); + if ($daemonConfig->getAcceptsDeployId() === KubernetesActions::DEPLOY_ID) { + $this->kubernetesActions->initGuzzleClient($daemonConfig); + $pingError = $this->kubernetesActions->ping($daemonConfig); + $daemonConfigAccessible = $pingError === ''; + $adminInitialData['daemon_config_accessible'] = $daemonConfigAccessible; + if (!$daemonConfigAccessible) { + $this->logger->error(sprintf('Deploy daemon "%s" is not accessible by Nextcloud: %s', $daemonConfig->getName(), $pingError)); + } + } else { + $this->dockerActions->initGuzzleClient($daemonConfig); + $daemonConfigAccessible = $this->dockerActions->ping($this->dockerActions->buildDockerUrl($daemonConfig)); + $adminInitialData['daemon_config_accessible'] = $daemonConfigAccessible; + if (!$daemonConfigAccessible) { + $this->logger->error(sprintf('Deploy daemon "%s" is not accessible by Nextcloud. Please check its configuration', $daemonConfig->getName())); + } } } }