Skip to content
Snippets Groups Projects
Commit 1055737a authored by Lukasz Lopatowski's avatar Lukasz Lopatowski
Browse files

Merge branch '302-move-application-availability-checks-from-janitor-to-platform' into 'develop'

Added remote cluster availability check for new app deployments

See merge request !245
parents 0c7c7b64 de88c67b
No related branches found
No related tags found
2 merge requests!273Release 1.8.0 update,!245Added remote cluster availability check for new app deployments
Pipeline #94886 passed
package net.geant.nmaas.nmservice.deployment;
import net.geant.nmaas.externalservices.kubernetes.RemoteClusterManager;
import net.geant.nmaas.externalservices.kubernetes.RemoteClusterMonitoringService;
import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.KubernetesRepositoryManager;
import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.entities.*;
import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.entities.HelmChartRepositoryEmbeddable;
import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.entities.KubernetesChart;
import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.entities.KubernetesNmServiceInfo;
import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.entities.KubernetesTemplate;
import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.entities.ServiceAccessMethodType;
import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.entities.ServiceStorageVolumeType;
import net.geant.nmaas.nmservice.deployment.exceptions.NmServiceRequestVerificationException;
import net.geant.nmaas.orchestration.Identifier;
import net.geant.nmaas.orchestration.entities.AppAccessMethod;
......@@ -15,6 +21,7 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.util.Collections;
......@@ -25,7 +32,6 @@ 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)
......@@ -38,9 +44,12 @@ class ServiceDeploymentWithKubernetesTest {
@Autowired
private KubernetesRepositoryManager repositoryManager;
@Autowired
@MockitoBean
private RemoteClusterManager remoteClusterManager;
@MockitoBean
private RemoteClusterMonitoringService remoteClusterMonitoringService;
private static final Identifier deploymentId = Identifier.newInstance(1L);
@AfterEach
......@@ -57,7 +66,32 @@ class ServiceDeploymentWithKubernetesTest {
@Test
void shouldConfirmSupportForDeploymentOnKubernetes() {
AppDeploymentSpec appDeploymentSpec = new AppDeploymentSpec();
AppDeployment appDeployment = appDeployment();
AppDeployment appDeployment = appDeployment(null);
appDeploymentSpec.setSupportedDeploymentEnvironments(Collections.singletonList(AppDeploymentEnv.KUBERNETES));
appDeploymentSpec.setKubernetesTemplate(new KubernetesTemplate(
null,
new KubernetesChart(null, "test", "0.0.0"),
"archive",
null,
new HelmChartRepositoryEmbeddable("test", "http://test")
));
appDeploymentSpec.setStorageVolumes(Collections.singleton(new AppStorageVolume(ServiceStorageVolumeType.MAIN, 2, null)));
appDeploymentSpec.setAccessMethods(Collections.singleton(new AppAccessMethod(ServiceAccessMethodType.DEFAULT, "name", "tag", null)));
orchestrator.verifyDeploymentEnvironmentSupportAndBuildNmServiceInfo(Identifier.newInstance(1L), appDeployment, appDeploymentSpec);
KubernetesNmServiceInfo info = repositoryManager.loadService(deploymentId);
assertThat(info, is(notNullValue()));
assertThat(info.getDeploymentId(), equalTo(appDeployment.getDeploymentId()));
assertThat(info.getDeploymentName(), equalTo(appDeployment.getDeploymentName()));
assertThat(info.getDomain(), equalTo(appDeployment.getDomain()));
assertThat(info.getDescriptiveDeploymentId().getValue(), equalTo("domain-appname-100"));
}
@Test
void shouldConfirmSupportForDeploymentOnKubernetesRemoteCluster() {
AppDeploymentSpec appDeploymentSpec = new AppDeploymentSpec();
AppDeployment appDeployment = appDeployment(1L);
appDeploymentSpec.setSupportedDeploymentEnvironments(Collections.singletonList(AppDeploymentEnv.KUBERNETES));
appDeploymentSpec.setKubernetesTemplate(new KubernetesTemplate(
null,
......@@ -68,6 +102,8 @@ class ServiceDeploymentWithKubernetesTest {
));
appDeploymentSpec.setStorageVolumes(Collections.singleton(new AppStorageVolume(ServiceStorageVolumeType.MAIN, 2, null)));
appDeploymentSpec.setAccessMethods(Collections.singleton(new AppAccessMethod(ServiceAccessMethodType.DEFAULT, "name", "tag", null)));
when(remoteClusterManager.clusterExists(1L)).thenReturn(Boolean.TRUE);
when(remoteClusterMonitoringService.clusterAvailable(1L)).thenReturn(Boolean.TRUE);
orchestrator.verifyDeploymentEnvironmentSupportAndBuildNmServiceInfo(Identifier.newInstance(1L), appDeployment, appDeploymentSpec);
KubernetesNmServiceInfo info = repositoryManager.loadService(deploymentId);
......@@ -81,16 +117,16 @@ class ServiceDeploymentWithKubernetesTest {
@Test
void shouldNotifyIncompatibilityForDeploymentOnKubernetes() {
AppDeploymentSpec appDeploymentSpec = new AppDeploymentSpec();
AppDeployment appDeployment = appDeployment(null);
appDeploymentSpec.setSupportedDeploymentEnvironments(Collections.emptyList());
appDeploymentSpec.setKubernetesTemplate(new KubernetesTemplate());
assertThrows(NmServiceRequestVerificationException.class, () -> {
AppDeploymentSpec appDeploymentSpec = new AppDeploymentSpec();
AppDeployment appDeployment = appDeployment();
appDeploymentSpec.setSupportedDeploymentEnvironments(Collections.emptyList());
appDeploymentSpec.setKubernetesTemplate(new KubernetesTemplate());
orchestrator.verifyDeploymentEnvironmentSupportAndBuildNmServiceInfo(null, appDeployment, appDeploymentSpec);
});
}
private AppDeployment appDeployment() {
private AppDeployment appDeployment(Long remoteClusterId) {
return AppDeployment.builder()
.instanceId(100L)
.deploymentId(deploymentId)
......@@ -99,7 +135,7 @@ class ServiceDeploymentWithKubernetesTest {
.applicationId(Identifier.newInstance("appId"))
.deploymentName("deploy")
.configFileRepositoryRequired(false)
.remoteClusterId(1L)
.remoteClusterId(remoteClusterId)
.appName("AppName").build();
}
......
......@@ -25,12 +25,23 @@ import static net.geant.nmaas.externalservices.kubernetes.RemoteClusterHelper.sa
@Service
@RequiredArgsConstructor
@Slf4j
public class RemoteClusterMonitor implements ClusterMonitoringService {
public class RemoteClusterMonitor implements RemoteClusterMonitoringService {
private final KClusterRepository clusterRepository;
private final KubernetesApiService kubernetesApiService;
private final RemoteClusterMailer mailer;
@Override
public boolean clusterAvailable(Long id) {
final KCluster cluster = clusterRepository.getReferenceById(id);
try {
kubernetesApiService.getKubernetesVersion(cluster);
return true;
} catch (Exception e) {
return false;
}
}
@Override
public void updateAllClusterState() {
restoreKubeconfigFileIfMissing();
......
......@@ -10,14 +10,14 @@ import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
@Slf4j
public class ClusterMonitoringJob implements Job {
public class RemoteClusterMonitoringJob implements Job {
private final ClusterMonitoringService clusterMonitoringService;
private final RemoteClusterMonitoringService remoteClusterMonitoringService;
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
log.info("Triggering cluster health check...");
clusterMonitoringService.updateAllClusterState();
remoteClusterMonitoringService.updateAllClusterState();
}
}
package net.geant.nmaas.externalservices.kubernetes;
public interface ClusterMonitoringService {
public interface RemoteClusterMonitoringService {
boolean clusterAvailable(Long id);
void updateAllClusterState();
}
......@@ -5,6 +5,7 @@ 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.RemoteClusterMonitoringService;
import net.geant.nmaas.externalservices.kubernetes.entities.IngressControllerConfigOption;
import net.geant.nmaas.externalservices.kubernetes.entities.KCluster;
import net.geant.nmaas.gitlab.GitLabManager;
......@@ -13,8 +14,6 @@ import net.geant.nmaas.nmservice.deployment.ContainerOrchestrator;
import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.components.cluster.KClusterCheckException;
import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.components.helm.HelmChartIngressVariable;
import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.components.ingress.IngressControllerManipulationException;
import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.janitor.JanitorResponseException;
import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.janitor.JanitorService;
import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.entities.KubernetesNmServiceInfo;
import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.entities.KubernetesTemplate;
import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.entities.ParameterType;
......@@ -22,6 +21,8 @@ import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.en
import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.entities.ServiceAccessMethodView;
import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.entities.ServiceStorageVolume;
import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.exceptions.KServiceManipulationException;
import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.janitor.JanitorResponseException;
import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.janitor.JanitorService;
import net.geant.nmaas.nmservice.deployment.exceptions.ContainerCheckFailedException;
import net.geant.nmaas.nmservice.deployment.exceptions.ContainerOrchestratorInternalErrorException;
import net.geant.nmaas.nmservice.deployment.exceptions.CouldNotDeployNmServiceException;
......@@ -51,6 +52,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
......@@ -85,6 +87,7 @@ public class KubernetesManager implements ContainerOrchestrator {
private final GitLabManager gitLabManager;
private final JanitorService janitorService;
private final RemoteClusterManager remoteClusterManager;
private final RemoteClusterMonitoringService remoteClusterMonitoringService;
@Override
@Loggable(LogLevel.INFO)
......@@ -100,7 +103,16 @@ public class KubernetesManager implements ContainerOrchestrator {
} catch (IllegalArgumentException iae) {
throw new NmServiceRequestVerificationException(iae.getMessage());
}
//todo
if (Objects.nonNull(appDeployment.getRemoteClusterId())) {
if (!remoteClusterManager.clusterExists(appDeployment.getRemoteClusterId())) {
throw new NmServiceRequestVerificationException(String.format("Remote cluster with id %s doesn't exist", appDeployment.getRemoteClusterId()));
} else {
if (!remoteClusterMonitoringService.clusterAvailable(appDeployment.getRemoteClusterId())) {
throw new NmServiceRequestVerificationException(String.format("Remote cluster with id %s is currently unavailable", appDeployment.getRemoteClusterId()));
}
}
}
KubernetesNmServiceInfo serviceInfo = new KubernetesNmServiceInfo(
deploymentId,
......@@ -108,11 +120,9 @@ public class KubernetesManager implements ContainerOrchestrator {
appDeployment.getDomain(),
appDeployment.getDescriptiveDeploymentId()
);
//verify cluster
if (remoteClusterManager.clusterExists(appDeployment.getRemoteClusterId())) {
if (Objects.nonNull(appDeployment.getRemoteClusterId())) {
serviceInfo.setRemoteCluster(remoteClusterManager.getCluster(appDeployment.getRemoteClusterId()));
}
serviceInfo.setKubernetesTemplate(KubernetesTemplate.copy(appDeploymentSpec.getKubernetesTemplate()));
serviceInfo.setStorageVolumes(generateTemplateStorageVolumes(appDeploymentSpec.getStorageVolumes()));
serviceInfo.setAccessMethods(generateTemplateAccessMethods(appDeploymentSpec.getAccessMethods()));
......
......@@ -2,7 +2,7 @@ package net.geant.nmaas.scheduling;
import com.google.common.base.Strings;
import lombok.extern.slf4j.Slf4j;
import net.geant.nmaas.externalservices.kubernetes.ClusterMonitoringJob;
import net.geant.nmaas.externalservices.kubernetes.RemoteClusterMonitoringJob;
import net.geant.nmaas.portal.service.ConfigurationManager;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -18,17 +18,17 @@ public class ClusterHealthCheckScheduleInit implements InitializingBean {
public static final String CLUSTER_HEALTH_CHECK = "ClusterHealthCheck";
private final ClusterMonitoringJob clusterMonitoringJob;
private final RemoteClusterMonitoringJob remoteClusterMonitoringJob;
private final ScheduleManager scheduleManager;
private final ConfigurationManager configurationManager;
private final String healthCheckJobCron;
@Autowired
public ClusterHealthCheckScheduleInit(ClusterMonitoringJob clusterMonitoringJob,
public ClusterHealthCheckScheduleInit(RemoteClusterMonitoringJob remoteClusterMonitoringJob,
ScheduleManager scheduleManager,
ConfigurationManager configurationManager,
@Value("${nmaas.service.health-check.cron}") String healthCheckJobCron) {
this.clusterMonitoringJob = clusterMonitoringJob;
this.remoteClusterMonitoringJob = remoteClusterMonitoringJob;
this.scheduleManager = scheduleManager;
this.configurationManager = configurationManager;
this.healthCheckJobCron = healthCheckJobCron;
......@@ -40,13 +40,13 @@ public class ClusterHealthCheckScheduleInit implements InitializingBean {
final String healthCheckJobCronFromDb = configurationManager.getConfiguration().getHealthCheckJobCron();
if (!Strings.isNullOrEmpty(healthCheckJobCronFromDb)) {
log.debug("Scheduling cluster health check job based on cron loaded from the database");
this.scheduleManager.createJob(clusterMonitoringJob, CLUSTER_HEALTH_CHECK, healthCheckJobCronFromDb);
this.scheduleManager.createJob(remoteClusterMonitoringJob, CLUSTER_HEALTH_CHECK, healthCheckJobCronFromDb);
log.error("Adding new job for health check cluster ...");
} else if (Strings.isNullOrEmpty(healthCheckJobCron)) {
log.warn("Cluster health check cron expression not provided");
} else {
log.debug("Scheduling cluster health check job based on cron loaded from properties");
this.scheduleManager.createJob(clusterMonitoringJob, CLUSTER_HEALTH_CHECK, healthCheckJobCron);
this.scheduleManager.createJob(remoteClusterMonitoringJob, CLUSTER_HEALTH_CHECK, healthCheckJobCron);
}
}
......
......@@ -3,6 +3,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.RemoteClusterMonitoringService;
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;
......@@ -71,6 +72,7 @@ public class KubernetesManagerTest {
private final GitLabManager gitLabManager = mock(GitLabManager.class);
private final JanitorService janitorService = mock(JanitorService.class);
private final RemoteClusterManager remoteClusterManager = mock(RemoteClusterManager.class);
private final RemoteClusterMonitoringService remoteClusterMonitoringService = mock(RemoteClusterMonitoringService.class);
private final KubernetesDeploymentRemoteClusterParametersProvider remoteClusterParametersProvider = mock(KubernetesDeploymentRemoteClusterParametersProvider.class);
private static final Identifier DEPLOYMENT_ID = Identifier.newInstance("deploymentId");
......@@ -87,7 +89,8 @@ public class KubernetesManagerTest {
ingressManager,
gitLabManager,
janitorService,
remoteClusterManager
remoteClusterManager,
remoteClusterMonitoringService
);
@BeforeEach
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment