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 12221857a73a159df9d65fb982c435bbf841b09b..25cdb65cc27c6a5cf4f98c5fdc9bf95e8a570944 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(); } 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 c99ac38a4fe8fdfbd0426ed4d25f8d3b351b13bb..bf8c9f6a1db8dc3a6c1a2c250a9c070c78b3402e 100644 --- a/src/main/java/net/geant/nmaas/externalservices/kubernetes/RemoteClusterManager.java +++ b/src/main/java/net/geant/nmaas/externalservices/kubernetes/RemoteClusterManager.java @@ -351,4 +351,8 @@ public class RemoteClusterManager implements ClusterMonitoringService { } + public boolean clusterExists(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 1cb6ce71487bd05b78fbade29f70dae91319b9af..ab50670ce702020ee8318f6a3f813de6ec4c2eea 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) @@ -96,6 +98,7 @@ public class KubernetesManager implements ContainerOrchestrator { } catch (IllegalArgumentException iae) { throw new NmServiceRequestVerificationException(iae.getMessage()); } + //todo KubernetesNmServiceInfo serviceInfo = new KubernetesNmServiceInfo( deploymentId, @@ -103,6 +106,11 @@ public class KubernetesManager implements ContainerOrchestrator { appDeployment.getDomain(), appDeployment.getDescriptiveDeploymentId() ); + //verify cluster + if(remoteClusterManager.clusterExists(appDeployment.getRemoteClusterId())) { + 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 f4ba07022f7d0a78e95fe8f4dcf31ab0dec71644..0aaf87e860233474089ba70039fbce2394495cdd 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 OPTION_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 01a3fd9b4307cc5eea008c719b76d0442d1d6b4c..dfc719d8abda50051c29c5f4b2ed08aba522ece6 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/HelmKServiceManager.java b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmKServiceManager.java index 753891c45e3e7d4b994bb74ab1a777580518e248..5419effb43ab57463fd89c96edb50d578694d7b7 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; @@ -75,26 +76,41 @@ 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 ); } 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 940c89fa9b85beac192549668b1df98f86943d54..692e26b541fe15dc01aef97825bdc636b1dcdd7b 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,8 +25,12 @@ 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(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"); } @@ -35,6 +39,7 @@ public class HelmInstallCommand extends HelmCommand { sb.append(SPACE).append(OPTION_VERSION).append(SPACE).append(chartVersion); } addTlsOptionIfRequired(helmVersion, enableTls, sb); + return new HelmInstallCommand(sb.toString()); } 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 e2f56ccb6d5a2c1c28894c21616ad0fec369d6bf..886ff994df77a43af404f210d40da1c9fbb70b62 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,7 +1,10 @@ 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; import net.geant.nmaas.nmservice.deployment.entities.NmServiceInfo; import net.geant.nmaas.orchestration.Identifier; @@ -38,6 +41,10 @@ public class KubernetesNmServiceInfo extends NmServiceInfo { @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) private Set<ServiceAccessMethod> accessMethods; + @ManyToOne + @JoinColumn(name = "k_cluster_id", referencedColumnName = "id") + private KCluster remoteCluster; + public KubernetesNmServiceInfo () { super(); } @@ -46,4 +53,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 73173f116825dda60fe71b772bb9897e0b37927f..6593de17059fffb3ba403dc82acdda17ed701325 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 3810ab4bbcf8f45dd015521e01b508f0d0dbd047..1da23840cb3c47d9147ad889a0c93a4cab44f3ee 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; @@ -18,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 @@ -29,6 +31,8 @@ public class AppRequestVerificationTask { private AppDeploymentRepository repository; private ApplicationRepository appRepository; + private RemoteClusterManager remoteClusterManager; + @EventListener @Loggable(LogLevel.INFO) @Transactional(propagation = Propagation.REQUIRES_NEW) @@ -39,6 +43,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.clusterExists(appDeployment.getRemoteClusterId())) { + throw new InvalidAttributesException("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 81365d8a6ed7c899f34f4ee9eeff9ac7f03351a2..0a2f7e395efbcbc596163f69b7c6ffceeacc5919 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/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 0000000000000000000000000000000000000000..a43ff1a50ab7bf88301362cd08387965221a17ab --- /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 k_cluster_id integer; + +ALTER TABLE kubernetes_nm_service_info +ADD CONSTRAINT fk_kubernetes_nm_service_info_kcluster +FOREIGN KEY (k_cluster_id) +REFERENCES k_cluster (id) +ON DELETE SET NULL; + +ALTER TABLE app_deployment +ADD COLUMN remote_cluster_id integer; \ No newline at end of file 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 e731123936fbfa7898f805c50e70e49dbe1d8ce1..71dfd8bbe46d70db352e86aa141dea8486767566 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 74b90525221a703be60760041acfa9ccb517c425..9bd0e19eb80a4419e723e216700fddcc7187bc41 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 0ebf9adc9ddcfcaceebc693ebe1c5dfec3b704c1..f743955611888d0dc852135850bdb170cf8e77df 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() + 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() + 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"); + } + } 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 6171c102318ac1bf8e99820409db14223e7b90f9..622f4cd25704c5a4af63235d9bd1389790545c55 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,13 +35,14 @@ public class AppRequestVerificationTaskTest { @BeforeEach public void setup() { - task = new AppRequestVerificationTask(deploy, deployments, applications); + task = new AppRequestVerificationTask(deploy, deployments, applications, remoteClusterManager); } @Test 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.clusterExists(any())).thenReturn(true); task.trigger(new AppVerifyRequestActionEvent(this, deploymentId)); verify(deploy, times(1)).verifyRequest(any(Identifier.class), any(AppDeployment.class), isNull()); }