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 4677d8d6b625acdb8508b3b49f797de5456fba3b..36ae7abb54274fa717b06109e22bd0bbf82b5a44 100644 --- a/src/main/java/net/geant/nmaas/externalservices/kubernetes/RemoteClusterManager.java +++ b/src/main/java/net/geant/nmaas/externalservices/kubernetes/RemoteClusterManager.java @@ -330,4 +330,16 @@ public class RemoteClusterManager implements ClusterMonitoringService { return Files.exists(path) && Files.isRegularFile(path) && Files.isReadable(path); } + public void removeCluster(Long id) { + try { + if(clusterRepository.existsById(id)) { + this.clusterRepository.deleteById(id); + } + } catch (RuntimeException ex) { + log.warn("Can not delete cluster {}", id); + log.error("Exception: {}", ex.getMessage()); + } + + } + } \ No newline at end of file diff --git a/src/main/java/net/geant/nmaas/externalservices/kubernetes/api/RemoteClusterManagerController.java b/src/main/java/net/geant/nmaas/externalservices/kubernetes/api/RemoteClusterManagerController.java index b09aad534eb0359466bcb3ca4e1199c882eabd91..61e1a93d48fd9915c6094d00a15d5705b29afac0 100644 --- a/src/main/java/net/geant/nmaas/externalservices/kubernetes/api/RemoteClusterManagerController.java +++ b/src/main/java/net/geant/nmaas/externalservices/kubernetes/api/RemoteClusterManagerController.java @@ -6,7 +6,9 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import net.geant.nmaas.externalservices.kubernetes.RemoteClusterManager; import net.geant.nmaas.externalservices.kubernetes.api.model.RemoteClusterView; +import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @@ -58,4 +60,10 @@ public class RemoteClusterManagerController { return remoteClusterManager.updateCluster(view, id); } + @PreAuthorize("hasRole('ROLE_SYSTEM_ADMIN') || hasRole('ROLE_OPERATOR')") + @DeleteMapping("/{id}") + public void deleteCluster(@PathVariable Long id) { + remoteClusterManager.removeCluster(id); + } + } diff --git a/src/main/java/net/geant/nmaas/portal/persistent/repositories/AppInstanceRepository.java b/src/main/java/net/geant/nmaas/portal/persistent/repositories/AppInstanceRepository.java index 3002af2e17a43f61ef9bb1fcfb515436054de9d5..a502ee89db7b1e874753ce4fd667b1f2904ebce2 100644 --- a/src/main/java/net/geant/nmaas/portal/persistent/repositories/AppInstanceRepository.java +++ b/src/main/java/net/geant/nmaas/portal/persistent/repositories/AppInstanceRepository.java @@ -49,14 +49,14 @@ public interface AppInstanceRepository extends JpaRepository<AppInstance, Long> @Query("select count(ai.id) FROM AppInstance ai where ai.createdAt >= :sinceTime") int countAllDeployedSinceTime(@Param("sinceTime") long sinceTime); - @Query("select count(ai.id) FROM AppInstance ai where ai.createdAt >= :sinceTime AND ai.createdAt <= :endTime") - int countAllDeployedSinceTime(@Param("sinceTime") long sinceTime, @Param("sinceTime") long toTime); + @Query("select count(ai.id) FROM AppInstance ai where ai.createdAt >= :sinceTime AND ai.createdAt < :endTime") + int countAllDeployedSinceTime(@Param("sinceTime") long sinceTime, @Param("endTime") long endTime); @Query("select count(ai.id) FROM AppInstance ai JOIN AppDeployment ad on ad.deploymentId = ai.internalId where ai.application.name = ?1") int countByName(String name); @Query("select ai FROM AppInstance ai where ai.createdAt >= :sinceTime AND ai.createdAt <= :endTime") - List<AppInstance> findAllInTimePeriod(@Param("sinceTime") long start, @Param("endTime") long end); + List<AppInstance> findAllInTimePeriod(@Param("sinceTime") long start, @Param("endTime") long endTime); int countAllByOwner(User user); diff --git a/src/main/java/net/geant/nmaas/portal/service/impl/DashboardServiceImpl.java b/src/main/java/net/geant/nmaas/portal/service/impl/DashboardServiceImpl.java index 420bf728bc72fac8b601463b616f1e3c4c739945..28fbdaf017c9710e0be7153591416501c59ce9aa 100644 --- a/src/main/java/net/geant/nmaas/portal/service/impl/DashboardServiceImpl.java +++ b/src/main/java/net/geant/nmaas/portal/service/impl/DashboardServiceImpl.java @@ -49,8 +49,10 @@ public class DashboardServiceImpl implements DashboardService { @Override public DashboardView getSystemDashboard(OffsetDateTime startDate, OffsetDateTime endDate) { - long startTimeStamp = System.currentTimeMillis() - startDate.toEpochSecond(); - long endTimeStamp = System.currentTimeMillis() - endDate.toEpochSecond(); + log.warn("Start date {} / end date {}", startDate, endDate); + + long startTimeStamp = startDate.toEpochSecond(); + long endTimeStamp = endDate.toEpochSecond(); List<String> baseNames = applicationBaseRepository.findAllNames(); @@ -68,7 +70,7 @@ public class DashboardServiceImpl implements DashboardService { //filter not deployed application applicationDeploymentCountPerName.entrySet().removeIf(app -> app.getValue() == 0); - + log.info("Start stamp {} / end stamp {}", startTimeStamp, endTimeStamp); return DashboardView.builder() .domainsCount(domainRepository.count()) diff --git a/src/test/java/net/geant/nmaas/portal/service/impl/DashboardServiceImplTest.java b/src/test/java/net/geant/nmaas/portal/service/impl/DashboardServiceImplTest.java index ae02141d1f25687a9ab34e683cac3d4ba49930cb..f35951e6cfdf5e61ca16780fabfdf728afd51910 100644 --- a/src/test/java/net/geant/nmaas/portal/service/impl/DashboardServiceImplTest.java +++ b/src/test/java/net/geant/nmaas/portal/service/impl/DashboardServiceImplTest.java @@ -128,34 +128,74 @@ public class DashboardServiceImplTest { } @Test -void getSystemDashboardShouldCalculateCorrectTimestamps() { - OffsetDateTime startDate = OffsetDateTime.now().minusHours(5); - OffsetDateTime endDate = OffsetDateTime.now(); - - // Mock required repository methods - when(domainRepository.count()).thenReturn(1L); - when(userRepository.count()).thenReturn(1L); - when(appInstanceRepo.count()).thenReturn(1L); - when(appInstanceRepo.countAllDeployedSinceTime(org.mockito.ArgumentMatchers.anyLong(), org.mockito.ArgumentMatchers.anyLong())).thenReturn(1); - when(applicationBaseRepository.findAllNames()).thenReturn(Collections.emptyList()); - when(appInstanceRepo.findAllInTimePeriod(org.mockito.ArgumentMatchers.anyLong(), org.mockito.ArgumentMatchers.anyLong())).thenReturn(Collections.emptyList()); - - // Call the method - dashboardService.getSystemDashboard(startDate, endDate); - - // Capture the arguments - ArgumentCaptor<Long> startCaptor = ArgumentCaptor.forClass(Long.class); - ArgumentCaptor<Long> endCaptor = ArgumentCaptor.forClass(Long.class); - - // Verify that the method was called with calculated timestamps - org.mockito.Mockito.verify(appInstanceRepo).countAllDeployedSinceTime(startCaptor.capture(), endCaptor.capture()); - - long startTimestamp = startCaptor.getValue(); - long endTimestamp = endCaptor.getValue(); - - // The timestamps should be positive and start should be greater than end (since it's calculated as now - toEpochSecond) - assert startTimestamp > 0; - assert endTimestamp > 0; - assert startTimestamp > endTimestamp; -} + void getSystemDashboardShouldCalculateCorrectTimestamps() { + OffsetDateTime startDate = OffsetDateTime.now().minusHours(5); + OffsetDateTime endDate = OffsetDateTime.now(); + + // Mock required repository methods + when(domainRepository.count()).thenReturn(1L); + when(userRepository.count()).thenReturn(1L); + when(appInstanceRepo.count()).thenReturn(1L); + when(appInstanceRepo.countAllDeployedSinceTime(org.mockito.ArgumentMatchers.anyLong(), org.mockito.ArgumentMatchers.anyLong())).thenReturn(1); + when(applicationBaseRepository.findAllNames()).thenReturn(Collections.emptyList()); + when(appInstanceRepo.findAllInTimePeriod(org.mockito.ArgumentMatchers.anyLong(), org.mockito.ArgumentMatchers.anyLong())).thenReturn(Collections.emptyList()); + + // Call the method + dashboardService.getSystemDashboard(startDate, endDate); + + // Capture the arguments + ArgumentCaptor<Long> startCaptor = ArgumentCaptor.forClass(Long.class); + ArgumentCaptor<Long> endCaptor = ArgumentCaptor.forClass(Long.class); + + org.mockito.Mockito.verify(appInstanceRepo).countAllDeployedSinceTime(startCaptor.capture(), endCaptor.capture()); + + long startTimestamp = startCaptor.getValue(); + long endTimestamp = endCaptor.getValue(); + + // The timestamps should be positive and start should be less than or equal to end + assert startTimestamp > 0; + assert endTimestamp > 0; + assert startTimestamp <= endTimestamp; + } + + @Test + void countAllDeployedSinceTimeShouldReturnCorrectCount() { + long sinceTime = 1000L; + long toTime = 2000L; + int expectedCount = 7; + + when(appInstanceRepo.countAllDeployedSinceTime(sinceTime, toTime)).thenReturn(expectedCount); + + int actualCount = appInstanceRepo.countAllDeployedSinceTime(sinceTime, toTime); + + assert actualCount == expectedCount; + org.mockito.Mockito.verify(appInstanceRepo).countAllDeployedSinceTime(sinceTime, toTime); + } + + @Test + void getSystemDashboardShouldCallCountAllDeployedSinceTimeWithCorrectArguments() { + OffsetDateTime startDate = OffsetDateTime.now().minusDays(2); + OffsetDateTime endDate = OffsetDateTime.now(); + + when(domainRepository.count()).thenReturn(1L); + when(userRepository.count()).thenReturn(1L); + when(appInstanceRepo.count()).thenReturn(1L); + when(appInstanceRepo.countAllDeployedSinceTime(org.mockito.ArgumentMatchers.anyLong(), org.mockito.ArgumentMatchers.anyLong())).thenReturn(5); + when(applicationBaseRepository.findAllNames()).thenReturn(Collections.emptyList()); + when(appInstanceRepo.findAllInTimePeriod(org.mockito.ArgumentMatchers.anyLong(), org.mockito.ArgumentMatchers.anyLong())).thenReturn(Collections.emptyList()); + + dashboardService.getSystemDashboard(startDate, endDate); + + ArgumentCaptor<Long> sinceCaptor = ArgumentCaptor.forClass(Long.class); + ArgumentCaptor<Long> toCaptor = ArgumentCaptor.forClass(Long.class); + + org.mockito.Mockito.verify(appInstanceRepo).countAllDeployedSinceTime(sinceCaptor.capture(), toCaptor.capture()); + + long sinceTime = sinceCaptor.getValue(); + long toTime = toCaptor.getValue(); + + assert sinceTime > 0; + assert toTime > 0; + assert sinceTime < toTime; + } } diff --git a/src/test/shell/data/i18n/de.json b/src/test/shell/data/i18n/de.json index 3a07ad01ea518de6b8fadbe92c36b89fe0cf5d69..3ffdc078875ee593fa55b1a41b02ef5e4fcd45d6 100644 --- a/src/test/shell/data/i18n/de.json +++ b/src/test/shell/data/i18n/de.json @@ -193,7 +193,8 @@ "UNKNOWN" : "Unknown", "DETAILS" : "Details", "STATE_SINCE" : "State last change", - "CONTACT_MAIL" : "Contact mail" + "CONTACT_MAIL" : "Contact mail", + "REMOVE" : "Remove cluster" }, "GITLAB": { "TITLE": "GitLab Konfiguration", @@ -1325,6 +1326,7 @@ "USER_ASSIGNMENT" : "User assignment", "DOMAIN_GROUP_CHANGE" : "Domain group change", "NEW" : "Add webhook", - "DETAILS" : "Webhooks details" + "DETAILS" : "Webhooks details", + "SAVE" : "Save webhook" } } diff --git a/src/test/shell/data/i18n/en.json b/src/test/shell/data/i18n/en.json index 6484fdeaec15e61cf86d41d39c73b4bec33e264e..cfdd02ec48997398bb6d9c484267061957070b75 100644 --- a/src/test/shell/data/i18n/en.json +++ b/src/test/shell/data/i18n/en.json @@ -194,7 +194,8 @@ "UNKNOWN" : "Unknown", "CONTACT_MAIL" : "Contact mail", "DETAILS" : "Details", - "STATE_SINCE" : "State last change" + "STATE_SINCE" : "State last change", + "REMOVE" : "Remove cluster" }, "GITLAB": { "TITLE": "GitLab configuration", @@ -1330,6 +1331,7 @@ "USER_ASSIGNMENT" : "User assignment", "DOMAIN_GROUP_CHANGE" : "Domain group change", "NEW" : "Add webhook", - "DETAILS" : "Webhooks details" + "DETAILS" : "Webhooks details", + "SAVE" : "Save webhook" } } diff --git a/src/test/shell/data/i18n/fr.json b/src/test/shell/data/i18n/fr.json index 449bdc580a1e0151fc743896e5d7a56e21695968..9a29496335ad280ca8e8d34504c229bbb2d92115 100644 --- a/src/test/shell/data/i18n/fr.json +++ b/src/test/shell/data/i18n/fr.json @@ -195,7 +195,8 @@ "UNKNOWN" : "Unknown", "CONTACT_MAIL" : "Contact mail", "DETAILS" : "Details", - "STATE_SINCE" : "State last change" + "STATE_SINCE" : "State last change", + "REMOVE" : "Remove cluster" }, "GITLAB": { "TITLE": "Configuration de GitLab", @@ -1329,6 +1330,7 @@ "USER_ASSIGNMENT" : "User assignment", "DOMAIN_GROUP_CHANGE" : "Domain group change", "NEW" : "Add webhook", - "DETAILS" : "Webhooks details" + "DETAILS" : "Webhooks details", + "SAVE" : "Save webhook" } } diff --git a/src/test/shell/data/i18n/pl.json b/src/test/shell/data/i18n/pl.json index ae51c715ddda44898afc023c818db0fb15c47109..5e12f67b165b2fe94e9424f245f152ccda23385e 100644 --- a/src/test/shell/data/i18n/pl.json +++ b/src/test/shell/data/i18n/pl.json @@ -194,7 +194,9 @@ "UNKNOWN" : "Nieznany", "CONTACT_MAIL" : "Email kontaktowy", "DETAILS" : "Detale", - "STATE_SINCE" : "Stan od" + "STATE_SINCE" : "Stan od", + "REMOVE" : "Remove cluster" + }, "GITLAB": { "TITLE": "Konfiguracja GitLab", @@ -1328,6 +1330,8 @@ "USER_ASSIGNMENT" : "User assignment", "DOMAIN_GROUP_CHANGE" : "Domain group change", "NEW" : "Add webhook", - "DETAILS" : "Webhooks details" + "DETAILS" : "Webhooks details", + "SAVE" : "Save webhook" + } }