Implement TargetFilterQueryManagement with AbstractJpaRepositoryManagement (#2587)

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
Avgustin Marinov
2025-08-05 09:53:24 +03:00
committed by GitHub
parent 1824839a6f
commit 7b24981a1d
36 changed files with 736 additions and 1482 deletions

View File

@@ -13,6 +13,7 @@ import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@@ -92,8 +93,7 @@ public class ObjectCopyUtil {
// java:S3776 - complexity is due to reflection and dynamic method invocation // java:S3776 - complexity is due to reflection and dynamic method invocation
// java:S3011 - low-level, reflection utility. intentionally changes the accessibility // java:S3011 - low-level, reflection utility. intentionally changes the accessibility
@SuppressWarnings({ "java:S3776", "java:S3011" }) @SuppressWarnings({ "java:S3776", "java:S3011" })
private static ToSetter toSetter( private static ToSetter toSetter(final Class<?> toClass, final String setterName, final String fieldName, final Class<?> type) {
final Class<?> toClass, final String setterName, final String fieldName, final Class<?> type) {
try { try {
final Method toSetterMethod = getMethod(toClass, setterName, type); final Method toSetterMethod = getMethod(toClass, setterName, type);
final Order order = toSetterMethod.getAnnotation(Order.class); final Order order = toSetterMethod.getAnnotation(Order.class);
@@ -128,7 +128,7 @@ public class ObjectCopyUtil {
private static UnaryOperator<Object> toGetter(final Class<?> toClass, final String getterName, final String fieldName) { private static UnaryOperator<Object> toGetter(final Class<?> toClass, final String getterName, final String fieldName) {
try { try {
final Method toGetterMethod = getMethod(toClass, getterName); final Method toGetterMethod = getMethod(toClass, toClass, getterName);
return to -> { return to -> {
try { try {
return toGetterMethod.invoke(to); return toGetterMethod.invoke(to);
@@ -175,23 +175,33 @@ public class ObjectCopyUtil {
} }
@NotNull @NotNull
private static Method getMethod(final Class<?> clazz, final String methodName, final Class<?>... parameterTypes) private static Method getMethod(final Class<?> clazz, final String methodName, final Class<?> parameterType)
throws NoSuchMethodException { throws NoSuchMethodException {
try { try {
return getMethod(clazz, clazz, methodName, parameterTypes); return getMethod(clazz, clazz, methodName, parameterType);
} catch (final NoSuchMethodException e) { } catch (final NoSuchMethodException e) {
if (parameterTypes.length == 1 && parameterTypes[0] == Boolean.class) { if (parameterType == Boolean.class) {
try { try {
return getMethod(clazz, methodName, boolean.class); return getMethod(clazz, methodName, boolean.class);
} catch (final NoSuchMethodException e2) { } catch (final NoSuchMethodException e2) {
throw e; throw e;
} }
} else {
final Method assignable = getMethodAssignable(clazz, methodName, parameterType);
if (assignable != null) {
return assignable;
}
final Method moreSpecific = getMethodMoreSpecific(clazz, methodName, parameterType);
if (moreSpecific != null) {
return moreSpecific;
}
} }
throw e; throw e;
} }
} }
@SuppressWarnings("java:S3011") // low-level, reflection utility. intentionally changes the accessibility @SuppressWarnings("java:S3011") // low-level, reflection utility. intentionally changes the accessibility
@NotNull
private static Method getMethod(final Class<?> target, final Class<?> clazz, final String methodName, final Class<?>... parameterTypes) private static Method getMethod(final Class<?> target, final Class<?> clazz, final String methodName, final Class<?>... parameterTypes)
throws NoSuchMethodException { throws NoSuchMethodException {
try { try {
@@ -208,6 +218,46 @@ public class ObjectCopyUtil {
} }
} }
@SuppressWarnings("java:S3011") // low-level, reflection utility. intentionally changes the accessibility
private static Method getMethodAssignable(final Class<?> clazz, final String methodName, final Class<?> parameterType) {
return Arrays.stream(clazz.getDeclaredMethods())
.filter(method -> methodName.equals(method.getName()))
.filter(method -> method.getParameterCount() == 1 && method.getParameterTypes()[0].isAssignableFrom(parameterType))
.findFirst()
.map(method -> {
method.setAccessible(true);
return method;
})
.orElseGet(() -> {
final Class<?> superClass = clazz.getSuperclass();
if (superClass == null) {
return null;
} else {
return getMethodAssignable(superClass, methodName, parameterType);
}
});
}
@SuppressWarnings("java:S3011") // low-level, reflection utility. intentionally changes the accessibility
private static Method getMethodMoreSpecific(final Class<?> clazz, final String methodName, final Class<?> parameterType) {
return Arrays.stream(clazz.getDeclaredMethods())
.filter(method -> methodName.equals(method.getName()))
.filter(method -> method.getParameterCount() == 1 && parameterType.isAssignableFrom(method.getParameterTypes()[0]))
.findFirst()
.map(method -> {
method.setAccessible(true);
return method;
})
.orElseGet(() -> {
final Class<?> superClass = clazz.getSuperclass();
if (superClass == null) {
return null;
} else {
return getMethodMoreSpecific(superClass, methodName, parameterType);
}
});
}
private static List<Method> getMethods(final Class<?> clazz) { private static List<Method> getMethods(final Class<?> clazz) {
final List<Method> methods = new ArrayList<>(); final List<Method> methods = new ArrayList<>();
for (final Method method : clazz.getDeclaredMethods()) { for (final Method method : clazz.getDeclaredMethods()) {

View File

@@ -27,8 +27,8 @@ import org.eclipse.hawkbit.mgmt.rest.resource.mapper.MgmtTargetFilterQueryMapper
import org.eclipse.hawkbit.mgmt.rest.resource.util.PagingUtility; import org.eclipse.hawkbit.mgmt.rest.resource.util.PagingUtility;
import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.AutoAssignDistributionSetUpdate;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
@@ -48,12 +48,12 @@ import org.springframework.web.bind.annotation.RestController;
@RestController @RestController
public class MgmtTargetFilterQueryResource implements MgmtTargetFilterQueryRestApi { public class MgmtTargetFilterQueryResource implements MgmtTargetFilterQueryRestApi {
private final TargetFilterQueryManagement filterManagement; private final TargetFilterQueryManagement<? extends TargetFilterQuery> filterManagement;
private final EntityFactory entityFactory; private final EntityFactory entityFactory;
private final TenantConfigHelper tenantConfigHelper; private final TenantConfigHelper tenantConfigHelper;
MgmtTargetFilterQueryResource( MgmtTargetFilterQueryResource(
final TargetFilterQueryManagement filterManagement, final EntityFactory entityFactory, final TargetFilterQueryManagement<? extends TargetFilterQuery> filterManagement, final EntityFactory entityFactory,
final SystemSecurityContext systemSecurityContext, final SystemSecurityContext systemSecurityContext,
final TenantConfigurationManagement tenantConfigurationManagement) { final TenantConfigurationManagement tenantConfigurationManagement) {
this.filterManagement = filterManagement; this.filterManagement = filterManagement;
@@ -77,27 +77,23 @@ public class MgmtTargetFilterQueryResource implements MgmtTargetFilterQueryRestA
final String rsqlParam, final int pagingOffsetParam, final int pagingLimitParam, final String sortParam, final String rsqlParam, final int pagingOffsetParam, final int pagingLimitParam, final String sortParam,
final String representationModeParam) { final String representationModeParam) {
final Pageable pageable = PagingUtility.toPageable(pagingOffsetParam, pagingLimitParam, sanitizeTargetFilterQuerySortParam(sortParam)); final Pageable pageable = PagingUtility.toPageable(pagingOffsetParam, pagingLimitParam, sanitizeTargetFilterQuerySortParam(sortParam));
final Slice<TargetFilterQuery> findTargetFiltersAll; final Page<? extends TargetFilterQuery> findTargetFiltersAll;
final long countTargetsAll;
if (rsqlParam != null) { if (rsqlParam != null) {
final Page<TargetFilterQuery> findFilterPage = filterManagement.findByRsql(rsqlParam, pageable); findTargetFiltersAll = filterManagement.findByRsql(rsqlParam, pageable);
countTargetsAll = findFilterPage.getTotalElements();
findTargetFiltersAll = findFilterPage;
} else { } else {
findTargetFiltersAll = filterManagement.findAll(pageable); findTargetFiltersAll = filterManagement.findAll(pageable);
countTargetsAll = filterManagement.count();
} }
final boolean isRepresentationFull = parseRepresentationMode(representationModeParam) == MgmtRepresentationMode.FULL; final boolean isRepresentationFull = parseRepresentationMode(representationModeParam) == MgmtRepresentationMode.FULL;
final List<MgmtTargetFilterQuery> rest = MgmtTargetFilterQueryMapper final List<MgmtTargetFilterQuery> rest = MgmtTargetFilterQueryMapper
.toResponse(findTargetFiltersAll.getContent(), tenantConfigHelper.isConfirmationFlowEnabled(), isRepresentationFull); .toResponse(findTargetFiltersAll.getContent(), tenantConfigHelper.isConfirmationFlowEnabled(), isRepresentationFull);
return ResponseEntity.ok(new PagedList<>(rest, countTargetsAll)); return ResponseEntity.ok(new PagedList<>(rest, filterManagement.count()));
} }
@Override @Override
public ResponseEntity<MgmtTargetFilterQuery> createFilter(final MgmtTargetFilterQueryRequestBody filter) { public ResponseEntity<MgmtTargetFilterQuery> createFilter(final MgmtTargetFilterQueryRequestBody filter) {
final TargetFilterQuery createdTarget = filterManagement.create(MgmtTargetFilterQueryMapper.fromRequest(entityFactory, filter)); final TargetFilterQuery createdTarget = filterManagement.create(MgmtTargetFilterQueryMapper.fromRequest(filter));
final MgmtTargetFilterQuery response = MgmtTargetFilterQueryMapper.toResponse( final MgmtTargetFilterQuery response = MgmtTargetFilterQueryMapper.toResponse(
createdTarget, tenantConfigHelper.isConfirmationFlowEnabled(), false); createdTarget, tenantConfigHelper.isConfirmationFlowEnabled(), false);
@@ -111,8 +107,9 @@ public class MgmtTargetFilterQueryResource implements MgmtTargetFilterQueryRestA
log.debug("updating target filter query {}", filterId); log.debug("updating target filter query {}", filterId);
final TargetFilterQuery updateFilter = filterManagement final TargetFilterQuery updateFilter = filterManagement
.update(entityFactory.targetFilterQuery().update(filterId).name(targetFilterRest.getName()) .update(TargetFilterQueryManagement.Update.builder()
.query(targetFilterRest.getQuery())); .id(filterId).name(targetFilterRest.getName()).query(targetFilterRest.getQuery())
.build());
final MgmtTargetFilterQuery response = MgmtTargetFilterQueryMapper.toResponse(updateFilter, final MgmtTargetFilterQuery response = MgmtTargetFilterQueryMapper.toResponse(updateFilter,
tenantConfigHelper.isConfirmationFlowEnabled(), false); tenantConfigHelper.isConfirmationFlowEnabled(), false);
@@ -152,7 +149,7 @@ public class MgmtTargetFilterQueryResource implements MgmtTargetFilterQueryRestA
: autoAssignRequest.getConfirmationRequired(); : autoAssignRequest.getConfirmationRequired();
final AutoAssignDistributionSetUpdate update = MgmtTargetFilterQueryMapper final AutoAssignDistributionSetUpdate update = MgmtTargetFilterQueryMapper
.fromRequest(entityFactory, filterId, autoAssignRequest).confirmationRequired(confirmationRequired); .fromRequest(filterId, autoAssignRequest).confirmationRequired(confirmationRequired);
final TargetFilterQuery updateFilter = filterManagement.updateAutoAssignDS(update); final TargetFilterQuery updateFilter = filterManagement.updateAutoAssignDS(update);
@@ -166,7 +163,7 @@ public class MgmtTargetFilterQueryResource implements MgmtTargetFilterQueryRestA
@Override @Override
@AuditLog(entity = "TargetFilter", type = AuditLog.Type.DELETE, description = "Delete Target Filter Assigned Distribution Set") @AuditLog(entity = "TargetFilter", type = AuditLog.Type.DELETE, description = "Delete Target Filter Assigned Distribution Set")
public ResponseEntity<Void> deleteAssignedDistributionSet(final Long filterId) { public ResponseEntity<Void> deleteAssignedDistributionSet(final Long filterId) {
filterManagement.updateAutoAssignDS(entityFactory.targetFilterQuery().updateAutoAssign(filterId).ds(null)); filterManagement.updateAutoAssignDS(new AutoAssignDistributionSetUpdate(filterId).ds(null));
return ResponseEntity.noContent().build(); return ResponseEntity.noContent().build();
} }

View File

@@ -24,8 +24,9 @@ import org.eclipse.hawkbit.mgmt.rest.api.MgmtDistributionSetRestApi;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetFilterQueryRestApi; import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetFilterQueryRestApi;
import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryCreate; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.AutoAssignDistributionSetUpdate;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.Create;
import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
@@ -38,7 +39,7 @@ import org.springframework.util.CollectionUtils;
public final class MgmtTargetFilterQueryMapper { public final class MgmtTargetFilterQueryMapper {
public static List<MgmtTargetFilterQuery> toResponse( public static List<MgmtTargetFilterQuery> toResponse(
final List<TargetFilterQuery> filters, final boolean confirmationFlowEnabled, final boolean isRepresentationFull) { final List<? extends TargetFilterQuery> filters, final boolean confirmationFlowEnabled, final boolean isRepresentationFull) {
if (CollectionUtils.isEmpty(filters)) { if (CollectionUtils.isEmpty(filters)) {
return Collections.emptyList(); return Collections.emptyList();
} }
@@ -86,15 +87,14 @@ public final class MgmtTargetFilterQueryMapper {
.postAssignedDistributionSet(targetRest.getId(), null)).withRel("autoAssignDS").expand()); .postAssignedDistributionSet(targetRest.getId(), null)).withRel("autoAssignDS").expand());
} }
public static TargetFilterQueryCreate fromRequest(final EntityFactory entityFactory, final MgmtTargetFilterQueryRequestBody filterRest) { public static Create fromRequest(final MgmtTargetFilterQueryRequestBody filterRest) {
return entityFactory.targetFilterQuery().create().name(filterRest.getName()).query(filterRest.getQuery()); return Create.builder().name(filterRest.getName()).query(filterRest.getQuery()).build();
} }
public static AutoAssignDistributionSetUpdate fromRequest(final EntityFactory entityFactory, final long filterId, public static AutoAssignDistributionSetUpdate fromRequest(final long filterId,
final MgmtDistributionSetAutoAssignment assignRest) { final MgmtDistributionSetAutoAssignment assignRest) {
final ActionType type = MgmtRestModelMapper.convertActionType(assignRest.getType()); final ActionType type = MgmtRestModelMapper.convertActionType(assignRest.getType());
return entityFactory.targetFilterQuery().updateAutoAssign(filterId).ds(assignRest.getId()).actionType(type) return new AutoAssignDistributionSetUpdate(filterId).ds(assignRest.getId()).actionType(type).weight(assignRest.getWeight());
.weight(assignRest.getWeight());
} }
} }

View File

@@ -45,6 +45,7 @@ import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleAssi
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
import org.eclipse.hawkbit.mgmt.rest.resource.util.ResourceUtility; import org.eclipse.hawkbit.mgmt.rest.resource.util.ResourceUtility;
import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.Create;
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository; import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository;
@@ -257,7 +258,7 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
// post one more to cause the quota to be exceeded // post one more to cause the quota to be exceeded
mvc.perform(post(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/" + disSet.getId() + "/assignedSM") mvc.perform(post(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/" + disSet.getId() + "/assignedSM")
.contentType(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON)
.content(toJson(List.of(moduleIDs.get(moduleIDs.size() - 1)).stream().map(MgmtId::new).toList()))) .content(toJson(Stream.of(moduleIDs.get(moduleIDs.size() - 1)).map(MgmtId::new).toList())))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isForbidden()) .andExpect(status().isForbidden())
.andExpect(jsonPath("$.exceptionClass", equalTo(AssignmentQuotaExceededException.class.getName()))) .andExpect(jsonPath("$.exceptionClass", equalTo(AssignmentQuotaExceededException.class.getName())))
@@ -711,12 +712,12 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
final String knownFilterName = "a"; final String knownFilterName = "a";
final DistributionSet createdDs = testdataFactory.createDistributionSet(); final DistributionSet createdDs = testdataFactory.createDistributionSet();
targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name(knownFilterName) targetFilterQueryManagement.create(Create.builder().name(knownFilterName)
.query("name==y").autoAssignDistributionSet(createdDs.getId())); .query("name==y").autoAssignDistributionSet(createdDs).build());
// create some dummy target filter queries // create some dummy target filter queries
targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name("b").query("name==y")); targetFilterQueryManagement.create(Create.builder().name("b").query("name==y").build());
targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name("c").query("name==y")); targetFilterQueryManagement.create(Create.builder().name("c").query("name==y").build());
mvc.perform(get(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/" + createdDs.getId() mvc.perform(get(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/" + createdDs.getId()
+ "/autoAssignTargetFilters")) + "/autoAssignTargetFilters"))
@@ -731,8 +732,7 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
@Test @Test
void ggetAutoAssignTargetFiltersOfDistributionSetWithParameters() throws Exception { void ggetAutoAssignTargetFiltersOfDistributionSetWithParameters() throws Exception {
final DistributionSet set = testdataFactory.createUpdatedDistributionSet(); final DistributionSet set = testdataFactory.createUpdatedDistributionSet();
targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name("filter1").query("name==a") targetFilterQueryManagement.create(Create.builder().name("filter1").query("name==a").autoAssignDistributionSet(set).build());
.autoAssignDistributionSet(set));
mvc.perform(get(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/" + set.getId() + "/autoAssignTargetFilters") mvc.perform(get(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/" + set.getId() + "/autoAssignTargetFilters")
.param("offset", "1").param("limit", "2").param("sort", "name:DESC").param("q", "name==*1") .param("offset", "1").param("limit", "2").param("sort", "name:DESC").param("q", "name==*1")
@@ -1622,12 +1622,10 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
DistributionSet ds2 = testdataFactory.createDistributionSet("DS2"); DistributionSet ds2 = testdataFactory.createDistributionSet("DS2");
targetFilterQueryManagement.create( targetFilterQueryManagement.create(
entityFactory.targetFilterQuery().create().name("test filter 1").autoAssignDistributionSet(ds1.getId()) Create.builder().name("test filter 1").autoAssignDistributionSet(ds1).query("name==targets*").build());
.query("name==targets*"));
targetFilterQueryManagement.create( targetFilterQueryManagement.create(
entityFactory.targetFilterQuery().create().name("test filter 2").autoAssignDistributionSet(ds1.getId()) Create.builder().name("test filter 2").autoAssignDistributionSet(ds1).query("name==targets*").build());
.query("name==targets*"));
mvc.perform(get(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{ds}/statistics/autoassignments", ds1.getId()).contentType( mvc.perform(get(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{ds}/statistics/autoassignments", ds1.getId()).contentType(
MediaType.APPLICATION_JSON)) MediaType.APPLICATION_JSON))
@@ -1657,8 +1655,7 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
DistributionSet ds2 = testdataFactory.createDistributionSet("DS2"); DistributionSet ds2 = testdataFactory.createDistributionSet("DS2");
targetFilterQueryManagement.create( targetFilterQueryManagement.create(
entityFactory.targetFilterQuery().create().name("test filter 1").autoAssignDistributionSet(ds1.getId()) Create.builder().name("test filter 1").autoAssignDistributionSet(ds1).query("name==autoAssignments*").build());
.query("name==autoAssignments*"));
Rollout rollout = testdataFactory.createRolloutByVariables("rollout", "description", Rollout rollout = testdataFactory.createRolloutByVariables("rollout", "description",
1, "name==targets*", ds1, "50", "5", false); 1, "name==targets*", ds1, "50", "5", false);
@@ -1689,14 +1686,14 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
*/ */
@Test @Test
void invalidateDistributionSet() throws Exception { void invalidateDistributionSet() throws Exception {
final DistributionSet distributionSet = testdataFactory.createDistributionSet(); DistributionSet distributionSet = testdataFactory.createDistributionSet();
final List<Target> targets = testdataFactory.createTargets(5, "invalidateDistributionSet"); final List<Target> targets = testdataFactory.createTargets(5, "invalidateDistributionSet");
assignDistributionSet(distributionSet, targets); // the distribution set is locked and the old instance become stale
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement distributionSet = assignDistributionSet(distributionSet, targets).getDistributionSet();
.create(entityFactory.targetFilterQuery().create().name("invalidateDistributionSet").query("name==*") final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement.create(
.autoAssignDistributionSet(distributionSet)); Create.builder().name("invalidateDistributionSet").query("name==*").autoAssignDistributionSet(distributionSet).build());
final Rollout rollout = testdataFactory.createRolloutByVariables("invalidateDistributionSet", "desc", 2, final Rollout rollout = testdataFactory.createRolloutByVariables(
"name==*", distributionSet, "50", "80"); "invalidateDistributionSet", "desc", 2, "name==*", distributionSet, "50", "80");
final JSONObject jsonObject = new JSONObject(); final JSONObject jsonObject = new JSONObject();
jsonObject.put("actionCancelationType", "soft"); jsonObject.put("actionCancelationType", "soft");
@@ -1812,15 +1809,13 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
private void prepareTestFilters(final String filterNamePrefix, final DistributionSet createdDs) { private void prepareTestFilters(final String filterNamePrefix, final DistributionSet createdDs) {
// create target filter queries that should be found // create target filter queries that should be found
targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name(filterNamePrefix + "1") targetFilterQueryManagement.create(Create.builder().name(filterNamePrefix + "1")
.query("name==y").autoAssignDistributionSet(createdDs.getId())); .query("name==y").autoAssignDistributionSet(createdDs).build());
targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name(filterNamePrefix + "2") targetFilterQueryManagement.create(Create.builder().name(filterNamePrefix + "2")
.query("name==y").autoAssignDistributionSet(createdDs.getId())); .query("name==y").autoAssignDistributionSet(createdDs).build());
// create some dummy target filter queries // create some dummy target filter queries
targetFilterQueryManagement targetFilterQueryManagement.create(Create.builder().name(filterNamePrefix + "b").query("name==y").build());
.create(entityFactory.targetFilterQuery().create().name(filterNamePrefix + "b").query("name==y")); targetFilterQueryManagement.create(Create.builder().name(filterNamePrefix + "c").query("name==y").build());
targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name(filterNamePrefix + "c").query("name==y"));
} }
private MvcResult executeMgmtTargetPost( private MvcResult executeMgmtTargetPost(

View File

@@ -32,6 +32,8 @@ import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
import org.eclipse.hawkbit.mgmt.rest.resource.mapper.MgmtRestModelMapper; import org.eclipse.hawkbit.mgmt.rest.resource.mapper.MgmtRestModelMapper;
import org.eclipse.hawkbit.mgmt.rest.resource.util.ResourceUtility; import org.eclipse.hawkbit.mgmt.rest.resource.util.ResourceUtility;
import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.AutoAssignDistributionSetUpdate;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.Create;
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
import org.eclipse.hawkbit.repository.exception.DeletedException; import org.eclipse.hawkbit.repository.exception.DeletedException;
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException; import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
@@ -96,7 +98,7 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
* Handles the GET request of retrieving all target filter queries within SP. * Handles the GET request of retrieving all target filter queries within SP.
*/ */
@Test @Test
void getTargetFilterQueries() throws Exception { void getTargetFilterQueries() throws Exception {
final String filterName = "filter_01"; final String filterName = "filter_01";
createSingleTargetFilterQuery(filterName, "name==test_01"); createSingleTargetFilterQuery(filterName, "name==test_01");
mvc.perform(get(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING)) mvc.perform(get(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING))
@@ -108,7 +110,7 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
* Handles the GET request of retrieving all target filter queries within SP based by parameter. Required Permission: READ_TARGET. * Handles the GET request of retrieving all target filter queries within SP based by parameter. Required Permission: READ_TARGET.
*/ */
@Test @Test
void getTargetFilterQueriesWithParameters() throws Exception { void getTargetFilterQueriesWithParameters() throws Exception {
mvc.perform(get(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "?limit=10&sort=name:ASC&offset=0&q=name==*1")) mvc.perform(get(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "?limit=10&sort=name:ASC&offset=0&q=name==*1"))
.andExpect(status().isOk()) .andExpect(status().isOk())
.andDo(MockMvcResultPrinter.print()); .andDo(MockMvcResultPrinter.print());
@@ -118,7 +120,7 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
* Handles the POST request of creating a new target filter query within SP. * Handles the POST request of creating a new target filter query within SP.
*/ */
@Test @Test
void createTargetFilterQuery() throws Exception { void createTargetFilterQuery() throws Exception {
final String name = "test_02"; final String name = "test_02";
final String filterQuery = "name==test_02"; final String filterQuery = "name==test_02";
final String body = new JSONObject() final String body = new JSONObject()
@@ -135,7 +137,7 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
* Ensures that deletion is executed if permitted. * Ensures that deletion is executed if permitted.
*/ */
@Test @Test
void deleteTargetFilterQueryReturnsOK() throws Exception { void deleteTargetFilterQueryReturnsOK() throws Exception {
final String filterName = "filter_01"; final String filterName = "filter_01";
final TargetFilterQuery filterQuery = createSingleTargetFilterQuery(filterName, "name==test_01"); final TargetFilterQuery filterQuery = createSingleTargetFilterQuery(filterName, "name==test_01");
@@ -149,7 +151,7 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
* Ensures that deletion is refused with not found if target does not exist. * Ensures that deletion is refused with not found if target does not exist.
*/ */
@Test @Test
void deleteTargetWhichDoesNotExistsLeadsToEntityNotFound() throws Exception { void deleteTargetWhichDoesNotExistsLeadsToEntityNotFound() throws Exception {
final String notExistingId = "4395"; final String notExistingId = "4395";
mvc.perform(delete(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/" + notExistingId)) mvc.perform(delete(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/" + notExistingId))
@@ -160,7 +162,7 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
* Ensures that update is refused with not found if target does not exist. * Ensures that update is refused with not found if target does not exist.
*/ */
@Test @Test
void updateTargetWhichDoesNotExistsLeadsToEntityNotFound() throws Exception { void updateTargetWhichDoesNotExistsLeadsToEntityNotFound() throws Exception {
final String notExistingId = "4395"; final String notExistingId = "4395";
mvc.perform(put(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/" + notExistingId).content("{}") mvc.perform(put(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/" + notExistingId).content("{}")
.contentType(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON))
@@ -172,7 +174,7 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
* Ensures that update request is reflected by repository. * Ensures that update request is reflected by repository.
*/ */
@Test @Test
void updateTargetFilterQueryQuery() throws Exception { void updateTargetFilterQueryQuery() throws Exception {
final String filterName = "filter_02"; final String filterName = "filter_02";
final String filterQuery = "name==test_02"; final String filterQuery = "name==test_02";
final String filterQuery2 = "name==test_02_changed"; final String filterQuery2 = "name==test_02_changed";
@@ -199,15 +201,14 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
* Ensures that update request is reflected by repository. * Ensures that update request is reflected by repository.
*/ */
@Test @Test
void updateTargetFilterQueryName() throws Exception { void updateTargetFilterQueryName() throws Exception {
final String filterName = "filter_03"; final String filterName = "filter_03";
final String filterName2 = "filter_03_changed"; final String filterName2 = "filter_03_changed";
final String filterQuery = "name==test_03"; final String filterQuery = "name==test_03";
final String body = new JSONObject().put("name", filterName2).toString(); final String body = new JSONObject().put("name", filterName2).toString();
// prepare // prepare
final TargetFilterQuery tfq = targetFilterQueryManagement final TargetFilterQuery tfq = targetFilterQueryManagement.create(Create.builder().name(filterName).query(filterQuery).build());
.create(entityFactory.targetFilterQuery().create().name(filterName).query(filterQuery));
mvc.perform(put(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/" + tfq.getId()).content(body) mvc.perform(put(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/" + tfq.getId()).content(body)
.contentType(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON))
@@ -227,7 +228,7 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
* Ensures that request returns list of filters in defined format. * Ensures that request returns list of filters in defined format.
*/ */
@Test @Test
void getTargetFilterQueryWithoutAdditionalRequestParameters() throws Exception { void getTargetFilterQueryWithoutAdditionalRequestParameters() throws Exception {
final int knownTargetAmount = 3; final int knownTargetAmount = 3;
final String idA = "a"; final String idA = "a";
final String idB = "b"; final String idB = "b";
@@ -259,7 +260,7 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
* Ensures that request returns list of filters in defined format in size reduced by given limit parameter. * Ensures that request returns list of filters in defined format in size reduced by given limit parameter.
*/ */
@Test @Test
void getTargetWithPagingLimitRequestParameter() throws Exception { void getTargetWithPagingLimitRequestParameter() throws Exception {
final int limitSize = 1; final int limitSize = 1;
final int knownTargetAmount = 3; final int knownTargetAmount = 3;
final String idA = "a"; final String idA = "a";
@@ -329,7 +330,7 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
* Ensures that request returns list of filters in defined format in size reduced by given limit and offset parameter. * Ensures that request returns list of filters in defined format in size reduced by given limit and offset parameter.
*/ */
@Test @Test
void getTargetWithPagingLimitAndOffsetRequestParameter() throws Exception { void getTargetWithPagingLimitAndOffsetRequestParameter() throws Exception {
final int knownTargetAmount = 5; final int knownTargetAmount = 5;
final int offsetParam = 2; final int offsetParam = 2;
final int expectedSize = knownTargetAmount - offsetParam; final int expectedSize = knownTargetAmount - offsetParam;
@@ -367,7 +368,7 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
* Ensures that a single target filter query can be retrieved via its id. * Ensures that a single target filter query can be retrieved via its id.
*/ */
@Test @Test
void getSingleTarget() throws Exception { void getSingleTarget() throws Exception {
// create first a target which can be retrieved by rest interface // create first a target which can be retrieved by rest interface
final String knownQuery = "name==test01"; final String knownQuery = "name==test01";
final String knownName = "someName"; final String knownName = "someName";
@@ -389,7 +390,7 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
* Ensures that the retrieval of a non-existing target filter query results in a HTTP Not found error (404). * Ensures that the retrieval of a non-existing target filter query results in a HTTP Not found error (404).
*/ */
@Test @Test
void getSingleTargetNoExistsResponseNotFound() throws Exception { void getSingleTargetNoExistsResponseNotFound() throws Exception {
final String targetIdNotExists = "546546"; final String targetIdNotExists = "546546";
// test // test
@@ -408,7 +409,7 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
* Ensures that the creation of a target filter query based on an invalid request payload results in a HTTP Bad Request error (400). * Ensures that the creation of a target filter query based on an invalid request payload results in a HTTP Bad Request error (400).
*/ */
@Test @Test
void createTargetFilterQueryWithBadPayloadBadRequest() throws Exception { void createTargetFilterQueryWithBadPayloadBadRequest() throws Exception {
final String notJson = "abc"; final String notJson = "abc";
final MvcResult mvcResult = mvc final MvcResult mvcResult = mvc
@@ -431,7 +432,7 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
* Ensures that the creation of a target filter query based on an invalid RSQL query results in a HTTP Bad Request error (400). * Ensures that the creation of a target filter query based on an invalid RSQL query results in a HTTP Bad Request error (400).
*/ */
@Test @Test
void createTargetFilterWithInvalidQuery() throws Exception { void createTargetFilterWithInvalidQuery() throws Exception {
final String invalidQuery = "name=abc"; final String invalidQuery = "name=abc";
final String body = new JSONObject().put("query", invalidQuery).put("name", "invalidFilter").toString(); final String body = new JSONObject().put("query", invalidQuery).put("name", "invalidFilter").toString();
@@ -470,7 +471,7 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
} }
/** /**
* Ensures that the update of a target filter query results in a HTTP Forbidden error (403) * Ensures that the update of a target filter query results in a HTTP Forbidden error (403)
* if the updated query addresses too many targets. * if the updated query addresses too many targets.
*/ */
@Test @Test
@@ -541,12 +542,10 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
* Handles the GET request of retrieving a the auto assign distribution set of a target filter query within SP. * Handles the GET request of retrieving a the auto assign distribution set of a target filter query within SP.
*/ */
@Test @Test
void getAssignDS() throws Exception { void getAssignDS() throws Exception {
final TargetFilterQuery filterQuery = createSingleTargetFilterQuery("filter_01", "name==test_01"); final TargetFilterQuery filterQuery = createSingleTargetFilterQuery("filter_01", "name==test_01");
final DistributionSet ds = testdataFactory.createDistributionSet("ds"); final DistributionSet ds = testdataFactory.createDistributionSet("ds");
targetFilterQueryManagement targetFilterQueryManagement.updateAutoAssignDS(new AutoAssignDistributionSetUpdate(filterQuery.getId()).ds(ds.getId()));
.updateAutoAssignDS(entityFactory.targetFilterQuery()
.updateAutoAssign(filterQuery.getId()).ds(ds.getId()));
mvc.perform(get(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/{targetFilterQueryId}/autoAssignDS", mvc.perform(get(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/{targetFilterQueryId}/autoAssignDS",
filterQuery.getId())) filterQuery.getId()))
@@ -558,7 +557,7 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
* Handles the POST request of setting a distribution set for auto assignment within SP. * Handles the POST request of setting a distribution set for auto assignment within SP.
*/ */
@Test @Test
void createAutoAssignDS() throws Exception { void createAutoAssignDS() throws Exception {
enableMultiAssignments(); enableMultiAssignments();
enableConfirmationFlow(); enableConfirmationFlow();
@@ -579,7 +578,7 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
* Handles the DELETE request of deleting the auto assign distribution set from a target filter query within SP. * Handles the DELETE request of deleting the auto assign distribution set from a target filter query within SP.
*/ */
@Test @Test
void deleteAutoAssignDS() throws Exception { void deleteAutoAssignDS() throws Exception {
final String filterName = "filter_01"; final String filterName = "filter_01";
final TargetFilterQuery filterQuery = createSingleTargetFilterQuery(filterName, "name==test_01"); final TargetFilterQuery filterQuery = createSingleTargetFilterQuery(filterName, "name==test_01");
mvc mvc
@@ -594,18 +593,17 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
* Ensures that the deletion of auto-assignment distribution set works as intended, deleting the auto-assignment action type as well * Ensures that the deletion of auto-assignment distribution set works as intended, deleting the auto-assignment action type as well
*/ */
@Test @Test
void deleteAutoAssignDistributionSetOfTargetFilterQuery() throws Exception { void deleteAutoAssignDistributionSetOfTargetFilterQuery() throws Exception {
final String knownQuery = "name==test06"; final String knownQuery = "name==test06";
final String knownName = "filter06"; final String knownName = "filter06";
final String dsName = "testDS"; final String dsName = "testDS";
final DistributionSet set = testdataFactory.createDistributionSet(dsName); final DistributionSet set = testdataFactory.createDistributionSet(dsName);
final TargetFilterQuery tfq = createSingleTargetFilterQuery(knownName, knownQuery); final TargetFilterQuery tfq = createSingleTargetFilterQuery(knownName, knownQuery);
targetFilterQueryManagement targetFilterQueryManagement.updateAutoAssignDS(new AutoAssignDistributionSetUpdate(tfq.getId()).ds(set.getId()));
.updateAutoAssignDS(entityFactory.targetFilterQuery().updateAutoAssign(tfq.getId()).ds(set.getId()));
implicitLock(set); implicitLock(set);
final TargetFilterQuery updatedFilterQuery = targetFilterQueryManagement.get(tfq.getId()).get(); final TargetFilterQuery updatedFilterQuery = targetFilterQueryManagement.get(tfq.getId()).orElseThrow();
assertThat(updatedFilterQuery.getAutoAssignDistributionSet()).isEqualTo(set); assertThat(updatedFilterQuery.getAutoAssignDistributionSet()).isEqualTo(set);
assertThat(updatedFilterQuery.getAutoAssignActionType()).isEqualTo(ActionType.FORCED); assertThat(updatedFilterQuery.getAutoAssignActionType()).isEqualTo(ActionType.FORCED);
@@ -631,7 +629,7 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
* An auto assignment containing a weight is only accepted when weight is valide and multi assignment is on. * An auto assignment containing a weight is only accepted when weight is valide and multi assignment is on.
*/ */
@Test @Test
void weightValidation() throws Exception { void weightValidation() throws Exception {
final Long filterId = createSingleTargetFilterQuery("filter1", "name==*").getId(); final Long filterId = createSingleTargetFilterQuery("filter1", "name==*").getId();
final Long dsId = testdataFactory.createDistributionSet().getId(); final Long dsId = testdataFactory.createDistributionSet().getId();
@@ -654,7 +652,7 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
.andDo(print()) .andDo(print())
.andExpect(status().isOk()); .andExpect(status().isOk());
final List<TargetFilterQuery> filters = targetFilterQueryManagement.findAll(PAGE).getContent(); final List<? extends TargetFilterQuery> filters = targetFilterQueryManagement.findAll(PAGE).getContent();
assertThat(filters).hasSize(1); assertThat(filters).hasSize(1);
assertThat(filters.get(0).getAutoAssignWeight()).contains(45); assertThat(filters.get(0).getAutoAssignWeight()).contains(45);
} }
@@ -678,9 +676,8 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
// do not provide something about the confirmation // do not provide something about the confirmation
verifyAutoAssignmentByActionType(tfq, set, null, null); verifyAutoAssignmentByActionType(tfq, set, null, null);
assertThat(targetFilterQueryManagement.get(tfq.getId())).hasValueSatisfying(filter -> { assertThat(targetFilterQueryManagement.get(tfq.getId())).hasValueSatisfying(filter ->
assertThat(filter.isConfirmationRequired()).isEqualTo(confirmationFlowActive); assertThat(filter.isConfirmationRequired()).isEqualTo(confirmationFlowActive));
});
} }
private static Stream<Arguments> confirmationOptions() { private static Stream<Arguments> confirmationOptions() {
@@ -803,6 +800,6 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
} }
private TargetFilterQuery createSingleTargetFilterQuery(final String name, final String query) { private TargetFilterQuery createSingleTargetFilterQuery(final String name, final String query) {
return targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name(name).query(query)); return targetFilterQueryManagement.create(Create.builder().name(name).query(query).build());
} }
} }

View File

@@ -14,7 +14,6 @@ import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_UP
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
@@ -29,7 +28,6 @@ import lombok.Getter;
import lombok.ToString; import lombok.ToString;
import lombok.experimental.SuperBuilder; import lombok.experimental.SuperBuilder;
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; 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.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException; import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException;
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException; import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
@@ -146,7 +144,7 @@ public interface DistributionSetManagement<T extends DistributionSet>
* @throws EntityNotFoundException if distribution set with given ID does not exist * @throws EntityNotFoundException if distribution set with given ID does not exist
*/ */
@PreAuthorize(HAS_UPDATE_REPOSITORY) @PreAuthorize(HAS_UPDATE_REPOSITORY)
void lock(final long id); T lock(final long id);
/** /**
* Unlocks a distribution set.<br/> * Unlocks a distribution set.<br/>
@@ -157,7 +155,7 @@ public interface DistributionSetManagement<T extends DistributionSet>
* @throws EntityNotFoundException if distribution set with given ID does not exist * @throws EntityNotFoundException if distribution set with given ID does not exist
*/ */
@PreAuthorize(HAS_UPDATE_REPOSITORY) @PreAuthorize(HAS_UPDATE_REPOSITORY)
void unlock(final long id); T unlock(final long id);
/** /**
* Find distribution set by id and throw an exception if it is deleted or invalidated. * Find distribution set by id and throw an exception if it is deleted or invalidated.
@@ -310,11 +308,11 @@ public interface DistributionSetManagement<T extends DistributionSet>
List<Statistic> countActionsByStatusForDistributionSet(@NotNull Long id); List<Statistic> countActionsByStatusForDistributionSet(@NotNull Long id);
/** /**
* Count all {@link org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate}s * Count all {@link TargetFilterQueryManagement.AutoAssignDistributionSetUpdate}s
* for Distribution Set. * for Distribution Set.
* *
* @param id to look for * @param id to look for
* @return number of {@link org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate}s * @return number of {@link TargetFilterQueryManagement.AutoAssignDistributionSetUpdate}s
*/ */
@PreAuthorize(HAS_READ_REPOSITORY) @PreAuthorize(HAS_READ_REPOSITORY)
Long countAutoAssignmentsForDistributionSet(@NotNull Long id); Long countAutoAssignmentsForDistributionSet(@NotNull Long id);

View File

@@ -13,7 +13,6 @@ import org.eclipse.hawkbit.repository.builder.ActionStatusBuilder;
import org.eclipse.hawkbit.repository.builder.RolloutBuilder; import org.eclipse.hawkbit.repository.builder.RolloutBuilder;
import org.eclipse.hawkbit.repository.builder.RolloutGroupBuilder; import org.eclipse.hawkbit.repository.builder.RolloutGroupBuilder;
import org.eclipse.hawkbit.repository.builder.TargetBuilder; import org.eclipse.hawkbit.repository.builder.TargetBuilder;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryBuilder;
import org.eclipse.hawkbit.repository.model.BaseEntity; import org.eclipse.hawkbit.repository.model.BaseEntity;
/** /**
@@ -21,6 +20,11 @@ import org.eclipse.hawkbit.repository.model.BaseEntity;
*/ */
public interface EntityFactory { public interface EntityFactory {
/**
* @return {@link TargetBuilder} object
*/
TargetBuilder target();
/** /**
* @return {@link ActionStatusBuilder} object * @return {@link ActionStatusBuilder} object
*/ */
@@ -35,14 +39,4 @@ public interface EntityFactory {
* @return {@link RolloutBuilder} object * @return {@link RolloutBuilder} object
*/ */
RolloutBuilder rollout(); RolloutBuilder rollout();
/**
* @return {@link TargetBuilder} object
*/
TargetBuilder target();
/**
* @return {@link TargetFilterQueryBuilder} object
*/
TargetFilterQueryBuilder targetFilterQuery();
} }

View File

@@ -9,16 +9,20 @@
*/ */
package org.eclipse.hawkbit.repository; package org.eclipse.hawkbit.repository;
import java.util.Optional;
import jakarta.validation.ConstraintViolationException;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
import org.eclipse.hawkbit.im.authentication.SpringEvalExpressions; import org.eclipse.hawkbit.im.authentication.SpringEvalExpressions;
import org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryCreate;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryUpdate;
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException; import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
@@ -26,8 +30,10 @@ import org.eclipse.hawkbit.repository.exception.InvalidAutoAssignActionTypeExcep
import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException; import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException;
import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException; import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException;
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
@@ -37,29 +43,13 @@ import org.springframework.security.access.prepost.PreAuthorize;
/** /**
* Management service for {@link TargetFilterQuery}s. * Management service for {@link TargetFilterQuery}s.
*/ */
public interface TargetFilterQueryManagement { public interface TargetFilterQueryManagement<T extends TargetFilterQuery>
extends RepositoryManagement<T, TargetFilterQueryManagement.Create, TargetFilterQueryManagement.Update> {
/** @Override
* Creates a new {@link TargetFilterQuery}. default String permissionGroup() {
* return "TARGET";
* @param create to create }
* @return the new {@link TargetFilterQuery}
* @throws ConstraintViolationException if fields are not filled as specified. Check
* {@link TargetFilterQueryCreate} for field constraints.
* @throws AssignmentQuotaExceededException if the maximum number of targets that is addressed by the
* given query is exceeded (auto-assignments only)
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_TARGET)
TargetFilterQuery create(@NotNull @Valid TargetFilterQueryCreate create);
/**
* Deletes the {@link TargetFilterQuery} with the given ID.
*
* @param targetFilterQueryId IDs of target filter query to be deleted
* @throws EntityNotFoundException if filter with given ID does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_DELETE_TARGET)
void delete(long targetFilterQueryId);
/** /**
* Verifies the provided filter syntax. * Verifies the provided filter syntax.
@@ -73,23 +63,6 @@ public interface TargetFilterQueryManagement {
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
boolean verifyTargetFilterQuerySyntax(@NotNull String query); boolean verifyTargetFilterQuerySyntax(@NotNull String query);
/**
* Retrieves all {@link TargetFilterQuery}s.
*
* @param pageable pagination parameter
* @return the found {@link TargetFilterQuery}s
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Slice<TargetFilterQuery> findAll(@NotNull Pageable pageable);
/**
* Counts all {@link TargetFilterQuery}s.
*
* @return the number of all target filter queries
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
long count();
/** /**
* Counts all target filters that have a given auto assign distribution set * Counts all target filters that have a given auto assign distribution set
* assigned. * assigned.
@@ -102,57 +75,6 @@ public interface TargetFilterQueryManagement {
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
long countByAutoAssignDistributionSetId(long autoAssignDistributionSetId); long countByAutoAssignDistributionSetId(long autoAssignDistributionSetId);
/**
* Retrieves all {@link TargetFilterQuery}s which match the given name
* filter.
*
* @param name name filter
* @param pageable pagination parameter
* @return the page with the found {@link TargetFilterQuery}s
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Slice<TargetFilterQuery> findByName(@NotNull String name, @NotNull Pageable pageable);
/**
* Counts all {@link TargetFilterQuery}s which match the given name filter.
*
* @param name name filter
* @return count of found {@link TargetFilterQuery}s
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
long countByName(@NotNull String name);
/**
* Retrieves all {@link TargetFilterQuery} which match the given RSQL filter.
*
* @param rsqlFilter RSQL filter string
* @param pageable pagination parameter
* @return the page with the found {@link TargetFilterQuery}s
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Page<TargetFilterQuery> findByRsql(@NotNull String rsqlFilter, @NotNull Pageable pageable);
/**
* Retrieves all {@link TargetFilterQuery}s which match the given query.
*
* @param query the query saved in the target filter query
* @param pageable pagination parameter
* @return the page with the found {@link TargetFilterQuery}s
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Slice<TargetFilterQuery> findByQuery(@NotNull String query, @NotNull Pageable pageable);
/**
* Retrieves all {@link TargetFilterQuery}s which match the given auto-assign distribution set ID.
*
* @param setId the auto assign distribution set
* @param pageable pagination parameter
* @return the page with the found {@link TargetFilterQuery}s
* @throws EntityNotFoundException if DS with given ID does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Slice<TargetFilterQuery> findByAutoAssignDistributionSetId(long setId, @NotNull Pageable pageable);
/** /**
* Retrieves all {@link TargetFilterQuery}s which match the given auto-assign distribution set and RSQL filter. * Retrieves all {@link TargetFilterQuery}s which match the given auto-assign distribution set and RSQL filter.
* *
@@ -174,39 +96,6 @@ public interface TargetFilterQueryManagement {
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Slice<TargetFilterQuery> findWithAutoAssignDS(@NotNull Pageable pageable); Slice<TargetFilterQuery> findWithAutoAssignDS(@NotNull Pageable pageable);
/**
* Finds the {@link TargetFilterQuery} by id.
*
* @param targetFilterQueryId Target filter query id
* @return the found {@link TargetFilterQuery}
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Optional<TargetFilterQuery> get(long targetFilterQueryId);
/**
* Finds the {@link TargetFilterQuery} that matches the given name.
*
* @param targetFilterQueryName Target filter query name
* @return the found {@link TargetFilterQuery}
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Optional<TargetFilterQuery> getByName(@NotNull String targetFilterQueryName);
/**
* Updates the {@link TargetFilterQuery}.
*
* @param update to be updated
* @return the updated {@link TargetFilterQuery}
* @throws EntityNotFoundException if either {@link TargetFilterQuery} and/or autoAssignDs are
* provided but not found
* @throws ConstraintViolationException if fields are not filled as specified. Check
* {@link TargetFilterQueryUpdate} for field constraints.
* @throws QuotaExceededException if the update contains a new query which addresses too many
* targets (auto-assignments only)
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
TargetFilterQuery update(@NotNull @Valid TargetFilterQueryUpdate update);
/** /**
* Updates the auto assign settings of an {@link TargetFilterQuery}. * Updates the auto assign settings of an {@link TargetFilterQuery}.
* *
@@ -224,8 +113,7 @@ public interface TargetFilterQueryManagement {
* invalidated * invalidated
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
TargetFilterQuery updateAutoAssignDS( TargetFilterQuery updateAutoAssignDS(@NotNull @Valid AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate);
@NotNull @Valid AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate);
/** /**
* Removes the given {@link DistributionSet} from all auto assignments. * Removes the given {@link DistributionSet} from all auto assignments.
@@ -235,4 +123,118 @@ public interface TargetFilterQueryManagement {
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
void cancelAutoAssignmentForDistributionSet(long setId); void cancelAutoAssignmentForDistributionSet(long setId);
@SuperBuilder
@Getter
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
final class Create extends UpdateCreate {
private DistributionSet autoAssignDistributionSet;
private ActionType autoAssignActionType;
@Setter
@Min(Action.WEIGHT_MIN)
@Max(Action.WEIGHT_MAX)
private Integer autoAssignWeight;
private boolean confirmationRequired;
}
@SuperBuilder
@Getter
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
final class Update extends UpdateCreate implements Identifiable<Long> {
@NotNull
private Long id;
}
@SuperBuilder
@Getter
class UpdateCreate {
@ValidString
@Size(min = 1, max = NamedEntity.NAME_MAX_SIZE)
@NotNull(groups = DistributionSetTagManagement.Create.class)
private String name;
@ValidString
@Size(min = 1, max = TargetFilterQuery.QUERY_MAX_SIZE)
private String query;
}
/**
* Builder to update the auto assign {@link DistributionSet} of a
* {@link TargetFilterQuery} entry. Defines all fields that can be updated.
*/
@Data
@Accessors(fluent = true)
@EqualsAndHashCode
@ToString
class AutoAssignDistributionSetUpdate {
private final long targetFilterId;
private Long dsId;
private ActionType actionType;
@Min(Action.WEIGHT_MIN)
@Max(Action.WEIGHT_MAX)
private Integer weight;
private Boolean confirmationRequired;
/**
* Constructor
*
* @param targetFilterId ID of {@link TargetFilterQuery} to update
*/
public AutoAssignDistributionSetUpdate(final long targetFilterId) {
this.targetFilterId = targetFilterId;
}
/**
* Specify {@link DistributionSet}
*
* @param dsId ID of the {@link DistributionSet}
* @return updated builder instance
*/
public AutoAssignDistributionSetUpdate ds(final Long dsId) {
this.dsId = dsId;
return this;
}
/**
* Specify {@link DistributionSet}
*
* @param actionType {@link ActionType} used for the auto assignment
* @return updated builder instance
*/
public AutoAssignDistributionSetUpdate actionType(final ActionType actionType) {
this.actionType = actionType;
return this;
}
/**
* Specify weight of resulting {@link Action}
*
* @param weight weight used for the auto assignment
* @return updated builder instance
*/
public AutoAssignDistributionSetUpdate weight(final Integer weight) {
this.weight = weight;
return this;
}
/**
* Specify initial confirmation state of resulting {@link Action}
*
* @param confirmationRequired if confirmation is required for this auto assignment (considered
* with confirmation flow active)
* @return updated builder instance
*/
public AutoAssignDistributionSetUpdate confirmationRequired(final boolean confirmationRequired) {
this.confirmationRequired = confirmationRequired;
return this;
}
}
} }

View File

@@ -1,95 +0,0 @@
/**
* Copyright (c) 2019 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.builder;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
/**
* Builder to update the auto assign {@link DistributionSet} of a
* {@link TargetFilterQuery} entry. Defines all fields that can be updated.
*/
@Getter
@EqualsAndHashCode
@ToString
public class AutoAssignDistributionSetUpdate {
private final long targetFilterId;
private Long dsId;
private ActionType actionType;
@Min(Action.WEIGHT_MIN)
@Max(Action.WEIGHT_MAX)
private Integer weight;
private Boolean confirmationRequired;
/**
* Constructor
*
* @param targetFilterId ID of {@link TargetFilterQuery} to update
*/
public AutoAssignDistributionSetUpdate(final long targetFilterId) {
this.targetFilterId = targetFilterId;
}
/**
* Specify {@link DistributionSet}
*
* @param dsId ID of the {@link DistributionSet}
* @return updated builder instance
*/
public AutoAssignDistributionSetUpdate ds(final Long dsId) {
this.dsId = dsId;
return this;
}
/**
* Specify {@link DistributionSet}
*
* @param actionType {@link ActionType} used for the auto assignment
* @return updated builder instance
*/
public AutoAssignDistributionSetUpdate actionType(final ActionType actionType) {
this.actionType = actionType;
return this;
}
/**
* Specify weight of resulting {@link Action}
*
* @param weight weight used for the auto assignment
* @return updated builder instance
*/
public AutoAssignDistributionSetUpdate weight(final Integer weight) {
this.weight = weight;
return this;
}
/**
* Specify initial confirmation state of resulting {@link Action}
*
* @param confirmationRequired if confirmation is required for this auto assignment (considered
* with confirmation flow active)
* @return updated builder instance
*/
public AutoAssignDistributionSetUpdate confirmationRequired(final boolean confirmationRequired) {
this.confirmationRequired = confirmationRequired;
return this;
}
}

View File

@@ -1,39 +0,0 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.hawkbit.repository.builder;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
/**
* Builder for {@link TargetFilterQuery}.
*/
public interface TargetFilterQueryBuilder {
/**
* Used to update a {@link TargetFilterQuery}
*
* @param id of the updatable entity
* @return builder instance
*/
TargetFilterQueryUpdate update(long id);
/**
* Used to update a the auto assignment of a {@link TargetFilterQuery}
*
* @param id of the updatable entity
* @return builder instance
*/
AutoAssignDistributionSetUpdate updateAutoAssign(long id);
/**
* @return builder instance
*/
TargetFilterQueryCreate create();
}

View File

@@ -1,95 +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.builder;
import java.util.Optional;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.repository.model.BaseEntity;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
/**
* Builder to create a new {@link TargetFilterQuery} entry. Defines all fields
* that can be set at creation time. Other fields are set by the repository
* automatically, e.g. {@link BaseEntity#getCreatedAt()}.
*/
public interface TargetFilterQueryCreate {
/**
* Set filter name
*
* @param name of {@link TargetFilterQuery#getName()}
* @return updated builder instance
*/
TargetFilterQueryCreate name(@Size(min = 1, max = NamedEntity.NAME_MAX_SIZE) @NotNull String name);
/**
* Set filter query
*
* @param query of {@link TargetFilterQuery#getQuery()}
* @return updated builder instance
*/
TargetFilterQueryCreate query(@Size(min = 1, max = TargetFilterQuery.QUERY_MAX_SIZE) @NotNull String query);
/**
* Set {@link DistributionSet} for auto assignment
*
* @param distributionSet for {@link TargetFilterQuery#getAutoAssignDistributionSet()}
* @return updated builder instance
*/
default TargetFilterQueryCreate autoAssignDistributionSet(final DistributionSet distributionSet) {
return autoAssignDistributionSet(Optional.ofNullable(distributionSet).map(DistributionSet::getId).orElse(null));
}
/**
* Set ID of {@link DistributionSet} for auto assignment
*
* @param dsId for {@link TargetFilterQuery#getAutoAssignDistributionSet()}
* @return updated builder instance
*/
TargetFilterQueryCreate autoAssignDistributionSet(Long dsId);
/**
* Set {@link ActionType} for auto assignment
*
* @param actionType for {@link TargetFilterQuery#getAutoAssignActionType()}
* @return updated builder instance
*/
TargetFilterQueryCreate autoAssignActionType(ActionType actionType);
/**
* Set weight of {@link Action} created during auto assignment
*
* @param weight weight of {@link Action} generated within auto assignment
* @return updated builder instance
*/
TargetFilterQueryCreate autoAssignWeight(Integer weight);
/**
* Specify initial confirmation state of resulting {@link Action} in auto
* assignment
*
* @param confirmationRequired if confirmation is required for configured auto assignment (considered
* with confirmation flow active)
* @return updated builder instance
*/
TargetFilterQueryCreate confirmationRequired(boolean confirmationRequired);
/**
* @return peek on current state of {@link TargetFilterQuery} in the builder
*/
TargetFilterQuery build();
}

View File

@@ -1,34 +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.builder;
import jakarta.validation.constraints.Size;
import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
/**
* Builder to update an existing {@link TargetFilterQuery} entry. Defines all
* fields that can be updated.
*/
public interface TargetFilterQueryUpdate {
/**
* @param name of {@link TargetFilterQuery#getName()}
* @return updated builder instance
*/
TargetFilterQueryUpdate name(@Size(min = 1, max = NamedEntity.NAME_MAX_SIZE) String name);
/**
* @param query of {@link TargetFilterQuery#getQuery()}
* @return updated builder instance
*/
TargetFilterQueryUpdate query(@Size(min = 1, max = TargetFilterQuery.QUERY_MAX_SIZE) String query);
}

View File

@@ -1,129 +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.builder;
import java.util.Optional;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import org.eclipse.hawkbit.repository.ValidString;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
/**
* Create and update builder DTO.
*
* @param <T> update or create builder interface
*/
public abstract class AbstractTargetFilterQueryUpdateCreate<T> extends AbstractBaseEntityBuilder {
@ValidString
protected String name;
@ValidString
protected String query;
protected Long distributionSetId;
protected ActionType actionType;
@Min(Action.WEIGHT_MIN)
@Max(Action.WEIGHT_MAX)
protected Integer weight;
protected Boolean confirmationRequired;
/**
* Set DS ID of the {@link Action} created during auto assignment
*
* @param distributionSetId of the {@link TargetFilterQuery}
* @return this builder
*/
public T autoAssignDistributionSet(final Long distributionSetId) {
this.distributionSetId = distributionSetId;
return (T) this;
}
public Optional<Long> getAutoAssignDistributionSetId() {
return Optional.ofNullable(distributionSetId);
}
/**
* Set {@link ActionType} of the {@link Action} created during auto
* assignment
*
* @param actionType of the {@link TargetFilterQuery}
* @return this builder
*/
public T autoAssignActionType(final ActionType actionType) {
this.actionType = actionType;
return (T) this;
}
/**
* Set weight of the {@link Action} created during auto assignment
*
* @param weight of the {@link TargetFilterQuery}
* @return this builder
*/
public T autoAssignWeight(final Integer weight) {
this.weight = weight;
return (T) this;
}
public Optional<Integer> getAutoAssignWeight() {
return Optional.ofNullable(weight);
}
public Optional<ActionType> getAutoAssignActionType() {
return Optional.ofNullable(actionType);
}
/**
* Set name of the filter
*
* @param name of the {@link TargetFilterQuery}
* @return this builder
*/
public T name(final String name) {
this.name = AbstractBaseEntityBuilder.strip(name);
return (T) this;
}
public Optional<String> getName() {
return Optional.ofNullable(name);
}
/**
* Set query used by the filter
*
* @param query of the {@link TargetFilterQuery}
* @return this builder
*/
public T query(final String query) {
this.query = AbstractBaseEntityBuilder.strip(query);
return (T) this;
}
public Optional<String> getQuery() {
return Optional.ofNullable(query);
}
/**
* @param confirmationRequired if confirmation is required for configured auto assignment
* (considered with confirmation flow active)
* @return updated builder instance
*/
public T confirmationRequired(final boolean confirmationRequired) {
this.confirmationRequired = confirmationRequired;
return (T) this;
}
public Optional<Boolean> getConfirmationRequired() {
return Optional.ofNullable(confirmationRequired);
}
}

View File

@@ -1,21 +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.builder;
/**
* Update implementation.
*/
public class GenericTargetFilterQueryUpdate extends AbstractTargetFilterQueryUpdateCreate<TargetFilterQueryUpdate>
implements TargetFilterQueryUpdate {
public GenericTargetFilterQueryUpdate(final Long id) {
super.id = id;
}
}

View File

@@ -14,7 +14,6 @@ import org.eclipse.hawkbit.repository.builder.ActionStatusBuilder;
import org.eclipse.hawkbit.repository.builder.RolloutBuilder; import org.eclipse.hawkbit.repository.builder.RolloutBuilder;
import org.eclipse.hawkbit.repository.builder.RolloutGroupBuilder; import org.eclipse.hawkbit.repository.builder.RolloutGroupBuilder;
import org.eclipse.hawkbit.repository.builder.TargetBuilder; import org.eclipse.hawkbit.repository.builder.TargetBuilder;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryBuilder;
import org.eclipse.hawkbit.repository.jpa.builder.JpaActionStatusBuilder; import org.eclipse.hawkbit.repository.jpa.builder.JpaActionStatusBuilder;
import org.eclipse.hawkbit.repository.jpa.builder.JpaRolloutGroupBuilder; import org.eclipse.hawkbit.repository.jpa.builder.JpaRolloutGroupBuilder;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@@ -26,17 +25,20 @@ import org.springframework.validation.annotation.Validated;
public class JpaEntityFactory implements EntityFactory { public class JpaEntityFactory implements EntityFactory {
private final TargetBuilder targetBuilder; private final TargetBuilder targetBuilder;
private final TargetFilterQueryBuilder targetFilterQueryBuilder;
private final RolloutBuilder rolloutBuilder; private final RolloutBuilder rolloutBuilder;
@SuppressWarnings("java:S107") @SuppressWarnings("java:S107")
public JpaEntityFactory( public JpaEntityFactory(
final TargetBuilder targetBuilder, final TargetFilterQueryBuilder targetFilterQueryBuilder, final TargetBuilder targetBuilder, final RolloutBuilder rolloutBuilder) {
final RolloutBuilder rolloutBuilder) {
this.targetBuilder = targetBuilder; this.targetBuilder = targetBuilder;
this.targetFilterQueryBuilder = targetFilterQueryBuilder;
this.rolloutBuilder = rolloutBuilder; this.rolloutBuilder = rolloutBuilder;
} }
@Override
public TargetBuilder target() {
return targetBuilder;
}
@Override @Override
public ActionStatusBuilder actionStatus() { public ActionStatusBuilder actionStatus() {
return new JpaActionStatusBuilder(); return new JpaActionStatusBuilder();
@@ -51,14 +53,4 @@ public class JpaEntityFactory implements EntityFactory {
public RolloutBuilder rollout() { public RolloutBuilder rollout() {
return rolloutBuilder; return rolloutBuilder;
} }
@Override
public TargetBuilder target() {
return targetBuilder;
}
@Override
public TargetFilterQueryBuilder targetFilterQuery() {
return targetFilterQueryBuilder;
}
} }

View File

@@ -44,7 +44,6 @@ import org.eclipse.hawkbit.repository.artifact.encryption.ArtifactEncryptionServ
import org.eclipse.hawkbit.repository.autoassign.AutoAssignExecutor; import org.eclipse.hawkbit.repository.autoassign.AutoAssignExecutor;
import org.eclipse.hawkbit.repository.builder.RolloutBuilder; import org.eclipse.hawkbit.repository.builder.RolloutBuilder;
import org.eclipse.hawkbit.repository.builder.TargetBuilder; import org.eclipse.hawkbit.repository.builder.TargetBuilder;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryBuilder;
import org.eclipse.hawkbit.repository.event.ApplicationEventFilter; import org.eclipse.hawkbit.repository.event.ApplicationEventFilter;
import org.eclipse.hawkbit.repository.event.remote.EventEntityManager; import org.eclipse.hawkbit.repository.event.remote.EventEntityManager;
import org.eclipse.hawkbit.repository.event.remote.EventEntityManagerHolder; import org.eclipse.hawkbit.repository.event.remote.EventEntityManagerHolder;
@@ -58,7 +57,6 @@ import org.eclipse.hawkbit.repository.jpa.autocleanup.AutoCleanupScheduler;
import org.eclipse.hawkbit.repository.jpa.autocleanup.CleanupTask; import org.eclipse.hawkbit.repository.jpa.autocleanup.CleanupTask;
import org.eclipse.hawkbit.repository.jpa.builder.JpaRolloutBuilder; import org.eclipse.hawkbit.repository.jpa.builder.JpaRolloutBuilder;
import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetBuilder; import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetBuilder;
import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetFilterQueryBuilder;
import org.eclipse.hawkbit.repository.jpa.cluster.DistributedLockRepository; import org.eclipse.hawkbit.repository.jpa.cluster.DistributedLockRepository;
import org.eclipse.hawkbit.repository.jpa.cluster.LockProperties; import org.eclipse.hawkbit.repository.jpa.cluster.LockProperties;
import org.eclipse.hawkbit.repository.jpa.event.JpaEventEntityManager; import org.eclipse.hawkbit.repository.jpa.event.JpaEventEntityManager;
@@ -316,16 +314,6 @@ public class JpaRepositoryConfiguration {
return new JpaRolloutBuilder(distributionSetManagement); return new JpaRolloutBuilder(distributionSetManagement);
} }
/**
* @param distributionSetManagement for loading
* {@link TargetFilterQuery#getAutoAssignDistributionSet()}
* @return TargetFilterQueryBuilder bean
*/
@Bean
TargetFilterQueryBuilder targetFilterQueryBuilder(final DistributionSetManagement<? extends DistributionSet> distributionSetManagement) {
return new JpaTargetFilterQueryBuilder(distributionSetManagement);
}
/** /**
* @return the {@link SystemSecurityContext} singleton bean which make it * @return the {@link SystemSecurityContext} singleton bean which make it
* accessible in beans which cannot access the service directly, e.g. * accessible in beans which cannot access the service directly, e.g.
@@ -436,10 +424,8 @@ public class JpaRepositoryConfiguration {
*/ */
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
EntityFactory entityFactory( EntityFactory entityFactory(final TargetBuilder targetBuilder, final RolloutBuilder rolloutBuilder) {
final TargetBuilder targetBuilder, final TargetFilterQueryBuilder targetFilterQueryBuilder, return new JpaEntityFactory(targetBuilder, rolloutBuilder);
final RolloutBuilder rolloutBuilder) {
return new JpaEntityFactory(targetBuilder, targetFilterQueryBuilder, rolloutBuilder);
} }
/** /**

View File

@@ -1,46 +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.builder;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate;
import org.eclipse.hawkbit.repository.builder.GenericTargetFilterQueryUpdate;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryBuilder;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryCreate;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryUpdate;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
/**
* Builder implementation for {@link TargetFilterQuery}.
*/
public class JpaTargetFilterQueryBuilder implements TargetFilterQueryBuilder {
private final DistributionSetManagement<? extends DistributionSet> distributionSetManagement;
public JpaTargetFilterQueryBuilder(final DistributionSetManagement<? extends DistributionSet> distributionSetManagement) {
this.distributionSetManagement = distributionSetManagement;
}
@Override
public TargetFilterQueryUpdate update(final long id) {
return new GenericTargetFilterQueryUpdate(id);
}
@Override
public AutoAssignDistributionSetUpdate updateAutoAssign(final long id) {
return new AutoAssignDistributionSetUpdate(id);
}
@Override
public TargetFilterQueryCreate create() {
return new JpaTargetFilterQueryCreate(distributionSetManagement);
}
}

View File

@@ -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.builder;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.builder.AbstractTargetFilterQueryUpdateCreate;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryCreate;
import org.eclipse.hawkbit.repository.exception.InvalidAutoAssignActionTypeException;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetFilterQuery;
import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
/**
* Create/build implementation.
*/
public class JpaTargetFilterQueryCreate extends AbstractTargetFilterQueryUpdateCreate<TargetFilterQueryCreate>
implements TargetFilterQueryCreate {
private final DistributionSetManagement<? extends DistributionSet> distributionSetManagement;
JpaTargetFilterQueryCreate(final DistributionSetManagement<? extends DistributionSet> distributionSetManagement) {
this.distributionSetManagement = distributionSetManagement;
}
@Override
public JpaTargetFilterQuery build() {
return new JpaTargetFilterQuery(name, query,
getAutoAssignDistributionSetId().map(distributionSetManagement::getValidAndComplete).orElse(null),
getAutoAssignActionType().filter(JpaTargetFilterQueryCreate::isAutoAssignActionTypeValid).orElse(null),
weight, getConfirmationRequired().orElse(false));
}
private static boolean isAutoAssignActionTypeValid(final ActionType actionType) {
if (!TargetFilterQuery.ALLOWED_AUTO_ASSIGN_ACTION_TYPES.contains(actionType)) {
throw new InvalidAutoAssignActionTypeException();
}
return true;
}
}

View File

@@ -99,7 +99,6 @@ import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice; import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.domain.Specification;
import org.springframework.orm.jpa.vendor.Database; import org.springframework.orm.jpa.vendor.Database;
import org.springframework.retry.RetryCallback;
import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable; import org.springframework.retry.annotation.Retryable;
import org.springframework.retry.backoff.FixedBackOffPolicy; import org.springframework.retry.backoff.FixedBackOffPolicy;
@@ -122,28 +121,15 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
* Maximum amount of Actions that are started at once. * Maximum amount of Actions that are started at once.
*/ */
private static final int ACTION_PAGE_LIMIT = 1000; private static final int ACTION_PAGE_LIMIT = 1000;
private static final String QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED_DEFAULT = private static final String QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED_DEFAULT = "DELETE FROM sp_action " + "WHERE tenant=" + Jpa.nativeQueryParamPrefix() + "tenant" + " AND status IN (%s)" + " AND last_modified_at<" + Jpa.nativeQueryParamPrefix() + "last_modified_at LIMIT " + ACTION_PAGE_LIMIT;
"DELETE FROM sp_action " +
"WHERE tenant=" + Jpa.nativeQueryParamPrefix() + "tenant" +
" AND status IN (%s)" +
" AND last_modified_at<" + Jpa.nativeQueryParamPrefix() + "last_modified_at LIMIT " + ACTION_PAGE_LIMIT;
private static final EnumMap<Database, String> QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED; private static final EnumMap<Database, String> QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED;
static { static {
QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED = new EnumMap<>(Database.class); QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED = new EnumMap<>(Database.class);
QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED.put( QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED.put(Database.SQL_SERVER,
Database.SQL_SERVER, "DELETE TOP (" + ACTION_PAGE_LIMIT + ") FROM sp_action " + "WHERE tenant=" + Jpa.nativeQueryParamPrefix() + "tenant" + " AND status IN (%s)" + " AND last_modified_at<" + Jpa.nativeQueryParamPrefix() + "last_modified_at ");
"DELETE TOP (" + ACTION_PAGE_LIMIT + ") FROM sp_action " + QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED.put(Database.POSTGRESQL,
"WHERE tenant=" + Jpa.nativeQueryParamPrefix() + "tenant" + "DELETE FROM sp_action " + "WHERE id IN (SELECT id FROM sp_action " + "WHERE tenant=" + Jpa.nativeQueryParamPrefix() + "tenant" + " AND status IN (%s)" + " AND last_modified_at<" + Jpa.nativeQueryParamPrefix() + "last_modified_at LIMIT " + ACTION_PAGE_LIMIT + ")");
" AND status IN (%s)" +
" AND last_modified_at<" + Jpa.nativeQueryParamPrefix() + "last_modified_at ");
QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED.put(
Database.POSTGRESQL,
"DELETE FROM sp_action " +
"WHERE id IN (SELECT id FROM sp_action " +
"WHERE tenant=" + Jpa.nativeQueryParamPrefix() + "tenant" +
" AND status IN (%s)" +
" AND last_modified_at<" + Jpa.nativeQueryParamPrefix() + "last_modified_at LIMIT " + ACTION_PAGE_LIMIT + ")");
} }
private final EntityManager entityManager; private final EntityManager entityManager;
@@ -161,8 +147,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
private final RetryTemplate retryTemplate; private final RetryTemplate retryTemplate;
@SuppressWarnings("java:S107") @SuppressWarnings("java:S107")
protected JpaDeploymentManagement( protected JpaDeploymentManagement(final EntityManager entityManager, final ActionRepository actionRepository,
final EntityManager entityManager, final ActionRepository actionRepository,
final JpaDistributionSetManagement distributionSetManagement, final TargetRepository targetRepository, final JpaDistributionSetManagement distributionSetManagement, final TargetRepository targetRepository,
final ActionStatusRepository actionStatusRepository, final AuditorAware<String> auditorProvider, final ActionStatusRepository actionStatusRepository, final AuditorAware<String> auditorProvider,
final AfterTransactionCommitExecutor afterCommit, final PlatformTransactionManager txManager, final AfterTransactionCommitExecutor afterCommit, final PlatformTransactionManager txManager,
@@ -175,12 +160,10 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
this.targetRepository = targetRepository; this.targetRepository = targetRepository;
this.auditorProvider = auditorProvider; this.auditorProvider = auditorProvider;
this.txManager = txManager; this.txManager = txManager;
onlineDsAssignmentStrategy = new OnlineDsAssignmentStrategy(targetRepository, afterCommit, onlineDsAssignmentStrategy = new OnlineDsAssignmentStrategy(targetRepository, afterCommit, actionRepository, actionStatusRepository,
actionRepository, actionStatusRepository, quotaManagement, this::isMultiAssignmentsEnabled, quotaManagement, this::isMultiAssignmentsEnabled, this::isConfirmationFlowEnabled, repositoryProperties);
this::isConfirmationFlowEnabled, repositoryProperties); offlineDsAssignmentStrategy = new OfflineDsAssignmentStrategy(targetRepository, afterCommit, actionRepository, actionStatusRepository,
offlineDsAssignmentStrategy = new OfflineDsAssignmentStrategy(targetRepository, afterCommit, quotaManagement, this::isMultiAssignmentsEnabled, this::isConfirmationFlowEnabled, repositoryProperties);
actionRepository, actionStatusRepository, quotaManagement,
this::isMultiAssignmentsEnabled, this::isConfirmationFlowEnabled, repositoryProperties);
this.tenantConfigurationManagement = tenantConfigurationManagement; this.tenantConfigurationManagement = tenantConfigurationManagement;
this.systemSecurityContext = systemSecurityContext; this.systemSecurityContext = systemSecurityContext;
this.tenantAware = tenantAware; this.tenantAware = tenantAware;
@@ -197,30 +180,28 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
@Override @Override
@Transactional(isolation = Isolation.READ_COMMITTED) @Transactional(isolation = Isolation.READ_COMMITTED)
public List<DistributionSetAssignmentResult> assignDistributionSets( public List<DistributionSetAssignmentResult> assignDistributionSets(final String initiatedBy,
final String initiatedBy, final List<DeploymentRequest> deploymentRequests, final String actionMessage) { final List<DeploymentRequest> deploymentRequests, final String actionMessage) {
return assignDistributionSets0(initiatedBy, deploymentRequests, actionMessage); return assignDistributionSets0(initiatedBy, deploymentRequests, actionMessage);
} }
private List<DistributionSetAssignmentResult> assignDistributionSets0( private List<DistributionSetAssignmentResult> assignDistributionSets0(final String initiatedBy,
final String initiatedBy, final List<DeploymentRequest> deploymentRequests, final String actionMessage) { final List<DeploymentRequest> deploymentRequests, final String actionMessage) {
WeightValidationHelper.usingContext(systemSecurityContext, tenantConfigurationManagement).validate(deploymentRequests); WeightValidationHelper.usingContext(systemSecurityContext, tenantConfigurationManagement).validate(deploymentRequests);
return assignDistributionSets(initiatedBy, deploymentRequests, actionMessage, onlineDsAssignmentStrategy); return assignDistributionSets(initiatedBy, deploymentRequests, actionMessage, onlineDsAssignmentStrategy);
} }
@Override @Override
public List<DistributionSetAssignmentResult> offlineAssignedDistributionSets( public List<DistributionSetAssignmentResult> offlineAssignedDistributionSets(final Collection<Entry<String, Long>> assignments,
final Collection<Entry<String, Long>> assignments, final String initiatedBy) { final String initiatedBy) {
final Collection<Entry<String, Long>> distinctAssignments = assignments.stream().distinct().toList(); final Collection<Entry<String, Long>> distinctAssignments = assignments.stream().distinct().toList();
enforceMaxAssignmentsPerRequest(distinctAssignments.size()); enforceMaxAssignmentsPerRequest(distinctAssignments.size());
final List<DeploymentRequest> deploymentRequests = distinctAssignments.stream() final List<DeploymentRequest> deploymentRequests = distinctAssignments.stream()
.map(entry -> DeploymentManagement.deploymentRequest(entry.getKey(), entry.getValue()).build()) .map(entry -> DeploymentManagement.deploymentRequest(entry.getKey(), entry.getValue()).build()).toList();
.toList();
return assignDistributionSets( return assignDistributionSets(auditorAware.getCurrentAuditor().orElse(tenantAware.getCurrentUsername()), deploymentRequests, null,
auditorAware.getCurrentAuditor().orElse(tenantAware.getCurrentUsername()), offlineDsAssignmentStrategy);
deploymentRequests, null, offlineDsAssignmentStrategy);
} }
@Override @Override
@@ -231,8 +212,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
@Override @Override
@Transactional(isolation = Isolation.READ_COMMITTED) @Transactional(isolation = Isolation.READ_COMMITTED)
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, @Retryable(retryFor = {
backoff = @Backoff(delay = Constants.TX_RT_DELAY)) ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
public Action cancelAction(final long actionId) { public Action cancelAction(final long actionId) {
return cancelAction0(actionId); return cancelAction0(actionId);
} }
@@ -240,8 +221,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
private Action cancelAction0(final long actionId) { private Action cancelAction0(final long actionId) {
log.debug("cancelAction({})", actionId); log.debug("cancelAction({})", actionId);
final JpaAction action = actionRepository.findById(actionId) final JpaAction action = actionRepository.findById(actionId).orElseThrow(() -> new EntityNotFoundException(Action.class, actionId));
.orElseThrow(() -> new EntityNotFoundException(Action.class, actionId));
if (action.isCancelingOrCanceled()) { if (action.isCancelingOrCanceled()) {
throw new CancelActionNotAllowedException("Actions in canceling or canceled state cannot be canceled"); throw new CancelActionNotAllowedException("Actions in canceling or canceled state cannot be canceled");
@@ -297,8 +277,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
@Override @Override
public Optional<Action> findAction(final long actionId) { public Optional<Action> findAction(final long actionId) {
return actionRepository.findById(actionId) return actionRepository.findById(actionId)
.filter(action -> targetRepository.exists(TargetSpecifications.hasId(action.getTarget().getId()))) .filter(action -> targetRepository.exists(TargetSpecifications.hasId(action.getTarget().getId()))).map(JpaAction.class::cast);
.map(JpaAction.class::cast);
} }
@Override @Override
@@ -326,8 +305,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
@Override @Override
public Slice<Action> findActionsByTarget(final String controllerId, final Pageable pageable) { public Slice<Action> findActionsByTarget(final String controllerId, final Pageable pageable) {
assertTargetReadAllowed(controllerId); assertTargetReadAllowed(controllerId);
return actionRepository.findAll(ActionSpecifications.byTargetControllerId(controllerId), pageable) return actionRepository.findAll(ActionSpecifications.byTargetControllerId(controllerId), pageable).map(Action.class::cast);
.map(Action.class::cast);
} }
@Override @Override
@@ -357,8 +335,9 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
final CriteriaQuery<String> selMsgQuery = msgQuery.select(join); final CriteriaQuery<String> selMsgQuery = msgQuery.select(join);
selMsgQuery.where(cb.equal(as.get(AbstractJpaBaseEntity_.id), actionStatusId)); selMsgQuery.where(cb.equal(as.get(AbstractJpaBaseEntity_.id), actionStatusId));
final List<String> result = new ArrayList<>(entityManager.createQuery(selMsgQuery) final List<String> result = new ArrayList<>(
.setFirstResult((int) pageable.getOffset()).setMaxResults(pageable.getPageSize()).getResultList()); entityManager.createQuery(selMsgQuery).setFirstResult((int) pageable.getOffset()).setMaxResults(pageable.getPageSize())
.getResultList());
return new PageImpl<>(result, pageable, result.size()); return new PageImpl<>(result, pageable, result.size());
} }
@@ -372,16 +351,14 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
@Override @Override
public Page<Action> findActiveActionsByTarget(final String controllerId, final Pageable pageable) { public Page<Action> findActiveActionsByTarget(final String controllerId, final Pageable pageable) {
assertTargetReadAllowed(controllerId); assertTargetReadAllowed(controllerId);
return actionRepository return actionRepository.findAll(ActionSpecifications.byTargetControllerIdAndActive(controllerId, true), pageable)
.findAll(ActionSpecifications.byTargetControllerIdAndActive(controllerId, true), pageable)
.map(Action.class::cast); .map(Action.class::cast);
} }
@Override @Override
public Page<Action> findInActiveActionsByTarget(final String controllerId, final Pageable pageable) { public Page<Action> findInActiveActionsByTarget(final String controllerId, final Pageable pageable) {
assertTargetReadAllowed(controllerId); assertTargetReadAllowed(controllerId);
return actionRepository return actionRepository.findAll(ActionSpecifications.byTargetControllerIdAndActive(controllerId, false), pageable)
.findAll(ActionSpecifications.byTargetControllerIdAndActive(controllerId, false), pageable)
.map(Action.class::cast); .map(Action.class::cast);
} }
@@ -393,15 +370,14 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
@Override @Override
@Transactional(isolation = Isolation.READ_COMMITTED) @Transactional(isolation = Isolation.READ_COMMITTED)
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, @Retryable(retryFor = {
backoff = @Backoff(delay = Constants.TX_RT_DELAY)) ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
public Action forceQuitAction(final long actionId) { public Action forceQuitAction(final long actionId) {
return forceQuitAction0(actionId); return forceQuitAction0(actionId);
} }
private Action forceQuitAction0(final long actionId) { private Action forceQuitAction0(final long actionId) {
final JpaAction action = actionRepository.findById(actionId) final JpaAction action = actionRepository.findById(actionId).orElseThrow(() -> new EntityNotFoundException(Action.class, actionId));
.orElseThrow(() -> new EntityNotFoundException(Action.class, actionId));
if (!action.isCancelingOrCanceled()) { if (!action.isCancelingOrCanceled()) {
throw new ForceQuitActionNotAllowedException(action.getId() + " is not canceled yet and cannot be force quit"); throw new ForceQuitActionNotAllowedException(action.getId() + " is not canceled yet and cannot be force quit");
@@ -426,8 +402,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
@Override @Override
@Transactional @Transactional
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, @Retryable(retryFor = {
backoff = @Backoff(delay = Constants.TX_RT_DELAY)) ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
public Action forceTargetAction(final long actionId) { public Action forceTargetAction(final long actionId) {
final JpaAction action = actionRepository.findById(actionId).map(this::assertTargetUpdateAllowed) final JpaAction action = actionRepository.findById(actionId).map(this::assertTargetUpdateAllowed)
.orElseThrow(() -> new EntityNotFoundException(Action.class, actionId)); .orElseThrow(() -> new EntityNotFoundException(Action.class, actionId));
@@ -441,8 +417,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
@Override @Override
@Transactional(isolation = Isolation.READ_COMMITTED) @Transactional(isolation = Isolation.READ_COMMITTED)
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, @Retryable(retryFor = {
backoff = @Backoff(delay = Constants.TX_RT_DELAY)) ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
public void cancelInactiveScheduledActionsForTargets(final List<Long> targetIds) { public void cancelInactiveScheduledActionsForTargets(final List<Long> targetIds) {
if (!isMultiAssignmentsEnabled()) { if (!isMultiAssignmentsEnabled()) {
targetRepository.getAccessController().ifPresent(v -> { targetRepository.getAccessController().ifPresent(v -> {
@@ -458,38 +434,32 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
@Override @Override
public void startScheduledActionsByRolloutGroupParent(final long rolloutId, final long distributionSetId, final Long rolloutGroupParentId) { public void startScheduledActionsByRolloutGroupParent(final long rolloutId, final long distributionSetId, final Long rolloutGroupParentId) {
while (DeploymentHelper.runInNewTransaction( while (DeploymentHelper.runInNewTransaction(txManager, "startScheduledActions-" + rolloutId, status -> {
txManager, final PageRequest pageRequest = PageRequest.of(0, ACTION_PAGE_LIMIT);
"startScheduledActions-" + rolloutId, final Page<Action> groupScheduledActions;
status -> { if (rolloutGroupParentId == null) {
final PageRequest pageRequest = PageRequest.of(0, ACTION_PAGE_LIMIT); groupScheduledActions = actionRepository.findByRolloutIdAndRolloutGroupParentIsNullAndStatus(pageRequest, rolloutId,
final Page<Action> groupScheduledActions; Action.Status.SCHEDULED);
if (rolloutGroupParentId == null) { } else {
groupScheduledActions = actionRepository.findByRolloutIdAndRolloutGroupParentIsNullAndStatus(pageRequest, rolloutId, groupScheduledActions = actionRepository.findByRolloutIdAndRolloutGroupParentIdAndStatus(pageRequest, rolloutId,
Action.Status.SCHEDULED); rolloutGroupParentId, Action.Status.SCHEDULED);
} else { }
groupScheduledActions = actionRepository.findByRolloutIdAndRolloutGroupParentIdAndStatus(pageRequest, rolloutId,
rolloutGroupParentId, Action.Status.SCHEDULED);
}
if (groupScheduledActions.getContent().isEmpty()) { if (groupScheduledActions.getContent().isEmpty()) {
return 0L; return 0L;
} else { } else {
// self invocation won't check @PreAuthorize but it is already checked for the method // self invocation won't check @PreAuthorize but it is already checked for the method
startScheduledActions(groupScheduledActions.getContent()); startScheduledActions(groupScheduledActions.getContent());
return groupScheduledActions.getTotalElements(); return groupScheduledActions.getTotalElements();
} }
}) > 0) ; }) > 0) ;
} }
@Override @Override
public void startScheduledActions(final List<Action> rolloutGroupActions) { public void startScheduledActions(final List<Action> rolloutGroupActions) {
// Close actions already assigned and collect pending assignments // Close actions already assigned and collect pending assignments
final List<JpaAction> pendingTargetAssignments = rolloutGroupActions.stream() final List<JpaAction> pendingTargetAssignments = rolloutGroupActions.stream().map(JpaAction.class::cast)
.map(JpaAction.class::cast) .map(this::closeActionIfSetWasAlreadyAssigned).filter(Objects::nonNull).toList();
.map(this::closeActionIfSetWasAlreadyAssigned)
.filter(Objects::nonNull)
.toList();
if (pendingTargetAssignments.isEmpty()) { if (pendingTargetAssignments.isEmpty()) {
return; return;
} }
@@ -524,9 +494,9 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
// the database. // the database.
final List<Integer> statusList = status.stream().map(Status::ordinal).toList(); final List<Integer> statusList = status.stream().map(Status::ordinal).toList();
final Query deleteQuery = entityManager.createNativeQuery(String.format( final Query deleteQuery = entityManager.createNativeQuery(
getQueryForDeleteActionsByStatusAndLastModifiedBeforeString(database), String.format(getQueryForDeleteActionsByStatusAndLastModifiedBeforeString(database),
Jpa.formatNativeQueryInClause("status", statusList))); Jpa.formatNativeQueryInClause("status", statusList)));
deleteQuery.setParameter("tenant", tenantAware.getCurrentTenant().toUpperCase()); deleteQuery.setParameter("tenant", tenantAware.getCurrentTenant().toUpperCase());
Jpa.setNativeQueryInParameter(deleteQuery, "status", statusList); Jpa.setNativeQueryInParameter(deleteQuery, "status", statusList);
@@ -540,8 +510,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
public boolean hasPendingCancellations(final Long targetId) { public boolean hasPendingCancellations(final Long targetId) {
// target access checked in assertTargetReadAllowed // target access checked in assertTargetReadAllowed
assertTargetReadAllowed(targetId); assertTargetReadAllowed(targetId);
return actionRepository return actionRepository.exists(ActionSpecifications.byTargetIdAndIsActiveAndStatus(targetId, Action.Status.CANCELING));
.exists(ActionSpecifications.byTargetIdAndIsActiveAndStatus(targetId, Action.Status.CANCELING));
} }
@Override @Override
@@ -560,19 +529,17 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
} }
}); });
if (cancelationType == CancelationType.FORCE) { if (cancelationType == CancelationType.FORCE) {
actionRepository.findAll(ActionSpecifications.byDistributionSetIdAndActive(distributionSet.getId())) actionRepository.findAll(ActionSpecifications.byDistributionSetIdAndActive(distributionSet.getId())).forEach(action -> {
.forEach(action -> { try {
try { assertTargetUpdateAllowed(action);
assertTargetUpdateAllowed(action); forceQuitAction0(action.getId());
forceQuitAction0(action.getId()); log.debug("Action {} force canceled (force)", action.getId());
log.debug("Action {} force canceled (force)", action.getId()); } catch (final InsufficientPermissionException e) {
} catch (final InsufficientPermissionException e) { log.trace("Could not cancel action {} due to insufficient permissions.", action.getId(), e);
log.trace("Could not cancel action {} due to insufficient permissions.", action.getId(), e); } catch (final EntityNotFoundException e) {
} catch (final EntityNotFoundException e) { log.trace("Could not cancel action {} due to entity not found exception.", action.getId(), e);
log.trace("Could not cancel action {} due to entity not found exception.", action.getId(), }
e); });
}
});
} }
} }
@@ -585,9 +552,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
} }
private static Map<Long, List<TargetWithActionType>> convertRequest(final Collection<DeploymentRequest> deploymentRequests) { private static Map<Long, List<TargetWithActionType>> convertRequest(final Collection<DeploymentRequest> deploymentRequests) {
return deploymentRequests.stream().collect( return deploymentRequests.stream().collect(Collectors.groupingBy(DeploymentRequest::getDistributionSetId,
Collectors.groupingBy(DeploymentRequest::getDistributionSetId, Collectors.mapping(DeploymentRequest::getTargetWithActionType, Collectors.toList())));
Collectors.mapping(DeploymentRequest::getTargetWithActionType, Collectors.toList())));
} }
/** /**
@@ -601,16 +567,13 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
} }
private static DistributionSetAssignmentResult buildAssignmentResult( private static DistributionSetAssignmentResult buildAssignmentResult(
final JpaDistributionSet distributionSet, final JpaDistributionSet distributionSet, final List<JpaAction> assignedActions, final int totalTargetsForAssignment) {
final List<JpaAction> assignedActions, final int totalTargetsForAssignment) {
final int alreadyAssignedTargetsCount = totalTargetsForAssignment - assignedActions.size(); final int alreadyAssignedTargetsCount = totalTargetsForAssignment - assignedActions.size();
return new DistributionSetAssignmentResult(distributionSet, alreadyAssignedTargetsCount, assignedActions); return new DistributionSetAssignmentResult(distributionSet, alreadyAssignedTargetsCount, assignedActions);
} }
private static String getQueryForDeleteActionsByStatusAndLastModifiedBeforeString(final Database database) { private static String getQueryForDeleteActionsByStatusAndLastModifiedBeforeString(final Database database) {
return QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED.getOrDefault(database, return QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED.getOrDefault(database, QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED_DEFAULT);
QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED_DEFAULT);
} }
private static RetryTemplate createRetryTemplate() { private static RetryTemplate createRetryTemplate() {
@@ -627,16 +590,13 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
return template; return template;
} }
private List<DistributionSetAssignmentResult> assignDistributionSets( private List<DistributionSetAssignmentResult> assignDistributionSets(final String initiatedBy,
final String initiatedBy, final List<DeploymentRequest> deploymentRequests, final String actionMessage, final AbstractDsAssignmentStrategy strategy) {
final List<DeploymentRequest> deploymentRequests, final String actionMessage,
final AbstractDsAssignmentStrategy strategy) {
final List<DeploymentRequest> validatedRequests = validateAndFilterRequestForAssignments(deploymentRequests); final List<DeploymentRequest> validatedRequests = validateAndFilterRequestForAssignments(deploymentRequests);
final Map<Long, List<TargetWithActionType>> assignmentsByDsIds = convertRequest(validatedRequests); final Map<Long, List<TargetWithActionType>> assignmentsByDsIds = convertRequest(validatedRequests);
final List<DistributionSetAssignmentResult> results = assignmentsByDsIds.entrySet().stream() final List<DistributionSetAssignmentResult> results = assignmentsByDsIds.entrySet().stream()
.map(entry -> assignDistributionSetToTargetsWithRetry( .map(entry -> assignDistributionSetToTargetsWithRetry(initiatedBy, entry.getKey(), entry.getValue(), actionMessage, strategy))
initiatedBy, entry.getKey(), entry.getValue(), actionMessage, strategy))
.toList(); .toList();
strategy.sendDeploymentEvents(results); strategy.sendDeploymentEvents(results);
return results; return results;
@@ -660,9 +620,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
private void checkForMultiAssignment(final Collection<DeploymentRequest> deploymentRequests) { private void checkForMultiAssignment(final Collection<DeploymentRequest> deploymentRequests) {
if (!isMultiAssignmentsEnabled()) { if (!isMultiAssignmentsEnabled()) {
final long distinctTargetsInRequest = deploymentRequests.stream() final long distinctTargetsInRequest = deploymentRequests.stream()
.map(request -> request.getTargetWithActionType().getControllerId()) .map(request -> request.getTargetWithActionType().getControllerId()).distinct().count();
.distinct()
.count();
if (distinctTargetsInRequest < deploymentRequests.size()) { if (distinctTargetsInRequest < deploymentRequests.size()) {
throw new MultiAssignmentIsNotEnabledException(); throw new MultiAssignmentIsNotEnabledException();
} }
@@ -675,13 +633,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
} }
private void checkForTargetTypeCompatibility(final List<DeploymentRequest> deploymentRequests) { private void checkForTargetTypeCompatibility(final List<DeploymentRequest> deploymentRequests) {
final List<String> controllerIds = deploymentRequests.stream() final List<String> controllerIds = deploymentRequests.stream().map(DeploymentRequest::getControllerId).distinct().toList();
.map(DeploymentRequest::getControllerId) final List<Long> distSetIds = deploymentRequests.stream().map(DeploymentRequest::getDistributionSetId).distinct().toList();
.distinct()
.toList();
final List<Long> distSetIds = deploymentRequests.stream().map(DeploymentRequest::getDistributionSetId)
.distinct()
.toList();
if (controllerIds.size() > 1 && distSetIds.size() > 1) { if (controllerIds.size() > 1 && distSetIds.size() > 1) {
throw new IllegalStateException("Assigning multiple Distribution Sets to multiple Targets simultaneously is not allowed!"); throw new IllegalStateException("Assigning multiple Distribution Sets to multiple Targets simultaneously is not allowed!");
@@ -696,14 +649,10 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
private void checkCompatibilityForSingleDsAssignment(final Long distSetId, final List<String> controllerIds) { private void checkCompatibilityForSingleDsAssignment(final Long distSetId, final List<String> controllerIds) {
final DistributionSetType distSetType = distributionSetManagement.getValidAndComplete(distSetId).getType(); final DistributionSetType distSetType = distributionSetManagement.getValidAndComplete(distSetId).getType();
final Set<String> incompatibleTargetTypes = ListUtils.partition(controllerIds, Constants.MAX_ENTRIES_IN_STATEMENT) final Set<String> incompatibleTargetTypes = ListUtils.partition(controllerIds, Constants.MAX_ENTRIES_IN_STATEMENT).stream()
.stream()
.map(ids -> targetRepository.findAll(TargetSpecifications.hasControllerIdIn(ids) .map(ids -> targetRepository.findAll(TargetSpecifications.hasControllerIdIn(ids)
.and(TargetSpecifications.notCompatibleWithDistributionSetType(distSetType.getId())))) .and(TargetSpecifications.notCompatibleWithDistributionSetType(distSetType.getId())))).flatMap(List::stream)
.flatMap(List::stream) .map(Target::getTargetType).map(TargetType::getName).collect(Collectors.toSet());
.map(Target::getTargetType)
.map(TargetType::getName)
.collect(Collectors.toSet());
if (!incompatibleTargetTypes.isEmpty()) { if (!incompatibleTargetTypes.isEmpty()) {
throw new IncompatibleTargetTypeException(incompatibleTargetTypes, distSetType.getName()); throw new IncompatibleTargetTypeException(incompatibleTargetTypes, distSetType.getName());
@@ -717,13 +666,11 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
// we assume that list of assigned DS is less than // we assume that list of assigned DS is less than
// MAX_ENTRIES_IN_STATEMENT // MAX_ENTRIES_IN_STATEMENT
final Set<DistributionSetType> incompatibleDistSetTypes = distributionSetManagement.get(distSetIds).stream() final Set<DistributionSetType> incompatibleDistSetTypes = distributionSetManagement.get(distSetIds).stream()
.map(DistributionSet::getType) .map(DistributionSet::getType).collect(Collectors.toSet());
.collect(Collectors.toSet());
incompatibleDistSetTypes.removeAll(target.getTargetType().getDistributionSetTypes()); incompatibleDistSetTypes.removeAll(target.getTargetType().getDistributionSetTypes());
if (!incompatibleDistSetTypes.isEmpty()) { if (!incompatibleDistSetTypes.isEmpty()) {
final Set<String> distSetTypeNames = incompatibleDistSetTypes.stream() final Set<String> distSetTypeNames = incompatibleDistSetTypes.stream().map(DistributionSetType::getName)
.map(DistributionSetType::getName)
.collect(Collectors.toSet()); .collect(Collectors.toSet());
throw new IncompatibleTargetTypeException(target.getTargetType().getName(), distSetTypeNames); throw new IncompatibleTargetTypeException(target.getTargetType().getName(), distSetTypeNames);
} }
@@ -731,27 +678,21 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
} }
private List<DeploymentRequest> filterByTargetUpdatable(final List<DeploymentRequest> deploymentRequests) { private List<DeploymentRequest> filterByTargetUpdatable(final List<DeploymentRequest> deploymentRequests) {
final List<String> controllerIds = deploymentRequests.stream() final List<String> controllerIds = deploymentRequests.stream().map(DeploymentRequest::getControllerId).distinct().toList();
.map(DeploymentRequest::getControllerId)
.distinct()
.toList();
final List<String> found = targetRepository final List<String> found = targetRepository.findAll(AccessController.Operation.UPDATE,
.findAll(AccessController.Operation.UPDATE, TargetSpecifications.hasControllerIdIn(controllerIds)) TargetSpecifications.hasControllerIdIn(controllerIds)).stream().map(JpaTarget::getControllerId).toList();
.stream().map(JpaTarget::getControllerId).toList();
if (found.size() != controllerIds.size()) { if (found.size() != controllerIds.size()) {
return deploymentRequests.stream() return deploymentRequests.stream().filter(deploymentRequest -> found.contains(deploymentRequest.getControllerId())).toList();
.filter(deploymentRequest -> found.contains(deploymentRequest.getControllerId())).toList();
} }
return deploymentRequests; return deploymentRequests;
} }
private DistributionSetAssignmentResult assignDistributionSetToTargetsWithRetry(final String initiatedBy, private DistributionSetAssignmentResult assignDistributionSetToTargetsWithRetry(
final Long dsId, final Collection<TargetWithActionType> targetsWithActionType, final String actionMessage, final String initiatedBy, final Long dsId, final Collection<TargetWithActionType> targetsWithActionType, final String actionMessage,
final AbstractDsAssignmentStrategy assignmentStrategy) { final AbstractDsAssignmentStrategy assignmentStrategy) {
final RetryCallback<DistributionSetAssignmentResult, ConcurrencyFailureException> retryCallback = return retryTemplate.execute(retryContext ->
retryContext -> assignDistributionSetToTargets(initiatedBy, dsId, targetsWithActionType, actionMessage, assignmentStrategy); assignDistributionSetToTargets(initiatedBy, dsId, targetsWithActionType, actionMessage, assignmentStrategy));
return retryTemplate.execute(retryCallback);
} }
/** /**
@@ -777,29 +718,19 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
* {@link DistributionSetType}. * {@link DistributionSetType}.
*/ */
private DistributionSetAssignmentResult assignDistributionSetToTargets( private DistributionSetAssignmentResult assignDistributionSetToTargets(
final String initiatedBy, final Long dsId, final String initiatedBy, final Long dsId, final Collection<TargetWithActionType> targetsWithActionType, final String actionMessage,
final Collection<TargetWithActionType> targetsWithActionType, final String actionMessage,
final AbstractDsAssignmentStrategy assignmentStrategy) { final AbstractDsAssignmentStrategy assignmentStrategy) {
final JpaDistributionSet distributionSet = distributionSetManagement.getValidAndComplete(dsId); JpaDistributionSet distributionSet = distributionSetManagement.getValidAndComplete(dsId);
if (distributionSetManagement.isImplicitLockApplicable(distributionSet)) { if (distributionSetManagement.isImplicitLockApplicable(distributionSet)) {
// without new transaction DS changed event is not thrown // without new transaction DS changed event is not thrown
DeploymentHelper.runInNewTransaction(txManager, "Implicit lock", status -> { distributionSet = DeploymentHelper.runInNewTransaction(txManager, "Implicit lock", status -> distributionSetManagement.lock(dsId));
distributionSetManagement.lock(distributionSet.getId());
return null;
});
} }
final List<String> providedTargetIds = targetsWithActionType.stream() final List<String> providedTargetIds = targetsWithActionType.stream().map(TargetWithActionType::getControllerId).distinct().toList();
.map(TargetWithActionType::getControllerId)
.distinct()
.toList();
final List<String> existingTargetIds = ListUtils.partition(providedTargetIds, Constants.MAX_ENTRIES_IN_STATEMENT) final List<String> existingTargetIds = ListUtils.partition(providedTargetIds, Constants.MAX_ENTRIES_IN_STATEMENT).stream()
.stream()
.map(ids -> targetRepository.findAll(AccessController.Operation.UPDATE, TargetSpecifications.hasControllerIdIn(ids))) .map(ids -> targetRepository.findAll(AccessController.Operation.UPDATE, TargetSpecifications.hasControllerIdIn(ids)))
.flatMap(List::stream).map(JpaTarget::getControllerId) .flatMap(List::stream).map(JpaTarget::getControllerId).toList();
.toList();
final List<JpaTarget> targetEntities = assignmentStrategy.findTargetsForAssignment(existingTargetIds, distributionSet.getId()); final List<JpaTarget> targetEntities = assignmentStrategy.findTargetsForAssignment(existingTargetIds, distributionSet.getId());
if (targetEntities.isEmpty()) { if (targetEntities.isEmpty()) {
@@ -807,21 +738,19 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
} }
final List<TargetWithActionType> existingTargetsWithActionType = targetsWithActionType.stream() final List<TargetWithActionType> existingTargetsWithActionType = targetsWithActionType.stream()
.filter(target -> existingTargetIds.contains(target.getControllerId())) .filter(target -> existingTargetIds.contains(target.getControllerId())).toList();
.toList();
final List<JpaAction> assignedActions = doAssignDistributionSetToTargets( final List<JpaAction> assignedActions = doAssignDistributionSetToTargets(
initiatedBy, existingTargetsWithActionType, actionMessage, assignmentStrategy, distributionSet, targetEntities); initiatedBy, existingTargetsWithActionType, actionMessage, assignmentStrategy, distributionSet, targetEntities);
return buildAssignmentResult(distributionSet, assignedActions, existingTargetsWithActionType.size()); return buildAssignmentResult(distributionSet, assignedActions, existingTargetsWithActionType.size());
} }
private DistributionSetAssignmentResult allTargetsAlreadyAssignedResult( private DistributionSetAssignmentResult allTargetsAlreadyAssignedResult(final JpaDistributionSet distributionSetEntity,
final JpaDistributionSet distributionSetEntity, final int alreadyAssignedCount) { final int alreadyAssignedCount) {
// detaching as it is not necessary to persist the set itself // detaching as it is not necessary to persist the set itself
entityManager.detach(distributionSetEntity); entityManager.detach(distributionSetEntity);
// return with nothing as all targets had the DS already assigned // return with nothing as all targets had the DS already assigned
return new DistributionSetAssignmentResult(distributionSetEntity, alreadyAssignedCount, return new DistributionSetAssignmentResult(distributionSetEntity, alreadyAssignedCount, Collections.emptyList());
Collections.emptyList());
} }
private List<JpaAction> doAssignDistributionSetToTargets(final String initiatedBy, private List<JpaAction> doAssignDistributionSetToTargets(final String initiatedBy,
@@ -837,8 +766,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
// not active before and the manual assignment which has been done cancels them // not active before and the manual assignment which has been done cancels them
targetEntitiesIdsChunks.forEach(this::cancelInactiveScheduledActionsForTargets); targetEntitiesIdsChunks.forEach(this::cancelInactiveScheduledActionsForTargets);
setAssignedDistributionSetAndTargetUpdateStatus(assignmentStrategy, distributionSetEntity, targetEntitiesIdsChunks); setAssignedDistributionSetAndTargetUpdateStatus(assignmentStrategy, distributionSetEntity, targetEntitiesIdsChunks);
final Map<TargetWithActionType, JpaAction> assignedActions = createActions( final Map<TargetWithActionType, JpaAction> assignedActions = createActions(targetsWithActionType, targetEntities, distributionSetEntity,
targetsWithActionType, targetEntities, distributionSetEntity, assignmentStrategy, initiatedBy); assignmentStrategy, initiatedBy);
// create initial action status when action is created, so we remember // create initial action status when action is created, so we remember
// the initial running status because we will change the status // the initial running status because we will change the status
// of the action itself and with this action status we have a nicer action history. // of the action itself and with this action status we have a nicer action history.
@@ -856,12 +785,12 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
private void enforceMaxActionsPerTarget(final Collection<DeploymentRequest> deploymentRequests) { private void enforceMaxActionsPerTarget(final Collection<DeploymentRequest> deploymentRequests) {
final int quota = quotaManagement.getMaxActionsPerTarget(); final int quota = quotaManagement.getMaxActionsPerTarget();
final Map<String, Long> countOfTargetInRequest = deploymentRequests.stream() final Map<String, Long> countOfTargetInRequest = deploymentRequests.stream().map(DeploymentRequest::getControllerId)
.map(DeploymentRequest::getControllerId)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
countOfTargetInRequest.forEach((controllerId, count) -> QuotaHelper.assertAssignmentQuota(controllerId, count, countOfTargetInRequest.forEach(
quota, Action.class, Target.class, actionRepository::countByTargetControllerId)); (controllerId, count) -> QuotaHelper.assertAssignmentQuota(controllerId, count, quota, Action.class, Target.class,
actionRepository::countByTargetControllerId));
} }
private void closeOrCancelActiveActions(final AbstractDsAssignmentStrategy assignmentStrategy, final List<List<Long>> targetIdsChunks) { private void closeOrCancelActiveActions(final AbstractDsAssignmentStrategy assignmentStrategy, final List<List<Long>> targetIdsChunks) {
@@ -872,16 +801,15 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
} }
} }
private void setAssignedDistributionSetAndTargetUpdateStatus( private void setAssignedDistributionSetAndTargetUpdateStatus(final AbstractDsAssignmentStrategy assignmentStrategy,
final AbstractDsAssignmentStrategy assignmentStrategy,
final JpaDistributionSet set, final List<List<Long>> targetIdsChunks) { final JpaDistributionSet set, final List<List<Long>> targetIdsChunks) {
final String currentUser = auditorProvider.getCurrentAuditor().orElse(null); final String currentUser = auditorProvider.getCurrentAuditor().orElse(null);
assignmentStrategy.setAssignedDistributionSetAndTargetStatus(set, targetIdsChunks, currentUser); assignmentStrategy.setAssignedDistributionSetAndTargetStatus(set, targetIdsChunks, currentUser);
} }
private Map<TargetWithActionType, JpaAction> createActions( private Map<TargetWithActionType, JpaAction> createActions(final Collection<TargetWithActionType> targetsWithActionType,
final Collection<TargetWithActionType> targetsWithActionType, final List<JpaTarget> targets, final JpaDistributionSet set, final List<JpaTarget> targets, final JpaDistributionSet set, final AbstractDsAssignmentStrategy assignmentStrategy,
final AbstractDsAssignmentStrategy assignmentStrategy, final String initiatedBy) { final String initiatedBy) {
final Map<TargetWithActionType, JpaAction> persistedActions = new LinkedHashMap<>(); final Map<TargetWithActionType, JpaAction> persistedActions = new LinkedHashMap<>();
for (final TargetWithActionType twt : targetsWithActionType) { for (final TargetWithActionType twt : targetsWithActionType) {
final JpaAction targetAction = assignmentStrategy.createTargetAction(initiatedBy, twt, targets, set); final JpaAction targetAction = assignmentStrategy.createTargetAction(initiatedBy, twt, targets, set);
@@ -892,9 +820,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
return persistedActions; return persistedActions;
} }
private void createActionsStatus( private void createActionsStatus(final Map<TargetWithActionType, JpaAction> actions, final AbstractDsAssignmentStrategy assignmentStrategy,
final Map<TargetWithActionType, JpaAction> actions, final String actionMessage) {
final AbstractDsAssignmentStrategy assignmentStrategy, final String actionMessage) {
actionStatusRepository.saveAll(actions.entrySet().stream().map(entry -> { actionStatusRepository.saveAll(actions.entrySet().stream().map(entry -> {
final JpaAction action = entry.getValue(); final JpaAction action = entry.getValue();
final JpaActionStatus actionStatus = assignmentStrategy.createActionStatus(action, actionMessage); final JpaActionStatus actionStatus = assignmentStrategy.createActionStatus(action, actionMessage);
@@ -921,8 +848,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
// assignment already // assignment already
if (!isConfirmationRequired) { if (!isConfirmationRequired) {
// confirmation given on assignment dialog // confirmation given on assignment dialog
actionStatus.addMessage( actionStatus.addMessage(String.format("Assignment confirmed by initiator [%s].", action.getInitiatedBy()));
String.format("Assignment confirmed by initiator [%s].", action.getInitiatedBy()));
} else if (action.getTarget().getAutoConfirmationStatus() != null) { } else if (action.getTarget().getAutoConfirmationStatus() != null) {
// auto-confirmation is configured // auto-confirmation is configured
actionStatus.addMessage(action.getTarget().getAutoConfirmationStatus().constructActionMessage()); actionStatus.addMessage(action.getTarget().getAutoConfirmationStatus().constructActionMessage());
@@ -931,8 +857,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
} }
} else { } else {
actionStatus actionStatus.addMessage("Waiting for the confirmation by the device before processing with the deployment");
.addMessage("Waiting for the confirmation by the device before processing with the deployment");
} }
} }
} }
@@ -952,8 +877,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
} }
final JpaTarget target = action.getTarget(); final JpaTarget target = action.getTarget();
if (target.getAssignedDistributionSet() != null if (target.getAssignedDistributionSet() != null && action.getDistributionSet().getId()
&& action.getDistributionSet().getId().equals(target.getAssignedDistributionSet().getId())) { .equals(target.getAssignedDistributionSet().getId())) {
// the target has already the distribution set assigned, we don't // the target has already the distribution set assigned, we don't
// need to start the scheduled action, just finish it. // need to start the scheduled action, just finish it.
log.debug("Target {} has distribution set {} assigned. Closing action...", target.getControllerId(), log.debug("Target {} has distribution set {} assigned. Closing action...", target.getControllerId(),
@@ -990,8 +915,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
private List<JpaAction> activateActionsOfRolloutGroup(final List<JpaAction> actions) { private List<JpaAction> activateActionsOfRolloutGroup(final List<JpaAction> actions) {
actions.forEach(action -> { actions.forEach(action -> {
action.setActive(true); action.setActive(true);
final boolean confirmationRequired = action.getRolloutGroup().isConfirmationRequired() final boolean confirmationRequired = action.getRolloutGroup().isConfirmationRequired() && action.getTarget()
&& action.getTarget().getAutoConfirmationStatus() == null; .getAutoConfirmationStatus() == null;
if (isConfirmationFlowEnabled() && confirmationRequired) { if (isConfirmationFlowEnabled() && confirmationRequired) {
action.setStatus(Status.WAIT_FOR_CONFIRMATION); action.setStatus(Status.WAIT_FOR_CONFIRMATION);
return; return;
@@ -1022,18 +947,15 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
} }
private boolean isMultiAssignmentsEnabled() { private boolean isMultiAssignmentsEnabled() {
return TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement) return TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement).isMultiAssignmentsEnabled();
.isMultiAssignmentsEnabled();
} }
private boolean isConfirmationFlowEnabled() { private boolean isConfirmationFlowEnabled() {
return TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement) return TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement).isConfirmationFlowEnabled();
.isConfirmationFlowEnabled();
} }
private <T extends Serializable> T getConfigValue(final String key, final Class<T> valueType) { private <T extends Serializable> T getConfigValue(final String key, final Class<T> valueType) {
return systemSecurityContext return systemSecurityContext.runAsSystem(() -> tenantConfigurationManagement.getConfigurationValue(key, valueType).getValue());
.runAsSystem(() -> tenantConfigurationManagement.getConfigurationValue(key, valueType).getValue());
} }
private void assertTargetReadAllowed(final Long targetId) { private void assertTargetReadAllowed(final Long targetId) {
@@ -1051,8 +973,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
private JpaAction assertTargetUpdateAllowed(final JpaAction action) { private JpaAction assertTargetUpdateAllowed(final JpaAction action) {
targetRepository.findOne(TargetSpecifications.hasId(action.getTarget().getId())).ifPresentOrElse( targetRepository.findOne(TargetSpecifications.hasId(action.getTarget().getId())).ifPresentOrElse(
target -> targetRepository.getAccessController() target -> targetRepository.getAccessController()
.ifPresent(acm -> acm.assertOperationAllowed(AccessController.Operation.UPDATE, target)), .ifPresent(acm -> acm.assertOperationAllowed(AccessController.Operation.UPDATE, target)), () -> {
() -> {
throw new EntityNotFoundException(Action.class, action); throw new EntityNotFoundException(Action.class, action);
}); });
return action; return action;

View File

@@ -78,8 +78,7 @@ public class JpaDistributionSetInvalidationManagement implements DistributionSet
public void invalidateDistributionSet(final DistributionSetInvalidation distributionSetInvalidation) { public void invalidateDistributionSet(final DistributionSetInvalidation distributionSetInvalidation) {
log.debug("Invalidate distribution sets {}", distributionSetInvalidation.getDistributionSetIds()); log.debug("Invalidate distribution sets {}", distributionSetInvalidation.getDistributionSetIds());
final String tenant = tenantAware.getCurrentTenant(); final String tenant = tenantAware.getCurrentTenant();
if (shouldRolloutsBeCanceled(distributionSetInvalidation.getCancelationType(), if (shouldRolloutsBeCanceled(distributionSetInvalidation.getCancelationType(), distributionSetInvalidation.isCancelRollouts())) {
distributionSetInvalidation.isCancelRollouts())) {
final String handlerId = JpaRolloutManagement.createRolloutLockKey(tenant); final String handlerId = JpaRolloutManagement.createRolloutLockKey(tenant);
final Lock lock = lockRegistry.obtain(handlerId); final Lock lock = lockRegistry.obtain(handlerId);
try { try {
@@ -122,17 +121,15 @@ public class JpaDistributionSetInvalidationManagement implements DistributionSet
return cancelationType != CancelationType.NONE || cancelRollouts; return cancelationType != CancelationType.NONE || cancelRollouts;
} }
private void invalidateDistributionSetsInTransaction(final DistributionSetInvalidation distributionSetInvalidation, private void invalidateDistributionSetsInTransaction(final DistributionSetInvalidation distributionSetInvalidation, final String tenant) {
final String tenant) {
DeploymentHelper.runInNewTransaction(txManager, tenant + "-invalidateDS", status -> { DeploymentHelper.runInNewTransaction(txManager, tenant + "-invalidateDS", status -> {
distributionSetInvalidation.getDistributionSetIds().forEach(setId -> invalidateDistributionSet(setId, distributionSetInvalidation.getDistributionSetIds().forEach(setId -> invalidateDistributionSet(
distributionSetInvalidation.getCancelationType(), distributionSetInvalidation.isCancelRollouts())); setId, distributionSetInvalidation.getCancelationType(), distributionSetInvalidation.isCancelRollouts()));
return 0; return 0;
}); });
} }
private void invalidateDistributionSet(final long setId, final CancelationType cancelationType, private void invalidateDistributionSet(final long setId, final CancelationType cancelationType, final boolean cancelRollouts) {
final boolean cancelRollouts) {
final DistributionSet distributionSet = distributionSetManagement.getOrElseThrowException(setId); final DistributionSet distributionSet = distributionSetManagement.getOrElseThrowException(setId);
if (!distributionSet.isComplete()) { if (!distributionSet.isComplete()) {
throw new IncompleteDistributionSetException("Distribution set of type " throw new IncompleteDistributionSetException("Distribution set of type "

View File

@@ -248,23 +248,27 @@ public class JpaDistributionSetManagement
@Override @Override
@Transactional @Transactional
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY)) @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY))
public void lock(final long id) { public JpaDistributionSet lock(final long id) {
final JpaDistributionSet distributionSet = getById(id); final JpaDistributionSet distributionSet = getById(id);
if (!distributionSet.isLocked()) { if (distributionSet.isLocked()) {
return distributionSet;
} else {
lockSoftwareModules(distributionSet); lockSoftwareModules(distributionSet);
distributionSet.lock(); distributionSet.lock();
jpaRepository.save(distributionSet); return jpaRepository.save(distributionSet);
} }
} }
@Override @Override
@Transactional @Transactional
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY)) @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY))
public void unlock(final long id) { public JpaDistributionSet unlock(final long id) {
final JpaDistributionSet distributionSet = getById(id); final JpaDistributionSet distributionSet = getById(id);
if (distributionSet.isLocked()) { if (distributionSet.isLocked()) {
distributionSet.unlock(); distributionSet.unlock();
jpaRepository.save(distributionSet); return jpaRepository.save(distributionSet);
} else {
return distributionSet;
} }
} }

View File

@@ -10,11 +10,11 @@
package org.eclipse.hawkbit.repository.jpa.management; package org.eclipse.hawkbit.repository.jpa.management;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import jakarta.validation.constraints.NotNull; import jakarta.persistence.EntityManager;
import cz.jirutka.rsql.parser.RSQLParserException; import cz.jirutka.rsql.parser.RSQLParserException;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -27,17 +27,12 @@ import org.eclipse.hawkbit.repository.TargetFilterQueryFields;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.TargetManagement;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate;
import org.eclipse.hawkbit.repository.builder.GenericTargetFilterQueryUpdate;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryCreate;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryUpdate;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
import org.eclipse.hawkbit.repository.exception.InvalidAutoAssignActionTypeException; import org.eclipse.hawkbit.repository.exception.InvalidAutoAssignActionTypeException;
import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException;
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper; import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper;
import org.eclipse.hawkbit.repository.jpa.acm.AccessController;
import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetFilterQueryCreate;
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetFilterQuery; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetFilterQuery;
@@ -53,14 +48,11 @@ import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.utils.TenantConfigHelper; import org.eclipse.hawkbit.utils.TenantConfigHelper;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty;
import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.data.domain.AuditorAware; import org.springframework.data.domain.AuditorAware;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice; import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.domain.Specification;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
@@ -74,9 +66,10 @@ import org.springframework.validation.annotation.Validated;
@Validated @Validated
@Service @Service
@ConditionalOnBooleanProperty(prefix = "hawkbit.jpa", name = { "enabled", "target-filter-management" }, matchIfMissing = true) @ConditionalOnBooleanProperty(prefix = "hawkbit.jpa", name = { "enabled", "target-filter-management" }, matchIfMissing = true)
class JpaTargetFilterQueryManagement implements TargetFilterQueryManagement { class JpaTargetFilterQueryManagement
extends AbstractJpaRepositoryManagement<JpaTargetFilterQuery, TargetFilterQueryManagement.Create, TargetFilterQueryManagement.Update, TargetFilterQueryRepository, TargetFilterQueryFields>
implements TargetFilterQueryManagement<JpaTargetFilterQuery>{
private final TargetFilterQueryRepository targetFilterQueryRepository;
private final TargetManagement targetManagement; private final TargetManagement targetManagement;
private final DistributionSetManagement<? extends DistributionSet> distributionSetManagement; private final DistributionSetManagement<? extends DistributionSet> distributionSetManagement;
private final QuotaManagement quotaManagement; private final QuotaManagement quotaManagement;
@@ -87,12 +80,12 @@ class JpaTargetFilterQueryManagement implements TargetFilterQueryManagement {
private final AuditorAware<String> auditorAware; private final AuditorAware<String> auditorAware;
protected JpaTargetFilterQueryManagement( protected JpaTargetFilterQueryManagement(
final TargetFilterQueryRepository targetFilterQueryRepository, final TargetFilterQueryRepository targetFilterQueryRepository, final EntityManager entityManager,
final TargetManagement targetManagement, final DistributionSetManagement<? extends DistributionSet> distributionSetManagement, final TargetManagement targetManagement, final DistributionSetManagement<? extends DistributionSet> distributionSetManagement,
final QuotaManagement quotaManagement, final TenantConfigurationManagement tenantConfigurationManagement, final QuotaManagement quotaManagement, final TenantConfigurationManagement tenantConfigurationManagement,
final RepositoryProperties repositoryProperties, final RepositoryProperties repositoryProperties,
final SystemSecurityContext systemSecurityContext, final ContextAware contextAware, final AuditorAware<String> auditorAware) { final SystemSecurityContext systemSecurityContext, final ContextAware contextAware, final AuditorAware<String> auditorAware) {
this.targetFilterQueryRepository = targetFilterQueryRepository; super(targetFilterQueryRepository, entityManager);
this.targetManagement = targetManagement; this.targetManagement = targetManagement;
this.distributionSetManagement = distributionSetManagement; this.distributionSetManagement = distributionSetManagement;
this.quotaManagement = quotaManagement; this.quotaManagement = quotaManagement;
@@ -104,38 +97,22 @@ class JpaTargetFilterQueryManagement implements TargetFilterQueryManagement {
} }
@Override @Override
@Transactional public JpaTargetFilterQuery create(final Create create) {
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, validate(create);
backoff = @Backoff(delay = Constants.TX_RT_DELAY)) return super.create(create);
public TargetFilterQuery create(final TargetFilterQueryCreate c) { }
final JpaTargetFilterQueryCreate create = (JpaTargetFilterQueryCreate) c;
create.getQuery().ifPresent(query -> { @Override
// validate the RSQL query syntax public List<JpaTargetFilterQuery> create(final Collection<Create> create) {
RsqlUtility.getInstance().validateRsqlFor(query, TargetFields.class, JpaTarget.class); create.forEach(this::validate);
return super.create(create);
// enforce the 'max targets per auto assign' quota right here even
// if the result of the filter query can vary over time
create.getAutoAssignDistributionSetId().ifPresent(dsId -> {
WeightValidationHelper.usingContext(systemSecurityContext, tenantConfigurationManagement)
.validate(create);
assertMaxTargetsQuota(query, create.getName().orElse(null), dsId);
});
});
return targetFilterQueryRepository.save(AccessController.Operation.CREATE, create.build());
} }
@Override @Override
@Transactional @Transactional
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, public JpaTargetFilterQuery update(final Update update) {
backoff = @Backoff(delay = Constants.TX_RT_DELAY)) validate(update);
public void delete(final long targetFilterQueryId) { return super.update(update);
if (!targetFilterQueryRepository.existsById(targetFilterQueryId)) {
throw new EntityNotFoundException(TargetFilterQuery.class, targetFilterQueryId);
}
targetFilterQueryRepository.deleteById(targetFilterQueryId);
} }
@Override @Override
@@ -149,67 +126,9 @@ class JpaTargetFilterQueryManagement implements TargetFilterQueryManagement {
} }
} }
@Override
public Slice<TargetFilterQuery> findAll(final Pageable pageable) {
return JpaManagementHelper.findAllWithoutCountBySpec(targetFilterQueryRepository, null, pageable);
}
@Override
public long count() {
return targetFilterQueryRepository.count();
}
@Override @Override
public long countByAutoAssignDistributionSetId(final long autoAssignDistributionSetId) { public long countByAutoAssignDistributionSetId(final long autoAssignDistributionSetId) {
return targetFilterQueryRepository.countByAutoAssignDistributionSetId(autoAssignDistributionSetId); return jpaRepository.countByAutoAssignDistributionSetId(autoAssignDistributionSetId);
}
@Override
public Slice<TargetFilterQuery> findByName(final String name, final Pageable pageable) {
if (ObjectUtils.isEmpty(name)) {
return findAll(pageable);
}
return JpaManagementHelper.findAllWithoutCountBySpec(targetFilterQueryRepository,
Collections.singletonList(TargetFilterQuerySpecification.likeName(name)), pageable
);
}
@Override
public long countByName(final String name) {
if (ObjectUtils.isEmpty(name)) {
return count();
}
return JpaManagementHelper.countBySpec(targetFilterQueryRepository,
Collections.singletonList(TargetFilterQuerySpecification.likeName(name)));
}
@Override
public Page<TargetFilterQuery> findByRsql(final String rsqlFilter, final Pageable pageable) {
final List<Specification<JpaTargetFilterQuery>> specList = !ObjectUtils.isEmpty(rsqlFilter)
? Collections.singletonList(RsqlUtility.getInstance().buildRsqlSpecification(rsqlFilter, TargetFilterQueryFields.class))
: Collections.emptyList();
return JpaManagementHelper.findAllWithCountBySpec(targetFilterQueryRepository, specList, pageable);
}
@Override
public Slice<TargetFilterQuery> findByQuery(final String query, final Pageable pageable) {
final List<Specification<JpaTargetFilterQuery>> specList = !ObjectUtils.isEmpty(query)
? Collections.singletonList(TargetFilterQuerySpecification.equalsQuery(query))
: Collections.emptyList();
return JpaManagementHelper.findAllWithoutCountBySpec(targetFilterQueryRepository, specList, pageable);
}
@Override
public Slice<TargetFilterQuery> findByAutoAssignDistributionSetId(final long setId, @NotNull final Pageable pageable) {
final DistributionSet distributionSet = distributionSetManagement.getOrElseThrowException(setId);
return JpaManagementHelper.findAllWithoutCountBySpec(targetFilterQueryRepository,
Collections.singletonList(TargetFilterQuerySpecification.byAutoAssignDS(distributionSet)), pageable
);
} }
@Override @Override
@@ -222,59 +141,20 @@ class JpaTargetFilterQueryManagement implements TargetFilterQueryManagement {
specList.add(RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFilterQueryFields.class)); specList.add(RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFilterQueryFields.class));
} }
return JpaManagementHelper.findAllWithCountBySpec(targetFilterQueryRepository, specList, pageable); return JpaManagementHelper.findAllWithCountBySpec(jpaRepository, specList, pageable);
} }
@Override @Override
public Slice<TargetFilterQuery> findWithAutoAssignDS(final Pageable pageable) { public Slice<TargetFilterQuery> findWithAutoAssignDS(final Pageable pageable) {
return JpaManagementHelper.findAllWithoutCountBySpec(targetFilterQueryRepository, return JpaManagementHelper.findAllWithoutCountBySpec(
Collections.singletonList(TargetFilterQuerySpecification.withAutoAssignDS()), pageable jpaRepository, List.of(TargetFilterQuerySpecification.withAutoAssignDS()), pageable);
);
}
@Override
public Optional<TargetFilterQuery> get(final long targetFilterQueryId) {
return targetFilterQueryRepository.findById(targetFilterQueryId).map(TargetFilterQuery.class::cast);
}
@Override
public Optional<TargetFilterQuery> getByName(final String targetFilterQueryName) {
return targetFilterQueryRepository.findByName(targetFilterQueryName);
}
@Override
@Transactional
public TargetFilterQuery update(final TargetFilterQueryUpdate u) {
final GenericTargetFilterQueryUpdate update = (GenericTargetFilterQueryUpdate) u;
final JpaTargetFilterQuery targetFilterQuery = findTargetFilterQueryOrThrowExceptionIfNotFound(update.getId());
update.getName().ifPresent(targetFilterQuery::setName);
update.getQuery().ifPresent(query -> {
// enforce the 'max targets per auto assignment'-quota only if the
// query is going to change
if (targetFilterQuery.getAutoAssignDistributionSet() != null
&& !query.equals(targetFilterQuery.getQuery())) {
assertMaxTargetsQuota(query, targetFilterQuery.getName(),
targetFilterQuery.getAutoAssignDistributionSet().getId());
}
// set the new query
targetFilterQuery.setQuery(query);
});
update.getConfirmationRequired().ifPresent(targetFilterQuery::setConfirmationRequired);
return targetFilterQueryRepository.save(targetFilterQuery);
} }
@Override @Override
@Transactional @Transactional
public TargetFilterQuery updateAutoAssignDS(final AutoAssignDistributionSetUpdate update) { public TargetFilterQuery updateAutoAssignDS(final AutoAssignDistributionSetUpdate update) {
final JpaTargetFilterQuery targetFilterQuery = findTargetFilterQueryOrThrowExceptionIfNotFound( final JpaTargetFilterQuery targetFilterQuery = findTargetFilterQueryOrThrowExceptionIfNotFound(update.targetFilterId());
update.getTargetFilterId()); if (update.dsId() == null) {
if (update.getDsId() == null) {
targetFilterQuery.setAccessControlContext(null); targetFilterQuery.setAccessControlContext(null);
targetFilterQuery.setAutoAssignDistributionSet(null); targetFilterQuery.setAutoAssignDistributionSet(null);
targetFilterQuery.setAutoAssignActionType(null); targetFilterQuery.setAutoAssignActionType(null);
@@ -283,9 +163,9 @@ class JpaTargetFilterQueryManagement implements TargetFilterQueryManagement {
targetFilterQuery.setConfirmationRequired(false); targetFilterQuery.setConfirmationRequired(false);
} else { } else {
WeightValidationHelper.usingContext(systemSecurityContext, tenantConfigurationManagement).validate(update); WeightValidationHelper.usingContext(systemSecurityContext, tenantConfigurationManagement).validate(update);
assertMaxTargetsQuota(targetFilterQuery.getQuery(), targetFilterQuery.getName(), update.getDsId()); assertMaxTargetsQuota(targetFilterQuery.getQuery(), targetFilterQuery.getName(), update.dsId());
final JpaDistributionSet distributionSet = (JpaDistributionSet) distributionSetManagement final JpaDistributionSet distributionSet = (JpaDistributionSet) distributionSetManagement
.getValidAndComplete(update.getDsId()); .getValidAndComplete(update.dsId());
if (((JpaDistributionSetManagement) distributionSetManagement).isImplicitLockApplicable(distributionSet)) { if (((JpaDistributionSetManagement) distributionSetManagement).isImplicitLockApplicable(distributionSet)) {
distributionSetManagement.lock(distributionSet.getId()); distributionSetManagement.lock(distributionSet.getId());
@@ -293,23 +173,20 @@ class JpaTargetFilterQueryManagement implements TargetFilterQueryManagement {
targetFilterQuery.setAutoAssignDistributionSet(distributionSet); targetFilterQuery.setAutoAssignDistributionSet(distributionSet);
contextAware.getCurrentContext().ifPresent(targetFilterQuery::setAccessControlContext); contextAware.getCurrentContext().ifPresent(targetFilterQuery::setAccessControlContext);
targetFilterQuery.setAutoAssignInitiatedBy( targetFilterQuery.setAutoAssignInitiatedBy(auditorAware.getCurrentAuditor().orElse(targetFilterQuery.getCreatedBy()));
auditorAware.getCurrentAuditor().orElse(targetFilterQuery.getCreatedBy())); targetFilterQuery.setAutoAssignActionType(sanitizeAutoAssignActionType(update.actionType()));
targetFilterQuery.setAutoAssignActionType(sanitizeAutoAssignActionType(update.getActionType())); targetFilterQuery.setAutoAssignWeight(update.weight() == null ? repositoryProperties.getActionWeightIfAbsent() : update.weight());
targetFilterQuery.setAutoAssignWeight(
update.getWeight() == null ? repositoryProperties.getActionWeightIfAbsent() : update.getWeight());
final boolean confirmationRequired = final boolean confirmationRequired =
update.getConfirmationRequired() == null ? update.confirmationRequired() == null ? isConfirmationFlowEnabled() : update.confirmationRequired();
isConfirmationFlowEnabled() : update.getConfirmationRequired();
targetFilterQuery.setConfirmationRequired(confirmationRequired); targetFilterQuery.setConfirmationRequired(confirmationRequired);
} }
return targetFilterQueryRepository.save(targetFilterQuery); return jpaRepository.save(targetFilterQuery);
} }
@Override @Override
@Transactional @Transactional
public void cancelAutoAssignmentForDistributionSet(final long distributionSetId) { public void cancelAutoAssignmentForDistributionSet(final long distributionSetId) {
targetFilterQueryRepository.unsetAutoAssignDistributionSetAndActionTypeAndAccessContext(distributionSetId); jpaRepository.unsetAutoAssignDistributionSetAndActionTypeAndAccessContext(distributionSetId);
log.debug("Auto assignments for distribution sets {} deactivated", distributionSetId); log.debug("Auto assignments for distribution sets {} deactivated", distributionSetId);
} }
@@ -331,8 +208,7 @@ class JpaTargetFilterQueryManagement implements TargetFilterQueryManagement {
} }
private JpaTargetFilterQuery findTargetFilterQueryOrThrowExceptionIfNotFound(final Long queryId) { private JpaTargetFilterQuery findTargetFilterQueryOrThrowExceptionIfNotFound(final Long queryId) {
return targetFilterQueryRepository.findById(queryId) return jpaRepository.findById(queryId).orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, queryId));
.orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, queryId));
} }
private void assertMaxTargetsQuota(final String query, final String filterName, final long dsId) { private void assertMaxTargetsQuota(final String query, final String filterName, final long dsId) {
@@ -340,4 +216,51 @@ class JpaTargetFilterQueryManagement implements TargetFilterQueryManagement {
targetManagement.countByRsqlAndNonDSAndCompatibleAndUpdatable(dsId, query), targetManagement.countByRsqlAndNonDSAndCompatibleAndUpdatable(dsId, query),
quotaManagement.getMaxTargetsPerAutoAssignment(), Target.class, TargetFilterQuery.class, null); quotaManagement.getMaxTargetsPerAutoAssignment(), Target.class, TargetFilterQuery.class, null);
} }
}
private void validate(final Create create) {
Optional.ofNullable(create.getAutoAssignDistributionSet()).ifPresent(distributionSet -> {
if (!distributionSet.isValid()) {
throw new InvalidDistributionSetException();
}
if (!distributionSet.isComplete()) {
throw new IncompleteDistributionSetException();
}
});
Optional.ofNullable(create.getAutoAssignActionType()).ifPresent(actionType -> {
if (!TargetFilterQuery.ALLOWED_AUTO_ASSIGN_ACTION_TYPES.contains(actionType)) {
throw new InvalidAutoAssignActionTypeException();
}
});
Optional.ofNullable(create.getQuery()).ifPresent(query -> {
// validate the RSQL query syntax
RsqlUtility.getInstance().validateRsqlFor(query, TargetFields.class, JpaTarget.class);
// enforce the 'max targets per auto assign' quota right here even if the result of the filter query can vary over time
Optional.ofNullable(create.getAutoAssignDistributionSet()).ifPresent(dsId -> {
WeightValidationHelper.usingContext(systemSecurityContext, tenantConfigurationManagement).validate(create);
assertMaxTargetsQuota(query, create.getName(), dsId.getId());
});
});
if (create.getAutoAssignWeight() == null) {
create.setAutoAssignWeight(create.getAutoAssignDistributionSet() == null ? 0 : repositoryProperties.getActionWeightIfAbsent());
}
}
private void validate(final Update update) {
final JpaTargetFilterQuery targetFilterQuery = findTargetFilterQueryOrThrowExceptionIfNotFound(update.getId());
Optional.ofNullable(update.getQuery()).ifPresent(query -> {
// validate the RSQL query syntax
RsqlUtility.getInstance().validateRsqlFor(query, TargetFields.class, JpaTarget.class);
Optional.ofNullable(targetFilterQuery.getAutoAssignDistributionSet()).ifPresent(autoAssignDs -> {
// enforce the 'max targets per auto assignment'-quota only if the query is going to change
if (!query.equals(targetFilterQuery.getQuery())) {
assertMaxTargetsQuota(query, targetFilterQuery.getName(), autoAssignDs.getId());
}
});
// set the new query
targetFilterQuery.setQuery(query);
});
}
}

View File

@@ -64,11 +64,11 @@ public class JpaTargetFilterQuery extends AbstractJpaTenantAwareBaseEntity imple
@NotEmpty @NotEmpty
private String query; private String query;
@ManyToOne(optional = true, fetch = FetchType.LAZY, targetEntity = JpaDistributionSet.class) @ManyToOne(fetch = FetchType.LAZY, targetEntity = JpaDistributionSet.class)
@JoinColumn( @JoinColumn(
name = "auto_assign_distribution_set", name = "auto_assign_distribution_set",
foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_target_filter_query_auto_assign_distribution_set")) foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_target_filter_query_auto_assign_distribution_set"))
private JpaDistributionSet autoAssignDistributionSet; private DistributionSet autoAssignDistributionSet;
@Column(name = "auto_assign_action_type") @Column(name = "auto_assign_action_type")
@Convert(converter = JpaAction.ActionTypeConverter.class) @Convert(converter = JpaAction.ActionTypeConverter.class)

View File

@@ -33,22 +33,7 @@ public final class TargetFilterQuerySpecification {
* @return the {@link JpaTargetFilterQuery} {@link Specification} * @return the {@link JpaTargetFilterQuery} {@link Specification}
*/ */
public static Specification<JpaTargetFilterQuery> equalsQuery(final String queryValue) { public static Specification<JpaTargetFilterQuery> equalsQuery(final String queryValue) {
return (targetFilterQueryRoot, query, cb) -> cb.equal(targetFilterQueryRoot.get(JpaTargetFilterQuery_.query), return (targetFilterQueryRoot, query, cb) -> cb.equal(targetFilterQueryRoot.get(JpaTargetFilterQuery_.query), queryValue);
queryValue);
}
/**
* {@link Specification} for retrieving {@link JpaTargetFilterQuery}s based
* on is {@link JpaTargetFilterQuery#getName()}.
*
* @param searchText of the filter
* @return the {@link JpaTargetFilterQuery} {@link Specification}
*/
public static Specification<JpaTargetFilterQuery> likeName(final String searchText) {
return (targetFilterQueryRoot, query, cb) -> {
final String searchTextToLower = searchText.toLowerCase();
return cb.like(cb.lower(targetFilterQueryRoot.get(JpaTargetFilterQuery_.name)), searchTextToLower);
};
} }
/** /**

View File

@@ -11,10 +11,9 @@ package org.eclipse.hawkbit.repository.jpa.utils;
import java.util.List; import java.util.List;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate;
import org.eclipse.hawkbit.repository.exception.NoWeightProvidedInMultiAssignmentModeException; import org.eclipse.hawkbit.repository.exception.NoWeightProvidedInMultiAssignmentModeException;
import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetFilterQueryCreate;
import org.eclipse.hawkbit.repository.model.DeploymentRequest; import org.eclipse.hawkbit.repository.model.DeploymentRequest;
import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.security.SystemSecurityContext;
@@ -29,8 +28,8 @@ public final class WeightValidationHelper {
private final TenantConfigurationManagement tenantConfigurationManagement; private final TenantConfigurationManagement tenantConfigurationManagement;
private final SystemSecurityContext systemSecurityContext; private final SystemSecurityContext systemSecurityContext;
private WeightValidationHelper(final SystemSecurityContext systemSecurityContext, private WeightValidationHelper(
final TenantConfigurationManagement tenantConfigurationManagement) { final SystemSecurityContext systemSecurityContext, final TenantConfigurationManagement tenantConfigurationManagement) {
this.systemSecurityContext = systemSecurityContext; this.systemSecurityContext = systemSecurityContext;
this.tenantConfigurationManagement = tenantConfigurationManagement; this.tenantConfigurationManagement = tenantConfigurationManagement;
} }
@@ -41,8 +40,8 @@ public final class WeightValidationHelper {
* @param systemSecurityContext security context used to get the tenant and for execution * @param systemSecurityContext security context used to get the tenant and for execution
* @param tenantConfigurationManagement to get the value from * @param tenantConfigurationManagement to get the value from
*/ */
public static WeightValidationHelper usingContext(final SystemSecurityContext systemSecurityContext, public static WeightValidationHelper usingContext(
final TenantConfigurationManagement tenantConfigurationManagement) { final SystemSecurityContext systemSecurityContext, final TenantConfigurationManagement tenantConfigurationManagement) {
return new WeightValidationHelper(systemSecurityContext, tenantConfigurationManagement); return new WeightValidationHelper(systemSecurityContext, tenantConfigurationManagement);
} }
@@ -74,9 +73,8 @@ public final class WeightValidationHelper {
* *
* @param targetFilterQueryCreate the target filter query * @param targetFilterQueryCreate the target filter query
*/ */
public void validate(final JpaTargetFilterQueryCreate targetFilterQueryCreate) { public void validate(final TargetFilterQueryManagement.Create targetFilterQueryCreate) {
validateWeight(targetFilterQueryCreate.getAutoAssignWeight().orElse(null)); validateWeight(targetFilterQueryCreate.getAutoAssignWeight());
} }
/** /**
@@ -84,16 +82,14 @@ public final class WeightValidationHelper {
* *
* @param autoAssignDistributionSetUpdate the auto assignment distribution set update * @param autoAssignDistributionSetUpdate the auto assignment distribution set update
*/ */
public void validate(final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate) { public void validate(final TargetFilterQueryManagement.AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate) {
validateWeight(autoAssignDistributionSetUpdate.getWeight()); validateWeight(autoAssignDistributionSetUpdate.weight());
} }
/** /**
* Checks if the weight is valid * Checks if the weight is valid
* *
* @param weight weight tied to the rollout, auto assignment, or online * @param weight weight tied to the rollout, auto assignment, or online assignment.
* assignment.
*/ */
public void validateWeight(final Integer weight) { public void validateWeight(final Integer weight) {
final boolean hasWeight = weight != null; final boolean hasWeight = weight != null;
@@ -101,8 +97,7 @@ public final class WeightValidationHelper {
} }
/** /**
* Checks if the weight is valid with the multi-assignments being turned * Checks if the weight is valid with the multi-assignments being turned off/on.
* off/on.
* *
* @param hasWeight indicator of the weight if it has numerical value * @param hasWeight indicator of the weight if it has numerical value
* @param hasNoWeight indicator of the weight if it doesn't have a numerical value * @param hasNoWeight indicator of the weight if it doesn't have a numerical value
@@ -119,4 +114,4 @@ public final class WeightValidationHelper {
throw new NoWeightProvidedInMultiAssignmentModeException(); throw new NoWeightProvidedInMultiAssignmentModeException();
} }
} }
} }

View File

@@ -26,7 +26,7 @@ import java.util.Map;
import org.eclipse.hawkbit.repository.DistributionSetTagManagement; import org.eclipse.hawkbit.repository.DistributionSetTagManagement;
import org.eclipse.hawkbit.repository.Identifiable; import org.eclipse.hawkbit.repository.Identifiable;
import org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException; import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
@@ -259,7 +259,7 @@ class DistributionSetAccessControllerTest extends AbstractJpaIntegrationTest {
distributionSetManagement.lock(hidden.getId()); distributionSetManagement.lock(hidden.getId());
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name("test").query("id==*")); .create(TargetFilterQueryManagement.Create.builder().name("test").query("id==*").build());
runAs(withUser("user", runAs(withUser("user",
READ_REPOSITORY, READ_REPOSITORY,
@@ -268,14 +268,14 @@ class DistributionSetAccessControllerTest extends AbstractJpaIntegrationTest {
// read / update target needed to update target filter query // read / update target needed to update target filter query
READ_TARGET, UPDATE_TARGET), () -> { READ_TARGET, UPDATE_TARGET), () -> {
assertThat(targetFilterQueryManagement assertThat(targetFilterQueryManagement
.updateAutoAssignDS(new AutoAssignDistributionSetUpdate(targetFilterQuery.getId()).ds(permitted.getId()) .updateAutoAssignDS(new TargetFilterQueryManagement.AutoAssignDistributionSetUpdate(targetFilterQuery.getId()).ds(permitted.getId())
.actionType(Action.ActionType.FORCED).confirmationRequired(false)) .actionType(Action.ActionType.FORCED).confirmationRequired(false))
.getAutoAssignDistributionSet().getId()).isEqualTo(permitted.getId()); .getAutoAssignDistributionSet().getId()).isEqualTo(permitted.getId());
targetFilterQueryManagement targetFilterQueryManagement
.updateAutoAssignDS(new AutoAssignDistributionSetUpdate(targetFilterQuery.getId()) .updateAutoAssignDS(new TargetFilterQueryManagement.AutoAssignDistributionSetUpdate(targetFilterQuery.getId())
.ds(readOnly.getId()).actionType(Action.ActionType.FORCED).confirmationRequired(false)) .ds(readOnly.getId()).actionType(Action.ActionType.FORCED).confirmationRequired(false))
.getAutoAssignDistributionSet().getId(); .getAutoAssignDistributionSet().getId();
final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate = new AutoAssignDistributionSetUpdate( final TargetFilterQueryManagement.AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate = new TargetFilterQueryManagement.AutoAssignDistributionSetUpdate(
targetFilterQuery.getId()) targetFilterQuery.getId())
.ds(hidden.getId()).actionType(Action.ActionType.FORCED).confirmationRequired(false); .ds(hidden.getId()).actionType(Action.ActionType.FORCED).confirmationRequired(false);
assertThatThrownBy(() -> targetFilterQueryManagement.updateAutoAssignDS(autoAssignDistributionSetUpdate)) assertThatThrownBy(() -> targetFilterQueryManagement.updateAutoAssignDS(autoAssignDistributionSetUpdate))

View File

@@ -25,6 +25,8 @@ import java.util.List;
import org.eclipse.hawkbit.repository.FilterParams; import org.eclipse.hawkbit.repository.FilterParams;
import org.eclipse.hawkbit.repository.Identifiable; import org.eclipse.hawkbit.repository.Identifiable;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.AutoAssignDistributionSetUpdate;
import org.eclipse.hawkbit.repository.TargetTagManagement; import org.eclipse.hawkbit.repository.TargetTagManagement;
import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException; import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
@@ -103,7 +105,7 @@ class TargetAccessControllerTest extends AbstractJpaIntegrationTest {
}); });
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name("test").query("id==*")); .create(TargetFilterQueryManagement.Create.builder().name("test").query("id==*").build());
runAs(withUser("user", READ_TARGET + "/controllerId==" + permittedTarget.getControllerId()), () -> { runAs(withUser("user", READ_TARGET + "/controllerId==" + permittedTarget.getControllerId()), () -> {
// verify targetManagement#findByTargetFilterQuery // verify targetManagement#findByTargetFilterQuery
@@ -314,7 +316,7 @@ class TargetAccessControllerTest extends AbstractJpaIntegrationTest {
final List<Target> hiddenTargets = testdataFactory.createTargets("hidden1", "hidden2", "hidden3", "hidden4", "hidden5"); final List<Target> hiddenTargets = testdataFactory.createTargets("hidden1", "hidden2", "hidden3", "hidden4", "hidden5");
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name("testName").query("id==*")); .create(TargetFilterQueryManagement.Create.builder().name("testName").query("id==*").build());
runAs(withUser("user", runAs(withUser("user",
READ_TARGET + "/controllerId=in=(" + String.join(", ", List.of(updateTargetControllerIds)) + ")" + READ_TARGET + "/controllerId=in=(" + String.join(", ", List.of(updateTargetControllerIds)) + ")" +
@@ -322,8 +324,8 @@ class TargetAccessControllerTest extends AbstractJpaIntegrationTest {
UPDATE_TARGET + "/controllerId=in=(" + String.join(", ", List.of(updateTargetControllerIds)) + ")", UPDATE_TARGET + "/controllerId=in=(" + String.join(", ", List.of(updateTargetControllerIds)) + ")",
READ_REPOSITORY + "/id==" + distributionSet.getId()), () -> { READ_REPOSITORY + "/id==" + distributionSet.getId()), () -> {
targetFilterQueryManagement.updateAutoAssignDS(entityFactory.targetFilterQuery() targetFilterQueryManagement.updateAutoAssignDS(
.updateAutoAssign(targetFilterQuery.getId()).ds(distributionSet.getId())); new AutoAssignDistributionSetUpdate(targetFilterQuery.getId()).ds(distributionSet.getId()));
autoAssignChecker.checkAllTargets(); autoAssignChecker.checkAllTargets();

View File

@@ -12,17 +12,16 @@ package org.eclipse.hawkbit.repository.jpa.autoassign;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.eclipse.hawkbit.repository.DeploymentManagement; import org.eclipse.hawkbit.repository.DeploymentManagement;
import org.eclipse.hawkbit.repository.DistributionSetManagement.Create; import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.AutoAssignDistributionSetUpdate;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.Create;
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException; import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
import org.eclipse.hawkbit.repository.jpa.specifications.ActionSpecifications; import org.eclipse.hawkbit.repository.jpa.specifications.ActionSpecifications;
@@ -80,9 +79,9 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
// target filter query that matches all targets // target filter query that matches all targets
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name("filterA").query("name==*")); .create(Create.builder().name("filterA").query("name==*").build());
targetFilterQueryManagement.updateAutoAssignDS(entityFactory.targetFilterQuery() targetFilterQueryManagement.updateAutoAssignDS(
.updateAutoAssign(targetFilterQuery.getId()).ds(secondDistributionSet.getId())); new AutoAssignDistributionSetUpdate(targetFilterQuery.getId()).ds(secondDistributionSet.getId()));
// Run the check // Run the check
autoAssignChecker.checkAllTargets(); autoAssignChecker.checkAllTargets();
@@ -116,11 +115,10 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
final DistributionSet setB = testdataFactory.createDistributionSet("dsB"); final DistributionSet setB = testdataFactory.createDistributionSet("dsB");
// target filter query that matches all targets // target filter query that matches all targets
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement.updateAutoAssignDS(entityFactory final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement.updateAutoAssignDS(
.targetFilterQuery() new AutoAssignDistributionSetUpdate(targetFilterQueryManagement
.updateAutoAssign(targetFilterQueryManagement .create(Create.builder().name("filterA").query("name==*").build()).getId())
.create(entityFactory.targetFilterQuery().create().name("filterA").query("name==*")).getId()) .ds(setA.getId()));
.ds(setA.getId()));
implicitLock(setA); implicitLock(setA);
final String targetDsAIdPref = "targ"; final String targetDsAIdPref = "targ";
@@ -169,10 +167,10 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
final DistributionSet toAssignDs = testdataFactory.createDistributionSet(); final DistributionSet toAssignDs = testdataFactory.createDistributionSet();
// target filter query that matches all targets // target filter query that matches all targets
targetFilterQueryManagement.updateAutoAssignDS(entityFactory.targetFilterQuery() targetFilterQueryManagement.updateAutoAssignDS(
.updateAutoAssign(targetFilterQueryManagement new AutoAssignDistributionSetUpdate(targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name("filterA").query("name==*")).getId()) .create(Create.builder().name("filterA").query("name==*").build()).getId())
.ds(toAssignDs.getId())); .ds(toAssignDs.getId()));
implicitLock(toAssignDs); implicitLock(toAssignDs);
final List<Target> targets = testdataFactory.createTargets(25); final List<Target> targets = testdataFactory.createTargets(25);
@@ -200,11 +198,10 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
enableConfirmationFlow(); enableConfirmationFlow();
} }
targetFilterQueryManagement.updateAutoAssignDS(entityFactory targetFilterQueryManagement.updateAutoAssignDS(
.targetFilterQuery() new AutoAssignDistributionSetUpdate(targetFilterQueryManagement
.updateAutoAssign(targetFilterQueryManagement .create(Create.builder().name("filterA").query("name==*").build()).getId())
.create(entityFactory.targetFilterQuery().create().name("filterA").query("name==*")).getId()) .ds(distributionSet.getId()).confirmationRequired(confirmationRequired));
.ds(distributionSet.getId()).confirmationRequired(confirmationRequired));
final String targetDsAIdPref = "targ"; final String targetDsAIdPref = "targ";
final List<Target> targets = testdataFactory.createTargets(20, targetDsAIdPref, final List<Target> targets = testdataFactory.createTargets(20, targetDsAIdPref,
@@ -231,10 +228,10 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
} }
// target filter query that matches all targets // target filter query that matches all targets
targetFilterQueryManagement.updateAutoAssignDS(entityFactory.targetFilterQuery() targetFilterQueryManagement.updateAutoAssignDS(
.updateAutoAssign(targetFilterQueryManagement new AutoAssignDistributionSetUpdate(targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name("filterA").query("name==*")).getId()) .create(Create.builder().name("filterA").query("name==*").build()).getId())
.ds(toAssignDs.getId()).confirmationRequired(confirmationRequired)); .ds(toAssignDs.getId()).confirmationRequired(confirmationRequired));
final List<Target> targets = testdataFactory.createTargets(25); final List<Target> targets = testdataFactory.createTargets(25);
@@ -252,7 +249,7 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
void checkAutoAssignWithFailures() { void checkAutoAssignWithFailures() {
// incomplete distribution set that will be assigned // incomplete distribution set that will be assigned
final DistributionSet setF = distributionSetManagement.create(Create.builder() final DistributionSet setF = distributionSetManagement.create(DistributionSetManagement.Create.builder()
.type(testdataFactory.findOrCreateDefaultTestDsType()) .type(testdataFactory.findOrCreateDefaultTestDsType())
.name("dsA").version("1") .name("dsA").version("1")
.build()); .build());
@@ -263,15 +260,15 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
final String targetDsFIdPref = "targB"; final String targetDsFIdPref = "targB";
final Long filterId = targetFilterQueryManagement.create( final Long filterId = targetFilterQueryManagement.create(
entityFactory.targetFilterQuery().create().name("filterA").query("id==" + targetDsFIdPref + "*")) Create.builder().name("filterA").query("id==" + targetDsFIdPref + "*").build())
.getId(); .getId();
final AutoAssignDistributionSetUpdate targetFilterQuery = entityFactory.targetFilterQuery().updateAutoAssign(filterId).ds(setF.getId()); final AutoAssignDistributionSetUpdate targetFilterQuery = new AutoAssignDistributionSetUpdate(filterId).ds(setF.getId());
// target filter query that matches first bunch of targets, that should fail // target filter query that matches first bunch of targets, that should fail
assertThatExceptionOfType(IncompleteDistributionSetException.class).isThrownBy( assertThatExceptionOfType(IncompleteDistributionSetException.class).isThrownBy(
() -> targetFilterQueryManagement.updateAutoAssignDS(targetFilterQuery)); () -> targetFilterQueryManagement.updateAutoAssignDS(targetFilterQuery));
// target filter query that matches failed bunch of targets // target filter query that matches failed bunch of targets
targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name("filterB") targetFilterQueryManagement.create(Create.builder().name("filterB")
.query("id==" + targetDsAIdPref + "*").autoAssignDistributionSet(setA.getId())); .query("id==" + targetDsAIdPref + "*").autoAssignDistributionSet(setA).build());
implicitLock(setA); implicitLock(setA);
final List<Target> targetsF = testdataFactory.createTargets(10, targetDsFIdPref, final List<Target> targetsF = testdataFactory.createTargets(10, targetDsFIdPref,
@@ -308,13 +305,11 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
final String targetDsBIdPref = "B"; final String targetDsBIdPref = "B";
final String targetDsCIdPref = "C"; final String targetDsCIdPref = "C";
final List<Target> targetsA = createTargetsAndAutoAssignDistSet(targetDsAIdPref, 5, distributionSet, final List<Target> targetsA = createTargetsAndAutoAssignDistSet(targetDsAIdPref, 5, distributionSet, ActionType.FORCED);
ActionType.FORCED);
implicitLock(distributionSet); implicitLock(distributionSet);
final List<Target> targetsB = createTargetsAndAutoAssignDistSet(targetDsBIdPref, 10, distributionSet, final DistributionSet distributionSetLocked = distributionSetManagement.get(distributionSet.getId()).orElseThrow();
ActionType.SOFT); final List<Target> targetsB = createTargetsAndAutoAssignDistSet(targetDsBIdPref, 10, distributionSetLocked, ActionType.SOFT);
final List<Target> targetsC = createTargetsAndAutoAssignDistSet(targetDsCIdPref, 10, distributionSet, final List<Target> targetsC = createTargetsAndAutoAssignDistSet(targetDsCIdPref, 10, distributionSetLocked, ActionType.DOWNLOAD_ONLY);
ActionType.DOWNLOAD_ONLY);
final int targetsCount = targetsA.size() + targetsB.size() + targetsC.size(); final int targetsCount = targetsA.size() + targetsB.size() + targetsC.size();
@@ -339,8 +334,9 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
final int weight = 32; final int weight = 32;
enableMultiAssignments(); enableMultiAssignments();
targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name("a").query("name==*") targetFilterQueryManagement.create(Create.builder()
.autoAssignDistributionSet(ds).autoAssignWeight(weight)); .name("a").query("name==*").autoAssignDistributionSet(ds).autoAssignWeight(weight)
.build());
testdataFactory.createTargets(amountOfTargets); testdataFactory.createTargets(amountOfTargets);
autoAssignChecker.checkAllTargets(); autoAssignChecker.checkAllTargets();
@@ -357,8 +353,7 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
void filterWithoutWeightWorksInMultiAssignmentMode() { void filterWithoutWeightWorksInMultiAssignmentMode() {
final int amountOfTargets = 5; final int amountOfTargets = 5;
final DistributionSet ds = testdataFactory.createDistributionSet(); final DistributionSet ds = testdataFactory.createDistributionSet();
targetFilterQueryManagement.create( targetFilterQueryManagement.create(Create.builder().name("a").query("name==*").autoAssignDistributionSet(ds).build());
entityFactory.targetFilterQuery().create().name("a").query("name==*").autoAssignDistributionSet(ds));
enableMultiAssignments(); enableMultiAssignments();
testdataFactory.createTargets(amountOfTargets); testdataFactory.createTargets(amountOfTargets);
@@ -382,8 +377,8 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
.findOrCreateDistributionSetType("incompatibleDsType1", "incompDsType1"); .findOrCreateDistributionSetType("incompatibleDsType1", "incompDsType1");
final DistributionSetType incompatibleDsType2 = testdataFactory final DistributionSetType incompatibleDsType2 = testdataFactory
.findOrCreateDistributionSetType("incompatibleDsType2", "incompDsType2"); .findOrCreateDistributionSetType("incompatibleDsType2", "incompDsType2");
final TargetFilterQuery testFilter = targetFilterQueryManagement.create(entityFactory.targetFilterQuery() final TargetFilterQuery testFilter = targetFilterQueryManagement.create(
.create().name("test-filter").query("name==*").autoAssignDistributionSet(testDs)); Create.builder().name("test-filter").query("name==*").autoAssignDistributionSet(testDs).build());
final TargetType incompatibleEmptyType = testdataFactory.createTargetType("incompatibleEmptyType", Set.of()); final TargetType incompatibleEmptyType = testdataFactory.createTargetType("incompatibleEmptyType", Set.of());
final TargetType incompatibleSingleType = testdataFactory.createTargetType( final TargetType incompatibleSingleType = testdataFactory.createTargetType(
@@ -429,12 +424,7 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
Arguments.of(false, false, Status.RUNNING)); Arguments.of(false, false, Status.RUNNING));
} }
/** private void verifyThatTargetsHaveDistributionSetAssignment(final DistributionSet set, final List<Target> targets, final int count) {
* @param set the expected distribution set
* @param targets the targets that should have it
*/
private void verifyThatTargetsHaveDistributionSetAssignment(
final DistributionSet set, final List<Target> targets, final int count) {
final List<Long> targetIds = targets.stream().map(Target::getId).toList(); final List<Long> targetIds = targets.stream().map(Target::getId).toList();
final Slice<Target> targetsAll = targetManagement.findAll(PAGE); final Slice<Target> targetsAll = targetManagement.findAll(PAGE);
@@ -442,22 +432,19 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
for (final Target target : targetsAll) { for (final Target target : targetsAll) {
if (targetIds.contains(target.getId())) { if (targetIds.contains(target.getId())) {
assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId())) assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId())).as("assigned DS").contains(set);
.as("assigned DS").contains(set);
} }
} }
} }
private void verifyThatTargetsHaveDistributionSetAssignedAndActionStatus(final DistributionSet set, private void verifyThatTargetsHaveDistributionSetAssignedAndActionStatus(
final List<Target> targets, final Action.Status status) { final DistributionSet set, final List<Target> targets, final Action.Status status) {
final List<String> targetIds = targets.stream().map(Target::getControllerId).toList(); final List<String> targetIds = targets.stream().map(Target::getControllerId).toList();
final List<Target> targetsWithAssignedDS = targetManagement.findByAssignedDistributionSet(set.getId(), PAGE).getContent(); final List<Target> targetsWithAssignedDS = targetManagement.findByAssignedDistributionSet(set.getId(), PAGE).getContent();
assertThat(targetsWithAssignedDS).isNotEmpty(); assertThat(targetsWithAssignedDS).isNotEmpty();
assertThat(targetsWithAssignedDS).allMatch(target -> targetIds.contains(target.getControllerId())); assertThat(targetsWithAssignedDS).allMatch(target -> targetIds.contains(target.getControllerId()));
final List<Action> actionsByDs = findActionsByDistributionSet(PAGE, set.getId()) final List<Action> actionsByDs = findActionsByDistributionSet(PAGE, set.getId()).getContent();
.getContent();
assertThat(actionsByDs).hasSize(targets.size()); assertThat(actionsByDs).hasSize(targets.size());
assertThat(actionsByDs).allMatch(action -> action.getStatus() == status); assertThat(actionsByDs).allMatch(action -> action.getStatus() == status);
} }
@@ -490,9 +477,10 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
final List<Target> targets = testdataFactory.createTargets(targetCount, "target" + prefix, final List<Target> targets = testdataFactory.createTargets(targetCount, "target" + prefix,
prefix.concat(SPACE_AND_DESCRIPTION)); prefix.concat(SPACE_AND_DESCRIPTION));
targetFilterQueryManagement.create( targetFilterQueryManagement.create(Create.builder()
entityFactory.targetFilterQuery().create().name("filter" + prefix).query("id==target" + prefix + "*") .name("filter" + prefix).query("id==target" + prefix + "*")
.autoAssignDistributionSet(distributionSet).autoAssignActionType(actionType)); .autoAssignDistributionSet(distributionSet).autoAssignActionType(actionType)
.build());
return targets; return targets;
} }

View File

@@ -15,6 +15,7 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException; import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException; import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
@@ -145,12 +146,10 @@ class DistributionSetInvalidationManagementTest extends AbstractJpaIntegrationTe
*/ */
@Test @Test
void verifyInvalidateDistributionSetStopAll() { void verifyInvalidateDistributionSetStopAll() {
final InvalidationTestData invalidationTestData = createInvalidationTestData( final InvalidationTestData invalidationTestData = createInvalidationTestData("verifyInvalidateDistributionSetStopAll");
"verifyInvalidateDistributionSetStopAll");
final DistributionSetInvalidation distributionSetInvalidation = new DistributionSetInvalidation( final DistributionSetInvalidation distributionSetInvalidation = new DistributionSetInvalidation(
Collections.singletonList(invalidationTestData.getDistributionSet().getId()), CancelationType.SOFT, Collections.singletonList(invalidationTestData.getDistributionSet().getId()), CancelationType.SOFT,true);
true);
final DistributionSetInvalidationCount distributionSetInvalidationCount = distributionSetInvalidationManagement final DistributionSetInvalidationCount distributionSetInvalidationCount = distributionSetInvalidationManagement
.countEntitiesForInvalidation(distributionSetInvalidation); .countEntitiesForInvalidation(distributionSetInvalidation);
assertDistributionSetInvalidationCount(distributionSetInvalidationCount, 1, 5, 1); assertDistributionSetInvalidationCount(distributionSetInvalidationCount, 1, 5, 1);
@@ -185,10 +184,11 @@ class DistributionSetInvalidationManagementTest extends AbstractJpaIntegrationTe
/** /**
* Verify that invalidating an invalidated distribution set don't throws an exception * Verify that invalidating an invalidated distribution set don't throws an exception
* -> should be able to cancel actions again (if previous time there was a problem * -> should be able to cancel actions again (if previous time there was a problem
*/ */
@Test @Test
@SuppressWarnings("java:S2699") // test that no exception is thrown @SuppressWarnings("java:S2699")
// test that no exception is thrown
void verifyInvalidateInvalidatedDistributionSetDontThrowsException() { void verifyInvalidateInvalidatedDistributionSetDontThrowsException() {
final DistributionSet distributionSet = testdataFactory.createAndInvalidateDistributionSet(); final DistributionSet distributionSet = testdataFactory.createAndInvalidateDistributionSet();
distributionSetInvalidationManagement.invalidateDistributionSet( distributionSetInvalidationManagement.invalidateDistributionSet(
@@ -266,13 +266,13 @@ class DistributionSetInvalidationManagementTest extends AbstractJpaIntegrationTe
} }
private InvalidationTestData createInvalidationTestData(final String testName) { private InvalidationTestData createInvalidationTestData(final String testName) {
final DistributionSet distributionSet = testdataFactory.createDistributionSet(); DistributionSet distributionSet = testdataFactory.createDistributionSet();
final List<Target> targets = testdataFactory.createTargets(5, testName); final List<Target> targets = testdataFactory.createTargets(5, testName);
assignDistributionSet(distributionSet, targets); // if implicitly locked - the old distribution set becomes stale
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement.create(entityFactory.targetFilterQuery() distributionSet = assignDistributionSet(distributionSet, targets).getDistributionSet();
.create().name(testName).query("name==*").autoAssignDistributionSet(distributionSet)); final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement.create(TargetFilterQueryManagement.Create.builder()
final Rollout rollout = testdataFactory.createRolloutByVariables(testName, "desc", 2, "name==*", .name(testName).query("name==*").autoAssignDistributionSet(distributionSet).build());
distributionSet, "50", "80"); final Rollout rollout = testdataFactory.createRolloutByVariables(testName, "desc", 2, "name==*", distributionSet, "50", "80");
return new InvalidationTestData(distributionSet, targets, targetFilterQuery, rollout); return new InvalidationTestData(distributionSet, targets, targetFilterQuery, rollout);
} }

View File

@@ -35,6 +35,7 @@ import org.eclipse.hawkbit.repository.DistributionSetTagManagement;
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement; import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
import org.eclipse.hawkbit.repository.RepositoryProperties; import org.eclipse.hawkbit.repository.RepositoryProperties;
import org.eclipse.hawkbit.repository.SoftwareModuleManagement; import org.eclipse.hawkbit.repository.SoftwareModuleManagement;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetTagCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetTagCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetUpdatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetUpdatedEvent;
@@ -994,10 +995,14 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
DistributionSet ds2 = testdataFactory.createDistributionSet("DS2"); DistributionSet ds2 = testdataFactory.createDistributionSet("DS2");
testdataFactory.createTargets("targets", 4); testdataFactory.createTargets("targets", 4);
targetFilterQueryManagement.create( targetFilterQueryManagement.create(
entityFactory.targetFilterQuery().create().name("test filter 1").autoAssignDistributionSet(ds.getId()).query("name==targets*")); TargetFilterQueryManagement.Create.builder()
.name("test filter 1").autoAssignDistributionSet(ds).query("name==targets*")
.build());
targetFilterQueryManagement.create( targetFilterQueryManagement.create(
entityFactory.targetFilterQuery().create().name("test filter 2").autoAssignDistributionSet(ds.getId()).query("name==targets*")); TargetFilterQueryManagement.Create.builder()
.name("test filter 2").autoAssignDistributionSet(ds).query("name==targets*")
.build());
assertThat(distributionSetManagement.countAutoAssignmentsForDistributionSet(ds.getId())).isEqualTo(2); assertThat(distributionSetManagement.countAutoAssignmentsForDistributionSet(ds.getId())).isEqualTo(2);
assertThat(distributionSetManagement.countAutoAssignmentsForDistributionSet(ds2.getId())).isNull(); assertThat(distributionSetManagement.countAutoAssignmentsForDistributionSet(ds2.getId())).isNull();

View File

@@ -12,7 +12,8 @@ package org.eclipse.hawkbit.repository.jpa.management;
import java.util.List; import java.util.List;
import org.eclipse.hawkbit.im.authentication.SpPermission; import org.eclipse.hawkbit.im.authentication.SpPermission;
import org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.AutoAssignDistributionSetUpdate;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.Create;
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -28,7 +29,7 @@ class TargetFilterQueryManagementSecurityTest extends AbstractJpaIntegrationTest
@Test @Test
void createPermissionsCheck() { void createPermissionsCheck() {
assertPermissions( assertPermissions(
() -> targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name("name").query("controllerId==id")), () -> targetFilterQueryManagement.create(Create.builder().name("name").query("controllerId==id").build()),
List.of(SpPermission.CREATE_TARGET)); List.of(SpPermission.CREATE_TARGET));
} }
@@ -76,22 +77,6 @@ class TargetFilterQueryManagementSecurityTest extends AbstractJpaIntegrationTest
assertPermissions(() -> targetFilterQueryManagement.countByAutoAssignDistributionSetId(1L), List.of(SpPermission.READ_TARGET)); assertPermissions(() -> targetFilterQueryManagement.countByAutoAssignDistributionSetId(1L), List.of(SpPermission.READ_TARGET));
} }
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void findByNamePermissionsCheck() {
assertPermissions(() -> targetFilterQueryManagement.findByName("filterName", PAGE), List.of(SpPermission.READ_TARGET));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void countByNamePermissionsCheck() {
assertPermissions(() -> targetFilterQueryManagement.countByName("filterName"), List.of(SpPermission.READ_TARGET));
}
/** /**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions. * Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/ */
@@ -100,23 +85,6 @@ class TargetFilterQueryManagementSecurityTest extends AbstractJpaIntegrationTest
assertPermissions(() -> targetFilterQueryManagement.findByRsql("name==id", PAGE), List.of(SpPermission.READ_TARGET)); assertPermissions(() -> targetFilterQueryManagement.findByRsql("name==id", PAGE), List.of(SpPermission.READ_TARGET));
} }
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void findByQueryPermissionsCheck() {
assertPermissions(() -> targetFilterQueryManagement.findByQuery("controllerId==id", PAGE), List.of(SpPermission.READ_TARGET));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void findByAutoAssignDistributionSetIdPermissionsCheck() {
assertPermissions(() -> targetFilterQueryManagement.findByAutoAssignDistributionSetId(1L, PAGE),
List.of(SpPermission.READ_TARGET, SpPermission.READ_REPOSITORY));
}
/** /**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions. * Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/ */
@@ -142,23 +110,6 @@ class TargetFilterQueryManagementSecurityTest extends AbstractJpaIntegrationTest
assertPermissions(() -> targetFilterQueryManagement.get(1L), List.of(SpPermission.READ_TARGET)); assertPermissions(() -> targetFilterQueryManagement.get(1L), List.of(SpPermission.READ_TARGET));
} }
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void getTargetFilterQueryByNamePermissionsCheck() {
assertPermissions(() -> targetFilterQueryManagement.getByName("filterName"), List.of(SpPermission.READ_TARGET));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void updatePermissionsCheck() {
assertPermissions(() -> targetFilterQueryManagement.update(entityFactory.targetFilterQuery().update(1L)),
List.of(SpPermission.UPDATE_TARGET));
}
/** /**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions. * Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/ */

View File

@@ -27,9 +27,9 @@ import org.assertj.core.api.Assertions;
import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.AutoAssignDistributionSetUpdate;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryCreate; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.Create;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryUpdate; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.Update;
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TargetCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.TargetCreatedEvent;
@@ -67,10 +67,9 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
* Verifies that management get access reacts as specfied on calls for non existing entities by means of Optional not present. * Verifies that management get access reacts as specfied on calls for non existing entities by means of Optional not present.
*/ */
@Test @Test
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) }) @ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
void nonExistingEntityAccessReturnsNotPresent() { void nonExistingEntityAccessReturnsNotPresent() {
assertThat(targetFilterQueryManagement.get(NOT_EXIST_IDL)).isNotPresent(); assertThat(targetFilterQueryManagement.get(NOT_EXIST_IDL)).isNotPresent();
assertThat(targetFilterQueryManagement.getByName(NOT_EXIST_ID)).isNotPresent();
} }
/** /**
@@ -84,7 +83,7 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
void entityQueriesReferringToNotExistingEntitiesThrowsException() { void entityQueriesReferringToNotExistingEntitiesThrowsException() {
final DistributionSet set = testdataFactory.createDistributionSet(); final DistributionSet set = testdataFactory.createDistributionSet();
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement.create( final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement.create(
entityFactory.targetFilterQuery().create().name("test filter").query("name==PendingTargets001")); Create.builder().name("test filter").query("name==PendingTargets001").build());
verifyThrownExceptionBy(() -> targetFilterQueryManagement.delete(NOT_EXIST_IDL), "TargetFilterQuery"); verifyThrownExceptionBy(() -> targetFilterQueryManagement.delete(NOT_EXIST_IDL), "TargetFilterQuery");
@@ -93,20 +92,20 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
"DistributionSet"); "DistributionSet");
verifyThrownExceptionBy( verifyThrownExceptionBy(
() -> targetFilterQueryManagement.update(entityFactory.targetFilterQuery().update(NOT_EXIST_IDL)), () -> targetFilterQueryManagement.update(Update.builder().id(NOT_EXIST_IDL).build()),
"TargetFilterQuery"); "TargetFilterQuery");
verifyThrownExceptionBy(() -> targetFilterQueryManagement.updateAutoAssignDS( verifyThrownExceptionBy(() -> targetFilterQueryManagement.updateAutoAssignDS(
entityFactory.targetFilterQuery().updateAutoAssign(targetFilterQuery.getId()).ds(NOT_EXIST_IDL)), new AutoAssignDistributionSetUpdate(targetFilterQuery.getId()).ds(NOT_EXIST_IDL)),
"DistributionSet"); "DistributionSet");
verifyThrownExceptionBy( verifyThrownExceptionBy(
() -> targetFilterQueryManagement.updateAutoAssignDS( () -> targetFilterQueryManagement.updateAutoAssignDS(
entityFactory.targetFilterQuery().updateAutoAssign(NOT_EXIST_IDL).ds(set.getId())), new AutoAssignDistributionSetUpdate(NOT_EXIST_IDL).ds(set.getId())),
"TargetFilterQuery"); "TargetFilterQuery");
verifyThrownExceptionBy(() -> targetFilterQueryManagement.updateAutoAssignDS( verifyThrownExceptionBy(() -> targetFilterQueryManagement.updateAutoAssignDS(
entityFactory.targetFilterQuery().updateAutoAssign(targetFilterQuery.getId()).ds(NOT_EXIST_IDL)), new AutoAssignDistributionSetUpdate(targetFilterQuery.getId()).ds(NOT_EXIST_IDL)),
"DistributionSet"); "DistributionSet");
} }
@@ -117,8 +116,8 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
void createTargetFilterQuery() { void createTargetFilterQuery() {
final String filterName = "new target filter"; final String filterName = "new target filter";
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name(filterName).query("name==PendingTargets001")); .create(Create.builder().name(filterName).query("name==PendingTargets001").build());
assertEquals(targetFilterQuery, targetFilterQueryManagement.getByName(filterName).get(), assertEquals(targetFilterQuery, targetFilterQueryManagement.get(targetFilterQuery.getId()).get(),
"Retrieved newly created custom target filter"); "Retrieved newly created custom target filter");
} }
@@ -134,8 +133,8 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
final DistributionSet set = testdataFactory.createDistributionSet(); final DistributionSet set = testdataFactory.createDistributionSet();
// creation is supposed to work as there is no distribution set // creation is supposed to work as there is no distribution set
final TargetFilterQueryCreate targetFilterQueryCreate = entityFactory.targetFilterQuery().create() final Create targetFilterQueryCreate = Create.builder()
.name("testfilter").autoAssignDistributionSet(set.getId()).query("name==target*"); .name("testfilter").autoAssignDistributionSet(set).query("name==target*").build();
assertThatExceptionOfType(AssignmentQuotaExceededException.class) assertThatExceptionOfType(AssignmentQuotaExceededException.class)
.isThrownBy(() -> targetFilterQueryManagement.create(targetFilterQueryCreate)); .isThrownBy(() -> targetFilterQueryManagement.create(targetFilterQueryCreate));
} }
@@ -147,12 +146,11 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
void searchTargetFilterQuery() { void searchTargetFilterQuery() {
final String filterName = "targetFilterQueryName"; final String filterName = "targetFilterQueryName";
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name(filterName).query("name==PendingTargets001")); .create(Create.builder().name(filterName).query("name==PendingTargets001").build());
targetFilterQueryManagement.create( targetFilterQueryManagement.create(Create.builder().name("someOtherFilter").query("name==PendingTargets002").build());
entityFactory.targetFilterQuery().create().name("someOtherFilter").query("name==PendingTargets002"));
final List<TargetFilterQuery> results = targetFilterQueryManagement final List<? extends TargetFilterQuery> results = targetFilterQueryManagement
.findByRsql("name==" + filterName, PageRequest.of(0, 10)).getContent(); .findByRsql("name==" + filterName, PageRequest.of(0, 10)).getContent();
assertEquals(1, results.size(), "Search result should have 1 result"); assertEquals(1, results.size(), "Search result should have 1 result");
assertEquals(targetFilterQuery, results.get(0), "Retrieved newly created custom target filter"); assertEquals(targetFilterQuery, results.get(0), "Retrieved newly created custom target filter");
@@ -174,8 +172,7 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
@Test @Test
void createDuplicateTargetFilterQuery() { void createDuplicateTargetFilterQuery() {
final String filterName = "new target filter duplicate"; final String filterName = "new target filter duplicate";
final TargetFilterQueryCreate targetFilterQueryCreate = entityFactory.targetFilterQuery().create() final Create targetFilterQueryCreate = Create.builder().name(filterName).query("name==PendingTargets001").build();
.name(filterName).query("name==PendingTargets001");
targetFilterQueryManagement.create(targetFilterQueryCreate); targetFilterQueryManagement.create(targetFilterQueryCreate);
@@ -190,8 +187,8 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
@Test @Test
void deleteTargetFilterQuery() { void deleteTargetFilterQuery() {
final String filterName = "delete_target_filter_query"; final String filterName = "delete_target_filter_query";
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement.create(entityFactory.targetFilterQuery() final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement.create(
.create().name(filterName).query("name==PendingTargets001")); Create.builder().name(filterName).query("name==PendingTargets001").build());
targetFilterQueryManagement.delete(targetFilterQuery.getId()); targetFilterQueryManagement.delete(targetFilterQuery.getId());
assertFalse( assertFalse(
targetFilterQueryManagement.get(targetFilterQuery.getId()).isPresent(), targetFilterQueryManagement.get(targetFilterQuery.getId()).isPresent(),
@@ -205,11 +202,11 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
void updateTargetFilterQuery() { void updateTargetFilterQuery() {
final String filterName = "target_filter_01"; final String filterName = "target_filter_01";
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name(filterName).query("name==PendingTargets001")); .create(Create.builder().name(filterName).query("name==PendingTargets001").build());
final String newQuery = "status==UNKNOWN"; final String newQuery = "name==PendingTargets002";
targetFilterQueryManagement.update(entityFactory.targetFilterQuery().update(targetFilterQuery.getId()).query(newQuery)); targetFilterQueryManagement.update(Update.builder().id(targetFilterQuery.getId()).query(newQuery).build());
assertEquals(newQuery, targetFilterQueryManagement.getByName(filterName).get().getQuery(), assertEquals(newQuery, targetFilterQueryManagement.get(targetFilterQuery.getId()).get().getQuery(),
"Returns updated target filter query"); "Returns updated target filter query");
} }
@@ -220,12 +217,12 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
void assignDistributionSet() { void assignDistributionSet() {
final String filterName = "target_filter_02"; final String filterName = "target_filter_02";
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name(filterName).query("name==PendingTargets001")); .create(Create.builder().name(filterName).query("name==PendingTargets001").build());
final DistributionSet distributionSet = testdataFactory.createDistributionSet(); final DistributionSet distributionSet = testdataFactory.createDistributionSet();
verifyAutoAssignmentWithDefaultActionType(filterName, targetFilterQuery, distributionSet); verifyAutoAssignmentWithDefaultActionType(targetFilterQuery, distributionSet);
verifyAutoAssignmentWithSoftActionType(filterName, targetFilterQuery, distributionSet); verifyAutoAssignmentWithSoftActionType(targetFilterQuery, distributionSet);
verifyAutoAssignmentWithDownloadOnlyActionType(filterName, targetFilterQuery, distributionSet); verifyAutoAssignmentWithDownloadOnlyActionType(targetFilterQuery, distributionSet);
verifyAutoAssignmentWithInvalidActionType(targetFilterQuery, distributionSet); verifyAutoAssignmentWithInvalidActionType(targetFilterQuery, distributionSet);
verifyAutoAssignmentWithIncompleteDs(targetFilterQuery); verifyAutoAssignmentWithIncompleteDs(targetFilterQuery);
verifyAutoAssignmentWithSoftDeletedDs(targetFilterQuery); verifyAutoAssignmentWithSoftDeletedDs(targetFilterQuery);
@@ -243,12 +240,12 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
// creation is supposed to work as there is no distribution set // creation is supposed to work as there is no distribution set
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name("testfilter").query("name==target*")); .create(Create.builder().name("testfilter").query("name==target*").build());
// assigning a distribution set is supposed to fail as the query // assigning a distribution set is supposed to fail as the query
// addresses too many targets // addresses too many targets
final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate = entityFactory.targetFilterQuery() final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate =
.updateAutoAssign(targetFilterQuery.getId()).ds(distributionSet.getId()); new AutoAssignDistributionSetUpdate(targetFilterQuery.getId()).ds(distributionSet.getId());
assertThatExceptionOfType(AssignmentQuotaExceededException.class) assertThatExceptionOfType(AssignmentQuotaExceededException.class)
.isThrownBy(() -> targetFilterQueryManagement.updateAutoAssignDS(autoAssignDistributionSetUpdate)); .isThrownBy(() -> targetFilterQueryManagement.updateAutoAssignDS(autoAssignDistributionSetUpdate));
} }
@@ -264,12 +261,11 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
final DistributionSet set = testdataFactory.createDistributionSet(); final DistributionSet set = testdataFactory.createDistributionSet();
// creation is supposed to work as the query does not exceed the quota // creation is supposed to work as the query does not exceed the quota
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement.create(entityFactory.targetFilterQuery() final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement.create(
.create().name("testfilter").autoAssignDistributionSet(set.getId()).query("name==foo")); Create.builder().name("testfilter").autoAssignDistributionSet(set).query("name==foo").build());
// update with a query string that addresses too many targets // update with a query string that addresses too many targets
final TargetFilterQueryUpdate targetFilterQueryUpdate = entityFactory.targetFilterQuery().update(targetFilterQuery.getId()) final Update targetFilterQueryUpdate = Update.builder().id(targetFilterQuery.getId()).query("name==target*").build();
.query("name==target*");
assertThatExceptionOfType(AssignmentQuotaExceededException.class) assertThatExceptionOfType(AssignmentQuotaExceededException.class)
.isThrownBy(() -> targetFilterQueryManagement.update(targetFilterQueryUpdate)); .isThrownBy(() -> targetFilterQueryManagement.update(targetFilterQueryUpdate));
} }
@@ -281,23 +277,23 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
void removeAssignDistributionSet() { void removeAssignDistributionSet() {
final String filterName = "target_filter_03"; final String filterName = "target_filter_03";
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name(filterName).query("name==PendingTargets001")); .create(Create.builder().name(filterName).query("name==PendingTargets001").build());
final DistributionSet distributionSet = testdataFactory.createDistributionSet(); final DistributionSet distributionSet = testdataFactory.createDistributionSet();
targetFilterQueryManagement.updateAutoAssignDS(entityFactory.targetFilterQuery() targetFilterQueryManagement.updateAutoAssignDS(
.updateAutoAssign(targetFilterQuery.getId()).ds(distributionSet.getId())); new AutoAssignDistributionSetUpdate(targetFilterQuery.getId()).ds(distributionSet.getId()));
implicitLock(distributionSet); implicitLock(distributionSet);
// Check if target filter query is there // Check if target filter query is there
TargetFilterQuery tfq = targetFilterQueryManagement.getByName(filterName).get(); TargetFilterQuery tfq = targetFilterQueryManagement.get(targetFilterQuery.getId()).get();
assertEquals(distributionSet, tfq.getAutoAssignDistributionSet(), "Returns correct distribution set"); assertEquals(distributionSet, tfq.getAutoAssignDistributionSet(), "Returns correct distribution set");
assertEquals(ActionType.FORCED, tfq.getAutoAssignActionType(), "Return correct action type"); assertEquals(ActionType.FORCED, tfq.getAutoAssignActionType(), "Return correct action type");
distributionSetManagement.delete(distributionSet.getId()); distributionSetManagement.delete(distributionSet.getId());
// Check if auto assign distribution set is null // Check if auto assign distribution set is null
tfq = targetFilterQueryManagement.getByName(filterName).get(); tfq = targetFilterQueryManagement.get(targetFilterQuery.getId()).get();
assertNotNull(tfq, "Returns target filter query"); assertNotNull(tfq, "Returns target filter query");
assertNull(tfq.getAutoAssignDistributionSet(), "Returns distribution set as null"); assertNull(tfq.getAutoAssignDistributionSet(), "Returns distribution set as null");
assertNull(tfq.getAutoAssignActionType(), "Returns action type as null"); assertNull(tfq.getAutoAssignActionType(), "Returns action type as null");
@@ -316,14 +312,14 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
assignDistributionSet(distributionSet.getId(), target.getControllerId()); assignDistributionSet(distributionSet.getId(), target.getControllerId());
final Long filterId = targetFilterQueryManagement final Long filterId = targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name(filterName).query("name==PendingTargets001")) .create(Create.builder().name(filterName).query("name==PendingTargets001").build())
.getId(); .getId();
targetFilterQueryManagement.updateAutoAssignDS( targetFilterQueryManagement.updateAutoAssignDS(
entityFactory.targetFilterQuery().updateAutoAssign(filterId).ds(distributionSet.getId())); new AutoAssignDistributionSetUpdate(filterId).ds(distributionSet.getId()));
implicitLock(distributionSet); implicitLock(distributionSet);
// Check if target filter query is there with the distribution set // Check if target filter query is there with the distribution set
TargetFilterQuery tfq = targetFilterQueryManagement.getByName(filterName).get(); TargetFilterQuery tfq = targetFilterQueryManagement.get(filterId).get();
assertEquals(distributionSet, tfq.getAutoAssignDistributionSet(), "Returns correct distribution set"); assertEquals(distributionSet, tfq.getAutoAssignDistributionSet(), "Returns correct distribution set");
assertEquals(ActionType.FORCED, tfq.getAutoAssignActionType(), "Return correct action type"); assertEquals(ActionType.FORCED, tfq.getAutoAssignActionType(), "Return correct action type");
@@ -333,7 +329,7 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
assertTrue(distributionSetManagement.get(distributionSet.getId()).get().isDeleted(), "Distribution set should be deleted"); assertTrue(distributionSetManagement.get(distributionSet.getId()).get().isDeleted(), "Distribution set should be deleted");
// Check if auto assign distribution set is null // Check if auto assign distribution set is null
tfq = targetFilterQueryManagement.getByName(filterName).get(); tfq = targetFilterQueryManagement.get(filterId).get();
assertNotNull(tfq, "Returns target filter query"); assertNotNull(tfq, "Returns target filter query");
assertNull(tfq.getAutoAssignDistributionSet(), "Returns distribution set as null"); assertNull(tfq.getAutoAssignDistributionSet(), "Returns distribution set as null");
assertNull(tfq.getAutoAssignActionType(), "Returns action type as null"); assertNull(tfq.getAutoAssignActionType(), "Returns action type as null");
@@ -346,24 +342,23 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
void findFiltersWithDistributionSet() { void findFiltersWithDistributionSet() {
final String filterName = "d"; final String filterName = "d";
assertEquals(0L, targetFilterQueryManagement.count()); assertEquals(0L, targetFilterQueryManagement.count());
targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name("a").query("name==*")); targetFilterQueryManagement.create(Create.builder().name("a").query("name==*").build());
targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name("b").query("name==*")); targetFilterQueryManagement.create(Create.builder().name("b").query("name==*").build());
final DistributionSet distributionSet = testdataFactory.createDistributionSet(); final DistributionSet distributionSet = testdataFactory.createDistributionSet();
final DistributionSet distributionSet2 = testdataFactory.createDistributionSet("2"); final DistributionSet distributionSet2 = testdataFactory.createDistributionSet("2");
final TargetFilterQuery tfq = targetFilterQueryManagement.create( final TargetFilterQuery tfq = targetFilterQueryManagement.create(
entityFactory.targetFilterQuery().create() Create.builder()
.name("c").query("name==x").autoAssignDistributionSet(distributionSet).autoAssignActionType(ActionType.SOFT)); .name("c").query("name==x").autoAssignDistributionSet(distributionSet).autoAssignActionType(ActionType.SOFT)
.build());
final TargetFilterQuery tfq2 = targetFilterQueryManagement.create( final TargetFilterQuery tfq2 = targetFilterQueryManagement.create(
entityFactory.targetFilterQuery().create() Create.builder().name(filterName).query("name==z*").autoAssignDistributionSet(distributionSet2).build());
.name(filterName).query("name==z*").autoAssignDistributionSet(distributionSet2));
assertEquals(4L, targetFilterQueryManagement.count()); assertEquals(4L, targetFilterQueryManagement.count());
// check if find works // check if find works
verifyFindByDistributionSetAndRsql(distributionSet, null, tfq); verifyFindByDistributionSetAndRsql(distributionSet, null, tfq);
targetFilterQueryManagement.updateAutoAssignDS( targetFilterQueryManagement.updateAutoAssignDS(new AutoAssignDistributionSetUpdate(tfq2.getId()).ds(distributionSet.getId()));
entityFactory.targetFilterQuery().updateAutoAssign(tfq2.getId()).ds(distributionSet.getId()));
// check if find works for two // check if find works for two
verifyFindByDistributionSetAndRsql(distributionSet, null, tfq, tfq2); verifyFindByDistributionSetAndRsql(distributionSet, null, tfq, tfq2);
@@ -379,15 +374,13 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
void weightNotRequiredInMultiAssignmentMode() { void weightNotRequiredInMultiAssignmentMode() {
enableMultiAssignments(); enableMultiAssignments();
final DistributionSet ds = testdataFactory.createDistributionSet(); final DistributionSet ds = testdataFactory.createDistributionSet();
final Long filterId = targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name("a").query("name==*")).getId(); final Long filterId = targetFilterQueryManagement.create(Create.builder().name("a").query("name==*").build()).getId();
assertThat( assertThat(
targetFilterQueryManagement.create( targetFilterQueryManagement.create(Create.builder().name("b").query("name==*").autoAssignDistributionSet(ds).build()))
entityFactory.targetFilterQuery().create().name("b").query("name==*").autoAssignDistributionSet(ds)))
.isNotNull(); .isNotNull();
assertThat( assertThat(
targetFilterQueryManagement targetFilterQueryManagement.updateAutoAssignDS(new AutoAssignDistributionSetUpdate(filterId).ds(ds.getId())))
.updateAutoAssignDS(entityFactory.targetFilterQuery().updateAutoAssign(filterId).ds(ds.getId())))
.isNotNull(); .isNotNull();
} }
@@ -397,16 +390,15 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
@Test @Test
void weightAllowedWhenMultiAssignmentModeNotEnabled() { void weightAllowedWhenMultiAssignmentModeNotEnabled() {
final DistributionSet ds = testdataFactory.createDistributionSet(); final DistributionSet ds = testdataFactory.createDistributionSet();
final Long filterId = targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name("a").query("name==*")).getId(); final Long filterId = targetFilterQueryManagement.create(Create.builder().name("a").query("name==*").build()).getId();
assertThat( assertThat(
targetFilterQueryManagement.create( targetFilterQueryManagement.create(
entityFactory.targetFilterQuery().create() Create.builder().name("b").query("name==*").autoAssignDistributionSet(ds).autoAssignWeight(342).build()))
.name("b").query("name==*").autoAssignDistributionSet(ds).autoAssignWeight(342)))
.isNotNull(); .isNotNull();
assertThat( assertThat(
targetFilterQueryManagement.updateAutoAssignDS( targetFilterQueryManagement.updateAutoAssignDS(
entityFactory.targetFilterQuery().updateAutoAssign(filterId).ds(ds.getId()).weight(343))) new AutoAssignDistributionSetUpdate(filterId).ds(ds.getId()).weight(343)))
.isNotNull(); .isNotNull();
} }
@@ -418,10 +410,9 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
enableMultiAssignments(); enableMultiAssignments();
final DistributionSet ds = testdataFactory.createDistributionSet(); final DistributionSet ds = testdataFactory.createDistributionSet();
final Long filterId = targetFilterQueryManagement.create( final Long filterId = targetFilterQueryManagement.create(
entityFactory.targetFilterQuery().create().name("a") Create.builder().name("a").query("name==*").autoAssignDistributionSet(ds).autoAssignWeight(23).build()).getId();
.query("name==*").autoAssignDistributionSet(ds).autoAssignWeight(23)).getId();
assertThat(targetFilterQueryManagement.updateAutoAssignDS( assertThat(targetFilterQueryManagement.updateAutoAssignDS(
entityFactory.targetFilterQuery().updateAutoAssign(filterId).ds(null).weight(null))) new AutoAssignDistributionSetUpdate(filterId).ds(null).weight(null)))
.isNotNull(); .isNotNull();
} }
@@ -433,27 +424,27 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
enableMultiAssignments(); enableMultiAssignments();
final DistributionSet ds = testdataFactory.createDistributionSet(); final DistributionSet ds = testdataFactory.createDistributionSet();
final TargetFilterQueryCreate targetFilterQueryCreate = entityFactory.targetFilterQuery().create().name("a") final Create targetFilterQueryCreate = Create.builder().name("a")
.query("name==*").autoAssignDistributionSet(ds).autoAssignWeight(Action.WEIGHT_MAX + 1); .query("name==*").autoAssignDistributionSet(ds).autoAssignWeight(Action.WEIGHT_MAX + 1).build();
Assertions.assertThatExceptionOfType(ConstraintViolationException.class).isThrownBy( Assertions.assertThatExceptionOfType(ConstraintViolationException.class).isThrownBy(
() -> targetFilterQueryManagement.create(targetFilterQueryCreate)); () -> targetFilterQueryManagement.create(targetFilterQueryCreate));
final Long filterId = targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name("a") final Long filterId = targetFilterQueryManagement.create(Create.builder().name("a")
.query("name==*").autoAssignDistributionSet(ds).autoAssignWeight(Action.WEIGHT_MAX)).getId(); .query("name==*").autoAssignDistributionSet(ds).autoAssignWeight(Action.WEIGHT_MAX).build()).getId();
assertThat(targetFilterQueryManagement.get(filterId).get().getAutoAssignWeight()).contains(Action.WEIGHT_MAX); assertThat(targetFilterQueryManagement.get(filterId).get().getAutoAssignWeight()).contains(Action.WEIGHT_MAX);
final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate = entityFactory.targetFilterQuery().updateAutoAssign(filterId) final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate = new AutoAssignDistributionSetUpdate(filterId)
.ds(ds.getId()).weight(Action.WEIGHT_MAX + 1); .ds(ds.getId()).weight(Action.WEIGHT_MAX + 1);
Assertions.assertThatExceptionOfType(ConstraintViolationException.class) Assertions.assertThatExceptionOfType(ConstraintViolationException.class)
.isThrownBy(() -> targetFilterQueryManagement.updateAutoAssignDS(autoAssignDistributionSetUpdate)); .isThrownBy(() -> targetFilterQueryManagement.updateAutoAssignDS(autoAssignDistributionSetUpdate));
final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate2 = entityFactory.targetFilterQuery() final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate2 =
.updateAutoAssign(filterId).ds(ds.getId()).weight(Action.WEIGHT_MIN - 1); new AutoAssignDistributionSetUpdate(filterId).ds(ds.getId()).weight(Action.WEIGHT_MIN - 1);
Assertions.assertThatExceptionOfType(ConstraintViolationException.class) Assertions.assertThatExceptionOfType(ConstraintViolationException.class)
.isThrownBy(() -> targetFilterQueryManagement.updateAutoAssignDS(autoAssignDistributionSetUpdate2)); .isThrownBy(() -> targetFilterQueryManagement.updateAutoAssignDS(autoAssignDistributionSetUpdate2));
targetFilterQueryManagement.updateAutoAssignDS( targetFilterQueryManagement.updateAutoAssignDS(
entityFactory.targetFilterQuery().updateAutoAssign(filterId).ds(ds.getId()).weight(Action.WEIGHT_MAX)); new AutoAssignDistributionSetUpdate(filterId).ds(ds.getId()).weight(Action.WEIGHT_MAX));
targetFilterQueryManagement.updateAutoAssignDS( targetFilterQueryManagement.updateAutoAssignDS(
entityFactory.targetFilterQuery().updateAutoAssign(filterId).ds(ds.getId()).weight(Action.WEIGHT_MIN)); new AutoAssignDistributionSetUpdate(filterId).ds(ds.getId()).weight(Action.WEIGHT_MIN));
assertThat(targetFilterQueryManagement.get(filterId).get().getAutoAssignWeight()).contains(Action.WEIGHT_MIN); assertThat(targetFilterQueryManagement.get(filterId).get().getAutoAssignWeight()).contains(Action.WEIGHT_MIN);
} }
@@ -464,8 +455,9 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
void createTargetFilterWithInvalidDistributionSet() { void createTargetFilterWithInvalidDistributionSet() {
final DistributionSet distributionSet = testdataFactory.createAndInvalidateDistributionSet(); final DistributionSet distributionSet = testdataFactory.createAndInvalidateDistributionSet();
final TargetFilterQueryCreate targetFilterQueryCreate = entityFactory.targetFilterQuery().create() final Create targetFilterQueryCreate = Create.builder()
.name("createTargetFilterWithInvalidDistributionSet").query("name==*").autoAssignDistributionSet(distributionSet); .name("createTargetFilterWithInvalidDistributionSet").query("name==*").autoAssignDistributionSet(distributionSet)
.build();
assertThatExceptionOfType(InvalidDistributionSetException.class) assertThatExceptionOfType(InvalidDistributionSetException.class)
.as("Invalid distributionSet should throw an exception") .as("Invalid distributionSet should throw an exception")
.isThrownBy(() -> targetFilterQueryManagement.create(targetFilterQueryCreate)); .isThrownBy(() -> targetFilterQueryManagement.create(targetFilterQueryCreate));
@@ -478,9 +470,10 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
void createTargetFilterWithIncompleteDistributionSet() { void createTargetFilterWithIncompleteDistributionSet() {
final DistributionSet distributionSet = testdataFactory.createIncompleteDistributionSet(); final DistributionSet distributionSet = testdataFactory.createIncompleteDistributionSet();
final TargetFilterQueryCreate targetFilterQueryCreate = entityFactory.targetFilterQuery().create() final Create targetFilterQueryCreate = Create.builder()
.name("createTargetFilterWithIncompleteDistributionSet").query("name==*") .name("createTargetFilterWithIncompleteDistributionSet").query("name==*")
.autoAssignDistributionSet(distributionSet); .autoAssignDistributionSet(distributionSet)
.build();
assertThatExceptionOfType(IncompleteDistributionSetException.class) assertThatExceptionOfType(IncompleteDistributionSetException.class)
.as("Incomplete distributionSet should throw an exception") .as("Incomplete distributionSet should throw an exception")
.isThrownBy(() -> targetFilterQueryManagement.create(targetFilterQueryCreate)); .isThrownBy(() -> targetFilterQueryManagement.create(targetFilterQueryCreate));
@@ -492,9 +485,8 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
@Test @Test
void updateAutoAssignDsWithInvalidDistributionSet() { void updateAutoAssignDsWithInvalidDistributionSet() {
final DistributionSet distributionSet = testdataFactory.createDistributionSet(); final DistributionSet distributionSet = testdataFactory.createDistributionSet();
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement.create(Create.builder()
.create(entityFactory.targetFilterQuery().create().name("updateAutoAssignDsWithInvalidDistributionSet") .name("updateAutoAssignDsWithInvalidDistributionSet").query("name==*").autoAssignDistributionSet(distributionSet).build());
.query("name==*").autoAssignDistributionSet(distributionSet));
final DistributionSet invalidDistributionSet = testdataFactory.createAndInvalidateDistributionSet(); final DistributionSet invalidDistributionSet = testdataFactory.createAndInvalidateDistributionSet();
final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate = new AutoAssignDistributionSetUpdate(targetFilterQuery.getId()) final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate = new AutoAssignDistributionSetUpdate(targetFilterQuery.getId())
@@ -511,8 +503,8 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
void updateAutoAssignDsWithIncompleteDistributionSet() { void updateAutoAssignDsWithIncompleteDistributionSet() {
final DistributionSet distributionSet = testdataFactory.createDistributionSet(); final DistributionSet distributionSet = testdataFactory.createDistributionSet();
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement.create( final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement.create(
entityFactory.targetFilterQuery().create().name("updateAutoAssignDsWithIncompleteDistributionSet") Create.builder().name("updateAutoAssignDsWithIncompleteDistributionSet")
.query("name==*").autoAssignDistributionSet(distributionSet)); .query("name==*").autoAssignDistributionSet(distributionSet).build());
final DistributionSet incompleteDistributionSet = testdataFactory.createIncompleteDistributionSet(); final DistributionSet incompleteDistributionSet = testdataFactory.createIncompleteDistributionSet();
final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate = new AutoAssignDistributionSetUpdate(targetFilterQuery.getId()) final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate = new AutoAssignDistributionSetUpdate(targetFilterQuery.getId())
@@ -530,11 +522,11 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
for (final ActionType actionType : ActionType.values()) { for (final ActionType actionType : ActionType.values()) {
final Supplier<Long> create = () -> final Supplier<Long> create = () ->
targetFilterQueryManagement.create( targetFilterQueryManagement.create(
entityFactory.targetFilterQuery() Create.builder()
.create()
.name("testAutoAssignActionTypeConvert_" + actionType) .name("testAutoAssignActionTypeConvert_" + actionType)
.query("name==*") .query("name==*")
.autoAssignActionType(actionType)) .autoAssignActionType(actionType)
.build())
.getId(); .getId();
if (actionType == ActionType.TIMEFORCED) { if (actionType == ActionType.TIMEFORCED) {
assertThatExceptionOfType(AbstractServerRtException.class).isThrownBy(create::get); assertThatExceptionOfType(AbstractServerRtException.class).isThrownBy(create::get);
@@ -544,45 +536,36 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
} }
final JpaTargetFilterQuery jpaTargetFilterQuery = (JpaTargetFilterQuery) targetFilterQueryManagement.create( final JpaTargetFilterQuery jpaTargetFilterQuery = (JpaTargetFilterQuery) targetFilterQueryManagement.create(
entityFactory.targetFilterQuery() Create.builder().name("testAutoAssignActionTypeConvert").query("name==*").build());
.create()
.name("testAutoAssignActionTypeConvert")
.query("name==*"));
assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() ->
jpaTargetFilterQuery.setAutoAssignActionType(ActionType.TIMEFORCED)); jpaTargetFilterQuery.setAutoAssignActionType(ActionType.TIMEFORCED));
} }
private void verifyAutoAssignmentWithDefaultActionType(final String filterName, private void verifyAutoAssignmentWithDefaultActionType(final TargetFilterQuery targetFilterQuery, final DistributionSet distributionSet) {
final TargetFilterQuery targetFilterQuery, final DistributionSet distributionSet) { targetFilterQueryManagement.updateAutoAssignDS(
targetFilterQueryManagement.updateAutoAssignDS(entityFactory.targetFilterQuery() new AutoAssignDistributionSetUpdate(targetFilterQuery.getId()).ds(distributionSet.getId()));
.updateAutoAssign(targetFilterQuery.getId()).ds(distributionSet.getId()));
implicitLock(distributionSet); implicitLock(distributionSet);
verifyAutoAssignDsAndActionType(filterName, distributionSet, ActionType.FORCED); verifyAutoAssignDsAndActionType(targetFilterQuery.getId(), distributionSet, ActionType.FORCED);
} }
private void verifyAutoAssignmentWithSoftActionType(final String filterName, private void verifyAutoAssignmentWithSoftActionType(final TargetFilterQuery targetFilterQuery, final DistributionSet distributionSet) {
final TargetFilterQuery targetFilterQuery, final DistributionSet distributionSet) { targetFilterQueryManagement.updateAutoAssignDS(
targetFilterQueryManagement.updateAutoAssignDS(entityFactory.targetFilterQuery() new AutoAssignDistributionSetUpdate(targetFilterQuery.getId()).ds(distributionSet.getId()).actionType(ActionType.SOFT));
.updateAutoAssign(targetFilterQuery.getId()).ds(distributionSet.getId()).actionType(ActionType.SOFT)); verifyAutoAssignDsAndActionType(targetFilterQuery.getId(), distributionSet, ActionType.SOFT);
verifyAutoAssignDsAndActionType(filterName, distributionSet, ActionType.SOFT);
} }
private void verifyAutoAssignmentWithDownloadOnlyActionType(final String filterName, private void verifyAutoAssignmentWithDownloadOnlyActionType(final TargetFilterQuery targetFilterQuery, final DistributionSet distributionSet) {
final TargetFilterQuery targetFilterQuery, final DistributionSet distributionSet) {
targetFilterQueryManagement targetFilterQueryManagement
.updateAutoAssignDS(entityFactory.targetFilterQuery().updateAutoAssign(targetFilterQuery.getId()) .updateAutoAssignDS(new AutoAssignDistributionSetUpdate(targetFilterQuery.getId())
.ds(distributionSet.getId()).actionType(ActionType.DOWNLOAD_ONLY)); .ds(distributionSet.getId()).actionType(ActionType.DOWNLOAD_ONLY));
verifyAutoAssignDsAndActionType(filterName, distributionSet, ActionType.DOWNLOAD_ONLY); verifyAutoAssignDsAndActionType(targetFilterQuery.getId(), distributionSet, ActionType.DOWNLOAD_ONLY);
} }
private void verifyAutoAssignmentWithInvalidActionType(final TargetFilterQuery targetFilterQuery, private void verifyAutoAssignmentWithInvalidActionType(final TargetFilterQuery targetFilterQuery,
final DistributionSet distributionSet) { final DistributionSet distributionSet) {
// assigning a distribution set with TIMEFORCED action is supposed to // assigning a distribution set with TIMEFORCED action is supposed to fail as only FORCED and SOFT action types are allowed
// fail as only FORCED and SOFT action types are allowed final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate =
final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate = entityFactory.targetFilterQuery() new AutoAssignDistributionSetUpdate(targetFilterQuery.getId()).ds(distributionSet.getId()).actionType(ActionType.TIMEFORCED);
.updateAutoAssign(targetFilterQuery.getId())
.ds(distributionSet.getId())
.actionType(ActionType.TIMEFORCED);
assertThatExceptionOfType(InvalidAutoAssignActionTypeException.class) assertThatExceptionOfType(InvalidAutoAssignActionTypeException.class)
.isThrownBy(() -> targetFilterQueryManagement.updateAutoAssignDS(autoAssignDistributionSetUpdate)); .isThrownBy(() -> targetFilterQueryManagement.updateAutoAssignDS(autoAssignDistributionSetUpdate));
} }
@@ -594,8 +577,8 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
.name("incomplete").version("1") .name("incomplete").version("1")
.build()); .build());
final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate = entityFactory.targetFilterQuery() final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate =
.updateAutoAssign(targetFilterQuery.getId()).ds(incompleteDistributionSet.getId()); new AutoAssignDistributionSetUpdate(targetFilterQuery.getId()).ds(incompleteDistributionSet.getId());
assertThatExceptionOfType(IncompleteDistributionSetException.class) assertThatExceptionOfType(IncompleteDistributionSetException.class)
.isThrownBy(() -> targetFilterQueryManagement.updateAutoAssignDS(autoAssignDistributionSetUpdate)); .isThrownBy(() -> targetFilterQueryManagement.updateAutoAssignDS(autoAssignDistributionSetUpdate));
} }
@@ -605,14 +588,14 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
assignDistributionSet(softDeletedDs, testdataFactory.createTarget("forSoftDeletedDs")); assignDistributionSet(softDeletedDs, testdataFactory.createTarget("forSoftDeletedDs"));
distributionSetManagement.delete(softDeletedDs.getId()); distributionSetManagement.delete(softDeletedDs.getId());
final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate = entityFactory.targetFilterQuery() final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate =
.updateAutoAssign(targetFilterQuery.getId()).ds(softDeletedDs.getId()); new AutoAssignDistributionSetUpdate(targetFilterQuery.getId()).ds(softDeletedDs.getId());
assertThatExceptionOfType(DeletedException.class) assertThatExceptionOfType(DeletedException.class)
.isThrownBy(() -> targetFilterQueryManagement.updateAutoAssignDS(autoAssignDistributionSetUpdate)); .isThrownBy(() -> targetFilterQueryManagement.updateAutoAssignDS(autoAssignDistributionSetUpdate));
} }
private void verifyFindByDistributionSetAndRsql(final DistributionSet distributionSet, final String rsql, private void verifyFindByDistributionSetAndRsql(
final TargetFilterQuery... expectedFilterQueries) { final DistributionSet distributionSet, final String rsql, final TargetFilterQuery... expectedFilterQueries) {
final Page<TargetFilterQuery> tfqList = targetFilterQueryManagement final Page<TargetFilterQuery> tfqList = targetFilterQueryManagement
.findByAutoAssignDSAndRsql(distributionSet.getId(), rsql, PageRequest.of(0, 500)); .findByAutoAssignDSAndRsql(distributionSet.getId(), rsql, PageRequest.of(0, 500));
@@ -642,9 +625,8 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
Arrays.stream(expectedFilterQueries).map(TargetFilterQuery::getId).toArray(Long[]::new)); Arrays.stream(expectedFilterQueries).map(TargetFilterQuery::getId).toArray(Long[]::new));
} }
private void verifyAutoAssignDsAndActionType(final String filterName, final DistributionSet distributionSet, private void verifyAutoAssignDsAndActionType(final Long filterId, final DistributionSet distributionSet, final ActionType actionType) {
final ActionType actionType) { final TargetFilterQuery tfq = targetFilterQueryManagement.get(filterId).get();
final TargetFilterQuery tfq = targetFilterQueryManagement.getByName(filterName).get();
assertEquals(distributionSet, tfq.getAutoAssignDistributionSet(), "Returns correct distribution set"); assertEquals(distributionSet, tfq.getAutoAssignDistributionSet(), "Returns correct distribution set");
assertEquals(actionType, tfq.getAutoAssignActionType(), "Return correct action type"); assertEquals(actionType, tfq.getAutoAssignActionType(), "Return correct action type");

View File

@@ -19,6 +19,7 @@ import java.util.Set;
import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.FilterParams; import org.eclipse.hawkbit.repository.FilterParams;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.TargetTagManagement; import org.eclipse.hawkbit.repository.TargetTagManagement;
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.Action.Status;
@@ -215,7 +216,7 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
void findTargetWithoutAssignedDistributionSet() { void findTargetWithoutAssignedDistributionSet() {
final DistributionSet assignedSet = testdataFactory.createDistributionSet(""); final DistributionSet assignedSet = testdataFactory.createDistributionSet("");
final TargetFilterQuery tfq = targetFilterQueryManagement final TargetFilterQuery tfq = targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name("tfq").query("name==*")); .create(TargetFilterQueryManagement.Create.builder().name("tfq").query("name==*").build());
final List<Target> unassignedTargets = testdataFactory.createTargets(12, "unassigned", "unassigned"); final List<Target> unassignedTargets = testdataFactory.createTargets(12, "unassigned", "unassigned");
final List<Target> assignedTargets = testdataFactory.createTargets(10, "assigned", "assigned"); final List<Target> assignedTargets = testdataFactory.createTargets(10, "assigned", "assigned");
@@ -260,7 +261,7 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
final DistributionSet testDs = testdataFactory.createDistributionSet(); final DistributionSet testDs = testdataFactory.createDistributionSet();
final TargetType targetType = testdataFactory.createTargetType("testType", Set.of(testDs.getType())); final TargetType targetType = testdataFactory.createTargetType("testType", Set.of(testDs.getType()));
final TargetFilterQuery tfq = targetFilterQueryManagement final TargetFilterQuery tfq = targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name("test-filter").query("name==*")); .create(TargetFilterQueryManagement.Create.builder().name("test-filter").query("name==*").build());
final List<Target> targets = testdataFactory.createTargets(20, "withOutType"); final List<Target> targets = testdataFactory.createTargets(20, "withOutType");
final List<Target> targetWithCompatibleTypes = testdataFactory.createTargetsWithType(20, "compatible", final List<Target> targetWithCompatibleTypes = testdataFactory.createTargetsWithType(20, "compatible",
targetType); targetType);
@@ -284,7 +285,7 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
final TargetType incompatibleTargetType = testdataFactory.createTargetType( final TargetType incompatibleTargetType = testdataFactory.createTargetType(
"incompTestType", Set.of(testdataFactory.createDistributionSet().getType())); "incompTestType", Set.of(testdataFactory.createDistributionSet().getType()));
final TargetFilterQuery tfq = targetFilterQueryManagement final TargetFilterQuery tfq = targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name("test-filter").query("name==*")); .create(TargetFilterQueryManagement.Create.builder().name("test-filter").query("name==*").build());
final List<Target> targetsWithOutType = testdataFactory.createTargets(20, "withOutType"); final List<Target> targetsWithOutType = testdataFactory.createTargets(20, "withOutType");
final List<Target> targetsWithCompatibleType = testdataFactory.createTargetsWithType(20, "compatible", final List<Target> targetsWithCompatibleType = testdataFactory.createTargetsWithType(20, "compatible",

View File

@@ -13,6 +13,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import org.eclipse.hawkbit.repository.TargetFilterQueryFields; import org.eclipse.hawkbit.repository.TargetFilterQueryFields;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
@@ -41,12 +42,11 @@ class RsqlTargetFilterQueryFieldsTest extends AbstractJpaIntegrationTest {
final DistributionSet ds1 = testdataFactory.createDistributionSet("AutoAssignedDs_1"); final DistributionSet ds1 = testdataFactory.createDistributionSet("AutoAssignedDs_1");
final DistributionSet ds2 = testdataFactory.createDistributionSet("AutoAssignedDs_2"); final DistributionSet ds2 = testdataFactory.createDistributionSet("AutoAssignedDs_2");
filter1 = targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name(filterName1) filter1 = targetFilterQueryManagement.create(TargetFilterQueryManagement.Create.builder().name(filterName1)
.query("name==*").autoAssignDistributionSet(ds1).autoAssignActionType(ActionType.SOFT)); .query("name==*").autoAssignDistributionSet(ds1).autoAssignActionType(ActionType.SOFT).build());
filter2 = targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name(filterName2) filter2 = targetFilterQueryManagement.create(TargetFilterQueryManagement.Create.builder().name(filterName2)
.query("name==*").autoAssignDistributionSet(ds2)); .query("name==*").autoAssignDistributionSet(ds2).build());
targetFilterQueryManagement targetFilterQueryManagement.create(TargetFilterQueryManagement.Create.builder().name(filterName3).query("name==*").build());
.create(entityFactory.targetFilterQuery().create().name(filterName3).query("name==*"));
assertEquals(3L, targetFilterQueryManagement.count()); assertEquals(3L, targetFilterQueryManagement.count());
} }
@@ -68,7 +68,6 @@ class RsqlTargetFilterQueryFieldsTest extends AbstractJpaIntegrationTest {
assertRSQLQuery(TargetFilterQueryFields.ID.name() + "=in=(" + filter1.getId() + ",10000000)", 1); assertRSQLQuery(TargetFilterQueryFields.ID.name() + "=in=(" + filter1.getId() + ",10000000)", 1);
assertRSQLQuery(TargetFilterQueryFields.ID.name() + "=out=(" + filter1.getId() + ",10000000)", 2); assertRSQLQuery(TargetFilterQueryFields.ID.name() + "=out=(" + filter1.getId() + ",10000000)", 2);
} }
/** /**
@@ -117,7 +116,7 @@ class RsqlTargetFilterQueryFieldsTest extends AbstractJpaIntegrationTest {
} }
private void assertRSQLQuery(final String rsql, final long expectedFilterQueriesSize) { private void assertRSQLQuery(final String rsql, final long expectedFilterQueriesSize) {
final Page<TargetFilterQuery> findTargetFilterQueryPage = targetFilterQueryManagement.findByRsql(rsql, PAGE); final Page<? extends TargetFilterQuery> findTargetFilterQueryPage = targetFilterQueryManagement.findByRsql(rsql, PAGE);
assertThat(findTargetFilterQueryPage).isNotNull(); assertThat(findTargetFilterQueryPage).isNotNull();
assertThat(findTargetFilterQueryPage.getTotalElements()).isEqualTo(expectedFilterQueriesSize); assertThat(findTargetFilterQueryPage.getTotalElements()).isEqualTo(expectedFilterQueriesSize);
} }

View File

@@ -66,6 +66,7 @@ import org.eclipse.hawkbit.repository.model.RepositoryModelConstants;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.repository.model.Target; 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.TargetTag;
import org.eclipse.hawkbit.repository.model.TargetType; import org.eclipse.hawkbit.repository.model.TargetType;
import org.eclipse.hawkbit.repository.test.TestConfiguration; import org.eclipse.hawkbit.repository.test.TestConfiguration;
@@ -144,7 +145,7 @@ public abstract class AbstractIntegrationTest {
@Autowired @Autowired
protected TargetTypeManagement<? extends TargetType> targetTypeManagement; protected TargetTypeManagement<? extends TargetType> targetTypeManagement;
@Autowired @Autowired
protected TargetFilterQueryManagement targetFilterQueryManagement; protected TargetFilterQueryManagement<? extends TargetFilterQuery> targetFilterQueryManagement;
@Autowired @Autowired
protected TargetTagManagement<? extends TargetTag> targetTagManagement; protected TargetTagManagement<? extends TargetTag> targetTagManagement;
@Autowired @Autowired
@@ -316,34 +317,33 @@ public abstract class AbstractIntegrationTest {
return assignDistributionSet(dsID, controllerId, ActionType.FORCED); return assignDistributionSet(dsID, controllerId, ActionType.FORCED);
} }
protected DistributionSetAssignmentResult assignDistributionSet(final long dsID, final String controllerId, protected DistributionSetAssignmentResult assignDistributionSet(
final ActionType actionType) { final long dsID, final String controllerId, final ActionType actionType) {
return assignDistributionSet(dsID, Collections.singletonList(controllerId), actionType); return assignDistributionSet(dsID, Collections.singletonList(controllerId), actionType);
} }
protected DistributionSetAssignmentResult assignDistributionSet(final long dsID, final String controllerId, protected DistributionSetAssignmentResult assignDistributionSet(
final ActionType actionType, final long forcedTime) { final long dsId, final String controllerId, final ActionType actionType, final long forcedTime) {
return assignDistributionSet(dsID, Collections.singletonList(controllerId), actionType, forcedTime); return assignDistributionSet(dsId, Collections.singletonList(controllerId), actionType, forcedTime);
} }
protected DistributionSetAssignmentResult assignDistributionSet(final long dsID, final List<String> controllerIds, protected DistributionSetAssignmentResult assignDistributionSet(
final ActionType actionType) { final long dsId, final List<String> controllerIds, final ActionType actionType) {
return assignDistributionSet(dsID, controllerIds, actionType, RepositoryModelConstants.NO_FORCE_TIME); return assignDistributionSet(dsId, controllerIds, actionType, RepositoryModelConstants.NO_FORCE_TIME);
} }
protected DistributionSetAssignmentResult assignDistributionSet(final long dsID, final List<String> controllerIds, protected DistributionSetAssignmentResult assignDistributionSet(
final ActionType actionType, final long forcedTime) { final long dsID, final List<String> controllerIds, final ActionType actionType, final long forcedTime) {
return assignDistributionSet(dsID, controllerIds, actionType, forcedTime, null); return assignDistributionSet(dsID, controllerIds, actionType, forcedTime, null);
} }
protected DistributionSetAssignmentResult assignDistributionSet( protected DistributionSetAssignmentResult assignDistributionSet(
final long dsID, final List<String> controllerIds, final long dsId, final List<String> controllerIds, final ActionType actionType, final long forcedTime, final Integer weight) {
final ActionType actionType, final long forcedTime, final Integer weight) {
final boolean confirmationFlowActive = isConfirmationFlowActive(); final boolean confirmationFlowActive = isConfirmationFlowActive();
final List<DeploymentRequest> deploymentRequests = controllerIds.stream() final List<DeploymentRequest> deploymentRequests = controllerIds.stream()
.map(id -> DeploymentManagement.deploymentRequest(id, dsID).setActionType(actionType) .map(id -> DeploymentManagement.deploymentRequest(id, dsId)
.setForceTime(forcedTime).setWeight(weight).setConfirmationRequired(confirmationFlowActive) .setActionType(actionType).setForceTime(forcedTime).setWeight(weight).setConfirmationRequired(confirmationFlowActive)
.build()) .build())
.toList(); .toList();
final List<DistributionSetAssignmentResult> results = deploymentManagement.assignDistributionSets(deploymentRequests); final List<DistributionSetAssignmentResult> results = deploymentManagement.assignDistributionSets(deploymentRequests);
@@ -358,19 +358,15 @@ public abstract class AbstractIntegrationTest {
} }
protected DistributionSetAssignmentResult assignDistributionSet(final DistributionSet ds, final List<Target> targets) { protected DistributionSetAssignmentResult assignDistributionSet(final DistributionSet ds, final List<Target> targets) {
final List<String> targetIds = targets.stream().map(Target::getControllerId).toList(); return assignDistributionSet(ds.getId(), targets.stream().map(Target::getControllerId).toList(), ActionType.FORCED);
return assignDistributionSet(ds.getId(), targetIds, ActionType.FORCED);
} }
protected DistributionSetAssignmentResult assignDistributionSet(final Long dsId, final List<String> targetIds, protected DistributionSetAssignmentResult assignDistributionSet(final Long dsId, final List<String> targetIds, final int weight) {
final int weight) { return assignDistributionSet(dsId, targetIds, ActionType.FORCED, RepositoryModelConstants.NO_FORCE_TIME, weight);
return assignDistributionSet(dsId, targetIds, ActionType.FORCED, RepositoryModelConstants.NO_FORCE_TIME,
weight);
} }
protected DistributionSetAssignmentResult makeAssignment(final DeploymentRequest request) { protected DistributionSetAssignmentResult makeAssignment(final DeploymentRequest request) {
final List<DistributionSetAssignmentResult> results = deploymentManagement final List<DistributionSetAssignmentResult> results = deploymentManagement.assignDistributionSets(Collections.singletonList(request));
.assignDistributionSets(Collections.singletonList(request));
assertThat(results).hasSize(1); assertThat(results).hasSize(1);
return results.get(0); return results.get(0);
} }

View File

@@ -45,6 +45,7 @@ import org.eclipse.hawkbit.repository.RolloutManagement;
import org.eclipse.hawkbit.repository.SoftwareModuleManagement; import org.eclipse.hawkbit.repository.SoftwareModuleManagement;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement; import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.AutoAssignDistributionSetUpdate;
import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.TargetManagement;
import org.eclipse.hawkbit.repository.TargetTagManagement; import org.eclipse.hawkbit.repository.TargetTagManagement;
import org.eclipse.hawkbit.repository.TargetTypeManagement; import org.eclipse.hawkbit.repository.TargetTypeManagement;
@@ -154,7 +155,7 @@ public class TestdataFactory {
private final DistributionSetTypeManagement<?> distributionSetTypeManagement; private final DistributionSetTypeManagement<?> distributionSetTypeManagement;
private final DistributionSetInvalidationManagement distributionSetInvalidationManagement; private final DistributionSetInvalidationManagement distributionSetInvalidationManagement;
private final TargetManagement targetManagement; private final TargetManagement targetManagement;
private final TargetFilterQueryManagement targetFilterQueryManagement; private final TargetFilterQueryManagement<? extends TargetFilterQuery> targetFilterQueryManagement;
private final TargetTypeManagement<? extends TargetType> targetTypeManagement; private final TargetTypeManagement<? extends TargetType> targetTypeManagement;
private final TargetTagManagement<? extends TargetTag> targetTagManagement; private final TargetTagManagement<? extends TargetTag> targetTagManagement;
private final DeploymentManagement deploymentManagement; private final DeploymentManagement deploymentManagement;
@@ -966,9 +967,9 @@ public class TestdataFactory {
public TargetFilterQuery createTargetFilterWithTargetsAndActiveAutoAssignment() { public TargetFilterQuery createTargetFilterWithTargetsAndActiveAutoAssignment() {
createTargets(quotaManagement.getMaxTargetsPerAutoAssignment()); createTargets(quotaManagement.getMaxTargetsPerAutoAssignment());
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name("testName").query("id==*")); .create(TargetFilterQueryManagement.Create.builder().name("testName").query("id==*").build());
return targetFilterQueryManagement.updateAutoAssignDS(entityFactory.targetFilterQuery() return targetFilterQueryManagement.updateAutoAssignDS(
.updateAutoAssign(targetFilterQuery.getId()).ds(createDistributionSet().getId())); new AutoAssignDistributionSetUpdate(targetFilterQuery.getId()).ds(createDistributionSet().getId()));
} }
/** /**
@@ -1230,7 +1231,7 @@ public class TestdataFactory {
final DistributionSet distributionSet = createDistributionSet(); final DistributionSet distributionSet = createDistributionSet();
distributionSetInvalidationManagement.invalidateDistributionSet( distributionSetInvalidationManagement.invalidateDistributionSet(
new DistributionSetInvalidation(List.of(distributionSet.getId()), CancelationType.NONE, false)); new DistributionSetInvalidation(List.of(distributionSet.getId()), CancelationType.NONE, false));
return distributionSet; return distributionSetManagement.get(distributionSet.getId()).orElseThrow();
} }
/** /**