Refactoring the DDI Offline Distribution set assignment feature (#1798)

* Refactoring the DDI Offline Distribution set assignment feature

Signed-off-by: Denislav Prinov <denislav.prinov@bosch.com>

* Tests refactoring

Signed-off-by: Denislav Prinov <denislav.prinov@bosch.com>

* make it more visible the featyre is experimental

Signed-off-by: Denislav Prinov <denislav.prinov@bosch.com>

---------

Signed-off-by: Denislav Prinov <denislav.prinov@bosch.com>
This commit is contained in:
Denislav Prinov
2024-08-01 16:14:40 +03:00
committed by GitHub
parent 6fd52d4b4a
commit dc5b45b94a
6 changed files with 16 additions and 19 deletions

View File

@@ -13,7 +13,6 @@ import static org.eclipse.hawkbit.repository.model.Action.Status.DOWNLOADED;
import static org.eclipse.hawkbit.repository.model.Action.Status.FINISHED; import static org.eclipse.hawkbit.repository.model.Action.Status.FINISHED;
import static org.eclipse.hawkbit.repository.model.Target.CONTROLLER_ATTRIBUTE_KEY_SIZE; import static org.eclipse.hawkbit.repository.model.Target.CONTROLLER_ATTRIBUTE_KEY_SIZE;
import static org.eclipse.hawkbit.repository.model.Target.CONTROLLER_ATTRIBUTE_VALUE_SIZE; import static org.eclipse.hawkbit.repository.model.Target.CONTROLLER_ATTRIBUTE_VALUE_SIZE;
import static org.eclipse.hawkbit.security.SecurityContextTenantAware.SYSTEM_USER;
import java.net.URI; import java.net.URI;
import java.time.Duration; import java.time.Duration;
@@ -54,7 +53,6 @@ import org.eclipse.hawkbit.repository.RepositoryConstants;
import org.eclipse.hawkbit.repository.RepositoryProperties; import org.eclipse.hawkbit.repository.RepositoryProperties;
import org.eclipse.hawkbit.repository.TargetTypeManagement; import org.eclipse.hawkbit.repository.TargetTypeManagement;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.TargetTypeManagement;
import org.eclipse.hawkbit.repository.UpdateMode; import org.eclipse.hawkbit.repository.UpdateMode;
import org.eclipse.hawkbit.repository.builder.ActionStatusCreate; import org.eclipse.hawkbit.repository.builder.ActionStatusCreate;
import org.eclipse.hawkbit.repository.event.remote.CancelTargetAssignmentEvent; import org.eclipse.hawkbit.repository.event.remote.CancelTargetAssignmentEvent;
@@ -1107,19 +1105,18 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont
} }
@Override @Override
public boolean updateOfflineAssignedVersion(@NotEmpty String controllerId, String distributionName, String version){ public boolean updateOfflineAssignedVersion(@NotEmpty final String controllerId, final String distributionName, final String version){
List<DistributionSetAssignmentResult> distributionSetAssignmentResults = List<DistributionSetAssignmentResult> distributionSetAssignmentResults =
systemSecurityContext.runAsSystem(() -> systemSecurityContext.runAsSystem(() ->
distributionSetManagement.getByNameAndVersion(distributionName,version).map( distributionSetManagement.getByNameAndVersion(distributionName,version).map(
distributionSet -> deploymentManagement.offlineAssignedDistributionSets( distributionSet -> deploymentManagement.offlineAssignedDistributionSets(
List.of(Map.entry(controllerId, distributionSet.getId())),controllerId)) List.of(Map.entry(controllerId, distributionSet.getId())),controllerId))
.orElseThrow(() -> .orElseThrow(() ->
new EntityNotFoundException(DistributionSet.class, Map.entry(distributionName, version))) new EntityNotFoundException(DistributionSet.class, Map.entry(distributionName, version))));
.stream().toList());
boolean notAlreadyAssigned = distributionSetAssignmentResults.stream().findFirst() return distributionSetAssignmentResults.stream().findFirst()
.map(result-> result.getAlreadyAssigned()==0) .map(result-> result.getAlreadyAssigned()==0)
.orElseThrow(); .orElseThrow();
return notAlreadyAssigned;
} }
private void cancelAssignDistributionSetEvent(final Action action) { private void cancelAssignDistributionSetEvent(final Action action) {

View File

@@ -190,7 +190,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
@Override @Override
public List<DistributionSetAssignmentResult> offlineAssignedDistributionSets( public List<DistributionSetAssignmentResult> offlineAssignedDistributionSets(
Collection<Entry<String, Long>> assignments, String initiatedBy) { final Collection<Entry<String, Long>> assignments, final String initiatedBy) {
final Collection<Entry<String, Long>> distinctAssignments = assignments.stream().distinct().toList(); final Collection<Entry<String, Long>> distinctAssignments = assignments.stream().distinct().toList();
enforceMaxAssignmentsPerRequest(distinctAssignments.size()); enforceMaxAssignmentsPerRequest(distinctAssignments.size());

View File

@@ -844,6 +844,7 @@ public interface DdiRootControllerRestApi {
*/ */
@Operation(summary = "Set offline assigned version", description = """ @Operation(summary = "Set offline assigned version", description = """
Allow to set current running version. Allow to set current running version.
This method is EXPERIMENTAL and may change in future releases.
""") """)
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@@ -858,7 +859,7 @@ public interface DdiRootControllerRestApi {
@ApiResponse(responseCode = "415", description = "The request was attempt with a media-type which is not supported by the server for this resource.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), @ApiResponse(responseCode = "415", description = "The request was attempt with a media-type which is not supported by the server for this resource.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "429", description = "Too many requests. The server will refuse further attempts and the client has to wait another second.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))) @ApiResponse(responseCode = "429", description = "Too many requests. The server will refuse further attempts and the client has to wait another second.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true)))
}) })
@PostMapping(value = DdiRestConstants.BASE_V1_REQUEST_MAPPING + "/{controllerId}/" @PutMapping(value = DdiRestConstants.BASE_V1_REQUEST_MAPPING + "/{controllerId}/"
+ DdiRestConstants.INSTALLED_BASE_ACTION, consumes = { + DdiRestConstants.INSTALLED_BASE_ACTION, consumes = {
MediaType.APPLICATION_JSON_VALUE, DdiRestConstants.MEDIA_TYPE_CBOR }) MediaType.APPLICATION_JSON_VALUE, DdiRestConstants.MEDIA_TYPE_CBOR })
ResponseEntity<Void> setAsssignedOfflineVersion(@Valid DdiAssignedVersion ddiAssignedVersion, ResponseEntity<Void> setAsssignedOfflineVersion(@Valid DdiAssignedVersion ddiAssignedVersion,

View File

@@ -763,8 +763,9 @@ public class DdiRootController implements DdiRootControllerRestApi {
@PathVariable("tenant") final String tenant, @PathVariable("controllerId") final String controllerId){ @PathVariable("tenant") final String tenant, @PathVariable("controllerId") final String controllerId){
boolean updated = controllerManagement.updateOfflineAssignedVersion(controllerId, boolean updated = controllerManagement.updateOfflineAssignedVersion(controllerId,
ddiAssignedVersion.getName(), ddiAssignedVersion.getVersion()); ddiAssignedVersion.getName(), ddiAssignedVersion.getVersion());
if (updated) if (updated) {
return new ResponseEntity<>(HttpStatus.CREATED); return new ResponseEntity<>(HttpStatus.CREATED);
}
return new ResponseEntity<>(HttpStatus.OK); return new ResponseEntity<>(HttpStatus.OK);
} }
} }

View File

@@ -12,6 +12,7 @@ package org.eclipse.hawkbit.ddi.rest.resource;
import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.contains;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@@ -137,9 +138,9 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
statusMatcher); statusMatcher);
} }
protected ResultActions postInstalledBase(final String controllerId, final String content, protected ResultActions putInstalledBase(final String controllerId, final String content,
final ResultMatcher statusMatcher) throws Exception { final ResultMatcher statusMatcher) throws Exception {
return mvc.perform(post(INSTALLED_BASE_ROOT, tenantAware.getCurrentTenant(), controllerId) return mvc.perform(put(INSTALLED_BASE_ROOT, tenantAware.getCurrentTenant(), controllerId)
.content(content.getBytes()).contentType(MediaType.APPLICATION_JSON_UTF8)) .content(content.getBytes()).contentType(MediaType.APPLICATION_JSON_UTF8))
.andDo(MockMvcResultPrinter.print()).andExpect(statusMatcher); .andDo(MockMvcResultPrinter.print()).andExpect(statusMatcher);
} }

View File

@@ -42,7 +42,6 @@ import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedE
import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleUpdatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleUpdatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TargetCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.TargetCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent;
import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper;
import org.eclipse.hawkbit.repository.jpa.repository.ActionStatusRepository; import org.eclipse.hawkbit.repository.jpa.repository.ActionStatusRepository;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.ActionStatus; import org.eclipse.hawkbit.repository.model.ActionStatus;
@@ -56,9 +55,7 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
import org.springframework.hateoas.MediaTypes; import org.springframework.hateoas.MediaTypes;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
@@ -110,14 +107,14 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
// update assigned version // update assigned version
postInstalledBase(target.getControllerId(),getJsonInstalledBase(ds.getName(),ds.getVersion()),status() putInstalledBase(target.getControllerId(),getJsonInstalledBase(ds.getName(),ds.getVersion()),status()
.isCreated()); .isCreated());
assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId()).get().getId()) assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId()).get().getId())
.isEqualTo(ds.getId()); .isEqualTo(ds.getId());
// update assigned version while version already assigned // update assigned version while version already assigned
postInstalledBase(target.getControllerId(),getJsonInstalledBase(ds.getName(),ds.getVersion()),status().isOk()); putInstalledBase(target.getControllerId(),getJsonInstalledBase(ds.getName(),ds.getVersion()),status().isOk());
} }
@Test @Test
@Description("Ensure that installedVersion is version self assigned") @Description("Ensure that installedVersion is version self assigned")
@@ -128,7 +125,7 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
// get installed base // get installed base
postInstalledBase(target.getControllerId(),getJsonInstalledBase(dsName,dsVersion),status().isNotFound()); putInstalledBase(target.getControllerId(),getJsonInstalledBase(dsName,dsVersion),status().isNotFound());
assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId()).isEmpty()).isTrue(); assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId()).isEmpty()).isTrue();
} }