diff --git a/VERSION.txt b/VERSION.txt index 0c38bdafc168b00fbf81f283f49efd42972381af..51cfa716ace8da49b6e640a1141d7575498fb5c1 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1,3 +1,4 @@ +2.3.0 Add training access tokens to sandbox api calls. 2.2.10 Fix user ref creation failing on parallel requests. 2.2.9 Add check to prevent reviving an expired training instance. 2.2.8 Add check for training definition being in use when trying to add, remove and update tasks. diff --git a/src/main/java/cz/muni/ics/kypo/training/adaptive/controller/TrainingInstancesRestController.java b/src/main/java/cz/muni/ics/kypo/training/adaptive/controller/TrainingInstancesRestController.java index c39917f88af900613ceb44c2b58f5847fbdbcc5f..6034f7d7e3e5c43439df769023956a0f0c36ed00 100644 --- a/src/main/java/cz/muni/ics/kypo/training/adaptive/controller/TrainingInstancesRestController.java +++ b/src/main/java/cz/muni/ics/kypo/training/adaptive/controller/TrainingInstancesRestController.java @@ -86,6 +86,32 @@ public class TrainingInstancesRestController { return ResponseEntity.ok(trainingInstanceResource); } + /** + * Get requested Training Instance by pool id. + * + * @param poolId id of the assigned pool. + * @return Requested Training Instance by pool id. + */ + @ApiOperation(httpMethod = "GET", + value = "Get training instance by pool id.", + response = TrainingInstanceDTO.class, + nickname = "findTrainingInstanceByPoolId", + notes = "Returns training instance by pool id.", + produces = MediaType.APPLICATION_JSON_VALUE + ) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "The training instance has been found", response = TrainingInstanceDTO.class), + @ApiResponse(code = 404, message = "The training instance has not been found.", response = ApiError.class), + @ApiResponse(code = 500, message = "Unexpected condition was encountered.", response = ApiError.class) + }) + @GetMapping(path = "/pool/{poolId}", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity<Object> findTrainingInstanceByPoolId( + @ApiParam(value = "Pool ID", required = true) + @PathVariable("poolId") Long poolId) { + TrainingInstanceDTO trainingInstanceResource = trainingInstanceFacade.findByPoolId(poolId); + return ResponseEntity.ok(trainingInstanceResource); + } + /** * Get all Training Instances. * diff --git a/src/main/java/cz/muni/ics/kypo/training/adaptive/domain/training/TrainingInstance.java b/src/main/java/cz/muni/ics/kypo/training/adaptive/domain/training/TrainingInstance.java index 85f306716b7f622a0bb1f1d357ec2187fdf564a6..7a03dc311b6e8e967f2a4c7bf950c2d7967142fa 100644 --- a/src/main/java/cz/muni/ics/kypo/training/adaptive/domain/training/TrainingInstance.java +++ b/src/main/java/cz/muni/ics/kypo/training/adaptive/domain/training/TrainingInstance.java @@ -57,6 +57,11 @@ import java.util.Set; "LEFT OUTER JOIN FETCH td.authors " + "WHERE ti.id = :instanceId" ), + @NamedQuery( + name = "TrainingInstance.findByPoolId", + query = "SELECT ti FROM TrainingInstance ti " + + "WHERE ti.poolId = :poolId" + ), @NamedQuery( name = "TrainingInstance.findAllByTrainingDefinitionId", query = "SELECT ti FROM TrainingInstance ti JOIN FETCH ti.trainingDefinition td WHERE td.id = :trainingDefId" diff --git a/src/main/java/cz/muni/ics/kypo/training/adaptive/facade/TrainingInstanceFacade.java b/src/main/java/cz/muni/ics/kypo/training/adaptive/facade/TrainingInstanceFacade.java index 69c07477ce7530f0d7493c641686f4bca7ce8a5b..51141490e8c0276402dba793e03bd13b78257ad7 100644 --- a/src/main/java/cz/muni/ics/kypo/training/adaptive/facade/TrainingInstanceFacade.java +++ b/src/main/java/cz/muni/ics/kypo/training/adaptive/facade/TrainingInstanceFacade.java @@ -106,6 +106,18 @@ public class TrainingInstanceFacade { return trainingInstanceMapper.mapToDTO(trainingInstanceService.findByIdIncludingDefinition(id)); } + /** + * Finds specific Training Instance by pool id + * + * @param poolId ID of a pool + * @return specific {@link TrainingInstanceDTO} by pool id + */ + @IsOrganizerOrAdmin + @TransactionalRO + public TrainingInstanceDTO findByPoolId(Long poolId) { + return trainingInstanceMapper.mapToDTO(trainingInstanceService.findByPoolId(poolId)); + } + /** * Find all Training Instances. * @@ -145,21 +157,21 @@ public class TrainingInstanceFacade { Long oldPoolId = trainingInstance.getPoolId(); String accessToken = trainingInstanceService.update(updatedTrainingInstance); if (isPoolIdChanged(oldPoolId, updatedTrainingInstance.getPoolId())) { - handlePoolIdModification(oldPoolId, updatedTrainingInstance.getPoolId()); + handlePoolIdModification(oldPoolId, updatedTrainingInstance.getPoolId(), updatedTrainingInstance.getAccessToken()); } return accessToken; } - private void handlePoolIdModification(Long currentPoolId, Long newPoolId) { + private void handlePoolIdModification(Long currentPoolId, Long newPoolId, String accessToken) { if (currentPoolId == null) { - sandboxServiceApi.lockPool(newPoolId); + sandboxServiceApi.lockPool(newPoolId, accessToken); } else if (newPoolId == null) { sandboxServiceApi.unlockPool(currentPoolId); deleteBashCommandsByPool(currentPoolId); } else { sandboxServiceApi.unlockPool(currentPoolId); deleteBashCommandsByPool(currentPoolId); - sandboxServiceApi.lockPool(newPoolId); + sandboxServiceApi.lockPool(newPoolId, accessToken); } } @@ -182,7 +194,7 @@ public class TrainingInstanceFacade { trainingInstance.setId(null); TrainingInstance createdTrainingInstance = trainingInstanceService.create(trainingInstance); if (trainingInstance.getPoolId() != null) { - handlePoolIdModification(null, trainingInstance.getPoolId()); + handlePoolIdModification(null, trainingInstance.getPoolId(), trainingInstance.getAccessToken()); } return trainingInstanceMapper.mapToDTO(createdTrainingInstance); } @@ -282,7 +294,7 @@ public class TrainingInstanceFacade { "Training instance already contains pool Id. Please first unassign pool id and then assign another pool again.")); } // lock pool and update pool - sandboxServiceApi.lockPool(trainingInstanceAssignPoolIdDTO.getPoolId()); + sandboxServiceApi.lockPool(trainingInstanceAssignPoolIdDTO.getPoolId(), trainingInstance.getAccessToken()); trainingInstance.setPoolId(trainingInstanceAssignPoolIdDTO.getPoolId()); return trainingInstanceMapper.mapEntityToTIBasicInfo(trainingInstanceService.auditAndSave(trainingInstance)); } diff --git a/src/main/java/cz/muni/ics/kypo/training/adaptive/repository/training/TrainingInstanceRepository.java b/src/main/java/cz/muni/ics/kypo/training/adaptive/repository/training/TrainingInstanceRepository.java index 222353680bc4cd3279da6abefbf8d87b906ccf8d..5017272000a840cb06fb1e53247fc2d44439a42f 100644 --- a/src/main/java/cz/muni/ics/kypo/training/adaptive/repository/training/TrainingInstanceRepository.java +++ b/src/main/java/cz/muni/ics/kypo/training/adaptive/repository/training/TrainingInstanceRepository.java @@ -76,6 +76,14 @@ public interface TrainingInstanceRepository extends JpaRepository<TrainingInstan ) Optional<TrainingInstance> findById(Long id); + /** + * Find training instance by pool id. + * + * @param poolId the pool id + * @return {@link TrainingInstance} including its associated {@link TrainingDefinition} + */ + Optional<TrainingInstance> findByPoolId(@Param("poolId") Long poolId); + /** * Find training instance with start time in the past, end time in the future and by corresponding access token. * diff --git a/src/main/java/cz/muni/ics/kypo/training/adaptive/service/api/SandboxServiceApi.java b/src/main/java/cz/muni/ics/kypo/training/adaptive/service/api/SandboxServiceApi.java index 68fa0c659d5ef431619b1316e27728e4a55a07d9..8503ba6d6b8ab8bafc4461aa2876d417a086b71f 100644 --- a/src/main/java/cz/muni/ics/kypo/training/adaptive/service/api/SandboxServiceApi.java +++ b/src/main/java/cz/muni/ics/kypo/training/adaptive/service/api/SandboxServiceApi.java @@ -37,11 +37,11 @@ public class SandboxServiceApi { } - public Pair<Integer, String> getAndLockSandboxForTrainingRun(Long poolId) { + public Pair<Integer, String> getAndLockSandboxForTrainingRun(Long poolId, String trainingAccessToken) { try { SandboxInfo sandboxInfo = sandboxServiceWebClient .get() - .uri("/pools/{poolId}/sandboxes/get-and-lock", poolId) + .uri("/pools/{poolId}/sandboxes/get-and-lock/{trainingAccessToken}", poolId, trainingAccessToken) .retrieve() .bodyToMono(SandboxInfo.class) .block(); @@ -58,14 +58,17 @@ public class SandboxServiceApi { * Lock pool locked pool info. * * @param poolId the pool id + * @param accessToken the training access token * @return the locked pool info */ - public LockedPoolInfo lockPool(Long poolId) { + public LockedPoolInfo lockPool(Long poolId, String accessToken) { try { + String requestBody = String.format("{\"training_access_token\": \"%s\"}", accessToken); + return sandboxServiceWebClient .post() .uri("/pools/{poolId}/locks", poolId) - .body(Mono.just("{}"), String.class) + .body(Mono.just(requestBody), String.class) .retrieve() .bodyToMono(LockedPoolInfo.class) .block(); diff --git a/src/main/java/cz/muni/ics/kypo/training/adaptive/service/training/TrainingInstanceService.java b/src/main/java/cz/muni/ics/kypo/training/adaptive/service/training/TrainingInstanceService.java index 68c04fba404553223a9556466910010442fb7601..d9b70dd58def5a808b209ac5d62c1e5f58635496 100644 --- a/src/main/java/cz/muni/ics/kypo/training/adaptive/service/training/TrainingInstanceService.java +++ b/src/main/java/cz/muni/ics/kypo/training/adaptive/service/training/TrainingInstanceService.java @@ -74,6 +74,17 @@ public class TrainingInstanceService { .orElseThrow(() -> new EntityNotFoundException(new EntityErrorDetail(TrainingInstance.class, "id", instanceId.getClass(), instanceId))); } + /** + * Find specific Training instance by pool id. + * + * @param poolId the pool id + * @return the {@link TrainingInstance} + */ + public TrainingInstance findByPoolId(Long poolId) { + return trainingInstanceRepository.findByPoolId(poolId) + .orElseThrow(() -> new EntityNotFoundException(new EntityErrorDetail(TrainingInstance.class, "poolId", poolId.getClass(), poolId))); + } + /** * Find specific Training instance by id including its associated Training definition. * diff --git a/src/main/java/cz/muni/ics/kypo/training/adaptive/service/training/TrainingRunService.java b/src/main/java/cz/muni/ics/kypo/training/adaptive/service/training/TrainingRunService.java index b4b955ae315580a9b46c69a32f7d4916b5fea338..e226d8c1467d77e5dd67d509b6036bdcc78b3b7c 100644 --- a/src/main/java/cz/muni/ics/kypo/training/adaptive/service/training/TrainingRunService.java +++ b/src/main/java/cz/muni/ics/kypo/training/adaptive/service/training/TrainingRunService.java @@ -610,7 +610,7 @@ public class TrainingRunService { * @throws MicroserviceApiException error calling OpenStack Sandbox Service API */ public TrainingRun assignSandbox(TrainingRun trainingRun, long poolId) { - Pair<Integer, String> sandboxRefAndId = this.sandboxServiceApi.getAndLockSandboxForTrainingRun(poolId); + Pair<Integer, String> sandboxRefAndId = this.sandboxServiceApi.getAndLockSandboxForTrainingRun(poolId, trainingRun.getTrainingInstance().getAccessToken()); trainingRun.setSandboxInstanceRefId(sandboxRefAndId.getRight()); trainingRun.setSandboxInstanceAllocationId(sandboxRefAndId.getLeft()); return trainingRunRepository.save(trainingRun);