Cleanup TargetManagement (#2601)
Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -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;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import lombok.Data;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
|
||||
/**
|
||||
* Encapsulates a set of filters that may be specified (optionally). Properties
|
||||
* that are not specified (e.g. <code>null</code> for simple properties) When
|
||||
* applied, these filters are AND-gated.
|
||||
*/
|
||||
@Data
|
||||
public class FilterParams {
|
||||
|
||||
private final Collection<TargetUpdateStatus> filterByStatus;
|
||||
private final Boolean overdueState;
|
||||
private final String filterBySearchText;
|
||||
private final Boolean selectTargetWithNoTag;
|
||||
private final String[] filterByTagNames;
|
||||
private final Long filterByDistributionId;
|
||||
private final Boolean selectTargetWithNoTargetType;
|
||||
private final Long filterByTargetType;
|
||||
|
||||
/**
|
||||
* Constructor for the filter parameters of a Simple Filter.
|
||||
*
|
||||
* @param filterByInstalledOrAssignedDistributionSetId if set, a filter is added for the given
|
||||
* {@link DistributionSet#getId()}
|
||||
* @param filterByStatus if set, a filter is added for target states included by the
|
||||
* collection
|
||||
* @param overdueState if set, a filter is added for overdued devices
|
||||
* @param filterBySearchText if set, a filter is added for the given search text
|
||||
* @param selectTargetWithNoTag if set, tag-filtering is enabled
|
||||
* @param filterByTagNames if tag-filtering is enabled, a filter is added for the given
|
||||
* tag-names
|
||||
*/
|
||||
public FilterParams(final Collection<TargetUpdateStatus> filterByStatus, final Boolean overdueState,
|
||||
final String filterBySearchText, final Long filterByInstalledOrAssignedDistributionSetId,
|
||||
final Boolean selectTargetWithNoTag, final String... filterByTagNames) {
|
||||
this.filterByStatus = filterByStatus;
|
||||
this.overdueState = overdueState;
|
||||
this.filterBySearchText = filterBySearchText;
|
||||
this.filterByDistributionId = filterByInstalledOrAssignedDistributionSetId;
|
||||
this.selectTargetWithNoTag = selectTargetWithNoTag;
|
||||
this.filterByTagNames = filterByTagNames;
|
||||
this.selectTargetWithNoTargetType = false;
|
||||
this.filterByTargetType = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for the filter parameters of a Type Filter.
|
||||
*
|
||||
* @param filterBySearchText if set, a filter is added for the given search text
|
||||
* @param filterByInstalledOrAssignedDistributionSetId if set, a filter is added for the given
|
||||
* {@link DistributionSet#getId()}
|
||||
* @param selectTargetWithNoType if true, a filter is added with no type
|
||||
* @param filterByType if set, a filter is added for the given target type
|
||||
*/
|
||||
public FilterParams(final String filterBySearchText, final Long filterByInstalledOrAssignedDistributionSetId,
|
||||
final Boolean selectTargetWithNoType, final Long filterByType) {
|
||||
this.filterBySearchText = filterBySearchText;
|
||||
this.filterByDistributionId = filterByInstalledOrAssignedDistributionSetId;
|
||||
this.filterByStatus = null;
|
||||
this.overdueState = null;
|
||||
this.selectTargetWithNoTag = false;
|
||||
this.filterByTagNames = null;
|
||||
this.selectTargetWithNoTargetType = selectTargetWithNoType;
|
||||
this.filterByTargetType = filterByType;
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,6 @@ import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
|
||||
import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||
import org.eclipse.hawkbit.repository.model.TargetType;
|
||||
import org.eclipse.hawkbit.repository.model.TargetTypeAssignmentResult;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
@@ -81,104 +80,60 @@ public interface TargetManagement<T extends Target>
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts number of targets with the given distribution set assigned.
|
||||
* Get controller attributes of given {@link Target}.
|
||||
*
|
||||
* @param distributionSetId to search for
|
||||
* @return number of found {@link Target}s.
|
||||
* @throws EntityNotFoundException if distribution set with given ID does not exist
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_READ_DISTRIBUTION_SET_AND_READ_TARGET)
|
||||
long countByAssignedDistributionSet(long distributionSetId);
|
||||
|
||||
/**
|
||||
* Count {@link Target}s for all the given filter parameters.
|
||||
*
|
||||
* @param filterParams the filters to apply; only filters are enabled that have non-null
|
||||
* value; filters are AND-gated
|
||||
* @return the found number {@link Target}s
|
||||
* @throws EntityNotFoundException if distribution set with given ID does not exist
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_READ_TARGET)
|
||||
long countByFilters(@NotNull final FilterParams filterParams);
|
||||
|
||||
/**
|
||||
* Get the count of targets with the given distribution set id.
|
||||
*
|
||||
* @param distributionSetId to search for
|
||||
* @return number of found {@link Target}s.
|
||||
* @throws EntityNotFoundException if distribution set with given ID does not exist
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_READ_DISTRIBUTION_SET_AND_READ_TARGET)
|
||||
long countByInstalledDistributionSet(long distributionSetId);
|
||||
|
||||
/**
|
||||
* Checks if there is already a {@link Target} that has the given distribution
|
||||
* set Id assigned or installed.
|
||||
*
|
||||
* @param distributionSetId to search for
|
||||
* @return <code>true</code> if a {@link Target} exists.
|
||||
* @throws EntityNotFoundException if distribution set with given ID does not exist
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_READ_DISTRIBUTION_SET_AND_READ_TARGET)
|
||||
boolean existsByInstalledOrAssignedDistributionSet(long distributionSetId);
|
||||
|
||||
/**
|
||||
* Count {@link TargetFilterQuery}s for given target filter query with UPDATE permission.
|
||||
*
|
||||
* @param rsql filter definition in RSQL syntax
|
||||
* @return the found number of {@link Target}s
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_READ_TARGET)
|
||||
long countByRsqlAndUpdatable(@NotEmpty String rsql);
|
||||
|
||||
/**
|
||||
* Count all targets for given {@link TargetFilterQuery} and that are compatible
|
||||
* with the passed {@link DistributionSetType}.
|
||||
*
|
||||
* @param rsql filter definition in RSQL syntax
|
||||
* @param distributionSetIdTypeId ID of the {@link DistributionSetType} the targets need to be
|
||||
* compatible with
|
||||
* @return the found number of{@link Target}s
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_READ_TARGET)
|
||||
long countByRsqlAndCompatible(@NotEmpty String rsql, @NotNull Long distributionSetIdTypeId);
|
||||
|
||||
/**
|
||||
* Count all targets with failed actions for specific Rollout and that are
|
||||
* compatible with the passed {@link DistributionSetType} and created after
|
||||
* given timestamp
|
||||
*
|
||||
* @param rolloutId rolloutId of the rollout to be retried.
|
||||
* @param dsTypeId ID of the {@link DistributionSetType} the targets need to be
|
||||
* compatible with
|
||||
* @return the found number of{@link Target}s
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_READ_TARGET)
|
||||
long countByFailedInRollout(@NotEmpty String rolloutId, @NotNull Long dsTypeId);
|
||||
|
||||
/**
|
||||
* Count {@link TargetFilterQuery}s for given target filter query.
|
||||
*
|
||||
* @param targetFilterQueryId {@link TargetFilterQuery#getId()}
|
||||
* @return the found number of {@link Target}s
|
||||
* @throws EntityNotFoundException if {@link TargetFilterQuery} with given ID does not exist
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_READ_TARGET)
|
||||
long countByTargetFilterQuery(long targetFilterQueryId);
|
||||
|
||||
/**
|
||||
* Deletes target with the given controller ID.
|
||||
*
|
||||
* @param controllerId the controller ID of the target to be deleted
|
||||
* @param controllerId of the target
|
||||
* @return controller attributes as key/value pairs
|
||||
* @throws EntityNotFoundException if target with given ID does not exist
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_DELETE_TARGET)
|
||||
void deleteByControllerID(@NotEmpty String controllerId);
|
||||
@PreAuthorize(HAS_AUTH_READ_TARGET)
|
||||
Map<String, String> getControllerAttributes(@NotEmpty String controllerId);
|
||||
|
||||
/**
|
||||
* Finds all targets for all the given parameter {@link TargetFilterQuery} and
|
||||
* that don't have the specified distribution set in their action history and
|
||||
* are compatible with the passed {@link DistributionSetType}.
|
||||
* Verify if a target matches a specific target filter query, does not have a
|
||||
* specific DS already assigned and is compatible with it.
|
||||
*
|
||||
* @param controllerId of the {@link org.eclipse.hawkbit.repository.model.Target} to check
|
||||
* @param distributionSetId of the {@link org.eclipse.hawkbit.repository.model.DistributionSet} to consider
|
||||
* @param targetFilterQuery to execute
|
||||
* @return true if it matches
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_READ_DISTRIBUTION_SET_AND_READ_TARGET)
|
||||
boolean isTargetMatchingQueryAndDSNotAssignedAndCompatibleAndUpdatable(
|
||||
@NotNull String controllerId, long distributionSetId, @NotNull String targetFilterQuery);
|
||||
|
||||
/**
|
||||
* Find {@link Target}s based a given IDs.
|
||||
*
|
||||
* @param controllerIDs to look for.
|
||||
* @return List of found{@link Target}s
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_READ_TARGET)
|
||||
List<Target> getByControllerId(@NotEmpty Collection<String> controllerIDs);
|
||||
|
||||
/**
|
||||
* Gets a {@link Target} based a given controller id and includes the details specified by the details key.
|
||||
*
|
||||
* @param controllerId to look for.
|
||||
* @param detailsKey the key of the details to include, e.g. {@link #DETAILS_AUTO_CONFIRMATION_STATUS}
|
||||
* @return {@link Target}
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_READ_TARGET)
|
||||
Target getWithDetails(@NotEmpty String controllerId, String detailsKey);
|
||||
|
||||
@PreAuthorize(HAS_AUTH_READ_TARGET)
|
||||
default Target getWithDetails(@NotEmpty String controllerId) {
|
||||
return getWithDetails(controllerId, DETAILS_BASE);
|
||||
}
|
||||
|
||||
@PreAuthorize(HAS_AUTH_READ_TARGET)
|
||||
default Target getWithAutoConfigurationStatus(@NotEmpty String controllerId) {
|
||||
return getWithDetails(controllerId, DETAILS_AUTO_CONFIRMATION_STATUS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all targets for all the given parameter {@link TargetFilterQuery} and that don't have the specified distribution
|
||||
* set in their action history and are compatible with the passed {@link DistributionSetType}.
|
||||
*
|
||||
* @param distributionSetId id of the {@link DistributionSet}
|
||||
* @param rsql filter definition in RSQL syntax
|
||||
@@ -191,27 +146,12 @@ public interface TargetManagement<T extends Target>
|
||||
long distributionSetId, @NotNull String rsql, @NotNull Pageable pageable);
|
||||
|
||||
/**
|
||||
* Counts all targets for all the given parameter {@link TargetFilterQuery} and
|
||||
* that don't have the specified distribution set in their action history and
|
||||
* are compatible with the passed {@link DistributionSetType}.
|
||||
*
|
||||
* @param distributionSetId id of the {@link DistributionSet}
|
||||
* @param rsql filter definition in RSQL syntax
|
||||
* @return the count of found {@link Target}s
|
||||
* @throws EntityNotFoundException if distribution set with given ID does not exist
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_READ_DISTRIBUTION_SET_AND_READ_TARGET)
|
||||
long countByRsqlAndNonDSAndCompatibleAndUpdatable(long distributionSetId, @NotNull String rsql);
|
||||
|
||||
/**
|
||||
* Finds all targets for all the given parameter {@link TargetFilterQuery} and
|
||||
* that are not assigned to one of the {@link RolloutGroup}s and are compatible
|
||||
* with the passed {@link DistributionSetType}.
|
||||
* Finds all targets for all the given parameter {@link TargetFilterQuery} and that are not assigned to one of the {@link RolloutGroup}s
|
||||
* and are compatible with the passed {@link DistributionSetType}.
|
||||
*
|
||||
* @param groups the list of {@link RolloutGroup}s
|
||||
* @param rsql filter definition in RSQL syntax
|
||||
* @param distributionSetType type of the {@link DistributionSet} the targets must be compatible
|
||||
* withs
|
||||
* @param distributionSetType type of the {@link DistributionSet} the targets must be compatible withs
|
||||
* @param pageable the pageable to enhance the query for paging and sorting
|
||||
* @return a page of the found {@link Target}s
|
||||
*/
|
||||
@@ -221,23 +161,8 @@ public interface TargetManagement<T extends Target>
|
||||
@NotNull Pageable pageable);
|
||||
|
||||
/**
|
||||
* Counts all targets for all the given parameter {@link TargetFilterQuery} and
|
||||
* that are not assigned to one of the {@link RolloutGroup}s and are compatible
|
||||
* with the passed {@link DistributionSetType}.
|
||||
*
|
||||
* @param rsql filter definition in RSQL syntax
|
||||
* @param groups the list of {@link RolloutGroup}s
|
||||
* @param distributionSetType type of the {@link DistributionSet} the targets must be compatible with
|
||||
* @return count of the found {@link Target}s
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_ROLLOUT_MANAGEMENT_READ_AND_TARGET_READ)
|
||||
long countByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable(
|
||||
@NotNull String rsql, @NotEmpty Collection<Long> groups, @NotNull DistributionSetType distributionSetType);
|
||||
|
||||
/**
|
||||
* Finds all targets with failed actions for specific Rollout and that are not
|
||||
* assigned to one of the retried {@link RolloutGroup}s and are compatible with
|
||||
* the passed {@link DistributionSetType}.
|
||||
* Finds all targets with failed actions for specific Rollout and that are not assigned to one of the retried {@link RolloutGroup}s and
|
||||
* are compatible with the passed {@link DistributionSetType}.
|
||||
*
|
||||
* @param rolloutId rolloutId of the rollout to be retried.
|
||||
* @param groups the list of {@link RolloutGroup}s
|
||||
@@ -248,28 +173,12 @@ public interface TargetManagement<T extends Target>
|
||||
Slice<Target> findByFailedRolloutAndNotInRolloutGroups(
|
||||
@NotNull String rolloutId, @NotEmpty Collection<Long> groups, @NotNull Pageable pageable);
|
||||
|
||||
/**
|
||||
* Counts all targets with failed actions for specific Rollout and that are not
|
||||
* assigned to one of the {@link RolloutGroup}s and are compatible with the
|
||||
* passed {@link DistributionSetType}.
|
||||
*
|
||||
* @param rolloutId rolloutId of the rollout to be retried.
|
||||
* @param groups the list of {@link RolloutGroup}s
|
||||
* @return count of the found {@link Target}s
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_ROLLOUT_MANAGEMENT_READ_AND_TARGET_READ)
|
||||
long countByFailedRolloutAndNotInRolloutGroups(@NotNull String rolloutId, @NotEmpty Collection<Long> groups);
|
||||
|
||||
@PreAuthorize(HAS_AUTH_ROLLOUT_MANAGEMENT_READ_AND_TARGET_READ)
|
||||
Slice<Target> findByRsqlAndNoOverridingActionsAndNotInRolloutAndCompatibleAndUpdatable(
|
||||
final long rolloutId, @NotNull String rsql, @NotNull DistributionSetType distributionSetType, @NotNull Pageable pageable);
|
||||
|
||||
@PreAuthorize(HAS_AUTH_ROLLOUT_MANAGEMENT_READ_AND_TARGET_READ)
|
||||
long countByActionsInRolloutGroup(final long rolloutGroupId);
|
||||
|
||||
/**
|
||||
* Finds all targets of the provided {@link RolloutGroup} that have no Action
|
||||
* for the RolloutGroup.
|
||||
* Finds all targets of the provided {@link RolloutGroup} that have no Action for the RolloutGroup.
|
||||
*
|
||||
* @param group the {@link RolloutGroup}
|
||||
* @param pageable the pageable to enhance the query for paging and sorting
|
||||
@@ -297,8 +206,8 @@ public interface TargetManagement<T extends Target>
|
||||
* @param rsql the specification to filter the result set
|
||||
* @param pageable page parameter
|
||||
* @return the found {@link Target}s, never {@code null}
|
||||
* @throws RSQLParameterUnsupportedFieldException if a field in the RSQL string is used but not provided by the
|
||||
* given {@code fieldNameProvider}
|
||||
* @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 if distribution set with given ID does not exist
|
||||
*/
|
||||
@@ -306,13 +215,66 @@ public interface TargetManagement<T extends Target>
|
||||
Page<Target> findByAssignedDistributionSetAndRsql(long distributionSetId, @NotNull String rsql, @NotNull Pageable pageable);
|
||||
|
||||
/**
|
||||
* Find {@link Target}s based a given IDs.
|
||||
* Count all targets for given {@link TargetFilterQuery} and that are compatible
|
||||
* with the passed {@link DistributionSetType}.
|
||||
*
|
||||
* @param controllerIDs to look for.
|
||||
* @return List of found{@link Target}s
|
||||
* @param rsql filter definition in RSQL syntax
|
||||
* @param distributionSetIdTypeId ID of the {@link DistributionSetType} the targets need to be
|
||||
* compatible with
|
||||
* @return the found number of{@link Target}s
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_READ_TARGET)
|
||||
List<Target> getByControllerId(@NotEmpty Collection<String> controllerIDs);
|
||||
long countByRsqlAndCompatible(@NotEmpty String rsql, @NotNull Long distributionSetIdTypeId);
|
||||
|
||||
/**
|
||||
* Count all targets with failed actions for specific Rollout and that are compatible with the passed {@link DistributionSetType} and
|
||||
* created after given timestamp
|
||||
*
|
||||
* @param rolloutId rolloutId of the rollout to be retried.
|
||||
* @param dsTypeId ID of the {@link DistributionSetType} the targets need to be compatible with
|
||||
* @return the found number of{@link Target}s
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_READ_TARGET)
|
||||
long countByFailedInRollout(@NotEmpty String rolloutId, @NotNull Long dsTypeId);
|
||||
|
||||
/**
|
||||
* Counts all targets for all the given parameter {@link TargetFilterQuery} and that don't have the specified distribution set in their
|
||||
* action history and are compatible with the passed {@link DistributionSetType}.
|
||||
*
|
||||
* @param distributionSetId id of the {@link DistributionSet}
|
||||
* @param rsql filter definition in RSQL syntax
|
||||
* @return the count of found {@link Target}s
|
||||
* @throws EntityNotFoundException if distribution set with given ID does not exist
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_READ_DISTRIBUTION_SET_AND_READ_TARGET)
|
||||
long countByRsqlAndNonDsAndCompatibleAndUpdatable(long distributionSetId, @NotNull String rsql);
|
||||
|
||||
/**
|
||||
* Counts all targets for all the given parameter {@link TargetFilterQuery} and that are not assigned to one of the {@link RolloutGroup}s
|
||||
* and are compatible with the passed {@link DistributionSetType}.
|
||||
*
|
||||
* @param rsql filter definition in RSQL syntax
|
||||
* @param groups the list of {@link RolloutGroup}s
|
||||
* @param distributionSetType type of the {@link DistributionSet} the targets must be compatible with
|
||||
* @return count of the found {@link Target}s
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_ROLLOUT_MANAGEMENT_READ_AND_TARGET_READ)
|
||||
long countByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable(
|
||||
@NotNull String rsql, @NotEmpty Collection<Long> groups, @NotNull DistributionSetType distributionSetType);
|
||||
|
||||
/**
|
||||
* Counts all targets with failed actions for specific Rollout and that are not assigned to one of the {@link RolloutGroup}s and are
|
||||
* compatible with the passed {@link DistributionSetType}.
|
||||
*
|
||||
* @param rolloutId rolloutId of the rollout to be retried.
|
||||
* @param groups the list of {@link RolloutGroup}s
|
||||
* @return count of the found {@link Target}s
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_ROLLOUT_MANAGEMENT_READ_AND_TARGET_READ)
|
||||
long countByFailedRolloutAndNotInRolloutGroups(@NotNull String rolloutId, @NotEmpty Collection<Long> groups);
|
||||
|
||||
@PreAuthorize(HAS_AUTH_ROLLOUT_MANAGEMENT_READ_AND_TARGET_READ)
|
||||
long countByActionsInRolloutGroup(final long rolloutGroupId);
|
||||
|
||||
/**
|
||||
* Find a {@link Target} based a given ID.
|
||||
@@ -323,44 +285,6 @@ public interface TargetManagement<T extends Target>
|
||||
@PreAuthorize(HAS_AUTH_READ_TARGET)
|
||||
Optional<Target> getByControllerId(@NotEmpty String controllerId);
|
||||
|
||||
/**
|
||||
* Gets a {@link Target} based a given controller id and includes the details specified by the details key.
|
||||
*
|
||||
* @param controllerId to look for.
|
||||
* @param detailsKey the key of the details to include, e.g. {@link #DETAILS_AUTO_CONFIRMATION_STATUS}
|
||||
* @return {@link Target}
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_READ_TARGET)
|
||||
Target getWithDetails(@NotEmpty String controllerId, String detailsKey);
|
||||
|
||||
@PreAuthorize(HAS_AUTH_READ_TARGET)
|
||||
default Target getWithDetails(@NotEmpty String controllerId) {
|
||||
return getWithDetails(controllerId, DETAILS_BASE);
|
||||
}
|
||||
|
||||
@PreAuthorize(HAS_AUTH_READ_TARGET)
|
||||
default Target getWithAutoConfigurationStatus(@NotEmpty String controllerId) {
|
||||
return getWithDetails(controllerId, DETAILS_AUTO_CONFIRMATION_STATUS);
|
||||
}
|
||||
|
||||
@PreAuthorize(HAS_AUTH_READ_TARGET)
|
||||
default Target getWithTags(@NotEmpty String controllerId) {
|
||||
return getWithDetails(controllerId, DETAILS_TAGS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter {@link Target}s for all the given parameters. If all parameters except
|
||||
* pageable are null, all available {@link Target}s are returned.
|
||||
*
|
||||
* @param filterParams the filters to apply; only filters are enabled that have non-null
|
||||
* value; filters are AND-gated
|
||||
* @param pageable page parameters
|
||||
* @return the found {@link Target}s
|
||||
* @throws EntityNotFoundException if distribution set with given ID does not exist
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_READ_TARGET)
|
||||
Slice<Target> findByFilters(@NotNull FilterParams filterParams, @NotNull Pageable pageable);
|
||||
|
||||
/**
|
||||
* retrieves {@link Target}s by the installed {@link DistributionSet}.
|
||||
*
|
||||
@@ -388,30 +312,6 @@ public interface TargetManagement<T extends Target>
|
||||
@PreAuthorize(HAS_AUTH_READ_DISTRIBUTION_SET_AND_READ_TARGET)
|
||||
Page<Target> findByInstalledDistributionSetAndRsql(long distributionSetId, @NotNull String rsql, @NotNull Pageable pageReq);
|
||||
|
||||
/**
|
||||
* Retrieves the {@link Target} which have a certain {@link TargetUpdateStatus}.
|
||||
*
|
||||
* @param status the {@link TargetUpdateStatus} to be filtered on
|
||||
* @param pageable page parameter
|
||||
* @return the found {@link Target}s
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_READ_TARGET)
|
||||
Page<Target> findByUpdateStatus(@NotNull TargetUpdateStatus status, @NotNull Pageable pageable);
|
||||
|
||||
/**
|
||||
* Retrieves all target based on {@link TargetFilterQuery}.
|
||||
*
|
||||
* @param targetFilterQueryId {@link TargetFilterQuery#getId()}
|
||||
* @param pageable pagination parameter
|
||||
* @return the found {@link Target}s, never {@code null}
|
||||
* @throws EntityNotFoundException if {@link TargetFilterQuery} with given ID does not exist.
|
||||
* @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
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_READ_TARGET)
|
||||
Slice<Target> findByTargetFilterQuery(long targetFilterQueryId, @NotNull Pageable pageable);
|
||||
|
||||
/**
|
||||
* Find targets by tag name.
|
||||
*
|
||||
@@ -438,39 +338,35 @@ public interface TargetManagement<T extends Target>
|
||||
@PreAuthorize(HAS_AUTH_READ_TARGET)
|
||||
Page<Target> findByRsqlAndTag(@NotNull String rsql, long tagId, @NotNull Pageable pageable);
|
||||
|
||||
/**
|
||||
* Verify if a target matches a specific target filter query, does not have a
|
||||
* specific DS already assigned and is compatible with it.
|
||||
*
|
||||
* @param controllerId of the {@link org.eclipse.hawkbit.repository.model.Target} to check
|
||||
* @param distributionSetId of the {@link org.eclipse.hawkbit.repository.model.DistributionSet} to consider
|
||||
* @param targetFilterQuery to execute
|
||||
* @return true if it matches
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_READ_DISTRIBUTION_SET_AND_READ_TARGET)
|
||||
boolean isTargetMatchingQueryAndDSNotAssignedAndCompatibleAndUpdatable(
|
||||
@NotNull String controllerId, long distributionSetId, @NotNull String targetFilterQuery);
|
||||
|
||||
/**
|
||||
* Initiates {@link TargetType} assignment to given {@link Target}s. If some targets in the list have the {@link TargetType}
|
||||
* not yet assigned, they will get assigned. If all targets are already of that type, there will be no un-assignment.
|
||||
* Deletes target with the given controller ID.
|
||||
*
|
||||
* @param controllerIds to set the type to
|
||||
* @param typeId to assign targets to
|
||||
* @return {@link TargetTypeAssignmentResult} with all meta-data of the assignment outcome.
|
||||
* @throws EntityNotFoundException if target type with given id does not exist
|
||||
* @param controllerId the controller ID of the target to be deleted
|
||||
* @throws EntityNotFoundException if target with given ID does not exist
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_UPDATE_TARGET)
|
||||
TargetTypeAssignmentResult assignType(@NotEmpty Collection<String> controllerIds, @NotNull Long typeId);
|
||||
@PreAuthorize(HAS_AUTH_DELETE_TARGET)
|
||||
void deleteByControllerId(@NotEmpty String controllerId);
|
||||
|
||||
/**
|
||||
* Initiates {@link TargetType} un-assignment to given {@link Target}s. The type of the targets will be set to {@code null}
|
||||
* Assign a {@link TargetType} assignment to given {@link Target}.
|
||||
*
|
||||
* @param controllerIds to remove the type from
|
||||
* @return {@link TargetTypeAssignmentResult} with all meta-data of the assignment outcome.
|
||||
* @param controllerId to un-assign for
|
||||
* @param targetTypeId Target type id
|
||||
* @return the unassigned target
|
||||
* @throws EntityNotFoundException if TargetType with given target ID does not exist
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_UPDATE_TARGET)
|
||||
TargetTypeAssignmentResult unassignType(@NotEmpty Collection<String> controllerIds);
|
||||
Target assignType(@NotEmpty String controllerId, @NotNull Long targetTypeId);
|
||||
|
||||
/**
|
||||
* Un-assign a {@link TargetType} assignment to given {@link Target}.
|
||||
*
|
||||
* @param controllerId to un-assign for
|
||||
* @return the unassigned target
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_UPDATE_TARGET)
|
||||
Target unassignType(@NotEmpty String controllerId);
|
||||
|
||||
/**
|
||||
* Assign a {@link TargetTag} assignment to given {@link Target}s.
|
||||
@@ -495,6 +391,16 @@ public interface TargetManagement<T extends Target>
|
||||
@PreAuthorize(HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET)
|
||||
List<Target> assignTag(@NotEmpty Collection<String> controllerIds, long targetTagId);
|
||||
|
||||
/**
|
||||
* Finds a single target tags its id.
|
||||
*
|
||||
* @param controllerId of the {@link Target}
|
||||
* @return the found Tag set
|
||||
* @throws EntityNotFoundException if target with given ID does not exist
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_READ_TARGET)
|
||||
Set<TargetTag> getTags(@NotEmpty String controllerId);
|
||||
|
||||
/**
|
||||
* Un-assign a {@link TargetTag} assignment to given {@link Target}s.
|
||||
*
|
||||
@@ -519,24 +425,22 @@ public interface TargetManagement<T extends Target>
|
||||
List<Target> unassignTag(@NotEmpty Collection<String> controllerIds, long targetTagId);
|
||||
|
||||
/**
|
||||
* Un-assign a {@link TargetType} assignment to given {@link Target}.
|
||||
* Assigns the target group of the targets matching the provided rsql filter.
|
||||
*
|
||||
* @param controllerId to un-assign for
|
||||
* @return the unassigned target
|
||||
* @param group target group parameter
|
||||
* @param rsql rsql filter for {@link Target}
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_UPDATE_TARGET)
|
||||
Target unassignType(@NotEmpty String controllerId);
|
||||
void assignTargetGroupWithRsql(String group, @NotNull String rsql);
|
||||
|
||||
/**
|
||||
* Assign a {@link TargetType} assignment to given {@link Target}.
|
||||
* Assigns the provided group to the targets which are in the provided list of controllerIds.
|
||||
*
|
||||
* @param controllerId to un-assign for
|
||||
* @param targetTypeId Target type id
|
||||
* @return the unassigned target
|
||||
* @throws EntityNotFoundException if TargetType with given target ID does not exist
|
||||
* @param group target group parameter
|
||||
* @param controllerIds list of targets
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_UPDATE_TARGET)
|
||||
Target assignType(@NotEmpty String controllerId, @NotNull Long targetTypeId);
|
||||
void assignTargetsWithGroup(String group, @NotEmpty List<String> controllerIds);
|
||||
|
||||
/**
|
||||
* Finds targets by group or subgroup.
|
||||
@@ -557,82 +461,6 @@ public interface TargetManagement<T extends Target>
|
||||
@PreAuthorize(HAS_AUTH_READ_TARGET)
|
||||
List<String> findGroups();
|
||||
|
||||
/**
|
||||
* Assigns the target group of the targets matching the provided rsql filter.
|
||||
*
|
||||
* @param group target group parameter
|
||||
* @param rsql rsql filter for {@link Target}
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_UPDATE_TARGET)
|
||||
void assignTargetGroupWithRsql(String group, @NotNull String rsql);
|
||||
|
||||
/**
|
||||
* Assigns the provided group to the targets which are in the provided list of controllerIds.
|
||||
*
|
||||
* @param group target group parameter
|
||||
* @param controllerIds list of targets
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_UPDATE_TARGET)
|
||||
void assignTargetsWithGroup(String group, @NotEmpty List<String> controllerIds);
|
||||
|
||||
/**
|
||||
* Verifies that {@link Target} with given controller ID exists in the repository.
|
||||
*
|
||||
* @param controllerId of target
|
||||
* @return {@code true} if target with given ID exists
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_READ_TARGET)
|
||||
boolean existsByControllerId(@NotEmpty String controllerId);
|
||||
|
||||
/**
|
||||
* Finds a single target tags its id.
|
||||
*
|
||||
* @param controllerId of the {@link Target}
|
||||
* @return the found Tag set
|
||||
* @throws EntityNotFoundException if target with given ID does not exist
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_READ_TARGET)
|
||||
Set<TargetTag> getTags(@NotEmpty String controllerId);
|
||||
|
||||
/**
|
||||
* Get controller attributes of given {@link Target}.
|
||||
*
|
||||
* @param controllerId of the target
|
||||
* @return controller attributes as key/value pairs
|
||||
* @throws EntityNotFoundException if target with given ID does not exist
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_READ_TARGET)
|
||||
Map<String, String> getControllerAttributes(@NotEmpty String controllerId);
|
||||
|
||||
/**
|
||||
* Trigger given {@link Target} to update its attributes.
|
||||
*
|
||||
* @param controllerId of the target
|
||||
* @throws EntityNotFoundException if target with given ID does not exist
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_UPDATE_TARGET)
|
||||
void requestControllerAttributes(@NotEmpty String controllerId);
|
||||
|
||||
/**
|
||||
* Check if update of given {@link Target} attributes is already requested.
|
||||
*
|
||||
* @param controllerId of target
|
||||
* @return {@code true}: update of controller attributes triggered.
|
||||
* {@code false}: update of controller attributes not requested.
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_READ_TARGET)
|
||||
boolean isControllerAttributesRequested(@NotEmpty String controllerId);
|
||||
|
||||
/**
|
||||
* Retrieves {@link Target}s where
|
||||
* {@link #isControllerAttributesRequested(String)}.
|
||||
*
|
||||
* @param pageable page parameter
|
||||
* @return the found {@link Target}s
|
||||
*/
|
||||
@PreAuthorize(HAS_AUTH_READ_TARGET)
|
||||
Page<Target> findByControllerAttributesRequested(@NotNull Pageable pageable);
|
||||
|
||||
/**
|
||||
* Creates or updates a meta-data value.
|
||||
*
|
||||
@@ -718,8 +546,8 @@ public interface TargetManagement<T extends Target>
|
||||
// truncate controller ID to max name length (if too big)
|
||||
name = ObjectUtils.isEmpty(builder.name)
|
||||
? controllerId != null && controllerId.length() > NamedEntity.NAME_MAX_SIZE
|
||||
? controllerId.substring(0, NamedEntity.NAME_MAX_SIZE)
|
||||
: controllerId
|
||||
? controllerId.substring(0, NamedEntity.NAME_MAX_SIZE)
|
||||
: controllerId
|
||||
: builder.name;
|
||||
securityToken = ObjectUtils.isEmpty(builder.securityToken)
|
||||
? SecurityTokenGeneratorHolder.getInstance().generateToken()
|
||||
|
||||
@@ -55,9 +55,7 @@ public interface Action extends TenantAwareBaseEntity {
|
||||
DistributionSet getDistributionSet();
|
||||
|
||||
/**
|
||||
* @return <code>true</code> when action is in state
|
||||
* {@link Status#CANCELING} or {@link Status#CANCELED}, false
|
||||
* otherwise
|
||||
* @return <code>true</code> when action is in state {@link Status#CANCELING} or {@link Status#CANCELED}, false otherwise
|
||||
*/
|
||||
default boolean isCancelingOrCanceled() {
|
||||
return Status.CANCELING == getStatus() || Status.CANCELED == getStatus();
|
||||
@@ -340,4 +338,4 @@ public interface Action extends TenantAwareBaseEntity {
|
||||
DOWNLOAD_ONLY
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -15,10 +15,8 @@ import java.util.concurrent.TimeUnit;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
|
||||
/**
|
||||
* Status information of an {@link Action} which can be provided by the
|
||||
* {@link Target} or is added by the update server itself. This can be the start
|
||||
* of the {@link Action} life cycle, the end and update notifications in
|
||||
* between.
|
||||
* Status information of an {@link Action} which can be provided by the {@link Target} or is added by the update server itself.
|
||||
* This can be the start of the {@link Action} life cycle, the end and update notifications in between.
|
||||
*/
|
||||
public interface ActionStatus extends TenantAwareBaseEntity {
|
||||
|
||||
@@ -34,9 +32,8 @@ public interface ActionStatus extends TenantAwareBaseEntity {
|
||||
Action getAction();
|
||||
|
||||
/**
|
||||
* @return the {@link Status} of this {@link ActionStatus}. Caused
|
||||
* potentially a transition change of the {@link #getAction()} if
|
||||
* different from the previous {@link ActionStatus#getStatus()}.
|
||||
* @return the {@link Status} of this {@link ActionStatus}. Caused potentially a transition change of the {@link #getAction()} if
|
||||
* different from the previous {@link #getStatus()} call.
|
||||
*/
|
||||
Status getStatus();
|
||||
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2021 Bosch.IO 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;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* Result object for {@link TargetType} assignments.
|
||||
*/
|
||||
@Getter
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class TargetTypeAssignmentResult extends AbstractAssignmentResult<Target> {
|
||||
|
||||
private final TargetType targetType;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param alreadyAssigned count of already assigned (ignored) elements
|
||||
* @param assigned {@link List} of assigned {@link Target}s.
|
||||
* @param unassigned {@link List} of unassigned {@link Target}s.
|
||||
* @param targetType the assigned or unassigned tag
|
||||
*/
|
||||
public TargetTypeAssignmentResult(final int alreadyAssigned, final List<? extends Target> assigned,
|
||||
final List<? extends Target> unassigned, final TargetType targetType) {
|
||||
super(alreadyAssigned, assigned, unassigned);
|
||||
this.targetType = targetType;
|
||||
}
|
||||
}
|
||||
@@ -9,33 +9,14 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.management;
|
||||
|
||||
import static org.eclipse.hawkbit.repository.jpa.configuration.Constants.TX_RT_DELAY;
|
||||
import static org.eclipse.hawkbit.repository.jpa.configuration.Constants.TX_RT_MAX;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
import org.eclipse.hawkbit.repository.DistributionSetTagFields;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetTagManagement;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetRepository;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetTagRepository;
|
||||
import org.eclipse.hawkbit.repository.jpa.specifications.DistributionSetTagSpecifications;
|
||||
import org.eclipse.hawkbit.repository.jpa.specifications.TagSpecification;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty;
|
||||
import org.springframework.dao.ConcurrencyFailureException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.retry.annotation.Backoff;
|
||||
import org.springframework.retry.annotation.Retryable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@ConditionalOnBooleanProperty(prefix = "hawkbit.jpa", name = { "enabled", "distribution-set-tag-management" }, matchIfMissing = true)
|
||||
|
||||
@@ -211,7 +211,7 @@ class JpaTargetFilterQueryManagement
|
||||
|
||||
private void assertMaxTargetsQuota(final String query, final String filterName, final long dsId) {
|
||||
QuotaHelper.assertAssignmentQuota(filterName,
|
||||
targetManagement.countByRsqlAndNonDSAndCompatibleAndUpdatable(dsId, query),
|
||||
targetManagement.countByRsqlAndNonDsAndCompatibleAndUpdatable(dsId, query),
|
||||
quotaManagement.getMaxTargetsPerAutoAssignment(), Target.class, TargetFilterQuery.class, null);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ package org.eclipse.hawkbit.repository.jpa.management;
|
||||
|
||||
import static org.eclipse.hawkbit.repository.jpa.JpaManagementHelper.combineWithAnd;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -35,14 +34,9 @@ import jakarta.persistence.criteria.Root;
|
||||
import jakarta.persistence.metamodel.MapAttribute;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
|
||||
import org.apache.commons.collections4.ListUtils;
|
||||
import org.eclipse.hawkbit.repository.FilterParams;
|
||||
import org.eclipse.hawkbit.repository.QuotaManagement;
|
||||
import org.eclipse.hawkbit.repository.TargetFields;
|
||||
import org.eclipse.hawkbit.repository.TargetManagement;
|
||||
import org.eclipse.hawkbit.repository.TimestampCalculator;
|
||||
import org.eclipse.hawkbit.repository.event.EventPublisherHolder;
|
||||
import org.eclipse.hawkbit.repository.event.remote.TargetAttributesRequestedEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper;
|
||||
@@ -52,9 +46,7 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetType;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.RolloutGroupRepository;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.TargetFilterQueryRepository;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.TargetTagRepository;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.TargetTypeRepository;
|
||||
@@ -66,12 +58,8 @@ import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
|
||||
import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||
import org.eclipse.hawkbit.repository.model.TargetType;
|
||||
import org.eclipse.hawkbit.repository.model.TargetTypeAssignmentResult;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty;
|
||||
import org.springframework.dao.ConcurrencyFailureException;
|
||||
import org.springframework.data.domain.Page;
|
||||
@@ -82,7 +70,6 @@ import org.springframework.retry.annotation.Backoff;
|
||||
import org.springframework.retry.annotation.Retryable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
/**
|
||||
@@ -100,9 +87,7 @@ public class JpaTargetManagement
|
||||
private final QuotaManagement quotaManagement;
|
||||
private final TargetTypeRepository targetTypeRepository;
|
||||
private final RolloutGroupRepository rolloutGroupRepository;
|
||||
private final TargetFilterQueryRepository targetFilterQueryRepository;
|
||||
private final TargetTagRepository targetTagRepository;
|
||||
private final TenantAware tenantAware;
|
||||
|
||||
@SuppressWarnings("java:S107")
|
||||
protected JpaTargetManagement(
|
||||
@@ -110,83 +95,41 @@ public class JpaTargetManagement
|
||||
final JpaDistributionSetManagement distributionSetManagement, final QuotaManagement quotaManagement,
|
||||
final TargetTypeRepository targetTypeRepository,
|
||||
final RolloutGroupRepository rolloutGroupRepository,
|
||||
final TargetFilterQueryRepository targetFilterQueryRepository,
|
||||
final TargetTagRepository targetTagRepository,
|
||||
final TenantAware tenantAware) {
|
||||
final TargetTagRepository targetTagRepository) {
|
||||
super(jpaRepository, entityManager);
|
||||
this.distributionSetManagement = distributionSetManagement;
|
||||
this.quotaManagement = quotaManagement;
|
||||
this.targetTypeRepository = targetTypeRepository;
|
||||
this.rolloutGroupRepository = rolloutGroupRepository;
|
||||
this.targetFilterQueryRepository = targetFilterQueryRepository;
|
||||
this.targetTagRepository = targetTagRepository;
|
||||
this.tenantAware = tenantAware;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countByAssignedDistributionSet(final long distributionSetId) {
|
||||
final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException((distributionSetId));
|
||||
return jpaRepository.count(TargetSpecifications.hasAssignedDistributionSet(validDistSet.getId()));
|
||||
public Map<String, String> getControllerAttributes(final String controllerId) {
|
||||
return getMap(controllerId, JpaTarget_.controllerAttributes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countByFilters(final FilterParams filterParams) {
|
||||
final List<Specification<JpaTarget>> specList = buildSpecificationList(filterParams);
|
||||
return JpaManagementHelper.countBySpec(jpaRepository, specList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countByInstalledDistributionSet(final long distributionSetId) {
|
||||
final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException((distributionSetId));
|
||||
return jpaRepository.count(TargetSpecifications.hasInstalledDistributionSet(validDistSet.getId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean existsByInstalledOrAssignedDistributionSet(final long distributionSetId) {
|
||||
final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException((distributionSetId));
|
||||
return jpaRepository.exists(TargetSpecifications.hasInstalledOrAssignedDistributionSet(validDistSet.getId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countByRsqlAndUpdatable(String rsql) {
|
||||
public boolean isTargetMatchingQueryAndDSNotAssignedAndCompatibleAndUpdatable(
|
||||
final String controllerId, final long distributionSetId, final String targetFilterQuery) {
|
||||
RsqlUtility.getInstance().validateRsqlFor(targetFilterQuery, TargetFields.class, JpaTarget.class);
|
||||
final DistributionSet ds = distributionSetManagement.get(distributionSetId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, distributionSetId));
|
||||
final Long distSetTypeId = ds.getType().getId();
|
||||
final List<Specification<JpaTarget>> specList = List.of(
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class));
|
||||
return jpaRepository.count(AccessController.Operation.UPDATE, combineWithAnd(specList));
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(targetFilterQuery, TargetFields.class),
|
||||
TargetSpecifications.hasNotDistributionSetInActions(distributionSetId),
|
||||
TargetSpecifications.isCompatibleWithDistributionSetType(distSetTypeId),
|
||||
TargetSpecifications.hasControllerId(controllerId));
|
||||
|
||||
final Specification<JpaTarget> combinedSpecification = Objects
|
||||
.requireNonNull(SpecificationsBuilder.combineWithAnd(specList));
|
||||
return jpaRepository.exists(AccessController.Operation.UPDATE, combinedSpecification);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countByRsqlAndCompatible(final String rsql, final Long distributionSetIdTypeId) {
|
||||
final List<Specification<JpaTarget>> specList = List.of(
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class),
|
||||
TargetSpecifications.isCompatibleWithDistributionSetType(distributionSetIdTypeId));
|
||||
return JpaManagementHelper.countBySpec(jpaRepository, specList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countByFailedInRollout(final String rolloutId, final Long dsTypeId) {
|
||||
final List<Specification<JpaTarget>> specList = List.of(TargetSpecifications.failedActionsForRollout(rolloutId));
|
||||
return JpaManagementHelper.countBySpec(jpaRepository, specList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countByTargetFilterQuery(final long targetFilterQueryId) {
|
||||
final TargetFilterQuery targetFilterQuery = targetFilterQueryRepository
|
||||
.findById(targetFilterQueryId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, targetFilterQueryId));
|
||||
return countByRsql(targetFilterQuery.getQuery());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public void deleteByControllerID(final String controllerId) {
|
||||
jpaRepository.delete(getByControllerIdAndThrowIfNotFound(controllerId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Slice<Target> findByTargetFilterQueryAndNonDSAndCompatibleAndUpdatable(final long distributionSetId, final String rsql,
|
||||
final Pageable pageable) {
|
||||
public Slice<Target> findByTargetFilterQueryAndNonDSAndCompatibleAndUpdatable(
|
||||
final long distributionSetId, final String rsql, final Pageable pageable) {
|
||||
final DistributionSet jpaDistributionSet = distributionSetManagement.getOrElseThrowException(distributionSetId);
|
||||
final Long distSetTypeId = jpaDistributionSet.getType().getId();
|
||||
|
||||
@@ -202,16 +145,18 @@ public class JpaTargetManagement
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countByRsqlAndNonDSAndCompatibleAndUpdatable(final long distributionSetId, final String rsql) {
|
||||
final DistributionSet jpaDistributionSet = distributionSetManagement.getOrElseThrowException(distributionSetId);
|
||||
final Long distSetTypeId = jpaDistributionSet.getType().getId();
|
||||
public List<Target> getByControllerId(final Collection<String> controllerIDs) {
|
||||
return Collections.unmodifiableList(jpaRepository.findAll(TargetSpecifications.byControllerIdWithAssignedDsInJoin(controllerIDs)));
|
||||
}
|
||||
|
||||
return jpaRepository.count(
|
||||
AccessController.Operation.UPDATE,
|
||||
combineWithAnd(List.of(
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class),
|
||||
TargetSpecifications.hasNotDistributionSetInActions(distributionSetId),
|
||||
TargetSpecifications.isCompatibleWithDistributionSetType(distSetTypeId))));
|
||||
@Override
|
||||
public Optional<Target> getByControllerId(final String controllerId) {
|
||||
return jpaRepository.findByControllerId(controllerId).map(Target.class::cast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Target getWithDetails(final String controllerId, final String detailsKey) {
|
||||
return jpaRepository.getWithDetailsByControllerId(controllerId, "Target." + detailsKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -227,16 +172,6 @@ public class JpaTargetManagement
|
||||
.map(Target.class::cast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable(
|
||||
final String rsql, final Collection<Long> groups, final DistributionSetType dsType) {
|
||||
return jpaRepository.count(AccessController.Operation.UPDATE,
|
||||
combineWithAnd(List.of(
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class),
|
||||
TargetSpecifications.isNotInRolloutGroups(groups),
|
||||
TargetSpecifications.isCompatibleWithDistributionSetType(dsType.getId()))));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Slice<Target> findByFailedRolloutAndNotInRolloutGroups(String rolloutId, Collection<Long> groups, Pageable pageable) {
|
||||
final List<Specification<JpaTarget>> specList = List.of(
|
||||
@@ -245,14 +180,6 @@ public class JpaTargetManagement
|
||||
return JpaManagementHelper.findAllWithCountBySpec(jpaRepository, specList, pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countByFailedRolloutAndNotInRolloutGroups(String rolloutId, Collection<Long> groups) {
|
||||
final List<Specification<JpaTarget>> specList = List.of(
|
||||
TargetSpecifications.failedActionsForRollout(rolloutId),
|
||||
TargetSpecifications.isNotInRolloutGroups(groups));
|
||||
return JpaManagementHelper.countBySpec(jpaRepository, specList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Slice<Target> findByRsqlAndNoOverridingActionsAndNotInRolloutAndCompatibleAndUpdatable(
|
||||
final long rolloutId, final String rsql, final DistributionSetType distributionSetType, final Pageable pageable) {
|
||||
@@ -266,11 +193,6 @@ public class JpaTargetManagement
|
||||
.map(Target.class::cast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countByActionsInRolloutGroup(final long rolloutGroupId) {
|
||||
return jpaRepository.count(TargetSpecifications.isInActionRolloutGroup(rolloutGroupId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Slice<Target> findByInRolloutGroupWithoutAction(final long group, final Pageable pageable) {
|
||||
if (!rolloutGroupRepository.existsById(group)) {
|
||||
@@ -301,27 +223,6 @@ public class JpaTargetManagement
|
||||
return JpaManagementHelper.findAllWithCountBySpec(jpaRepository, specList, pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Target> getByControllerId(final Collection<String> controllerIDs) {
|
||||
return Collections.unmodifiableList(jpaRepository.findAll(TargetSpecifications.byControllerIdWithAssignedDsInJoin(controllerIDs)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Target> getByControllerId(final String controllerId) {
|
||||
return jpaRepository.findByControllerId(controllerId).map(Target.class::cast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Target getWithDetails(final String controllerId, final String detailsKey) {
|
||||
return jpaRepository.getWithDetailsByControllerId(controllerId, "Target." + detailsKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Slice<Target> findByFilters(final FilterParams filterParams, final Pageable pageable) {
|
||||
final List<Specification<JpaTarget>> specList = buildSpecificationList(filterParams);
|
||||
return JpaManagementHelper.findAllWithoutCountBySpec(jpaRepository, specList, pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<Target> findByInstalledDistributionSet(final long distributionSetId, final Pageable pageReq) {
|
||||
final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetId);
|
||||
@@ -341,23 +242,6 @@ public class JpaTargetManagement
|
||||
return JpaManagementHelper.findAllWithCountBySpec(jpaRepository, specList, pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<Target> findByUpdateStatus(final TargetUpdateStatus status, final Pageable pageable) {
|
||||
return JpaManagementHelper.findAllWithCountBySpec(
|
||||
jpaRepository, List.of(TargetSpecifications.hasTargetUpdateStatus(status)), pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Slice<Target> findByTargetFilterQuery(final long targetFilterQueryId, final Pageable pageable) {
|
||||
final TargetFilterQuery targetFilterQuery = targetFilterQueryRepository.findById(targetFilterQueryId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, targetFilterQueryId));
|
||||
|
||||
return JpaManagementHelper.findAllWithoutCountBySpec(
|
||||
jpaRepository, List.of(RsqlUtility.getInstance().buildRsqlSpecification(
|
||||
targetFilterQuery.getQuery(), TargetFields.class)), pageable
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<Target> findByTag(final long tagId, final Pageable pageable) {
|
||||
throwEntityNotFoundExceptionIfTagDoesNotExist(tagId);
|
||||
@@ -376,44 +260,61 @@ public class JpaTargetManagement
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public TargetTypeAssignmentResult assignType(final Collection<String> controllerIds, final Long typeId) {
|
||||
final JpaTargetType type = targetTypeRepository
|
||||
.findById(typeId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(TargetType.class, typeId));
|
||||
public long countByRsqlAndCompatible(final String rsql, final Long distributionSetIdTypeId) {
|
||||
final List<Specification<JpaTarget>> specList = List.of(
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class),
|
||||
TargetSpecifications.isCompatibleWithDistributionSetType(distributionSetIdTypeId));
|
||||
return JpaManagementHelper.countBySpec(jpaRepository, specList);
|
||||
}
|
||||
|
||||
final List<JpaTarget> targetsWithSameType = findTargetsByInSpecification(controllerIds, TargetSpecifications.hasTargetType(typeId));
|
||||
final List<JpaTarget> targetsWithoutSameType =
|
||||
findTargetsByInSpecification(controllerIds, TargetSpecifications.hasTargetTypeNot(typeId));
|
||||
@Override
|
||||
public long countByFailedInRollout(final String rolloutId, final Long dsTypeId) {
|
||||
final List<Specification<JpaTarget>> specList = List.of(TargetSpecifications.failedActionsForRollout(rolloutId));
|
||||
return JpaManagementHelper.countBySpec(jpaRepository, specList);
|
||||
}
|
||||
|
||||
// set new target type to all targets without that type
|
||||
targetsWithoutSameType.forEach(target -> target.setTargetType(type));
|
||||
@Override
|
||||
public long countByRsqlAndNonDsAndCompatibleAndUpdatable(final long distributionSetId, final String rsql) {
|
||||
final DistributionSet jpaDistributionSet = distributionSetManagement.getOrElseThrowException(distributionSetId);
|
||||
final Long distSetTypeId = jpaDistributionSet.getType().getId();
|
||||
|
||||
final TargetTypeAssignmentResult result = new TargetTypeAssignmentResult(
|
||||
targetsWithSameType.size(), jpaRepository.saveAll(targetsWithoutSameType), Collections.emptyList(), type);
|
||||
return jpaRepository.count(
|
||||
AccessController.Operation.UPDATE,
|
||||
combineWithAnd(List.of(
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class),
|
||||
TargetSpecifications.hasNotDistributionSetInActions(distributionSetId),
|
||||
TargetSpecifications.isCompatibleWithDistributionSetType(distSetTypeId))));
|
||||
}
|
||||
|
||||
// no reason to persist the type
|
||||
entityManager.detach(type);
|
||||
return result;
|
||||
@Override
|
||||
public long countByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable(
|
||||
final String rsql, final Collection<Long> groups, final DistributionSetType dsType) {
|
||||
return jpaRepository.count(AccessController.Operation.UPDATE,
|
||||
combineWithAnd(List.of(
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class),
|
||||
TargetSpecifications.isNotInRolloutGroups(groups),
|
||||
TargetSpecifications.isCompatibleWithDistributionSetType(dsType.getId()))));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countByFailedRolloutAndNotInRolloutGroups(String rolloutId, Collection<Long> groups) {
|
||||
final List<Specification<JpaTarget>> specList = List.of(
|
||||
TargetSpecifications.failedActionsForRollout(rolloutId),
|
||||
TargetSpecifications.isNotInRolloutGroups(groups));
|
||||
return JpaManagementHelper.countBySpec(jpaRepository, specList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countByActionsInRolloutGroup(final long rolloutGroupId) {
|
||||
return jpaRepository.count(TargetSpecifications.isInActionRolloutGroup(rolloutGroupId));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public TargetTypeAssignmentResult unassignType(final Collection<String> controllerIds) {
|
||||
final List<JpaTarget> allTargets = findTargetsByInSpecification(controllerIds, null);
|
||||
|
||||
if (allTargets.size() < controllerIds.size()) {
|
||||
throw new EntityNotFoundException(Target.class, controllerIds, allTargets.stream().map(Target::getControllerId).toList());
|
||||
}
|
||||
|
||||
// set new target type to null for all targets
|
||||
allTargets.forEach(target -> target.setTargetType(null));
|
||||
|
||||
return new TargetTypeAssignmentResult(0, Collections.emptyList(), jpaRepository.saveAll(allTargets), null);
|
||||
public void deleteByControllerId(final String controllerId) {
|
||||
jpaRepository.delete(getByControllerIdAndThrowIfNotFound(controllerId));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -445,6 +346,12 @@ public class JpaTargetManagement
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<TargetTag> getTags(@NotEmpty String controllerId) {
|
||||
// the method has PreAuthorized by itself
|
||||
return ((JpaTarget) getWithDetails(controllerId, DETAILS_TAGS)).getTags();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
@@ -474,16 +381,6 @@ public class JpaTargetManagement
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public Target unassignType(final String controllerId) {
|
||||
final JpaTarget target = getByControllerIdAndThrowIfNotFound(controllerId);
|
||||
target.setTargetType(null);
|
||||
return jpaRepository.save(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
@@ -500,23 +397,15 @@ public class JpaTargetManagement
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<Target> findTargetsByGroup(String group, final boolean withSubgroups, final Pageable pageable) {
|
||||
if (withSubgroups) {
|
||||
// search for eq(group) and like(group%)
|
||||
return JpaManagementHelper
|
||||
.findAllWithCountBySpec(jpaRepository, List.of(TargetSpecifications.eqOrSubTargetGroup(group)), pageable);
|
||||
} else {
|
||||
return JpaManagementHelper
|
||||
.findAllWithCountBySpec(jpaRepository, List.of(TargetSpecifications.eqTargetGroup(group)), pageable);
|
||||
}
|
||||
@Transactional
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public Target unassignType(final String controllerId) {
|
||||
final JpaTarget target = getByControllerIdAndThrowIfNotFound(controllerId);
|
||||
target.setTargetType(null);
|
||||
return jpaRepository.save(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> findGroups() {
|
||||
return jpaRepository.findDistinctGroups();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
@@ -547,69 +436,23 @@ public class JpaTargetManagement
|
||||
controllerIds.forEach(in::value);
|
||||
|
||||
entityManager.createQuery(criteriaQuery.set("group", group).where(in)).executeUpdate();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean existsByControllerId(final String controllerId) {
|
||||
return jpaRepository.exists(TargetSpecifications.hasControllerId(controllerId));
|
||||
public Page<Target> findTargetsByGroup(String group, final boolean withSubgroups, final Pageable pageable) {
|
||||
if (withSubgroups) {
|
||||
// search for eq(group) and like(group%)
|
||||
return JpaManagementHelper
|
||||
.findAllWithCountBySpec(jpaRepository, List.of(TargetSpecifications.eqOrSubTargetGroup(group)), pageable);
|
||||
} else {
|
||||
return JpaManagementHelper
|
||||
.findAllWithCountBySpec(jpaRepository, List.of(TargetSpecifications.eqTargetGroup(group)), pageable);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTargetMatchingQueryAndDSNotAssignedAndCompatibleAndUpdatable(
|
||||
final String controllerId, final long distributionSetId, final String targetFilterQuery) {
|
||||
RsqlUtility.getInstance().validateRsqlFor(targetFilterQuery, TargetFields.class, JpaTarget.class);
|
||||
final DistributionSet ds = distributionSetManagement.get(distributionSetId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, distributionSetId));
|
||||
final Long distSetTypeId = ds.getType().getId();
|
||||
final List<Specification<JpaTarget>> specList = List.of(
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(targetFilterQuery, TargetFields.class),
|
||||
TargetSpecifications.hasNotDistributionSetInActions(distributionSetId),
|
||||
TargetSpecifications.isCompatibleWithDistributionSetType(distSetTypeId),
|
||||
TargetSpecifications.hasControllerId(controllerId));
|
||||
|
||||
final Specification<JpaTarget> combinedSpecification = Objects
|
||||
.requireNonNull(SpecificationsBuilder.combineWithAnd(specList));
|
||||
return jpaRepository.exists(AccessController.Operation.UPDATE, combinedSpecification);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<TargetTag> getTags(@NotEmpty String controllerId) {
|
||||
// the method has PreAuthorized by itself
|
||||
return ((JpaTarget) getWithTags(controllerId)).getTags();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getControllerAttributes(final String controllerId) {
|
||||
return getMap(controllerId, JpaTarget_.controllerAttributes);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public void requestControllerAttributes(final String controllerId) {
|
||||
final JpaTarget target = getByControllerIdAndThrowIfNotFound(controllerId);
|
||||
jpaRepository.getAccessController()
|
||||
.ifPresent(acm -> acm.assertOperationAllowed(AccessController.Operation.UPDATE, target));
|
||||
target.setRequestControllerAttributes(true);
|
||||
AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit(() ->
|
||||
EventPublisherHolder.getInstance().getEventPublisher()
|
||||
.publishEvent(new TargetAttributesRequestedEvent(
|
||||
tenantAware.getCurrentTenant(), target.getId(), JpaTarget.class, target.getControllerId(),
|
||||
target.getAddress() != null ? target.getAddress().toString() : null
|
||||
)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isControllerAttributesRequested(final String controllerId) {
|
||||
return getByControllerIdAndThrowIfNotFound(controllerId).isRequestControllerAttributes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<Target> findByControllerAttributesRequested(final Pageable pageable) {
|
||||
return JpaManagementHelper.findAllWithCountBySpec(
|
||||
jpaRepository, List.of(TargetSpecifications.hasRequestControllerAttributesTrue()), pageable);
|
||||
public List<String> findGroups() {
|
||||
return jpaRepository.findDistinctGroups();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -695,22 +538,6 @@ public class JpaTargetManagement
|
||||
.collect(Collectors.toMap(entry -> (String) entry[0], entry -> (String) entry[1], (v1, v2) -> v1, LinkedHashMap::new));
|
||||
}
|
||||
|
||||
private static boolean hasTagsFilterActive(final FilterParams filterParams) {
|
||||
final boolean isNoTagActive = Boolean.TRUE.equals(filterParams.getSelectTargetWithNoTag());
|
||||
final boolean isAtLeastOneTagActive = filterParams.getFilterByTagNames() != null
|
||||
&& filterParams.getFilterByTagNames().length > 0;
|
||||
|
||||
return isNoTagActive || isAtLeastOneTagActive;
|
||||
}
|
||||
|
||||
private static boolean hasTypesFilterActive(final FilterParams filterParams) {
|
||||
return filterParams.getFilterByTargetType() != null;
|
||||
}
|
||||
|
||||
private static boolean hasNoTypeFilterActive(final FilterParams filterParams) {
|
||||
return Boolean.TRUE.equals(filterParams.getSelectTargetWithNoTargetType());
|
||||
}
|
||||
|
||||
private static Collection<String> notFound(final Collection<String> controllerIds, final List<JpaTarget> foundTargets) {
|
||||
final Map<String, JpaTarget> foundTargetMap = foundTargets.stream()
|
||||
.collect(Collectors.toMap(Target::getControllerId, Function.identity()));
|
||||
@@ -730,43 +557,6 @@ public class JpaTargetManagement
|
||||
QuotaHelper.assertAssignmentQuota(targetId, requested, limit, "Metadata", Target.class.getSimpleName(), null);
|
||||
}
|
||||
|
||||
private List<Specification<JpaTarget>> buildSpecificationList(final FilterParams filterParams) {
|
||||
final List<Specification<JpaTarget>> specList = new ArrayList<>();
|
||||
if ((filterParams.getFilterByStatus() != null) && !filterParams.getFilterByStatus().isEmpty()) {
|
||||
specList.add(TargetSpecifications.hasTargetUpdateStatus(filterParams.getFilterByStatus()));
|
||||
}
|
||||
if (filterParams.getOverdueState() != null && filterParams.getOverdueState()) {
|
||||
specList.add(TargetSpecifications.isOverdue(TimestampCalculator.calculateOverdueTimestamp()));
|
||||
}
|
||||
if (filterParams.getFilterByDistributionId() != null) {
|
||||
final DistributionSet validDistSet = distributionSetManagement
|
||||
.getOrElseThrowException(filterParams.getFilterByDistributionId());
|
||||
|
||||
specList.add(TargetSpecifications.hasInstalledOrAssignedDistributionSet(validDistSet.getId()));
|
||||
}
|
||||
if (!ObjectUtils.isEmpty(filterParams.getFilterBySearchText())) {
|
||||
specList.add(TargetSpecifications.likeControllerIdOrName(filterParams.getFilterBySearchText()));
|
||||
}
|
||||
if (hasTagsFilterActive(filterParams)) {
|
||||
specList.add(TargetSpecifications.hasTags(filterParams.getFilterByTagNames(),
|
||||
filterParams.getSelectTargetWithNoTag()));
|
||||
}
|
||||
|
||||
if (hasTypesFilterActive(filterParams)) {
|
||||
specList.add(TargetSpecifications.hasTargetType(filterParams.getFilterByTargetType()));
|
||||
} else if (hasNoTypeFilterActive(filterParams)) {
|
||||
specList.add(TargetSpecifications.hasNoTargetType());
|
||||
}
|
||||
|
||||
return specList;
|
||||
}
|
||||
|
||||
private List<JpaTarget> findTargetsByInSpecification(final Collection<String> controllerIds, final Specification<JpaTarget> specification) {
|
||||
return ListUtils.partition(new ArrayList<>(controllerIds), Constants.MAX_ENTRIES_IN_STATEMENT).stream()
|
||||
.map(ids -> jpaRepository.findAll(TargetSpecifications.hasControllerIdIn(ids).and(specification)))
|
||||
.flatMap(List::stream).toList();
|
||||
}
|
||||
|
||||
private List<Target> updateTag(
|
||||
final Collection<String> controllerIds, final long targetTagId, final Consumer<Collection<String>> notFoundHandler,
|
||||
final BiFunction<JpaTargetTag, JpaTarget, Target> updater) {
|
||||
@@ -776,8 +566,7 @@ public class JpaTargetManagement
|
||||
jpaRepository.findByControllerId(controllerIds.iterator().next())
|
||||
.map(List::of)
|
||||
.orElseGet(Collections::emptyList) :
|
||||
jpaRepository
|
||||
.findAll(TargetSpecifications.byControllerIdWithTagsInJoin(controllerIds));
|
||||
jpaRepository.findAll(TargetSpecifications.byControllerIdWithTagsInJoin(controllerIds));
|
||||
if (targets.size() < controllerIds.size()) {
|
||||
final Collection<String> notFound = notFound(controllerIds, targets);
|
||||
if (notFoundHandler == null) {
|
||||
|
||||
@@ -78,10 +78,6 @@ public final class ActionSpecifications {
|
||||
isNull ? cb.isNull(root.get(JpaAction_.weight)) : cb.isNotNull(root.get(JpaAction_.weight)));
|
||||
}
|
||||
|
||||
public static Specification<JpaAction> byDistributionSetId(final Long distributionSetId) {
|
||||
return (root, query, cb) -> cb.equal(root.get(JpaAction_.distributionSet).get(AbstractJpaBaseEntity_.id), distributionSetId);
|
||||
}
|
||||
|
||||
public static Specification<JpaAction> byDistributionSetIdAndActive(final Long distributionSetId) {
|
||||
return (root, query, cb) -> cb.and(
|
||||
cb.equal(root.get(JpaAction_.distributionSet).get(AbstractJpaBaseEntity_.id), distributionSetId),
|
||||
|
||||
@@ -77,23 +77,6 @@ public final class DistributionSetSpecification {
|
||||
return (dsRoot, query, cb) -> cb.equal(dsRoot.get(JpaDistributionSet_.valid), isValid);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link DistributionSet} with given {@link DistributionSet#getId()}.
|
||||
*
|
||||
* @param distid to search
|
||||
* @return the {@link DistributionSet} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaDistributionSet> byIdFetch(final Long distid) {
|
||||
return (dsRoot, query, cb) -> {
|
||||
final Predicate predicate = cb.equal(dsRoot.get(AbstractJpaBaseEntity_.id), distid);
|
||||
dsRoot.fetch(JpaDistributionSet_.modules, JoinType.LEFT);
|
||||
dsRoot.fetch(JpaDistributionSet_.type, JoinType.LEFT);
|
||||
query.distinct(true);
|
||||
|
||||
return predicate;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link DistributionSet} with given {@link DistributionSet#getId()}s.
|
||||
*
|
||||
@@ -162,16 +145,6 @@ public final class DistributionSetSpecification {
|
||||
return (dsRoot, query, cb) -> cb.equal(dsRoot.get(JpaDistributionSet_.type).get(AbstractJpaBaseEntity_.id), typeId);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link DistributionSet} for given id collection of {@link DistributionSet#getType()}.
|
||||
*
|
||||
* @param typeIds id collection of distribution set type to search
|
||||
* @return the {@link DistributionSet} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaDistributionSet> hasType(final Collection<Long> typeIds) {
|
||||
return (dsRoot, query, cb) -> dsRoot.get(JpaDistributionSet_.type).get(AbstractJpaBaseEntity_.id).in(typeIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link DistributionSet}s by tag.
|
||||
*
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2023 Bosch.IO 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.specifications;
|
||||
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaNamedEntity_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
|
||||
/**
|
||||
* Utility class for {@link JpaDistributionSetTag}s {@link Specification}s. The class provides Spring Data JPQL Specifications.
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public final class DistributionSetTagSpecifications {
|
||||
|
||||
public static Specification<JpaDistributionSetTag> byName(@NotEmpty final String name) {
|
||||
return (targetRoot, query, cb) -> cb.equal(targetRoot.get(AbstractJpaNamedEntity_.name), name);
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,8 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.specifications;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaNamedEntity_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaTypeEntity_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType;
|
||||
@@ -18,25 +20,11 @@ import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
|
||||
/**
|
||||
* Specifications class for {@link DistributionSetType}s. The class provides
|
||||
* Spring Data JPQL Specifications.
|
||||
* Specifications class for {@link DistributionSetType}s. The class provides Spring Data JPQL Specifications.
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public final class DistributionSetTypeSpecification {
|
||||
|
||||
private DistributionSetTypeSpecification() {
|
||||
// utility class
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link DistributionSetType}s with
|
||||
* DELETED attribute <code>false</code> - i.e. is not deleted.
|
||||
*
|
||||
* @return the {@link DistributionSetType} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaDistributionSetType> isNotDeleted() {
|
||||
return (targetRoot, query, cb) -> cb.equal(targetRoot.<Boolean> get(JpaDistributionSetType_.deleted), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link DistributionSetType} with
|
||||
* given {@link DistributionSetType#getName()} including fetching the
|
||||
@@ -60,4 +48,4 @@ public final class DistributionSetTypeSpecification {
|
||||
public static Specification<JpaDistributionSetType> byKey(final String key) {
|
||||
return (targetRoot, query, cb) -> cb.equal(targetRoot.get(AbstractJpaTypeEntity_.key), key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,91 +11,25 @@ package org.eclipse.hawkbit.repository.jpa.specifications;
|
||||
|
||||
import jakarta.persistence.criteria.ListJoin;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaNamedEntity_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaNamedVersionedEntity_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule_;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
|
||||
/**
|
||||
* Specifications class for {@link SoftwareModule}s. The class provides Spring
|
||||
* Data JPQL Specifications
|
||||
* Specifications class for {@link SoftwareModule}s. The class provides Spring Data JPQL Specifications
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public final class SoftwareModuleSpecification {
|
||||
|
||||
private SoftwareModuleSpecification() {
|
||||
// utility class
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link SoftwareModule} with given
|
||||
* {@link DistributionSet#getId()}.
|
||||
*
|
||||
* @param swModuleId to search
|
||||
* @return the {@link SoftwareModule} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaSoftwareModule> byId(final Long swModuleId) {
|
||||
return (swRoot, query, cb) -> cb.equal(swRoot.get(AbstractJpaBaseEntity_.id), swModuleId);
|
||||
}
|
||||
|
||||
public static Specification<JpaSoftwareModule> byAssignedToDs(final Long dsId) {
|
||||
return (swRoot, query, cb) -> {
|
||||
final ListJoin<JpaSoftwareModule, JpaDistributionSet> join = swRoot.join(JpaSoftwareModule_.assignedTo);
|
||||
return cb.equal(join.get(AbstractJpaBaseEntity_.ID), dsId);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link SoftwareModule}s with
|
||||
* DELETED attribute <code>false</code> - i.e. is not deleted.
|
||||
*
|
||||
* @return the {@link SoftwareModule} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaSoftwareModule> isNotDeleted() {
|
||||
return (swRoot, query, cb) -> cb.equal(swRoot.get(JpaSoftwareModule_.deleted), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link SoftwareModule}s by "like
|
||||
* name and like version".
|
||||
*
|
||||
* @param name to be filtered on
|
||||
* @param version to be filtered on
|
||||
* @return the {@link SoftwareModule} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaSoftwareModule> likeNameAndVersion(final String name, final String version) {
|
||||
return (smRoot, query, cb) -> cb.and(
|
||||
cb.like(cb.lower(smRoot.get(AbstractJpaNamedEntity_.name)), name.toLowerCase()),
|
||||
cb.like(cb.lower(smRoot.get(AbstractJpaNamedVersionedEntity_.version)), version.toLowerCase()));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link SoftwareModule}s by "like
|
||||
* name or like version".
|
||||
*
|
||||
* @param type to be filtered on
|
||||
* @return the {@link SoftwareModule} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaSoftwareModule> equalType(final Long type) {
|
||||
return (smRoot, query, cb) -> cb.equal(
|
||||
smRoot.get(JpaSoftwareModule_.type).get(AbstractJpaBaseEntity_.id), type);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for fetching {@link SoftwareModule}s type.
|
||||
*
|
||||
* @return the {@link SoftwareModule} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaSoftwareModule> fetchType() {
|
||||
return (smRoot, query, cb) -> {
|
||||
if (!query.getResultType().isAssignableFrom(Long.class)) {
|
||||
smRoot.fetch(JpaSoftwareModule_.type);
|
||||
}
|
||||
return cb.conjunction();
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2022 Bosch.IO 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.specifications;
|
||||
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleType;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleType_;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
|
||||
/**
|
||||
* Specifications class for {@link SoftwareModuleType}s. The class provides
|
||||
* Spring Data JPQL Specifications.
|
||||
*/
|
||||
public class SoftwareModuleTypeSpecification {
|
||||
|
||||
private SoftwareModuleTypeSpecification() {
|
||||
// utility class
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link SoftwareModuleType}s with
|
||||
* DELETED attribute <code>false</code> - i.e. is not deleted.
|
||||
*
|
||||
* @return the {@link SoftwareModuleType} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaSoftwareModuleType> isNotDeleted() {
|
||||
return (root, query, cb) -> cb.equal(root.get(JpaSoftwareModuleType_.deleted), false);
|
||||
}
|
||||
}
|
||||
@@ -1,48 +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.specifications;
|
||||
|
||||
import jakarta.persistence.criteria.Join;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag_;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
|
||||
/**
|
||||
* Specifications class for {@link org.eclipse.hawkbit.repository.model.Tag}s.
|
||||
* The class provides Spring Data JPQL Specifications.
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public final class TagSpecification {
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link DistributionSetTag}s by
|
||||
* assigned {@link DistributionSet}.
|
||||
*
|
||||
* @param dsId of the distribution set
|
||||
* @return the {@link JpaDistributionSetTag} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaDistributionSetTag> ofDistributionSet(final Long dsId) {
|
||||
return (dsRoot, query, criteriaBuilder) -> {
|
||||
final Join<JpaDistributionSetTag, JpaDistributionSet> tagJoin = dsRoot
|
||||
.join(JpaDistributionSetTag_.assignedToDistributionSet);
|
||||
|
||||
query.distinct(true);
|
||||
|
||||
return criteriaBuilder.equal(tagJoin.get(AbstractJpaBaseEntity_.id), dsId);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,8 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.specifications;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetFilterQuery;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetFilterQuery_;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
@@ -16,26 +18,11 @@ import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
|
||||
/**
|
||||
* Specifications class for {@link TargetFilterQuery}s. The class provides
|
||||
* Spring Data JPQL Specifications.
|
||||
* Specifications class for {@link TargetFilterQuery}s. The class provides Spring Data JPQL Specifications.
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public final class TargetFilterQuerySpecification {
|
||||
|
||||
private TargetFilterQuerySpecification() {
|
||||
// utility class
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link JpaTargetFilterQuery}s based
|
||||
* on is {@link JpaTargetFilterQuery#getQuery()}.
|
||||
*
|
||||
* @param queryValue the query of the filter
|
||||
* @return the {@link JpaTargetFilterQuery} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaTargetFilterQuery> equalsQuery(final String queryValue) {
|
||||
return (targetFilterQueryRoot, query, cb) -> cb.equal(targetFilterQueryRoot.get(JpaTargetFilterQuery_.query), queryValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link JpaTargetFilterQuery}s based
|
||||
* on is {@link JpaTargetFilterQuery#getName()}.
|
||||
|
||||
@@ -9,11 +9,9 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.specifications;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||
import jakarta.persistence.criteria.Join;
|
||||
import jakarta.persistence.criteria.JoinType;
|
||||
import jakarta.persistence.criteria.ListJoin;
|
||||
@@ -27,7 +25,6 @@ import jakarta.validation.constraints.NotNull;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaNamedEntity_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaAction_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
||||
@@ -108,16 +105,6 @@ public final class TargetSpecifications {
|
||||
return (targetRoot, query, cb) -> targetRoot.get(AbstractJpaBaseEntity_.id).in(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s that have the
|
||||
* request controller attributes flag set
|
||||
*
|
||||
* @return the {@link Target} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaTarget> hasRequestControllerAttributesTrue() {
|
||||
return (targetRoot, query, cb) -> cb.equal(targetRoot.get(JpaTarget_.requestControllerAttributes), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link JpaTarget}s including {@link JpaTarget#getAssignedDistributionSet()}.
|
||||
*
|
||||
@@ -132,26 +119,6 @@ public final class TargetSpecifications {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s by "equal to any given {@link TargetUpdateStatus}".
|
||||
*
|
||||
* @param updateStatus to be filtered on
|
||||
* @return the {@link Target} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaTarget> hasTargetUpdateStatus(final Collection<TargetUpdateStatus> updateStatus) {
|
||||
return (targetRoot, query, cb) -> targetRoot.get(JpaTarget_.updateStatus).in(updateStatus);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s by "equal to given {@link TargetUpdateStatus}".
|
||||
*
|
||||
* @param updateStatus to be filtered on
|
||||
* @return the {@link Target} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaTarget> hasTargetUpdateStatus(final TargetUpdateStatus updateStatus) {
|
||||
return (targetRoot, query, cb) -> cb.equal(targetRoot.get(JpaTarget_.updateStatus), updateStatus);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s by "not equal to given {@link TargetUpdateStatus}".
|
||||
*
|
||||
@@ -162,36 +129,6 @@ public final class TargetSpecifications {
|
||||
return (targetRoot, query, cb) -> cb.not(cb.equal(targetRoot.get(JpaTarget_.updateStatus), updateStatus));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s that are overdue. A target is overdue if it did not respond during the configured
|
||||
* intervals:<br>
|
||||
* <em>poll_itvl + overdue_itvl</em>
|
||||
*
|
||||
* @param overdueTimestamp the calculated timestamp to compare with the last response of a target (lastTargetQuery).<br>
|
||||
* The <code>overdueTimestamp</code> has to be calculated with the following expression:<br>
|
||||
* <em>overdueTimestamp = nowTimestamp - poll_itvl - overdue_itvl</em>
|
||||
* @return the {@link Target} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaTarget> isOverdue(final long overdueTimestamp) {
|
||||
return (targetRoot, query, cb) ->
|
||||
cb.lessThanOrEqualTo(targetRoot.get(JpaTarget_.lastTargetQuery), overdueTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s by "like controllerId or like name".
|
||||
*
|
||||
* @param searchText to be filtered on
|
||||
* @return the {@link Target} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaTarget> likeControllerIdOrName(final String searchText) {
|
||||
return (targetRoot, query, cb) -> {
|
||||
final String searchTextToLower = searchText.toLowerCase();
|
||||
return cb.or(
|
||||
cb.like(cb.lower(targetRoot.get(JpaTarget_.controllerId)), searchTextToLower),
|
||||
cb.like(cb.lower(targetRoot.get(AbstractJpaNamedEntity_.name)), searchTextToLower));
|
||||
};
|
||||
}
|
||||
|
||||
public static Specification<JpaTarget> eqTargetGroup(final String targetGroup) {
|
||||
return (targetRoot, query, criteriaBuilder) -> {
|
||||
final String groupTextToLower = targetGroup.toLowerCase();
|
||||
@@ -208,16 +145,6 @@ public final class TargetSpecifications {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s by "like controllerId".
|
||||
*
|
||||
* @param distributionId to be filtered on
|
||||
* @return the {@link Target} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaTarget> hasInstalledOrAssignedDistributionSet(@NotNull final Long distributionId) {
|
||||
return hasInstalledDistributionSet(distributionId).or(hasAssignedDistributionSet(distributionId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all targets by given {@link Target#getControllerId()}s and which are not yet assigned to given {@link DistributionSet}.
|
||||
*
|
||||
@@ -225,42 +152,14 @@ public final class TargetSpecifications {
|
||||
* @param distributionId set that is not yet assigned
|
||||
* @return the {@link Target} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaTarget> hasControllerIdAndAssignedDistributionSetIdNot(final List<String> tIDs,
|
||||
@NotNull final Long distributionId) {
|
||||
public static Specification<JpaTarget> hasControllerIdAndAssignedDistributionSetIdNot(
|
||||
final List<String> tIDs, @NotNull final Long distributionId) {
|
||||
return (targetRoot, query, cb) -> cb.and(targetRoot.get(JpaTarget_.controllerId).in(tIDs),
|
||||
cb.or(
|
||||
cb.notEqual(targetRoot.get(JpaTarget_.assignedDistributionSet).get(AbstractJpaBaseEntity_.id), distributionId),
|
||||
cb.isNull(targetRoot.get(JpaTarget_.assignedDistributionSet))));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s based on a {@link TargetTag} name.
|
||||
*
|
||||
* @param tagName to search for
|
||||
* @return the {@link Target} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaTarget> hasTagName(final String tagName) {
|
||||
return (targetRoot, query, cb) -> {
|
||||
final SetJoin<JpaTarget, JpaTargetTag> join = targetRoot.join(JpaTarget_.tags);
|
||||
return cb.equal(join.get(AbstractJpaNamedEntity_.name), tagName);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s by "has no tag names"or "has at least on of the given tag names".
|
||||
*
|
||||
* @param tagNames to be filtered on
|
||||
* @param selectTargetWithNoTag flag to get targets with no tag assigned
|
||||
* @return the {@link Target} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaTarget> hasTags(final String[] tagNames, final Boolean selectTargetWithNoTag) {
|
||||
return (targetRoot, query, cb) -> {
|
||||
final Predicate predicate = getHasTagsPredicate(targetRoot, cb, selectTargetWithNoTag, tagNames);
|
||||
query.distinct(true);
|
||||
return predicate;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s by assigned distribution set.
|
||||
*
|
||||
@@ -297,7 +196,7 @@ public final class TargetSpecifications {
|
||||
public static Specification<JpaTarget> isCompatibleWithDistributionSetType(final Long distributionSetTypeId) {
|
||||
return (targetRoot, query, cb) -> {
|
||||
// Since the targetRoot is changed by joining we need to get the isNull predicate first
|
||||
final Predicate targetTypeIsNull = getTargetTypeIsNullPredicate(targetRoot);
|
||||
final Predicate targetTypeIsNull = targetRoot.get(JpaTarget_.targetType).isNull();
|
||||
return cb.or(targetTypeIsNull, cb.equal(getDsTypeIdPath(targetRoot), distributionSetTypeId));
|
||||
};
|
||||
}
|
||||
@@ -409,36 +308,6 @@ public final class TargetSpecifications {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s by target type id
|
||||
*
|
||||
* @param typeId the id of the target type
|
||||
* @return the {@link Target} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaTarget> hasTargetType(final long typeId) {
|
||||
return (targetRoot, query, cb) -> cb.equal(targetRoot.get(JpaTarget_.targetType).get(AbstractJpaBaseEntity_.id), typeId);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s by target type id is equal to null
|
||||
*
|
||||
* @return the {@link Target} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaTarget> hasNoTargetType() {
|
||||
return (targetRoot, query, cb) -> cb.isNull(targetRoot.get(JpaTarget_.targetType));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s that don't have target type assigned
|
||||
*
|
||||
* @param typeId the id of the target type
|
||||
* @return the {@link Target} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaTarget> hasTargetTypeNot(final Long typeId) {
|
||||
return (targetRoot, query, cb) -> cb.or(getTargetTypeIsNullPredicate(targetRoot),
|
||||
cb.notEqual(targetRoot.get(JpaTarget_.targetType).get(AbstractJpaBaseEntity_.id), typeId));
|
||||
}
|
||||
|
||||
public static Specification<JpaTarget> failedActionsForRollout(final String rolloutId) {
|
||||
return (targetRoot, query, cb) -> {
|
||||
final Join<JpaTarget, Action> targetActions = targetRoot.join("actions");
|
||||
@@ -461,35 +330,6 @@ public final class TargetSpecifications {
|
||||
};
|
||||
}
|
||||
|
||||
private static Predicate getHasTagsPredicate(final Root<JpaTarget> targetRoot, final CriteriaBuilder cb,
|
||||
final Boolean selectTargetWithNoTag, final String[] tagNames) {
|
||||
final SetJoin<JpaTarget, JpaTargetTag> tags = targetRoot.join(JpaTarget_.tags, JoinType.LEFT);
|
||||
final Path<String> exp = tags.get(AbstractJpaNamedEntity_.name);
|
||||
|
||||
final List<Predicate> hasTagsPredicates = new ArrayList<>();
|
||||
if (isNoTagActive(selectTargetWithNoTag)) {
|
||||
hasTagsPredicates.add(exp.isNull());
|
||||
}
|
||||
if (isAtLeastOneTagActive(tagNames)) {
|
||||
hasTagsPredicates.add(exp.in((Object[]) tagNames));
|
||||
}
|
||||
|
||||
return hasTagsPredicates.stream().reduce(cb::or)
|
||||
.orElseThrow(() -> new RuntimeException("Neither NO_TAG, nor TAG target tag filter was provided!"));
|
||||
}
|
||||
|
||||
private static boolean isNoTagActive(final Boolean selectTargetWithNoTag) {
|
||||
return Boolean.TRUE.equals(selectTargetWithNoTag);
|
||||
}
|
||||
|
||||
private static boolean isAtLeastOneTagActive(final String[] tagNames) {
|
||||
return tagNames != null && tagNames.length > 0;
|
||||
}
|
||||
|
||||
private static Predicate getTargetTypeIsNullPredicate(final Root<JpaTarget> targetRoot) {
|
||||
return targetRoot.get(JpaTarget_.targetType).isNull();
|
||||
}
|
||||
|
||||
private static Path<Long> getDsTypeIdPath(final Root<JpaTarget> root) {
|
||||
final Join<JpaTarget, JpaTargetType> targetTypeJoin = root.join(JpaTarget_.targetType, JoinType.LEFT);
|
||||
return targetTypeJoin.join(JpaTargetType_.distributionSetTypes, JoinType.LEFT).get(AbstractJpaBaseEntity_.id);
|
||||
|
||||
@@ -31,16 +31,6 @@ import org.springframework.data.jpa.domain.Specification;
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public final class TargetTypeSpecification {
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link TargetType}s by controllerId
|
||||
*
|
||||
* @param ids to search for
|
||||
* @return the {@link TargetType} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaTargetType> hasIdIn(final Collection<Long> ids) {
|
||||
return (targetRoot, query, cb) -> targetRoot.get(AbstractJpaBaseEntity_.id).in(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link TargetType}s based on a {@link DistributionSetType} name.
|
||||
*
|
||||
@@ -73,14 +63,4 @@ public final class TargetTypeSpecification {
|
||||
public static Specification<JpaTargetType> hasName(final String name) {
|
||||
return (targetRoot, query, cb) -> cb.equal(targetRoot.get(AbstractJpaNamedEntity_.name), name);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link TargetType}s by "like name".
|
||||
*
|
||||
* @param name to be filtered on
|
||||
* @return the {@link TargetType} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaTargetType> likeName(final String name) {
|
||||
return (targetRoot, query, cb) -> cb.like(cb.lower(targetRoot.get(AbstractJpaNamedEntity_.name)), name.toLowerCase());
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,9 @@ import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
|
||||
import org.eclipse.hawkbit.im.authentication.SpPermission;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaAction_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup;
|
||||
@@ -58,14 +60,12 @@ 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.DistributionSetTag;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||
import org.eclipse.hawkbit.repository.model.TargetType;
|
||||
import org.eclipse.hawkbit.repository.model.TargetTypeAssignmentResult;
|
||||
import org.eclipse.hawkbit.repository.test.TestConfiguration;
|
||||
import org.eclipse.hawkbit.repository.test.util.AbstractIntegrationTest;
|
||||
import org.eclipse.hawkbit.repository.test.util.RolloutTestApprovalStrategy;
|
||||
@@ -191,9 +191,8 @@ public abstract class AbstractJpaIntegrationTest extends AbstractIntegrationTest
|
||||
return distributionSetManagement.unassignTag(sets.stream().map(DistributionSet::getId).toList(), tag.getId());
|
||||
}
|
||||
|
||||
protected TargetTypeAssignmentResult initiateTypeAssignment(final Collection<Target> targets, final TargetType type) {
|
||||
return targetManagement.assignType(
|
||||
targets.stream().map(Target::getControllerId).toList(), type.getId());
|
||||
protected void initiateTypeAssignment(final Collection<Target> targets, final TargetType type) {
|
||||
targets.stream().map(Target::getControllerId).forEach(id -> targetManagement.assignType(id, type.getId()));
|
||||
}
|
||||
|
||||
protected void assertRollout(final Rollout rollout, final boolean dynamic, final Rollout.RolloutStatus status, final int groupCreated,
|
||||
@@ -312,6 +311,10 @@ public abstract class AbstractJpaIntegrationTest extends AbstractIntegrationTest
|
||||
return rolloutGroupRepository.findById(group.getId()).get();
|
||||
}
|
||||
|
||||
protected static Specification<JpaAction> byDistributionSetId(final Long distributionSetId) {
|
||||
return (root, query, cb) -> cb.equal(root.get(JpaAction_.distributionSet).get(AbstractJpaBaseEntity_.id), distributionSetId);
|
||||
}
|
||||
|
||||
private JpaRollout refresh(final Rollout rollout) {
|
||||
return rolloutRepository.findById(rollout.getId()).get();
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.repository.FilterParams;
|
||||
import org.eclipse.hawkbit.repository.Identifiable;
|
||||
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
|
||||
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.AutoAssignDistributionSetUpdate;
|
||||
@@ -76,10 +75,6 @@ class TargetAccessControllerTest extends AbstractJpaIntegrationTest {
|
||||
assertThat(targetManagement.findByRsql("id==*", Pageable.unpaged()).get().map(Identifiable::getId).toList())
|
||||
.containsOnly(permittedTarget.getId());
|
||||
|
||||
// verify targetManagement#findByUpdateStatus
|
||||
assertThat(targetManagement.findByUpdateStatus(TargetUpdateStatus.REGISTERED, Pageable.unpaged()).get()
|
||||
.map(Identifiable::getId).toList()).containsOnly(permittedTarget.getId());
|
||||
|
||||
// verify targetManagement#getByControllerID
|
||||
assertThat(targetManagement.getByControllerId(permittedTarget.getControllerId())).isPresent();
|
||||
final String hiddenTargetControllerId = hiddenTarget.getControllerId();
|
||||
@@ -106,19 +101,6 @@ class TargetAccessControllerTest extends AbstractJpaIntegrationTest {
|
||||
.as("Target should not be found.")
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
});
|
||||
|
||||
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement
|
||||
.create(TargetFilterQueryManagement.Create.builder().name("test").query("id==*").build());
|
||||
|
||||
runAs(withUser("user", READ_TARGET + "/controllerId==" + permittedTarget.getControllerId()), () -> {
|
||||
// verify targetManagement#findByTargetFilterQuery
|
||||
assertThat(targetManagement.findByTargetFilterQuery(targetFilterQuery.getId(), Pageable.unpaged()).get()
|
||||
.map(Identifiable::getId).toList()).containsOnly(permittedTarget.getId());
|
||||
|
||||
// verify targetManagement#findByTargetFilterQuery (used by UI)
|
||||
assertThat(targetManagement.findByFilters(new FilterParams(null, null, null, null), Pageable.unpaged()).get()
|
||||
.map(Identifiable::getId).toList()).containsOnly(permittedTarget.getId());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -208,11 +190,6 @@ class TargetAccessControllerTest extends AbstractJpaIntegrationTest {
|
||||
.create(Create.builder().controllerId("device02").updateStatus(TargetUpdateStatus.REGISTERED).build())
|
||||
.getControllerId();
|
||||
|
||||
runAs(withUser("user", READ_TARGET + "/controllerId==" + permittedTarget.getControllerId()), () ->
|
||||
// verify targetManagement#findByUpdateStatus before assignment
|
||||
assertThat(targetManagement.findByUpdateStatus(TargetUpdateStatus.REGISTERED, Pageable.unpaged()).get()
|
||||
.map(Identifiable::getId).toList()).containsOnly(permittedTarget.getId()));
|
||||
|
||||
runAs(withUser("user",
|
||||
READ_TARGET + "/controllerId==" + permittedTarget.getControllerId(),
|
||||
UPDATE_TARGET + "/controllerId==" + permittedTarget.getControllerId(),
|
||||
@@ -221,14 +198,6 @@ class TargetAccessControllerTest extends AbstractJpaIntegrationTest {
|
||||
assertThat(assignDistributionSet(dsId, permittedTarget.getControllerId()).getAssigned()).isEqualTo(1);
|
||||
// assigning of not allowed target behaves as not found
|
||||
assertThatThrownBy(() -> assignDistributionSet(dsId, hiddenTargetControllerId)).isInstanceOf(AssertionError.class);
|
||||
|
||||
// verify targetManagement#findByUpdateStatus(REGISTERED) after assignment
|
||||
assertThat(targetManagement.findByUpdateStatus(TargetUpdateStatus.REGISTERED, Pageable.unpaged())
|
||||
.getTotalElements()).isZero();
|
||||
|
||||
// verify targetManagement#findByUpdateStatus(PENDING) after assignment
|
||||
assertThat(targetManagement.findByUpdateStatus(TargetUpdateStatus.PENDING, Pageable.unpaged()).get()
|
||||
.map(Identifiable::getId).toList()).containsOnly(permittedTarget.getId());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -145,7 +145,7 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
|
||||
verifyThatTargetsHaveDistributionSetAssignment(setB, targets.subList(10, 20), targetsCount);
|
||||
|
||||
// Count the number of targets that will be assigned with setA
|
||||
assertThat(targetManagement.countByRsqlAndNonDSAndCompatibleAndUpdatable(setA.getId(), targetFilterQuery.getQuery()))
|
||||
assertThat(targetManagement.countByRsqlAndNonDsAndCompatibleAndUpdatable(setA.getId(), targetFilterQuery.getQuery()))
|
||||
.isEqualTo(15);
|
||||
|
||||
// Run the check
|
||||
@@ -405,7 +405,7 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
|
||||
final List<Long> compatibleTargets = Stream
|
||||
.of(compatibleTargetsSingleType, compatibleTargetsMultiType, compatibleTargetsWithoutType)
|
||||
.flatMap(Collection::stream).map(Target::getId).toList();
|
||||
final long compatibleCount = targetManagement.countByRsqlAndNonDSAndCompatibleAndUpdatable(testDs.getId(),
|
||||
final long compatibleCount = targetManagement.countByRsqlAndNonDsAndCompatibleAndUpdatable(testDs.getId(),
|
||||
testFilter.getQuery());
|
||||
assertThat(compatibleCount).isEqualTo(compatibleTargets.size());
|
||||
|
||||
@@ -498,7 +498,7 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
private Slice<Action> findActionsByDistributionSet(final Pageable pageable, final long distributionSetId) {
|
||||
return actionRepository
|
||||
.findAll(ActionSpecifications.byDistributionSetId(distributionSetId), pageable)
|
||||
.findAll(byDistributionSetId(distributionSetId), pageable)
|
||||
.map(Action.class::cast);
|
||||
}
|
||||
}
|
||||
@@ -95,7 +95,7 @@ class RepositoryEntityEventTest extends AbstractJpaIntegrationTest {
|
||||
void targetDeletedEventIsPublished() throws InterruptedException {
|
||||
final Target createdTarget = testdataFactory.createTarget("12345");
|
||||
|
||||
targetManagement.deleteByControllerID("12345");
|
||||
targetManagement.deleteByControllerId("12345");
|
||||
|
||||
final TargetDeletedEvent targetDeletedEvent = eventListener.waitForEvent(TargetDeletedEvent.class);
|
||||
assertThat(targetDeletedEvent).isNotNull();
|
||||
|
||||
@@ -1788,7 +1788,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest {
|
||||
distributionSetManagement.get(distributionSetId).orElseThrow(() ->
|
||||
new EntityNotFoundException(DistributionSet.class, distributionSetId));
|
||||
return actionRepository
|
||||
.findAll(ActionSpecifications.byDistributionSetId(distributionSetId), pageable)
|
||||
.findAll(byDistributionSetId(distributionSetId), pageable)
|
||||
.map(Action.class::cast);
|
||||
}
|
||||
|
||||
|
||||
@@ -958,11 +958,12 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
expectedTargetCountStatus.put(TotalTargetCountStatus.Status.FINISHED, 9L);
|
||||
validateRolloutActionStatus(rolloutTwo.getId(), expectedTargetCountStatus);
|
||||
changeStatusForAllRunningActions(rolloutTwo, Status.FINISHED);
|
||||
final Page<Target> targetPage = targetManagement.findByUpdateStatus(TargetUpdateStatus.IN_SYNC, PAGE);
|
||||
final List<Target> targetList = targetPage.getContent();
|
||||
final List<? extends Target> targetList = findByUpdateStatus(TargetUpdateStatus.IN_SYNC, PAGE);
|
||||
// 15 targets in finished/IN_SYNC status and same DS assigned
|
||||
assertThat(targetList).hasSize(amountTargetsForRollout);
|
||||
targetList.stream().map(Target::getControllerId).map(deploymentManagement::getAssignedDistributionSet)
|
||||
targetList.stream()
|
||||
.map(Target::getControllerId)
|
||||
.map(deploymentManagement::getAssignedDistributionSet)
|
||||
.forEach(d -> assertThat(d).contains(distributionSet));
|
||||
}
|
||||
|
||||
|
||||
@@ -12,25 +12,18 @@ package org.eclipse.hawkbit.repository.jpa.management;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.hawkbit.repository.DistributionSetManagement;
|
||||
import org.eclipse.hawkbit.repository.FilterParams;
|
||||
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
|
||||
import org.eclipse.hawkbit.repository.TargetManagement;
|
||||
import org.eclipse.hawkbit.repository.TargetTagManagement;
|
||||
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
|
||||
import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||
import org.eclipse.hawkbit.repository.model.TargetType;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
@@ -39,157 +32,6 @@ import org.junit.jupiter.api.Test;
|
||||
*/
|
||||
class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
private static final String SPACE_AND_DESCRIPTION = " description";
|
||||
|
||||
/**
|
||||
* Verifies that targets with given target type are returned from repository.
|
||||
*/
|
||||
@Test
|
||||
void findTargetByTargetType() {
|
||||
final TargetType testType = testdataFactory.createTargetType("testType", Set.of(standardDsType));
|
||||
final List<Target> unassigned = testdataFactory.createTargets(9, "unassigned");
|
||||
final List<Target> assigned = testdataFactory.createTargetsWithType(11, "assigned", testType);
|
||||
|
||||
assertThat(targetManagement.findByFilters(new FilterParams(null, null, false, testType.getId()), PAGE))
|
||||
.as("Contains the targets with set type").containsAll(assigned)
|
||||
.as("and that means the following expected amount").hasSize(11);
|
||||
assertThat(targetManagement.countByFilters(new FilterParams(null, null, false, testType.getId())))
|
||||
.as("Count the targets with set type").isEqualTo(11);
|
||||
|
||||
assertThat(targetManagement.findByFilters(new FilterParams(null, null, true, null), PAGE))
|
||||
.as("Contains the targets without a type").containsAll(unassigned)
|
||||
.as("and that means the following expected amount").hasSize(9);
|
||||
assertThat(targetManagement.countByFilters(new FilterParams(null, null, true, null)))
|
||||
.as("Counts the targets without a type").isEqualTo(9);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests different parameter combinations for target search operations.
|
||||
* and query definitions by RSQL (named and un-named).
|
||||
*/
|
||||
@Test
|
||||
void targetSearchWithVariousFilterCombinations() {
|
||||
final TargetTag targTagX = targetTagManagement.create(TargetTagManagement.Create.builder().name("TargTag-X").build());
|
||||
final TargetTag targTagY = targetTagManagement.create(TargetTagManagement.Create.builder().name("TargTag-Y").build());
|
||||
final TargetTag targTagZ = targetTagManagement.create(TargetTagManagement.Create.builder().name("TargTag-Z").build());
|
||||
final TargetTag targTagW = targetTagManagement.create(TargetTagManagement.Create.builder().name("TargTag-W").build());
|
||||
|
||||
final DistributionSet setA = testdataFactory.createDistributionSet("A");
|
||||
final DistributionSet setB = testdataFactory.createDistributionSet("B");
|
||||
|
||||
final TargetType targetTypeX = testdataFactory.createTargetType("TargetTypeX", Set.of(setB.getType()));
|
||||
|
||||
final DistributionSet installedSet = testdataFactory.createDistributionSet("another");
|
||||
|
||||
final Long lastTargetQueryNotOverdue = System.currentTimeMillis();
|
||||
final Long lastTargetQueryAlwaysOverdue = 0L;
|
||||
|
||||
final String targetDsAIdPref = "targ-A";
|
||||
List<Target> targAs = testdataFactory.createTargets(100, targetDsAIdPref,
|
||||
targetDsAIdPref.concat(SPACE_AND_DESCRIPTION), lastTargetQueryNotOverdue);
|
||||
targAs = assignTag(targAs, targTagX);
|
||||
|
||||
final Target targSpecialName = targetManagement
|
||||
.update(TargetManagement.Update.builder().id(targAs.get(0).getId()).name("targ-A-special").build());
|
||||
|
||||
final String targetDsBIdPref = "targ-B";
|
||||
List<Target> targBs = testdataFactory.createTargets(100, targetDsBIdPref,
|
||||
targetDsBIdPref.concat(SPACE_AND_DESCRIPTION), lastTargetQueryAlwaysOverdue);
|
||||
|
||||
targBs = assignTag(targBs, targTagY);
|
||||
targBs = assignTag(targBs, targTagW);
|
||||
|
||||
final String targetDsCIdPref = "targ-C";
|
||||
List<Target> targCs = testdataFactory.createTargets(100, targetDsCIdPref,
|
||||
targetDsCIdPref.concat(SPACE_AND_DESCRIPTION), lastTargetQueryAlwaysOverdue);
|
||||
|
||||
targCs = assignTag(targCs, targTagZ);
|
||||
targCs = assignTag(targCs, targTagW);
|
||||
|
||||
final String targetDsDIdPref = "targ-D";
|
||||
final List<Target> targDs = testdataFactory.createTargets(100, targetDsDIdPref,
|
||||
targetDsDIdPref.concat(SPACE_AND_DESCRIPTION), null);
|
||||
|
||||
final String targetDsEIdPref = "targ-E";
|
||||
final List<Target> targEs = testdataFactory.createTargetsWithType(100, targetDsEIdPref, targetTypeX);
|
||||
|
||||
final String assignedC = targCs.iterator().next().getControllerId();
|
||||
assignDistributionSet(setA.getId(), assignedC);
|
||||
final String assignedA = targAs.iterator().next().getControllerId();
|
||||
assignDistributionSet(setA.getId(), assignedA);
|
||||
final String assignedB = targBs.iterator().next().getControllerId();
|
||||
assignDistributionSet(setA.getId(), assignedB);
|
||||
final String assignedE = targEs.iterator().next().getControllerId();
|
||||
assignDistributionSet(setB.getId(), assignedE);
|
||||
final String installedC = targCs.iterator().next().getControllerId();
|
||||
final Long actionId = getFirstAssignedActionId(assignDistributionSet(installedSet.getId(), assignedC));
|
||||
|
||||
// set one installed DS also
|
||||
controllerManagement.addUpdateActionStatus(
|
||||
entityFactory.actionStatus().create(actionId).status(Status.FINISHED).message("message"));
|
||||
assignDistributionSet(setA.getId(), installedC);
|
||||
|
||||
final List<TargetUpdateStatus> unknown = List.of(TargetUpdateStatus.UNKNOWN);
|
||||
final List<TargetUpdateStatus> pending = List.of(TargetUpdateStatus.PENDING);
|
||||
final List<TargetUpdateStatus> both = List.of(TargetUpdateStatus.UNKNOWN, TargetUpdateStatus.PENDING);
|
||||
|
||||
// get final updated version of targets
|
||||
targAs = targetManagement.getByControllerId(targAs.stream().map(Target::getControllerId).toList());
|
||||
targBs = targetManagement.getByControllerId(targBs.stream().map(Target::getControllerId).toList());
|
||||
targCs = targetManagement.getByControllerId(targCs.stream().map(Target::getControllerId).toList());
|
||||
|
||||
// try to find several targets with different filter settings
|
||||
verifyThat1TargetHasNameAndId("targ-A-special", targSpecialName.getControllerId());
|
||||
verifyThatRepositoryContains500Targets();
|
||||
verifyThat200TargetsHaveTagD(targTagW, concat(targBs, targCs));
|
||||
verifyThat100TargetsContainsGivenTextAndHaveTagAssigned(targTagY, targTagW, targBs);
|
||||
verifyThat1TargetHasTagHasDescOrNameAndDs(targTagW, setA, targetManagement.getByControllerId(assignedC).get());
|
||||
verifyThat0TargetsWithTagAndDescOrNameHasDS(targTagW, setA);
|
||||
verifyThat0TargetsWithNameOrdescAndDSHaveTag(targTagX, setA);
|
||||
verifyThat3TargetsHaveDSAssigned(setA, targetManagement.getByControllerId(Arrays.asList(assignedA, assignedB, assignedC)));
|
||||
verifyThat1TargetWithDescOrNameHasDS(setA, targetManagement.getByControllerId(assignedA).get());
|
||||
List<Target> expected = concat(targAs, targBs, targCs, targDs);
|
||||
expected.removeAll(targetManagement.getByControllerId(Arrays.asList(assignedA, assignedB, assignedC)));
|
||||
verifyThat496TargetsAreInStatusUnknown(unknown, expected);
|
||||
expected = concat(targBs, targCs);
|
||||
expected.removeAll(targetManagement.getByControllerId(Arrays.asList(assignedB, assignedC)));
|
||||
verifyThat198TargetsAreInStatusUnknownAndHaveGivenTags(targTagY, targTagW, unknown, expected);
|
||||
verifyThat0TargetsAreInStatusUnknownAndHaveDSAssigned(setA, unknown);
|
||||
expected = concat(targAs);
|
||||
expected.remove(targetManagement.getByControllerId(assignedA).get());
|
||||
verifyThat99TargetsWithNameOrDescriptionAreInGivenStatus(unknown, expected);
|
||||
expected = concat(targBs);
|
||||
expected.remove(targetManagement.getByControllerId(assignedB).get());
|
||||
verifyThat99TargetsWithGivenNameOrDescAndTagAreInStatusUnknown(targTagW, unknown, expected);
|
||||
verifyThat4TargetsAreInStatusPending(pending,
|
||||
targetManagement.getByControllerId(Arrays.asList(assignedA, assignedB, assignedC, assignedE)));
|
||||
verifyThat3TargetsWithGivenDSAreInPending(setA, pending,
|
||||
targetManagement.getByControllerId(Arrays.asList(assignedA, assignedB, assignedC)));
|
||||
verifyThat1TargetWithGivenNameOrDescAndDSIsInPending(setA, pending,
|
||||
targetManagement.getByControllerId(assignedA).get());
|
||||
verifyThat1TargetWithGivenNameOrDescAndTagAndDSIsInPending(targTagW, setA, pending,
|
||||
targetManagement.getByControllerId(assignedB).get());
|
||||
verifyThat2TargetsWithGivenTagAndDSIsInPending(targTagW, setA, pending,
|
||||
targetManagement.getByControllerId(Arrays.asList(assignedB, assignedC)));
|
||||
verifyThat2TargetsWithGivenTagAreInPending(targTagW, pending,
|
||||
targetManagement.getByControllerId(Arrays.asList(assignedB, assignedC)));
|
||||
verifyThat200targetsWithGivenTagAreInStatusPendingOrUnknown(targTagW, both, concat(targBs, targCs));
|
||||
verifyThat1TargetAIsInStatusPendingAndHasDSInstalled(installedSet, pending,
|
||||
targetManagement.getByControllerId(installedC).get());
|
||||
verifyThat1TargetHasTypeAndDSAssigned(targetTypeX, setB, targetManagement.getByControllerId(assignedE).get());
|
||||
verifyThatTargetsHasNoTypeAndDSAssignedOrInstalled(setA,
|
||||
targetManagement.getByControllerId(Arrays.asList(assignedA, assignedB, assignedC)));
|
||||
verifyThatTargetsHasNoTypeAndDSAssignedOrInstalled(installedSet,
|
||||
targetManagement.getByControllerId(Collections.singletonList(installedC)));
|
||||
verifyThat100TargetsContainsGivenTextAndHaveTypeAssigned(targetTypeX, targEs);
|
||||
verifyThat400TargetsContainsGivenTextAndHaveNoTypeAssigned(concat(targAs, targBs, targCs, targDs));
|
||||
|
||||
expected = concat(targBs, targCs);
|
||||
expected.removeAll(targetManagement.getByControllerId(Arrays.asList(assignedB, assignedC)));
|
||||
verifyThat198TargetsAreInStatusUnknownAndOverdue(unknown, expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that targets with given assigned DS are returned from repository.
|
||||
*/
|
||||
@@ -305,358 +147,4 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
|
||||
.containsExactlyInAnyOrderElementsOf(testTargets).as("does not contain incompatible targets")
|
||||
.doesNotContainAnyElementsOf(targetsWithIncompatibleType);
|
||||
}
|
||||
|
||||
private void verifyThat1TargetAIsInStatusPendingAndHasDSInstalled(final DistributionSet installedSet,
|
||||
final List<TargetUpdateStatus> pending, final Target expected) {
|
||||
final FilterParams filterParams = new FilterParams(pending, null, null, installedSet.getId(), Boolean.FALSE);
|
||||
final String query = "updatestatus==pending and installedds.name==" + installedSet.getName();
|
||||
assertThat(targetManagement.findByFilters(filterParams, PAGE).getContent()).as("has number of elements")
|
||||
.hasSize(1).as("that number is also returned by count query")
|
||||
.hasSize((int) targetManagement.countByFilters(filterParams))
|
||||
.as("and contains the following elements").containsExactly(expected)
|
||||
.as("and filter query returns the same result")
|
||||
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
|
||||
}
|
||||
|
||||
private void verifyThat200targetsWithGivenTagAreInStatusPendingOrUnknown(final TargetTag targTagW,
|
||||
final List<TargetUpdateStatus> both, final List<Target> expected) {
|
||||
final FilterParams filterParams = new FilterParams(both, null, null, null, Boolean.FALSE, targTagW.getName());
|
||||
final String query = "(updatestatus==pending or updatestatus==unknown) and tag==" + targTagW.getName();
|
||||
|
||||
assertThat(targetManagement.findByFilters(filterParams, PAGE).getContent()).as("has number of elements")
|
||||
.hasSize(200).as("that number is also returned by count query")
|
||||
.hasSize((int) targetManagement.countByFilters(filterParams))
|
||||
.as("and contains the following elements").containsAll(expected)
|
||||
.as("and filter query returns the same result")
|
||||
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
|
||||
}
|
||||
|
||||
private void verifyThat2TargetsWithGivenTagAreInPending(final TargetTag targTagW,
|
||||
final List<TargetUpdateStatus> pending, final List<Target> expected) {
|
||||
final FilterParams filterParams = new FilterParams(pending, null, null, null, Boolean.FALSE,
|
||||
targTagW.getName());
|
||||
final String query = "updatestatus==pending and tag==" + targTagW.getName();
|
||||
|
||||
assertThat(targetManagement.findByFilters(filterParams, PAGE).getContent()).as("has number of elements")
|
||||
.hasSize(2).as("that number is also returned by count query")
|
||||
.hasSize((int) targetManagement.countByFilters(filterParams))
|
||||
.as("and contains the following elements").containsAll(expected)
|
||||
.as("and filter query returns the same result")
|
||||
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
|
||||
}
|
||||
|
||||
private void verifyThat2TargetsWithGivenTagAndDSIsInPending(final TargetTag targTagW, final DistributionSet setA,
|
||||
final List<TargetUpdateStatus> pending, final List<Target> expected) {
|
||||
final FilterParams filterParams = new FilterParams(pending, null, null, setA.getId(), Boolean.FALSE,
|
||||
targTagW.getName());
|
||||
final String query = "updatestatus==pending and (assignedds.name==" + setA.getName() + " or installedds.name=="
|
||||
+ setA.getName() + ") and tag==" + targTagW.getName();
|
||||
|
||||
assertThat(targetManagement.findByFilters(filterParams, PAGE).getContent()).as("has number of elements")
|
||||
.hasSize(2).as("that number is also returned by count query")
|
||||
.hasSize((int) targetManagement.countByFilters(filterParams))
|
||||
.as("and contains the following elements").containsAll(expected)
|
||||
.as("and filter query returns the same result")
|
||||
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
|
||||
}
|
||||
|
||||
private void verifyThat1TargetWithGivenNameOrDescAndTagAndDSIsInPending(final TargetTag targTagW,
|
||||
final DistributionSet setA, final List<TargetUpdateStatus> pending, final Target expected) {
|
||||
final FilterParams filterParams = new FilterParams(pending, null, "%targ-B%", setA.getId(), Boolean.FALSE,
|
||||
targTagW.getName());
|
||||
final String query = "updatestatus==pending and (assignedds.name==" + setA.getName() + " or installedds.name=="
|
||||
+ setA.getName() + ") and (name==*targ-B* or description==*targ-B*) and tag==" + targTagW.getName();
|
||||
|
||||
assertThat(targetManagement.findByFilters(filterParams, PAGE).getContent()).as("has number of elements")
|
||||
.hasSize(1).as("that number is also returned by count query")
|
||||
.hasSize((int) targetManagement.countByFilters(filterParams))
|
||||
.as("and contains the following elements").containsExactly(expected)
|
||||
.as("and filter query returns the same result")
|
||||
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
|
||||
}
|
||||
|
||||
private void verifyThat1TargetWithGivenNameOrDescAndDSIsInPending(final DistributionSet setA,
|
||||
final List<TargetUpdateStatus> pending, final Target expected) {
|
||||
final FilterParams filterParams = new FilterParams(pending, null, "%targ-A%", setA.getId(), Boolean.FALSE);
|
||||
final String query = "updatestatus==pending and (assignedds.name==" + setA.getName() + " or installedds.name=="
|
||||
+ setA.getName() + ") and (name==*targ-A* or description==*targ-A*)";
|
||||
|
||||
assertThat(targetManagement.findByFilters(filterParams, PAGE).getContent()).as("has number of elements")
|
||||
.hasSize(1).as("that number is also returned by count query")
|
||||
.hasSize((int) targetManagement.countByFilters(filterParams))
|
||||
.as("and contains the following elements").containsExactly(expected)
|
||||
.as("and filter query returns the same result")
|
||||
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
|
||||
}
|
||||
|
||||
private void verifyThat3TargetsWithGivenDSAreInPending(final DistributionSet setA,
|
||||
final List<TargetUpdateStatus> pending, final List<Target> expected) {
|
||||
final FilterParams filterParams = new FilterParams(pending, null, null, setA.getId(), Boolean.FALSE);
|
||||
final String query = "updatestatus==pending and (assignedds.name==" + setA.getName() + " or installedds.name=="
|
||||
+ setA.getName() + ")";
|
||||
|
||||
assertThat(targetManagement.findByFilters(filterParams, PAGE).getContent()).as("has number of elements")
|
||||
.hasSize(3).as("that number is also returned by count query")
|
||||
.hasSize((int) targetManagement.countByFilters(filterParams))
|
||||
.as("and contains the following elements").containsAll(expected)
|
||||
.as("and filter query returns the same result")
|
||||
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
|
||||
}
|
||||
|
||||
private void verifyThat4TargetsAreInStatusPending(final List<TargetUpdateStatus> pending,
|
||||
final List<Target> expected) {
|
||||
final FilterParams filterParams = new FilterParams(pending, null, null, null, Boolean.FALSE);
|
||||
final String query = "updatestatus==pending";
|
||||
|
||||
assertThat(targetManagement.findByFilters(filterParams, PAGE).getContent()).as("has number of elements")
|
||||
.hasSize(4).as("that number is also returned by count query")
|
||||
.hasSize((int) targetManagement.countByFilters(filterParams))
|
||||
.as("and contains the following elements").containsAll(expected)
|
||||
.as("and filter query returns the same result")
|
||||
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
|
||||
}
|
||||
|
||||
private void verifyThat99TargetsWithGivenNameOrDescAndTagAreInStatusUnknown(final TargetTag targTagW,
|
||||
final List<TargetUpdateStatus> unknown, final List<Target> expected) {
|
||||
final FilterParams filterParams = new FilterParams(unknown, null, "%targ-B%", null, Boolean.FALSE,
|
||||
targTagW.getName());
|
||||
final String query = "updatestatus==unknown and (name==*targ-B* or description==*targ-B*) and tag=="
|
||||
+ targTagW.getName();
|
||||
|
||||
assertThat(targetManagement.findByFilters(filterParams, PAGE).getContent()).as("has number of elements")
|
||||
.hasSize(99).as("that number is also returned by count query")
|
||||
.hasSize((int) targetManagement.countByFilters(filterParams))
|
||||
.as("and contains the following elements").containsAll(expected)
|
||||
.as("and filter query returns the same result")
|
||||
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
|
||||
}
|
||||
|
||||
private void verifyThat99TargetsWithNameOrDescriptionAreInGivenStatus(final List<TargetUpdateStatus> unknown,
|
||||
final List<Target> expected) {
|
||||
final FilterParams filterParams = new FilterParams(unknown, null, "%targ-A%", null, Boolean.FALSE);
|
||||
final String query = "updatestatus==unknown and (name==*targ-A* or description==*targ-A*)";
|
||||
|
||||
assertThat(targetManagement.findByFilters(filterParams, PAGE).getContent()).as("has number of elements")
|
||||
.hasSize(99).as("that number is also returned by count query")
|
||||
.hasSize((int) targetManagement.countByFilters(filterParams))
|
||||
.as("and contains the following elements").containsAll(expected)
|
||||
.as("and filter query returns the same result")
|
||||
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
|
||||
}
|
||||
|
||||
private void verifyThat0TargetsAreInStatusUnknownAndHaveDSAssigned(final DistributionSet setA,
|
||||
final List<TargetUpdateStatus> unknown) {
|
||||
final FilterParams filterParams = new FilterParams(unknown, null, null, setA.getId(), Boolean.FALSE);
|
||||
final String query = "updatestatus==unknown and (assignedds.name==" + setA.getName() + " or installedds.name=="
|
||||
+ setA.getName() + ")";
|
||||
|
||||
assertThat(targetManagement.findByFilters(filterParams, PAGE).getContent())
|
||||
.as("that number is also returned by count query")
|
||||
.hasSize((int) targetManagement.countByFilters(filterParams))
|
||||
.as("and filter query returns the same result")
|
||||
.hasSize(targetManagement.findByRsql(query, PAGE).getContent().size())
|
||||
.as("has number of elements")
|
||||
.isEmpty();
|
||||
}
|
||||
|
||||
private void verifyThat198TargetsAreInStatusUnknownAndHaveGivenTags(final TargetTag targTagY,
|
||||
final TargetTag targTagW, final List<TargetUpdateStatus> unknown, final List<Target> expected) {
|
||||
final FilterParams filterParams = new FilterParams(unknown, null, null, null, Boolean.FALSE, targTagY.getName(),
|
||||
targTagW.getName());
|
||||
final String query = "updatestatus==unknown and (tag==" + targTagY.getName() + " or tag==" + targTagW.getName()
|
||||
+ ")";
|
||||
|
||||
assertThat(targetManagement.findByFilters(filterParams, PAGE).getContent()).as("has number of elements")
|
||||
.hasSize(198).as("that number is also returned by count query")
|
||||
.hasSize((int) targetManagement.countByFilters(filterParams))
|
||||
.as("and contains the following elements").containsAll(expected)
|
||||
.as("and filter query returns the same result")
|
||||
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
|
||||
}
|
||||
|
||||
private void verifyThat496TargetsAreInStatusUnknown(final List<TargetUpdateStatus> unknown,
|
||||
final List<Target> expected) {
|
||||
final FilterParams filterParams = new FilterParams(unknown, null, null, null, Boolean.FALSE);
|
||||
final String query = "updatestatus==unknown";
|
||||
|
||||
assertThat(targetManagement.findByFilters(filterParams, PAGE).getContent()).as("has number of elements")
|
||||
.hasSize(496).as("that number is also returned by count query")
|
||||
.hasSize((int) targetManagement.countByFilters(filterParams))
|
||||
.as("and contains the following elements").containsAll(expected)
|
||||
.as("and filter query returns the same result")
|
||||
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
|
||||
}
|
||||
|
||||
private void verifyThat198TargetsAreInStatusUnknownAndOverdue(final List<TargetUpdateStatus> unknown,
|
||||
final List<Target> expected) {
|
||||
final FilterParams filterParams = new FilterParams(unknown, Boolean.TRUE, null, null, Boolean.FALSE);
|
||||
// be careful: simple filters are concatenated using AND-gating
|
||||
final String query = "lastcontrollerrequestat=le=${overdue_ts};updatestatus==UNKNOWN";
|
||||
|
||||
assertThat(targetManagement.findByFilters(filterParams, PAGE).getContent()).as("has number of elements")
|
||||
.hasSize(198).as("that number is also returned by count query")
|
||||
.hasSize((int) targetManagement.countByFilters(filterParams))
|
||||
.as("and contains the following elements").containsAll(expected)
|
||||
.as("and filter query returns the same result")
|
||||
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
|
||||
}
|
||||
|
||||
private void verifyThat1TargetWithDescOrNameHasDS(final DistributionSet setA, final Target expected) {
|
||||
final FilterParams filterParams = new FilterParams(null, null, "%targ-A%", setA.getId(), Boolean.FALSE);
|
||||
final String query = "(name==*targ-A* or description==*targ-A*) and (assignedds.name==" + setA.getName()
|
||||
+ " or installedds.name==" + setA.getName() + ")";
|
||||
|
||||
assertThat(targetManagement.findByFilters(filterParams, PAGE).getContent()).as("has number of elements")
|
||||
.hasSize(1).as("that number is also returned by count query")
|
||||
.hasSize((int) targetManagement.countByFilters(filterParams))
|
||||
.as("and contains the following elements").containsExactly(expected)
|
||||
.as("and filter query returns the same result")
|
||||
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
|
||||
}
|
||||
|
||||
private void verifyThat3TargetsHaveDSAssigned(final DistributionSet setA, final List<Target> expected) {
|
||||
final FilterParams filterParams = new FilterParams(null, null, null, setA.getId(), Boolean.FALSE);
|
||||
final String query = "assignedds.name==" + setA.getName() + " or installedds.name==" + setA.getName();
|
||||
|
||||
assertThat(targetManagement.findByFilters(filterParams, PAGE).getContent()).as("has number of elements")
|
||||
.hasSize(3).as("that number is also returned by count query")
|
||||
.hasSize((int) targetManagement.countByFilters(filterParams))
|
||||
.as("and contains the following elements").containsAll(expected)
|
||||
.as("and filter query returns the same result")
|
||||
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
|
||||
}
|
||||
|
||||
private void verifyThat0TargetsWithNameOrdescAndDSHaveTag(final TargetTag targTagX, final DistributionSet setA) {
|
||||
final FilterParams filterParams = new FilterParams(null, null, "%targ-C%", setA.getId(), Boolean.FALSE,
|
||||
targTagX.getName());
|
||||
final String query = "(name==*targ-C* or description==*targ-C*) and tag==" + targTagX.getName()
|
||||
+ " and (assignedds.name==" + setA.getName() + " or installedds.name==" + setA.getName() + ")";
|
||||
assertThat(targetManagement.findByFilters(filterParams, PAGE).getContent())
|
||||
.as("that number is also returned by count query")
|
||||
.hasSize((int) targetManagement.countByFilters(filterParams))
|
||||
.as("and filter query returns the same result")
|
||||
.hasSize(targetManagement.findByRsql(query, PAGE).getContent().size())
|
||||
.as("has number of elements")
|
||||
.isEmpty();
|
||||
}
|
||||
|
||||
private void verifyThat0TargetsWithTagAndDescOrNameHasDS(final TargetTag targTagW, final DistributionSet setA) {
|
||||
final FilterParams filterParams = new FilterParams(null, null, "%targ-A%", setA.getId(), Boolean.FALSE,
|
||||
targTagW.getName());
|
||||
final String query = "(name==*targ-A* or description==*targ-A*) and tag==" + targTagW.getName()
|
||||
+ " and (assignedds.name==" + setA.getName() + " or installedds.name==" + setA.getName() + ")";
|
||||
assertThat(targetManagement.findByFilters(filterParams, PAGE).getContent())
|
||||
.hasSize((int) targetManagement.countByFilters(filterParams))
|
||||
.as("and filter query returns the same result")
|
||||
.hasSize(targetManagement.findByRsql(query, PAGE).getContent().size())
|
||||
.as("has number of elements")
|
||||
.isEmpty();
|
||||
}
|
||||
|
||||
private void verifyThat1TargetHasTagHasDescOrNameAndDs(final TargetTag targTagW, final DistributionSet setA,
|
||||
final Target expected) {
|
||||
final FilterParams filterParams = new FilterParams(null, null, "%targ-C%", setA.getId(), Boolean.FALSE,
|
||||
targTagW.getName());
|
||||
final String query = "(name==*targ-c* or description==*targ-C*) and tag==" + targTagW.getName()
|
||||
+ " and (assignedds.name==" + setA.getName() + " or installedds.name==" + setA.getName() + ")";
|
||||
assertThat(targetManagement.findByFilters(filterParams, PAGE).getContent()).as("has number of elements")
|
||||
.hasSize(1).as("that number is also returned by count query")
|
||||
.hasSize((int) targetManagement.countByFilters(filterParams))
|
||||
.as("and contains the following elements").containsExactly(expected)
|
||||
.as("and filter query returns the same result")
|
||||
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
|
||||
}
|
||||
|
||||
private void verifyThat1TargetHasNameAndId(final String name, final String controllerId) {
|
||||
final FilterParams filterParamsByName = new FilterParams(null, null, name, null, Boolean.FALSE);
|
||||
assertThat(targetManagement.findByFilters(filterParamsByName, PAGE).getContent()).as("has number of elements")
|
||||
.hasSize(1).as("that number is also returned by count query")
|
||||
.hasSize((int) targetManagement.countByFilters(filterParamsByName));
|
||||
|
||||
final FilterParams filterParamsByControllerId = new FilterParams(null, null, controllerId, null, Boolean.FALSE);
|
||||
assertThat(targetManagement.findByFilters(filterParamsByControllerId, PAGE).getContent())
|
||||
.as("has number of elements").hasSize(1).as("that number is also returned by count query")
|
||||
.hasSize((int) targetManagement.countByFilters(filterParamsByControllerId));
|
||||
}
|
||||
|
||||
private void verifyThat100TargetsContainsGivenTextAndHaveTagAssigned(final TargetTag targTagY,
|
||||
final TargetTag targTagW, final List<Target> expected) {
|
||||
final FilterParams filterParams = new FilterParams(null, null, "%targ-B%", null, Boolean.FALSE,
|
||||
targTagY.getName(), targTagW.getName());
|
||||
final String query = "(name==*targ-B* or description==*targ-B*) and (tag==" + targTagY.getName() + " or tag=="
|
||||
+ targTagW.getName() + ")";
|
||||
assertThat(targetManagement.findByFilters(filterParams, PAGE).getContent()).as("has number of elements")
|
||||
.hasSize(100).as("that number is also returned by count query")
|
||||
.hasSize((int) targetManagement.countByFilters(filterParams))
|
||||
.as("and contains the following elements").containsAll(expected)
|
||||
.as("and filter query returns the same result")
|
||||
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
private List<Target> concat(final List<Target>... targets) {
|
||||
final List<Target> result = new ArrayList<>();
|
||||
Arrays.asList(targets).forEach(result::addAll);
|
||||
return result;
|
||||
}
|
||||
|
||||
private void verifyThat200TargetsHaveTagD(final TargetTag targTagD, final List<Target> expected) {
|
||||
final FilterParams filterParams = new FilterParams(null, null, null, null, Boolean.FALSE, targTagD.getName());
|
||||
final String query = "tag==" + targTagD.getName();
|
||||
assertThat(targetManagement.findByFilters(filterParams, PAGE).getContent()).as("Expected number of results is")
|
||||
.hasSize(200).as("and is expected number of results is equal to ")
|
||||
.hasSize((int) targetManagement.countByFilters(filterParams))
|
||||
.as("and contains the following elements").containsAll(expected)
|
||||
.as("and filter query returns the same result")
|
||||
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
|
||||
}
|
||||
|
||||
private void verifyThatRepositoryContains500Targets() {
|
||||
final FilterParams filterParams = new FilterParams(null, null, null, null, null);
|
||||
assertThat(targetManagement.findByFilters(filterParams, PAGE).getContent())
|
||||
.as("Overall we expect that many targets in the repository").hasSize(500)
|
||||
.as("which is also reflected by repository count").hasSize((int) targetManagement.count())
|
||||
.as("which is also reflected by call without specification")
|
||||
.containsAll(targetManagement.findAll(PAGE).getContent());
|
||||
}
|
||||
|
||||
private void verifyThat1TargetHasTypeAndDSAssigned(final TargetType type, final DistributionSet set,
|
||||
final Target expected) {
|
||||
final FilterParams filterParams = new FilterParams(null, set.getId(), Boolean.FALSE, type.getId());
|
||||
assertThat(targetManagement.findByFilters(filterParams, PAGE).getContent()).as("has number of elements")
|
||||
.hasSize(1).as("that number is also returned by count query")
|
||||
.hasSize((int) targetManagement.countByFilters(filterParams))
|
||||
.as("and contains the following elements").containsExactly(expected);
|
||||
}
|
||||
|
||||
private void verifyThatTargetsHasNoTypeAndDSAssignedOrInstalled(final DistributionSet set,
|
||||
final List<Target> expected) {
|
||||
final FilterParams filterParams = new FilterParams(null, set.getId(), Boolean.TRUE, null);
|
||||
assertThat(targetManagement.findByFilters(filterParams, PAGE).getContent()).as("has number of elements")
|
||||
.hasSize(expected.size()).as("that number is also returned by count query")
|
||||
.hasSize((int) targetManagement.countByFilters(filterParams))
|
||||
.as("and contains the following elements").containsAll(expected);
|
||||
}
|
||||
|
||||
private void verifyThat100TargetsContainsGivenTextAndHaveTypeAssigned(final TargetType targetType,
|
||||
final List<Target> expected) {
|
||||
final FilterParams filterParams = new FilterParams("%targ-E%", null, Boolean.FALSE, targetType.getId());
|
||||
final List<Target> filteredTargets = targetManagement.findByFilters(filterParams, PAGE).getContent();
|
||||
assertThat(filteredTargets).as("has number of elements").hasSize(100)
|
||||
.as("that number is also returned by count query")
|
||||
.hasSize((int) targetManagement.countByFilters(filterParams));
|
||||
// Comparing the controller ids, as one of the targets was modified, so
|
||||
// a 1:1
|
||||
// comparison of the objects is not possible
|
||||
assertThat(filteredTargets.stream().map(Target::getControllerId).toList())
|
||||
.containsAll(expected.stream().map(Target::getControllerId).toList());
|
||||
}
|
||||
|
||||
private void verifyThat400TargetsContainsGivenTextAndHaveNoTypeAssigned(final List<Target> expected) {
|
||||
final FilterParams filterParams = new FilterParams("%targ-%", null, Boolean.TRUE, null);
|
||||
assertThat(targetManagement.findByFilters(filterParams, PAGE).getContent()).as("has number of elements")
|
||||
.hasSize(400).as("that number is also returned by count query")
|
||||
.hasSize((int) targetManagement.countByFilters(filterParams))
|
||||
.as("and contains the following elements").containsAll(expected);
|
||||
}
|
||||
}
|
||||
@@ -14,11 +14,9 @@ import java.util.Map;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.hawkbit.im.authentication.SpPermission;
|
||||
import org.eclipse.hawkbit.repository.FilterParams;
|
||||
import org.eclipse.hawkbit.repository.TargetManagement.Create;
|
||||
import org.eclipse.hawkbit.repository.TargetManagement.Update;
|
||||
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.eclipse.hawkbit.repository.test.util.WithUser;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -29,42 +27,6 @@ import org.junit.jupiter.api.Test;
|
||||
@Slf4j
|
||||
class TargetManagementSecurityTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
/**
|
||||
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
|
||||
*/
|
||||
@Test
|
||||
void countByAssignedDistributionSetPermissionsCheck() {
|
||||
assertPermissions(() -> targetManagement.countByAssignedDistributionSet(1L),
|
||||
List.of(SpPermission.READ_TARGET, SpPermission.READ_REPOSITORY));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
|
||||
*/
|
||||
@Test
|
||||
void countByFiltersPermissionsCheck() {
|
||||
assertPermissions(() -> targetManagement.countByFilters(new FilterParams(null, null, null, null, null, null)),
|
||||
List.of(SpPermission.READ_TARGET));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
|
||||
*/
|
||||
@Test
|
||||
void countByInstalledDistributionSetPermissionsCheck() {
|
||||
assertPermissions(() -> targetManagement.countByInstalledDistributionSet(1L),
|
||||
List.of(SpPermission.READ_TARGET, SpPermission.READ_REPOSITORY));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
|
||||
*/
|
||||
@Test
|
||||
void existsByInstalledOrAssignedDistributionSetPermissionsCheck() {
|
||||
assertPermissions(() -> targetManagement.existsByInstalledOrAssignedDistributionSet(1L),
|
||||
List.of(SpPermission.READ_TARGET, SpPermission.READ_REPOSITORY));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
|
||||
*/
|
||||
@@ -73,14 +35,6 @@ class TargetManagementSecurityTest extends AbstractJpaIntegrationTest {
|
||||
assertPermissions(() -> targetManagement.countByRsql("controllerId==id"), List.of(SpPermission.READ_TARGET));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
|
||||
*/
|
||||
@Test
|
||||
void countByRsqlAndUpdatablePermissionsCheck() {
|
||||
assertPermissions(() -> targetManagement.countByRsqlAndUpdatable("controllerId==id"), List.of(SpPermission.READ_TARGET));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
|
||||
*/
|
||||
@@ -138,21 +92,13 @@ class TargetManagementSecurityTest extends AbstractJpaIntegrationTest {
|
||||
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
|
||||
*/
|
||||
@Test
|
||||
void deleteByControllerIDPermissionsCheck() {
|
||||
void deleteByControllerIdPermissionsCheck() {
|
||||
assertPermissions(() -> {
|
||||
targetManagement.deleteByControllerID("controllerId");
|
||||
targetManagement.deleteByControllerId("controllerId");
|
||||
return null;
|
||||
}, List.of(SpPermission.DELETE_TARGET));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
|
||||
*/
|
||||
@Test
|
||||
void countByTargetFilterQueryPermissionsCheck() {
|
||||
assertPermissions(() -> targetManagement.countByTargetFilterQuery(1L), List.of(SpPermission.READ_TARGET));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
|
||||
*/
|
||||
@@ -166,8 +112,8 @@ class TargetManagementSecurityTest extends AbstractJpaIntegrationTest {
|
||||
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
|
||||
*/
|
||||
@Test
|
||||
void countByRsqlAndNonDSAndCompatibleAndUpdatablePermissionsCheck() {
|
||||
assertPermissions(() -> targetManagement.countByRsqlAndNonDSAndCompatibleAndUpdatable(1L, "controllerId==id"),
|
||||
void countByRsqlAndNonDsAndCompatibleAndUpdatablePermissionsCheck() {
|
||||
assertPermissions(() -> targetManagement.countByRsqlAndNonDsAndCompatibleAndUpdatable(1L, "controllerId==id"),
|
||||
List.of(SpPermission.READ_TARGET, SpPermission.READ_REPOSITORY));
|
||||
}
|
||||
|
||||
@@ -262,15 +208,6 @@ class TargetManagementSecurityTest extends AbstractJpaIntegrationTest {
|
||||
assertPermissions(() -> targetManagement.getByControllerId("controllerId"), List.of(SpPermission.READ_TARGET));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
|
||||
*/
|
||||
@Test
|
||||
void findByFiltersPermissionsCheck() {
|
||||
assertPermissions(() -> targetManagement.findByFilters(new FilterParams(null, null, null, null, null, null), PAGE),
|
||||
List.of(SpPermission.READ_TARGET));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
|
||||
*/
|
||||
@@ -289,14 +226,6 @@ class TargetManagementSecurityTest extends AbstractJpaIntegrationTest {
|
||||
List.of(SpPermission.READ_TARGET, SpPermission.READ_REPOSITORY));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
|
||||
*/
|
||||
@Test
|
||||
void findByUpdateStatusPermissionsCheck() {
|
||||
assertPermissions(() -> targetManagement.findByUpdateStatus(TargetUpdateStatus.IN_SYNC, PAGE), List.of(SpPermission.READ_TARGET));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
|
||||
*/
|
||||
@@ -313,14 +242,6 @@ class TargetManagementSecurityTest extends AbstractJpaIntegrationTest {
|
||||
assertPermissions(() -> targetManagement.findByRsql("controllerId==id", PAGE), List.of(SpPermission.READ_TARGET));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
|
||||
*/
|
||||
@Test
|
||||
void findByTargetFilterQueryPermissionsCheck() {
|
||||
assertPermissions(() -> targetManagement.findByTargetFilterQuery(1L, PAGE), List.of(SpPermission.READ_TARGET));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
|
||||
*/
|
||||
@@ -337,14 +258,6 @@ class TargetManagementSecurityTest extends AbstractJpaIntegrationTest {
|
||||
assertPermissions(() -> targetManagement.findByRsqlAndTag("controllerId==id", 1L, PAGE), List.of(SpPermission.READ_TARGET));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
|
||||
*/
|
||||
@Test
|
||||
void assignTypePermissionsCheck() {
|
||||
assertPermissions(() -> targetManagement.assignType(List.of("controllerId"), 1L), List.of(SpPermission.UPDATE_TARGET));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
|
||||
*/
|
||||
@@ -388,14 +301,6 @@ class TargetManagementSecurityTest extends AbstractJpaIntegrationTest {
|
||||
List.of(SpPermission.UPDATE_TARGET, SpPermission.READ_REPOSITORY));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
|
||||
*/
|
||||
@Test
|
||||
void unassignTypePermissionsCheck() {
|
||||
assertPermissions(() -> targetManagement.unassignType(List.of("controllerId")), List.of(SpPermission.UPDATE_TARGET));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
|
||||
*/
|
||||
@@ -428,14 +333,6 @@ class TargetManagementSecurityTest extends AbstractJpaIntegrationTest {
|
||||
assertPermissions(() -> targetManagement.get(List.of(1L)), List.of(SpPermission.READ_TARGET));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
|
||||
*/
|
||||
@Test
|
||||
void existsByControllerIdPermissionsCheck() {
|
||||
assertPermissions(() -> targetManagement.existsByControllerId("controllerId"), List.of(SpPermission.READ_TARGET));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
|
||||
*/
|
||||
@@ -462,33 +359,6 @@ class TargetManagementSecurityTest extends AbstractJpaIntegrationTest {
|
||||
assertPermissions(() -> targetManagement.getControllerAttributes("controllerId"), List.of(SpPermission.READ_TARGET));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
|
||||
*/
|
||||
@Test
|
||||
void requestControllerAttributesPermissionsCheck() {
|
||||
assertPermissions(() -> {
|
||||
targetManagement.requestControllerAttributes("controllerId");
|
||||
return null;
|
||||
}, List.of(SpPermission.UPDATE_TARGET));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
|
||||
*/
|
||||
@Test
|
||||
void isControllerAttributesRequestedPermissionsCheck() {
|
||||
assertPermissions(() -> targetManagement.isControllerAttributesRequested("controllerId"), List.of(SpPermission.READ_TARGET));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
|
||||
*/
|
||||
@Test
|
||||
void findByControllerAttributesRequestedPermissionsCheck() {
|
||||
assertPermissions(() -> targetManagement.findByControllerAttributesRequested(PAGE), List.of(SpPermission.READ_TARGET));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
|
||||
*/
|
||||
|
||||
@@ -26,13 +26,18 @@ import java.util.NoSuchElementException;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||
import jakarta.persistence.criteria.JoinType;
|
||||
import jakarta.persistence.criteria.Path;
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
import jakarta.persistence.criteria.Root;
|
||||
import jakarta.persistence.criteria.SetJoin;
|
||||
import jakarta.validation.ConstraintViolationException;
|
||||
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.awaitility.Awaitility;
|
||||
import org.eclipse.hawkbit.im.authentication.SpPermission;
|
||||
import org.eclipse.hawkbit.im.authentication.SpRole;
|
||||
import org.eclipse.hawkbit.repository.FilterParams;
|
||||
import org.eclipse.hawkbit.repository.Identifiable;
|
||||
import org.eclipse.hawkbit.repository.TargetManagement.Create;
|
||||
import org.eclipse.hawkbit.repository.TargetManagement.Update;
|
||||
@@ -54,12 +59,16 @@ import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.InvalidTargetAddressException;
|
||||
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.JpaManagementHelper;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaNamedEntity_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
@@ -70,9 +79,7 @@ import org.eclipse.hawkbit.repository.model.Tag;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||
import org.eclipse.hawkbit.repository.model.TargetType;
|
||||
import org.eclipse.hawkbit.repository.model.TargetTypeAssignmentResult;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility;
|
||||
import org.eclipse.hawkbit.repository.test.matcher.Expect;
|
||||
import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
|
||||
import org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch;
|
||||
@@ -81,6 +88,7 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
|
||||
/**
|
||||
* Feature: Component Tests - Repository<br/>
|
||||
@@ -91,7 +99,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
private static final String WHITESPACE_ERROR = "target with whitespaces in controller id should not be created";
|
||||
|
||||
/**
|
||||
* Verifies that management get access react as specified on calls for non existing entities by means
|
||||
* Verifies that management get access react as specified on calls for non existing entities by means
|
||||
* of Optional not present.
|
||||
*/
|
||||
@Test
|
||||
@@ -104,8 +112,8 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that management queries react as specified on calls for non existing entities
|
||||
* by means of throwing EntityNotFoundException.
|
||||
* Verifies that management queries react as specified on calls for non existing entities
|
||||
* by means of throwing EntityNotFoundException.
|
||||
*/
|
||||
@Test
|
||||
@ExpectEvents({
|
||||
@@ -122,15 +130,10 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
verifyThrownExceptionBy(() -> targetManagement.findByTag(NOT_EXIST_IDL, PAGE), "TargetTag");
|
||||
verifyThrownExceptionBy(() -> targetManagement.findByRsqlAndTag("name==*", NOT_EXIST_IDL, PAGE), "TargetTag");
|
||||
|
||||
verifyThrownExceptionBy(() -> targetManagement.countByAssignedDistributionSet(NOT_EXIST_IDL), "DistributionSet");
|
||||
verifyThrownExceptionBy(() -> targetManagement.countByInstalledDistributionSet(NOT_EXIST_IDL), "DistributionSet");
|
||||
verifyThrownExceptionBy(() -> targetManagement.existsByInstalledOrAssignedDistributionSet(NOT_EXIST_IDL), "DistributionSet");
|
||||
|
||||
verifyThrownExceptionBy(() -> targetManagement.countByTargetFilterQuery(NOT_EXIST_IDL), "TargetFilterQuery");
|
||||
verifyThrownExceptionBy(() -> targetManagement.countByRsqlAndNonDSAndCompatibleAndUpdatable(NOT_EXIST_IDL, "name==*"),
|
||||
verifyThrownExceptionBy(() -> targetManagement.countByRsqlAndNonDsAndCompatibleAndUpdatable(NOT_EXIST_IDL, "name==*"),
|
||||
"DistributionSet");
|
||||
|
||||
verifyThrownExceptionBy(() -> targetManagement.deleteByControllerID(NOT_EXIST_ID), "Target");
|
||||
verifyThrownExceptionBy(() -> targetManagement.deleteByControllerId(NOT_EXIST_ID), "Target");
|
||||
verifyThrownExceptionBy(() -> targetManagement.delete(Collections.singletonList(NOT_EXIST_IDL)), "Target");
|
||||
|
||||
verifyThrownExceptionBy(
|
||||
@@ -166,7 +169,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
*/
|
||||
@Test
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1) })
|
||||
void getTargetSecurityTokenOnlyWithCorrectPermission() throws Exception {
|
||||
void getTargetSecurityTokenOnlyWithCorrectPermission() {
|
||||
final Target createdTarget = targetManagement
|
||||
.create(Create.builder().controllerId("targetWithSecurityToken").securityToken("token").build());
|
||||
|
||||
@@ -280,10 +283,8 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
target = createTargetWithAttributes("4711");
|
||||
assertThat(targetManagement.count()).as("target count is wrong").isEqualTo(1);
|
||||
assertThat(targetManagement.existsByControllerId("4711")).isTrue();
|
||||
targetManagement.delete(Collections.singletonList(target.getId()));
|
||||
assertThat(targetManagement.count()).as("target count is wrong").isZero();
|
||||
assertThat(targetManagement.existsByControllerId("4711")).isFalse();
|
||||
|
||||
final List<Long> targets = new ArrayList<>();
|
||||
for (int i = 0; i < 5; i++) {
|
||||
@@ -316,19 +317,6 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
final DistributionSet testDs1 = testdataFactory.createDistributionSet("test");
|
||||
final DistributionSet testDs2 = testdataFactory.createDistributionSet("test2");
|
||||
|
||||
assertThat(targetManagement.countByAssignedDistributionSet(testDs1.getId()))
|
||||
.as("For newly created distributions sets the assigned target count should be zero").isZero();
|
||||
assertThat(targetManagement.countByInstalledDistributionSet(testDs1.getId()))
|
||||
.as("For newly created distributions sets the installed target count should be zero").isZero();
|
||||
assertThat(targetManagement.existsByInstalledOrAssignedDistributionSet(testDs1.getId()))
|
||||
.as("Exists assigned or installed query should return false for new distribution sets").isFalse();
|
||||
assertThat(targetManagement.countByAssignedDistributionSet(testDs2.getId()))
|
||||
.as("For newly created distributions sets the assigned target count should be zero").isZero();
|
||||
assertThat(targetManagement.countByInstalledDistributionSet(testDs2.getId()))
|
||||
.as("For newly created distributions sets the installed target count should be zero").isZero();
|
||||
assertThat(targetManagement.existsByInstalledOrAssignedDistributionSet(testDs2.getId()))
|
||||
.as("For newly created distributions sets the assigned target count should be zero").isFalse();
|
||||
|
||||
createTargetWithAttributes("4711");
|
||||
|
||||
final long current = System.currentTimeMillis();
|
||||
@@ -344,19 +332,6 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
Target target = targetManagement.getByControllerId("4711").orElseThrow(IllegalStateException::new);
|
||||
// read data
|
||||
|
||||
assertThat(targetManagement.countByAssignedDistributionSet(testDs1.getId())).as("Target count is wrong")
|
||||
.isZero();
|
||||
assertThat(targetManagement.countByInstalledDistributionSet(testDs1.getId())).as("Target count is wrong")
|
||||
.isEqualTo(1);
|
||||
assertThat(targetManagement.existsByInstalledOrAssignedDistributionSet(testDs1.getId()))
|
||||
.as("Target count is wrong").isTrue();
|
||||
assertThat(targetManagement.countByAssignedDistributionSet(testDs2.getId())).as("Target count is wrong")
|
||||
.isEqualTo(1);
|
||||
assertThat(targetManagement.countByInstalledDistributionSet(testDs2.getId())).as("Target count is wrong")
|
||||
.isZero();
|
||||
assertThat(targetManagement.existsByInstalledOrAssignedDistributionSet(testDs2.getId()))
|
||||
.as("Target count is wrong").isTrue();
|
||||
assertThat(target.getLastTargetQuery()).as("Target query is not work").isGreaterThanOrEqualTo(current);
|
||||
|
||||
final DistributionSet assignedDs = deploymentManagement.getAssignedDistributionSet("4711")
|
||||
@@ -401,8 +376,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@ExpectEvents({
|
||||
@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1) })
|
||||
void singleTargetIsInsertedIntoRepo() throws Exception {
|
||||
|
||||
void singleTargetIsInsertedIntoRepo() {
|
||||
final String myCtrlID = "myCtrlID";
|
||||
|
||||
Target savedTarget = testdataFactory.createTarget(myCtrlID);
|
||||
@@ -482,7 +456,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
}
|
||||
|
||||
targetManagement.deleteByControllerID(extra.getControllerId());
|
||||
targetManagement.deleteByControllerId(extra.getControllerId());
|
||||
|
||||
final int numberToDelete = 50;
|
||||
final Collection<? extends Target> targetsToDelete = firstList.subList(0, numberToDelete);
|
||||
@@ -495,7 +469,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
assertThat(firstList.spliterator().getExactSizeIfKnown() - numberToDelete).as("Size of split list")
|
||||
.isEqualTo(targetsLeft.spliterator().getExactSizeIfKnown());
|
||||
|
||||
Assertions.<Target>assertThat(targetsLeft).as("Not all undeleted found").doesNotContain(deletedTargets);
|
||||
Assertions.<Target> assertThat(targetsLeft).as("Not all undeleted found").doesNotContain(deletedTargets);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -567,7 +541,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
assignTag(tagABCTargets, tagB);
|
||||
assignTag(tagABCTargets, tagC);
|
||||
|
||||
assertThat(targetManagement.countByFilters(new FilterParams(null, null, null, null, Boolean.FALSE, "X")))
|
||||
assertThat(countByFilters(new FilterParams(Boolean.FALSE, "X")))
|
||||
.as("Target count is wrong").isZero();
|
||||
|
||||
// search for targets with tag tagA
|
||||
@@ -597,11 +571,11 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
checkTargetHasNotTags(tagCTargets, tagA, tagB);
|
||||
|
||||
// check again target lists refreshed from DB
|
||||
assertThat(targetManagement.countByFilters(new FilterParams(null, null, null, null, Boolean.FALSE, "A")))
|
||||
assertThat(countByFilters(new FilterParams(Boolean.FALSE, "A")))
|
||||
.as("Target count is wrong").isEqualTo(targetWithTagA.size());
|
||||
assertThat(targetManagement.countByFilters(new FilterParams(null, null, null, null, Boolean.FALSE, "B")))
|
||||
assertThat(countByFilters(new FilterParams(Boolean.FALSE, "B")))
|
||||
.as("Target count is wrong").isEqualTo(targetWithTagB.size());
|
||||
assertThat(targetManagement.countByFilters(new FilterParams(null, null, null, null, Boolean.FALSE, "C")))
|
||||
assertThat(countByFilters(new FilterParams(Boolean.FALSE, "C")))
|
||||
.as("Target count is wrong").isEqualTo(targetWithTagC.size());
|
||||
}
|
||||
|
||||
@@ -682,12 +656,10 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
testdataFactory.createTargets(25, "target-id-B", "first description");
|
||||
|
||||
final String[] tagNames = null;
|
||||
final List<Target> targetsListWithNoTag = targetManagement
|
||||
.findByFilters(new FilterParams(null, null, null, null, Boolean.TRUE, tagNames), PAGE).getContent();
|
||||
final long targetsListWithNoTag = countByFilters(new FilterParams(Boolean.TRUE, tagNames));
|
||||
|
||||
assertThat(targetManagement.count()).as("Total targets").isEqualTo(50L);
|
||||
assertThat(targetsListWithNoTag).as("Targets with no tag").hasSize(25);
|
||||
|
||||
assertThat(targetsListWithNoTag).as("Targets with no tag").isEqualTo(25);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -758,16 +730,11 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
void verifyRequestControllerAttributes() {
|
||||
final String knownControllerId = "KnownControllerId";
|
||||
final Target target = createTargetWithAttributes(knownControllerId);
|
||||
|
||||
assertThat(targetManagement.findByControllerAttributesRequested(PAGE)).isEmpty();
|
||||
assertThat(targetManagement.isControllerAttributesRequested(knownControllerId)).isFalse();
|
||||
|
||||
targetManagement.requestControllerAttributes(knownControllerId);
|
||||
final Target updated = targetManagement.getByControllerId(knownControllerId).get();
|
||||
|
||||
assertThat(target.isRequestControllerAttributes()).isFalse();
|
||||
assertThat(targetManagement.findByControllerAttributesRequested(PAGE).getContent()).contains(updated);
|
||||
assertThat(targetManagement.isControllerAttributesRequested(knownControllerId)).isTrue();
|
||||
|
||||
targetManagement.update(Update.builder().id(target.getId()).requestControllerAttributes(true).build());
|
||||
final Target updated = targetManagement.getByControllerId(knownControllerId).orElseThrow();
|
||||
assertThat(updated.isRequestControllerAttributes()).isTrue();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -949,8 +916,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@ExpectEvents({
|
||||
@Expect(type = TargetCreatedEvent.class, count = 20),
|
||||
@Expect(type = TargetTypeCreatedEvent.class, count = 2),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 29),
|
||||
@Expect(type = TargetDeletedEvent.class, count = 1) })
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 20) })
|
||||
void targetTypeBulkAssignments() {
|
||||
final List<Target> typeATargets = testdataFactory.createTargets(10, "typeATargets", "first description");
|
||||
final List<Target> typeBTargets = testdataFactory.createTargets(10, "typeBTargets", "first description");
|
||||
@@ -960,30 +926,16 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
final TargetType typeB = testdataFactory.createTargetType("B", Set.of(standardDsType));
|
||||
|
||||
// assign target type to target
|
||||
TargetTypeAssignmentResult resultA = initiateTypeAssignment(typeATargets, typeA);
|
||||
TargetTypeAssignmentResult resultB = initiateTypeAssignment(typeBTargets, typeB);
|
||||
assertThat(resultA.getAssigned()).isEqualTo(10);
|
||||
assertThat(resultB.getAssigned()).isEqualTo(10);
|
||||
initiateTypeAssignment(typeATargets, typeA);
|
||||
initiateTypeAssignment(typeBTargets, typeB);
|
||||
checkTargetsHaveType(typeATargets, typeA);
|
||||
checkTargetsHaveType(typeBTargets, typeB);
|
||||
|
||||
// double assignment does not unassign
|
||||
resultA = initiateTypeAssignment(typeATargets, typeA);
|
||||
resultB = initiateTypeAssignment(typeBTargets, typeB);
|
||||
assertThat(resultA.getAssigned()).isZero();
|
||||
assertThat(resultB.getAssigned()).isZero();
|
||||
assertThat(resultA.getAlreadyAssigned()).isEqualTo(10);
|
||||
assertThat(resultB.getAlreadyAssigned()).isEqualTo(10);
|
||||
initiateTypeAssignment(typeATargets, typeA);
|
||||
initiateTypeAssignment(typeBTargets, typeB);
|
||||
checkTargetsHaveType(typeATargets, typeA);
|
||||
checkTargetsHaveType(typeBTargets, typeB);
|
||||
|
||||
// verify that type assignment does not throw an error if target list
|
||||
// includes an unknown id
|
||||
targetManagement.deleteByControllerID(typeATargets.get(0).getControllerId());
|
||||
final TargetTypeAssignmentResult resultC = initiateTypeAssignment(typeATargets, typeB);
|
||||
assertThat(resultC.getAssigned()).isEqualTo(9);
|
||||
assertThat(resultC.getAlreadyAssigned()).isZero();
|
||||
checkTargetsHaveType(typeATargets, typeB);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1170,13 +1122,11 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet();
|
||||
|
||||
assertThat(targetManagement.isTargetMatchingQueryAndDSNotAssignedAndCompatibleAndUpdatable(
|
||||
"notExisting", ds.getId(),"name==*")).isFalse();
|
||||
"notExisting", ds.getId(), "name==*")).isFalse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests action based aspects of the dynamic group assignment filters.
|
||||
*/
|
||||
/**
|
||||
* Target matches filter no active action with ge weight.
|
||||
*/
|
||||
@Test
|
||||
@@ -1344,6 +1294,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
.as("target with too long address should not be updated")
|
||||
.isThrownBy(() -> targetManagement.update(targetUpdate));
|
||||
}
|
||||
|
||||
private void createTargetWithInvalidControllerId() {
|
||||
final Create targetCreateEmpty = Create.builder().controllerId("").build();
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
@@ -1424,8 +1375,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
private void checkTargetHasNotTags(final Iterable<Target> targets, final TargetTag... tags) {
|
||||
for (final Target tl : targets) {
|
||||
targetManagement.getByControllerId(tl.getControllerId()).get();
|
||||
|
||||
targetManagement.getByControllerId(tl.getControllerId()).orElseThrow();
|
||||
for (final Tag tag : tags) {
|
||||
for (final Tag tt : getTargetTags(tl.getControllerId())) {
|
||||
if (tag.getName().equals(tt.getName())) {
|
||||
@@ -1438,7 +1388,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
private void insertMetadata(final String knownKey, final String knownValue, final Target target) {
|
||||
targetManagement.createMetadata(target.getControllerId(), Map.of(knownKey, knownValue));
|
||||
assertThat(targetManagement.getMetadata(target.getControllerId()).get(knownKey)).isEqualTo(knownValue);
|
||||
assertThat(targetManagement.getMetadata(target.getControllerId())).containsEntry(knownKey, knownValue);
|
||||
}
|
||||
|
||||
private void checkTargetsHaveType(final List<Target> targets, final TargetType type) {
|
||||
@@ -1461,14 +1411,11 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
return target;
|
||||
}
|
||||
|
||||
private Target createTargetWithTargetTypeAndMetadata(final String controllerId, final TargetType targetType, final int count) {
|
||||
private void createTargetWithTargetTypeAndMetadata(final String controllerId, final TargetType targetType, final int count) {
|
||||
final Target target = testdataFactory.createTarget(controllerId, controllerId, targetType);
|
||||
|
||||
for (int index = 1; index <= count; index++) {
|
||||
insertMetadata("key" + index, controllerId + "-value" + index, target);
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
private void createAction(final Target target, final Rollout rollout, final Integer weight, final Action.Status status,
|
||||
@@ -1499,4 +1446,65 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
assertThat(foundTargetsByMetadataAndControllerId.getContent().stream().map(Target::getControllerId))
|
||||
.as("Targets found by RSQL filter have wrong controller ids").containsExactlyInAnyOrder(controllerIds);
|
||||
}
|
||||
}
|
||||
|
||||
private long countByFilters(final FilterParams filterParams) {
|
||||
final List<Specification<JpaTarget>> specList = buildSpecificationList(filterParams);
|
||||
return JpaManagementHelper.countBySpec(targetRepository, specList);
|
||||
}
|
||||
|
||||
private List<Specification<JpaTarget>> buildSpecificationList(final FilterParams filterParams) {
|
||||
final List<Specification<JpaTarget>> specList = new ArrayList<>();
|
||||
if (hasTagsFilterActive(filterParams)) {
|
||||
specList.add(hasTags(filterParams.filterByTagNames(), filterParams.selectTargetWithNoTag()));
|
||||
}
|
||||
return specList;
|
||||
}
|
||||
|
||||
private static boolean hasTagsFilterActive(final FilterParams filterParams) {
|
||||
final boolean isNoTagActive = Boolean.TRUE.equals(filterParams.selectTargetWithNoTag());
|
||||
final boolean isAtLeastOneTagActive = filterParams.filterByTagNames() != null && filterParams.filterByTagNames().length > 0;
|
||||
return isNoTagActive || isAtLeastOneTagActive;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s by "has no tag names"or "has at least on of the given tag names".
|
||||
*
|
||||
* @param tagNames to be filtered on
|
||||
* @param selectTargetWithNoTag flag to get targets with no tag assigned
|
||||
* @return the {@link Target} {@link Specification}
|
||||
*/
|
||||
private static Specification<JpaTarget> hasTags(final String[] tagNames, final Boolean selectTargetWithNoTag) {
|
||||
return (targetRoot, query, cb) -> {
|
||||
final Predicate predicate = getHasTagsPredicate(targetRoot, cb, selectTargetWithNoTag, tagNames);
|
||||
query.distinct(true);
|
||||
return predicate;
|
||||
};
|
||||
}
|
||||
|
||||
private static Predicate getHasTagsPredicate(
|
||||
final Root<JpaTarget> targetRoot, final CriteriaBuilder cb, final Boolean selectTargetWithNoTag, final String[] tagNames) {
|
||||
final SetJoin<JpaTarget, JpaTargetTag> tags = targetRoot.join(JpaTarget_.tags, JoinType.LEFT);
|
||||
final Path<String> exp = tags.get(AbstractJpaNamedEntity_.name);
|
||||
|
||||
final List<Predicate> hasTagsPredicates = new ArrayList<>();
|
||||
if (isNoTagActive(selectTargetWithNoTag)) {
|
||||
hasTagsPredicates.add(exp.isNull());
|
||||
}
|
||||
if (isAtLeastOneTagActive(tagNames)) {
|
||||
hasTagsPredicates.add(exp.in((Object[]) tagNames));
|
||||
}
|
||||
|
||||
return hasTagsPredicates.stream().reduce(cb::or)
|
||||
.orElseThrow(() -> new RuntimeException("Neither NO_TAG, nor TAG target tag filter was provided!"));
|
||||
}
|
||||
|
||||
private static boolean isNoTagActive(final Boolean selectTargetWithNoTag) {
|
||||
return Boolean.TRUE.equals(selectTargetWithNoTag);
|
||||
}
|
||||
|
||||
private static boolean isAtLeastOneTagActive(final String[] tagNames) {
|
||||
return tagNames != null && tagNames.length > 0;
|
||||
}
|
||||
|
||||
private record FilterParams(Boolean selectTargetWithNoTag, String... filterByTagNames) {}
|
||||
}
|
||||
@@ -31,8 +31,6 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.awaitility.Awaitility;
|
||||
import org.awaitility.core.ConditionFactory;
|
||||
import org.eclipse.hawkbit.repository.artifact.ArtifactRepository;
|
||||
import org.eclipse.hawkbit.repository.artifact.exception.ArtifactStoreException;
|
||||
import org.eclipse.hawkbit.repository.ArtifactManagement;
|
||||
import org.eclipse.hawkbit.repository.ConfirmationManagement;
|
||||
import org.eclipse.hawkbit.repository.ControllerManagement;
|
||||
@@ -55,6 +53,8 @@ import org.eclipse.hawkbit.repository.TargetManagement;
|
||||
import org.eclipse.hawkbit.repository.TargetTagManagement;
|
||||
import org.eclipse.hawkbit.repository.TargetTypeManagement;
|
||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||
import org.eclipse.hawkbit.repository.artifact.ArtifactRepository;
|
||||
import org.eclipse.hawkbit.repository.artifact.exception.ArtifactStoreException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||
@@ -70,6 +70,7 @@ import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
|
||||
import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||
import org.eclipse.hawkbit.repository.model.TargetType;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.eclipse.hawkbit.repository.test.TestConfiguration;
|
||||
import org.eclipse.hawkbit.repository.test.matcher.EventVerifier;
|
||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||
@@ -436,7 +437,8 @@ public abstract class AbstractIntegrationTest {
|
||||
return ds.getModules().stream().filter(module -> module.getType().equals(type)).findAny();
|
||||
}
|
||||
|
||||
protected Optional<? extends SoftwareModule> findFirstModuleByType(final DistributionSetManagement.Create dsCreate, final SoftwareModuleType type) {
|
||||
protected Optional<? extends SoftwareModule> findFirstModuleByType(final DistributionSetManagement.Create dsCreate,
|
||||
final SoftwareModuleType type) {
|
||||
return dsCreate.getModules().stream().filter(module -> module.getType().equals(type)).findAny();
|
||||
}
|
||||
|
||||
@@ -512,4 +514,8 @@ public abstract class AbstractIntegrationTest {
|
||||
throw new ArtifactStoreException("Cannot create temp file", e);
|
||||
}
|
||||
}
|
||||
|
||||
protected List<? extends Target> findByUpdateStatus(final TargetUpdateStatus status, final Pageable pageable) {
|
||||
return targetManagement.findAll(pageable).stream().filter(target -> status.equals(target.getUpdateStatus())).toList();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user