From 876539ba0a1d11abaabead5f8dad0c61ebe68526 Mon Sep 17 00:00:00 2001 From: Oleksander Piskun Date: Tue, 7 Apr 2026 10:27:48 +0300 Subject: [PATCH 1/2] fix: do not require harp_frp_address for K8s. add to UI readonly support of "kubernetes-install" Signed-off-by: Oleksander Piskun --- .../workflows/tests-deploy-k8s-clusterip.yml | 2 +- .../tests-deploy-k8s-loadbalancer.yml | 2 +- .github/workflows/tests-deploy-k8s-manual.yml | 2 +- .github/workflows/tests-deploy-k8s.yml | 2 +- lib/Command/Daemon/ListDaemons.php | 2 +- lib/Command/Daemon/RegisterDaemon.php | 10 ++--- .../DaemonConfig/DaemonConfigDetailsModal.vue | 24 +++++++++++- .../DaemonConfig/ManageDaemonConfigModal.vue | 38 +++++++++++++++++-- tests/test_occ_commands_k8s.py | 2 +- 9 files changed, 69 insertions(+), 15 deletions(-) diff --git a/.github/workflows/tests-deploy-k8s-clusterip.yml b/.github/workflows/tests-deploy-k8s-clusterip.yml index 4e0b3669..4b4630cc 100644 --- a/.github/workflows/tests-deploy-k8s-clusterip.yml +++ b/.github/workflows/tests-deploy-k8s-clusterip.yml @@ -170,7 +170,7 @@ jobs: run: | ./occ app_api:daemon:register \ k8s_test "K8s Test" "kubernetes-install" "http" "${{ env.NODE_IP }}:8780" "http://${{ env.NODE_IP }}" \ - --harp --harp_shared_key "${{ env.HP_SHARED_KEY }}" --harp_frp_address "${{ env.NODE_IP }}:8782" \ + --harp --harp_shared_key "${{ env.HP_SHARED_KEY }}" \ --k8s --k8s_expose_type=clusterip --set-default ./occ app_api:daemon:list diff --git a/.github/workflows/tests-deploy-k8s-loadbalancer.yml b/.github/workflows/tests-deploy-k8s-loadbalancer.yml index 51b8f7c6..614cd963 100644 --- a/.github/workflows/tests-deploy-k8s-loadbalancer.yml +++ b/.github/workflows/tests-deploy-k8s-loadbalancer.yml @@ -175,7 +175,7 @@ jobs: run: | ./occ app_api:daemon:register \ k8s_test "K8s Test" "kubernetes-install" "http" "${{ env.NODE_IP }}:8780" "http://${{ env.NODE_IP }}" \ - --harp --harp_shared_key "${{ env.HP_SHARED_KEY }}" --harp_frp_address "${{ env.NODE_IP }}:8782" \ + --harp --harp_shared_key "${{ env.HP_SHARED_KEY }}" \ --k8s --k8s_expose_type=loadbalancer --set-default ./occ app_api:daemon:list diff --git a/.github/workflows/tests-deploy-k8s-manual.yml b/.github/workflows/tests-deploy-k8s-manual.yml index c469f1c3..f0da2429 100644 --- a/.github/workflows/tests-deploy-k8s-manual.yml +++ b/.github/workflows/tests-deploy-k8s-manual.yml @@ -170,7 +170,7 @@ jobs: run: | ./occ app_api:daemon:register \ k8s_test "K8s Test" "kubernetes-install" "http" "${{ env.NODE_IP }}:8780" "http://${{ env.NODE_IP }}" \ - --harp --harp_shared_key "${{ env.HP_SHARED_KEY }}" --harp_frp_address "${{ env.NODE_IP }}:8782" \ + --harp --harp_shared_key "${{ env.HP_SHARED_KEY }}" \ --k8s --k8s_expose_type=manual --k8s_upstream_host=${{ env.MANUAL_CLUSTER_IP }} --set-default ./occ app_api:daemon:list diff --git a/.github/workflows/tests-deploy-k8s.yml b/.github/workflows/tests-deploy-k8s.yml index a9b4c67c..92b096b5 100644 --- a/.github/workflows/tests-deploy-k8s.yml +++ b/.github/workflows/tests-deploy-k8s.yml @@ -162,7 +162,7 @@ jobs: run: | ./occ app_api:daemon:register \ k8s_test "K8s Test" "kubernetes-install" "http" "${{ env.NODE_IP }}:8780" "http://${{ env.NODE_IP }}" \ - --harp --harp_shared_key "${{ env.HP_SHARED_KEY }}" --harp_frp_address "${{ env.NODE_IP }}:8782" \ + --harp --harp_shared_key "${{ env.HP_SHARED_KEY }}" \ --k8s --k8s_expose_type=nodeport --set-default ./occ app_api:daemon:list diff --git a/lib/Command/Daemon/ListDaemons.php b/lib/Command/Daemon/ListDaemons.php index bb1a3799..2425ba04 100644 --- a/lib/Command/Daemon/ListDaemons.php +++ b/lib/Command/Daemon/ListDaemons.php @@ -76,7 +76,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $daemon->getHost(), $deployConfig['nextcloud_url'], isset($deployConfig['harp']) ? 'yes' : 'no', - $deployConfig['harp']['frp_address'] ?? '(none)', + ($deployConfig['harp']['frp_address'] ?? null) ?: '(none)', $deployConfig['harp']['docker_socket_port'] ?? '(none)', ]; } diff --git a/lib/Command/Daemon/RegisterDaemon.php b/lib/Command/Daemon/RegisterDaemon.php index 782af7e9..8be5f00a 100644 --- a/lib/Command/Daemon/RegisterDaemon.php +++ b/lib/Command/Daemon/RegisterDaemon.php @@ -45,7 +45,7 @@ protected function configure(): void { $this->addOption('compute_device', null, InputOption::VALUE_REQUIRED, 'Computation device for GPU support (cpu|cuda|rocm)'); $this->addOption('set-default', null, InputOption::VALUE_NONE, 'Set DaemonConfig as default'); $this->addOption('harp', null, InputOption::VALUE_NONE, 'Set the daemon to use HaRP for all Docker and ExApp communication'); - $this->addOption('harp_frp_address', null, InputOption::VALUE_REQUIRED, '[host]:[port] of the HaRP FRP server, the default host is same as the HaRP host, port is 8782'); + $this->addOption('harp_frp_address', null, InputOption::VALUE_REQUIRED, '[host]:[port] of the HaRP FRP server (not required for K8s daemons). Default: same as HaRP host, port 8782'); $this->addOption('harp_shared_key', null, InputOption::VALUE_REQUIRED, 'HaRP shared key for secure communication between HaRP and AppAPI'); $this->addOption('harp_docker_socket_port', null, InputOption::VALUE_REQUIRED, '\'remotePort\' of the FRP client of the remote Docker socket proxy. There is one included in the harp container so this can be skipped for default setups.', '24000'); $this->addOption('harp_exapp_direct', null, InputOption::VALUE_NONE, 'Flag for the advanced setups only. Disables the FRP tunnel between ExApps and HaRP.'); @@ -68,9 +68,9 @@ protected function configure(): void { $this->addUsage('local_docker "Docker Local" "docker-install" "http" "/var/run/docker.sock" "http://nextcloud.local" --net=nextcloud --set-default --compute_device=cuda'); // Kubernetes usage examples - $this->addUsage('k8s_daemon "Kubernetes HaRP" "kubernetes-install" "http" "harp.nextcloud.svc:8780" "http://nextcloud.local" --harp --harp_shared_key "secret" --harp_frp_address "harp.nextcloud.svc:8782" --k8s'); - $this->addUsage('k8s_daemon_nodeport "K8s NodePort" "kubernetes-install" "http" "harp.example.com:8780" "http://nextcloud.local" --harp --harp_shared_key "secret" --harp_frp_address "harp.example.com:8782" --k8s --k8s_expose_type=nodeport --k8s_upstream_host="k8s-node.example.com"'); - $this->addUsage('k8s_daemon_lb "K8s LoadBalancer" "kubernetes-install" "http" "harp.example.com:8780" "http://nextcloud.local" --harp --harp_shared_key "secret" --harp_frp_address "harp.example.com:8782" --k8s --k8s_expose_type=loadbalancer'); + $this->addUsage('k8s_daemon "Kubernetes HaRP" "kubernetes-install" "http" "harp.nextcloud.svc:8780" "http://nextcloud.local" --harp --harp_shared_key "secret" --k8s'); + $this->addUsage('k8s_daemon_nodeport "K8s NodePort" "kubernetes-install" "http" "harp.example.com:8780" "http://nextcloud.local" --harp --harp_shared_key "secret" --k8s --k8s_expose_type=nodeport --k8s_upstream_host="k8s-node.example.com"'); + $this->addUsage('k8s_daemon_lb "K8s LoadBalancer" "kubernetes-install" "http" "harp.example.com:8780" "http://nextcloud.local" --harp --harp_shared_key "secret" --k8s --k8s_expose_type=loadbalancer'); } protected function execute(InputInterface $input, OutputInterface $output): int { @@ -91,7 +91,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $output->writeln('Value error: HaRP enabled daemon requires `harp_shared_key` option.'); return 1; } - if ($isHarp && !$input->getOption('harp_frp_address')) { + if ($isHarp && !$isK8s && !$input->getOption('harp_frp_address')) { $output->writeln('Value error: HaRP enabled daemon requires `harp_frp_address` option.'); return 1; } diff --git a/src/components/DaemonConfig/DaemonConfigDetailsModal.vue b/src/components/DaemonConfig/DaemonConfigDetailsModal.vue index 5b39d386..a427aca5 100644 --- a/src/components/DaemonConfig/DaemonConfigDetailsModal.vue +++ b/src/components/DaemonConfig/DaemonConfigDetailsModal.vue @@ -18,15 +18,37 @@ {{ t('app_api', 'The "Manual install" daemon is usually used for development. It cannot be set as the default daemon.') }} + + {{ t('app_api', 'This is a Kubernetes daemon managed via CLI.') }} + +

{{ t('app_api', 'ExApps installed') }}: {{ daemon.exAppsCount }}

{{ t('app_api', 'Name') }}: {{ daemon.name }}

{{ t('app_api', 'Protocol') }}: {{ daemon.protocol }}

{{ t('app_api', 'Host') }}: {{ daemon.host }}

-

+

{{ t('app_api', 'ExApp direct communication (FRP disabled)') }}: {{ daemon.deploy_config.harp.exapp_direct ?? false }}

+ +

{{ t('app_api', 'Deploy options') }}

{{ t('app_api', 'Docker network') }}: {{ daemon.deploy_config.net }}

{{ t('app_api', 'Nextcloud URL') }}: {{ daemon.deploy_config.nextcloud_url }}

diff --git a/src/components/DaemonConfig/ManageDaemonConfigModal.vue b/src/components/DaemonConfig/ManageDaemonConfigModal.vue index be29eaa8..5cdbf164 100644 --- a/src/components/DaemonConfig/ManageDaemonConfigModal.vue +++ b/src/components/DaemonConfig/ManageDaemonConfigModal.vue @@ -55,6 +55,7 @@ v-model="host" :label="isHarp ? t('app_api', 'HaRP host') : t('app_api', 'Daemon host')" :placeholder="daemonHostHelperText" + :readonly="isEdit && isK8s" :aria-label="daemonHostHelperText" /> @@ -66,6 +67,7 @@ v-model="deployConfig.haproxy_password" :label="isHarp ? t('app_api', 'HaRP shared key') : t('app_api', 'HaProxy password')" :error="isHaProxyPasswordValid === false" + :disabled="isEdit && isK8s" :placeholder="haProxyPasswordHelperText" :aria-label="haProxyPasswordHelperText" :helper-text="!isHaProxyPasswordValid ? t('app_api', 'The password must be at least 12 characters long') : ''" @@ -77,6 +79,7 @@ id="nextcloud-url" v-model="nextcloud_url" :label="t('app_api', 'Nextcloud URL')" + :readonly="isEdit && isK8s" :helper-text="getNextcloudUrlHelperText" :input-class="getNextcloudUrlHelperText !== '' ? 'text-warning' : ''" :placeholder="t('app_api', 'Nextcloud URL')" @@ -106,12 +109,13 @@
{{ t('app_api', 'Enable HaRP') }}
-
+
-
+
-
+
@@ -179,6 +185,7 @@ v-model="memoryLimit" :label="t('app_api', 'Memory limit (in MiB)')" :placeholder="t('app_api', 'Memory limit (in MiB)')" + :readonly="isEdit && isK8s" :aria-label="t('app_api', 'Memory limit (in MiB)')" :error="isMemoryLimitValid === false" :helper-text="isMemoryLimitValid === false ? t('app_api', 'Must be a positive integer') : ''" /> @@ -191,11 +198,29 @@ v-model="cpuLimit" :label="t('app_api', 'CPU limit')" :placeholder="t('app_api', 'CPU limit as decimal value')" + :readonly="isEdit && isK8s" :aria-label="t('app_api', 'CPU limit')" :error="isCpuLimitValid === false" :helper-text="isCpuLimitValid === false ? t('app_api', 'Must be a positive number') : ''" />
+
+

{{ t('app_api', 'Kubernetes settings') }}

+

{{ t('app_api', 'Expose type') }}: {{ deployConfig.kubernetes.expose_type }}

+

+ {{ t('app_api', 'Node port') }}: {{ deployConfig.kubernetes.node_port }} +

+

+ {{ t('app_api', 'Upstream host') }}: {{ deployConfig.kubernetes.upstream_host }} +

+

+ {{ t('app_api', 'External traffic policy') }}: {{ deployConfig.kubernetes.external_traffic_policy }} +

+

+ {{ t('app_api', 'Load balancer IP') }}: {{ deployConfig.kubernetes.load_balancer_ip }} +

+

{{ t('app_api', 'Node address type') }}: {{ deployConfig.kubernetes.node_address_type }}

+