JpaDistributionSet#metadata made Map (#2411)
Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -1,33 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* Sort fields for DistributionSetMetadata.
|
||||
*/
|
||||
@Getter
|
||||
public enum DistributionSetMetadataFields implements RsqlQueryField {
|
||||
|
||||
KEY("key"),
|
||||
VALUE("value");
|
||||
|
||||
private final String jpaEntityFieldName;
|
||||
|
||||
DistributionSetMetadataFields(final String jpaEntityFieldName) {
|
||||
this.jpaEntityFieldName = jpaEntityFieldName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String identifierFieldName() {
|
||||
return KEY.getJpaEntityFieldName();
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,7 @@ import org.eclipse.hawkbit.mgmt.json.model.target.MgmtTarget;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.targetfilter.MgmtTargetFilterQuery;
|
||||
import org.eclipse.hawkbit.rest.json.model.ExceptionInfo;
|
||||
import org.springframework.hateoas.MediaTypes;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
@@ -44,6 +45,7 @@ import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
/**
|
||||
* REST Resource handling for DistributionSet CRUD operations.
|
||||
@@ -473,15 +475,50 @@ public interface MgmtDistributionSetRestApi {
|
||||
@RequestBody List<MgmtTargetAssignmentRequestBody> assignments,
|
||||
@RequestParam(value = "offline", required = false) Boolean offline);
|
||||
|
||||
/**
|
||||
* Creates a list of meta-data for a specific distribution set.
|
||||
*
|
||||
* @param distributionSetId the ID of the distribution set to create meta data for
|
||||
* @param metadataRest the list of meta-data entries to create
|
||||
*/
|
||||
@Operation(summary = "Create a list of meta data for a specific distribution set",
|
||||
description = "Create a list of meta data entries Required permissions: READ_REPOSITORY and UPDATE_TARGET")
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(responseCode = "201", description = "Successfully created"),
|
||||
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
|
||||
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
|
||||
@ApiResponse(responseCode = "401", description = "The request requires user authentication.",
|
||||
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
|
||||
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
|
||||
"changed (i.e. read-only) or data volume restriction applies.",
|
||||
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
|
||||
@ApiResponse(responseCode = "404", description = "Distribution Set not found.",
|
||||
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
|
||||
@ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource.",
|
||||
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
|
||||
@ApiResponse(responseCode = "406", description = "In case accept header is specified and not application/json.",
|
||||
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
|
||||
@ApiResponse(responseCode = "409", description = "E.g. in case an entity is created or modified by another " +
|
||||
"user in another request at the same time. You may retry your modification request.",
|
||||
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)))
|
||||
})
|
||||
@PostMapping(value = MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/metadata",
|
||||
consumes = { MediaType.APPLICATION_JSON_VALUE, MediaTypes.HAL_JSON_VALUE })
|
||||
@ResponseStatus(HttpStatus.CREATED)
|
||||
void createMetadata(
|
||||
@PathVariable("distributionSetId") Long distributionSetId,
|
||||
@RequestBody List<MgmtMetadata> metadataRest);
|
||||
|
||||
/**
|
||||
* Gets a paged list of meta-data for a distribution set.
|
||||
*
|
||||
* @param distributionSetId the ID of the distribution set for the meta-data
|
||||
* @param pagingOffsetParam the offset of list of targets for pagination, might not be present in the rest request then default value will
|
||||
* be applied
|
||||
* @param pagingLimitParam the limit of the paged request, might not be present in the rest request then default value will be applied
|
||||
* @param sortParam the sorting parameter in the request URL, syntax {@code field:direction, field:direction}
|
||||
* @param rsqlParam the search parameter in the request URL, syntax {@code q=key==abc}
|
||||
* @return status OK if get request is successful with the paged list of meta data
|
||||
*/
|
||||
@Operation(summary = "Return meta data for Distribution Set", description = "Get a paged list of meta data for a " +
|
||||
@@ -507,37 +544,14 @@ public interface MgmtDistributionSetRestApi {
|
||||
})
|
||||
@GetMapping(value = MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/metadata",
|
||||
produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<PagedList<MgmtMetadata>> getMetadata(
|
||||
@PathVariable("distributionSetId") Long distributionSetId,
|
||||
@RequestParam(
|
||||
value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET,
|
||||
defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET)
|
||||
@Schema(description = "The paging offset (default is 0)")
|
||||
int pagingOffsetParam,
|
||||
@RequestParam(
|
||||
value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT,
|
||||
defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT)
|
||||
@Schema(description = "The maximum number of entries in a page (default is 50)")
|
||||
int pagingLimitParam,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SORTING, required = false)
|
||||
@Schema(description = """
|
||||
The query parameter sort allows to define the sort order for the result of a query. A sort criteria
|
||||
consists of the name of a field and the sort direction (ASC for ascending and DESC descending).
|
||||
The sequence of the sort criteria (multiple can be used) defines the sort order of the entities
|
||||
in the result.""")
|
||||
String sortParam,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SEARCH, required = false)
|
||||
@Schema(description = """
|
||||
Query fields based on the Feed Item Query Language (FIQL). See Entity Definitions for
|
||||
available fields.""")
|
||||
String rsqlParam);
|
||||
ResponseEntity<PagedList<MgmtMetadata>> getMetadata(@PathVariable("distributionSetId") Long distributionSetId);
|
||||
|
||||
/**
|
||||
* Gets a single meta data value for a specific key of a distribution set.
|
||||
* Gets a single meta-data value for a specific key of a distribution set.
|
||||
*
|
||||
* @param distributionSetId the ID of the distribution set to get the meta data from
|
||||
* @param metadataKey the key of the meta data entry to retrieve the value from
|
||||
* @return status OK if get request is successful with the value of the meta data
|
||||
* @param distributionSetId the ID of the distribution set to get the meta-data from
|
||||
* @param metadataKey the key of the meta-data entry to retrieve the value from
|
||||
* @return status OK with the value of the meta-data, if the request is successful
|
||||
*/
|
||||
@Operation(summary = "Return single meta data value for a specific key of a Distribution Set",
|
||||
description = "Get a single meta data value for a meta data key. Required permission: READ_REPOSITORY")
|
||||
@@ -567,12 +581,11 @@ public interface MgmtDistributionSetRestApi {
|
||||
@PathVariable("metadataKey") String metadataKey);
|
||||
|
||||
/**
|
||||
* Updates a single meta data value of a distribution set.
|
||||
* Updates a single meta-data value of a distribution set.
|
||||
*
|
||||
* @param distributionSetId the ID of the distribution set to update the meta data entry
|
||||
* @param metadataKey the key of the meta data to update the value
|
||||
* @param metadataKey the key of the meta-data to update the value
|
||||
* @param metadata update body
|
||||
* @return status OK if the update request is successful and the updated meta data result
|
||||
*/
|
||||
@Operation(summary = "Update single meta data value of a distribution set", description = "Update a single meta " +
|
||||
"data value for speficic key. Required permission: UPDATE_REPOSITORY")
|
||||
@@ -601,9 +614,9 @@ public interface MgmtDistributionSetRestApi {
|
||||
"and the client has to wait another second.",
|
||||
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true)))
|
||||
})
|
||||
@PutMapping(value = MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/metadata/{metadataKey}",
|
||||
produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<MgmtMetadata> updateMetadata(
|
||||
@PutMapping(value = MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/metadata/{metadataKey}")
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
void updateMetadata(
|
||||
@PathVariable("distributionSetId") Long distributionSetId,
|
||||
@PathVariable("metadataKey") String metadataKey,
|
||||
@RequestBody MgmtMetadataBodyPut metadata);
|
||||
@@ -613,7 +626,6 @@ public interface MgmtDistributionSetRestApi {
|
||||
*
|
||||
* @param distributionSetId the ID of the distribution set to delete the meta data entry
|
||||
* @param metadataKey the key of the meta data to delete
|
||||
* @return status OK if the delete request is successful
|
||||
*/
|
||||
@Operation(summary = "Delete a single meta data entry from the distribution set", description = "Delete a single " +
|
||||
"meta data. Required permission: UPDATE_REPOSITORY")
|
||||
@@ -637,51 +649,11 @@ public interface MgmtDistributionSetRestApi {
|
||||
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true)))
|
||||
})
|
||||
@DeleteMapping(value = MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/metadata/{metadataKey}")
|
||||
ResponseEntity<Void> deleteMetadata(
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
void deleteMetadata(
|
||||
@PathVariable("distributionSetId") Long distributionSetId,
|
||||
@PathVariable("metadataKey") String metadataKey);
|
||||
|
||||
/**
|
||||
* Creates a list of meta data for a specific distribution set.
|
||||
*
|
||||
* @param distributionSetId the ID of the distribution set to create meta data for
|
||||
* @param metadataRest the list of meta data entries to create
|
||||
* @return status created if post request is successful with the value of the created meta data
|
||||
*/
|
||||
@Operation(summary = "Create a list of meta data for a specific distribution set", description = "Create a list " +
|
||||
"of meta data entries Required permissions: READ_REPOSITORY and UPDATE_TARGET")
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(responseCode = "201", description = "Successfully created"),
|
||||
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
|
||||
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
|
||||
@ApiResponse(responseCode = "401", description = "The request requires user authentication.",
|
||||
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
|
||||
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
|
||||
"changed (i.e. read-only) or data volume restriction applies.",
|
||||
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
|
||||
@ApiResponse(responseCode = "404", description = "Distribution Set not found.",
|
||||
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
|
||||
@ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource.",
|
||||
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
|
||||
@ApiResponse(responseCode = "406", description = "In case accept header is specified and not application/json.",
|
||||
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
|
||||
@ApiResponse(responseCode = "409", description = "E.g. in case an entity is created or modified by another " +
|
||||
"user in another request at the same time. You may retry your modification request.",
|
||||
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)))
|
||||
})
|
||||
@PostMapping(value = MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/metadata",
|
||||
consumes = { MediaType.APPLICATION_JSON_VALUE, MediaTypes.HAL_JSON_VALUE },
|
||||
produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<List<MgmtMetadata>> createMetadata(
|
||||
@PathVariable("distributionSetId") Long distributionSetId,
|
||||
@RequestBody List<MgmtMetadata> metadataRest);
|
||||
|
||||
/**
|
||||
* Assigns a list of software modules to a distribution set.
|
||||
*
|
||||
|
||||
@@ -16,6 +16,8 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
@@ -31,7 +33,6 @@ import org.eclipse.hawkbit.repository.EntityFactory;
|
||||
import org.eclipse.hawkbit.repository.builder.DistributionSetCreate;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.MetaData;
|
||||
import org.eclipse.hawkbit.rest.json.model.ResponseList;
|
||||
|
||||
@@ -53,16 +54,6 @@ public final class MgmtDistributionSetMapper {
|
||||
return sets.stream().map(dsRest -> fromRequest(dsRest, entityFactory)).toList();
|
||||
}
|
||||
|
||||
static List<MetaData> fromRequestDsMetadata(final List<MgmtMetadata> metadata, final EntityFactory entityFactory) {
|
||||
if (metadata == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return metadata.stream()
|
||||
.map(metadataRest -> entityFactory.generateDsMetadata(metadataRest.getKey(), metadataRest.getValue()))
|
||||
.toList();
|
||||
}
|
||||
|
||||
static MgmtDistributionSet toResponse(final DistributionSet distributionSet) {
|
||||
if (distributionSet == null) {
|
||||
return null;
|
||||
@@ -100,10 +91,8 @@ public final class MgmtDistributionSetMapper {
|
||||
response.add(linkTo(methodOn(MgmtDistributionSetTypeRestApi.class)
|
||||
.getDistributionSetType(distributionSet.getType().getId())).withRel("type").expand());
|
||||
|
||||
response.add(linkTo(methodOn(MgmtDistributionSetRestApi.class).getMetadata(response.getId(),
|
||||
MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET_VALUE,
|
||||
MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT_VALUE, null, null)).withRel("metadata")
|
||||
.expand());
|
||||
response.add(linkTo(methodOn(MgmtDistributionSetRestApi.class).getMetadata(response.getId()))
|
||||
.withRel("metadata").expand());
|
||||
}
|
||||
|
||||
static MgmtTargetAssignmentResponseBody toResponse(final DistributionSetAssignmentResult dsAssignmentResult) {
|
||||
@@ -138,19 +127,21 @@ public final class MgmtDistributionSetMapper {
|
||||
sets.stream().map(MgmtDistributionSetMapper::toResponse).toList());
|
||||
}
|
||||
|
||||
static MgmtMetadata toResponseDsMetadata(final DistributionSetMetadata metadata) {
|
||||
static MgmtMetadata toResponseDsMetadata(final String key, String value) {
|
||||
final MgmtMetadata metadataRest = new MgmtMetadata();
|
||||
metadataRest.setKey(metadata.getKey());
|
||||
metadataRest.setValue(metadata.getValue());
|
||||
metadataRest.setKey(key);
|
||||
metadataRest.setValue(value);
|
||||
return metadataRest;
|
||||
}
|
||||
|
||||
static List<MgmtMetadata> toResponseDsMetadata(final List<DistributionSetMetadata> metadata) {
|
||||
final List<MgmtMetadata> mappedList = new ArrayList<>(metadata.size());
|
||||
for (final DistributionSetMetadata distributionSetMetadata : metadata) {
|
||||
mappedList.add(toResponseDsMetadata(distributionSetMetadata));
|
||||
}
|
||||
return mappedList;
|
||||
static Map<String, String> fromRequestDsMetadata(final List<MgmtMetadata> metadata) {
|
||||
return metadata == null
|
||||
? Collections.emptyMap()
|
||||
: metadata.stream().collect(Collectors.toMap(MgmtMetadata::getKey, MgmtMetadata::getValue));
|
||||
}
|
||||
|
||||
static List<MgmtMetadata> toResponseDsMetadata(final Map<String, String> metadata) {
|
||||
return metadata.entrySet().stream().map(e -> toResponseDsMetadata(e.getKey(), e.getValue())).toList();
|
||||
}
|
||||
|
||||
static List<MgmtDistributionSet> toResponseFromDsList(final List<DistributionSet> sets) {
|
||||
|
||||
@@ -14,6 +14,7 @@ import java.util.AbstractMap.SimpleEntry;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -54,7 +55,6 @@ import org.eclipse.hawkbit.repository.model.DeploymentRequest;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
@@ -279,64 +279,37 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<PagedList<MgmtMetadata>> getMetadata(
|
||||
final Long distributionSetId,
|
||||
final int pagingOffsetParam, final int pagingLimitParam, final String sortParam, final String rsqlParam) {
|
||||
final int sanitizedOffsetParam = PagingUtility.sanitizeOffsetParam(pagingOffsetParam);
|
||||
final int sanitizedLimitParam = PagingUtility.sanitizePageLimitParam(pagingLimitParam);
|
||||
final Sort sorting = PagingUtility.sanitizeDistributionSetMetadataSortParam(sortParam);
|
||||
public void createMetadata(final Long distributionSetId, final List<MgmtMetadata> metadataRest) {
|
||||
distributionSetManagement.createMetadata(distributionSetId, MgmtDistributionSetMapper.fromRequestDsMetadata(metadataRest));
|
||||
}
|
||||
|
||||
final Pageable pageable = new OffsetBasedPageRequest(sanitizedOffsetParam, sanitizedLimitParam, sorting);
|
||||
final Page<DistributionSetMetadata> metaDataPage;
|
||||
|
||||
if (rsqlParam != null) {
|
||||
metaDataPage = distributionSetManagement.findMetaDataByDistributionSetIdAndRsql(distributionSetId, rsqlParam, pageable
|
||||
);
|
||||
} else {
|
||||
metaDataPage = distributionSetManagement.findMetaDataByDistributionSetId(distributionSetId, pageable);
|
||||
}
|
||||
|
||||
return ResponseEntity
|
||||
.ok(new PagedList<>(MgmtDistributionSetMapper.toResponseDsMetadata(metaDataPage.getContent()), metaDataPage.getTotalElements()));
|
||||
@Override
|
||||
public ResponseEntity<PagedList<MgmtMetadata>> getMetadata(final Long distributionSetId) {
|
||||
final Map<String, String> metadata = distributionSetManagement.getMetadata(distributionSetId);
|
||||
return ResponseEntity.ok(new PagedList<>(MgmtDistributionSetMapper.toResponseDsMetadata(metadata), metadata.size()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<MgmtMetadata> getMetadataValue(final Long distributionSetId, final String metadataKey) {
|
||||
// check if distribution set exists otherwise throw exception immediately
|
||||
final DistributionSetMetadata findOne = distributionSetManagement
|
||||
.findMetaDataByDistributionSetId(distributionSetId, metadataKey)
|
||||
.orElseThrow(() -> new EntityNotFoundException(DistributionSetMetadata.class, distributionSetId, metadataKey));
|
||||
return ResponseEntity.ok(MgmtDistributionSetMapper.toResponseDsMetadata(findOne));
|
||||
final String metadataValue = distributionSetManagement.getMetadata(distributionSetId).get(metadataKey);
|
||||
if (metadataValue == null) {
|
||||
throw new EntityNotFoundException("Target metadata", distributionSetId + ":" + metadataKey);
|
||||
}
|
||||
return ResponseEntity.ok(MgmtDistributionSetMapper.toResponseDsMetadata(metadataKey, metadataValue));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<MgmtMetadata> updateMetadata(
|
||||
final Long distributionSetId, final String metadataKey, final MgmtMetadataBodyPut metadata) {
|
||||
// check if distribution set exists otherwise throw exception immediately
|
||||
final DistributionSetMetadata updated = distributionSetManagement.updateMetaData(distributionSetId,
|
||||
entityFactory.generateDsMetadata(metadataKey, metadata.getValue()));
|
||||
return ResponseEntity.ok(MgmtDistributionSetMapper.toResponseDsMetadata(updated));
|
||||
public void updateMetadata(final Long distributionSetId, final String metadataKey, final MgmtMetadataBodyPut metadata) {
|
||||
distributionSetManagement.updateMetadata(distributionSetId, metadataKey, metadata.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<Void> deleteMetadata(final Long distributionSetId, final String metadataKey) {
|
||||
// check if distribution set exists otherwise throw exception immediately
|
||||
distributionSetManagement.deleteMetaData(distributionSetId, metadataKey);
|
||||
return ResponseEntity.ok().build();
|
||||
public void deleteMetadata(final Long distributionSetId, final String metadataKey) {
|
||||
distributionSetManagement.deleteMetadata(distributionSetId, metadataKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<List<MgmtMetadata>> createMetadata(final Long distributionSetId, final List<MgmtMetadata> metadataRest) {
|
||||
// check if distribution set exists otherwise throw exception immediately
|
||||
final List<DistributionSetMetadata> created = distributionSetManagement.putMetaData(distributionSetId,
|
||||
MgmtDistributionSetMapper.fromRequestDsMetadata(metadataRest, entityFactory));
|
||||
return new ResponseEntity<>(MgmtDistributionSetMapper.toResponseDsMetadata(created), HttpStatus.CREATED);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<Void> assignSoftwareModules(
|
||||
final Long distributionSetId, final List<MgmtSoftwareModuleAssignment> softwareModuleIDs) {
|
||||
public ResponseEntity<Void> assignSoftwareModules(final Long distributionSetId, final List<MgmtSoftwareModuleAssignment> softwareModuleIDs) {
|
||||
distributionSetManagement.assignSoftwareModules(
|
||||
distributionSetId,
|
||||
softwareModuleIDs.stream()
|
||||
|
||||
@@ -15,7 +15,6 @@ import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
||||
import org.eclipse.hawkbit.repository.ActionFields;
|
||||
import org.eclipse.hawkbit.repository.ActionStatusFields;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetFields;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetMetadataFields;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetTypeFields;
|
||||
import org.eclipse.hawkbit.repository.RolloutFields;
|
||||
import org.eclipse.hawkbit.repository.RolloutGroupFields;
|
||||
@@ -133,12 +132,12 @@ public final class PagingUtility {
|
||||
return Sort.by(SortUtility.parse(ActionStatusFields.class, sortParam));
|
||||
}
|
||||
|
||||
public static Sort sanitizeDistributionSetMetadataSortParam(final String sortParam) {
|
||||
public static Sort sanitizeMetadataSortParam(final String sortParam) {
|
||||
if (sortParam == null) {
|
||||
// default
|
||||
return Sort.by(Direction.ASC, DistributionSetMetadataFields.KEY.getJpaEntityFieldName());
|
||||
return Sort.by(Direction.ASC, SoftwareModuleMetadataFields.KEY.getJpaEntityFieldName());
|
||||
}
|
||||
return Sort.by(SortUtility.parse(DistributionSetMetadataFields.class, sortParam));
|
||||
return Sort.by(SortUtility.parse(SoftwareModuleMetadataFields.class, sortParam));
|
||||
}
|
||||
|
||||
public static Sort sanitizeSoftwareModuleMetadataSortParam(final String sortParam) {
|
||||
|
||||
@@ -30,6 +30,7 @@ import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.IntStream;
|
||||
@@ -51,7 +52,6 @@ import org.eclipse.hawkbit.repository.jpa.specifications.ActionSpecifications;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.NamedEntity;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
@@ -890,20 +890,20 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
|
||||
.getWithDetails(distributionSetManagement.findByRsql("name==three", PAGE).getContent().get(0).getId())
|
||||
.get();
|
||||
|
||||
assertThat((Object)JsonPath.compile("[0]_links.self.href").read(mvcResult.getResponse().getContentAsString()))
|
||||
assertThat((Object) JsonPath.compile("[0]_links.self.href").read(mvcResult.getResponse().getContentAsString()))
|
||||
.hasToString("http://localhost/rest/v1/distributionsets/" + one.getId());
|
||||
|
||||
assertThat((Object)JsonPath.compile("[0]id").read(mvcResult.getResponse().getContentAsString()))
|
||||
assertThat((Object) JsonPath.compile("[0]id").read(mvcResult.getResponse().getContentAsString()))
|
||||
.hasToString(String.valueOf(one.getId()));
|
||||
assertThat((Object)JsonPath.compile("[1]_links.self.href").read(mvcResult.getResponse().getContentAsString()))
|
||||
assertThat((Object) JsonPath.compile("[1]_links.self.href").read(mvcResult.getResponse().getContentAsString()))
|
||||
.hasToString("http://localhost/rest/v1/distributionsets/" + two.getId());
|
||||
|
||||
assertThat((Object)JsonPath.compile("[1]id").read(mvcResult.getResponse().getContentAsString()))
|
||||
assertThat((Object) JsonPath.compile("[1]id").read(mvcResult.getResponse().getContentAsString()))
|
||||
.hasToString(String.valueOf(two.getId()));
|
||||
assertThat((Object)JsonPath.compile("[2]_links.self.href").read(mvcResult.getResponse().getContentAsString()))
|
||||
assertThat((Object) JsonPath.compile("[2]_links.self.href").read(mvcResult.getResponse().getContentAsString()))
|
||||
.hasToString("http://localhost/rest/v1/distributionsets/" + three.getId());
|
||||
|
||||
assertThat((Object)JsonPath.compile("[2]id").read(mvcResult.getResponse().getContentAsString()))
|
||||
assertThat((Object) JsonPath.compile("[2]id").read(mvcResult.getResponse().getContentAsString()))
|
||||
.hasToString(String.valueOf(three.getId()));
|
||||
|
||||
// check in database
|
||||
@@ -1105,23 +1105,14 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
|
||||
metaData1.put(new JSONObject().put("key", knownKey1).put("value", knownValue1));
|
||||
metaData1.put(new JSONObject().put("key", knownKey2).put("value", knownValue2));
|
||||
|
||||
mvc.perform(post("/rest/v1/distributionsets/{dsId}/metadata", testDS.getId()).accept(MediaType.APPLICATION_JSON)
|
||||
.contentType(MediaType.APPLICATION_JSON).content(metaData1.toString()))
|
||||
mvc.perform(post("/rest/v1/distributionsets/{dsId}/metadata", testDS.getId())
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(metaData1.toString()))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isCreated())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
|
||||
.andExpect(jsonPath("[0]key", equalTo(knownKey1)))
|
||||
.andExpect(jsonPath("[0]value", equalTo(knownValue1)))
|
||||
.andExpect(jsonPath("[1]key", equalTo(knownKey2)))
|
||||
.andExpect(jsonPath("[1]value", equalTo(knownValue2)));
|
||||
.andExpect(status().isCreated());
|
||||
|
||||
final DistributionSetMetadata metaKey1 = distributionSetManagement
|
||||
.findMetaDataByDistributionSetId(testDS.getId(), knownKey1).get();
|
||||
final DistributionSetMetadata metaKey2 = distributionSetManagement
|
||||
.findMetaDataByDistributionSetId(testDS.getId(), knownKey2).get();
|
||||
|
||||
assertThat(metaKey1.getValue()).isEqualTo(knownValue1);
|
||||
assertThat(metaKey2.getValue()).isEqualTo(knownValue2);
|
||||
assertThat(distributionSetManagement.getMetadata(testDS.getId()).get(knownKey1)).isEqualTo(knownValue1);
|
||||
assertThat(distributionSetManagement.getMetadata(testDS.getId()).get(knownKey2)).isEqualTo(knownValue2);
|
||||
|
||||
// verify quota enforcement
|
||||
final int maxMetaData = quotaManagement.getMaxMetaDataEntriesPerDistributionSet();
|
||||
@@ -1131,17 +1122,14 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
|
||||
metaData2.put(new JSONObject().put("key", knownKey1 + i).put("value", knownValue1 + i));
|
||||
}
|
||||
|
||||
mvc.perform(post("/rest/v1/distributionsets/{dsId}/metadata", testDS.getId()).accept(MediaType.APPLICATION_JSON)
|
||||
.contentType(MediaType.APPLICATION_JSON).content(metaData2.toString()))
|
||||
mvc.perform(post("/rest/v1/distributionsets/{dsId}/metadata", testDS.getId())
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(metaData2.toString()))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isForbidden());
|
||||
|
||||
// verify that the number of meta data entries has not changed
|
||||
// (we cannot use the PAGE constant here as it tries to sort by ID)
|
||||
assertThat(distributionSetManagement
|
||||
.findMetaDataByDistributionSetId(testDS.getId(), PageRequest.of(0, Integer.MAX_VALUE))
|
||||
.getTotalElements()).isEqualTo(metaData1.length());
|
||||
|
||||
// verify that the number of meta-data entries has not changed (we cannot use the PAGE constant here as it tries to sort by ID)
|
||||
assertThat(distributionSetManagement.getMetadata(testDS.getId())).hasSize(metaData1.length());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1151,25 +1139,18 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
|
||||
final String knownKey = "knownKey";
|
||||
final String knownValue = "knownValue";
|
||||
final String updateValue = "valueForUpdate";
|
||||
|
||||
final DistributionSet testDS = testdataFactory.createDistributionSet("one");
|
||||
createDistributionSetMetadata(testDS.getId(), entityFactory.generateDsMetadata(knownKey, knownValue));
|
||||
distributionSetManagement.createMetadata(testDS.getId(), Map.of(knownKey, knownValue));
|
||||
|
||||
final JSONObject jsonObject = new JSONObject().put("key", knownKey).put("value", updateValue);
|
||||
|
||||
mvc.perform(put("/rest/v1/distributionsets/{dsId}/metadata/{key}", testDS.getId(), knownKey)
|
||||
.accept(MediaType.APPLICATION_JSON).contentType(MediaType.APPLICATION_JSON)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(jsonObject.toString()))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
|
||||
.andExpect(jsonPath("key", equalTo(knownKey)))
|
||||
.andExpect(jsonPath("value", equalTo(updateValue)));
|
||||
|
||||
final DistributionSetMetadata assertDS = distributionSetManagement
|
||||
.findMetaDataByDistributionSetId(testDS.getId(), knownKey).get();
|
||||
assertThat(assertDS.getValue()).isEqualTo(updateValue);
|
||||
.andExpect(status().isOk());
|
||||
|
||||
assertThat(distributionSetManagement.getMetadata(testDS.getId()).get(knownKey)).isEqualTo(updateValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1180,13 +1161,18 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
|
||||
final String knownValue = "knownValue";
|
||||
|
||||
final DistributionSet testDS = testdataFactory.createDistributionSet("one");
|
||||
createDistributionSetMetadata(testDS.getId(), entityFactory.generateDsMetadata(knownKey, knownValue));
|
||||
distributionSetManagement.createMetadata(testDS.getId(), Map.of(knownKey, knownValue));
|
||||
|
||||
mvc.perform(delete("/rest/v1/distributionsets/{dsId}/metadata/{key}", testDS.getId(), knownKey))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
assertThat(distributionSetManagement.findMetaDataByDistributionSetId(testDS.getId(), knownKey)).isNotPresent();
|
||||
// already deleted
|
||||
mvc.perform(delete("/rest/v1/distributionsets/{dsId}/metadata/{key}", testDS.getId(), knownKey))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotFound());
|
||||
|
||||
assertThat(distributionSetManagement.getMetadata(testDS.getId()).get(knownKey)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1195,9 +1181,8 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
|
||||
// prepare and create metadata for deletion
|
||||
final String knownKey = "knownKey";
|
||||
final String knownValue = "knownValue";
|
||||
|
||||
final DistributionSet testDS = testdataFactory.createDistributionSet("one");
|
||||
createDistributionSetMetadata(testDS.getId(), entityFactory.generateDsMetadata(knownKey, knownValue));
|
||||
distributionSetManagement.createMetadata(testDS.getId(), Map.of(knownKey, knownValue));
|
||||
|
||||
mvc.perform(delete("/rest/v1/distributionsets/{dsId}/metadata/XXX", testDS.getId(), knownKey))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
@@ -1207,17 +1192,17 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotFound());
|
||||
|
||||
assertThat(distributionSetManagement.findMetaDataByDistributionSetId(testDS.getId(), knownKey)).isPresent();
|
||||
assertThat(distributionSetManagement.getMetadata(testDS.getId()).get(knownKey)).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a metadata entry selection through API reflects the repository content.")
|
||||
void geteMetadataKey() throws Exception {
|
||||
void getMetadataKey() throws Exception {
|
||||
// prepare and create metadata
|
||||
final String knownKey = "knownKey";
|
||||
final String knownValue = "knownValue";
|
||||
final DistributionSet testDS = testdataFactory.createDistributionSet("one");
|
||||
createDistributionSetMetadata(testDS.getId(), entityFactory.generateDsMetadata(knownKey, knownValue));
|
||||
distributionSetManagement.createMetadata(testDS.getId(), Map.of(knownKey, knownValue));
|
||||
|
||||
mvc.perform(get("/rest/v1/distributionsets/{dsId}/metadata/{key}", testDS.getId(), knownKey))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
@@ -1234,43 +1219,15 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
|
||||
final String knownValuePrefix = "knownValue";
|
||||
final DistributionSet testDS = testdataFactory.createDistributionSet("one");
|
||||
for (int index = 0; index < totalMetadata; index++) {
|
||||
distributionSetManagement.putMetaData(testDS.getId(),
|
||||
List.of(entityFactory.generateDsMetadata(knownKeyPrefix + index, knownValuePrefix + index)));
|
||||
distributionSetManagement.createMetadata(testDS.getId(), Map.of(knownKeyPrefix + index, knownValuePrefix + index));
|
||||
}
|
||||
|
||||
mvc.perform(get(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/metadata",
|
||||
testDS.getId()))
|
||||
mvc.perform(get(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/metadata", testDS.getId()))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a metadata entry paged list selection through API reflectes the repository content.")
|
||||
void getPagedListOfMetadata() throws Exception {
|
||||
|
||||
final int totalMetadata = 10;
|
||||
final int limitParam = 5;
|
||||
final String offsetParam = "0";
|
||||
final String knownKeyPrefix = "knownKey";
|
||||
final String knownValuePrefix = "knownValue";
|
||||
final DistributionSet testDS = testdataFactory.createDistributionSet("one");
|
||||
for (int index = 0; index < totalMetadata; index++) {
|
||||
createDistributionSetMetadata(testDS.getId(),
|
||||
entityFactory.generateDsMetadata(knownKeyPrefix + index, knownValuePrefix + index));
|
||||
}
|
||||
|
||||
mvc.perform(get("/rest/v1/distributionsets/{dsId}/metadata?offset=" + offsetParam + "&limit=" + limitParam,
|
||||
testDS.getId()))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("size", equalTo(limitParam)))
|
||||
.andExpect(jsonPath("total", equalTo(totalMetadata)))
|
||||
.andExpect(jsonPath("content[0].key", equalTo("knownKey0")))
|
||||
.andExpect(jsonPath("content[0].value", equalTo("knownValue0")));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a DS search with query parameters returns the expected result.")
|
||||
void searchDistributionSetRsql() throws Exception {
|
||||
@@ -1334,29 +1291,6 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
|
||||
.andExpect(jsonPath("content[0].controllerId", equalTo("1")));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a DS metadata filtered query with value==knownValue1 parameter returns only the metadata entries with that value.")
|
||||
void searchDistributionSetMetadataRsql() throws Exception {
|
||||
final int totalMetadata = 10;
|
||||
final String knownKeyPrefix = "knownKey";
|
||||
final String knownValuePrefix = "knownValue";
|
||||
final DistributionSet testDS = testdataFactory.createDistributionSet("one");
|
||||
for (int index = 0; index < totalMetadata; index++) {
|
||||
createDistributionSetMetadata(testDS.getId(),
|
||||
entityFactory.generateDsMetadata(knownKeyPrefix + index, knownValuePrefix + index));
|
||||
}
|
||||
|
||||
final String rsqlSearchValue1 = "value==knownValue1";
|
||||
|
||||
mvc.perform(get("/rest/v1/distributionsets/{dsId}/metadata?q=" + rsqlSearchValue1, testDS.getId()))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("size", equalTo(1)))
|
||||
.andExpect(jsonPath("total", equalTo(1)))
|
||||
.andExpect(jsonPath("content[0].key", equalTo("knownKey1")))
|
||||
.andExpect(jsonPath("content[0].value", equalTo("knownValue1")));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that multi target assignment through API is reflected by the repository in the case of "
|
||||
+ "DOWNLOAD_ONLY.")
|
||||
|
||||
@@ -11,6 +11,7 @@ package org.eclipse.hawkbit.repository;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
@@ -30,7 +31,6 @@ import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldExc
|
||||
import org.eclipse.hawkbit.repository.exception.UnsupportedSoftwareModuleForThisDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetFilter;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
|
||||
import org.eclipse.hawkbit.repository.model.MetaData;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
@@ -124,29 +124,38 @@ public interface DistributionSetManagement extends RepositoryManagement<Distribu
|
||||
List<DistributionSet> unassignTag(@NotEmpty Collection<Long> ids, long tagId);
|
||||
|
||||
/**
|
||||
* Creates a list of distribution set meta-data entries.
|
||||
* Creates a map of distribution set meta-data entries.
|
||||
*
|
||||
* @param id if the {@link DistributionSet} the metadata has to be created for
|
||||
* @param metadata the meta-data entries to create or update
|
||||
* @return the updated or created distribution set meta-data entries
|
||||
* @throws EntityNotFoundException if given set does not exist
|
||||
* @throws EntityAlreadyExistsException in case one of the meta-data entry already exists for the specific key
|
||||
* @throws AssignmentQuotaExceededException if the maximum number of {@link MetaData} entries is exceeded for the addressed
|
||||
* {@link DistributionSet}
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
|
||||
List<DistributionSetMetadata> putMetaData(long id, @NotEmpty Collection<MetaData> metadata);
|
||||
void createMetadata(long id, @NotEmpty Map<String, String> metadata);
|
||||
|
||||
/**
|
||||
* Updates a distribution set meta-data value if corresponding entry exists.
|
||||
* Finds all meta-data by the given distribution set id.
|
||||
*
|
||||
* @param id the distribution set id to retrieve the meta-data from
|
||||
* @return a paged result of all meta-data entries for a given distribution set id
|
||||
* @throws EntityNotFoundException if distribution set with given ID does not exist
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
|
||||
Map<String, String> getMetadata(long id);
|
||||
|
||||
/**
|
||||
* Updates a distribution set meta-data values by adding them.
|
||||
*
|
||||
* @param id {@link DistributionSet} of the meta-data entry to be updated
|
||||
* @param metadata meta-data entry to be updated
|
||||
* @return the updated meta-data entry
|
||||
* @param key meta data-entry key to be updated
|
||||
* @param value meta data-entry to be new value
|
||||
* @throws EntityNotFoundException in case the meta-data entry does not exist and cannot be updated
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
|
||||
DistributionSetMetadata updateMetaData(long id, @NotNull MetaData metadata);
|
||||
void updateMetadata(long id, @NotNull String key, @NotNull String value);
|
||||
|
||||
/**
|
||||
* Deletes a distribution set meta-data entry.
|
||||
@@ -156,7 +165,7 @@ public interface DistributionSetManagement extends RepositoryManagement<Distribu
|
||||
* @throws EntityNotFoundException if given set does not exist
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
|
||||
void deleteMetaData(long id, @NotEmpty String key);
|
||||
void deleteMetadata(long id, @NotEmpty String key);
|
||||
|
||||
/**
|
||||
* Locks a distribution set. From then on its functional properties could not be changed, and it could be assigned to targets
|
||||
@@ -221,33 +230,6 @@ public interface DistributionSetManagement extends RepositoryManagement<Distribu
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
|
||||
Optional<DistributionSet> findByNameAndVersion(@NotEmpty String distributionName, @NotEmpty String version);
|
||||
|
||||
/**
|
||||
* Finds all meta-data by the given distribution set id.
|
||||
*
|
||||
* @param id the distribution set id to retrieve the meta-data from
|
||||
* @param pageable the page request to page the result
|
||||
* @return a paged result of all meta-data entries for a given distribution
|
||||
* set id
|
||||
* @throws EntityNotFoundException if distribution set with given ID does not exist
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
|
||||
Page<DistributionSetMetadata> findMetaDataByDistributionSetId(long id, @NotNull Pageable pageable);
|
||||
|
||||
/**
|
||||
* Finds all meta-data by the given distribution set id.
|
||||
*
|
||||
* @param id the distribution set id to retrieve the meta-data from
|
||||
* @param rsqlParam rsql query string
|
||||
* @param pageable the page request to page the result
|
||||
* @return a paged result of all meta-data entries for a given distribution set id
|
||||
* @throws RSQLParameterUnsupportedFieldException if a field in the RSQL string is used but not provided by the given
|
||||
* {@code fieldNameProvider}
|
||||
* @throws RSQLParameterSyntaxException if the RSQL syntax is wrong
|
||||
* @throws EntityNotFoundException of distribution set with given ID does not exist
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
|
||||
Page<DistributionSetMetadata> findMetaDataByDistributionSetIdAndRsql(long id, @NotNull String rsqlParam, @NotNull Pageable pageable);
|
||||
|
||||
/**
|
||||
* Finds all {@link DistributionSet}s based on completeness.
|
||||
*
|
||||
@@ -295,25 +277,6 @@ public interface DistributionSetManagement extends RepositoryManagement<Distribu
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
|
||||
Page<DistributionSet> findByRsqlAndTag(@NotNull String rsqlParam, long tagId, @NotNull Pageable pageable);
|
||||
|
||||
/**
|
||||
* Finds a single distribution set meta-data by its id.
|
||||
*
|
||||
* @param id of the {@link DistributionSet}
|
||||
* @param key of the meta-data element
|
||||
* @return the found DistributionSetMetadata
|
||||
* @throws EntityNotFoundException is set with given ID does not exist
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
|
||||
Optional<DistributionSetMetadata> findMetaDataByDistributionSetId(long id, @NotEmpty String key);/**
|
||||
* Counts all meta-data by the given distribution set id.
|
||||
*
|
||||
* @param id the distribution set id to retrieve the meta-data count from
|
||||
* @return count of ds metadata
|
||||
* @throws EntityNotFoundException if distribution set with given ID does not exist
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
|
||||
long countMetaDataByDistributionSetId(long id);
|
||||
|
||||
/**
|
||||
* Counts all {@link DistributionSet}s based on completeness.
|
||||
*
|
||||
|
||||
@@ -9,9 +9,6 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
import org.eclipse.hawkbit.repository.builder.ActionStatusBuilder;
|
||||
import org.eclipse.hawkbit.repository.builder.DistributionSetBuilder;
|
||||
import org.eclipse.hawkbit.repository.builder.DistributionSetTypeBuilder;
|
||||
@@ -43,17 +40,6 @@ public interface EntityFactory {
|
||||
*/
|
||||
DistributionSetBuilder distributionSet();
|
||||
|
||||
/**
|
||||
* Generates an {@link MetaData} element for distribution set without
|
||||
* persisting it.
|
||||
*
|
||||
* @param key {@link MetaData#getKey()}
|
||||
* @param value {@link MetaData#getValue()}
|
||||
* @return {@link MetaData} object
|
||||
*/
|
||||
MetaData generateDsMetadata(@Size(min = 1, max = MetaData.KEY_MAX_SIZE) @NotNull String key,
|
||||
@Size(max = MetaData.VALUE_MAX_SIZE) String value);
|
||||
|
||||
/**
|
||||
* @return {@link SoftwareModuleMetadataBuilder} object
|
||||
*/
|
||||
|
||||
@@ -23,6 +23,16 @@ import java.util.Set;
|
||||
*/
|
||||
public interface DistributionSet extends NamedVersionedEntity {
|
||||
|
||||
/**
|
||||
* Maximum length of metadata key.
|
||||
*/
|
||||
int METADATA_KEY_SIZE = 128;
|
||||
|
||||
/**
|
||||
* Maximum length of metadata value.
|
||||
*/
|
||||
int METADATA_VALUE_SIZE = 4000;
|
||||
|
||||
/**
|
||||
* @return type of the {@link DistributionSet}.
|
||||
*/
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.model;
|
||||
|
||||
/**
|
||||
* {@link MetaData} of a {@link DistributionSet}.
|
||||
*/
|
||||
public interface DistributionSetMetadata extends MetaData {
|
||||
|
||||
/**
|
||||
* @return {@link DistributionSet} of this {@link MetaData} entry.
|
||||
*/
|
||||
DistributionSet getDistributionSet();
|
||||
|
||||
@Override
|
||||
default Long getEntityId() {
|
||||
return getDistributionSet().getId();
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,6 @@ import org.eclipse.hawkbit.repository.jpa.builder.JpaActionStatusBuilder;
|
||||
import org.eclipse.hawkbit.repository.jpa.builder.JpaRolloutGroupBuilder;
|
||||
import org.eclipse.hawkbit.repository.jpa.builder.JpaSoftwareModuleTypeBuilder;
|
||||
import org.eclipse.hawkbit.repository.jpa.builder.JpaTagBuilder;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.MetaData;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
@@ -71,11 +70,6 @@ public class JpaEntityFactory implements EntityFactory {
|
||||
return distributionSetBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaData generateDsMetadata(final String key, final String value) {
|
||||
return new JpaDistributionSetMetadata(key, value == null ? null : value.strip());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SoftwareModuleMetadataBuilder softwareModuleMetadata() {
|
||||
return softwareModuleMetadataBuilder;
|
||||
|
||||
@@ -119,7 +119,6 @@ import org.eclipse.hawkbit.repository.jpa.model.helper.SecurityTokenGeneratorHol
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.TenantAwareHolder;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.ActionStatusRepository;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetMetadataRepository;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetRepository;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetTagRepository;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetTypeRepository;
|
||||
@@ -536,7 +535,6 @@ public class RepositoryApplicationConfiguration {
|
||||
final DistributionSetRepository distributionSetRepository,
|
||||
final DistributionSetTagManagement distributionSetTagManagement, final SystemManagement systemManagement,
|
||||
final DistributionSetTypeManagement distributionSetTypeManagement, final QuotaManagement quotaManagement,
|
||||
final DistributionSetMetadataRepository distributionSetMetadataRepository,
|
||||
final TargetRepository targetRepository,
|
||||
final TargetFilterQueryRepository targetFilterQueryRepository, final ActionRepository actionRepository,
|
||||
final SystemSecurityContext systemSecurityContext, final TenantConfigurationManagement tenantConfigurationManagement,
|
||||
@@ -544,7 +542,7 @@ public class RepositoryApplicationConfiguration {
|
||||
final DistributionSetTagRepository distributionSetTagRepository,
|
||||
final JpaProperties properties, final RepositoryProperties repositoryProperties) {
|
||||
return new JpaDistributionSetManagement(entityManager, distributionSetRepository, distributionSetTagManagement,
|
||||
systemManagement, distributionSetTypeManagement, quotaManagement, distributionSetMetadataRepository,
|
||||
systemManagement, distributionSetTypeManagement, quotaManagement,
|
||||
targetRepository, targetFilterQueryRepository, actionRepository,
|
||||
TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement),
|
||||
virtualPropertyReplacer, softwareModuleRepository, distributionSetTagRepository,
|
||||
|
||||
@@ -12,9 +12,9 @@ package org.eclipse.hawkbit.repository.jpa.management;
|
||||
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.IMPLICIT_LOCK_ENABLED;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
@@ -24,11 +24,15 @@ import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||
import jakarta.persistence.criteria.CriteriaQuery;
|
||||
import jakarta.persistence.criteria.MapJoin;
|
||||
import jakarta.persistence.criteria.Root;
|
||||
import jakarta.persistence.metamodel.MapAttribute;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import org.eclipse.hawkbit.repository.DistributionSetFields;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetManagement;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetMetadataFields;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetTagManagement;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
|
||||
import org.eclipse.hawkbit.repository.QuotaManagement;
|
||||
@@ -49,14 +53,10 @@ import org.eclipse.hawkbit.repository.jpa.acm.AccessController;
|
||||
import org.eclipse.hawkbit.repository.jpa.builder.JpaDistributionSetCreate;
|
||||
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.DsMetadataCompositeKey;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetMetadata;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetMetadata_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetMetadataRepository;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetRepository;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetTagRepository;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.SoftwareModuleRepository;
|
||||
@@ -69,10 +69,8 @@ import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetFilter;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.MetaData;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.Statistic;
|
||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||
@@ -103,7 +101,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
private final SystemManagement systemManagement;
|
||||
private final DistributionSetTypeManagement distributionSetTypeManagement;
|
||||
private final QuotaManagement quotaManagement;
|
||||
private final DistributionSetMetadataRepository distributionSetMetadataRepository;
|
||||
private final TargetRepository targetRepository;
|
||||
private final TargetFilterQueryRepository targetFilterQueryRepository;
|
||||
private final ActionRepository actionRepository;
|
||||
@@ -120,7 +117,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
final DistributionSetRepository distributionSetRepository,
|
||||
final DistributionSetTagManagement distributionSetTagManagement, final SystemManagement systemManagement,
|
||||
final DistributionSetTypeManagement distributionSetTypeManagement, final QuotaManagement quotaManagement,
|
||||
final DistributionSetMetadataRepository distributionSetMetadataRepository,
|
||||
final TargetRepository targetRepository,
|
||||
final TargetFilterQueryRepository targetFilterQueryRepository, final ActionRepository actionRepository,
|
||||
final TenantConfigHelper tenantConfigHelper,
|
||||
@@ -135,7 +131,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
this.systemManagement = systemManagement;
|
||||
this.distributionSetTypeManagement = distributionSetTypeManagement;
|
||||
this.quotaManagement = quotaManagement;
|
||||
this.distributionSetMetadataRepository = distributionSetMetadataRepository;
|
||||
this.targetRepository = targetRepository;
|
||||
this.targetFilterQueryRepository = targetFilterQueryRepository;
|
||||
this.actionRepository = actionRepository;
|
||||
@@ -360,21 +355,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public DistributionSetMetadata updateMetaData(final long id, final MetaData md) {
|
||||
// check if exists otherwise throw entity not found exception
|
||||
final JpaDistributionSetMetadata toUpdate = (JpaDistributionSetMetadata) findMetaDataByDistributionSetId(id, md.getKey())
|
||||
.orElseThrow(() -> new EntityNotFoundException(DistributionSetMetadata.class, id, md.getKey()));
|
||||
toUpdate.setValue(md.getValue());
|
||||
|
||||
// touch it to update the lock revision because we are modifying the DS indirectly, it will, also check UPDATE access
|
||||
JpaManagementHelper.touch(entityManager, distributionSetRepository, (JpaDistributionSet) getValid(id));
|
||||
return distributionSetMetadataRepository.save(toUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
@@ -394,34 +374,60 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
@Transactional
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public List<DistributionSetMetadata> putMetaData(final long id, final Collection<MetaData> md) {
|
||||
public void createMetadata(final long id, final Map<String, String> md) {
|
||||
final JpaDistributionSet distributionSet = (JpaDistributionSet) getValid(id);
|
||||
assertMetaDataQuota(id, md.size());
|
||||
|
||||
md.forEach(meta -> checkAndThrowIfDistributionSetMetadataAlreadyExists(
|
||||
new DsMetadataCompositeKey(id, meta.getKey())));
|
||||
// get the modifiable metadata map
|
||||
final Map<String, String> metadata = distributionSet.getMetadata();
|
||||
md.keySet().forEach(key -> {
|
||||
if (metadata.containsKey(key)) {
|
||||
throw new EntityAlreadyExistsException("Metadata entry with key '" + key + "' already exists");
|
||||
}
|
||||
});
|
||||
metadata.putAll(md);
|
||||
|
||||
JpaManagementHelper.touch(entityManager, distributionSetRepository, distributionSet);
|
||||
assertMetaDataQuota(id, metadata.size());
|
||||
|
||||
return md.stream()
|
||||
.map(meta -> distributionSetMetadataRepository
|
||||
.save(new JpaDistributionSetMetadata(meta.getKey(), distributionSet, meta.getValue())))
|
||||
.collect(Collectors.toUnmodifiableList());
|
||||
distributionSetRepository.save(distributionSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getMetadata(final long id) {
|
||||
assertDistributionSetExists(id);
|
||||
return getMap(id, JpaDistributionSet_.metadata);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public void deleteMetaData(final long id, final String key) {
|
||||
final JpaDistributionSetMetadata metadata = (JpaDistributionSetMetadata) findMetaDataByDistributionSetId(
|
||||
id, key)
|
||||
.orElseThrow(() -> new EntityNotFoundException(DistributionSetMetadata.class, id, key));
|
||||
public void updateMetadata(final long id, final String key, final String value) {
|
||||
final JpaDistributionSet distributionSet = (JpaDistributionSet) getValid(id);
|
||||
|
||||
// touch it to update the lock revision because we are modifying the
|
||||
// DS indirectly, it will, also check UPDATE access
|
||||
JpaManagementHelper.touch(entityManager, distributionSetRepository, metadata.getDistributionSet());
|
||||
distributionSetMetadataRepository.deleteById(metadata.getId());
|
||||
// get the modifiable metadata map
|
||||
final Map<String, String> metadata = distributionSet.getMetadata();
|
||||
if (!metadata.containsKey(key)) {
|
||||
throw new EntityNotFoundException("DistributionSet metadata", id + ":" + key);
|
||||
}
|
||||
metadata.put(key, value);
|
||||
|
||||
distributionSetRepository.save(distributionSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public void deleteMetadata(final long id, final String key) {
|
||||
final JpaDistributionSet distributionSet = (JpaDistributionSet) getValid(id);
|
||||
|
||||
// get the modifiable metadata map
|
||||
final Map<String, String> metadata = distributionSet.getMetadata();
|
||||
if (metadata.remove(key) == null) {
|
||||
throw new EntityNotFoundException("DistributionSet metadata", id + ":" + key);
|
||||
}
|
||||
|
||||
distributionSetRepository.save(distributionSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -504,33 +510,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
return distributionSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<DistributionSetMetadata> findMetaDataByDistributionSetId(final long id, final Pageable pageable) {
|
||||
assertDistributionSetExists(id);
|
||||
|
||||
return JpaManagementHelper.findAllWithCountBySpec(distributionSetMetadataRepository, Collections.singletonList(byDsIdSpec(id)), pageable
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countMetaDataByDistributionSetId(final long id) {
|
||||
assertDistributionSetExists(id);
|
||||
|
||||
return distributionSetMetadataRepository.countByDistributionSetId(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<DistributionSetMetadata> findMetaDataByDistributionSetIdAndRsql(final long id, final String rsqlParam,
|
||||
final Pageable pageable) {
|
||||
assertDistributionSetExists(id);
|
||||
|
||||
final List<Specification<JpaDistributionSetMetadata>> specList = Arrays
|
||||
.asList(RSQLUtility.buildRsqlSpecification(rsqlParam, DistributionSetMetadataFields.class,
|
||||
virtualPropertyReplacer, database), byDsIdSpec(id));
|
||||
|
||||
return JpaManagementHelper.findAllWithCountBySpec(distributionSetMetadataRepository, specList, pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Slice<DistributionSet> findByCompleted(final Pageable pageReq, final Boolean complete) {
|
||||
final List<Specification<JpaDistributionSet>> specifications = buildSpecsByComplete(complete);
|
||||
@@ -577,15 +556,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
DistributionSetSpecification.hasTag(tagId), DistributionSetSpecification.isNotDeleted()), pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<DistributionSetMetadata> findMetaDataByDistributionSetId(final long id, final String key) {
|
||||
assertDistributionSetExists(id);
|
||||
|
||||
return distributionSetMetadataRepository
|
||||
.findById(new DsMetadataCompositeKey(id, key))
|
||||
.map(DistributionSetMetadata.class::cast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countByTypeId(final long typeId) {
|
||||
if (!distributionSetTypeManagement.exists(typeId)) {
|
||||
@@ -732,6 +702,24 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, String> getMap(final long id, final MapAttribute<JpaDistributionSet, String, String> mapAttribute) {
|
||||
final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
|
||||
final CriteriaQuery<Object[]> query = cb.createQuery(Object[].class);
|
||||
|
||||
final Root<JpaDistributionSet> targetRoot = query.from(JpaDistributionSet.class);
|
||||
query.where(cb.equal(targetRoot.get(AbstractJpaBaseEntity_.ID), id));
|
||||
|
||||
final MapJoin<JpaDistributionSet, String, String> mapJoin = targetRoot.join(mapAttribute);
|
||||
query.multiselect(mapJoin.key(), mapJoin.value());
|
||||
query.orderBy(cb.asc(mapJoin.key()));
|
||||
|
||||
return entityManager
|
||||
.createQuery(query)
|
||||
.getResultList()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(entry -> (String) entry[0], entry -> (String) entry[1], (v1, v2) -> v1, LinkedHashMap::new));
|
||||
}
|
||||
|
||||
private JpaSoftwareModule findSoftwareModuleAndThrowExceptionIfNotFound(final Long softwareModuleId) {
|
||||
return softwareModuleRepository.findById(softwareModuleId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, softwareModuleId));
|
||||
@@ -754,9 +742,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
}
|
||||
|
||||
private void assertMetaDataQuota(final Long dsId, final int requested) {
|
||||
QuotaHelper.assertAssignmentQuota(dsId, requested, quotaManagement.getMaxMetaDataEntriesPerDistributionSet(),
|
||||
DistributionSetMetadata.class, DistributionSet.class,
|
||||
distributionSetMetadataRepository::countByDistributionSetId);
|
||||
final int limit = quotaManagement.getMaxMetaDataEntriesPerDistributionSet();
|
||||
QuotaHelper.assertAssignmentQuota(dsId, requested, limit, "Metadata", DistributionSet.class.getSimpleName(), null);
|
||||
}
|
||||
|
||||
private void assertSoftwareModuleQuota(final Long id, final int requested) {
|
||||
@@ -764,11 +751,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
SoftwareModule.class, DistributionSet.class, softwareModuleRepository::countByAssignedToId);
|
||||
}
|
||||
|
||||
private Specification<JpaDistributionSetMetadata> byDsIdSpec(final long dsId) {
|
||||
return (root, query, cb) -> cb
|
||||
.equal(root.get(JpaDistributionSetMetadata_.distributionSet).get(AbstractJpaBaseEntity_.id), dsId);
|
||||
}
|
||||
|
||||
private void assertDistributionSetIsNotAssignedToTargets(final Long distributionSet) {
|
||||
if (actionRepository.countByDistributionSetId(distributionSet) > 0) {
|
||||
throw new EntityReadOnlyException(String.format(
|
||||
@@ -776,13 +758,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
}
|
||||
}
|
||||
|
||||
private void checkAndThrowIfDistributionSetMetadataAlreadyExists(final DsMetadataCompositeKey metadataId) {
|
||||
if (distributionSetMetadataRepository.existsById(metadataId)) {
|
||||
throw new EntityAlreadyExistsException(
|
||||
"Metadata entry with key '" + metadataId.getKey() + "' already exists");
|
||||
}
|
||||
}
|
||||
|
||||
private List<JpaDistributionSet> getDistributionSets(final Collection<Long> ids) {
|
||||
final List<JpaDistributionSet> foundDs = distributionSetRepository.findAllById(ids);
|
||||
if (foundDs.size() != ids.size()) {
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.model;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* The DistributionSet Metadata composite key which contains the meta-data key and the ID of the DistributionSet itself.
|
||||
*/
|
||||
@NoArgsConstructor // Default constructor for JPA
|
||||
@Setter
|
||||
@Getter
|
||||
public final class DsMetadataCompositeKey implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String key;
|
||||
private Long distributionSet;
|
||||
|
||||
/**
|
||||
* @param distributionSet the distribution set for this meta data
|
||||
* @param key the key of the meta data
|
||||
*/
|
||||
public DsMetadataCompositeKey(final Long distributionSet, final String key) {
|
||||
this.distributionSet = distributionSet;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + (distributionSet == null ? 0 : distributionSet.hashCode());
|
||||
result = prime * result + (key == null ? 0 : key.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final DsMetadataCompositeKey other = (DsMetadataCompositeKey) obj;
|
||||
if (distributionSet == null) {
|
||||
if (other.distributionSet != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!distributionSet.equals(other.distributionSet)) {
|
||||
return false;
|
||||
}
|
||||
if (key == null) {
|
||||
return other.key == null;
|
||||
} else {
|
||||
return key.equals(other.key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,13 +13,14 @@ import java.io.Serial;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import jakarta.persistence.CascadeType;
|
||||
import jakarta.persistence.CollectionTable;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.ConstraintMode;
|
||||
import jakarta.persistence.ElementCollection;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.ForeignKey;
|
||||
@@ -28,9 +29,9 @@ import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.JoinTable;
|
||||
import jakarta.persistence.ManyToMany;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.MapKeyColumn;
|
||||
import jakarta.persistence.NamedAttributeNode;
|
||||
import jakarta.persistence.NamedEntityGraph;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.UniqueConstraint;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
@@ -47,7 +48,6 @@ import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetExcepti
|
||||
import org.eclipse.hawkbit.repository.exception.LockedException;
|
||||
import org.eclipse.hawkbit.repository.exception.UnsupportedSoftwareModuleForThisDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
@@ -109,11 +109,16 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen
|
||||
foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_tag_tag")) })
|
||||
private Set<DistributionSetTag> tags = new HashSet<>();
|
||||
|
||||
@ToString.Exclude
|
||||
@OneToMany(mappedBy = "distributionSet", fetch = FetchType.LAZY,
|
||||
cascade = { CascadeType.REMOVE },
|
||||
targetEntity = JpaDistributionSetMetadata.class)
|
||||
private List<DistributionSetMetadata> metadata;
|
||||
// no cascade option on an ElementCollection, the target objects are always persisted, merged, removed with their parent
|
||||
@Getter
|
||||
@ElementCollection
|
||||
@CollectionTable(
|
||||
name = "sp_ds_metadata",
|
||||
joinColumns = { @JoinColumn(name = "ds", nullable = false) },
|
||||
foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_metadata_ds"))
|
||||
@MapKeyColumn(name = "meta_key", length = DistributionSet.METADATA_KEY_SIZE)
|
||||
@Column(name = "meta_value", length = DistributionSet.METADATA_VALUE_SIZE)
|
||||
private Map<String, String> metadata;
|
||||
|
||||
@Column(name = "complete")
|
||||
private boolean complete;
|
||||
@@ -217,14 +222,6 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen
|
||||
return tags.remove(tag);
|
||||
}
|
||||
|
||||
public List<DistributionSetMetadata> getMetadata() {
|
||||
if (metadata == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return Collections.unmodifiableList(metadata);
|
||||
}
|
||||
|
||||
public void lock() {
|
||||
if (!isComplete()) {
|
||||
throw new IncompleteDistributionSetException("Could not be locked while incomplete!");
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.model;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
import jakarta.persistence.ConstraintMode;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.ForeignKey;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.IdClass;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
||||
|
||||
/**
|
||||
* Meta data for {@link DistributionSet}.
|
||||
*/
|
||||
@NoArgsConstructor // Default constructor needed for JPA entities.
|
||||
@Getter
|
||||
@IdClass(DsMetadataCompositeKey.class)
|
||||
@Entity
|
||||
@Table(name = "sp_ds_metadata")
|
||||
public class JpaDistributionSetMetadata extends AbstractJpaMetaData implements DistributionSetMetadata {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Id
|
||||
@ManyToOne(fetch = FetchType.LAZY, optional = false)
|
||||
@JoinColumn(name = "ds", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_metadata_ds"))
|
||||
private JpaDistributionSet distributionSet;
|
||||
|
||||
public JpaDistributionSetMetadata(final String key, final String value) {
|
||||
super(key, value);
|
||||
}
|
||||
|
||||
public JpaDistributionSetMetadata(final String key, final DistributionSet distributionSet, final String value) {
|
||||
super(key, value);
|
||||
this.distributionSet = (JpaDistributionSet) distributionSet;
|
||||
}
|
||||
|
||||
public DsMetadataCompositeKey getId() {
|
||||
return new DsMetadataCompositeKey(distributionSet.getId(), getKey());
|
||||
}
|
||||
|
||||
public void setDistributionSet(final DistributionSet distributionSet) {
|
||||
this.distributionSet = (JpaDistributionSet) distributionSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = super.hashCode();
|
||||
result = prime * result + ((distributionSet == null) ? 0 : distributionSet.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
// exception squid:S2259 - obj is checked for null in super
|
||||
@SuppressWarnings("squid:S2259")
|
||||
public boolean equals(final Object obj) {
|
||||
if (!super.equals(obj)) {
|
||||
return false;
|
||||
}
|
||||
final JpaDistributionSetMetadata other = (JpaDistributionSetMetadata) obj;
|
||||
if (distributionSet == null) {
|
||||
return other.distributionSet == null;
|
||||
} else {
|
||||
return distributionSet.equals(other.distributionSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.repository;
|
||||
|
||||
import org.eclipse.hawkbit.repository.jpa.model.DsMetadataCompositeKey;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* {@link DistributionSetMetadata} repository.
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public interface DistributionSetMetadataRepository
|
||||
extends PagingAndSortingRepository<JpaDistributionSetMetadata, DsMetadataCompositeKey>,
|
||||
CrudRepository<JpaDistributionSetMetadata, DsMetadataCompositeKey>,
|
||||
JpaSpecificationExecutor<JpaDistributionSetMetadata> {
|
||||
|
||||
/**
|
||||
* Counts the meta data entries that match the given distribution set ID.
|
||||
* <p/>
|
||||
* No access control applied
|
||||
*
|
||||
* @param id of the distribution set.
|
||||
* @return The number of matching meta data entries.
|
||||
*/
|
||||
long countByDistributionSetId(@Param("id") Long id);
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
|
||||
@@ -28,14 +29,12 @@ import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
|
||||
import org.eclipse.hawkbit.repository.jpa.acm.AccessController;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetMetadata;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
||||
import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetFilter;
|
||||
import org.eclipse.hawkbit.repository.model.MetaData;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -121,12 +120,18 @@ class DistributionSetAccessControllerTest extends AbstractAccessControllerTest {
|
||||
@Description("Verifies read access rules for distribution sets")
|
||||
void verifyDistributionSetUpdates() {
|
||||
// permit all operations first to prepare test setup
|
||||
permitAllOperations(AccessController.Operation.READ);
|
||||
permitAllOperations(AccessController.Operation.CREATE);
|
||||
permitAllOperations(AccessController.Operation.UPDATE);
|
||||
|
||||
final DistributionSet permitted = testdataFactory.createDistributionSet();
|
||||
final String mdPresetKey = "metadata.preset";
|
||||
final String mdPresetValue = "presetValue";
|
||||
distributionSetManagement.createMetadata(permitted.getId(), Map.of(mdPresetKey, mdPresetValue));
|
||||
final DistributionSet readOnly = testdataFactory.createDistributionSet();
|
||||
distributionSetManagement.createMetadata(readOnly.getId(), Map.of(mdPresetKey, mdPresetValue));
|
||||
final DistributionSet hidden = testdataFactory.createDistributionSet();
|
||||
distributionSetManagement.createMetadata(hidden.getId(), Map.of(mdPresetKey, mdPresetValue));
|
||||
|
||||
final SoftwareModule swModule = testdataFactory.createSoftwareModuleOs();
|
||||
|
||||
@@ -134,52 +139,49 @@ class DistributionSetAccessControllerTest extends AbstractAccessControllerTest {
|
||||
testAccessControlManger.deleteAllRules();
|
||||
// define access controlling rule
|
||||
defineAccess(AccessController.Operation.READ, permitted, readOnly);
|
||||
|
||||
// allow updating the permitted distributionSet
|
||||
defineAccess(AccessController.Operation.READ, permitted);
|
||||
defineAccess(AccessController.Operation.UPDATE, permitted);
|
||||
|
||||
// verify distributionSetManagement#assignSoftwareModules
|
||||
final var singleModuleIdList = Collections.singletonList(swModule.getId());
|
||||
final List<Long> singleModuleIdList = Collections.singletonList(swModule.getId());
|
||||
assertThat(distributionSetManagement.assignSoftwareModules(permitted.getId(), singleModuleIdList))
|
||||
.satisfies(ds -> assertThat(ds.getModules().stream().map(Identifiable::getId).toList()).contains(swModule.getId()));
|
||||
final Long readOnlyId = readOnly.getId();
|
||||
assertThatThrownBy(() -> distributionSetManagement.assignSoftwareModules(readOnlyId, singleModuleIdList))
|
||||
.as("Distribution set not allowed to me modified.")
|
||||
.isInstanceOf(EntityNotFoundException.class);
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
final Long hiddenId = hidden.getId();
|
||||
assertThatThrownBy(() -> distributionSetManagement.assignSoftwareModules(hiddenId, singleModuleIdList))
|
||||
.as("Distribution set should not be visible.")
|
||||
.isInstanceOf(EntityNotFoundException.class);
|
||||
|
||||
final JpaDistributionSetMetadata metadata = new JpaDistributionSetMetadata("test", "test");
|
||||
final Map<String, String> metadata = Map.of("test.create", mdPresetValue);
|
||||
|
||||
// verify distributionSetManagement#createMetaData
|
||||
final List<MetaData> metadataList = Collections.singletonList(metadata);
|
||||
distributionSetManagement.putMetaData(permitted.getId(), metadataList);
|
||||
assertThatThrownBy(() -> distributionSetManagement.putMetaData(readOnlyId, metadataList))
|
||||
.as("Distribution set not allowed to me modified.")
|
||||
.isInstanceOf(EntityNotFoundException.class);
|
||||
assertThatThrownBy(() -> distributionSetManagement.putMetaData(hiddenId, metadataList))
|
||||
distributionSetManagement.createMetadata(permitted.getId(), metadata);
|
||||
assertThatThrownBy(() -> distributionSetManagement.createMetadata(readOnlyId, metadata))
|
||||
.as("Distribution set not allowed to be modified.")
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
assertThatThrownBy(() -> distributionSetManagement.createMetadata(hiddenId, metadata))
|
||||
.as("Distribution set should not be visible.")
|
||||
.isInstanceOf(EntityNotFoundException.class);
|
||||
|
||||
// verify distributionSetManagement#updateMetaData
|
||||
distributionSetManagement.updateMetaData(permitted.getId(), metadata);
|
||||
assertThatThrownBy(() -> distributionSetManagement.updateMetaData(readOnlyId, metadata))
|
||||
final String newValue = "newValue";
|
||||
distributionSetManagement.updateMetadata(permitted.getId(), mdPresetKey, newValue);
|
||||
assertThatThrownBy(() -> distributionSetManagement.updateMetadata(readOnlyId, mdPresetKey, newValue))
|
||||
.as("Distribution set not allowed to me modified.")
|
||||
.isInstanceOf(EntityNotFoundException.class);
|
||||
assertThatThrownBy(() -> distributionSetManagement.updateMetaData(hiddenId, metadata))
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
assertThatThrownBy(() -> distributionSetManagement.updateMetadata(hiddenId, mdPresetKey, newValue))
|
||||
.as("Distribution set should not be visible.")
|
||||
.isInstanceOf(EntityNotFoundException.class);
|
||||
|
||||
// verify distributionSetManagement#deleteMetaData
|
||||
final String metadataKey = metadata.getKey();
|
||||
distributionSetManagement.deleteMetaData(permitted.getId(), metadataKey);
|
||||
assertThatThrownBy(() -> distributionSetManagement.deleteMetaData(readOnlyId, metadataKey))
|
||||
final String metadataKey = metadata.entrySet().stream().findAny().get().getKey();
|
||||
distributionSetManagement.deleteMetadata(permitted.getId(), metadataKey);
|
||||
assertThatThrownBy(() -> distributionSetManagement.deleteMetadata(readOnlyId, mdPresetKey))
|
||||
.as("Distribution set not allowed to me modified.")
|
||||
.isInstanceOf(EntityNotFoundException.class);
|
||||
assertThatThrownBy(() -> distributionSetManagement.deleteMetaData(hiddenId, metadataKey))
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
assertThatThrownBy(() -> distributionSetManagement.deleteMetadata(hiddenId, mdPresetKey))
|
||||
.as("Distribution set should not be visible.")
|
||||
.isInstanceOf(EntityNotFoundException.class);
|
||||
}
|
||||
|
||||
@@ -220,13 +220,12 @@ class TargetAccessControllerTest extends AbstractAccessControllerTest {
|
||||
|
||||
final Target permittedTarget = targetManagement
|
||||
.create(entityFactory.target().create().controllerId("device01").status(TargetUpdateStatus.REGISTERED));
|
||||
|
||||
final String hiddenTargetControllerId = targetManagement
|
||||
.create(entityFactory.target().create().controllerId("device02").status(TargetUpdateStatus.REGISTERED))
|
||||
.getControllerId();
|
||||
|
||||
// define access controlling rule
|
||||
defineAccess(AccessController.Operation.READ, permittedTarget);
|
||||
overwriteAccess(AccessController.Operation.READ, permittedTarget);
|
||||
|
||||
// verify targetManagement#findByUpdateStatus before assignment
|
||||
assertThat(targetManagement.findByUpdateStatus(Pageable.unpaged(), TargetUpdateStatus.REGISTERED).get()
|
||||
@@ -269,18 +268,15 @@ class TargetAccessControllerTest extends AbstractAccessControllerTest {
|
||||
|
||||
final Target manageableTarget = targetManagement
|
||||
.create(entityFactory.target().create().controllerId("device01").status(TargetUpdateStatus.REGISTERED));
|
||||
|
||||
final Target readOnlyTarget = targetManagement
|
||||
.create(entityFactory.target().create().controllerId("device02").status(TargetUpdateStatus.REGISTERED));
|
||||
|
||||
// define access controlling rule
|
||||
defineAccess(AccessController.Operation.READ, manageableTarget, readOnlyTarget);
|
||||
|
||||
defineAccess(AccessController.Operation.UPDATE, manageableTarget);
|
||||
// overwriting full access controlling rule
|
||||
overwriteAccess(AccessController.Operation.READ, manageableTarget, readOnlyTarget);
|
||||
overwriteAccess(AccessController.Operation.UPDATE, manageableTarget);
|
||||
|
||||
// assignment is permitted for manageableTarget
|
||||
assertThat(assignDistributionSet(firstDsId, manageableTarget.getControllerId()).getAssigned())
|
||||
.isEqualTo(1);
|
||||
assertThat(assignDistributionSet(firstDsId, manageableTarget.getControllerId()).getAssigned()).isEqualTo(1);
|
||||
|
||||
// assignment is denied for readOnlyTarget (read, but no update permissions)
|
||||
final var readOnlyTargetControllerId = readOnlyTarget.getControllerId();
|
||||
@@ -309,19 +305,17 @@ class TargetAccessControllerTest extends AbstractAccessControllerTest {
|
||||
|
||||
final List<Target> updateTargets = testdataFactory.createTargets("update1", "update2", "update3");
|
||||
final List<Target> readTargets = testdataFactory.createTargets("read1", "read2", "read3", "read4");
|
||||
final List<Target> hiddenTargets = testdataFactory.createTargets(
|
||||
"hidden1", "hidden2", "hidden3", "hidden4", "hidden5");
|
||||
final List<Target> hiddenTargets = testdataFactory.createTargets("hidden1", "hidden2", "hidden3", "hidden4", "hidden5");
|
||||
|
||||
defineAccess(AccessController.Operation.UPDATE, updateTargets);
|
||||
defineAccess(AccessController.Operation.READ, merge(readTargets, updateTargets));
|
||||
overwriteAccess(AccessController.Operation.READ, merge(readTargets, updateTargets));
|
||||
|
||||
final Rollout rollout = testdataFactory.createRolloutByVariables("testRollout", "description",
|
||||
updateTargets.size(), "id==*", ds, "50", "5");
|
||||
final Rollout rollout = testdataFactory.createRolloutByVariables(
|
||||
"testRollout", "description", updateTargets.size(), "id==*", ds, "50", "5");
|
||||
|
||||
assertThat(rollout.getTotalTargets()).isEqualTo(updateTargets.size());
|
||||
|
||||
final List<RolloutGroup> content = rolloutGroupManagement.findByRollout(rollout.getId(), Pageable.unpaged())
|
||||
.getContent();
|
||||
final List<RolloutGroup> content = rolloutGroupManagement.findByRollout(rollout.getId(), Pageable.unpaged()).getContent();
|
||||
assertThat(content).hasSize(updateTargets.size());
|
||||
|
||||
final List<Target> rolloutTargets = content.stream().flatMap(
|
||||
@@ -393,6 +387,18 @@ class TargetAccessControllerTest extends AbstractAccessControllerTest {
|
||||
target -> ids.contains(target.getId()));
|
||||
}
|
||||
|
||||
private void overwriteAccess(final AccessController.Operation operation, final Target... target) {
|
||||
overwriteAccess(operation, List.of(target));
|
||||
}
|
||||
|
||||
private void overwriteAccess(final AccessController.Operation operation, final List<Target> targets) {
|
||||
final List<Long> ids = targets.stream().map(Target::getId).toList();
|
||||
testAccessControlManger.overwriteAccessRule(
|
||||
JpaTarget.class, operation,
|
||||
TargetSpecifications.hasIdIn(ids),
|
||||
target -> ids.contains(target.getId()));
|
||||
}
|
||||
|
||||
private static Specification<JpaDistributionSet> dsById(final Long distid) {
|
||||
return (dsRoot, query, cb) -> {
|
||||
final Predicate predicate = cb.equal(dsRoot.get(JpaDistributionSet_.id), distid);
|
||||
|
||||
@@ -14,6 +14,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
@@ -37,14 +38,9 @@ class TargetTypeAccessControllerTest extends AbstractAccessControllerTest {
|
||||
@Test
|
||||
@Description("Verifies read access rules for target types")
|
||||
void verifyTargetTypeReadOperations() {
|
||||
permitAllOperations(AccessController.Operation.READ);
|
||||
permitAllOperations(AccessController.Operation.CREATE);
|
||||
|
||||
final TargetType permittedTargetType = targetTypeManagement
|
||||
.create(entityFactory.targetType().create().name("type1"));
|
||||
|
||||
final TargetType hiddenTargetType = targetTypeManagement
|
||||
.create(entityFactory.targetType().create().name("type2"));
|
||||
final TargetType permittedTargetType = targetTypeManagement.create(entityFactory.targetType().create().name("type1"));
|
||||
final TargetType hiddenTargetType = targetTypeManagement.create(entityFactory.targetType().create().name("type2"));
|
||||
|
||||
// define access controlling rule
|
||||
defineAccess(AccessController.Operation.READ, permittedTargetType);
|
||||
@@ -67,12 +63,12 @@ class TargetTypeAccessControllerTest extends AbstractAccessControllerTest {
|
||||
assertThat(targetTypeManagement.count()).isEqualTo(1);
|
||||
|
||||
// verify targetTypeManagement#countByName
|
||||
// assertThat(targetTypeManagement.countByName(permittedTargetType.getName())).isEqualTo(1);
|
||||
// assertThat(targetTypeManagement.countByName(hiddenTargetType.getName())).isZero();
|
||||
assertThat(targetTypeManagement.countByName(permittedTargetType.getName())).isEqualTo(1);
|
||||
assertThat(targetTypeManagement.countByName(hiddenTargetType.getName())).isZero();
|
||||
|
||||
// verify targetTypeManagement#countByName
|
||||
// assertThat(targetTypeManagement.countByName(permittedTargetType.getName())).isEqualTo(1);
|
||||
// assertThat(targetTypeManagement.countByName(hiddenTargetType.getName())).isZero();
|
||||
assertThat(targetTypeManagement.countByName(permittedTargetType.getName())).isEqualTo(1);
|
||||
assertThat(targetTypeManagement.countByName(hiddenTargetType.getName())).isZero();
|
||||
|
||||
// verify targetTypeManagement#get by id
|
||||
assertThat(targetTypeManagement.get(permittedTargetType.getId())).isPresent();
|
||||
@@ -161,15 +157,11 @@ class TargetTypeAccessControllerTest extends AbstractAccessControllerTest {
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
}
|
||||
|
||||
private void defineAccess(final AccessController.Operation operation, final TargetType... targetType) {
|
||||
defineAccess(operation, List.of(targetType));
|
||||
}
|
||||
|
||||
private void defineAccess(final AccessController.Operation operation, final List<TargetType> targetTypes) {
|
||||
final List<Long> ids = targetTypes.stream().map(TargetType::getId).toList();
|
||||
private void defineAccess(final AccessController.Operation operation, final TargetType... targetTypes) {
|
||||
final List<Long> ids = Stream.of(targetTypes).map(TargetType::getId).toList();
|
||||
testAccessControlManger.defineAccessRule(
|
||||
JpaTargetType.class, operation,
|
||||
TargetTypeSpecification.hasIdIn(ids),
|
||||
targetType -> ids.contains(targetType.getId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,23 @@ public class TestAccessControlManger {
|
||||
public <T> void defineAccessRule(
|
||||
final Class<T> ruleClass, final AccessController.Operation operation,
|
||||
final Specification<T> specification, final Predicate<T> check) {
|
||||
accessRules.put(new AccessRuleId<>(ruleClass, operation), new AccessRule<>(specification, check));
|
||||
defineAccessRule(ruleClass, operation, specification, check, false);
|
||||
}
|
||||
|
||||
public <T> void overwriteAccessRule(
|
||||
final Class<T> ruleClass, final AccessController.Operation operation,
|
||||
final Specification<T> specification, final Predicate<T> check) {
|
||||
defineAccessRule(ruleClass, operation, specification, check, true);
|
||||
}
|
||||
|
||||
private <T> void defineAccessRule(
|
||||
final Class<T> ruleClass, final AccessController.Operation operation,
|
||||
final Specification<T> specification, final Predicate<T> check, final boolean overwrite) {
|
||||
final AccessRuleId<T> ruleId = new AccessRuleId<>(ruleClass, operation);
|
||||
if (!overwrite && accessRules.containsKey(ruleId)) {
|
||||
throw new IllegalStateException("Access rule already defined for " + ruleId + "! You should explicitly set overwrite to true.");
|
||||
}
|
||||
accessRules.put(ruleId, new AccessRule<>(specification, check));
|
||||
}
|
||||
|
||||
public <T extends AbstractJpaBaseEntity> Specification<T> getAccessRule(final Class<T> ruleClass,
|
||||
@@ -53,8 +69,7 @@ public class TestAccessControlManger {
|
||||
} else {
|
||||
for (final T entity : entities) {
|
||||
if (!accessRule.checker.test(entity)) {
|
||||
throw new InsufficientPermissionException(
|
||||
"Access to " + ruleClass.getName() + "/" + entity + " not allowed by checker!");
|
||||
throw new InsufficientPermissionException("Access to " + ruleClass.getName() + "/" + entity + " not allowed by checker!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -67,4 +82,4 @@ public class TestAccessControlManger {
|
||||
private record AccessRuleId<T>(Class<T> ruleClass, AccessController.Operation operation) {}
|
||||
|
||||
private record AccessRule<T>(Specification<T> specification, Predicate<T> checker) {}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
package org.eclipse.hawkbit.repository.jpa.management;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
@@ -66,17 +67,36 @@ class DistributionSetManagementSecurityTest
|
||||
|
||||
@Test
|
||||
@Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.")
|
||||
void createMetaDataPermissionsCheck() {
|
||||
void createMetadataPermissionsCheck() {
|
||||
assertPermissions(
|
||||
() -> distributionSetManagement.putMetaData(1L, List.of(entityFactory.generateDsMetadata("key", "value"))),
|
||||
() -> {
|
||||
distributionSetManagement.createMetadata(1L, Map.of("key", "value"));
|
||||
return null;
|
||||
},
|
||||
List.of(SpPermission.UPDATE_REPOSITORY));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.")
|
||||
void deleteMetaDataPermissionsCheck() {
|
||||
void getMetadataPermissiosCheck() {
|
||||
assertPermissions(() -> distributionSetManagement.getMetadata(1L), List.of(SpPermission.READ_REPOSITORY));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.")
|
||||
void updateMetadataPermissionsCheck() {
|
||||
assertPermissions(() -> {
|
||||
distributionSetManagement.deleteMetaData(1L, "key");
|
||||
distributionSetManagement.updateMetadata(1L,"key", "value");
|
||||
return null;
|
||||
},
|
||||
List.of(SpPermission.UPDATE_REPOSITORY));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.")
|
||||
void deleteMetadataPermissionsCheck() {
|
||||
assertPermissions(() -> {
|
||||
distributionSetManagement.deleteMetadata(1L, "key");
|
||||
return null;
|
||||
}, List.of(SpPermission.UPDATE_REPOSITORY));
|
||||
}
|
||||
@@ -135,25 +155,6 @@ class DistributionSetManagementSecurityTest
|
||||
assertPermissions(() -> distributionSetManagement.getOrElseThrowException(1L), List.of(SpPermission.READ_REPOSITORY));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.")
|
||||
void findMetaDataByDistributionSetIdPermissionsCheck() {
|
||||
assertPermissions(() -> distributionSetManagement.findMetaDataByDistributionSetId(1L, PAGE), List.of(SpPermission.READ_REPOSITORY));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.")
|
||||
void countMetaDataByDistributionSetIdPermissionsCheck() {
|
||||
assertPermissions(() -> distributionSetManagement.countMetaDataByDistributionSetId(1L), List.of(SpPermission.READ_REPOSITORY));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.")
|
||||
void findMetaDataByDistributionSetIdAndRsqlPermissionsCheck() {
|
||||
assertPermissions(() -> distributionSetManagement.findMetaDataByDistributionSetIdAndRsql(1L, "rsql", PAGE),
|
||||
List.of(SpPermission.READ_REPOSITORY));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.")
|
||||
void findByCompletedPermissionsCheck() {
|
||||
@@ -192,12 +193,6 @@ class DistributionSetManagementSecurityTest
|
||||
assertPermissions(() -> distributionSetManagement.findByRsqlAndTag("rsql", 1L, PAGE), List.of(SpPermission.READ_REPOSITORY));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.")
|
||||
void getMetaDataByDistributionSetIdPermissionsCheck() {
|
||||
assertPermissions(() -> distributionSetManagement.findMetaDataByDistributionSetId(1L, "key"), List.of(SpPermission.READ_REPOSITORY));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.")
|
||||
void isInUsePermissionsCheck() {
|
||||
@@ -210,13 +205,6 @@ class DistributionSetManagementSecurityTest
|
||||
assertPermissions(() -> distributionSetManagement.unassignSoftwareModule(1L, 1L), List.of(SpPermission.UPDATE_REPOSITORY));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.")
|
||||
void updateMetaDataPermissionsCheck() {
|
||||
assertPermissions(() -> distributionSetManagement.updateMetaData(1L, entityFactory.generateDsMetadata("key", "value")),
|
||||
List.of(SpPermission.UPDATE_REPOSITORY));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.")
|
||||
void countByTypeIdPermissionsCheck() {
|
||||
|
||||
@@ -18,7 +18,9 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
@@ -49,17 +51,14 @@ import org.eclipse.hawkbit.repository.exception.LockedException;
|
||||
import org.eclipse.hawkbit.repository.exception.UnsupportedSoftwareModuleForThisDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetFilter;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetFilter.DistributionSetFilterBuilder;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation.CancelationType;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.MetaData;
|
||||
import org.eclipse.hawkbit.repository.model.NamedEntity;
|
||||
import org.eclipse.hawkbit.repository.model.NamedVersionedEntity;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
@@ -71,8 +70,6 @@ import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
|
||||
import org.eclipse.hawkbit.repository.test.util.WithUser;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
|
||||
/**
|
||||
* {@link DistributionSetManagement} tests.
|
||||
@@ -96,7 +93,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
assertThat(distributionSetManagement.get(NOT_EXIST_IDL)).isNotPresent();
|
||||
assertThat(distributionSetManagement.getWithDetails(NOT_EXIST_IDL)).isNotPresent();
|
||||
assertThat(distributionSetManagement.findByNameAndVersion(NOT_EXIST_ID, NOT_EXIST_ID)).isNotPresent();
|
||||
assertThat(distributionSetManagement.findMetaDataByDistributionSetId(set.getId(), NOT_EXIST_ID)).isNotPresent();
|
||||
assertThat(distributionSetManagement.getMetadata(set.getId()).get(NOT_EXIST_ID)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -138,44 +135,30 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.create(
|
||||
entityFactory.distributionSet().create().name("xxx").type(NOT_EXIST_ID)), "DistributionSetType");
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.putMetaData(
|
||||
NOT_EXIST_IDL, singletonList(entityFactory.generateDsMetadata("123", "123"))), "DistributionSet");
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.createMetadata(NOT_EXIST_IDL, Map.of("123", "123")), "DistributionSet");
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.delete(singletonList(NOT_EXIST_IDL)), "DistributionSet");
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.delete(NOT_EXIST_IDL), "DistributionSet");
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.deleteMetaData(NOT_EXIST_IDL, "xxx"),
|
||||
"DistributionSet");
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.deleteMetaData(set.getId(), NOT_EXIST_ID),
|
||||
"DistributionSetMetadata");
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.deleteMetadata(NOT_EXIST_IDL, "xxx"), "DistributionSet");
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.deleteMetadata(set.getId(), NOT_EXIST_ID), "DistributionSet");
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.findByAction(NOT_EXIST_IDL), "Action");
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.findMetaDataByDistributionSetId(NOT_EXIST_IDL, "xxx"),
|
||||
"DistributionSet");
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.getMetadata(NOT_EXIST_IDL).get("xxx"), "DistributionSet");
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.findMetaDataByDistributionSetId(NOT_EXIST_IDL, PAGE),
|
||||
"DistributionSet");
|
||||
|
||||
verifyThrownExceptionBy(
|
||||
() -> distributionSetManagement.findMetaDataByDistributionSetIdAndRsql(NOT_EXIST_IDL, "name==*", PAGE),
|
||||
"DistributionSet");
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.getMetadata(NOT_EXIST_IDL).get(PAGE), "DistributionSet");
|
||||
|
||||
assertThatThrownBy(() -> distributionSetManagement.isInUse(NOT_EXIST_IDL))
|
||||
.isInstanceOf(EntityNotFoundException.class).hasMessageContaining(NOT_EXIST_ID)
|
||||
.hasMessageContaining("DistributionSet");
|
||||
|
||||
verifyThrownExceptionBy(
|
||||
() -> distributionSetManagement.update(entityFactory.distributionSet().update(NOT_EXIST_IDL)),
|
||||
"DistributionSet");
|
||||
() -> distributionSetManagement.update(entityFactory.distributionSet().update(NOT_EXIST_IDL)), "DistributionSet");
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.updateMetaData(NOT_EXIST_IDL,
|
||||
entityFactory.generateDsMetadata("xxx", "xxx")), "DistributionSet");
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.updateMetadata(NOT_EXIST_IDL,"xxx", "xxx"), "DistributionSet");
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.updateMetadata(set.getId(),NOT_EXIST_ID, "xxx"), "DistributionSet");
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.updateMetaData(set.getId(),
|
||||
entityFactory.generateDsMetadata(NOT_EXIST_ID, "xxx")), "DistributionSetMetadata");
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.getOrElseThrowException(NOT_EXIST_IDL),
|
||||
"DistributionSet");
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.getOrElseThrowException(NOT_EXIST_IDL), "DistributionSet");
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.getValidAndComplete(NOT_EXIST_IDL), "DistributionSet");
|
||||
|
||||
@@ -247,68 +230,57 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Checks that metadata for a distribution set can be created.")
|
||||
void createDistributionSetMetadata() {
|
||||
void createMetadata() {
|
||||
final String knownKey = "dsMetaKnownKey";
|
||||
final String knownValue = "dsMetaKnownValue";
|
||||
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("testDs");
|
||||
|
||||
final DistributionSetMetadata metadata = new JpaDistributionSetMetadata(knownKey, ds, knownValue);
|
||||
final JpaDistributionSetMetadata createdMetadata = (JpaDistributionSetMetadata) createDistributionSetMetadata(
|
||||
ds.getId(), metadata);
|
||||
|
||||
assertThat(createdMetadata).isNotNull();
|
||||
assertThat(createdMetadata.getId().getKey()).isEqualTo(knownKey);
|
||||
assertThat(createdMetadata.getDistributionSet().getId()).isEqualTo(ds.getId());
|
||||
assertThat(createdMetadata.getValue()).isEqualTo(knownValue);
|
||||
insertMetadata(knownKey, knownValue, ds); // and validate
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies the enforcement of the metadata quota per distribution set.")
|
||||
void createDistributionSetMetadataUntilQuotaIsExceeded() {
|
||||
void createMetadataUntilQuotaIsExceeded() {
|
||||
|
||||
// add meta data one by one
|
||||
final DistributionSet ds1 = testdataFactory.createDistributionSet("ds1");
|
||||
final int maxMetaData = quotaManagement.getMaxMetaDataEntriesPerDistributionSet();
|
||||
for (int i = 0; i < maxMetaData; ++i) {
|
||||
assertThat((JpaDistributionSetMetadata) createDistributionSetMetadata(ds1.getId(),
|
||||
new JpaDistributionSetMetadata("k" + i, ds1, "v" + i))).isNotNull();
|
||||
insertMetadata("k" + i, "v" + i, ds1);
|
||||
}
|
||||
|
||||
// quota exceeded
|
||||
final Long ds1Id = ds1.getId();
|
||||
final JpaDistributionSetMetadata jpaMaxMetaData = new JpaDistributionSetMetadata("k" + maxMetaData, ds1, "v" + maxMetaData);
|
||||
assertThatExceptionOfType(AssignmentQuotaExceededException.class)
|
||||
.isThrownBy(() -> createDistributionSetMetadata(ds1Id, jpaMaxMetaData));
|
||||
.isThrownBy(() -> insertMetadata("k" + maxMetaData, "v" + maxMetaData, ds1));
|
||||
|
||||
// add multiple meta data entries at once
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSet("ds2");
|
||||
final List<MetaData> metaData2 = new ArrayList<>();
|
||||
final Map<String, String> metaData2 = new HashMap<>();
|
||||
for (int i = 0; i < maxMetaData + 1; ++i) {
|
||||
metaData2.add(new JpaDistributionSetMetadata("k" + i, ds2, "v" + i));
|
||||
metaData2.put("k" + i, "v" + i);
|
||||
}
|
||||
// verify quota is exceeded
|
||||
final Long ds2Id = ds2.getId();
|
||||
assertThatExceptionOfType(AssignmentQuotaExceededException.class)
|
||||
.isThrownBy(() -> createDistributionSetMetadata(ds2Id, metaData2));
|
||||
.isThrownBy(() -> distributionSetManagement.createMetadata(ds2Id, metaData2));
|
||||
|
||||
// add some meta data entries
|
||||
final DistributionSet ds3 = testdataFactory.createDistributionSet("ds3");
|
||||
final int firstHalf = Math.round((maxMetaData) / 2.f);
|
||||
final Long ds3Id = ds3.getId();
|
||||
for (int i = 0; i < firstHalf; ++i) {
|
||||
createDistributionSetMetadata(ds3Id, new JpaDistributionSetMetadata("k" + i, ds3, "v" + i));
|
||||
insertMetadata("k" + i, "v" + i, ds3);
|
||||
}
|
||||
// add too many data entries
|
||||
final int secondHalf = maxMetaData - firstHalf;
|
||||
final List<MetaData> metaData3 = new ArrayList<>();
|
||||
final Map<String, String> metaData3 = new HashMap<>();
|
||||
for (int i = 0; i < secondHalf + 1; ++i) {
|
||||
metaData3.add(new JpaDistributionSetMetadata("kk" + i, ds3, "vv" + i));
|
||||
metaData3.put("kk" + i, "vv" + i);
|
||||
}
|
||||
// verify quota is exceeded
|
||||
assertThatExceptionOfType(AssignmentQuotaExceededException.class)
|
||||
.isThrownBy(() -> createDistributionSetMetadata(ds3Id, metaData3));
|
||||
|
||||
.isThrownBy(() -> distributionSetManagement.createMetadata(ds3Id, metaData3));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -507,7 +479,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Test
|
||||
@WithUser(allSpPermissions = true)
|
||||
@Description("Checks that metadata for a distribution set can be updated.")
|
||||
void updateDistributionSetMetadata() {
|
||||
void updateMetadata() {
|
||||
final String knownKey = "myKnownKey";
|
||||
final String knownValue = "myKnownValue";
|
||||
final String knownUpdateValue = "myNewUpdatedValue";
|
||||
@@ -519,26 +491,22 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
waitNextMillis();
|
||||
// create an DS meta data entry
|
||||
createDistributionSetMetadata(ds.getId(), new JpaDistributionSetMetadata(knownKey, ds, knownValue));
|
||||
insertMetadata(knownKey, knownValue, ds);
|
||||
|
||||
final DistributionSet changedLockRevisionDS = getOrThrow(distributionSetManagement.get(ds.getId()));
|
||||
assertThat(changedLockRevisionDS.getOptLockRevision()).isEqualTo(2);
|
||||
|
||||
waitNextMillis();
|
||||
// update the DS metadata
|
||||
final JpaDistributionSetMetadata updated = (JpaDistributionSetMetadata) distributionSetManagement
|
||||
.updateMetaData(ds.getId(), entityFactory.generateDsMetadata(knownKey, knownUpdateValue));
|
||||
distributionSetManagement.updateMetadata(ds.getId(), knownKey, knownUpdateValue);
|
||||
// we are updating the sw metadata so also modifying the base software
|
||||
// module so opt lock revision must be three
|
||||
final DistributionSet reloadedDS = getOrThrow(distributionSetManagement.get(ds.getId()));
|
||||
assertThat(reloadedDS.getOptLockRevision()).isEqualTo(3);
|
||||
assertThat(reloadedDS.getLastModifiedAt()).isPositive();
|
||||
|
||||
// verify updated meta data contains the updated value
|
||||
assertThat(updated).isNotNull();
|
||||
assertThat(updated.getValue()).isEqualTo(knownUpdateValue);
|
||||
assertThat(updated.getId().getKey()).isEqualTo(knownKey);
|
||||
assertThat(updated.getDistributionSet().getId()).isEqualTo(ds.getId());
|
||||
// verify updated meta data is the updated value
|
||||
assertThat(distributionSetManagement.getMetadata(ds.getId()).get(knownKey)).isEqualTo(knownUpdateValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -783,37 +751,22 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Queries and loads the metadata related to a given software module.")
|
||||
void findAllDistributionSetMetadataByDsId() {
|
||||
@Description("Queries and loads the metadata related to a given distribution set.")
|
||||
void getMetadata() {
|
||||
// create a DS
|
||||
final DistributionSet ds1 = testdataFactory.createDistributionSet("testDs1");
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSet("testDs2");
|
||||
|
||||
for (int index = 0; index < quotaManagement.getMaxMetaDataEntriesPerDistributionSet(); index++) {
|
||||
createDistributionSetMetadata(ds1.getId(),
|
||||
new JpaDistributionSetMetadata("key" + index, ds1, "value" + index));
|
||||
insertMetadata("key" + index, "value" + index, ds1);
|
||||
}
|
||||
|
||||
for (int index = 0; index <= quotaManagement.getMaxMetaDataEntriesPerDistributionSet() - 2; index++) {
|
||||
createDistributionSetMetadata(ds2.getId(),
|
||||
new JpaDistributionSetMetadata("key" + index, ds2, "value" + index));
|
||||
insertMetadata("key" + index, "value" + index, ds2);
|
||||
}
|
||||
|
||||
final Page<DistributionSetMetadata> metadataOfDs1 = distributionSetManagement
|
||||
.findMetaDataByDistributionSetId(ds1.getId(), PageRequest.of(0, 100));
|
||||
|
||||
final Page<DistributionSetMetadata> metadataOfDs2 = distributionSetManagement
|
||||
.findMetaDataByDistributionSetId(ds2.getId(), PageRequest.of(0, 100));
|
||||
|
||||
assertThat(metadataOfDs1.getNumberOfElements())
|
||||
.isEqualTo(quotaManagement.getMaxMetaDataEntriesPerDistributionSet());
|
||||
assertThat(metadataOfDs1.getTotalElements())
|
||||
.isEqualTo(quotaManagement.getMaxMetaDataEntriesPerDistributionSet());
|
||||
|
||||
assertThat(metadataOfDs2.getNumberOfElements())
|
||||
.isEqualTo(quotaManagement.getMaxMetaDataEntriesPerDistributionSet() - 1);
|
||||
assertThat(metadataOfDs2.getTotalElements())
|
||||
.isEqualTo(quotaManagement.getMaxMetaDataEntriesPerDistributionSet() - 1);
|
||||
assertThat(distributionSetManagement.getMetadata(ds1.getId())).hasSize(quotaManagement.getMaxMetaDataEntriesPerDistributionSet());
|
||||
assertThat(distributionSetManagement.getMetadata(ds2.getId())).hasSize(quotaManagement.getMaxMetaDataEntriesPerDistributionSet() - 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -897,23 +850,20 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
final String knownUpdateValue = "knownUpdateValue";
|
||||
|
||||
final Long dsId = testdataFactory.createDistributionSet().getId();
|
||||
distributionSetManagement.putMetaData(dsId,
|
||||
singletonList(entityFactory.generateDsMetadata(knownKey1, knownValue)));
|
||||
distributionSetManagement.createMetadata(dsId, Map.of(knownKey1, knownValue));
|
||||
|
||||
distributionSetInvalidationManagement.invalidateDistributionSet(
|
||||
new DistributionSetInvalidation(singletonList(dsId), CancelationType.NONE, false));
|
||||
|
||||
// assert that no new metadata can be created
|
||||
final List<MetaData> metadata = singletonList(entityFactory.generateDsMetadata(knownKey2, knownValue));
|
||||
assertThatExceptionOfType(InvalidDistributionSetException.class)
|
||||
.as("Invalid distributionSet should throw an exception")
|
||||
.isThrownBy(() -> distributionSetManagement.putMetaData(dsId, metadata));
|
||||
.isThrownBy(() -> distributionSetManagement.createMetadata(dsId, Map.of(knownKey2, knownValue)));
|
||||
|
||||
// assert that an existing metadata can not be updated
|
||||
final MetaData metadata2 = entityFactory.generateDsMetadata(knownKey1, knownUpdateValue);
|
||||
assertThatExceptionOfType(InvalidDistributionSetException.class)
|
||||
.as("Invalid distributionSet should throw an exception")
|
||||
.isThrownBy(() -> distributionSetManagement.updateMetaData(dsId, metadata2));
|
||||
.isThrownBy(() -> distributionSetManagement.updateMetadata(dsId, knownKey1, knownUpdateValue));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1265,6 +1215,11 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
.isComplete(Boolean.FALSE).isDeleted(Boolean.FALSE));
|
||||
}
|
||||
|
||||
private void insertMetadata(final String knownKey, final String knownValue, final DistributionSet distributionSet) {
|
||||
distributionSetManagement.createMetadata(distributionSet.getId(), Map.of(knownKey, knownValue));
|
||||
assertThat(distributionSetManagement.getMetadata(distributionSet.getId()).get(knownKey)).isEqualTo(knownValue);
|
||||
}
|
||||
|
||||
private void assertThatFilterContainsOnlyGivenDistributionSets(final DistributionSetFilterBuilder filterBuilder,
|
||||
final List<DistributionSet> distributionSets) {
|
||||
final int expectedDsSize = distributionSets.size();
|
||||
|
||||
@@ -1,234 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.rsql;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
import io.qameta.allure.Story;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetFields;
|
||||
import org.eclipse.hawkbit.repository.SoftwareModuleFields;
|
||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException;
|
||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
|
||||
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||
import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.orm.jpa.vendor.Database;
|
||||
|
||||
@Feature("Component Tests - Repository")
|
||||
@Story("RSQL filter distribution set")
|
||||
@SuppressWarnings("java:S6813") // constructor injects are not possible for test classes
|
||||
class RSQLDistributionSetFieldTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
protected VirtualPropertyReplacer virtualPropertyReplacer;
|
||||
@Autowired
|
||||
protected EntityManager entityManager;
|
||||
|
||||
private DistributionSet ds;
|
||||
private SoftwareModule sm;
|
||||
|
||||
@BeforeEach
|
||||
void setupBeforeTest() {
|
||||
|
||||
sm = testdataFactory.createSoftwareModuleApp("SM");
|
||||
|
||||
ds = testdataFactory.createDistributionSet(Collections.singletonList(sm), "DS");
|
||||
ds = distributionSetManagement.update(entityFactory.distributionSet().update(ds.getId()).description("DS"));
|
||||
createDistributionSetMetadata(ds.getId(), entityFactory.generateDsMetadata("metaKey", "metaValue"));
|
||||
|
||||
DistributionSet ds2 = testdataFactory.createDistributionSets("NewDS", 3).get(0);
|
||||
|
||||
ds2 = distributionSetManagement.update(entityFactory.distributionSet().update(ds2.getId()).description("DS%"));
|
||||
createDistributionSetMetadata(ds2.getId(), entityFactory.generateDsMetadata("metaKey", "value"));
|
||||
|
||||
final DistributionSetTag distSetTag = distributionSetTagManagement
|
||||
.create(entityFactory.tag().create().name("Tag1"));
|
||||
distributionSetTagManagement.create(entityFactory.tag().create().name("Tag2"));
|
||||
distributionSetTagManagement.create(entityFactory.tag().create().name("Tag3"));
|
||||
distributionSetTagManagement.create(entityFactory.tag().create().name("Tag4"));
|
||||
|
||||
distributionSetManagement.assignTag(Arrays.asList(ds.getId(), ds2.getId()), distSetTag.getId());
|
||||
|
||||
final DistributionSet ds3 = distributionSetManagement
|
||||
.create(entityFactory.distributionSet().create().name("test123").version("noDescription"));
|
||||
distributionSetManagement.invalidate(ds3);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test filter distribution set by id")
|
||||
void testFilterByParameterId() {
|
||||
assertRSQLQuery(DistributionSetFields.ID.name() + "==" + ds.getId(), 1);
|
||||
assertRSQLQuery(DistributionSetFields.ID.name() + "!=" + ds.getId(), 4);
|
||||
assertRSQLQuery(DistributionSetFields.ID.name() + "==" + -1, 0);
|
||||
assertRSQLQuery(DistributionSetFields.ID.name() + "!=" + -1, 5);
|
||||
|
||||
// Not supported for numbers
|
||||
if (Database.POSTGRESQL.equals(getDatabase())) {
|
||||
return;
|
||||
}
|
||||
|
||||
assertRSQLQuery(DistributionSetFields.ID.name() + "=in=(" + ds.getId() + ",10000000)", 1);
|
||||
assertRSQLQuery(DistributionSetFields.ID.name() + "=out=(" + ds.getId() + ",10000000)", 4);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test filter distribution set by name")
|
||||
void testFilterByParameterName() {
|
||||
assertRSQLQuery(DistributionSetFields.NAME.name() + "==DS", 1);
|
||||
assertRSQLQuery(DistributionSetFields.NAME.name() + "!=DS", 4);
|
||||
assertRSQLQuery(DistributionSetFields.NAME.name() + "==*DS", 4);
|
||||
assertRSQLQuery(DistributionSetFields.NAME.name() + "==noExist*", 0);
|
||||
assertRSQLQuery(DistributionSetFields.NAME.name() + "=in=(DS,notexist)", 1);
|
||||
assertRSQLQuery(DistributionSetFields.NAME.name() + "=out=(DS,notexist)", 4);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test filter distribution set by assigned software module")
|
||||
void testFilterBySoftwareModule() {
|
||||
assertRSQLQuery(DistributionSetFields.MODULE.name() + "." + SoftwareModuleFields.NAME.name() + "==" + sm.getName(), 1);
|
||||
assertRSQLQuery(DistributionSetFields.MODULE.name() + "." + SoftwareModuleFields.ID.name() + "==" + sm.getId(), 1);
|
||||
assertRSQLQuery(DistributionSetFields.MODULE.name() + "." + SoftwareModuleFields.NAME.name() + "==noExist", 0);
|
||||
assertRSQLQuery(DistributionSetFields.MODULE.name() + "." + SoftwareModuleFields.ID.name() + "=in=(" + sm.getId() + ", -1)", 1);
|
||||
assertRSQLQuery(DistributionSetFields.MODULE.name() + "." + SoftwareModuleFields.ID.name() + "=out=(" + sm.getId() + ", -1)", 4);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test filter distribution set by description")
|
||||
void testFilterByParameterDescription() {
|
||||
assertRSQLQuery(DistributionSetFields.DESCRIPTION.name() + "==''", 1);
|
||||
assertRSQLQuery(DistributionSetFields.DESCRIPTION.name() + "!=''", 4);
|
||||
assertRSQLQuery(DistributionSetFields.DESCRIPTION.name() + "==DS", 1);
|
||||
assertRSQLQuery(DistributionSetFields.DESCRIPTION.name() + "!=DS*", 3);
|
||||
assertRSQLQuery(DistributionSetFields.DESCRIPTION.name() + "!=DS", 4);
|
||||
assertRSQLQuery(DistributionSetFields.DESCRIPTION.name() + "==DS*", 2);
|
||||
assertRSQLQuery(DistributionSetFields.DESCRIPTION.name() + "==DS%", 1);
|
||||
assertRSQLQuery(DistributionSetFields.DESCRIPTION.name() + "==noExist*", 0);
|
||||
assertRSQLQuery(DistributionSetFields.DESCRIPTION.name() + "=in=(DS,notexist)", 1);
|
||||
assertRSQLQuery(DistributionSetFields.DESCRIPTION.name() + "=out=(DS,notexist)", 4);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test filter distribution set by version")
|
||||
void testFilterByParameterVersion() {
|
||||
assertRSQLQuery(DistributionSetFields.VERSION.name() + "==" + TestdataFactory.DEFAULT_VERSION, 1);
|
||||
assertRSQLQuery(DistributionSetFields.VERSION.name() + "!=" + TestdataFactory.DEFAULT_VERSION, 4);
|
||||
assertRSQLQuery(DistributionSetFields.VERSION.name() + "=in=(" + TestdataFactory.DEFAULT_VERSION + ",1.0.0,1.0.1)", 3);
|
||||
assertRSQLQuery(DistributionSetFields.VERSION.name() + "=out=(" + TestdataFactory.DEFAULT_VERSION + ",error)", 4);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test filter distribution set by complete property")
|
||||
void testFilterByAttributeComplete() {
|
||||
assertRSQLQuery(DistributionSetFields.COMPLETE.name() + "==true", 3);
|
||||
final String noExistStar = DistributionSetFields.COMPLETE.name() + "==noExist*";
|
||||
assertThatExceptionOfType(RSQLParameterSyntaxException.class)
|
||||
.isThrownBy(() -> assertRSQLQuery(noExistStar, 0));
|
||||
assertRSQLQuery(DistributionSetFields.COMPLETE.name() + "=in=(true)", 3);
|
||||
assertRSQLQuery(DistributionSetFields.COMPLETE.name() + "=out=(true)", 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test filter distribution set by valid property")
|
||||
void testFilterByAttributeValid() {
|
||||
assertRSQLQuery(DistributionSetFields.VALID.name() + "==true", 4);
|
||||
assertRSQLQuery(DistributionSetFields.VALID.name() + "==false", 1);
|
||||
final String rsqlNoExistStar = DistributionSetFields.VALID.name() + "==noExist*";
|
||||
assertThatExceptionOfType(RSQLParameterSyntaxException.class)
|
||||
.isThrownBy(() -> assertRSQLQuery(rsqlNoExistStar, 0));
|
||||
assertRSQLQuery(DistributionSetFields.VALID.name() + "=in=(true)", 4);
|
||||
assertRSQLQuery(DistributionSetFields.VALID.name() + "=out=(true)", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test filter distribution set by tag name")
|
||||
void testFilterByTag() {
|
||||
assertRSQLQuery(DistributionSetFields.TAG.name() + "==Tag1", 2);
|
||||
assertRSQLQuery(DistributionSetFields.TAG.name() + "!=Tag1", 3);
|
||||
assertRSQLQuery(DistributionSetFields.TAG.name() + "==T*", 2);
|
||||
assertRSQLQuery(DistributionSetFields.TAG.name() + "==noExist*", 0);
|
||||
assertRSQLQuery(DistributionSetFields.TAG.name() + "=in=(Tag1,notexist)", 2);
|
||||
assertRSQLQuery(DistributionSetFields.TAG.name() + "=out=(null)", 5);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test filter distribution set by type key")
|
||||
void testFilterByType() {
|
||||
assertRSQLQuery(DistributionSetFields.TYPE.name() + "==" + TestdataFactory.DS_TYPE_DEFAULT, 4);
|
||||
assertRSQLQuery(DistributionSetFields.TYPE.name() + "==noExist*", 0);
|
||||
assertRSQLQuery(DistributionSetFields.TYPE.name() + "=in=(" + TestdataFactory.DS_TYPE_DEFAULT + ",ecl)", 4);
|
||||
assertRSQLQuery(DistributionSetFields.TYPE.name() + "=out=(" + TestdataFactory.DS_TYPE_DEFAULT + ")", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test filter distribution set by metadata")
|
||||
void testFilterByMetadata() {
|
||||
createDistributionSetWithMetadata("key.dot", "value.dot");
|
||||
|
||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".metaKey==metaValue", 1);
|
||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".metaKey==*v*", 2);
|
||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".metaKey==noExist*", 0);
|
||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".metaKey=in=(metaValue,notexist)", 1);
|
||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".metaKey=out=(metaValue,notexist)", 1);
|
||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".notExist==metaValue", 0);
|
||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".key.dot==value.dot", 1);
|
||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".key.dot*==value.dot", 0);
|
||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".key.*==value.dot", 0);
|
||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".key.==value.dot", 0);
|
||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".key*==value.dot", 0);
|
||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".*==value.dot", 0);
|
||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + "..==value.dot", 0);
|
||||
assertRSQLQueryThrowsException(
|
||||
DistributionSetFields.METADATA.name() + ".==value.dot",
|
||||
RSQLParameterUnsupportedFieldException.class);
|
||||
assertRSQLQueryThrowsException(
|
||||
DistributionSetFields.METADATA.name() + "*==value.dot",
|
||||
RSQLParameterUnsupportedFieldException.class);
|
||||
assertRSQLQueryThrowsException(
|
||||
DistributionSetFields.METADATA.name() + "==value.dot",
|
||||
RSQLParameterUnsupportedFieldException.class);
|
||||
|
||||
}
|
||||
|
||||
private void assertRSQLQuery(final String rsqlParam, final long expectedEntity) {
|
||||
final Page<DistributionSet> find = distributionSetManagement.findByRsql(rsqlParam, PageRequest.of(0, 100));
|
||||
final long countAll = find.getTotalElements();
|
||||
assertThat(find).as("Found entity is should not be null").isNotNull();
|
||||
assertThat(countAll).as("Found entity size is wrong").isEqualTo(expectedEntity);
|
||||
}
|
||||
|
||||
private <T extends Throwable> void assertRSQLQueryThrowsException(final String rsqlParam, final Class<T> expectedException) {
|
||||
assertThatExceptionOfType(expectedException)
|
||||
.isThrownBy(() -> RSQLUtility.validateRsqlFor(
|
||||
rsqlParam, DistributionSetFields.class, JpaDistributionSet.class, virtualPropertyReplacer, entityManager));
|
||||
}
|
||||
|
||||
private DistributionSet createDistributionSetWithMetadata(final String metadataKeyName, final String metadataValue) {
|
||||
final DistributionSet distributionSet = testdataFactory.createDistributionSet();
|
||||
createDistributionSetMetadata(distributionSet.getId(), entityFactory.generateDsMetadata(metadataKeyName, metadataValue));
|
||||
return distributionSet;
|
||||
}
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.rsql;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
import io.qameta.allure.Story;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetMetadataFields;
|
||||
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.MetaData;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
|
||||
@Feature("Component Tests - Repository")
|
||||
@Story("RSQL filter distribution set metadata")
|
||||
class RSQLDistributionSetMetadataFieldsTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
private Long distributionSetId;
|
||||
|
||||
@BeforeEach
|
||||
void setupBeforeTest() {
|
||||
final DistributionSet distributionSet = testdataFactory.createDistributionSet("DS");
|
||||
distributionSetId = distributionSet.getId();
|
||||
|
||||
final List<MetaData> metadata = new ArrayList<>(5);
|
||||
for (int i = 0; i < 5; i++) {
|
||||
metadata.add(entityFactory.generateDsMetadata("" + i, "" + i));
|
||||
}
|
||||
|
||||
distributionSetManagement.putMetaData(distributionSetId, metadata);
|
||||
|
||||
distributionSetManagement.putMetaData(distributionSetId,
|
||||
Arrays.asList(entityFactory.generateDsMetadata("emptyValueTest", null)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test filter distribution set metadata by key")
|
||||
void testFilterByParameterKey() {
|
||||
assertRSQLQuery(DistributionSetMetadataFields.KEY.name() + "==1", 1);
|
||||
assertRSQLQuery(DistributionSetMetadataFields.KEY.name() + "!=1", 5);
|
||||
assertRSQLQuery(DistributionSetMetadataFields.KEY.name() + "=in=(1,2)", 2);
|
||||
assertRSQLQuery(DistributionSetMetadataFields.KEY.name() + "=out=(1,2)", 4);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test filter distribution set metadata by value")
|
||||
void testFilterByParameterValue() {
|
||||
assertRSQLQuery(DistributionSetMetadataFields.VALUE.name() + "==''", 1);
|
||||
assertRSQLQuery(DistributionSetMetadataFields.VALUE.name() + "!=''", 5);
|
||||
assertRSQLQuery(DistributionSetMetadataFields.VALUE.name() + "==1", 1);
|
||||
assertRSQLQuery(DistributionSetMetadataFields.VALUE.name() + "!=1", 5);
|
||||
assertRSQLQuery(DistributionSetMetadataFields.VALUE.name() + "=in=(1,2)", 2);
|
||||
assertRSQLQuery(DistributionSetMetadataFields.VALUE.name() + "=out=(1,2)", 4);
|
||||
}
|
||||
|
||||
private void assertRSQLQuery(final String rsqlParam, final long expectedEntities) {
|
||||
|
||||
final Page<DistributionSetMetadata> findEnitity = distributionSetManagement
|
||||
.findMetaDataByDistributionSetIdAndRsql(distributionSetId, rsqlParam, PageRequest.of(0, 100));
|
||||
final long countAllEntities = findEnitity.getTotalElements();
|
||||
assertThat(findEnitity).isNotNull();
|
||||
assertThat(countAllEntities).isEqualTo(expectedEntities);
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import java.time.ZonedDateTime;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -56,7 +57,6 @@ import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||
import org.eclipse.hawkbit.repository.model.DeploymentRequest;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.MetaData;
|
||||
import org.eclipse.hawkbit.repository.model.RepositoryModelConstants;
|
||||
@@ -412,16 +412,7 @@ public abstract class AbstractIntegrationTest {
|
||||
}
|
||||
|
||||
protected boolean isConfirmationFlowActive() {
|
||||
return tenantConfigurationManagement.getConfigurationValue(TenantConfigurationKey.USER_CONFIRMATION_ENABLED,
|
||||
Boolean.class).getValue();
|
||||
}
|
||||
|
||||
protected DistributionSetMetadata createDistributionSetMetadata(final long dsId, final MetaData md) {
|
||||
return createDistributionSetMetadata(dsId, Collections.singletonList(md)).get(0);
|
||||
}
|
||||
|
||||
protected List<DistributionSetMetadata> createDistributionSetMetadata(final long dsId, final List<MetaData> md) {
|
||||
return distributionSetManagement.putMetaData(dsId, md);
|
||||
return tenantConfigurationManagement.getConfigurationValue(TenantConfigurationKey.USER_CONFIRMATION_ENABLED, Boolean.class).getValue();
|
||||
}
|
||||
|
||||
protected Long getOsModule(final DistributionSet ds) {
|
||||
|
||||
Reference in New Issue
Block a user