From dfecad1da459e92a12bca1d02ac44e135085e055 Mon Sep 17 00:00:00 2001
From: kbeyro <121854496+kbeyro@users.noreply.github.com>
Date: Tue, 27 May 2025 14:02:41 +0200
Subject: [PATCH 01/13] add cluster path if exist

---
 .../kubernetes/components/helm/HelmCommand.java          | 2 ++
 .../kubernetes/components/helm/HelmCommandExecutor.java  | 9 +++++----
 .../components/helm/commands/HelmInstallCommand.java     | 6 +++++-
 3 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmCommand.java b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmCommand.java
index f4ba07022..fb2e4bd9f 100644
--- a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmCommand.java
+++ b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmCommand.java
@@ -16,6 +16,8 @@ public abstract class HelmCommand implements Command {
     protected static final String HELM_VERSION_2 = "v2";
     protected static final String HELM_VERSION_3 = "v3";
 
+    protected static final String KUBECONFIG = "--kubeconfig";
+
     protected String command;
 
     @Override
diff --git a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmCommandExecutor.java b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmCommandExecutor.java
index 01a3fd9b4..dfc719d8a 100644
--- a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmCommandExecutor.java
+++ b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmCommandExecutor.java
@@ -46,11 +46,11 @@ public class HelmCommandExecutor {
         this.enableTls = enableTls;
     }
 
-    void executeHelmInstallCommand(String namespace, String releaseName, KubernetesTemplate template, Map<String, String> arguments) {
-        executeInstall(namespace, releaseName, template, arguments);
+    void executeHelmInstallCommand(String namespace, String releaseName, KubernetesTemplate template, Map<String, String> arguments, String kubeConfigPath) {
+        executeInstall(namespace, releaseName, template, arguments, kubeConfigPath);
     }
 
-    private void executeInstall(String namespace, String releaseName, KubernetesTemplate template, Map<String, String> arguments) {
+    private void executeInstall(String namespace, String releaseName, KubernetesTemplate template, Map<String, String> arguments, String kubeConfigPath) {
         try {
             HelmInstallCommand command = HelmInstallCommand.commandWithRepo(
                     helmVersion,
@@ -59,7 +59,8 @@ public class HelmCommandExecutor {
                     arguments,
                     constructChartNameWithRepo(template.getChart().getName()),
                     template.getChart().getVersion(),
-                    enableTls
+                    enableTls,
+                    kubeConfigPath
             );
             commandExecutor.execute(command);
         } catch (CommandExecutionException e) {
diff --git a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/commands/HelmInstallCommand.java b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/commands/HelmInstallCommand.java
index 940c89fa9..c5cab7455 100644
--- a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/commands/HelmInstallCommand.java
+++ b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/commands/HelmInstallCommand.java
@@ -25,7 +25,7 @@ public class HelmInstallCommand extends HelmCommand {
      * @param enableTls    flag indicating if tls option should be added
      * @return complete command object
      */
-    public static HelmInstallCommand commandWithRepo(String helmVersion, String namespace, String releaseName, Map<String, String> values, String chartName, String chartVersion, boolean enableTls) {
+    public static HelmInstallCommand commandWithRepo(String helmVersion, String namespace, String releaseName, Map<String, String> values, String chartName, String chartVersion, boolean enableTls, String kubeConfigPath) {
         StringBuilder sb = buildBaseInstallCommand(helmVersion, namespace, releaseName, values);
         if (chartName == null || chartName.isEmpty()) {
             throw new IllegalArgumentException("Chart name can't be null or empty");
@@ -35,6 +35,10 @@ public class HelmInstallCommand extends HelmCommand {
             sb.append(SPACE).append(OPTION_VERSION).append(SPACE).append(chartVersion);
         }
         addTlsOptionIfRequired(helmVersion, enableTls, sb);
+
+        if(kubeConfigPath != null && !kubeConfigPath.isEmpty()) {
+            sb.append(SPACE).append(KUBECONFIG).append(SPACE).append(kubeConfigPath);
+        }
         return new HelmInstallCommand(sb.toString());
     }
 
-- 
GitLab


From 445221f4a9ff0fc448abfddda78b3eabf99b1e5b Mon Sep 17 00:00:00 2001
From: kbeyro <121854496+kbeyro@users.noreply.github.com>
Date: Tue, 27 May 2025 14:02:58 +0200
Subject: [PATCH 02/13] map cluster to path if cluster is added

---
 .../kubernetes/components/helm/HelmKServiceManager.java       | 3 ++-
 .../kubernetes/components/helm/HelmKServiceManagerTest.java   | 4 ++--
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmKServiceManager.java b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmKServiceManager.java
index 753891c45..1cd6308ae 100644
--- a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmKServiceManager.java
+++ b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmKServiceManager.java
@@ -75,7 +75,8 @@ public class HelmKServiceManager implements KServiceLifecycleManager {
                 namespaceService.namespace(serviceInfo.getDomain()),
                 serviceInfo.getDescriptiveDeploymentId().getValue(),
                 serviceInfo.getKubernetesTemplate(),
-                createArgumentsMap(serviceInfo)
+                createArgumentsMap(serviceInfo),
+                serviceInfo.getRemoteCluster() != null ? serviceInfo.getRemoteCluster().getPathConfigFile() : null
         );
     }
 
diff --git a/src/test/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmKServiceManagerTest.java b/src/test/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmKServiceManagerTest.java
index 0ebf9adc9..b3e27ed59 100644
--- a/src/test/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmKServiceManagerTest.java
+++ b/src/test/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmKServiceManagerTest.java
@@ -119,7 +119,7 @@ public class HelmKServiceManagerTest {
                 eq("namespace"),
                 eq("descriptiveDeploymentId"),
                 k8sTemplateArg.capture(),
-                argumentsArg.capture()
+                argumentsArg.capture(), null
         );
         assertThat(argumentsArg.getValue()).isNotEmpty();
         assertThat(argumentsArg.getValue().size()).isEqualTo(11);
@@ -143,7 +143,7 @@ public class HelmKServiceManagerTest {
                 eq("namespace"),
                 eq("descriptiveDeploymentId"),
                 any(),
-                any()
+                any(), null
         );
     }
 
-- 
GitLab


From fbe742f6dbfad53f2cc94552411ee422f414cd94 Mon Sep 17 00:00:00 2001
From: kbeyro <121854496+kbeyro@users.noreply.github.com>
Date: Tue, 27 May 2025 14:03:13 +0200
Subject: [PATCH 03/13] add cluster to deployment

---
 .../kubernetes/RemoteClusterManager.java      |  4 +++
 .../kubernetes/KubernetesManager.java         | 27 ++++++++++++++-----
 .../entities/KubernetesNmServiceInfo.java     |  8 ++++++
 .../orchestration/entities/AppDeployment.java |  2 ++
 .../tasks/app/AppRequestVerificationTask.java |  6 +++++
 .../api/market/AppInstanceController.java     |  1 +
 .../service/impl/DomainServiceImpl.java       |  2 +-
 .../app/AppRequestVerificationTaskTest.java   |  4 ++-
 8 files changed, 46 insertions(+), 8 deletions(-)

diff --git a/src/main/java/net/geant/nmaas/externalservices/kubernetes/RemoteClusterManager.java b/src/main/java/net/geant/nmaas/externalservices/kubernetes/RemoteClusterManager.java
index 1ce39f84b..7ab5cf48d 100644
--- a/src/main/java/net/geant/nmaas/externalservices/kubernetes/RemoteClusterManager.java
+++ b/src/main/java/net/geant/nmaas/externalservices/kubernetes/RemoteClusterManager.java
@@ -349,4 +349,8 @@ public class RemoteClusterManager implements ClusterMonitoringService {
 
     }
 
+    public boolean clusterExist(Long id) {
+        return clusterRepository.existsById(id);
+    }
+
 }
\ No newline at end of file
diff --git a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/KubernetesManager.java b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/KubernetesManager.java
index 1cb6ce714..b4668e77e 100644
--- a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/KubernetesManager.java
+++ b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/KubernetesManager.java
@@ -4,6 +4,7 @@ import com.google.common.base.Strings;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import net.geant.nmaas.externalservices.kubernetes.KubernetesClusterIngressManager;
+import net.geant.nmaas.externalservices.kubernetes.RemoteClusterManager;
 import net.geant.nmaas.externalservices.kubernetes.entities.IngressControllerConfigOption;
 import net.geant.nmaas.gitlab.GitLabManager;
 import net.geant.nmaas.gitlab.exceptions.GitLabInvalidConfigurationException;
@@ -81,6 +82,7 @@ public class KubernetesManager implements ContainerOrchestrator {
     private final KubernetesClusterIngressManager ingressManager;
     private final GitLabManager gitLabManager;
     private final JanitorService janitorService;
+    private final RemoteClusterManager remoteClusterManager;
 
     @Override
     @Loggable(LogLevel.INFO)
@@ -97,12 +99,25 @@ public class KubernetesManager implements ContainerOrchestrator {
             throw new NmServiceRequestVerificationException(iae.getMessage());
         }
 
-        KubernetesNmServiceInfo serviceInfo = new KubernetesNmServiceInfo(
-                deploymentId,
-                appDeployment.getDeploymentName(),
-                appDeployment.getDomain(),
-                appDeployment.getDescriptiveDeploymentId()
-        );
+        KubernetesNmServiceInfo serviceInfo;
+        //verify cluster
+        if(remoteClusterManager.clusterExist(appDeployment.getRemoteClusterId())) {
+            serviceInfo = new KubernetesNmServiceInfo(
+                    deploymentId,
+                    appDeployment.getDeploymentName(),
+                    appDeployment.getDomain(),
+                    appDeployment.getDescriptiveDeploymentId(),
+                    remoteClusterManager.getCluster(appDeployment.getRemoteClusterId()));
+        } else {
+            serviceInfo = new KubernetesNmServiceInfo(
+                    deploymentId,
+                    appDeployment.getDeploymentName(),
+                    appDeployment.getDomain(),
+                    appDeployment.getDescriptiveDeploymentId()
+            );
+        }
+
+
         serviceInfo.setKubernetesTemplate(KubernetesTemplate.copy(appDeploymentSpec.getKubernetesTemplate()));
         serviceInfo.setStorageVolumes(generateTemplateStorageVolumes(appDeploymentSpec.getStorageVolumes()));
         serviceInfo.setAccessMethods(generateTemplateAccessMethods(appDeploymentSpec.getAccessMethods()));
diff --git a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/entities/KubernetesNmServiceInfo.java b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/entities/KubernetesNmServiceInfo.java
index e2f56ccb6..7c77eb865 100644
--- a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/entities/KubernetesNmServiceInfo.java
+++ b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/entities/KubernetesNmServiceInfo.java
@@ -2,6 +2,7 @@ package net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.e
 
 import lombok.Getter;
 import lombok.Setter;
+import net.geant.nmaas.externalservices.kubernetes.entities.KCluster;
 import net.geant.nmaas.nmservice.deployment.entities.NmServiceInfo;
 import net.geant.nmaas.orchestration.Identifier;
 
@@ -38,6 +39,8 @@ public class KubernetesNmServiceInfo extends NmServiceInfo {
     @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
     private Set<ServiceAccessMethod> accessMethods;
 
+    private KCluster remoteCluster;
+
     public KubernetesNmServiceInfo () {
         super();
     }
@@ -46,4 +49,9 @@ public class KubernetesNmServiceInfo extends NmServiceInfo {
         super(deploymentId, deploymentName, domain, descriptiveDeploymentId);
     }
 
+    public KubernetesNmServiceInfo(Identifier deploymentId, String deploymentName, String domain, Identifier descriptiveDeploymentId, KCluster kCluster) {
+        super(deploymentId, deploymentName, domain, descriptiveDeploymentId);
+        this.remoteCluster = kCluster;
+    }
+
 }
diff --git a/src/main/java/net/geant/nmaas/orchestration/entities/AppDeployment.java b/src/main/java/net/geant/nmaas/orchestration/entities/AppDeployment.java
index 73173f116..6593de170 100644
--- a/src/main/java/net/geant/nmaas/orchestration/entities/AppDeployment.java
+++ b/src/main/java/net/geant/nmaas/orchestration/entities/AppDeployment.java
@@ -127,6 +127,8 @@ public class AppDeployment {
 
     private Long instanceId;
 
+    private Long remoteClusterId;
+
     /**
      * Globally unique descriptive application deployment identifier
      */
diff --git a/src/main/java/net/geant/nmaas/orchestration/tasks/app/AppRequestVerificationTask.java b/src/main/java/net/geant/nmaas/orchestration/tasks/app/AppRequestVerificationTask.java
index 3810ab4bb..f7d1e2993 100644
--- a/src/main/java/net/geant/nmaas/orchestration/tasks/app/AppRequestVerificationTask.java
+++ b/src/main/java/net/geant/nmaas/orchestration/tasks/app/AppRequestVerificationTask.java
@@ -2,6 +2,7 @@ package net.geant.nmaas.orchestration.tasks.app;
 
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import net.geant.nmaas.externalservices.kubernetes.RemoteClusterManager;
 import net.geant.nmaas.nmservice.deployment.NmServiceDeploymentProvider;
 import net.geant.nmaas.orchestration.Identifier;
 import net.geant.nmaas.orchestration.entities.AppDeployment;
@@ -29,6 +30,8 @@ public class AppRequestVerificationTask {
     private AppDeploymentRepository repository;
     private ApplicationRepository appRepository;
 
+    private RemoteClusterManager remoteClusterManager;
+
     @EventListener
     @Loggable(LogLevel.INFO)
     @Transactional(propagation = Propagation.REQUIRES_NEW)
@@ -39,6 +42,9 @@ public class AppRequestVerificationTask {
             final AppDeployment appDeployment = repository.findByDeploymentId(deploymentId).orElseThrow(() -> new InvalidDeploymentIdException(deploymentId));
             final Application application = appRepository.findById(Long.valueOf(appDeployment.getApplicationId().getValue())).orElseThrow(() ->
                     new InvalidApplicationIdException("Application for deployment " + deploymentId + " does not exist in repository"));
+            if(!remoteClusterManager.clusterExist(appDeployment.getRemoteClusterId())) {
+                throw new InvalidDeploymentIdException("Wrong remote cluster Id");
+            }
             serviceDeployment.verifyRequest(
                     deploymentId,
                     appDeployment,
diff --git a/src/main/java/net/geant/nmaas/portal/api/market/AppInstanceController.java b/src/main/java/net/geant/nmaas/portal/api/market/AppInstanceController.java
index 81365d8a6..0a2f7e395 100644
--- a/src/main/java/net/geant/nmaas/portal/api/market/AppInstanceController.java
+++ b/src/main/java/net/geant/nmaas/portal/api/market/AppInstanceController.java
@@ -297,6 +297,7 @@ public class AppInstanceController extends AppBaseController {
                 .owner(principal.getName())
                 .appName(app.getName())
                 .descriptiveDeploymentId(createDescriptiveDeploymentId(domain.getCodename(), app.getName(), appInstance.getId()))
+                .remoteClusterId(clusterId)
                 .build();
 
         Identifier internalId = appLifecycleManager.deployApplication(appDeployment);
diff --git a/src/main/java/net/geant/nmaas/portal/service/impl/DomainServiceImpl.java b/src/main/java/net/geant/nmaas/portal/service/impl/DomainServiceImpl.java
index 5af2eeecb..88cad0edc 100644
--- a/src/main/java/net/geant/nmaas/portal/service/impl/DomainServiceImpl.java
+++ b/src/main/java/net/geant/nmaas/portal/service/impl/DomainServiceImpl.java
@@ -200,7 +200,7 @@ public class DomainServiceImpl implements DomainService {
                 eventPublisher.publishEvent(new DomainCreatedEvent(this, new DomainCreatedEvent.DomainSpec(saved.getId(), saved.getName(), saved.getCodename(), request.getAnnotations())));
             }
             //call existing webhooks
-            webhookEventRepository.findIdByEventType(WebhookEventType.DOMAIN_CREATION).forEach(id -> scheduleManager.createOneTimeJob(DomainCreationJob.class, "DomainCreation_" + id + "_" + saved.getId(), Map.of("webhookId", id, "domainId", saved.getId())));
+//            webhookEventRepository.findIdByEventType(WebhookEventType.DOMAIN_CREATION).forEach(id -> scheduleManager.createOneTimeJob(DomainCreationJob.class, "DomainCreation_" + id + "_" + saved.getId(), Map.of("webhookId", id, "domainId", saved.getId())));
             return saved;
         } catch (Exception ex) {
             throw new ProcessingException("Unable to create new domain with given name or codename.");
diff --git a/src/test/java/net/geant/nmaas/orchestration/tasks/app/AppRequestVerificationTaskTest.java b/src/test/java/net/geant/nmaas/orchestration/tasks/app/AppRequestVerificationTaskTest.java
index 6171c1023..8112568ad 100644
--- a/src/test/java/net/geant/nmaas/orchestration/tasks/app/AppRequestVerificationTaskTest.java
+++ b/src/test/java/net/geant/nmaas/orchestration/tasks/app/AppRequestVerificationTaskTest.java
@@ -1,5 +1,6 @@
 package net.geant.nmaas.orchestration.tasks.app;
 
+import net.geant.nmaas.externalservices.kubernetes.RemoteClusterManager;
 import net.geant.nmaas.nmservice.deployment.NmServiceDeploymentProvider;
 import net.geant.nmaas.orchestration.Identifier;
 import net.geant.nmaas.orchestration.entities.AppDeployment;
@@ -25,6 +26,7 @@ public class AppRequestVerificationTaskTest {
     private NmServiceDeploymentProvider deploy = mock(NmServiceDeploymentProvider.class);
     private AppDeploymentRepository deployments = mock(AppDeploymentRepository.class);
     private ApplicationRepository applications = mock(ApplicationRepository.class);
+    private RemoteClusterManager remoteClusterManager = mock(RemoteClusterManager.class);
 
     private AppRequestVerificationTask task;
 
@@ -33,7 +35,7 @@ public class AppRequestVerificationTaskTest {
 
     @BeforeEach
     public void setup() {
-        task = new AppRequestVerificationTask(deploy, deployments, applications);
+        task = new AppRequestVerificationTask(deploy, deployments, applications, remoteClusterManager);
     }
 
     @Test
-- 
GitLab


From a163faff515fec57468d9ba541feba71f3c20ee4 Mon Sep 17 00:00:00 2001
From: kbeyro <121854496+kbeyro@users.noreply.github.com>
Date: Tue, 27 May 2025 14:43:24 +0200
Subject: [PATCH 04/13] reverse domain service comment

---
 .../net/geant/nmaas/portal/service/impl/DomainServiceImpl.java  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main/java/net/geant/nmaas/portal/service/impl/DomainServiceImpl.java b/src/main/java/net/geant/nmaas/portal/service/impl/DomainServiceImpl.java
index 88cad0edc..5af2eeecb 100644
--- a/src/main/java/net/geant/nmaas/portal/service/impl/DomainServiceImpl.java
+++ b/src/main/java/net/geant/nmaas/portal/service/impl/DomainServiceImpl.java
@@ -200,7 +200,7 @@ public class DomainServiceImpl implements DomainService {
                 eventPublisher.publishEvent(new DomainCreatedEvent(this, new DomainCreatedEvent.DomainSpec(saved.getId(), saved.getName(), saved.getCodename(), request.getAnnotations())));
             }
             //call existing webhooks
-//            webhookEventRepository.findIdByEventType(WebhookEventType.DOMAIN_CREATION).forEach(id -> scheduleManager.createOneTimeJob(DomainCreationJob.class, "DomainCreation_" + id + "_" + saved.getId(), Map.of("webhookId", id, "domainId", saved.getId())));
+            webhookEventRepository.findIdByEventType(WebhookEventType.DOMAIN_CREATION).forEach(id -> scheduleManager.createOneTimeJob(DomainCreationJob.class, "DomainCreation_" + id + "_" + saved.getId(), Map.of("webhookId", id, "domainId", saved.getId())));
             return saved;
         } catch (Exception ex) {
             throw new ProcessingException("Unable to create new domain with given name or codename.");
-- 
GitLab


From 644da20d70ba0114a3f92bb8be221fccc0e48114 Mon Sep 17 00:00:00 2001
From: kbeyro <121854496+kbeyro@users.noreply.github.com>
Date: Tue, 27 May 2025 15:04:24 +0200
Subject: [PATCH 05/13] refactor

---
 .../entities/KClusterDeployment.java          |  4 +++
 .../kubernetes/KubernetesManager.java         | 25 +++++++----------
 .../components/helm/HelmCommand.java          |  2 +-
 .../components/helm/HelmKServiceManager.java  | 27 ++++++++++++++-----
 .../helm/commands/HelmInstallCommand.java     |  7 ++---
 .../tasks/app/AppRequestVerificationTask.java |  3 ++-
 6 files changed, 41 insertions(+), 27 deletions(-)

diff --git a/src/main/java/net/geant/nmaas/externalservices/kubernetes/entities/KClusterDeployment.java b/src/main/java/net/geant/nmaas/externalservices/kubernetes/entities/KClusterDeployment.java
index a35995704..7db61dcff 100644
--- a/src/main/java/net/geant/nmaas/externalservices/kubernetes/entities/KClusterDeployment.java
+++ b/src/main/java/net/geant/nmaas/externalservices/kubernetes/entities/KClusterDeployment.java
@@ -12,6 +12,10 @@ import lombok.Builder;
 import lombok.Getter;
 import lombok.NoArgsConstructor;
 import lombok.Setter;
+import net.geant.nmaas.orchestration.entities.DomainTechDetails;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Optional;
 
 @Entity
 @Table(name = "k_cluster_deployment")
diff --git a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/KubernetesManager.java b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/KubernetesManager.java
index b4668e77e..752b3fa95 100644
--- a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/KubernetesManager.java
+++ b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/KubernetesManager.java
@@ -98,26 +98,19 @@ public class KubernetesManager implements ContainerOrchestrator {
         } catch (IllegalArgumentException iae) {
             throw new NmServiceRequestVerificationException(iae.getMessage());
         }
-
-        KubernetesNmServiceInfo serviceInfo;
+        //todo
+
+        KubernetesNmServiceInfo serviceInfo = new KubernetesNmServiceInfo(
+                deploymentId,
+                appDeployment.getDeploymentName(),
+                appDeployment.getDomain(),
+                appDeployment.getDescriptiveDeploymentId()
+        );
         //verify cluster
         if(remoteClusterManager.clusterExist(appDeployment.getRemoteClusterId())) {
-            serviceInfo = new KubernetesNmServiceInfo(
-                    deploymentId,
-                    appDeployment.getDeploymentName(),
-                    appDeployment.getDomain(),
-                    appDeployment.getDescriptiveDeploymentId(),
-                    remoteClusterManager.getCluster(appDeployment.getRemoteClusterId()));
-        } else {
-            serviceInfo = new KubernetesNmServiceInfo(
-                    deploymentId,
-                    appDeployment.getDeploymentName(),
-                    appDeployment.getDomain(),
-                    appDeployment.getDescriptiveDeploymentId()
-            );
+           serviceInfo.setRemoteCluster(remoteClusterManager.getCluster(appDeployment.getRemoteClusterId()));
         }
 
-
         serviceInfo.setKubernetesTemplate(KubernetesTemplate.copy(appDeploymentSpec.getKubernetesTemplate()));
         serviceInfo.setStorageVolumes(generateTemplateStorageVolumes(appDeploymentSpec.getStorageVolumes()));
         serviceInfo.setAccessMethods(generateTemplateAccessMethods(appDeploymentSpec.getAccessMethods()));
diff --git a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmCommand.java b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmCommand.java
index fb2e4bd9f..0aaf87e86 100644
--- a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmCommand.java
+++ b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmCommand.java
@@ -16,7 +16,7 @@ public abstract class HelmCommand implements Command {
     protected static final String HELM_VERSION_2 = "v2";
     protected static final String HELM_VERSION_3 = "v3";
 
-    protected static final String KUBECONFIG = "--kubeconfig";
+    protected static final String OPTION_KUBECONFIG = "--kubeconfig";
 
     protected String command;
 
diff --git a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmKServiceManager.java b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmKServiceManager.java
index 1cd6308ae..5419effb4 100644
--- a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmKServiceManager.java
+++ b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmKServiceManager.java
@@ -7,6 +7,7 @@ import net.geant.nmaas.externalservices.kubernetes.KubernetesClusterIngressManag
 import net.geant.nmaas.externalservices.kubernetes.KubernetesClusterNamespaceService;
 import net.geant.nmaas.externalservices.kubernetes.entities.IngressCertificateConfigOption;
 import net.geant.nmaas.externalservices.kubernetes.entities.IngressResourceConfigOption;
+import net.geant.nmaas.externalservices.kubernetes.entities.KCluster;
 import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.KServiceLifecycleManager;
 import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.KubernetesRepositoryManager;
 import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.entities.KubernetesNmServiceInfo;
@@ -82,20 +83,34 @@ public class HelmKServiceManager implements KServiceLifecycleManager {
 
     private Map<String, String> createArgumentsMap(KubernetesNmServiceInfo serviceInfo) {
         Map<String, String> arguments = new HashMap<>();
-        if (deploymentManager.getForceDedicatedWorkers()) {
-            arguments.put(HELM_INSTALL_OPTION_DEDICATED_WORKERS, serviceInfo.getDomain());
-        }
+
         Set<ServiceStorageVolume> serviceStorageVolumes = serviceInfo.getStorageVolumes();
         if (!serviceStorageVolumes.isEmpty()) {
             arguments.putAll(getPersistenceVariables(serviceStorageVolumes, deploymentManager.getStorageClass(serviceInfo.getDomain()), serviceInfo.getDescriptiveDeploymentId().getValue()));
         }
-        Set<ServiceAccessMethod> externalAccessMethods = serviceExternalAccessMethods(serviceInfo.getAccessMethods());
-        if (!externalAccessMethods.isEmpty()) {
-            arguments.putAll(getIngressVariables(ingressManager.getResourceConfigOption(), externalAccessMethods, serviceInfo.getDomain()));
+
+        if(serviceInfo.getRemoteCluster() == null) {
+            if (deploymentManager.getForceDedicatedWorkers()) {
+                arguments.put(HELM_INSTALL_OPTION_DEDICATED_WORKERS, serviceInfo.getDomain());
+            }
+            Set<ServiceAccessMethod> externalAccessMethods = serviceExternalAccessMethods(serviceInfo.getAccessMethods());
+            if (!externalAccessMethods.isEmpty()) {
+                arguments.putAll(getIngressVariables(ingressManager.getResourceConfigOption(), externalAccessMethods, serviceInfo.getDomain()));
+            }
+        } else {
+            if (serviceInfo.getRemoteCluster().getDeployment().getForceDedicatedWorkers()) {
+                arguments.put(HELM_INSTALL_OPTION_DEDICATED_WORKERS, serviceInfo.getDomain());
+            }
+            Set<ServiceAccessMethod> externalAccessMethods = serviceExternalAccessMethods(serviceInfo.getAccessMethods());
+            if (!externalAccessMethods.isEmpty()) {
+                arguments.putAll(getIngressVariables(serviceInfo.getRemoteCluster().getIngress().getResourceConfigOption(), externalAccessMethods, serviceInfo.getDomain()));
+            }
         }
+
         if (serviceInfo.getAdditionalParameters() != null && !serviceInfo.getAdditionalParameters().isEmpty()) {
             arguments.putAll(removeRedundantParameters(serviceInfo.getAdditionalParameters()));
         }
+
         return arguments;
     }
 
diff --git a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/commands/HelmInstallCommand.java b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/commands/HelmInstallCommand.java
index c5cab7455..692e26b54 100644
--- a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/commands/HelmInstallCommand.java
+++ b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/commands/HelmInstallCommand.java
@@ -27,6 +27,10 @@ public class HelmInstallCommand extends HelmCommand {
      */
     public static HelmInstallCommand commandWithRepo(String helmVersion, String namespace, String releaseName, Map<String, String> values, String chartName, String chartVersion, boolean enableTls, String kubeConfigPath) {
         StringBuilder sb = buildBaseInstallCommand(helmVersion, namespace, releaseName, values);
+
+        if(kubeConfigPath != null && !kubeConfigPath.isEmpty()) {
+            sb.append(SPACE).append(OPTION_KUBECONFIG).append(SPACE).append(kubeConfigPath);
+        }
         if (chartName == null || chartName.isEmpty()) {
             throw new IllegalArgumentException("Chart name can't be null or empty");
         }
@@ -36,9 +40,6 @@ public class HelmInstallCommand extends HelmCommand {
         }
         addTlsOptionIfRequired(helmVersion, enableTls, sb);
 
-        if(kubeConfigPath != null && !kubeConfigPath.isEmpty()) {
-            sb.append(SPACE).append(KUBECONFIG).append(SPACE).append(kubeConfigPath);
-        }
         return new HelmInstallCommand(sb.toString());
     }
 
diff --git a/src/main/java/net/geant/nmaas/orchestration/tasks/app/AppRequestVerificationTask.java b/src/main/java/net/geant/nmaas/orchestration/tasks/app/AppRequestVerificationTask.java
index f7d1e2993..cd623ce85 100644
--- a/src/main/java/net/geant/nmaas/orchestration/tasks/app/AppRequestVerificationTask.java
+++ b/src/main/java/net/geant/nmaas/orchestration/tasks/app/AppRequestVerificationTask.java
@@ -19,6 +19,7 @@ import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
 
+import javax.naming.directory.InvalidAttributesException;
 import java.time.LocalDateTime;
 
 @Component
@@ -43,7 +44,7 @@ public class AppRequestVerificationTask {
             final Application application = appRepository.findById(Long.valueOf(appDeployment.getApplicationId().getValue())).orElseThrow(() ->
                     new InvalidApplicationIdException("Application for deployment " + deploymentId + " does not exist in repository"));
             if(!remoteClusterManager.clusterExist(appDeployment.getRemoteClusterId())) {
-                throw new InvalidDeploymentIdException("Wrong remote cluster Id");
+                throw new InvalidAttributesException("Wrong remote cluster Id");
             }
             serviceDeployment.verifyRequest(
                     deploymentId,
-- 
GitLab


From a30f767be31ebd4084bf8eac6b4525372a24943f Mon Sep 17 00:00:00 2001
From: kbeyro <121854496+kbeyro@users.noreply.github.com>
Date: Tue, 27 May 2025 15:33:06 +0200
Subject: [PATCH 06/13] add test

---
 .../kubernetes/KubernetesManagerTest.java     |  5 +-
 .../helm/HelmCommandPreparationTest.java      | 16 ++--
 .../helm/HelmKServiceManagerTest.java         | 73 ++++++++++++++++++-
 3 files changed, 82 insertions(+), 12 deletions(-)

diff --git a/src/test/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/KubernetesManagerTest.java b/src/test/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/KubernetesManagerTest.java
index e73112393..71dfd8bbe 100644
--- a/src/test/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/KubernetesManagerTest.java
+++ b/src/test/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/KubernetesManagerTest.java
@@ -2,6 +2,7 @@ package net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes;
 
 import com.google.common.collect.Sets;
 import net.geant.nmaas.externalservices.kubernetes.KubernetesClusterIngressManager;
+import net.geant.nmaas.externalservices.kubernetes.RemoteClusterManager;
 import net.geant.nmaas.externalservices.kubernetes.entities.IngressControllerConfigOption;
 import net.geant.nmaas.gitlab.GitLabManager;
 import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.components.cluster.DefaultKClusterValidator;
@@ -69,6 +70,7 @@ public class KubernetesManagerTest {
     private final KubernetesClusterIngressManager ingressManager = mock(KubernetesClusterIngressManager.class);
     private final GitLabManager gitLabManager = mock(GitLabManager.class);
     private final JanitorService janitorService = mock(JanitorService.class);
+    private final RemoteClusterManager remoteClusterManager = mock(RemoteClusterManager.class);
 
     private static final Identifier DEPLOYMENT_ID = Identifier.newInstance("deploymentId");
 
@@ -82,7 +84,8 @@ public class KubernetesManagerTest {
             ingressResourceManager,
             ingressManager,
             gitLabManager,
-            janitorService
+            janitorService,
+            remoteClusterManager
     );
 
     @BeforeEach
diff --git a/src/test/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmCommandPreparationTest.java b/src/test/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmCommandPreparationTest.java
index 74b905252..9bd0e19eb 100644
--- a/src/test/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmCommandPreparationTest.java
+++ b/src/test/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmCommandPreparationTest.java
@@ -57,7 +57,7 @@ public class HelmCommandPreparationTest {
                         RELEASE_NAME,
                         null,
                         CHART_NAME_WITH_REPO,
-                        null, false).asString(),
+                        null, false, null).asString(),
                 equalTo(CORRECT_HELM_INSTALL_COMMAND_USING_CHART_FROM_REPO));
         assertThat(
                 HelmInstallCommand.commandWithRepo(
@@ -66,7 +66,7 @@ public class HelmCommandPreparationTest {
                         RELEASE_NAME,
                         null,
                         CHART_NAME_WITH_REPO,
-                        CHART_VERSION, false).asString(),
+                        CHART_VERSION, false, null).asString(),
                 equalTo(CORRECT_HELM_INSTALL_COMMAND_USING_CHART_FROM_REPO_WITH_VERSION));
     }
 
@@ -79,7 +79,7 @@ public class HelmCommandPreparationTest {
                         RELEASE_NAME,
                         null,
                         CHART_NAME_WITH_REPO,
-                        null, false).asString(),
+                        null, false, null).asString(),
                 equalTo(CORRECT_HELM_INSTALL_COMMAND_FOR_v3_USING_CHART_FROM_REPO));
         assertThat(
                 HelmInstallCommand.commandWithRepo(
@@ -88,7 +88,7 @@ public class HelmCommandPreparationTest {
                         RELEASE_NAME,
                         null,
                         CHART_NAME_WITH_REPO,
-                        CHART_VERSION, false).asString(),
+                        CHART_VERSION, false, null).asString(),
                 equalTo(CORRECT_HELM_INSTALL_COMMAND_FOR_V3_USING_CHART_FROM_REPO_WITH_VERSION));
     }
 
@@ -101,7 +101,7 @@ public class HelmCommandPreparationTest {
                         RELEASE_NAME,
                         null,
                         CHART_NAME_WITH_REPO,
-                        null, true).asString(),
+                        null, true, null).asString(),
                 equalTo(CORRECT_HELM_INSTALL_COMMAND_USING_CHART_FROM_REPO + TLS));
         assertThat(
                 HelmInstallCommand.commandWithRepo(
@@ -110,7 +110,7 @@ public class HelmCommandPreparationTest {
                         RELEASE_NAME,
                         null,
                         CHART_NAME_WITH_REPO,
-                        CHART_VERSION, true).asString(),
+                        CHART_VERSION, true, null).asString(),
                 equalTo(CORRECT_HELM_INSTALL_COMMAND_USING_CHART_FROM_REPO_WITH_VERSION + TLS));
     }
 
@@ -127,7 +127,7 @@ public class HelmCommandPreparationTest {
                         arguments,
                         CHART_NAME_WITH_REPO,
                         CHART_VERSION,
-                        false).asString(),
+                        false, null).asString(),
                 allOf(containsString(CORRECT_HELM_INSTALL_COMMAND_FIRST_PART),
                         containsString("testPersistenceName"),
                         containsString("testStorageClass"))
@@ -147,7 +147,7 @@ public class HelmCommandPreparationTest {
                         arguments,
                         CHART_NAME_WITH_REPO,
                         CHART_VERSION,
-                        true).asString(),
+                        true, null).asString(),
                 allOf(containsString(CORRECT_HELM_INSTALL_COMMAND_FIRST_PART),
                         containsString("testPersistenceName"),
                         containsString("testStorageClass"),
diff --git a/src/test/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmKServiceManagerTest.java b/src/test/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmKServiceManagerTest.java
index b3e27ed59..f74395561 100644
--- a/src/test/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmKServiceManagerTest.java
+++ b/src/test/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmKServiceManagerTest.java
@@ -5,6 +5,11 @@ import net.geant.nmaas.externalservices.kubernetes.KubernetesClusterIngressManag
 import net.geant.nmaas.externalservices.kubernetes.KubernetesClusterNamespaceService;
 import net.geant.nmaas.externalservices.kubernetes.entities.IngressCertificateConfigOption;
 import net.geant.nmaas.externalservices.kubernetes.entities.IngressResourceConfigOption;
+import net.geant.nmaas.externalservices.kubernetes.entities.KCluster;
+import net.geant.nmaas.externalservices.kubernetes.entities.KClusterDeployment;
+import net.geant.nmaas.externalservices.kubernetes.entities.KClusterIngress;
+import net.geant.nmaas.externalservices.kubernetes.entities.KClusterState;
+import net.geant.nmaas.externalservices.kubernetes.entities.NamespaceConfigOption;
 import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.KubernetesRepositoryManager;
 import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.entities.KubernetesNmServiceInfo;
 import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.entities.KubernetesTemplate;
@@ -18,6 +23,7 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.mockito.ArgumentCaptor;
 
+import java.time.OffsetDateTime;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
@@ -119,7 +125,8 @@ public class HelmKServiceManagerTest {
                 eq("namespace"),
                 eq("descriptiveDeploymentId"),
                 k8sTemplateArg.capture(),
-                argumentsArg.capture(), null
+                argumentsArg.capture(),
+                eq(null)
         );
         assertThat(argumentsArg.getValue()).isNotEmpty();
         assertThat(argumentsArg.getValue().size()).isEqualTo(11);
@@ -142,8 +149,9 @@ public class HelmKServiceManagerTest {
         verify(helmCommandExecutor, times(1)).executeHelmInstallCommand(
                 eq("namespace"),
                 eq("descriptiveDeploymentId"),
-                any(),
-                any(), null
+                any(KubernetesTemplate.class),
+                any(Map.class),
+                eq(null)
         );
     }
 
@@ -228,4 +236,63 @@ public class HelmKServiceManagerTest {
         );
     }
 
+    @Test
+    void shouldDeployServiceWithKubeconfigPath() {
+        when(namespaceService.namespace("domain")).thenReturn("namespace");
+        when(ingressManager.getResourceConfigOption()).thenReturn(IngressResourceConfigOption.DEPLOY_FROM_CHART);
+        when(ingressManager.getIngressPerDomain()).thenReturn(false);
+        when(ingressManager.getSupportedIngressClass()).thenReturn("testIngressClass");
+        when(ingressManager.getTlsSupported()).thenReturn(true);
+        when(ingressManager.getIssuerOrWildcardName()).thenReturn("testIssuerName");
+        when(ingressManager.getCertificateConfigOption()).thenReturn(IngressCertificateConfigOption.USE_LETSENCRYPT);
+
+
+        KClusterDeployment mockDeployment = KClusterDeployment.builder()
+                .namespaceConfigOption(NamespaceConfigOption.CREATE_NAMESPACE)
+                .defaultNamespace("default-namespace")
+                .defaultStorageClass("default-storage-class")
+                .smtpServerHostname("smtp.example.com")
+                .smtpServerPort(587)
+                .smtpServerUsername("user@example.com")
+                .smtpServerPassword("password")
+                .smtpFromDefaultDomain("example.com")
+                .forceDedicatedWorkers(true)
+                .build();
+
+        KClusterIngress mockIngress = KClusterIngress.builder().resourceConfigOption(IngressResourceConfigOption.NOT_USED).build();
+
+
+        KCluster mockCluster = KCluster.builder()
+                .id(1L)
+                .name("TestCluster")
+                .codename("test-cluster")
+                .description("Mocked Kubernetes Cluster")
+                .creationDate(OffsetDateTime.now())
+                .modificationDate(OffsetDateTime.now())
+                .clusterConfigFile("mock-cluster-config")
+                .pathConfigFile("mock/path/to/kubeconfig")
+                .state(KClusterState.UNKNOWN)
+                .currentStateSince(OffsetDateTime.now())
+                .contactEmail("test@example.com")
+                .deployment(mockDeployment)
+                .ingress(mockIngress)
+                .build();
+
+        KubernetesNmServiceInfo service = repositoryManager.loadService(deploymentId);
+        service.setRemoteCluster(mockCluster);
+        when(repositoryManager.loadService(deploymentId)).thenReturn(service);
+
+        manager.deployService(deploymentId);
+
+        ArgumentCaptor<String> kubeconfigPathArg = ArgumentCaptor.forClass(String.class);
+        verify(helmCommandExecutor, times(1)).executeHelmInstallCommand(
+                eq("namespace"),
+                eq("descriptiveDeploymentId"),
+                any(KubernetesTemplate.class),
+                any(Map.class),
+                kubeconfigPathArg.capture()
+        );
+        assertThat(kubeconfigPathArg.getValue()).isEqualTo("mock/path/to/kubeconfig");
+    }
+
 }
-- 
GitLab


From e8bd0fa7afe119e3ac2f89feb6a9bdfb87c8a921 Mon Sep 17 00:00:00 2001
From: kbeyro <121854496+kbeyro@users.noreply.github.com>
Date: Tue, 27 May 2025 15:35:56 +0200
Subject: [PATCH 07/13] add connection to cluster from nm service

---
 .../kubernetes/entities/KubernetesNmServiceInfo.java          | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/entities/KubernetesNmServiceInfo.java b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/entities/KubernetesNmServiceInfo.java
index 7c77eb865..61203bf07 100644
--- a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/entities/KubernetesNmServiceInfo.java
+++ b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/entities/KubernetesNmServiceInfo.java
@@ -1,5 +1,7 @@
 package net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.entities;
 
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
 import lombok.Getter;
 import lombok.Setter;
 import net.geant.nmaas.externalservices.kubernetes.entities.KCluster;
@@ -39,6 +41,8 @@ public class KubernetesNmServiceInfo extends NmServiceInfo {
     @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
     private Set<ServiceAccessMethod> accessMethods;
 
+    @ManyToOne
+    @JoinColumn(name = "kcluster_id", referencedColumnName = "id")
     private KCluster remoteCluster;
 
     public KubernetesNmServiceInfo () {
-- 
GitLab


From ba22336e3fa35e4d5d8f6769506ff76cc06c8a53 Mon Sep 17 00:00:00 2001
From: kbeyro <121854496+kbeyro@users.noreply.github.com>
Date: Tue, 27 May 2025 15:42:28 +0200
Subject: [PATCH 08/13] add migration

---
 .../V1.8.0_20250527_1530__AddConnectionToCluster.sql  | 11 +++++++++++
 1 file changed, 11 insertions(+)
 create mode 100644 src/main/resources/db/migration/common/V1.8.0_20250527_1530__AddConnectionToCluster.sql

diff --git a/src/main/resources/db/migration/common/V1.8.0_20250527_1530__AddConnectionToCluster.sql b/src/main/resources/db/migration/common/V1.8.0_20250527_1530__AddConnectionToCluster.sql
new file mode 100644
index 000000000..0316f56e7
--- /dev/null
+++ b/src/main/resources/db/migration/common/V1.8.0_20250527_1530__AddConnectionToCluster.sql
@@ -0,0 +1,11 @@
+ALTER TABLE kubernetes_nm_service_info
+ADD COLUMN kcluster_id integer;
+
+ALTER TABLE kubernetes_nm_service_info
+ADD CONSTRAINT fk_kubernetes_nm_service_info_kcluster
+FOREIGN KEY (kcluster_id)
+REFERENCES kcluster (id)
+ON DELETE SET NULL;
+
+ALTER TABLE app_deployment
+ADD COLUMN remote_cluster_id integer;
\ No newline at end of file
-- 
GitLab


From 8a97cb352d03abe9bf4630456b48828e139ad91a Mon Sep 17 00:00:00 2001
From: kbeyro <121854496+kbeyro@users.noreply.github.com>
Date: Tue, 27 May 2025 15:47:24 +0200
Subject: [PATCH 09/13] fix test

---
 .../orchestration/tasks/app/AppRequestVerificationTaskTest.java  | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/test/java/net/geant/nmaas/orchestration/tasks/app/AppRequestVerificationTaskTest.java b/src/test/java/net/geant/nmaas/orchestration/tasks/app/AppRequestVerificationTaskTest.java
index 8112568ad..53b50f799 100644
--- a/src/test/java/net/geant/nmaas/orchestration/tasks/app/AppRequestVerificationTaskTest.java
+++ b/src/test/java/net/geant/nmaas/orchestration/tasks/app/AppRequestVerificationTaskTest.java
@@ -42,6 +42,7 @@ public class AppRequestVerificationTaskTest {
     public void shouldTriggerRequestVerify() throws InterruptedException {
         when(deployments.findByDeploymentId(deploymentId)).thenReturn(Optional.of(AppDeployment.builder().applicationId(Identifier.newInstance(10L)).build()));
         when(applications.findById(any(Long.class))).thenReturn(Optional.of(new Application()));
+        when(remoteClusterManager.clusterExist(any())).thenReturn(true);
         task.trigger(new AppVerifyRequestActionEvent(this, deploymentId));
         verify(deploy, times(1)).verifyRequest(any(Identifier.class), any(AppDeployment.class), isNull());
     }
-- 
GitLab


From 95c0b7ec6e162c20e19b9e46df96392b762b5f9b Mon Sep 17 00:00:00 2001
From: kbeyro <121854496+kbeyro@users.noreply.github.com>
Date: Tue, 27 May 2025 15:49:47 +0200
Subject: [PATCH 10/13] small refactor

---
 .../externalservices/kubernetes/RemoteClusterManager.java     | 2 +-
 .../kubernetes/entities/KClusterDeployment.java               | 4 ----
 .../containerorchestrators/kubernetes/KubernetesManager.java  | 2 +-
 .../orchestration/tasks/app/AppRequestVerificationTask.java   | 2 +-
 .../tasks/app/AppRequestVerificationTaskTest.java             | 2 +-
 5 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/src/main/java/net/geant/nmaas/externalservices/kubernetes/RemoteClusterManager.java b/src/main/java/net/geant/nmaas/externalservices/kubernetes/RemoteClusterManager.java
index 7ab5cf48d..e8a450a03 100644
--- a/src/main/java/net/geant/nmaas/externalservices/kubernetes/RemoteClusterManager.java
+++ b/src/main/java/net/geant/nmaas/externalservices/kubernetes/RemoteClusterManager.java
@@ -349,7 +349,7 @@ public class RemoteClusterManager implements ClusterMonitoringService {
 
     }
 
-    public boolean clusterExist(Long id) {
+    public boolean clusterExists(Long id) {
         return clusterRepository.existsById(id);
     }
 
diff --git a/src/main/java/net/geant/nmaas/externalservices/kubernetes/entities/KClusterDeployment.java b/src/main/java/net/geant/nmaas/externalservices/kubernetes/entities/KClusterDeployment.java
index 7db61dcff..a35995704 100644
--- a/src/main/java/net/geant/nmaas/externalservices/kubernetes/entities/KClusterDeployment.java
+++ b/src/main/java/net/geant/nmaas/externalservices/kubernetes/entities/KClusterDeployment.java
@@ -12,10 +12,6 @@ import lombok.Builder;
 import lombok.Getter;
 import lombok.NoArgsConstructor;
 import lombok.Setter;
-import net.geant.nmaas.orchestration.entities.DomainTechDetails;
-import org.apache.commons.lang3.StringUtils;
-
-import java.util.Optional;
 
 @Entity
 @Table(name = "k_cluster_deployment")
diff --git a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/KubernetesManager.java b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/KubernetesManager.java
index 752b3fa95..ab50670ce 100644
--- a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/KubernetesManager.java
+++ b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/KubernetesManager.java
@@ -107,7 +107,7 @@ public class KubernetesManager implements ContainerOrchestrator {
                 appDeployment.getDescriptiveDeploymentId()
         );
         //verify cluster
-        if(remoteClusterManager.clusterExist(appDeployment.getRemoteClusterId())) {
+        if(remoteClusterManager.clusterExists(appDeployment.getRemoteClusterId())) {
            serviceInfo.setRemoteCluster(remoteClusterManager.getCluster(appDeployment.getRemoteClusterId()));
         }
 
diff --git a/src/main/java/net/geant/nmaas/orchestration/tasks/app/AppRequestVerificationTask.java b/src/main/java/net/geant/nmaas/orchestration/tasks/app/AppRequestVerificationTask.java
index cd623ce85..1da23840c 100644
--- a/src/main/java/net/geant/nmaas/orchestration/tasks/app/AppRequestVerificationTask.java
+++ b/src/main/java/net/geant/nmaas/orchestration/tasks/app/AppRequestVerificationTask.java
@@ -43,7 +43,7 @@ public class AppRequestVerificationTask {
             final AppDeployment appDeployment = repository.findByDeploymentId(deploymentId).orElseThrow(() -> new InvalidDeploymentIdException(deploymentId));
             final Application application = appRepository.findById(Long.valueOf(appDeployment.getApplicationId().getValue())).orElseThrow(() ->
                     new InvalidApplicationIdException("Application for deployment " + deploymentId + " does not exist in repository"));
-            if(!remoteClusterManager.clusterExist(appDeployment.getRemoteClusterId())) {
+            if(!remoteClusterManager.clusterExists(appDeployment.getRemoteClusterId())) {
                 throw new InvalidAttributesException("Wrong remote cluster Id");
             }
             serviceDeployment.verifyRequest(
diff --git a/src/test/java/net/geant/nmaas/orchestration/tasks/app/AppRequestVerificationTaskTest.java b/src/test/java/net/geant/nmaas/orchestration/tasks/app/AppRequestVerificationTaskTest.java
index 53b50f799..622f4cd25 100644
--- a/src/test/java/net/geant/nmaas/orchestration/tasks/app/AppRequestVerificationTaskTest.java
+++ b/src/test/java/net/geant/nmaas/orchestration/tasks/app/AppRequestVerificationTaskTest.java
@@ -42,7 +42,7 @@ public class AppRequestVerificationTaskTest {
     public void shouldTriggerRequestVerify() throws InterruptedException {
         when(deployments.findByDeploymentId(deploymentId)).thenReturn(Optional.of(AppDeployment.builder().applicationId(Identifier.newInstance(10L)).build()));
         when(applications.findById(any(Long.class))).thenReturn(Optional.of(new Application()));
-        when(remoteClusterManager.clusterExist(any())).thenReturn(true);
+        when(remoteClusterManager.clusterExists(any())).thenReturn(true);
         task.trigger(new AppVerifyRequestActionEvent(this, deploymentId));
         verify(deploy, times(1)).verifyRequest(any(Identifier.class), any(AppDeployment.class), isNull());
     }
-- 
GitLab


From 500706f201aa3afa239da4694e875eb752c3c7fe Mon Sep 17 00:00:00 2001
From: kbeyro <121854496+kbeyro@users.noreply.github.com>
Date: Tue, 27 May 2025 16:15:36 +0200
Subject: [PATCH 11/13] fix migration

---
 .../common/V1.8.0_20250527_1530__AddConnectionToCluster.sql   | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/main/resources/db/migration/common/V1.8.0_20250527_1530__AddConnectionToCluster.sql b/src/main/resources/db/migration/common/V1.8.0_20250527_1530__AddConnectionToCluster.sql
index 0316f56e7..a821f3eea 100644
--- a/src/main/resources/db/migration/common/V1.8.0_20250527_1530__AddConnectionToCluster.sql
+++ b/src/main/resources/db/migration/common/V1.8.0_20250527_1530__AddConnectionToCluster.sql
@@ -3,8 +3,8 @@ ADD COLUMN kcluster_id integer;
 
 ALTER TABLE kubernetes_nm_service_info
 ADD CONSTRAINT fk_kubernetes_nm_service_info_kcluster
-FOREIGN KEY (kcluster_id)
-REFERENCES kcluster (id)
+FOREIGN KEY (k_cluster_id)
+REFERENCES k_cluster (id)
 ON DELETE SET NULL;
 
 ALTER TABLE app_deployment
-- 
GitLab


From dce4b8337152284ec895daad4144e758140f6695 Mon Sep 17 00:00:00 2001
From: kbeyro <121854496+kbeyro@users.noreply.github.com>
Date: Tue, 27 May 2025 16:19:03 +0200
Subject: [PATCH 12/13] refactor after changes

---
 .../kubernetes/entities/KubernetesNmServiceInfo.java            | 2 +-
 .../common/V1.8.0_20250527_1530__AddConnectionToCluster.sql     | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/entities/KubernetesNmServiceInfo.java b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/entities/KubernetesNmServiceInfo.java
index 61203bf07..886ff994d 100644
--- a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/entities/KubernetesNmServiceInfo.java
+++ b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/entities/KubernetesNmServiceInfo.java
@@ -42,7 +42,7 @@ public class KubernetesNmServiceInfo extends NmServiceInfo {
     private Set<ServiceAccessMethod> accessMethods;
 
     @ManyToOne
-    @JoinColumn(name = "kcluster_id", referencedColumnName = "id")
+    @JoinColumn(name = "k_cluster_id", referencedColumnName = "id")
     private KCluster remoteCluster;
 
     public KubernetesNmServiceInfo () {
diff --git a/src/main/resources/db/migration/common/V1.8.0_20250527_1530__AddConnectionToCluster.sql b/src/main/resources/db/migration/common/V1.8.0_20250527_1530__AddConnectionToCluster.sql
index a821f3eea..a43ff1a50 100644
--- a/src/main/resources/db/migration/common/V1.8.0_20250527_1530__AddConnectionToCluster.sql
+++ b/src/main/resources/db/migration/common/V1.8.0_20250527_1530__AddConnectionToCluster.sql
@@ -1,5 +1,5 @@
 ALTER TABLE kubernetes_nm_service_info
-ADD COLUMN kcluster_id integer;
+ADD COLUMN k_cluster_id integer;
 
 ALTER TABLE kubernetes_nm_service_info
 ADD CONSTRAINT fk_kubernetes_nm_service_info_kcluster
-- 
GitLab


From 1baa920d5e96ac986572d812dcace51073af1690 Mon Sep 17 00:00:00 2001
From: kbeyro <121854496+kbeyro@users.noreply.github.com>
Date: Tue, 27 May 2025 16:35:30 +0200
Subject: [PATCH 13/13] fix test

---
 .../deployment/ServiceDeploymentWithKubernetesTest.java    | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/src/integrationTest/java/net/geant/nmaas/nmservice/deployment/ServiceDeploymentWithKubernetesTest.java b/src/integrationTest/java/net/geant/nmaas/nmservice/deployment/ServiceDeploymentWithKubernetesTest.java
index 12221857a..25cdb65cc 100644
--- a/src/integrationTest/java/net/geant/nmaas/nmservice/deployment/ServiceDeploymentWithKubernetesTest.java
+++ b/src/integrationTest/java/net/geant/nmaas/nmservice/deployment/ServiceDeploymentWithKubernetesTest.java
@@ -1,5 +1,6 @@
 package net.geant.nmaas.nmservice.deployment;
 
+import net.geant.nmaas.externalservices.kubernetes.RemoteClusterManager;
 import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.KubernetesRepositoryManager;
 import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.entities.*;
 import net.geant.nmaas.nmservice.deployment.exceptions.NmServiceRequestVerificationException;
@@ -24,6 +25,8 @@ import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.is;
 import static org.hamcrest.core.IsNull.notNullValue;
 import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
 
 @ExtendWith(SpringExtension.class)
 @SpringBootTest
@@ -35,6 +38,9 @@ class ServiceDeploymentWithKubernetesTest {
 	@Autowired
 	private KubernetesRepositoryManager repositoryManager;
 
+	@Autowired
+	private RemoteClusterManager remoteClusterManager;
+
 	private static final Identifier deploymentId = Identifier.newInstance(1L);
 
 	@AfterEach
@@ -93,6 +99,7 @@ class ServiceDeploymentWithKubernetesTest {
 				.applicationId(Identifier.newInstance("appId"))
 				.deploymentName("deploy")
 				.configFileRepositoryRequired(false)
+				.remoteClusterId(1L)
 				.appName("AppName").build();
 	}
 
-- 
GitLab