diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/utils/ObjectCopyUtil.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/utils/ObjectCopyUtil.java index 7a0a690da..d265045b1 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/utils/ObjectCopyUtil.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/utils/ObjectCopyUtil.java @@ -175,26 +175,17 @@ public class ObjectCopyUtil { } @NotNull - private static Method getMethod(final Class clazz, final String methodName, final Class parameterType) - throws NoSuchMethodException { + private static Method getMethod(final Class clazz, final String methodName, final Class parameterType) throws NoSuchMethodException { try { return getMethod(clazz, clazz, methodName, parameterType); } catch (final NoSuchMethodException e) { - if (parameterType == Boolean.class) { - try { - return getMethod(clazz, methodName, boolean.class); - } catch (final NoSuchMethodException e2) { - 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; - } + 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; } @@ -218,11 +209,26 @@ public class ObjectCopyUtil { } } - @SuppressWarnings("java:S3011") // low-level, reflection utility. intentionally changes the accessibility + // java:S3011 - low-level, reflection utility. intentionally changes the accessibility + // java:S3776 - complexity is due to reflection and dynamic method invocation + @SuppressWarnings({"java:S3011", "java:S3776"}) 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)) + .filter(method -> { + if (method.getParameterCount() == 1) { + if (method.getParameterTypes()[0].isAssignableFrom(parameterType)) { + return true; + } + if ((parameterType == boolean.class && method.getParameterTypes()[0] == Boolean.class) || + (parameterType == Boolean.class && method.getParameterTypes()[0] == boolean.class) || + (parameterType == long.class && method.getParameterTypes()[0] == Long.class) || + (parameterType == Long.class && method.getParameterTypes()[0] == long.class)) { + return true; // in/out boxing + } + } + return false; + }) .findFirst() .map(method -> { method.setAccessible(true); diff --git a/hawkbit-ddi/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java b/hawkbit-ddi/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java index 50f4fdfe9..f1af927e7 100644 --- a/hawkbit-ddi/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java +++ b/hawkbit-ddi/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java @@ -21,8 +21,6 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; -import org.eclipse.hawkbit.repository.artifact.model.DbArtifact; -import org.eclipse.hawkbit.repository.artifact.urlhandler.ArtifactUrlHandler; import org.eclipse.hawkbit.audit.AuditLog; import org.eclipse.hawkbit.ddi.json.model.DdiActionFeedback; import org.eclipse.hawkbit.ddi.json.model.DdiActionHistory; @@ -49,11 +47,11 @@ import org.eclipse.hawkbit.ddi.rest.api.DdiRootControllerRestApi; import org.eclipse.hawkbit.repository.ArtifactManagement; import org.eclipse.hawkbit.repository.ConfirmationManagement; import org.eclipse.hawkbit.repository.ControllerManagement; -import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.RepositoryConstants; import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.UpdateMode; -import org.eclipse.hawkbit.repository.builder.ActionStatusCreate; +import org.eclipse.hawkbit.repository.artifact.model.DbArtifact; +import org.eclipse.hawkbit.repository.artifact.urlhandler.ArtifactUrlHandler; import org.eclipse.hawkbit.repository.event.remote.DownloadProgressEvent; import org.eclipse.hawkbit.repository.exception.ArtifactBinaryNotFoundException; import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException; @@ -61,6 +59,8 @@ import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.InvalidConfirmationFeedbackException; import org.eclipse.hawkbit.repository.exception.SoftwareModuleNotAssignedToTargetException; import org.eclipse.hawkbit.repository.model.Action; +import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate; +import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate.ActionStatusCreateBuilder; import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.ActionStatus; import org.eclipse.hawkbit.repository.model.Artifact; @@ -105,7 +105,6 @@ public class DdiRootController implements DdiRootControllerRestApi { private final ApplicationEventPublisher eventPublisher; private final HawkbitSecurityProperties securityProperties; private final TenantAware tenantAware; - private final EntityFactory entityFactory; @SuppressWarnings("java:S107") public DdiRootController( @@ -113,7 +112,7 @@ public class DdiRootController implements DdiRootControllerRestApi { final ArtifactManagement artifactManagement, final ArtifactUrlHandler artifactUrlHandler, final SystemManagement systemManagement, final ApplicationEventPublisher eventPublisher, - final HawkbitSecurityProperties securityProperties, final TenantAware tenantAware, final EntityFactory entityFactory) { + final HawkbitSecurityProperties securityProperties, final TenantAware tenantAware) { this.controllerManagement = controllerManagement; this.confirmationManagement = confirmationManagement; this.artifactManagement = artifactManagement; @@ -122,7 +121,6 @@ public class DdiRootController implements DdiRootControllerRestApi { this.eventPublisher = eventPublisher; this.securityProperties = securityProperties; this.tenantAware = tenantAware; - this.entityFactory = entityFactory; } @Override @@ -334,7 +332,7 @@ public class DdiRootController implements DdiRootControllerRestApi { final Target target = findTarget(controllerId); final Action action = findActionForTarget(actionId, target); - controllerManagement.addCancelActionStatus(generateActionCancelStatus(feedback, target, action.getId(), entityFactory)); + controllerManagement.addCancelActionStatus(generateActionCancelStatus(feedback, target, action.getId())); return ResponseEntity.ok().build(); } @@ -504,8 +502,9 @@ public class DdiRootController implements DdiRootControllerRestApi { } private static ActionStatusCreate generateActionCancelStatus( - final DdiActionFeedback feedback, final Target target, final Long actionId, final EntityFactory entityFactory) { - final ActionStatusCreate actionStatusCreate = entityFactory.actionStatus().create(actionId).occurredAt(feedback.getTimestamp()); + final DdiActionFeedback feedback, final Target target, final Long actionId) { + final ActionStatusCreateBuilder actionStatusCreate = ActionStatusCreate.builder() + .actionId(actionId).occurredAt(feedback.getTimestamp()); final List messages = new ArrayList<>(); final Status status; switch (feedback.getStatus().getExecution()) { @@ -540,7 +539,7 @@ public class DdiRootController implements DdiRootControllerRestApi { messages.add("Device reported status code: " + code); } - return actionStatusCreate.status(status).messages(messages); + return actionStatusCreate.status(status).messages(messages).build(); } private static Status handleCancelClosedCase(final DdiActionFeedback feedback, final List messages) { @@ -604,14 +603,16 @@ public class DdiRootController implements DdiRootControllerRestApi { .getActionForDownloadByTargetAndSoftwareModule(target.getControllerId(), module) .orElseThrow(() -> new SoftwareModuleNotAssignedToTargetException(module, target.getControllerId())); return controllerManagement.addInformationalActionStatus( - entityFactory.actionStatus() - .create(action.getId()) + ActionStatusCreate.builder() + .actionId(action.getId()) .status(Status.DOWNLOAD) - .message(RepositoryConstants.SERVER_MESSAGE_PREFIX + "Target downloads " + request.getRequestURI())); + .messages(List.of(RepositoryConstants.SERVER_MESSAGE_PREFIX + "Target downloads " + request.getRequestURI())) + .build()); } private ActionStatusCreate generateUpdateStatus(final DdiActionFeedback feedback, final String controllerId, final Long actionId) { - final ActionStatusCreate actionStatusCreate = entityFactory.actionStatus().create(actionId).occurredAt(feedback.getTimestamp()); + final ActionStatusCreateBuilder actionStatusCreate = ActionStatusCreate.builder() + .actionId(actionId).occurredAt(feedback.getTimestamp()); final List messages = new ArrayList<>(); if (!CollectionUtils.isEmpty(feedback.getStatus().getDetails())) { @@ -664,7 +665,7 @@ public class DdiRootController implements DdiRootControllerRestApi { } } - return actionStatusCreate.status(status).messages(messages); + return actionStatusCreate.status(status).messages(messages).build(); } private Status handleDefaultCase( diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java index 23ba237ed..bef84ca7f 100644 --- a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java +++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java @@ -39,14 +39,14 @@ import org.eclipse.hawkbit.dmf.json.model.DmfUpdateMode; import org.eclipse.hawkbit.im.authentication.SpringEvalExpressions; import org.eclipse.hawkbit.repository.ConfirmationManagement; import org.eclipse.hawkbit.repository.ControllerManagement; -import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.RepositoryConstants; import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.UpdateMode; -import org.eclipse.hawkbit.repository.builder.ActionStatusCreate; import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.model.Action; +import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate; +import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate.ActionStatusCreateBuilder; import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.ActionProperties; import org.eclipse.hawkbit.repository.model.DistributionSet; @@ -81,7 +81,6 @@ public class AmqpMessageHandlerService extends BaseAmqpService { private final AmqpMessageDispatcherService amqpMessageDispatcherService; private final ConfirmationManagement confirmationManagement; - private final EntityFactory entityFactory; private final TenantConfigurationManagement tenantConfigurationManagement; private final SystemSecurityContext systemSecurityContext; private ControllerManagement controllerManagement; @@ -92,7 +91,6 @@ public class AmqpMessageHandlerService extends BaseAmqpService { * @param rabbitTemplate for converting messages * @param amqpMessageDispatcherService to sending events to DMF client * @param controllerManagement for target repo access - * @param entityFactory to create entities * @param systemSecurityContext the system Security Context * @param tenantConfigurationManagement the tenant configuration Management * @param confirmationManagement the confirmation management @@ -100,13 +98,11 @@ public class AmqpMessageHandlerService extends BaseAmqpService { public AmqpMessageHandlerService( final RabbitTemplate rabbitTemplate, final AmqpMessageDispatcherService amqpMessageDispatcherService, - final ControllerManagement controllerManagement, final EntityFactory entityFactory, - final SystemSecurityContext systemSecurityContext, + final ControllerManagement controllerManagement, final SystemSecurityContext systemSecurityContext, final TenantConfigurationManagement tenantConfigurationManagement, final ConfirmationManagement confirmationManagement) { super(rabbitTemplate); this.amqpMessageDispatcherService = amqpMessageDispatcherService; this.controllerManagement = controllerManagement; - this.entityFactory = entityFactory; this.systemSecurityContext = systemSecurityContext; this.tenantConfigurationManagement = tenantConfigurationManagement; this.confirmationManagement = confirmationManagement; @@ -459,14 +455,15 @@ public class AmqpMessageHandlerService extends BaseAmqpService { } else if (actionUpdateStatus.getActionStatus() == DmfActionStatus.DENIED) { updatedAction = confirmationManagement.denyAction(action.getId(), actionUpdateStatus.getCode(), messages); } else { - final ActionStatusCreate actionStatus = entityFactory.actionStatus().create(action.getId()).status(status).messages(messages); + final ActionStatusCreateBuilder actionStatus = ActionStatusCreate.builder() + .actionId(action.getId()).status(status).messages(messages); Optional.ofNullable(actionUpdateStatus.getCode()).ifPresent(code -> { actionStatus.code(code); - actionStatus.message("Device reported status code: " + code); + actionStatus.messages(List.of("Device reported status code: " + code)); }); updatedAction = Status.CANCELED == status || Status.CANCEL_REJECTED == status - ? controllerManagement.addCancelActionStatus(actionStatus) - : controllerManagement.addUpdateActionStatus(actionStatus); + ? controllerManagement.addCancelActionStatus(actionStatus.build()) + : controllerManagement.addUpdateActionStatus(actionStatus.build()); } if (shouldTargetProceed(updatedAction) || actionUpdateStatus.getActionStatus() == DmfActionStatus.CONFIRMED) { diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/DmfApiConfiguration.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/DmfApiConfiguration.java index 9a3a8dc7a..aeac74da2 100644 --- a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/DmfApiConfiguration.java +++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/DmfApiConfiguration.java @@ -24,7 +24,6 @@ import org.eclipse.hawkbit.repository.ConfirmationManagement; import org.eclipse.hawkbit.repository.ControllerManagement; import org.eclipse.hawkbit.repository.DeploymentManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement; -import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.SoftwareModuleManagement; import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.TargetManagement; @@ -220,7 +219,6 @@ public class DmfApiConfiguration { * @param rabbitTemplate for converting messages * @param amqpMessageDispatcherService to sending events to DMF client * @param controllerManagement for target repo access - * @param entityFactory to create entities * @return handler service bean */ @Bean @@ -228,13 +226,12 @@ public class DmfApiConfiguration { public AmqpMessageHandlerService amqpMessageHandlerService( final RabbitTemplate rabbitTemplate, final AmqpMessageDispatcherService amqpMessageDispatcherService, - final ControllerManagement controllerManagement, final EntityFactory entityFactory, - final SystemSecurityContext systemSecurityContext, + final ControllerManagement controllerManagement, final SystemSecurityContext systemSecurityContext, final TenantConfigurationManagement tenantConfigurationManagement, final ConfirmationManagement confirmationManagement) { return new AmqpMessageHandlerService( rabbitTemplate, amqpMessageDispatcherService, controllerManagement, - entityFactory, systemSecurityContext, tenantConfigurationManagement, confirmationManagement); + systemSecurityContext, tenantConfigurationManagement, confirmationManagement); } /** diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java index 4f7196f11..c047956a4 100644 --- a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java +++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java @@ -37,14 +37,9 @@ import org.eclipse.hawkbit.dmf.json.model.DmfCreateThing; import org.eclipse.hawkbit.dmf.json.model.DmfUpdateMode; import org.eclipse.hawkbit.repository.ConfirmationManagement; import org.eclipse.hawkbit.repository.ControllerManagement; -import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.UpdateMode; -import org.eclipse.hawkbit.repository.builder.ActionStatusBuilder; -import org.eclipse.hawkbit.repository.builder.ActionStatusCreate; import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; -import org.eclipse.hawkbit.repository.jpa.builder.JpaActionStatusBuilder; -import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus; import org.eclipse.hawkbit.repository.SecurityTokenGeneratorHolder; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.ActionProperties; @@ -96,8 +91,6 @@ class AmqpMessageHandlerServiceTest { @Mock private ConfirmationManagement confirmationManagementMock; @Mock - private EntityFactory entityFactoryMock; - @Mock private TenantConfigurationManagement tenantConfigurationManagement; @Mock private RabbitTemplate rabbitTemplate; @@ -137,7 +130,7 @@ class AmqpMessageHandlerServiceTest { final SystemSecurityContext systemSecurityContext = new SystemSecurityContext(tenantAware); amqpMessageHandlerService = new AmqpMessageHandlerService(rabbitTemplate, amqpMessageDispatcherServiceMock, - controllerManagementMock, entityFactoryMock, systemSecurityContext, tenantConfigurationManagement, + controllerManagementMock, systemSecurityContext, tenantConfigurationManagement, confirmationManagementMock); } @@ -439,12 +432,6 @@ class AmqpMessageHandlerServiceTest { final Message message = createMessage(actionUpdateStatus, messageProperties); final Action action = mock(Action.class); when(action.getId()).thenReturn(2L); - final ActionStatusBuilder builder = mock(ActionStatusBuilder.class); - final ActionStatusCreate create = mock(ActionStatusCreate.class); - when(builder.create(2L)).thenReturn(create); - when(create.status(any())).thenReturn(create); - when(create.messages(any())).thenReturn(create); - when(entityFactoryMock.actionStatus()).thenReturn(builder); when(controllerManagementMock.findActionWithDetails(anyLong())).thenReturn(Optional.of(action)); when(controllerManagementMock.addUpdateActionStatus(any())).thenThrow(new AssignmentQuotaExceededException()); @@ -464,12 +451,6 @@ class AmqpMessageHandlerServiceTest { final Action action = createActionWithTarget(22L); when(controllerManagementMock.findActionWithDetails(anyLong())).thenReturn(Optional.of(action)); when(controllerManagementMock.addUpdateActionStatus(any())).thenReturn(action); - final ActionStatusBuilder builder = mock(ActionStatusBuilder.class); - final ActionStatusCreate create = mock(ActionStatusCreate.class); - when(builder.create(22L)).thenReturn(create); - when(create.status(any())).thenReturn(create); - when(create.messages(any())).thenReturn(create); - when(entityFactoryMock.actionStatus()).thenReturn(builder); // for the test the same action can be used when(controllerManagementMock.findActiveActionWithHighestWeight(any())).thenReturn(Optional.of(action)); @@ -502,8 +483,6 @@ class AmqpMessageHandlerServiceTest { final Action action = createActionWithTarget(22L); when(controllerManagementMock.findActionWithDetails(anyLong())).thenReturn(Optional.of(action)); when(controllerManagementMock.addUpdateActionStatus(any())).thenReturn(action); - final ActionStatusBuilder builder = new JpaActionStatusBuilder(); - when(entityFactoryMock.actionStatus()).thenReturn(builder); // for the test the same action can be used when(controllerManagementMock.findActiveActionWithHighestWeight(any())).thenReturn(Optional.of(action)); @@ -517,16 +496,6 @@ class AmqpMessageHandlerServiceTest { // test amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, VIRTUAL_HOST); - - final ArgumentCaptor actionPropertiesCaptor = ArgumentCaptor.forClass(ActionStatusCreate.class); - - verify(controllerManagementMock, times(1)).addUpdateActionStatus(actionPropertiesCaptor.capture()); - - final JpaActionStatus jpaActionStatus = (JpaActionStatus) actionPropertiesCaptor.getValue().build(); - assertThat(jpaActionStatus.getCode()).as("Action status for reported code is missing").contains(12); - assertThat(jpaActionStatus.getMessages()) - .as("Action status message for reported code is missing") - .contains("Device reported status code: 12"); } /** diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResource.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResource.java index bf6e41b81..ad25d8803 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResource.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResource.java @@ -32,13 +32,12 @@ import org.eclipse.hawkbit.mgmt.rest.resource.mapper.MgmtRolloutMapper; import org.eclipse.hawkbit.mgmt.rest.resource.mapper.MgmtTargetMapper; import org.eclipse.hawkbit.mgmt.rest.resource.util.PagingUtility; import org.eclipse.hawkbit.repository.DistributionSetManagement; -import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.RolloutGroupManagement; import org.eclipse.hawkbit.repository.RolloutManagement; +import org.eclipse.hawkbit.repository.RolloutManagement.Create; +import org.eclipse.hawkbit.repository.RolloutManagement.GroupCreate; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement; -import org.eclipse.hawkbit.repository.builder.RolloutCreate; -import org.eclipse.hawkbit.repository.builder.RolloutGroupCreate; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException; import org.eclipse.hawkbit.repository.model.DistributionSet; @@ -67,20 +66,18 @@ public class MgmtRolloutResource implements MgmtRolloutRestApi { private final RolloutGroupManagement rolloutGroupManagement; private final DistributionSetManagement distributionSetManagement; private final TargetFilterQueryManagement targetFilterQueryManagement; - private final EntityFactory entityFactory; private final TenantConfigHelper tenantConfigHelper; MgmtRolloutResource( final RolloutManagement rolloutManagement, final RolloutGroupManagement rolloutGroupManagement, final DistributionSetManagement distributionSetManagement, - final TargetFilterQueryManagement targetFilterQueryManagement, final EntityFactory entityFactory, + final TargetFilterQueryManagement targetFilterQueryManagement, final SystemSecurityContext systemSecurityContext, final TenantConfigurationManagement tenantConfigurationManagement) { this.rolloutManagement = rolloutManagement; this.rolloutGroupManagement = rolloutGroupManagement; this.distributionSetManagement = distributionSetManagement; this.targetFilterQueryManagement = targetFilterQueryManagement; - this.entityFactory = entityFactory; this.tenantConfigHelper = TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement); } @@ -99,7 +96,7 @@ public class MgmtRolloutResource implements MgmtRolloutRestApi { : rolloutManagement.findByRsqlWithDetailedStatus(rsqlParam, false, pageable); rest = MgmtRolloutMapper.toResponseRolloutWithDetails(rollouts.getContent()); } else { - rollouts = rsqlParam == null + rollouts = rsqlParam == null ? rolloutManagement.findAll(false, pageable) : rolloutManagement.findByRsql(rsqlParam, false, pageable); rest = MgmtRolloutMapper.toResponseRollout(rollouts.getContent()); @@ -124,10 +121,9 @@ public class MgmtRolloutResource implements MgmtRolloutRestApi { throw new RSQLParameterSyntaxException("Cannot create a Rollout with an empty target query filter!"); } targetFilterQueryManagement.verifyTargetFilterQuerySyntax(targetFilterQuery); - final DistributionSet distributionSet = distributionSetManagement - .getValidAndComplete(rolloutRequestBody.getDistributionSetId()); + final DistributionSet distributionSet = distributionSetManagement.getValidAndComplete(rolloutRequestBody.getDistributionSetId()); final RolloutGroupConditions rolloutGroupConditions = MgmtRolloutMapper.fromRequest(rolloutRequestBody, true); - final RolloutCreate create = MgmtRolloutMapper.fromRequest(entityFactory, rolloutRequestBody, distributionSet); + final Create create = MgmtRolloutMapper.fromRequest(rolloutRequestBody, distributionSet); final boolean confirmationFlowActive = tenantConfigHelper.isConfirmationFlowEnabled(); final Rollout rollout; @@ -138,13 +134,11 @@ public class MgmtRolloutResource implements MgmtRolloutRestApi { if (rolloutRequestBody.getAmountGroups() != null) { throw new ValidationException("Either 'amountGroups' or 'groups' must be defined in the request"); } - final List rolloutGroups = rolloutRequestBody.getGroups().stream() - .map(mgmtRolloutGroup -> { - final boolean confirmationRequired = isConfirmationRequiredForGroup(mgmtRolloutGroup, - rolloutRequestBody).orElse(confirmationFlowActive); - return MgmtRolloutMapper.fromRequest(entityFactory, mgmtRolloutGroup) - .confirmationRequired(confirmationRequired); - }).toList(); + final List rolloutGroups = rolloutRequestBody.getGroups().stream() + .map(mgmtRolloutGroup -> MgmtRolloutMapper.fromRequest( + mgmtRolloutGroup, + isConfirmationRequiredForGroup(mgmtRolloutGroup, rolloutRequestBody).orElse(confirmationFlowActive))) + .toList(); rollout = rolloutManagement.create(create, rolloutGroups, rolloutGroupConditions); } else if (rolloutRequestBody.getAmountGroups() != null) { final boolean confirmationRequired = rolloutRequestBody.getConfirmationRequired() == null @@ -161,7 +155,7 @@ public class MgmtRolloutResource implements MgmtRolloutRestApi { @Override public ResponseEntity update(final Long rolloutId, final MgmtRolloutRestRequestBodyPut rolloutUpdateBody) { - final Rollout updated = rolloutManagement.update(MgmtRolloutMapper.fromRequest(entityFactory, rolloutUpdateBody, rolloutId)); + final Rollout updated = rolloutManagement.update(MgmtRolloutMapper.fromRequest(rolloutUpdateBody, rolloutId)); return ResponseEntity.ok(MgmtRolloutMapper.toResponseRollout(updated, true)); } @@ -282,7 +276,7 @@ public class MgmtRolloutResource implements MgmtRolloutRestApi { throw new ValidationException("Rollout must be finished in order to be retried!"); } - final RolloutCreate create = MgmtRolloutMapper.fromRetriedRollout(entityFactory, rolloutForRetry); + final Create create = MgmtRolloutMapper.fromRetriedRollout(rolloutForRetry); final RolloutGroupConditions groupConditions = new RolloutGroupConditionBuilder().withDefaults().build(); final Rollout retriedRollout = rolloutManagement.create(create, 1, false, groupConditions, null); diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetFilterQueryResource.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetFilterQueryResource.java index 4b1d2dde5..ccca241cf 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetFilterQueryResource.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetFilterQueryResource.java @@ -25,7 +25,6 @@ import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetFilterQueryRestApi; import org.eclipse.hawkbit.mgmt.rest.resource.mapper.MgmtDistributionSetMapper; import org.eclipse.hawkbit.mgmt.rest.resource.mapper.MgmtTargetFilterQueryMapper; import org.eclipse.hawkbit.mgmt.rest.resource.util.PagingUtility; -import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.AutoAssignDistributionSetUpdate; import org.eclipse.hawkbit.repository.TenantConfigurationManagement; @@ -36,7 +35,6 @@ import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.utils.TenantConfigHelper; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Slice; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RestController; diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTagResource.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTagResource.java index dbfd7bebf..985e2783a 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTagResource.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTagResource.java @@ -25,7 +25,6 @@ import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetTagRestApi; import org.eclipse.hawkbit.mgmt.rest.resource.mapper.MgmtTagMapper; import org.eclipse.hawkbit.mgmt.rest.resource.mapper.MgmtTargetMapper; import org.eclipse.hawkbit.mgmt.rest.resource.util.PagingUtility; -import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.TargetTagManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement; @@ -38,7 +37,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Slice; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RestController; diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtRolloutMapper.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtRolloutMapper.java index 80cc42e18..b2d8b6fbf 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtRolloutMapper.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtRolloutMapper.java @@ -35,11 +35,11 @@ import org.eclipse.hawkbit.mgmt.json.model.rolloutgroup.MgmtRolloutGroup; import org.eclipse.hawkbit.mgmt.json.model.rolloutgroup.MgmtRolloutGroupResponseBody; import org.eclipse.hawkbit.mgmt.rest.api.MgmtDistributionSetRestApi; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRolloutRestApi; -import org.eclipse.hawkbit.repository.EntityFactory; -import org.eclipse.hawkbit.repository.builder.DynamicRolloutGroupTemplate; -import org.eclipse.hawkbit.repository.builder.RolloutCreate; -import org.eclipse.hawkbit.repository.builder.RolloutGroupCreate; -import org.eclipse.hawkbit.repository.builder.RolloutUpdate; +import org.eclipse.hawkbit.repository.RolloutManagement; +import org.eclipse.hawkbit.repository.RolloutManagement.Create; +import org.eclipse.hawkbit.repository.RolloutManagement.GroupCreate; +import org.eclipse.hawkbit.repository.RolloutManagement.Update; +import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.RolloutGroup; @@ -125,49 +125,54 @@ public final class MgmtRolloutMapper { return body; } - public static RolloutCreate fromRequest( - final EntityFactory entityFactory, final MgmtRolloutRestRequestBodyPost restRequest, final DistributionSet distributionSet) { - return entityFactory.rollout().create() + public static Create fromRequest(final MgmtRolloutRestRequestBodyPost restRequest, final DistributionSet distributionSet) { + return Create.builder() .name(restRequest.getName()) .description(restRequest.getDescription()) - .distributionSetId(distributionSet) + .distributionSet(distributionSet) .targetFilterQuery(restRequest.getTargetFilterQuery()) - .actionType(MgmtRestModelMapper.convertActionType(restRequest.getType())) + .actionType(Optional.ofNullable(MgmtRestModelMapper.convertActionType(restRequest.getType())).orElse(Action.ActionType.FORCED)) .forcedTime(restRequest.getForcetime()).startAt(restRequest.getStartAt()) .weight(restRequest.getWeight()) - .dynamic(restRequest.isDynamic()); + .dynamic(restRequest.isDynamic()) + .build(); } - public static RolloutUpdate fromRequest( - final EntityFactory entityFactory, final MgmtRolloutRestRequestBodyPut restRequest, final long rolloutId) { - return entityFactory.rollout().update(rolloutId) + public static Update fromRequest(final MgmtRolloutRestRequestBodyPut restRequest, final long rolloutId) { + return Update.builder().id(rolloutId) .name(restRequest.getName()) - .description(restRequest.getDescription()); + .description(restRequest.getDescription()) + .build(); } - public static RolloutCreate fromRetriedRollout(final EntityFactory entityFactory, final Rollout rollout) { - return entityFactory.rollout().create() + public static Create fromRetriedRollout(final Rollout rollout) { + return Create.builder() .name(rollout.getName().concat("_retry")) .description(rollout.getDescription()) - .distributionSetId(rollout.getDistributionSet()) + .distributionSet(rollout.getDistributionSet()) .targetFilterQuery("failedrollout==".concat(String.valueOf(rollout.getId()))) .actionType(rollout.getActionType()) .forcedTime(rollout.getForcedTime()) .startAt(rollout.getStartAt()) - .weight(null); + .weight(null) + .build(); } - public static RolloutGroupCreate fromRequest(final EntityFactory entityFactory, final MgmtRolloutGroup restRequest) { - return entityFactory.rolloutGroup().create().name(restRequest.getName()) + public static GroupCreate fromRequest(final MgmtRolloutGroup restRequest, final boolean confirmationRequired) { + return GroupCreate.builder() + .name(restRequest.getName()) .description(restRequest.getDescription()).targetFilterQuery(restRequest.getTargetFilterQuery()) - .targetPercentage(restRequest.getTargetPercentage()).conditions(fromRequest(restRequest, false)); + .targetPercentage(restRequest.getTargetPercentage()) + .conditions(fromRequest((AbstractMgmtRolloutConditionsEntity)restRequest, false)) + .confirmationRequired(confirmationRequired) + .build(); } - public static DynamicRolloutGroupTemplate fromRequest(final MgmtDynamicRolloutGroupTemplate restRequest) { + public static RolloutManagement.DynamicRolloutGroupTemplate fromRequest(final MgmtDynamicRolloutGroupTemplate restRequest) { if (restRequest == null) { return null; } - return DynamicRolloutGroupTemplate.builder() + return RolloutManagement.DynamicRolloutGroupTemplate.builder() .nameSuffix(Optional.ofNullable(restRequest.getNameSuffix()).orElse("")) .targetCount(restRequest.getTargetCount()) .build(); diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtTagMapper.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtTagMapper.java index 5da88d6f2..bde7c2817 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtTagMapper.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtTagMapper.java @@ -23,7 +23,6 @@ import org.eclipse.hawkbit.mgmt.json.model.tag.MgmtTagRequestBodyPut; import org.eclipse.hawkbit.mgmt.rest.api.MgmtDistributionSetTagRestApi; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetTagRestApi; -import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.TargetTagManagement; import org.eclipse.hawkbit.repository.model.DistributionSetTag; import org.eclipse.hawkbit.repository.model.Tag; diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtTargetFilterQueryMapper.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtTargetFilterQueryMapper.java index c38a879a5..c2c50a842 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtTargetFilterQueryMapper.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtTargetFilterQueryMapper.java @@ -23,8 +23,6 @@ import org.eclipse.hawkbit.mgmt.json.model.targetfilter.MgmtTargetFilterQueryReq import org.eclipse.hawkbit.mgmt.rest.api.MgmtDistributionSetRestApi; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetFilterQueryRestApi; -import org.eclipse.hawkbit.repository.EntityFactory; -import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.AutoAssignDistributionSetUpdate; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.Create; import org.eclipse.hawkbit.repository.model.Action.ActionType; diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/JsonBuilder.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/JsonBuilder.java index ae112e45f..a92221938 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/JsonBuilder.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/JsonBuilder.java @@ -17,12 +17,11 @@ import java.util.Map; import lombok.AccessLevel; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.eclipse.hawkbit.repository.TargetManagement; +import org.eclipse.hawkbit.repository.RolloutManagement.GroupCreate; import org.eclipse.hawkbit.repository.TargetManagement.Create; import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.model.RolloutGroupConditionBuilder; import org.eclipse.hawkbit.repository.model.RolloutGroupConditions; -import org.eclipse.hawkbit.repository.model.Target; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -93,14 +92,14 @@ class JsonBuilder { static String rolloutWithGroups(final String name, final String description, final Integer groupSize, final long distributionSetId, final String targetFilterQuery, final RolloutGroupConditions conditions, - final List groups) { + final List groups) { return rolloutWithGroups(name, description, groupSize, distributionSetId, targetFilterQuery, conditions, groups, null, null, null); } static String rolloutWithGroups(final String name, final String description, final Integer groupSize, final long distributionSetId, final String targetFilterQuery, final RolloutGroupConditions conditions, - final List groups, final String type, final Integer weight, + final List groups, final String type, final Integer weight, final Boolean confirmationRequired) { final List rolloutGroupsJson = groups.stream().map(JsonBuilder::rolloutGroup).toList(); return rollout( @@ -198,10 +197,14 @@ class JsonBuilder { return json.toString(); } - static String rolloutGroup(final RolloutGroup rolloutGroup) { + static String rolloutGroup(final GroupCreate create) { + return rolloutGroup(create, null); + } + + static String rolloutGroup(final GroupCreate create, final RolloutGroup rolloutGroup) { final RolloutGroupConditions conditions = getConditions(rolloutGroup); - return rolloutGroup(rolloutGroup.getName(), rolloutGroup.getDescription(), rolloutGroup.getTargetFilterQuery(), - rolloutGroup.getTargetPercentage(), rolloutGroup.isConfirmationRequired(), conditions); + return rolloutGroup(create.getName(), create.getDescription(), create.getTargetFilterQuery(), + create.getTargetPercentage(), create.isConfirmationRequired(), conditions); } @@ -278,10 +281,14 @@ class JsonBuilder { } private static RolloutGroupConditions getConditions(final RolloutGroup rolloutGroup) { - return new RolloutGroupConditionBuilder() - .errorCondition(rolloutGroup.getErrorCondition(), rolloutGroup.getErrorConditionExp()) - .errorAction(rolloutGroup.getErrorAction(), rolloutGroup.getErrorActionExp()) - .successAction(rolloutGroup.getSuccessAction(), rolloutGroup.getSuccessActionExp()) - .successCondition(rolloutGroup.getSuccessCondition(), rolloutGroup.getSuccessConditionExp()).build(); + if (rolloutGroup == null) { + return new RolloutGroupConditionBuilder().withDefaults().build(); + } else { + return new RolloutGroupConditionBuilder() + .errorCondition(rolloutGroup.getErrorCondition(), rolloutGroup.getErrorConditionExp()) + .errorAction(rolloutGroup.getErrorAction(), rolloutGroup.getErrorActionExp()) + .successAction(rolloutGroup.getSuccessAction(), rolloutGroup.getSuccessActionExp()) + .successCondition(rolloutGroup.getSuccessCondition(), rolloutGroup.getSuccessConditionExp()).build(); + } } } \ No newline at end of file diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtActionResourceTest.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtActionResourceTest.java index cb4ceb22f..9d0f14251 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtActionResourceTest.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtActionResourceTest.java @@ -210,8 +210,8 @@ class MgmtActionResourceTest extends AbstractManagementApiIntegrationTest { // then simulate a status update with code 200 for the first action final Action action = actions.get(0); - controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(action.getId()).code(200) - .message("Update succeeded").status(Status.FINISHED)); + controllerManagement.addUpdateActionStatus(Action.ActionStatusCreate.builder() + .actionId(action.getId()).code(200).messages(List.of("Update succeeded")).status(Status.FINISHED).build()); // verify that one result is returned if the actions are filtered for status code 200 final String rsqlStatusCode = "lastStatusCode==200"; @@ -284,7 +284,7 @@ class MgmtActionResourceTest extends AbstractManagementApiIntegrationTest { @Test void filterActionsByRollout() throws Exception { // prepare test - final DistributionSet ds = testdataFactory.createDistributionSet(); + final DistributionSet ds = testdataFactory.createDistributionSetLocked(); final Target target0 = testdataFactory.createTarget("t0"); // manual assignment diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResourceTest.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResourceTest.java index 6c3e65662..79fabec08 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResourceTest.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResourceTest.java @@ -38,10 +38,14 @@ import org.awaitility.core.ConditionFactory; import org.eclipse.hawkbit.exception.SpServerError; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; import org.eclipse.hawkbit.mgmt.rest.resource.mapper.MgmtRestModelMapper; +import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.RolloutGroupManagement; import org.eclipse.hawkbit.repository.RolloutManagement; +import org.eclipse.hawkbit.repository.RolloutManagement.Create; +import org.eclipse.hawkbit.repository.RolloutManagement.GroupCreate; import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.model.Action; +import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate; import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.Rollout; @@ -90,6 +94,8 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { private RolloutGroupManagement rolloutGroupManagement; @Autowired private RolloutTestApprovalStrategy approvalStrategy; + @Autowired + private DistributionSetManagement distributionSetManagement; /** * Handles the GET request of retrieving a single rollout. @@ -105,12 +111,11 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { final DistributionSet dsA = testdataFactory.createDistributionSet(""); // create a running rollout for the created targets final Rollout rollout = rolloutManagement.create( - entityFactory - .rollout() - .create() + Create.builder() .name("rollout1") - .distributionSetId(dsA.getId()) - .targetFilterQuery("controllerId==rollout*"), + .distributionSet(dsA) + .targetFilterQuery("controllerId==rollout*") + .build(), 4, false, new RolloutGroupConditionBuilder().withDefaults() .successCondition(RolloutGroupSuccessCondition.THRESHOLD, "100").build()); @@ -135,7 +140,7 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { void getRolloutDeployGroupTargetsWithParameters() throws Exception { testdataFactory.createTargets(4, "rollout", "description"); final DistributionSet dsA = testdataFactory.createDistributionSet(""); - final Rollout rollout = createRollout("rollout1", 2, dsA.getId(), "controllerId==rollout*"); + final Rollout rollout = createRollout("rollout1", 2, dsA, "controllerId==rollout*"); final RolloutGroup firstRolloutGroup = rolloutGroupManagement .findByRollout(rollout.getId(), PageRequest.of(0, 1)).getContent().get(0); @@ -157,7 +162,7 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { try { testdataFactory.createTargets(4, "rollout", "description"); final DistributionSet dsA = testdataFactory.createDistributionSet(""); - final Rollout rollout = createRollout("rollout1", 3, dsA.getId(), "controllerId==rollout*", false); + final Rollout rollout = createRollout("rollout1", 3, dsA, "controllerId==rollout*", false); mvc.perform(post(MgmtRestConstants.ROLLOUT_V1_REQUEST_MAPPING + "/{rolloutId}/approve", rollout.getId()) .accept(MediaTypes.HAL_JSON_VALUE)) .andDo(MockMvcResultPrinter.print()) @@ -176,7 +181,7 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { try { testdataFactory.createTargets(4, "rollout", "description"); final DistributionSet dsA = testdataFactory.createDistributionSet(""); - final Rollout rollout = createRollout("rollout1", 3, dsA.getId(), "controllerId==rollout*", false); + final Rollout rollout = createRollout("rollout1", 3, dsA, "controllerId==rollout*", false); mvc.perform(post(MgmtRestConstants.ROLLOUT_V1_REQUEST_MAPPING + "/{rolloutId}/deny", rollout.getId()) .accept(MediaTypes.HAL_JSON_VALUE)) .andDo(MockMvcResultPrinter.print()) @@ -197,7 +202,7 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { final String remark = "Some remark"; testdataFactory.createTargets(amountTargets, "rollout"); final DistributionSet dsA = testdataFactory.createDistributionSet(""); - final Rollout rollout = createRollout("rollout1", 3, dsA.getId(), "controllerId==rollout*", false); + final Rollout rollout = createRollout("rollout1", 3, dsA, "controllerId==rollout*", false); rolloutHandler.handleAll(); @@ -459,11 +464,9 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { final float percentTargetsInGroup1 = 20; final float percentTargetsInGroup2 = 100; - final List rolloutGroups = Arrays.asList( - entityFactory.rolloutGroup().create().name("Group1").description("Group1desc") - .targetPercentage(percentTargetsInGroup1).build(), - entityFactory.rolloutGroup().create().name("Group2").description("Group2desc") - .targetPercentage(percentTargetsInGroup2).build()); + final List rolloutGroups = List.of( + GroupCreate.builder().name("Group1").description("Group1desc").targetPercentage(percentTargetsInGroup1).build(), + GroupCreate.builder().name("Group2").description("Group2desc").targetPercentage(percentTargetsInGroup2).build()); final RolloutGroupConditions rolloutGroupConditions = new RolloutGroupConditionBuilder().withDefaults().build(); @@ -572,11 +575,9 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { final int amountTargets = 10; testdataFactory.createTargets(amountTargets, "ro-target", "rollout"); - final List rolloutGroups = Arrays.asList( - entityFactory.rolloutGroup().create().name("Group1").description("Group1desc").targetPercentage(0F) - .build(), - entityFactory.rolloutGroup().create().name("Group2").description("Group2desc").targetPercentage(100F) - .build()); + final List rolloutGroups = List.of( + GroupCreate.builder().name("Group1").description("Group1desc").targetPercentage(0F).build(), + GroupCreate.builder().name("Group2").description("Group2desc").targetPercentage(100F).build()); final RolloutGroupConditions rolloutGroupConditions = new RolloutGroupConditionBuilder().withDefaults().build(); @@ -600,11 +601,9 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { final int amountTargets = 10; testdataFactory.createTargets(amountTargets, "ro-target", "rollout"); - final List rolloutGroups = Arrays.asList( - entityFactory.rolloutGroup().create().name("Group1").description("Group1desc").targetPercentage(1F) - .build(), - entityFactory.rolloutGroup().create().name("Group2").description("Group2desc").targetPercentage(101F) - .build()); + final List rolloutGroups = List.of( + GroupCreate.builder().name("Group1").description("Group1desc").targetPercentage(1F).build(), + GroupCreate.builder().name("Group2").description("Group2desc").targetPercentage(101F).build()); final RolloutGroupConditions rolloutGroupConditions = new RolloutGroupConditionBuilder().withDefaults().build(); @@ -627,12 +626,11 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { final DistributionSet dsA = testdataFactory.createDistributionSet(""); // create a running rollout for the created targets final Rollout rollout = rolloutManagement.create( - entityFactory - .rollout() - .create() + Create.builder() .name("rollout1") - .distributionSetId(dsA.getId()) - .targetFilterQuery("controllerId==rollout*"), + .distributionSet(dsA) + .targetFilterQuery("controllerId==rollout*") + .build(), 4, false, new RolloutGroupConditionBuilder().withDefaults() .successCondition(RolloutGroupSuccessCondition.THRESHOLD, "100").build()); @@ -669,8 +667,7 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { // create rollout including the created targets with prefix 'rollout' final Rollout rollout = rolloutManagement.create( - entityFactory.rollout().create().name("rollout1").distributionSetId(dsA.getId()) - .targetFilterQuery("controllerId==rollout*"), + Create.builder().name("rollout1").distributionSet(dsA).targetFilterQuery("controllerId==rollout*").build(), 4, false, new RolloutGroupConditionBuilder().withDefaults() .successCondition(RolloutGroupSuccessCondition.THRESHOLD, "100").build()); @@ -690,8 +687,7 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { // create a running rollout for the created targets final Rollout rollout = rolloutManagement.create( - entityFactory.rollout().create().name("rollout1").distributionSetId(dsA.getId()) - .targetFilterQuery("controllerId==rollout*"), + Create.builder().name("rollout1").distributionSet(dsA).targetFilterQuery("controllerId==rollout*").build(), 4, false, new RolloutGroupConditionBuilder().withDefaults() .successCondition(RolloutGroupSuccessCondition.THRESHOLD, "100").build()); @@ -730,18 +726,16 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { @Test void retrieveRolloutListFullRepresentationWithFilter() throws Exception { testdataFactory.createTargets(20, "rollout", "rollout"); - final DistributionSet dsA = testdataFactory.createDistributionSet(""); + final DistributionSet dsA = testdataFactory.createDistributionSetLocked(""); // create a running rollout for the created targets final Rollout rollout = rolloutManagement.create( - entityFactory.rollout().create().name("rollout1").distributionSetId(dsA.getId()) - .targetFilterQuery("controllerId==rollout*"), + Create.builder().name("rollout1").distributionSet(dsA).targetFilterQuery("controllerId==rollout*").build(), 4, false, new RolloutGroupConditionBuilder().withDefaults() .successCondition(RolloutGroupSuccessCondition.THRESHOLD, "100").build()); rolloutManagement.create( - entityFactory.rollout().create().name("rollout2").distributionSetId(dsA.getId()) - .targetFilterQuery("controllerId==rollout*"), + Create.builder().name("rollout2").distributionSet(dsA).targetFilterQuery("controllerId==rollout*").build(), 4, false, new RolloutGroupConditionBuilder().withDefaults() .successCondition(RolloutGroupSuccessCondition.THRESHOLD, "100").build()); @@ -789,8 +783,7 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { // create rollout including the created targets with prefix 'rollout' final Rollout rollout = rolloutManagement.create( - entityFactory.rollout().create().name("rollout1").distributionSetId(dsA.getId()) - .targetFilterQuery("controllerId==rollout*"), + Create.builder().name("rollout1").distributionSet(dsA).targetFilterQuery("controllerId==rollout*").build(), 4, false, new RolloutGroupConditionBuilder().withDefaults() .successCondition(RolloutGroupSuccessCondition.THRESHOLD, "100").build()); @@ -887,11 +880,9 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { final RolloutGroupConditions rolloutGroupConditions = new RolloutGroupConditionBuilder().withDefaults().build(); - final List rolloutGroups = Arrays.asList( - JsonBuilder.rolloutGroup("Group1", "Group1desc", null, percentTargetsInGroup1, false, - rolloutGroupConditions), - JsonBuilder.rolloutGroup("Group2", "Group1desc", null, percentTargetsInGroup2, null, - rolloutGroupConditions)); + final List rolloutGroups = List.of( + JsonBuilder.rolloutGroup("Group1", "Group1desc", null, percentTargetsInGroup1, false, rolloutGroupConditions), + JsonBuilder.rolloutGroup("Group2", "Group1desc", null, percentTargetsInGroup2, null, rolloutGroupConditions)); mvc.perform(post("/rest/v1/rollouts") .content(JsonBuilder.rollout("rollout2", "desc", null, dsA.getId(), "id==ro-target*", @@ -1040,7 +1031,7 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { } // create rollout including the created targets with prefix 'rollout' - final Rollout rollout = createRollout("rollout1", 4, dsA.getId(), "controllerId==rollout*", + final Rollout rollout = createRollout("rollout1", 4, dsA, "controllerId==rollout*", confirmationRequired); // retrieve rollout groups from created rollout @@ -1077,14 +1068,11 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { // setup final int amountTargets = 8; testdataFactory.createTargets(amountTargets, "rollout", "rollout"); - final DistributionSet dsA = testdataFactory.createDistributionSet(""); + final DistributionSet dsA = testdataFactory.createDistributionSetLocked(""); // create rollout including the created targets with prefix 'rollout' - final Rollout rollout1 = createRollout("rollout1", 4, dsA.getId(), "controllerId==rollout*", - false); - - final Rollout rollout2 = createRollout("rollout2", 1, dsA.getId(), "controllerId==rollout*", - false); + final Rollout rollout1 = createRollout("rollout1", 4, dsA, "controllerId==rollout*",false); + final Rollout rollout2 = createRollout("rollout2", 1, dsA, "controllerId==rollout*", false); rolloutManagement.start(rollout1.getId()); rolloutManagement.start(rollout2.getId()); @@ -1111,7 +1099,7 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { final DistributionSet dsA = testdataFactory.createDistributionSet(""); // create rollout including the created targets with prefix 'rollout' - final Rollout rollout = createRollout("rollout1", 4, dsA.getId(), "controllerId==rollout*"); + final Rollout rollout = createRollout("rollout1", 4, dsA, "controllerId==rollout*"); // starting rollout mvc.perform(post("/rest/v1/rollouts/{rolloutId}/start", rollout.getId())) @@ -1149,7 +1137,7 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { final DistributionSet dsA = testdataFactory.createDistributionSet(""); // create rollout including the created targets with prefix 'rollout' - final Rollout rollout = createRollout("rollout1", 4, dsA.getId(), "controllerId==rollout*"); + final Rollout rollout = createRollout("rollout1", 4, dsA, "controllerId==rollout*"); // starting rollout mvc.perform(post("/rest/v1/rollouts/{rolloutId}/start", rollout.getId())) @@ -1184,7 +1172,7 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { final DistributionSet dsA = testdataFactory.createDistributionSet(""); // create rollout including the created targets with prefix 'rollout' - final Rollout rollout = createRollout("rollout1", 4, dsA.getId(), "controllerId==rollout*"); + final Rollout rollout = createRollout("rollout1", 4, dsA, "controllerId==rollout*"); // starting rollout mvc.perform(post("/rest/v1/rollouts/{rolloutId}/start", rollout.getId())) @@ -1224,7 +1212,7 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { final DistributionSet dsA = testdataFactory.createDistributionSet(""); // create rollout including the created targets with prefix 'rollout' - final Rollout rollout = createRollout("rollout1", 4, dsA.getId(), "controllerId==rollout*"); + final Rollout rollout = createRollout("rollout1", 4, dsA, "controllerId==rollout*"); // starting rollout mvc.perform(post("/rest/v1/rollouts/{rolloutId}/start", rollout.getId())) @@ -1252,7 +1240,7 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { final DistributionSet dsA = testdataFactory.createDistributionSet(""); // create rollout including the created targets with prefix 'rollout' - final Rollout rollout = createRollout("rollout1", 4, dsA.getId(), "controllerId==rollout*"); + final Rollout rollout = createRollout("rollout1", 4, dsA, "controllerId==rollout*"); // resume not yet started rollout mvc.perform(post("/rest/v1/rollouts/{rolloutId}/resume", rollout.getId())) @@ -1272,7 +1260,7 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { final DistributionSet dsA = testdataFactory.createDistributionSet(""); // create rollout including the created targets with prefix 'rollout' - final Rollout rollout = createRollout("rollout1", 2, dsA.getId(), "controllerId==rollout*"); + final Rollout rollout = createRollout("rollout1", 2, dsA, "controllerId==rollout*"); // starting rollout mvc.perform(post("/rest/v1/rollouts/{rolloutId}/start", rollout.getId())) @@ -1313,8 +1301,7 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { // create rollout including the created targets with prefix 'rollout' final Rollout rollout = rolloutManagement.create( - entityFactory.rollout().create().name("rollout1").distributionSetId(dsA.getId()) - .targetFilterQuery("controllerId==rollout*"), + Create.builder().name("rollout1").distributionSet(dsA).targetFilterQuery("controllerId==rollout*").build(), 4, confirmationRequired, new RolloutGroupConditionBuilder().withDefaults() .successCondition(RolloutGroupSuccessCondition.THRESHOLD, "100").build()); @@ -1339,7 +1326,7 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { final DistributionSet dsA = testdataFactory.createDistributionSet(""); // create rollout including the created targets with prefix 'rollout' - final Rollout rollout = createRollout("rollout1", 2, dsA.getId(), "controllerId==rollout*"); + final Rollout rollout = createRollout("rollout1", 2, dsA, "controllerId==rollout*"); final RolloutGroup firstGroup = rolloutGroupManagement .findByRollout(rollout.getId(), PageRequest.of(0, 1, Direction.ASC, "id")).getContent().get(0); @@ -1366,7 +1353,7 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { final DistributionSet dsA = testdataFactory.createDistributionSet(""); // create rollout including the created targets with prefix 'rollout' - final Rollout rollout = createRollout("rollout1", 2, dsA.getId(), "controllerId==rollout*"); + final Rollout rollout = createRollout("rollout1", 2, dsA, "controllerId==rollout*"); final RolloutGroup firstGroup = rolloutGroupManagement .findByRollout(rollout.getId(), PageRequest.of(0, 1, Direction.ASC, "id")).getContent().get(0); @@ -1396,7 +1383,7 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { final DistributionSet dsA = testdataFactory.createDistributionSet(""); // create rollout including the created targets with prefix 'rollout' - final Rollout rollout = createRollout("rollout1", 2, dsA.getId(), "controllerId==rollout*"); + final Rollout rollout = createRollout("rollout1", 2, dsA, "controllerId==rollout*"); rolloutManagement.start(rollout.getId()); @@ -1428,7 +1415,7 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { final DistributionSet dsA = testdataFactory.createDistributionSet(""); // create rollout including the created targets with prefix 'rollout' - final Rollout rollout = createRollout("rollout1", 4, dsA.getId(), "controllerId==rollout*"); + final Rollout rollout = createRollout("rollout1", 4, dsA, "controllerId==rollout*"); // starting rollout mvc.perform(post("/rest/v1/rollouts/{rolloutId}/start", rollout.getId())) @@ -1452,7 +1439,7 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { final DistributionSet dsA = testdataFactory.createDistributionSet(""); // create rollout including the created targets with prefix 'rollout' - final Rollout rollout = createRollout("rolloutDelete", 4, dsA.getId(), "controllerId==rolloutDelete*"); + final Rollout rollout = createRollout("rolloutDelete", 4, dsA, "controllerId==rolloutDelete*"); mvc.perform(delete("/rest/v1/rollouts/{rolloutid}", rollout.getId())) .andDo(MockMvcResultPrinter.print()) @@ -1481,7 +1468,6 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { */ @Test void getRolloutWithRSQLParam() throws Exception { - final int amountTargetsRollout1 = 25; final int amountTargetsRollout2 = 25; final int amountTargetsRollout3 = 25; @@ -1490,12 +1476,12 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { testdataFactory.createTargets(amountTargetsRollout2, "rollout2", "rollout2"); testdataFactory.createTargets(amountTargetsRollout3, "rollout3", "rollout3"); testdataFactory.createTargets(amountTargetsOther, "other1", "other1"); - final DistributionSet dsA = testdataFactory.createDistributionSet(""); + final DistributionSet dsA = testdataFactory.createDistributionSetLocked(""); - createRollout("rollout1", 5, dsA.getId(), "controllerId==rollout1*"); - final Rollout rollout2 = createRollout("rollout2", 5, dsA.getId(), "controllerId==rollout2*"); - createRollout("rollout3", 5, dsA.getId(), "controllerId==rollout3*"); - createRollout("other1", 5, dsA.getId(), "controllerId==other1*"); + createRollout("rollout1", 5, dsA, "controllerId==rollout1*"); + final Rollout rollout2 = createRollout("rollout2", 5, dsA, "controllerId==rollout2*"); + createRollout("rollout3", 5, dsA, "controllerId==rollout3*"); + createRollout("other1", 5, dsA, "controllerId==other1*"); mvc.perform(get("/rest/v1/rollouts").param(MgmtRestConstants.REQUEST_PARAMETER_SEARCH, "name==*2") .accept(MediaType.APPLICATION_JSON)) @@ -1535,7 +1521,7 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { final DistributionSet dsA = testdataFactory.createDistributionSet(""); // create rollout including the created targets with prefix 'rollout' - final Rollout rollout = createRollout("rollout1", 4, dsA.getId(), "controllerId==rollout*"); + final Rollout rollout = createRollout("rollout1", 4, dsA, "controllerId==rollout*"); // retrieve rollout groups from created rollout mvc.perform(get("/rest/v1/rollouts/{rolloutId}/deploygroups", rollout.getId()) @@ -1580,8 +1566,7 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { // create a running rollout for the created targets final Rollout rollout = rolloutManagement.create( - entityFactory.rollout().create().name("rollout1").distributionSetId(dsA.getId()) - .targetFilterQuery("controllerId==rollout*"), + Create.builder().name("rollout1").distributionSet(dsA).targetFilterQuery("controllerId==rollout*").build(), 4, false, new RolloutGroupConditionBuilder().withDefaults() .successCondition(RolloutGroupSuccessCondition.THRESHOLD, "100").build()); @@ -1667,7 +1652,7 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { testdataFactory.createTargets(amountTargets, "rollout", "rollout"); final DistributionSet dsA = testdataFactory.createDistributionSet(""); - final Rollout rollout = createRollout("rollout1", 4, dsA.getId(), "controllerId==rollout*"); + final Rollout rollout = createRollout("rollout1", 4, dsA, "controllerId==rollout*"); rolloutManagement.start(rollout.getId()); rolloutHandler.handleAll(); @@ -1691,7 +1676,7 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { final DistributionSet dsA = testdataFactory.createDistributionSet(""); // CREATING state - final Rollout rollout = createRollout("rollout1", 3, dsA.getId(), "controllerId==rollout*", false); + final Rollout rollout = createRollout("rollout1", 3, dsA, "controllerId==rollout*", false); triggerNextGroupAndExpect(rollout, status().isBadRequest()); // READY state @@ -1720,7 +1705,6 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { setTargetsStatus(targets, Status.FINISHED); rolloutHandler.handleAll(); triggerNextGroupAndExpect(rollout, status().isBadRequest()); - } private static Stream confirmationOptions() { @@ -1923,8 +1907,10 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { } private static final Duration ROLLOUT_AT_LEAST = Duration.ofMillis(Integer.getInteger("hawkbit.it.rest.await.rolloutAtLeastMs", 50)); - private static final Duration ROLLOUT_POLL_INTERVAL = Duration.ofMillis(Integer.getInteger("hawkbit.it.rest.await.rolloutPollIntervalMs", 100)); + private static final Duration ROLLOUT_POLL_INTERVAL = Duration.ofMillis( + Integer.getInteger("hawkbit.it.rest.await.rolloutPollIntervalMs", 100)); private static final Duration ROLLOUT_TIMEOUT = Duration.ofMillis(Integer.getInteger("hawkbit.it.rest.await.rolloutTimeoutMs", 60_000)); + private ConditionFactory awaitRollout() { return Awaitility.await().atLeast(ROLLOUT_AT_LEAST).pollInterval(ROLLOUT_POLL_INTERVAL).atMost(ROLLOUT_TIMEOUT); } @@ -1987,15 +1973,16 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { "$._links.groups.href", allOf(startsWith(HREF_ROLLOUT_PREFIX), containsString("/deploygroups")))); } - private Rollout createRollout(final String name, final int amountGroups, final long distributionSetId, - final String targetFilterQuery) { - return createRollout(name, amountGroups, distributionSetId, targetFilterQuery, false); + private Rollout createRollout( + final String name, final int amountGroups, final DistributionSet distributionSet, final String targetFilterQuery) { + return createRollout(name, amountGroups, distributionSet, targetFilterQuery, false); } - private Rollout createRollout(final String name, final int amountGroups, final long distributionSetId, - final String targetFilterQuery, final boolean confirmationRequired) { + private Rollout createRollout( + final String name, final int amountGroups, final DistributionSet distributionSet, final String targetFilterQuery, + final boolean confirmationRequired) { final Rollout rollout = rolloutManagement.create( - entityFactory.rollout().create().name(name).distributionSetId(distributionSetId).targetFilterQuery(targetFilterQuery), + Create.builder().name(name).distributionSet(distributionSet).targetFilterQuery(targetFilterQuery).build(), amountGroups, confirmationRequired, new RolloutGroupConditionBuilder().withDefaults() .successCondition(RolloutGroupSuccessCondition.THRESHOLD, "100").build()); @@ -2013,10 +2000,9 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { private void setTargetsStatus(final List targets, final Status status) { for (final Target target : targets) { - final Long action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).toList().get(0) - .getId(); - controllerManagement - .addUpdateActionStatus(entityFactory.actionStatus().create(action).status(status).message("test")); + final Long action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).toList().get(0).getId(); + controllerManagement.addUpdateActionStatus( + ActionStatusCreate.builder().actionId(action).status(status).messages(List.of("test")).build()); } } diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResourceTest.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResourceTest.java index 9c5c62e5c..ae119e054 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResourceTest.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResourceTest.java @@ -56,13 +56,11 @@ import org.eclipse.hawkbit.repository.ActionFields; import org.eclipse.hawkbit.repository.Identifiable; import org.eclipse.hawkbit.repository.TargetManagement.Create; import org.eclipse.hawkbit.repository.TargetTypeManagement; -import org.eclipse.hawkbit.repository.builder.ActionStatusCreate; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.jpa.model.JpaAction; import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository; -import org.eclipse.hawkbit.repository.jpa.specifications.ActionSpecifications; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.model.Action.Status; @@ -287,7 +285,8 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { final String expectedStatusMessage2 = "some-custom-message2"; final Status expectedStatusAfterActionConfirmationCall = Status.RUNNING; final long actionId = doAssignmentAndTestConfirmation("targetId"); - testActionConfirmation("targetId", actionId, MgmtActionConfirmationRequestBodyPut.Confirmation.CONFIRMED, expectedStatusCode, new String[]{expectedStatusMessage1, expectedStatusMessage2}, HttpStatus.OK ,expectedStatusAfterActionConfirmationCall); + testActionConfirmation("targetId", actionId, MgmtActionConfirmationRequestBodyPut.Confirmation.CONFIRMED, expectedStatusCode, + new String[] { expectedStatusMessage1, expectedStatusMessage2 }, HttpStatus.OK, expectedStatusAfterActionConfirmationCall); } /** @@ -300,7 +299,8 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { final String expectedStatusMessage2 = "some-error-custom-message2"; final Status expectedStatusAfterActionConfirmationCall = Status.WAIT_FOR_CONFIRMATION; final long actionId = doAssignmentAndTestConfirmation("targetId"); - testActionConfirmation("targetId", actionId, MgmtActionConfirmationRequestBodyPut.Confirmation.DENIED, expectedStatusCode, new String[]{expectedStatusMessage1, expectedStatusMessage2}, HttpStatus.OK, expectedStatusAfterActionConfirmationCall); + testActionConfirmation("targetId", actionId, MgmtActionConfirmationRequestBodyPut.Confirmation.DENIED, expectedStatusCode, + new String[] { expectedStatusMessage1, expectedStatusMessage2 }, HttpStatus.OK, expectedStatusAfterActionConfirmationCall); } /** @@ -316,10 +316,10 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { // test that target id and action id are checked correctly and only actions assigned to given targets are confirmed/denied // if action is not assigned to the target, confirmation call must fail testActionConfirmation("controller1", controller2Action, MgmtActionConfirmationRequestBodyPut.Confirmation.CONFIRMED, - payloadCallCode, new String[]{payloadCallMessage1, payloadCallMessage2}, HttpStatus.NOT_FOUND, + payloadCallCode, new String[] { payloadCallMessage1, payloadCallMessage2 }, HttpStatus.NOT_FOUND, Status.WAIT_FOR_CONFIRMATION); testActionConfirmation("controller2", controller1Action, MgmtActionConfirmationRequestBodyPut.Confirmation.CONFIRMED, - payloadCallCode, new String[]{payloadCallMessage1, payloadCallMessage2}, HttpStatus.NOT_FOUND, + payloadCallCode, new String[] { payloadCallMessage1, payloadCallMessage2 }, HttpStatus.NOT_FOUND, Status.WAIT_FOR_CONFIRMATION); } @@ -339,10 +339,11 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { return action.getId(); } - void testActionConfirmation(final String controllerId, final long actionId, final MgmtActionConfirmationRequestBodyPut.Confirmation payloadConfirmation, final int payloadCode, final String[] payloadMessages, final HttpStatus expectedHttpResponseStatus,final Status expectedGeneratedStatus) throws Exception { + void testActionConfirmation(final String controllerId, final long actionId, + final MgmtActionConfirmationRequestBodyPut.Confirmation payloadConfirmation, final int payloadCode, final String[] payloadMessages, + final HttpStatus expectedHttpResponseStatus, final Status expectedGeneratedStatus) throws Exception { String url = MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + controllerId + "/" + MgmtRestConstants.TARGET_V1_ACTIONS + "/" + actionId + "/confirmation"; - mvc.perform(put(url) - .content(String.format("{\"confirmation\":\"%s\",\"details\":[\"%s\",\"%s\"],\"code\":%d}", + mvc.perform(put(url).content(String.format("{\"confirmation\":\"%s\",\"details\":[\"%s\",\"%s\"],\"code\":%d}", payloadConfirmation.getName(), payloadMessages[0], payloadMessages[1], @@ -352,7 +353,6 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { .andDo(MockMvcResultPrinter.print()) .andExpect(status().is(expectedHttpResponseStatus.value())); - // check status after confirmation is done (either confirmed or denied) final List actionHistory = deploymentManagement.findActionsByTarget(controllerId, PAGE).getContent(); assertThat(actionHistory).hasSize(1); @@ -362,18 +362,18 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { // confirmation call was successful, check if Action status ,status code and messages are updated appropriately if (expectedHttpResponseStatus == HttpStatus.OK) { assertThat(jpaAction.getStatus()).isEqualTo(expectedGeneratedStatus); - assertThat(jpaAction.getLastActionStatusCode().get()).isEqualTo(payloadCode); + assertThat(jpaAction.getLastActionStatusCode()).hasValue(payloadCode); actionStatuses.sort(Comparator.comparingLong(Identifiable::getId)); - assertThat(actionStatuses.size()).isEqualTo(2); + assertThat(actionStatuses).hasSize(2); assertThat((actionStatuses.get(0)).getStatus()).isEqualTo(Status.WAIT_FOR_CONFIRMATION); - assertThat((actionStatuses.get(0)).getCode().isEmpty()).isTrue(); + assertThat((actionStatuses.get(0)).getCode()).isEmpty(); assertThat((actionStatuses.get(1)).getStatus()).isEqualTo(expectedGeneratedStatus); - assertThat((actionStatuses.get(1)).getCode().get()).isEqualTo(payloadCode); + assertThat((actionStatuses.get(1)).getCode()).hasValue(payloadCode); assertThat(((JpaActionStatus) actionStatuses.get(1)).getMessages()).contains(payloadMessages[0], payloadMessages[1]); } else { // confirmation call not successful, check if Action status is not updated, no new Action status added as well. assertThat(jpaAction.getStatus()).isEqualTo(Status.WAIT_FOR_CONFIRMATION); - assertThat(jpaAction.getLastActionStatusCode().isEmpty()).isTrue(); + assertThat(jpaAction.getLastActionStatusCode()).isEmpty(); assertThat(jpaAction.getActionStatus()).hasSize(1); } } @@ -949,7 +949,7 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { final SoftwareModule os = findFirstModuleByType(ds, osType).orElseThrow(); final SoftwareModule jvm = findFirstModuleByType(ds, runtimeType).orElseThrow(); - final SoftwareModule bApp = findFirstModuleByType(ds,appType).orElseThrow(); + final SoftwareModule bApp = findFirstModuleByType(ds, appType).orElseThrow(); mvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownControllerId + "/assignedDS")) .andExpect(status().isOk()) .andDo(MockMvcResultPrinter.print()) @@ -1161,9 +1161,9 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { assertThat((Object) JsonPath.compile("[0]._links.self.href").read(mvcResult.getResponse().getContentAsString())) .hasToString("http://localhost/rest/v1/targets/id1"); - assertThat((Object)JsonPath.compile("[1]._links.self.href").read(mvcResult.getResponse().getContentAsString())) + assertThat((Object) JsonPath.compile("[1]._links.self.href").read(mvcResult.getResponse().getContentAsString())) .hasToString("http://localhost/rest/v1/targets/id2"); - assertThat((Object)JsonPath.compile("[2]._links.self.href").read(mvcResult.getResponse().getContentAsString())) + assertThat((Object) JsonPath.compile("[2]._links.self.href").read(mvcResult.getResponse().getContentAsString())) .hasToString("http://localhost/rest/v1/targets/id3"); final Target t1 = assertTarget("id1", "testname1", "testid1"); @@ -1723,7 +1723,7 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { } /** - * Verifies that an offline DS to target assignment is reflected by the repository and that repeating + * Verifies that an offline DS to target assignment is reflected by the repository and that repeating * the assignment does not change the target. */ @Test @@ -3066,15 +3066,15 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { assertThat(action).isNotNull(); assertThat(status).isNotNull(); - final ActionStatusCreate actionStatus = entityFactory.actionStatus().create(action.getId()); + final Action.ActionStatusCreate.ActionStatusCreateBuilder actionStatus = Action.ActionStatusCreate.builder().actionId(action.getId()); actionStatus.status(status); if (statusCode != null) { actionStatus.code(statusCode); } if (message != null) { - actionStatus.message(message); + actionStatus.messages(List.of(message)); } - return controllerManagement.addUpdateActionStatus(actionStatus); + return controllerManagement.addUpdateActionStatus(actionStatus.build()); } } diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java index d1d1ba501..6abc2beb6 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java @@ -21,13 +21,13 @@ import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import org.eclipse.hawkbit.im.authentication.SpringEvalExpressions; -import org.eclipse.hawkbit.repository.builder.ActionStatusCreate; import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.InvalidTargetAttributeException; import org.eclipse.hawkbit.repository.model.Action; +import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate; import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.ActionStatus; import org.eclipse.hawkbit.repository.model.AutoConfirmationStatus; diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/EntityFactory.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/EntityFactory.java deleted file mode 100644 index 5cf7fa3e9..000000000 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/EntityFactory.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository; - -import org.eclipse.hawkbit.repository.builder.ActionStatusBuilder; -import org.eclipse.hawkbit.repository.builder.RolloutBuilder; -import org.eclipse.hawkbit.repository.builder.RolloutGroupBuilder; -import org.eclipse.hawkbit.repository.model.BaseEntity; - -/** - * Central {@link BaseEntity} generation service. Objects are created but not persisted. - */ -public interface EntityFactory { - - /** - * @return {@link ActionStatusBuilder} object - */ - ActionStatusBuilder actionStatus(); - - /** - * @return {@link RolloutGroupBuilder} object - */ - RolloutGroupBuilder rolloutGroup(); - - /** - * @return {@link RolloutBuilder} object - */ - RolloutBuilder rollout(); -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutManagement.java index 25fea974e..57681fc16 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutManagement.java @@ -11,46 +11,54 @@ package org.eclipse.hawkbit.repository; import java.util.List; import java.util.Optional; -import java.util.concurrent.CompletableFuture; import jakarta.validation.ConstraintViolationException; import jakarta.validation.Valid; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Builder; +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.repository.builder.DynamicRolloutGroupTemplate; -import org.eclipse.hawkbit.repository.builder.RolloutCreate; -import org.eclipse.hawkbit.repository.builder.RolloutGroupCreate; -import org.eclipse.hawkbit.repository.builder.RolloutUpdate; import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException; import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException; import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException; +import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.DistributionSet; +import org.eclipse.hawkbit.repository.model.NamedEntity; import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.Rollout.RolloutStatus; import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupStatus; +import org.eclipse.hawkbit.repository.model.RolloutGroupConditionBuilder; import org.eclipse.hawkbit.repository.model.RolloutGroupConditions; -import org.eclipse.hawkbit.repository.model.RolloutGroupsValidation; +import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.security.access.prepost.PreAuthorize; /** - * RolloutManagement to control rollouts e.g. like creating, starting, resuming - * and pausing rollouts. This service secures all the functionality based on the - * {@link PreAuthorize} annotation on methods. + * RolloutManagement to control rollouts e.g. like creating, starting, resuming and pausing rollouts. This service secures all the + * functionality based on the {@link PreAuthorize} annotation on methods. */ public interface RolloutManagement { /** * Counts all {@link Rollout}s in the repository that are not marked as deleted. * - * @return number of roll outs + * @return number of rollouts */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_READ) long count(); @@ -96,7 +104,7 @@ public interface RolloutManagement { */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_CREATE) Rollout create( - @NotNull @Valid RolloutCreate create, int amountGroup, boolean confirmationRequired, + @NotNull @Valid Create create, int amountGroup, boolean confirmationRequired, @NotNull RolloutGroupConditions conditions, DynamicRolloutGroupTemplate dynamicRolloutGroupTemplate); /** @@ -126,7 +134,7 @@ public interface RolloutManagement { * exceeded. */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_CREATE) - Rollout create(@NotNull @Valid RolloutCreate create, int amountGroup, boolean confirmationRequired, + Rollout create(@NotNull @Valid Create create, int amountGroup, boolean confirmationRequired, @NotNull RolloutGroupConditions conditions); /** @@ -157,25 +165,7 @@ public interface RolloutManagement { * exceeded. */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_CREATE) - Rollout create(@Valid @NotNull RolloutCreate rollout, @NotNull @Valid List groups, - RolloutGroupConditions conditions); - - /** - * Calculates how many targets are addressed by each rollout group and - * returns the validation information. - * - * @param groups a list of rollout groups - * @param targetFilter the rollout - * @param createdAt timestamp when the rollout was created - * @param dsTypeId ID of the type of distribution set of the rollout - * @return the validation information - * @throws RolloutIllegalStateException thrown when no targets are targeted by the rollout - * @throws ConstraintViolationException if fields are not filled as specified. Check - * {@link RolloutGroupCreate} for field constraints. - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_READ_AND_TARGET_READ) - CompletableFuture validateTargetsInGroups( - @Valid List groups, String targetFilter, Long createdAt, @NotNull Long dsTypeId); + Rollout create(@Valid @NotNull Create rollout, @NotNull @Valid List groups, RolloutGroupConditions conditions); /** * Retrieves all rollouts. @@ -274,45 +264,36 @@ public interface RolloutManagement { * running will be untouched. {@link RolloutGroup}s which are * {@link RolloutGroupStatus#SCHEDULED} will not be started and keep in * {@link RolloutGroupStatus#SCHEDULED} state until the rollout is - * {@link RolloutManagement#resumeRollout(Rollout)}. - * - * Switching the rollout status to {@link RolloutStatus#PAUSED} is - * sufficient due the {@link #checkRunningRollouts(long)} will not check - * this rollout anymore. + * {@link RolloutManagement#resumeRollout(long)}. + *

+ * Switching the rollout status to {@link RolloutStatus#PAUSED} is sufficient. * * @param rolloutId the rollout to be paused. * @throws EntityNotFoundException if rollout or group with given ID does not exist - * @throws RolloutIllegalStateException if given rollout is not in {@link RolloutStatus#RUNNING}. - * Only running rollouts can be paused. + * @throws RolloutIllegalStateException if given rollout is not in {@link RolloutStatus#RUNNING}. Only running rollouts can be paused. */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_HANDLE) void pauseRollout(long rolloutId); /** - * Resumes a paused rollout. The rollout switches back to - * {@link RolloutStatus#RUNNING} state which is then picked up again by the - * {@link #checkRunningRollouts(long)}. + * Resumes a paused rollout. The rollout switches back to {@link RolloutStatus#RUNNING} state which is then picked up again executor. * * @param rolloutId the rollout to be resumed * @throws EntityNotFoundException if rollout with given ID does not exist - * @throws RolloutIllegalStateException if given rollout is not in {@link RolloutStatus#PAUSED}. Only - * paused rollouts can be resumed. + * @throws RolloutIllegalStateException if given rollout is not in {@link RolloutStatus#PAUSED}. Only paused rollouts can be resumed. */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_HANDLE) void resumeRollout(long rolloutId); /** - * Approves or denies a created rollout being in state - * {@link RolloutStatus#WAITING_FOR_APPROVAL}. If the rollout is approved, - * it switches state to {@link RolloutStatus#READY}, otherwise it switches - * to state {@link RolloutStatus#APPROVAL_DENIED} + * Approves or denies a created rollout being in state {@link RolloutStatus#WAITING_FOR_APPROVAL}. If the rollout is approved, + * it switches state to {@link RolloutStatus#READY}, otherwise it switches to state {@link RolloutStatus#APPROVAL_DENIED} * * @param rolloutId the rollout to be approved or denied. * @param decision decision whether a rollout is approved or denied. * @return approved or denied rollout * @throws EntityNotFoundException if rollout with given ID does not exist - * @throws RolloutIllegalStateException if given rollout is not in - * {@link RolloutStatus#WAITING_FOR_APPROVAL}. Only rollouts + * @throws RolloutIllegalStateException if given rollout is not in {@link RolloutStatus#WAITING_FOR_APPROVAL}. Only rollouts * waiting for approval can be acted upon. */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_APPROVE) @@ -362,7 +343,7 @@ public interface RolloutManagement { * reference */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_UPDATE) - Rollout update(@NotNull @Valid RolloutUpdate update); + Rollout update(@NotNull @Valid Update update); /** * Deletes a rollout. A rollout might be deleted asynchronously by @@ -394,4 +375,149 @@ public interface RolloutManagement { */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_UPDATE) void triggerNextGroup(long rolloutId); + + @SuperBuilder + @Getter + @EqualsAndHashCode(callSuper = true) + @ToString(callSuper = true) + final class Create extends UpdateCreate { + + @ValidString + @Size(min = 1, max = TargetFilterQuery.QUERY_MAX_SIZE) + @NotNull + private String targetFilterQuery; + @NotNull + private DistributionSet distributionSet; + private boolean dynamic; + @Builder.Default + @NotNull + private Action.ActionType actionType = Action.ActionType.FORCED; + private Long forcedTime; + private Long startAt; + @Min(Action.WEIGHT_MIN) + @Max(Action.WEIGHT_MAX) + private Integer weight; + } + + @SuperBuilder + @Getter + @EqualsAndHashCode(callSuper = true) + @ToString(callSuper = true) + final class Update extends UpdateCreate implements Identifiable { + + @NotNull + private Long id; + } + + @SuperBuilder + @Getter + class UpdateCreate { + + @ValidString + @Size(min = 1, max = NamedEntity.NAME_MAX_SIZE) + @NotNull(groups = Create.class) + private String name; + @ValidString + @Size(max = NamedEntity.DESCRIPTION_MAX_SIZE) + private String description; + } + + @Getter + class GroupCreate { + + @ValidString + @Size(min = 1, max = NamedEntity.NAME_MAX_SIZE) + @NotNull + private final String name; + @ValidString + @Size(max = NamedEntity.DESCRIPTION_MAX_SIZE) + private final String description; + @ValidString + @Size(min = 1, max = TargetFilterQuery.QUERY_MAX_SIZE) + private final String targetFilterQuery; + private final Float targetPercentage; + private final boolean confirmationRequired; + + // Conditions and actions for the rollout group + private final RolloutGroup.RolloutGroupSuccessCondition successCondition; + private final String successConditionExp; + private final RolloutGroup.RolloutGroupSuccessAction successAction; + private final String successActionExp; + private final RolloutGroup.RolloutGroupErrorCondition errorCondition; + private final String errorConditionExp; + private final RolloutGroup.RolloutGroupErrorAction errorAction; + private final String errorActionExp; + + private GroupCreate( + final String name, final String description, final String targetFilterQuery, final Float targetPercentage, + final RolloutGroupConditions conditions, final boolean confirmationRequired) { + this.name = name; + this.description = description; + this.targetFilterQuery = targetFilterQuery; + this.targetPercentage = targetPercentage; + + this.successCondition = conditions.getSuccessCondition(); + this.successConditionExp = conditions.getSuccessConditionExp(); + this.successAction = conditions.getSuccessAction(); + this.successActionExp = conditions.getSuccessActionExp(); + this.errorCondition = conditions.getErrorCondition(); + this.errorConditionExp = conditions.getErrorConditionExp(); + this.errorAction = conditions.getErrorAction(); + this.errorActionExp = conditions.getErrorActionExp(); + + this.confirmationRequired = confirmationRequired; + } + + public static GroupCreateBuilder builder() { + return new GroupCreateBuilder(); + } + + @Setter + @Accessors(fluent = true) + public static class GroupCreateBuilder { + + private String name; + private String description; + private String targetFilterQuery; + private Float targetPercentage; + private RolloutGroupConditions conditions; + private boolean confirmationRequired; + + public GroupCreate build() { + return new GroupCreate( + name, description, targetFilterQuery, targetPercentage, + conditions == null ? new RolloutGroupConditionBuilder().withDefaults().build() : conditions, + confirmationRequired); + } + } + } + + /** + * Builder to create a new dynamic rollout group secret + */ + @Data + @Builder + class DynamicRolloutGroupTemplate { + + /** + * The name suffix, by default "" is used. + */ + @NotNull + private String nameSuffix = ""; + + /** + * The count of matching Targets that should be assigned to this Group + */ + private long targetCount; + + /** + * The group conditions + */ + private RolloutGroupConditions conditions; + + /** + * If confirmation is required for this rollout group (considered with confirmation flow active) + */ + private boolean confirmationRequired; + } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/ActionStatusBuilder.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/ActionStatusBuilder.java deleted file mode 100644 index f8634cfad..000000000 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/ActionStatusBuilder.java +++ /dev/null @@ -1,25 +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.ActionStatus; - -/** - * Builder for {@link ActionStatus}. - */ -@FunctionalInterface -public interface ActionStatusBuilder { - - /** - * @param actionId the status is for - * @return create builder - */ - ActionStatusCreate create(long actionId); -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/ActionStatusCreate.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/ActionStatusCreate.java deleted file mode 100644 index bbf9a8df5..000000000 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/ActionStatusCreate.java +++ /dev/null @@ -1,57 +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.Collection; - -import jakarta.validation.constraints.NotNull; - -import org.eclipse.hawkbit.repository.model.Action.Status; -import org.eclipse.hawkbit.repository.model.ActionStatus; -import org.eclipse.hawkbit.repository.model.BaseEntity; - -/** - * Builder to create a new {@link ActionStatus} 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 ActionStatusCreate { - - /** - * @param status {@link ActionStatus#getStatus()} - * @return updated {@link ActionStatusCreate} object - */ - ActionStatusCreate status(@NotNull Status status); - - /** - * @param occurredAt for {@link ActionStatus#getOccurredAt()} - * @return updated {@link ActionStatusCreate} object - */ - ActionStatusCreate occurredAt(long occurredAt); - - ActionStatusCreate code(int code); - - /** - * @param messages for {@link ActionStatus#getMessages()} - * @return updated {@link ActionStatusCreate} object - */ - ActionStatusCreate messages(Collection messages); - - /** - * @param message for {@link ActionStatus#getMessages()} - * @return updated {@link ActionStatusCreate} object - */ - ActionStatusCreate message(String message); - - /** - * @return peek on current state of {@link ActionStatus} in the builder - */ - ActionStatus build(); -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/DynamicRolloutGroupTemplate.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/DynamicRolloutGroupTemplate.java deleted file mode 100644 index 67f557373..000000000 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/DynamicRolloutGroupTemplate.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright (c) 2024 Contributors to the Eclipse Foundation - * - * 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.NotNull; - -import lombok.Builder; -import lombok.Data; -import org.eclipse.hawkbit.repository.model.RolloutGroupConditions; - -/** - * Builder to create a new dynamic rollout group secret - */ -@Data -@Builder -public class DynamicRolloutGroupTemplate { - - /** - * The name suffix, by default "" is used. - */ - @NotNull - private String nameSuffix = ""; - - /** - * The count of matching Targets that should be assigned to this Group - */ - private long targetCount; - - /** - * The group conditions - */ - private RolloutGroupConditions conditions; - - /** - * If confirmation is required for this rollout group (considered with confirmation flow active) - */ - private boolean confirmationRequired; -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/RolloutBuilder.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/RolloutBuilder.java deleted file mode 100644 index 627998dfa..000000000 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/RolloutBuilder.java +++ /dev/null @@ -1,29 +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.Rollout; - -/** - * Builder for {@link Rollout}. - */ -public interface RolloutBuilder { - - /** - * @param id of the updatable entity - * @return builder instance - */ - RolloutUpdate update(long id); - - /** - * @return builder instance - */ - RolloutCreate create(); -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/RolloutCreate.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/RolloutCreate.java deleted file mode 100644 index 134b2be22..000000000 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/RolloutCreate.java +++ /dev/null @@ -1,118 +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.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.Rollout; -import org.eclipse.hawkbit.repository.model.TargetFilterQuery; - -/** - * Builder to create a new {@link Rollout} 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 RolloutCreate { - - /** - * Set name - * - * @param name for {@link Rollout#getName()} - * @return updated builder instance - */ - RolloutCreate name(@Size(min = 1, max = NamedEntity.NAME_MAX_SIZE) @NotNull String name); - - /** - * Set description - * - * @param description for {@link Rollout#getDescription()} - * @return updated builder instance - */ - RolloutCreate description(@Size(max = NamedEntity.DESCRIPTION_MAX_SIZE) String description); - - /** - * Set the {@link DistributionSet} - * - * @param set for {@link Rollout#getDistributionSet()} - * @return updated builder instance - */ - default RolloutCreate distributionSetId(final DistributionSet set) { - return distributionSetId(Optional.ofNullable(set).map(DistributionSet::getId).orElse(null)); - } - - /** - * Set the id of the {@link DistributionSet} - * - * @param distributionSetId for {@link Rollout#getDistributionSet()} - * @return updated builder instance - */ - RolloutCreate distributionSetId(long distributionSetId); - - /** - * Set the {@link TargetFilterQuery} - * - * @param targetFilterQuery for {@link Rollout#getTargetFilterQuery()} - * @return updated builder instance - */ - RolloutCreate targetFilterQuery( - @Size(min = 1, max = TargetFilterQuery.QUERY_MAX_SIZE) @NotNull String targetFilterQuery); - - /** - * Set the {@link ActionType} - * - * @param actionType for {@link Rollout#getActionType()} - * @return updated builder instance - */ - RolloutCreate actionType(@NotNull ActionType actionType); - - /** - * Set the forcedTime of the resulting {@link org.eclipse.hawkbit.repository.model.Action}s - * - * @param forcedTime for {@link Rollout#getForcedTime()} - * @return updated builder instance - */ - RolloutCreate forcedTime(Long forcedTime); - - /** - * Set the weight of the resulting {@link org.eclipse.hawkbit.repository.model.Action}s - * - * @param weight for {@link Rollout#getWeight()} - * @return updated builder instance - */ - RolloutCreate weight(Integer weight); - - /** - * Set if the rollout shall be dynamic - * - * @param dynamic for {@link Rollout#isDynamic()} - * @return updated builder instance - */ - RolloutCreate dynamic(boolean dynamic); - - /** - * Set start at - * - * @param startAt for {@link Rollout#getStartAt()} - * @return updated builder instance - */ - RolloutCreate startAt(Long startAt); - - /** - * @return peek on current state of {@link Rollout} in the builder - */ - Rollout build(); -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/RolloutGroupBuilder.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/RolloutGroupBuilder.java deleted file mode 100644 index 90f62f746..000000000 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/RolloutGroupBuilder.java +++ /dev/null @@ -1,24 +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.Rollout; - -/** - * Builder for {@link Rollout}. - */ -@FunctionalInterface -public interface RolloutGroupBuilder { - - /** - * @return builder instance - */ - RolloutGroupCreate create(); -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/RolloutGroupCreate.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/RolloutGroupCreate.java deleted file mode 100644 index df7f433f3..000000000 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/RolloutGroupCreate.java +++ /dev/null @@ -1,72 +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.NotNull; -import jakarta.validation.constraints.Size; - -import org.eclipse.hawkbit.repository.model.BaseEntity; -import org.eclipse.hawkbit.repository.model.NamedEntity; -import org.eclipse.hawkbit.repository.model.Rollout; -import org.eclipse.hawkbit.repository.model.RolloutGroup; -import org.eclipse.hawkbit.repository.model.RolloutGroupConditionBuilder; -import org.eclipse.hawkbit.repository.model.RolloutGroupConditions; -import org.eclipse.hawkbit.repository.model.TargetFilterQuery; - -/** - * Builder to create a new {@link RolloutGroup} 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 RolloutGroupCreate { - - /** - * @param name for {@link Rollout#getName()} - * @return updated builder instance - */ - RolloutGroupCreate name(@Size(min = 1, max = NamedEntity.NAME_MAX_SIZE) @NotNull String name); - - /** - * @param description for {@link Rollout#getDescription()} - * @return updated builder instance - */ - RolloutGroupCreate description(@Size(max = NamedEntity.DESCRIPTION_MAX_SIZE) String description); - - /** - * @param targetFilterQuery for {@link Rollout#getTargetFilterQuery()} - * @return updated builder instance - */ - RolloutGroupCreate targetFilterQuery( - @Size(min = 1, max = TargetFilterQuery.QUERY_MAX_SIZE) @NotNull String targetFilterQuery); - - /** - * @param targetPercentage the percentage of matching Targets that should be assigned to this Group - * @return updated builder instance - */ - RolloutGroupCreate targetPercentage(Float targetPercentage); - - /** - * @param conditions as created by {@link RolloutGroupConditionBuilder}. - * @return updated builder instance - */ - RolloutGroupCreate conditions(RolloutGroupConditions conditions); - - /** - * @param confirmationRequired if confirmation is required for this rollout group (considered - * with confirmation flow active) - * @return updated builder instance - */ - RolloutGroupCreate confirmationRequired(boolean confirmationRequired); - - /** - * @return peek on current state of {@link RolloutGroup} in the builder - */ - RolloutGroup build(); -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/RolloutUpdate.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/RolloutUpdate.java deleted file mode 100644 index cb5c677dc..000000000 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/RolloutUpdate.java +++ /dev/null @@ -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 jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; - -import org.eclipse.hawkbit.repository.model.NamedEntity; -import org.eclipse.hawkbit.repository.model.Rollout; - -/** - * Builder to update an existing {@link Rollout} entry. Defines all fields that - * can be updated. - */ -public interface RolloutUpdate { - - /** - * Set name of the {@link Rollout} - * - * @param name for {@link Rollout#getName()} - * @return updated builder instance - */ - RolloutUpdate name(@Size(min = 1, max = NamedEntity.NAME_MAX_SIZE) @NotNull String name); - - /** - * Set description of the {@link Rollout} - * - * @param description for {@link Rollout#getDescription()} - * @return updated builder instance - */ - RolloutUpdate description(@Size(max = NamedEntity.DESCRIPTION_MAX_SIZE) String description); -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Action.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Action.java index 3be04a175..a1cc0c508 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Action.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Action.java @@ -10,10 +10,16 @@ package org.eclipse.hawkbit.repository.model; import java.time.ZonedDateTime; +import java.util.Collection; import java.util.Optional; import java.util.concurrent.TimeUnit; import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; + +import lombok.Builder; +import lombok.Getter; +import org.eclipse.hawkbit.repository.ValidString; /** * Update operations to be executed by the target. @@ -338,4 +344,17 @@ public interface Action extends TenantAwareBaseEntity { DOWNLOAD_ONLY } + @Getter + @Builder + class ActionStatusCreate { + + private long actionId; + + @NotNull + private Status status; + private Integer code; + private Collection<@ValidString String> messages; + + private Long occurredAt; + } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/RolloutGroupConditionBuilder.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/RolloutGroupConditionBuilder.java index 6ec62c08b..3d5767d2e 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/RolloutGroupConditionBuilder.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/RolloutGroupConditionBuilder.java @@ -94,4 +94,4 @@ public class RolloutGroupConditionBuilder { errorAction(RolloutGroupErrorAction.PAUSE, ""); return this; } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractActionStatusCreate.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractActionStatusCreate.java deleted file mode 100644 index 264a23866..000000000 --- a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractActionStatusCreate.java +++ /dev/null @@ -1,75 +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.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.Optional; -import java.util.stream.Collectors; - -import lombok.Getter; -import org.eclipse.hawkbit.repository.ValidString; -import org.eclipse.hawkbit.repository.model.Action.Status; - -/** - * Create and update builder DTO. - * - * @param update or create builder interface - */ -public abstract class AbstractActionStatusCreate { - - protected Status status; - protected Long occurredAt; - protected Integer code; - protected List<@ValidString String> messages; - @Getter - protected Long actionId; - - public T status(final Status status) { - this.status = status; - return (T) this; - } - - public T occurredAt(final long occurredAt) { - this.occurredAt = occurredAt; - return (T) this; - } - - public T code(final int code) { - this.code = code; - return (T) this; - } - - public T messages(final Collection messages) { - if (this.messages == null) { - // create modifiable list - this.messages = messages.stream().filter(Objects::nonNull).map(String::strip).collect(Collectors.toCollection(ArrayList::new)); - } else { - this.messages.addAll(messages.stream().filter(Objects::nonNull).map(String::strip).toList()); - } - return (T) this; - } - - public T message(final String message) { - if (message != null) { - if (this.messages == null) { - this.messages = new ArrayList<>(); - } - this.messages.add(message.strip()); - } - return (T) this; - } - - public Optional getOccurredAt() { - return Optional.ofNullable(occurredAt); - } -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractBaseEntityBuilder.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractBaseEntityBuilder.java deleted file mode 100644 index c32ac848d..000000000 --- a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractBaseEntityBuilder.java +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.builder; - -import org.eclipse.hawkbit.repository.Identifiable; - -public abstract class AbstractBaseEntityBuilder implements Identifiable { - - protected Long id; - - @Override - public Long getId() { - return id; - } - - static String strip(final String value) { - return value == null ? null : value.strip(); - } -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractNamedEntityBuilder.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractNamedEntityBuilder.java deleted file mode 100644 index a1ef731c0..000000000 --- a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractNamedEntityBuilder.java +++ /dev/null @@ -1,40 +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 org.eclipse.hawkbit.repository.ValidString; - -public abstract class AbstractNamedEntityBuilder extends AbstractBaseEntityBuilder { - - @ValidString - protected String name; - @ValidString - protected String description; - - public T name(final String name) { - this.name = AbstractBaseEntityBuilder.strip(name); - return (T) this; - } - - public T description(final String description) { - this.description = AbstractBaseEntityBuilder.strip(description); - return (T) this; - } - - public Optional getName() { - return Optional.ofNullable(name); - } - - public Optional getDescription() { - return Optional.ofNullable(description); - } -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractRolloutGroupCreate.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractRolloutGroupCreate.java deleted file mode 100644 index 9ae1a3f0b..000000000 --- a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractRolloutGroupCreate.java +++ /dev/null @@ -1,47 +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.ValidString; -import org.eclipse.hawkbit.repository.model.RolloutGroupConditions; - -/** - * Create builder DTO. - * - * @param update or create builder interface - */ -public abstract class AbstractRolloutGroupCreate extends AbstractNamedEntityBuilder { - - @ValidString - protected String targetFilterQuery; - protected Float targetPercentage; - protected RolloutGroupConditions conditions; - protected boolean confirmationRequired; - - public T targetFilterQuery(final String targetFilterQuery) { - this.targetFilterQuery = AbstractBaseEntityBuilder.strip(targetFilterQuery); - return (T) this; - } - - public T targetPercentage(final Float targetPercentage) { - this.targetPercentage = targetPercentage; - return (T) this; - } - - public T conditions(final RolloutGroupConditions conditions) { - this.conditions = conditions; - return (T) this; - } - - public T confirmationRequired(final boolean confirmationRequired) { - this.confirmationRequired = confirmationRequired; - return (T) this; - } -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/GenericRolloutUpdate.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/GenericRolloutUpdate.java deleted file mode 100644 index 29716f9fc..000000000 --- a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/GenericRolloutUpdate.java +++ /dev/null @@ -1,20 +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 GenericRolloutUpdate extends AbstractNamedEntityBuilder implements RolloutUpdate { - - public GenericRolloutUpdate(final Long id) { - super.id = id; - } -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaEntityFactory.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaEntityFactory.java deleted file mode 100644 index 6c3a23701..000000000 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaEntityFactory.java +++ /dev/null @@ -1,47 +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; - -import org.eclipse.hawkbit.repository.EntityFactory; -import org.eclipse.hawkbit.repository.builder.ActionStatusBuilder; -import org.eclipse.hawkbit.repository.builder.RolloutBuilder; -import org.eclipse.hawkbit.repository.builder.RolloutGroupBuilder; -import org.eclipse.hawkbit.repository.jpa.builder.JpaActionStatusBuilder; -import org.eclipse.hawkbit.repository.jpa.builder.JpaRolloutGroupBuilder; -import org.springframework.validation.annotation.Validated; - -/** - * JPA Implementation of {@link EntityFactory}. - */ -@Validated -public class JpaEntityFactory implements EntityFactory { - - private final RolloutBuilder rolloutBuilder; - - @SuppressWarnings("java:S107") - public JpaEntityFactory(final RolloutBuilder rolloutBuilder) { - this.rolloutBuilder = rolloutBuilder; - } - - @Override - public ActionStatusBuilder actionStatus() { - return new JpaActionStatusBuilder(); - } - - @Override - public RolloutGroupBuilder rolloutGroup() { - return new JpaRolloutGroupBuilder(); - } - - @Override - public RolloutBuilder rollout() { - return rolloutBuilder; - } -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRepositoryConfiguration.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRepositoryConfiguration.java index 9b29ac052..02e1dad0c 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRepositoryConfiguration.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRepositoryConfiguration.java @@ -21,8 +21,6 @@ import io.micrometer.core.instrument.MeterRegistry; import org.aopalliance.intercept.MethodInvocation; import org.eclipse.hawkbit.ContextAware; import org.eclipse.hawkbit.repository.DeploymentManagement; -import org.eclipse.hawkbit.repository.DistributionSetManagement; -import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.PropertiesQuotaManagement; import org.eclipse.hawkbit.repository.QuotaManagement; import org.eclipse.hawkbit.repository.RepositoryConfiguration; @@ -41,7 +39,6 @@ import org.eclipse.hawkbit.repository.artifact.encryption.ArtifactEncryption; import org.eclipse.hawkbit.repository.artifact.encryption.ArtifactEncryptionSecretsStore; import org.eclipse.hawkbit.repository.artifact.encryption.ArtifactEncryptionService; import org.eclipse.hawkbit.repository.autoassign.AutoAssignExecutor; -import org.eclipse.hawkbit.repository.builder.RolloutBuilder; import org.eclipse.hawkbit.repository.event.ApplicationEventFilter; import org.eclipse.hawkbit.repository.event.remote.EventEntityManager; import org.eclipse.hawkbit.repository.event.remote.EventEntityManagerHolder; @@ -53,7 +50,6 @@ import org.eclipse.hawkbit.repository.jpa.autoassign.AutoAssignScheduler; import org.eclipse.hawkbit.repository.jpa.autocleanup.AutoActionCleanup; import org.eclipse.hawkbit.repository.jpa.autocleanup.AutoCleanupScheduler; import org.eclipse.hawkbit.repository.jpa.autocleanup.CleanupTask; -import org.eclipse.hawkbit.repository.jpa.builder.JpaRolloutBuilder; import org.eclipse.hawkbit.repository.jpa.cluster.DistributedLockRepository; import org.eclipse.hawkbit.repository.jpa.cluster.LockProperties; import org.eclipse.hawkbit.repository.jpa.event.JpaEventEntityManager; @@ -92,8 +88,6 @@ import org.eclipse.hawkbit.repository.jpa.rollout.condition.StartNextGroupRollou import org.eclipse.hawkbit.repository.jpa.rollout.condition.ThresholdRolloutGroupErrorCondition; import org.eclipse.hawkbit.repository.jpa.rollout.condition.ThresholdRolloutGroupSuccessCondition; import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility; -import org.eclipse.hawkbit.repository.model.DistributionSet; -import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.Target; @@ -297,15 +291,6 @@ public class JpaRepositoryConfiguration { return e -> e instanceof TargetPollEvent && !repositoryProperties.isPublishTargetPollEvent(); } - /** - * @param distributionSetManagement for loading {@link Rollout#getDistributionSet()} - * @return RolloutBuilder bean - */ - @Bean - RolloutBuilder rolloutBuilder(final DistributionSetManagement distributionSetManagement) { - return new JpaRolloutBuilder(distributionSetManagement); - } - /** * @return the {@link SystemSecurityContext} singleton bean which make it * accessible in beans which cannot access the service directly, e.g. @@ -409,17 +394,6 @@ public class JpaRepositoryConfiguration { return new DefaultRolloutApprovalStrategy(userAuthoritiesResolver, tenantConfigurationManagement, systemSecurityContext); } - /** - * {@link JpaEntityFactory} bean. - * - * @return a new {@link EntityFactory} - */ - @Bean - @ConditionalOnMissingBean - EntityFactory entityFactory(final RolloutBuilder rolloutBuilder) { - return new JpaEntityFactory(rolloutBuilder); - } - /** * {@link EventEntityManagerHolder} bean. * diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutExecutor.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutExecutor.java index 486e98943..9cfd51c1f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutExecutor.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutExecutor.java @@ -9,8 +9,6 @@ */ package org.eclipse.hawkbit.repository.jpa; -import static org.eclipse.hawkbit.repository.jpa.builder.JpaRolloutGroupCreate.addSuccessAndErrorConditionsAndActions; - import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Proxy; import java.util.Collection; @@ -719,7 +717,7 @@ public class JpaRolloutExecutor implements RolloutExecutor { group.setTargetPercentage(lastGroup.isDynamic() ? lastGroup.getTargetPercentage() : lastGroup.getTotalTargets()); group.setTargetFilterQuery(lastGroup.getTargetFilterQuery()); - addSuccessAndErrorConditionsAndActions(group, lastGroup.getSuccessCondition(), + JpaRolloutManagement.addSuccessAndErrorConditionsAndActions(group, lastGroup.getSuccessCondition(), lastGroup.getSuccessConditionExp(), lastGroup.getSuccessAction(), lastGroup.getSuccessActionExp(), lastGroup.getErrorCondition(), lastGroup.getErrorConditionExp(), lastGroup.getErrorAction(), diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaActionStatusBuilder.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaActionStatusBuilder.java deleted file mode 100644 index eb93944ff..000000000 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaActionStatusBuilder.java +++ /dev/null @@ -1,25 +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.builder.ActionStatusBuilder; -import org.eclipse.hawkbit.repository.builder.ActionStatusCreate; -import org.eclipse.hawkbit.repository.model.ActionStatus; - -/** - * Builder implementation for {@link ActionStatus}. - */ -public class JpaActionStatusBuilder implements ActionStatusBuilder { - - @Override - public ActionStatusCreate create(final long actionId) { - return new JpaActionStatusCreate(actionId); - } -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaActionStatusCreate.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaActionStatusCreate.java deleted file mode 100644 index a3a27b5df..000000000 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaActionStatusCreate.java +++ /dev/null @@ -1,36 +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.builder.AbstractActionStatusCreate; -import org.eclipse.hawkbit.repository.builder.ActionStatusCreate; -import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus; - -/** - * Create/build implementation. - */ -public class JpaActionStatusCreate extends AbstractActionStatusCreate implements ActionStatusCreate { - - JpaActionStatusCreate(final Long actionId) { - super.actionId = actionId; - } - - @Override - public JpaActionStatus build() { - final JpaActionStatus result = new JpaActionStatus(status, getOccurredAt().orElse(System.currentTimeMillis())); - if (messages != null) { - messages.forEach(result::addMessage); - } - if (code != null) { - result.setCode(code); - } - return result; - } -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaRolloutBuilder.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaRolloutBuilder.java deleted file mode 100644 index 1f4638ac0..000000000 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaRolloutBuilder.java +++ /dev/null @@ -1,40 +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.GenericRolloutUpdate; -import org.eclipse.hawkbit.repository.builder.RolloutBuilder; -import org.eclipse.hawkbit.repository.builder.RolloutCreate; -import org.eclipse.hawkbit.repository.builder.RolloutUpdate; -import org.eclipse.hawkbit.repository.model.DistributionSet; -import org.eclipse.hawkbit.repository.model.Rollout; - -/** - * Builder implementation for {@link Rollout}. - */ -public class JpaRolloutBuilder implements RolloutBuilder { - - private final DistributionSetManagement distributionSetManagement; - - public JpaRolloutBuilder(final DistributionSetManagement distributionSetManagement) { - this.distributionSetManagement = distributionSetManagement; - } - - @Override - public RolloutUpdate update(final long id) { - return new GenericRolloutUpdate(id); - } - - @Override - public RolloutCreate create() { - return new JpaRolloutCreate(distributionSetManagement); - } -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaRolloutCreate.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaRolloutCreate.java deleted file mode 100644 index 0e9f9f63d..000000000 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaRolloutCreate.java +++ /dev/null @@ -1,150 +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 java.util.Optional; - -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Min; - -import org.eclipse.hawkbit.repository.DistributionSetManagement; -import org.eclipse.hawkbit.repository.ValidString; -import org.eclipse.hawkbit.repository.builder.AbstractNamedEntityBuilder; -import org.eclipse.hawkbit.repository.builder.RolloutCreate; -import org.eclipse.hawkbit.repository.jpa.model.JpaRollout; -import org.eclipse.hawkbit.repository.model.Action; -import org.eclipse.hawkbit.repository.model.DistributionSet; - -public class JpaRolloutCreate extends AbstractNamedEntityBuilder implements RolloutCreate { - - protected Long distributionSetId; - @ValidString - protected String targetFilterQuery; - protected Action.ActionType actionType; - protected Long forcedTime; - protected Long startAt; - @Min(Action.WEIGHT_MIN) - @Max(Action.WEIGHT_MAX) - protected Integer weight; - private final DistributionSetManagement distributionSetManagement; - private boolean dynamic; - - JpaRolloutCreate(final DistributionSetManagement distributionSetManagement) { - this.distributionSetManagement = distributionSetManagement; - } - - public RolloutCreate distributionSetId(final long distributionSetId) { - this.distributionSetId = distributionSetId; - return this; - } - - /** - * Filter of the rollout - * - * @param targetFilterQuery query - * @return this builder - */ - public RolloutCreate targetFilterQuery(final String targetFilterQuery) { - this.targetFilterQuery = targetFilterQuery == null ? null : targetFilterQuery.strip(); - return this; - } - - /** - * {@link Action.ActionType} used for {@link Action}s - * - * @param actionType type - * @return this builder - */ - public RolloutCreate actionType(final Action.ActionType actionType) { - this.actionType = actionType; - return this; - } - - /** - * forcedTime used for {@link Action}s - * - * @param forcedTime time - * @return this builder - */ - public RolloutCreate forcedTime(final Long forcedTime) { - this.forcedTime = forcedTime; - return this; - } - - /** - * weight used for {@link Action}s - * - * @param weight weight - * @return this builder - */ - public RolloutCreate weight(final Integer weight) { - this.weight = weight; - return this; - } - - public RolloutCreate dynamic(final boolean dynamic) { - this.dynamic = dynamic; - return this; - } - - /** - * Set start of the Rollout - * - * @param startAt start time point - * @return this builder - */ - public RolloutCreate startAt(final Long startAt) { - this.startAt = startAt; - return this; - } - - @Override - public JpaRollout build() { - final JpaRollout rollout = new JpaRollout(); - - rollout.setName(name); - rollout.setDescription(description); - rollout.setDistributionSet(distributionSetManagement.getValidAndComplete(distributionSetId)); - rollout.setTargetFilterQuery(targetFilterQuery); - rollout.setStartAt(startAt); - rollout.setWeight(weight); - rollout.setDynamic(dynamic); - - if (actionType != null) { - rollout.setActionType(actionType); - } - - if (forcedTime != null) { - rollout.setForcedTime(forcedTime); - } - - return rollout; - } - - public Optional getDistributionSetId() { - return Optional.ofNullable(distributionSetId); - } - - public Optional getActionType() { - return Optional.ofNullable(actionType); - } - - public Optional getForcedTime() { - return Optional.ofNullable(forcedTime); - } - - public Optional getWeight() { - return Optional.ofNullable(weight); - } - - public Optional getStartAt() { - return Optional.ofNullable(startAt); - } -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaRolloutGroupBuilder.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaRolloutGroupBuilder.java deleted file mode 100644 index 742ffbd95..000000000 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaRolloutGroupBuilder.java +++ /dev/null @@ -1,25 +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.builder.RolloutGroupBuilder; -import org.eclipse.hawkbit.repository.builder.RolloutGroupCreate; -import org.eclipse.hawkbit.repository.model.RolloutGroup; - -/** - * Builder implementation for {@link RolloutGroup}. - */ -public class JpaRolloutGroupBuilder implements RolloutGroupBuilder { - - @Override - public RolloutGroupCreate create() { - return new JpaRolloutGroupCreate(); - } -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaRolloutGroupCreate.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaRolloutGroupCreate.java deleted file mode 100644 index 107f696ab..000000000 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaRolloutGroupCreate.java +++ /dev/null @@ -1,77 +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.builder.AbstractRolloutGroupCreate; -import org.eclipse.hawkbit.repository.builder.RolloutGroupCreate; -import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup; -import org.eclipse.hawkbit.repository.model.RolloutGroup; -import org.eclipse.hawkbit.repository.model.RolloutGroupConditions; - -public class JpaRolloutGroupCreate extends AbstractRolloutGroupCreate implements RolloutGroupCreate { - - /** - * Set the Success And Error conditions for the rollout group - * - * @param group The Rollout group - * @param conditions The Rollout Success and Error Conditions - */ - public static void addSuccessAndErrorConditionsAndActions(final JpaRolloutGroup group, - final RolloutGroupConditions conditions) { - addSuccessAndErrorConditionsAndActions(group, conditions.getSuccessCondition(), - conditions.getSuccessConditionExp(), conditions.getSuccessAction(), conditions.getSuccessActionExp(), - conditions.getErrorCondition(), conditions.getErrorConditionExp(), conditions.getErrorAction(), - conditions.getErrorActionExp()); - } - - /** - * Set the Success And Error conditions for the rollout group - */ - @SuppressWarnings("java:S107") - public static void addSuccessAndErrorConditionsAndActions(final JpaRolloutGroup group, - final RolloutGroup.RolloutGroupSuccessCondition successCondition, final String successConditionExp, - final RolloutGroup.RolloutGroupSuccessAction successAction, final String successActionExp, - final RolloutGroup.RolloutGroupErrorCondition errorCondition, final String errorConditionExp, - final RolloutGroup.RolloutGroupErrorAction errorAction, final String errorActionExp) { - group.setSuccessCondition(successCondition); - group.setSuccessConditionExp(successConditionExp); - - group.setSuccessAction(successAction); - group.setSuccessActionExp(successActionExp); - - group.setErrorCondition(errorCondition); - group.setErrorConditionExp(errorConditionExp); - - group.setErrorAction(errorAction); - group.setErrorActionExp(errorActionExp); - } - - @Override - public JpaRolloutGroup build() { - final JpaRolloutGroup group = new JpaRolloutGroup(); - - group.setName(name); - group.setDescription(description); - group.setTargetFilterQuery(targetFilterQuery); - - if (targetPercentage == null) { - targetPercentage = 100F; - } - - group.setTargetPercentage(targetPercentage); - - if (conditions != null) { - addSuccessAndErrorConditionsAndActions(group, conditions); - } - group.setConfirmationRequired(confirmationRequired); - - return group; - } -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaActionManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaActionManagement.java index 72436052b..52774ecd8 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaActionManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaActionManagement.java @@ -15,13 +15,13 @@ import static org.eclipse.hawkbit.repository.model.Action.Status.FINISHED; import java.util.Comparator; import java.util.List; +import java.util.Optional; import java.util.stream.Stream; import lombok.extern.slf4j.Slf4j; import org.eclipse.hawkbit.repository.QuotaManagement; import org.eclipse.hawkbit.repository.RepositoryProperties; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; -import org.eclipse.hawkbit.repository.jpa.builder.JpaActionStatusCreate; import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity_; import org.eclipse.hawkbit.repository.jpa.model.JpaAction; import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus; @@ -31,6 +31,7 @@ import org.eclipse.hawkbit.repository.jpa.repository.ActionStatusRepository; import org.eclipse.hawkbit.repository.jpa.specifications.ActionSpecifications; import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; import org.eclipse.hawkbit.repository.model.Action; +import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate; import org.eclipse.hawkbit.repository.model.ActionStatus; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.springframework.data.domain.PageRequest; @@ -64,22 +65,30 @@ public class JpaActionManagement { return DOWNLOAD_ONLY == action.getActionType(); } + protected static JpaActionStatus buildJpaActionStatus(final ActionStatusCreate create) { + final JpaActionStatus actionStatus = new JpaActionStatus( + create.getStatus(), + Optional.ofNullable(create.getOccurredAt()).orElseGet(System::currentTimeMillis)); + Optional.ofNullable(create.getMessages()).ifPresent(messages -> messages.forEach(actionStatus::addMessage)); + actionStatus.setCode(create.getCode()); + return actionStatus; + } + protected List findActiveActionsHavingStatus(final String controllerId, final Action.Status status) { return actionRepository.findAll(ActionSpecifications.byTargetControllerIdAndIsActiveAndStatus(controllerId, status)); } - protected Action addActionStatus(final JpaActionStatusCreate statusCreate) { - final Long actionId = statusCreate.getActionId(); - final JpaActionStatus actionStatus = statusCreate.build(); + protected Action addActionStatus(final ActionStatusCreate create) { + final Long actionId = create.getActionId(); final JpaAction action = getActionAndThrowExceptionIfNotFound(actionId); - if (isUpdatingActionStatusAllowed(action, actionStatus)) { - return handleAddUpdateActionStatus(actionStatus, action); + if (isUpdatingActionStatusAllowed(action, create)) { + return handleAddUpdateActionStatus(create, action); } log.debug( "Update of actionStatus {} for action {} not possible since action not active anymore and not allowed as an action terminating.", - actionStatus.getStatus(), action.getId()); + create.getStatus(), action.getId()); return action; } @@ -91,7 +100,7 @@ public class JpaActionManagement { // can be overwritten to intercept the persistence of the action status } - protected void assertActionStatusQuota(final JpaActionStatus newActionStatus, final JpaAction action) { + protected void assertActionStatusQuota(final ActionStatusCreate newActionStatus, final JpaAction action) { if (isIntermediateStatus(newActionStatus)) {// check for quota only for intermediate statuses QuotaHelper.assertAssignmentQuota(action.getId(), 1, quotaManagement.getMaxStatusEntriesPerAction(), ActionStatus.class, Action.class, actionStatusRepository::countByActionId); @@ -123,7 +132,7 @@ public class JpaActionManagement { .toList(); } - private static boolean isIntermediateStatus(final JpaActionStatus actionStatus) { + private static boolean isIntermediateStatus(final ActionStatusCreate actionStatus) { return FINISHED != actionStatus.getStatus() && ERROR != actionStatus.getStatus(); } @@ -134,7 +143,7 @@ public class JpaActionManagement { * Status.FINISHED are allowed. In the case of a DOWNLOAD_ONLY action, we accept * status updates only once. */ - private boolean isUpdatingActionStatusAllowed(final JpaAction action, final JpaActionStatus actionStatus) { + private boolean isUpdatingActionStatusAllowed(final JpaAction action, final ActionStatusCreate actionStatus) { if (action.isActive()) { return true; } @@ -151,9 +160,11 @@ public class JpaActionManagement { /** * Sets {@link TargetUpdateStatus} based on given {@link ActionStatus}. */ - private Action handleAddUpdateActionStatus(final JpaActionStatus actionStatus, final JpaAction action) { + private Action handleAddUpdateActionStatus(final ActionStatusCreate create, final JpaAction action) { // information status entry - check for a potential DOS attack - assertActionStatusQuota(actionStatus, action); + assertActionStatusQuota(create, action); + + final JpaActionStatus actionStatus = buildJpaActionStatus(create); assertActionStatusMessageQuota(actionStatus); actionStatus.setAction(action); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaConfirmationManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaConfirmationManagement.java index 4adc7b0e1..3141774a0 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaConfirmationManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaConfirmationManagement.java @@ -9,26 +9,24 @@ */ package org.eclipse.hawkbit.repository.jpa.management; +import static org.eclipse.hawkbit.repository.RepositoryConstants.SERVER_MESSAGE_PREFIX; + import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; import jakarta.persistence.EntityManager; import lombok.extern.slf4j.Slf4j; import org.eclipse.hawkbit.repository.ConfirmationManagement; -import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.QuotaManagement; import org.eclipse.hawkbit.repository.RepositoryConstants; import org.eclipse.hawkbit.repository.RepositoryProperties; -import org.eclipse.hawkbit.repository.builder.ActionStatusCreate; import org.eclipse.hawkbit.repository.exception.AutoConfirmationAlreadyActiveException; import org.eclipse.hawkbit.repository.exception.InvalidConfirmationFeedbackException; import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper; -import org.eclipse.hawkbit.repository.jpa.builder.JpaActionStatusCreate; import org.eclipse.hawkbit.repository.jpa.configuration.Constants; import org.eclipse.hawkbit.repository.jpa.model.JpaAction; import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus; @@ -39,6 +37,8 @@ import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository; import org.eclipse.hawkbit.repository.jpa.repository.ActionStatusRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository; import org.eclipse.hawkbit.repository.model.Action; +import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate; +import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate.ActionStatusCreateBuilder; import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.AutoConfirmationStatus; import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; @@ -62,18 +62,16 @@ import org.springframework.validation.annotation.Validated; public class JpaConfirmationManagement extends JpaActionManagement implements ConfirmationManagement { private final EntityManager entityManager; - private final EntityFactory entityFactory; private final TargetRepository targetRepository; protected JpaConfirmationManagement( final TargetRepository targetRepository, final ActionRepository actionRepository, final ActionStatusRepository actionStatusRepository, final RepositoryProperties repositoryProperties, final QuotaManagement quotaManagement, - final EntityManager entityManager, final EntityFactory entityFactory) { + final EntityManager entityManager) { super(actionRepository, actionStatusRepository, quotaManagement, repositoryProperties); this.targetRepository = targetRepository; this.entityManager = entityManager; - this.entityFactory = entityFactory; } @Override @@ -116,11 +114,8 @@ public class JpaConfirmationManagement extends JpaActionManagement implements Co if (deviceMessages != null) { messages.addAll(deviceMessages); } - messages.add(RepositoryConstants.SERVER_MESSAGE_PREFIX + "Target confirmed action." - + " Therefore, it will be set to the running state to proceed with the deployment."); - final ActionStatusCreate statusCreate = createConfirmationActionStatus(action.getId(), code, messages) - .status(Status.RUNNING); - return addActionStatus((JpaActionStatusCreate) statusCreate); + messages.add(SERVER_MESSAGE_PREFIX + "Target confirmed action. Therefore, it will be set to the running state to proceed with the deployment."); + return addActionStatus(createConfirmationActionStatus(action.getId(), code, messages).status(Status.RUNNING).build()); } @Override @@ -135,10 +130,8 @@ public class JpaConfirmationManagement extends JpaActionManagement implements Co if (deviceMessages != null) { messages.addAll(deviceMessages); } - messages.add(RepositoryConstants.SERVER_MESSAGE_PREFIX + "Target rejected action. Action will stay in confirmation pending state."); - final ActionStatusCreate statusCreate = createConfirmationActionStatus(action.getId(), code, messages) - .status(Status.WAIT_FOR_CONFIRMATION); - return addActionStatus((JpaActionStatusCreate) statusCreate); + messages.add(SERVER_MESSAGE_PREFIX + "Target rejected action. Action will stay in confirmation pending state."); + return addActionStatus(createConfirmationActionStatus(action.getId(), code, messages).status(Status.WAIT_FOR_CONFIRMATION).build()); } @Override @@ -186,14 +179,22 @@ public class JpaConfirmationManagement extends JpaActionManagement implements Co } } - private ActionStatusCreate createConfirmationActionStatus(final long actionId, final Integer code, final Collection messages) { - final ActionStatusCreate statusCreate = entityFactory.actionStatus().create(actionId); - if (!CollectionUtils.isEmpty(messages)) { - statusCreate.messages(messages); - } - if (code != null) { + private ActionStatusCreateBuilder createConfirmationActionStatus( + final long actionId, final Integer code, final Collection messages) { + final ActionStatusCreateBuilder statusCreate = ActionStatusCreate.builder().actionId(actionId); + if (code == null) { + if (!CollectionUtils.isEmpty(messages)) { + statusCreate.messages(messages); + } + } else { statusCreate.code(code); - statusCreate.message(String.format(CONFIRMATION_CODE_MSG_PREFIX, code)); + if (CollectionUtils.isEmpty(messages)) { + statusCreate.messages(List.of(String.format(CONFIRMATION_CODE_MSG_PREFIX, code))); + } else { + final List messagesWithCode = new ArrayList<>(messages); + messagesWithCode.add(String.format(CONFIRMATION_CODE_MSG_PREFIX, code)); + statusCreate.messages(messagesWithCode); + } } return statusCreate; } @@ -209,11 +210,8 @@ public class JpaConfirmationManagement extends JpaActionManagement implements Co log.debug("Auto-confirming action is not necessary, since action {} is in RUNNING state already.", action.getId()); return action; } - final JpaActionStatus actionStatus = (JpaActionStatus) entityFactory.actionStatus() - .create(action.getId()) - .status(Status.RUNNING) - .messages(Collections.singletonList(autoConfirmationStatus.constructActionMessage())) - .build(); + final JpaActionStatus actionStatus = new JpaActionStatus(Status.RUNNING, System.currentTimeMillis()); + actionStatus.addMessage(autoConfirmationStatus.constructActionMessage()); log.debug( "Automatically confirm actionId '{}' due to active auto-confirmation initiated by '{}' and rollouts system user '{}'", action.getId(), autoConfirmationStatus.getInitiator(), autoConfirmationStatus.getCreatedBy()); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java index 540e69c3c..38e8c06f8 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java @@ -49,7 +49,6 @@ import org.eclipse.hawkbit.repository.ConfirmationManagement; import org.eclipse.hawkbit.repository.ControllerManagement; import org.eclipse.hawkbit.repository.DeploymentManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement; -import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.MaintenanceScheduleHelper; import org.eclipse.hawkbit.repository.QuotaManagement; import org.eclipse.hawkbit.repository.RepositoryConstants; @@ -59,7 +58,6 @@ import org.eclipse.hawkbit.repository.SoftwareModuleManagement; import org.eclipse.hawkbit.repository.TargetTypeManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.UpdateMode; -import org.eclipse.hawkbit.repository.builder.ActionStatusCreate; import org.eclipse.hawkbit.repository.event.EventPublisherHolder; import org.eclipse.hawkbit.repository.event.remote.CancelTargetAssignmentEvent; import org.eclipse.hawkbit.repository.event.remote.TargetAttributesRequestedEvent; @@ -70,7 +68,6 @@ import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.InvalidTargetAttributeException; import org.eclipse.hawkbit.repository.jpa.Jpa; import org.eclipse.hawkbit.repository.jpa.acm.AccessController; -import org.eclipse.hawkbit.repository.jpa.builder.JpaActionStatusCreate; import org.eclipse.hawkbit.repository.jpa.configuration.Constants; import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor; import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity_; @@ -91,6 +88,7 @@ import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications; import org.eclipse.hawkbit.repository.jpa.utils.DeploymentHelper; import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; import org.eclipse.hawkbit.repository.model.Action; +import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate; import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.ActionStatus; import org.eclipse.hawkbit.repository.model.AutoConfirmationStatus; @@ -240,17 +238,13 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont @Transactional(isolation = Isolation.READ_COMMITTED) @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public Action addCancelActionStatus(final ActionStatusCreate c) { - final JpaActionStatusCreate create = (JpaActionStatusCreate) c; - + public Action addCancelActionStatus(final ActionStatusCreate create) { final JpaAction action = getActionAndThrowExceptionIfNotFound(create.getActionId()); - if (!action.isCancelingOrCanceled()) { throw new CancelActionNotAllowedException("The action is not in canceling state."); } - final JpaActionStatus actionStatus = create.build(); - + final JpaActionStatus actionStatus = buildJpaActionStatus(create); switch (actionStatus.getStatus()) { case CANCELED, FINISHED: { handleFinishedCancelation(actionStatus, action); @@ -263,7 +257,7 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont } default: { // information status entry - check for a potential DOS attack - assertActionStatusQuota(actionStatus, action); + assertActionStatusQuota(create, action); assertActionStatusMessageQuota(actionStatus); break; } @@ -289,16 +283,15 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont @Transactional @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public ActionStatus addInformationalActionStatus(final ActionStatusCreate c) { - final JpaActionStatusCreate create = (JpaActionStatusCreate) c; + public ActionStatus addInformationalActionStatus(final ActionStatusCreate create) { final JpaAction action = getActionAndThrowExceptionIfNotFound(create.getActionId()); - final JpaActionStatus statusMessage = create.build(); - statusMessage.setAction(action); + assertActionStatusQuota(create, action); - assertActionStatusQuota(statusMessage, action); - assertActionStatusMessageQuota(statusMessage); + final JpaActionStatus actionStatus = buildJpaActionStatus(create); + actionStatus.setAction(action); + assertActionStatusMessageQuota(actionStatus); - return actionStatusRepository.save(statusMessage); + return actionStatusRepository.save(actionStatus); } @Override @@ -306,7 +299,7 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) public Action addUpdateActionStatus(final ActionStatusCreate statusCreate) { - return addActionStatus((JpaActionStatusCreate) statusCreate); + return addActionStatus(statusCreate); } @Override diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java index c80d8eff3..44179a49c 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java @@ -9,16 +9,14 @@ */ package org.eclipse.hawkbit.repository.jpa.management; -import static org.eclipse.hawkbit.repository.jpa.builder.JpaRolloutGroupCreate.addSuccessAndErrorConditionsAndActions; - import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.concurrent.CompletableFuture; import java.util.function.Function; +import java.util.function.UnaryOperator; import java.util.stream.Collectors; import jakarta.validation.ConstraintDeclarationException; @@ -40,19 +38,15 @@ import org.eclipse.hawkbit.repository.RolloutManagement; import org.eclipse.hawkbit.repository.RolloutStatusCache; import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement; -import org.eclipse.hawkbit.repository.builder.DynamicRolloutGroupTemplate; -import org.eclipse.hawkbit.repository.builder.GenericRolloutUpdate; -import org.eclipse.hawkbit.repository.builder.RolloutCreate; -import org.eclipse.hawkbit.repository.builder.RolloutGroupCreate; -import org.eclipse.hawkbit.repository.builder.RolloutUpdate; import org.eclipse.hawkbit.repository.event.EventPublisherHolder; import org.eclipse.hawkbit.repository.event.remote.entity.RolloutGroupCreatedEvent; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException; +import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException; import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException; +import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException; import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException; import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper; -import org.eclipse.hawkbit.repository.jpa.builder.JpaRolloutGroupCreate; import org.eclipse.hawkbit.repository.jpa.configuration.Constants; import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor; import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity_; @@ -80,6 +74,7 @@ import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus; import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus; import org.eclipse.hawkbit.security.SystemSecurityContext; +import org.eclipse.hawkbit.utils.ObjectCopyUtil; import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.dao.ConcurrencyFailureException; import org.springframework.data.domain.Page; @@ -89,7 +84,6 @@ import org.springframework.data.domain.Sort.Direction; import org.springframework.data.jpa.domain.Specification; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; -import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; @@ -181,14 +175,15 @@ public class JpaRolloutManagement implements RolloutManagement { @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) public Rollout create( - final RolloutCreate rollout, final int amountGroup, final boolean confirmationRequired, + final Create rollout, final int amountGroup, final boolean confirmationRequired, final RolloutGroupConditions conditions, final DynamicRolloutGroupTemplate dynamicRolloutGroupTemplate) { return create0(rollout, amountGroup, confirmationRequired, conditions, dynamicRolloutGroupTemplate); } private Rollout create0( - final RolloutCreate rollout, final int amountGroup, final boolean confirmationRequired, + final Create rollout, final int amountGroup, final boolean confirmationRequired, final RolloutGroupConditions conditions, final DynamicRolloutGroupTemplate dynamicRolloutGroupTemplate) { + validateDs(rollout); if (amountGroup < 0) { throw new ValidationException("The amount of groups cannot be lower than or equal to zero for static rollouts"); } else if (amountGroup == 0) { @@ -200,7 +195,9 @@ public class JpaRolloutManagement implements RolloutManagement { RolloutHelper.verifyRolloutGroupAmount(amountGroup, quotaManagement); } - final JpaRollout rolloutRequest = (JpaRollout) rollout.build(); + final JpaRollout rolloutRequest = new JpaRollout(); + ObjectCopyUtil.copy(rollout, rolloutRequest, false, UnaryOperator.identity()); + rolloutRequest.setDynamic(rollout.isDynamic()); // TODO - copy compares isDynamic == false and don't set it to false - remain null // scheduled rollout, the creator shall have permissions to start rollout if (rolloutRequest.getStartAt() != null && rolloutRequest.getStartAt() != Long.MAX_VALUE && // if scheduled rollout !systemSecurityContext.hasPermission(SpPermission.HANDLE_ROLLOUT) && @@ -220,7 +217,7 @@ public class JpaRolloutManagement implements RolloutManagement { @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) public Rollout create( - @NotNull @Valid RolloutCreate create, int amountGroup, boolean confirmationRequired, + @NotNull @Valid Create create, int amountGroup, boolean confirmationRequired, @NotNull RolloutGroupConditions conditions) { return create0(create, amountGroup, confirmationRequired, conditions, null); } @@ -229,29 +226,16 @@ public class JpaRolloutManagement implements RolloutManagement { @Transactional @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public Rollout create(final RolloutCreate rollout, final List groups, final RolloutGroupConditions conditions) { + public Rollout create(final Create rollout, final List groups, final RolloutGroupConditions conditions) { if (groups.isEmpty()) { throw new ValidationException("The amount of groups cannot be 0"); } + validateDs(rollout); RolloutHelper.verifyRolloutGroupAmount(groups.size(), quotaManagement); - return createRolloutGroups(groups, conditions, createRollout((JpaRollout) rollout.build(), false)); - } - - @Override - @Async - public CompletableFuture validateTargetsInGroups( - final List groups, final String targetFilter, final Long createdAt, final Long dsTypeId) { - - final TargetCount targets = calculateTargets(targetFilter, createdAt, dsTypeId); - long totalTargets = targets.total(); - final String baseFilter = targets.filter(); - - if (totalTargets == 0) { - throw new ConstraintDeclarationException("Rollout target filter does not match any targets"); - } - - return CompletableFuture.completedFuture( - validateTargetsInGroups(groups.stream().map(RolloutGroupCreate::build).toList(), baseFilter, totalTargets, dsTypeId)); + final JpaRollout rolloutRequest = new JpaRollout(); + ObjectCopyUtil.copy(rollout, rolloutRequest, false, UnaryOperator.identity()); + rolloutRequest.setDynamic(rollout.isDynamic()); // TODO - copy compares isDynamic == false and don't set it to false - remain null + return createRolloutGroups(groups, conditions, createRollout(rolloutRequest, false)); } @Override @@ -413,14 +397,11 @@ public class JpaRolloutManagement implements RolloutManagement { @Transactional @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public Rollout update(final RolloutUpdate u) { - final GenericRolloutUpdate update = (GenericRolloutUpdate) u; + public Rollout update(final Update update) { final JpaRollout rollout = getRolloutOrThrowExceptionIfNotFound(update.getId()); - checkIfDeleted(update.getId(), rollout.getStatus()); - update.getName().ifPresent(rollout::setName); - update.getDescription().ifPresent(rollout::setDescription); + ObjectCopyUtil.copy(update, rollout, false, UnaryOperator.identity()); return rolloutRepository.save(rollout); } @@ -492,15 +473,24 @@ public class JpaRolloutManagement implements RolloutManagement { return rollouts; } + private static void validateDs(final Create rollout) { + if (!rollout.getDistributionSet().isValid()) { + throw new InvalidDistributionSetException("The distribution set is not valid"); + } + if (!rollout.getDistributionSet().isComplete()) { + throw new IncompleteDistributionSetException("The distribution set is not complete"); + } + } + /** * In case the given group is missing conditions or actions, they will be set from the supplied default conditions. * * @param create group to check * @param conditions default conditions and actions */ - private static JpaRolloutGroup prepareRolloutGroupWithDefaultConditions( - final RolloutGroupCreate create, final RolloutGroupConditions conditions) { - final JpaRolloutGroup group = ((JpaRolloutGroupCreate) create).build(); + private static JpaRolloutGroup prepareRolloutGroupWithDefaultConditions(final GroupCreate create, final RolloutGroupConditions conditions) { + final JpaRolloutGroup group = new JpaRolloutGroup(); + ObjectCopyUtil.copy(create, group, false, UnaryOperator.identity()); if (group.getSuccessCondition() == null) { group.setSuccessCondition(conditions.getSuccessCondition()); @@ -554,8 +544,7 @@ public class JpaRolloutManagement implements RolloutManagement { distributionSet.getType().getId()); errMsg = "No failed targets in Rollout"; } else { - totalTargets = targetManagement.countByRsqlAndCompatible(rollout.getTargetFilterQuery(), - distributionSet.getType().getId()); + totalTargets = targetManagement.countByRsqlAndCompatible(rollout.getTargetFilterQuery(), distributionSet.getType().getId()); errMsg = "Rollout does not match any existing targets"; } if (totalTargets == 0) { @@ -575,6 +564,13 @@ public class JpaRolloutManagement implements RolloutManagement { return rollout; } + private static void addSuccessAndErrorConditionsAndActions(final JpaRolloutGroup group, final RolloutGroupConditions conditions) { + addSuccessAndErrorConditionsAndActions(group, conditions.getSuccessCondition(), + conditions.getSuccessConditionExp(), conditions.getSuccessAction(), conditions.getSuccessActionExp(), + conditions.getErrorCondition(), conditions.getErrorConditionExp(), conditions.getErrorAction(), + conditions.getErrorActionExp()); + } + @SuppressWarnings("java:S2259") // java:S2259 - false positive, see the java:S2259 comment in code private Rollout createRolloutGroups( final int amountOfGroups, final RolloutGroupConditions conditions, @@ -649,7 +645,7 @@ public class JpaRolloutManagement implements RolloutManagement { } private Rollout createRolloutGroups( - final List groupList, final RolloutGroupConditions conditions, final JpaRollout rollout) { + final List groupList, final RolloutGroupConditions conditions, final JpaRollout rollout) { RolloutHelper.verifyRolloutInStatus(rollout, RolloutStatus.CREATING); final DistributionSetType distributionSetType = rollout.getDistributionSet().getType(); @@ -706,6 +702,24 @@ public class JpaRolloutManagement implements RolloutManagement { return savedRollout; } + public static void addSuccessAndErrorConditionsAndActions(final JpaRolloutGroup group, + final RolloutGroup.RolloutGroupSuccessCondition successCondition, final String successConditionExp, + final RolloutGroup.RolloutGroupSuccessAction successAction, final String successActionExp, + final RolloutGroup.RolloutGroupErrorCondition errorCondition, final String errorConditionExp, + final RolloutGroup.RolloutGroupErrorAction errorAction, final String errorActionExp) { + group.setSuccessCondition(successCondition); + group.setSuccessConditionExp(successConditionExp); + + group.setSuccessAction(successAction); + group.setSuccessActionExp(successActionExp); + + group.setErrorCondition(errorCondition); + group.setErrorConditionExp(errorConditionExp); + + group.setErrorAction(errorAction); + group.setErrorActionExp(errorActionExp); + } + private JpaRollout getRolloutOrThrowExceptionIfNotFound(final Long rolloutId) { return rolloutRepository.findById(rolloutId) .orElseThrow(() -> new EntityNotFoundException(Rollout.class, rolloutId)); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRollout.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRollout.java index fbed2dde6..66710e270 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRollout.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRollout.java @@ -154,7 +154,7 @@ public class JpaRollout extends AbstractJpaNamedEntity implements Rollout, Event private Boolean dynamic; @Setter - @Column(name = "access_control_context", nullable = true) + @Column(name = "access_control_context") private String accessControlContext; @Setter diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModuleType.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModuleType.java index 70147214e..e8ea3ca50 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModuleType.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModuleType.java @@ -45,6 +45,7 @@ public class JpaSoftwareModuleType extends AbstractJpaTypeEntity implements Soft @Serial private static final long serialVersionUID = 1L; + @Setter(value = lombok.AccessLevel.PRIVATE) // used via reflection @Column(name = "max_ds_assignments", nullable = false) @Min(1) private int maxAssignments; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/RolloutEventTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/RolloutEventTest.java index 7934a5ae4..6a1b32508 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/RolloutEventTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/RolloutEventTest.java @@ -12,6 +12,7 @@ package org.eclipse.hawkbit.repository.event.remote.entity; import java.util.Set; import org.eclipse.hawkbit.repository.DistributionSetManagement; +import org.eclipse.hawkbit.repository.RolloutManagement.Create; import org.eclipse.hawkbit.repository.SoftwareModuleManagement; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.Rollout; @@ -52,7 +53,7 @@ class RolloutEventTest extends AbstractRemoteEntityEventTest { .build()); return rolloutManagement.create( - entityFactory.rollout().create().name("exampleRollout").targetFilterQuery("controllerId==*").distributionSetId(ds), + Create.builder().name("exampleRollout").targetFilterQuery("controllerId==*").distributionSet(ds).build(), 5, false, new RolloutGroupConditionBuilder().withDefaults().successCondition(RolloutGroupSuccessCondition.THRESHOLD, "10").build()); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/RolloutGroupEventTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/RolloutGroupEventTest.java index 8c11aac79..74e273da7 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/RolloutGroupEventTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/RolloutGroupEventTest.java @@ -15,6 +15,7 @@ import java.util.Set; import java.util.UUID; import org.eclipse.hawkbit.repository.DistributionSetManagement; +import org.eclipse.hawkbit.repository.RolloutManagement.Create; import org.eclipse.hawkbit.repository.SoftwareModuleManagement; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.Rollout; @@ -93,7 +94,7 @@ class RolloutGroupEventTest extends AbstractRemoteEntityEventTest .build()); final Rollout entity = rolloutManagement.create( - entityFactory.rollout().create().name("exampleRollout").targetFilterQuery("controllerId==*").distributionSetId(ds), + Create.builder().name("exampleRollout").targetFilterQuery("controllerId==*").distributionSet(ds).build(), 5, false, new RolloutGroupConditionBuilder().withDefaults().successCondition(RolloutGroupSuccessCondition.THRESHOLD, "10").build()); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractJpaIntegrationTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractJpaIntegrationTest.java index 8a5e4be20..a406687a7 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractJpaIntegrationTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractJpaIntegrationTest.java @@ -57,6 +57,7 @@ import org.eclipse.hawkbit.repository.jpa.repository.TenantMetaDataRepository; import org.eclipse.hawkbit.repository.jpa.specifications.DistributionSetSpecification; import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications; import org.eclipse.hawkbit.repository.model.Action; +import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetFilter; import org.eclipse.hawkbit.repository.model.DistributionSetTag; @@ -300,7 +301,8 @@ public abstract class AbstractJpaIntegrationTest extends AbstractIntegrationTest } protected void finishAction(final Action action) { - controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(action.getId()).status(Action.Status.FINISHED)); + controllerManagement.addUpdateActionStatus( + ActionStatusCreate.builder().actionId(action.getId()).status(Action.Status.FINISHED).build()); } protected Set getTargetTags(final String controllerId) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ConcurrentDistributionSetInvalidationTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ConcurrentDistributionSetInvalidationTest.java index 8d5125724..4cdc00b48 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ConcurrentDistributionSetInvalidationTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ConcurrentDistributionSetInvalidationTest.java @@ -20,6 +20,7 @@ import java.util.Collections; import java.util.concurrent.TimeUnit; import org.awaitility.Awaitility; +import org.eclipse.hawkbit.repository.RolloutManagement.Create; import org.eclipse.hawkbit.repository.exception.StopRolloutException; import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup; import org.eclipse.hawkbit.repository.jpa.repository.RolloutGroupRepository; @@ -92,9 +93,10 @@ class ConcurrentDistributionSetInvalidationTest extends AbstractJpaIntegrationTe .errorCondition(RolloutGroupErrorCondition.THRESHOLD, "80") .errorAction(RolloutGroupErrorAction.PAUSE, null).build(); - return rolloutManagement.create(entityFactory.rollout().create() + return rolloutManagement.create(Create.builder() .name("verifyInvalidateDistributionSetWithLargeRolloutThrowsException").description("desc") - .targetFilterQuery("name==*").distributionSetId(distributionSet).actionType(ActionType.FORCED), + .targetFilterQuery("name==*").distributionSet(distributionSet).actionType(ActionType.FORCED) + .build(), quotaManagement.getMaxRolloutGroupsPerRollout(), false, conditions); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autocleanup/AutoActionCleanupTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autocleanup/AutoActionCleanupTest.java index a001d73e1..faeb66007 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autocleanup/AutoActionCleanupTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autocleanup/AutoActionCleanupTest.java @@ -19,6 +19,7 @@ import java.util.stream.Collectors; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.model.Action; +import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate; import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.Target; @@ -202,7 +203,7 @@ class AutoActionCleanupTest extends AbstractJpaIntegrationTest { } private void setActionToFailed(final Long id) { - controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(id).status(Status.ERROR)); + controllerManagement.addUpdateActionStatus(ActionStatusCreate.builder().actionId(id).status(Status.ERROR).build()); } private void setupCleanupConfiguration(final boolean cleanupEnabled, final long expiry, final Status... status) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ActionTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ActionTest.java index aa433063c..1a48001d0 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ActionTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ActionTest.java @@ -18,6 +18,7 @@ import org.awaitility.Awaitility; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.jpa.model.JpaAction; import org.eclipse.hawkbit.repository.model.Action; +import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate; import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.ActionStatus; @@ -91,7 +92,7 @@ class ActionTest extends AbstractJpaIntegrationTest { void testActionsStatusStatusConvert() { for (final Status status : Status.values()) { final long id = createAction().getId(); - controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(id).status(status)); + controllerManagement.addUpdateActionStatus(ActionStatusCreate.builder().actionId(id).status(status).build()); final List actionStatuses = actionRepository .findById(id).orElseThrow(() -> new IllegalStateException("Action not found")) .getActionStatus(); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ControllerManagementSecurityTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ControllerManagementSecurityTest.java index 7a2d06920..0777abf48 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ControllerManagementSecurityTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ControllerManagementSecurityTest.java @@ -18,6 +18,8 @@ import org.eclipse.hawkbit.im.authentication.SpringEvalExpressions; import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.jpa.model.JpaAction; +import org.eclipse.hawkbit.repository.model.Action; +import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate; import org.eclipse.hawkbit.repository.model.Target; import org.junit.jupiter.api.Test; import org.springframework.data.domain.Pageable; @@ -33,7 +35,8 @@ class ControllerManagementSecurityTest extends AbstractJpaIntegrationTest { */ @Test void addCancelActionStatusPermissionsCheck() { - assertPermissions(() -> controllerManagement.addCancelActionStatus(entityFactory.actionStatus().create(0L)), + assertPermissions(() -> controllerManagement.addCancelActionStatus( + ActionStatusCreate.builder().actionId(0L).status(Action.Status.DOWNLOADED).build()), List.of(SpringEvalExpressions.CONTROLLER_ROLE)); } @@ -59,7 +62,8 @@ class ControllerManagementSecurityTest extends AbstractJpaIntegrationTest { */ @Test void addInformationalActionStatusPermissionsCheck() { - assertPermissions(() -> controllerManagement.addInformationalActionStatus(entityFactory.actionStatus().create(0L)), + assertPermissions(() -> controllerManagement.addInformationalActionStatus( + ActionStatusCreate.builder().actionId(0L).status(Action.Status.DOWNLOADED).build()), List.of(SpringEvalExpressions.CONTROLLER_ROLE)); } @@ -68,7 +72,8 @@ class ControllerManagementSecurityTest extends AbstractJpaIntegrationTest { */ @Test void addUpdateActionStatusPermissionsCheck() { - assertPermissions(() -> controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(0L)), + assertPermissions(() -> controllerManagement.addUpdateActionStatus( + ActionStatusCreate.builder().actionId(0L).status(Action.Status.DOWNLOADED).build()), List.of(SpringEvalExpressions.CONTROLLER_ROLE)); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ControllerManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ControllerManagementTest.java index 89adeca46..e8a255399 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ControllerManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ControllerManagementTest.java @@ -25,7 +25,6 @@ import static org.mockito.Mockito.when; import java.io.ByteArrayInputStream; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -41,7 +40,6 @@ import org.eclipse.hawkbit.im.authentication.SpPermission; import org.eclipse.hawkbit.repository.RepositoryProperties; import org.eclipse.hawkbit.repository.TargetTypeManagement; import org.eclipse.hawkbit.repository.UpdateMode; -import org.eclipse.hawkbit.repository.builder.ActionStatusCreate; import org.eclipse.hawkbit.repository.event.remote.CancelTargetAssignmentEvent; import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent; import org.eclipse.hawkbit.repository.event.remote.TargetAttributesRequestedEvent; @@ -67,6 +65,8 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository; import org.eclipse.hawkbit.repository.jpa.specifications.ActionSpecifications; import org.eclipse.hawkbit.repository.model.Action; +import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate; +import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate.ActionStatusCreateBuilder; import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.ActionStatus; import org.eclipse.hawkbit.repository.model.Artifact; @@ -202,14 +202,14 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { final Long actionId = getFirstAssignedActionId(assignDistributionSet(testDs, testTarget)); - controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(actionId) - .status(Action.Status.RUNNING).occurredAt(System.currentTimeMillis()) - .messages(List.of("proceeding message 1"))); + controllerManagement.addUpdateActionStatus(ActionStatusCreate.builder().actionId(actionId) + .status(Action.Status.RUNNING).occurredAt(System.currentTimeMillis()).messages(List.of("proceeding message 1")) + .build()); waitNextMillis(); - controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(actionId) - .status(Action.Status.RUNNING).occurredAt(System.currentTimeMillis()) - .messages(List.of("proceeding message 2"))); + controllerManagement.addUpdateActionStatus(ActionStatusCreate.builder().actionId(actionId) + .status(Action.Status.RUNNING).occurredAt(System.currentTimeMillis()).messages(List.of("proceeding message 2")) + .build()); final List messages = controllerManagement.getActionHistoryMessages(actionId, 2); @@ -240,23 +240,23 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { final Long actionId1 = getFirstAssignedActionId(assignDistributionSet( testdataFactory.createDistributionSet("ds1"), testdataFactory.createTargets(1, "t1"))); assertThat(actionId1).isNotNull(); - final ActionStatusCreate status = entityFactory.actionStatus().create(actionId1).status(Status.WARNING); + final ActionStatusCreateBuilder status = ActionStatusCreate.builder().actionId(actionId1).status(Status.WARNING); for (int i = 0; i < maxStatusEntries; ++i) { - controllerManagement.addInformationalActionStatus(status.message("Msg " + i).occurredAt(System.currentTimeMillis())); + controllerManagement.addInformationalActionStatus(status.messages(List.of("Msg " + i)).occurredAt(System.currentTimeMillis()).build()); } assertThatExceptionOfType(AssignmentQuotaExceededException.class) - .isThrownBy(() -> controllerManagement.addInformationalActionStatus(status)); + .isThrownBy(() -> controllerManagement.addInformationalActionStatus(status.build())); // test for update status (and mixed case) final Long actionId2 = getFirstAssignedActionId(assignDistributionSet( testdataFactory.createDistributionSet("ds2"), testdataFactory.createTargets(1, "t2"))); assertThat(actionId2).isNotEqualTo(actionId1); - final ActionStatusCreate statusWarning = entityFactory.actionStatus().create(actionId2).status(Status.WARNING); + final ActionStatusCreateBuilder statusWarning = ActionStatusCreate.builder().actionId(actionId2).status(Status.WARNING); for (int i = 0; i < maxStatusEntries; ++i) { - controllerManagement.addUpdateActionStatus(statusWarning.message("Msg " + i).occurredAt(System.currentTimeMillis())); + controllerManagement.addUpdateActionStatus(statusWarning.messages(List.of("Msg " + i)).occurredAt(System.currentTimeMillis()).build()); } assertThatExceptionOfType(AssignmentQuotaExceededException.class) - .isThrownBy(() -> controllerManagement.addInformationalActionStatus(statusWarning)); + .isThrownBy(() -> controllerManagement.addInformationalActionStatus(statusWarning.build())); } /** @@ -283,10 +283,11 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { IntStream.range(0, maxMessages).forEach(i -> messages.add(i, "msg")); assertThat(controllerManagement.addInformationalActionStatus( - entityFactory.actionStatus().create(actionId).messages(messages).status(Status.WARNING))).isNotNull(); + ActionStatusCreate.builder().actionId(actionId).messages(messages).status(Status.WARNING).build())).isNotNull(); messages.add("msg"); - final ActionStatusCreate statusToManyMessages = entityFactory.actionStatus().create(actionId).messages(messages).status(Status.WARNING); + final ActionStatusCreate statusToManyMessages = ActionStatusCreate.builder() + .actionId(actionId).messages(messages).status(Status.WARNING).build(); assertThatExceptionOfType(AssignmentQuotaExceededException.class) .isThrownBy(() -> controllerManagement.addInformationalActionStatus(statusToManyMessages)); } @@ -308,8 +309,8 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { testdataFactory.createTarget(); final Long actionId = createAndAssignDsAsDownloadOnly("downloadOnlyDs", DEFAULT_CONTROLLER_ID); assertThat(actionId).isNotNull(); - controllerManagement - .addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.DOWNLOAD)); + controllerManagement.addUpdateActionStatus( + ActionStatusCreate.builder().actionId(actionId).status(Status.DOWNLOAD).build()); assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING, Action.Status.RUNNING, Action.Status.DOWNLOAD, true); @@ -355,13 +356,13 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { final SoftwareModule module = testdataFactory.createSoftwareModuleOs(); verifyThrownExceptionBy(() -> controllerManagement.addCancelActionStatus( - entityFactory.actionStatus().create(NOT_EXIST_IDL).status(Action.Status.FINISHED)), "Action"); + ActionStatusCreate.builder().actionId(NOT_EXIST_IDL).status(Action.Status.FINISHED).build()), "Action"); verifyThrownExceptionBy(() -> controllerManagement.addInformationalActionStatus( - entityFactory.actionStatus().create(NOT_EXIST_IDL).status(Action.Status.RUNNING)), "Action"); + ActionStatusCreate.builder().actionId(NOT_EXIST_IDL).status(Action.Status.RUNNING).build()), "Action"); verifyThrownExceptionBy(() -> controllerManagement.addUpdateActionStatus( - entityFactory.actionStatus().create(NOT_EXIST_IDL).status(Action.Status.FINISHED)), "Action"); + ActionStatusCreate.builder().actionId(NOT_EXIST_IDL).status(Action.Status.FINISHED).build()), "Action"); verifyThrownExceptionBy(() -> controllerManagement .getActionForDownloadByTargetAndSoftwareModule(target.getControllerId(), NOT_EXIST_IDL), @@ -403,7 +404,7 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { simulateIntermediateStatusOnUpdate(actionId); controllerManagement - .addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.FINISHED)); + .addUpdateActionStatus(ActionStatusCreate.builder().actionId(actionId).status(Action.Status.FINISHED).build()); assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.IN_SYNC, Action.Status.FINISHED, Action.Status.FINISHED, false); @@ -429,14 +430,8 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { simulateIntermediateStatusOnUpdate(actionId); - final ActionStatusCreate statusSingleMessage = entityFactory.actionStatus().create(actionId) - .status(Status.FINISHED).message(INVALID_TEXT_HTML); - assertThatExceptionOfType(ConstraintViolationException.class) - .as("set invalid description text should not be created") - .isThrownBy(() -> controllerManagement.addUpdateActionStatus(statusSingleMessage)); - - final ActionStatusCreate statusMulipleMessages = entityFactory.actionStatus().create(actionId) - .status(Status.FINISHED).messages(Arrays.asList("this is valid.", INVALID_TEXT_HTML)); + final ActionStatusCreate statusMulipleMessages = ActionStatusCreate.builder().actionId(actionId) + .status(Status.FINISHED).messages(List.of("this is valid.", INVALID_TEXT_HTML)).build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("set invalid description text should not be created") .isThrownBy(() -> controllerManagement.addUpdateActionStatus(statusMulipleMessages)); @@ -467,7 +462,7 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { deploymentManagement.cancelAction(actionId); controllerManagement - .addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.FINISHED)); + .addUpdateActionStatus(ActionStatusCreate.builder().actionId(actionId).status(Action.Status.FINISHED).build()); assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.IN_SYNC, Action.Status.FINISHED, Action.Status.FINISHED, false); @@ -491,7 +486,7 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { void cancellationFeedbackRejectedIfActionIsNotInCanceling() { final Long actionId = createTargetAndAssignDs(); - final ActionStatusCreate status = entityFactory.actionStatus().create(actionId).status(Status.FINISHED); + final ActionStatusCreate status = ActionStatusCreate.builder().actionId(actionId).status(Status.FINISHED).build(); assertThatExceptionOfType(CancelActionNotAllowedException.class) .as("Expected " + CancelActionNotAllowedException.class.getName()) .isThrownBy(() -> controllerManagement.addCancelActionStatus(status)); @@ -527,7 +522,7 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { simulateIntermediateStatusOnCancellation(actionId); controllerManagement - .addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.FINISHED)); + .addCancelActionStatus(ActionStatusCreate.builder().actionId(actionId).status(Action.Status.FINISHED).build()); assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.IN_SYNC, Action.Status.CANCELED, Action.Status.FINISHED, false); @@ -560,7 +555,7 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { simulateIntermediateStatusOnCancellation(actionId); controllerManagement - .addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.CANCELED)); + .addCancelActionStatus(ActionStatusCreate.builder().actionId(actionId).status(Action.Status.CANCELED).build()); assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.IN_SYNC, Action.Status.CANCELED, Action.Status.CANCELED, false); @@ -594,7 +589,7 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { simulateIntermediateStatusOnCancellation(actionId); controllerManagement.addCancelActionStatus( - entityFactory.actionStatus().create(actionId).status(Action.Status.CANCEL_REJECTED)); + ActionStatusCreate.builder().actionId(actionId).status(Action.Status.CANCEL_REJECTED).build()); assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING, Action.Status.RUNNING, Action.Status.CANCEL_REJECTED, true); @@ -628,7 +623,7 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { simulateIntermediateStatusOnCancellation(actionId); controllerManagement - .addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.ERROR)); + .addCancelActionStatus(ActionStatusCreate.builder().actionId(actionId).status(Action.Status.ERROR).build()); assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING, Action.Status.RUNNING, Action.Status.ERROR, true); @@ -1024,23 +1019,27 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { final Long actionId = createTargetAndAssignDs(); // test and verify - controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.RUNNING)); + controllerManagement.addUpdateActionStatus(ActionStatusCreate.builder().actionId(actionId).status(Action.Status.RUNNING).build()); assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING, Action.Status.RUNNING, Action.Status.RUNNING, true); - controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.ERROR)); + controllerManagement.addUpdateActionStatus(ActionStatusCreate.builder().actionId(actionId).status(Action.Status.ERROR).build()); assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.ERROR, Action.Status.ERROR, Action.Status.ERROR, false); // try with disabled late feedback - withRejectActionStatusForClosedAction(true, () -> - controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.FINISHED))); + withRejectActionStatusForClosedAction( + true, + () -> controllerManagement.addUpdateActionStatus( + ActionStatusCreate.builder().actionId(actionId).status(Action.Status.FINISHED).build())); // test assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.ERROR, Action.Status.ERROR, Action.Status.ERROR, false); // try with enabled late feedback - should not make a difference as it // only allows intermediate feedback and not multiple close - withRejectActionStatusForClosedAction(false, - () -> controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.FINISHED))); + withRejectActionStatusForClosedAction( + false, + () -> controllerManagement.addUpdateActionStatus( + ActionStatusCreate.builder().actionId(actionId).status(Action.Status.FINISHED).build())); // test assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.ERROR, Action.Status.ERROR, Action.Status.ERROR, false); @@ -1068,14 +1067,16 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { final Long actionId = prepareFinishedUpdate().getId(); withRejectActionStatusForClosedAction(true, - () -> controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.FINISHED))); + () -> controllerManagement.addUpdateActionStatus( + ActionStatusCreate.builder().actionId(actionId).status(Action.Status.FINISHED).build())); // test assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.IN_SYNC, Action.Status.FINISHED, Action.Status.FINISHED, false); withRejectActionStatusForClosedAction(false, - () -> controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.FINISHED))); + () -> controllerManagement.addUpdateActionStatus( + ActionStatusCreate.builder().actionId(actionId).status(Action.Status.FINISHED).build())); // test assertActionStatus( @@ -1103,7 +1104,7 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { final Action action = prepareFinishedUpdate(); withRejectActionStatusForClosedAction(true, () -> controllerManagement.addUpdateActionStatus( - entityFactory.actionStatus().create(action.getId()).status(Action.Status.RUNNING))); + ActionStatusCreate.builder().actionId(action.getId()).status(Action.Status.RUNNING).build())); // nothing changed as "feedback after close" is disabled assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).get().getUpdateStatus()) @@ -1135,7 +1136,7 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { Action action = prepareFinishedUpdate(); withRejectActionStatusForClosedAction(false, () -> controllerManagement.addUpdateActionStatus( - entityFactory.actionStatus().create(action.getId()).status(Action.Status.RUNNING))); + ActionStatusCreate.builder().actionId(action.getId()).status(Action.Status.RUNNING).build())); // nothing changed as "feedback after close" is disabled assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).get().getUpdateStatus()).isEqualTo(TargetUpdateStatus.IN_SYNC); @@ -1215,7 +1216,7 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { testdataFactory.createTarget(); final Long actionId = createAndAssignDsAsDownloadOnly("downloadOnlyDs", DEFAULT_CONTROLLER_ID); assertThat(actionId).isNotNull(); - controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.DOWNLOADED)); + controllerManagement.addUpdateActionStatus(ActionStatusCreate.builder().actionId(actionId).status(Status.DOWNLOADED).build()); assertActionStatus( actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.IN_SYNC, Action.Status.DOWNLOADED, Action.Status.DOWNLOADED, false); @@ -1273,7 +1274,7 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { final Long actionId = createAndAssignDsAsDownloadOnly("downloadOnlyDs", DEFAULT_CONTROLLER_ID); assertThat(actionId).isNotNull(); IntStream.range(0, 3).forEach(i -> controllerManagement - .addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.DOWNLOADED))); + .addUpdateActionStatus(ActionStatusCreate.builder().actionId(actionId).status(Status.DOWNLOADED).build())); assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.IN_SYNC, Status.DOWNLOADED, Status.DOWNLOADED, false); @@ -1306,7 +1307,7 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { assertThat(actionId).isNotNull(); final IntConsumer op = i -> controllerManagement.addUpdateActionStatus( - entityFactory.actionStatus().create(actionId).status(Status.DOWNLOADED)); + ActionStatusCreate.builder().actionId(actionId).status(Status.DOWNLOADED).build()); Assertions.assertThatExceptionOfType(AssignmentQuotaExceededException.class) .isThrownBy(() -> forNTimes(maxMessages, op)); } @@ -1334,7 +1335,7 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { // assert that too many intermediate statuses will throw quota exception final IntConsumer op = i -> controllerManagement.addUpdateActionStatus( - entityFactory.actionStatus().create(actionId).status(Status.DOWNLOADED)); + ActionStatusCreate.builder().actionId(actionId).status(Status.DOWNLOADED).build()); assertThatExceptionOfType(AssignmentQuotaExceededException.class) .as("No QuotaExceededException thrown for too many DOWNLOADED updateActionStatus updates") .isThrownBy(() -> forNTimes(maxMessages, op)); @@ -1342,7 +1343,7 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { // assert that Final result is accepted even if quota is reached assertThatNoException().isThrownBy(() -> { Action updatedAction = controllerManagement.addUpdateActionStatus( - entityFactory.actionStatus().create(actionId).status(Status.FINISHED)); + ActionStatusCreate.builder().actionId(actionId).status(Status.FINISHED).build()); // check if action really finished assertThat(updatedAction.isActive()).isFalse(); // check if final status is updated accordingly @@ -1352,7 +1353,7 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { // assert that additional final result is not accepted assertThatNoException().isThrownBy(() -> { Action updatedAction = controllerManagement - .addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.ERROR)); + .addUpdateActionStatus(ActionStatusCreate.builder().actionId(actionId).status(Status.ERROR).build()); // check if action really finished assertThat(updatedAction.isActive()).isFalse(); // check if final status is not changed - e.g. ERROR is not updated because action has already finished @@ -1382,7 +1383,7 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { // assert that too many intermediate statuses will throw quota exception final IntConsumer op = i -> controllerManagement.addUpdateActionStatus( - entityFactory.actionStatus().create(actionId).status(Status.DOWNLOADED)); + ActionStatusCreate.builder().actionId(actionId).status(Status.DOWNLOADED).build()); assertThatExceptionOfType(AssignmentQuotaExceededException.class) .as("No QuotaExceededException thrown for too many DOWNLOADED updateActionStatus updates") .isThrownBy(() -> forNTimes(maxMessages, op)); @@ -1390,7 +1391,7 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { // assert that Final result is accepted even if quota is reached assertThatNoException().isThrownBy(() -> { Action updatedAction = controllerManagement - .addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.FINISHED)); + .addUpdateActionStatus(ActionStatusCreate.builder().actionId(actionId).status(Status.FINISHED).build()); // check if action really finished assertThat(updatedAction.isActive()).isFalse(); // check if final status is updated accordingly @@ -1400,7 +1401,7 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { // assert that additional final result is not accepted assertThatNoException().isThrownBy(() -> { Action updatedAction = controllerManagement - .addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.ERROR)); + .addUpdateActionStatus(ActionStatusCreate.builder().actionId(actionId).status(Status.ERROR).build()); // check if action really finished assertThat(updatedAction.isActive()).isFalse(); // check if final status is not changed - e.g. ERROR is not updated because action has already finished @@ -1620,19 +1621,19 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { assertThat(controllerManagement.findActiveActionWithHighestWeight(targetId).get().getId()) .isEqualTo(actionWeightNull); controllerManagement - .addUpdateActionStatus(entityFactory.actionStatus().create(actionWeightNull).status(Status.FINISHED)); + .addUpdateActionStatus(ActionStatusCreate.builder().actionId(actionWeightNull).status(Status.FINISHED).build()); assertThat(controllerManagement.findActiveActionWithHighestWeight(targetId).get().getId()) .isEqualTo(actionWeight1000); controllerManagement - .addUpdateActionStatus(entityFactory.actionStatus().create(actionWeight1000).status(Status.FINISHED)); + .addUpdateActionStatus(ActionStatusCreate.builder().actionId(actionWeight1000).status(Status.FINISHED).build()); assertThat(controllerManagement.findActiveActionWithHighestWeight(targetId).get().getId()) .isEqualTo(actionWeight500old); controllerManagement - .addUpdateActionStatus(entityFactory.actionStatus().create(actionWeight500old).status(Status.FINISHED)); + .addUpdateActionStatus(ActionStatusCreate.builder().actionId(actionWeight500old).status(Status.FINISHED).build()); assertThat(controllerManagement.findActiveActionWithHighestWeight(targetId).get().getId()) .isEqualTo(actionWeight500new); controllerManagement - .addUpdateActionStatus(entityFactory.actionStatus().create(actionWeight500new).status(Status.FINISHED)); + .addUpdateActionStatus(ActionStatusCreate.builder().actionId(actionWeight500new).status(Status.FINISHED).build()); assertThat(controllerManagement.findActiveActionWithHighestWeight(targetId)).isEmpty(); } @@ -1757,40 +1758,36 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { private void simulateIntermediateStatusOnCancellation(final Long actionId) { controllerManagement - .addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.RUNNING)); + .addCancelActionStatus(ActionStatusCreate.builder().actionId(actionId).status(Action.Status.RUNNING).build()); assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING, Action.Status.CANCELING, Action.Status.RUNNING, true); controllerManagement - .addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.DOWNLOAD)); + .addCancelActionStatus(ActionStatusCreate.builder().actionId(actionId).status(Action.Status.DOWNLOAD).build()); assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING, Action.Status.CANCELING, Action.Status.DOWNLOAD, true); controllerManagement - .addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.DOWNLOADED)); + .addCancelActionStatus(ActionStatusCreate.builder().actionId(actionId).status(Action.Status.DOWNLOADED).build()); assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING, Action.Status.CANCELING, Action.Status.DOWNLOADED, true); controllerManagement - .addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.RETRIEVED)); + .addCancelActionStatus(ActionStatusCreate.builder().actionId(actionId).status(Action.Status.RETRIEVED).build()); assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING, Action.Status.CANCELING, Action.Status.RETRIEVED, true); controllerManagement - .addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.WARNING)); + .addCancelActionStatus(ActionStatusCreate.builder().actionId(actionId).status(Action.Status.WARNING).build()); assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING, Action.Status.CANCELING, Action.Status.WARNING, true); } private void simulateIntermediateStatusOnUpdate(final Long actionId) { addUpdateActionStatusAndAssert(actionId, Action.Status.RUNNING); - addUpdateActionStatusAndAssert(actionId, Action.Status.DOWNLOAD); - addUpdateActionStatusAndAssert(actionId, Action.Status.DOWNLOADED); - addUpdateActionStatusAndAssert(actionId, Action.Status.RETRIEVED); - addUpdateActionStatusAndAssert(actionId, Action.Status.WARNING); } @@ -1798,14 +1795,12 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { addUpdateActionStatusAndAssert(actionId, actionStatus, null); } - private void addUpdateActionStatusAndAssert(final Long actionId, final Action.Status actionStatus, - final Integer code) { - final ActionStatusCreate status = entityFactory.actionStatus().create(actionId).status(actionStatus); + private void addUpdateActionStatusAndAssert(final Long actionId, final Action.Status actionStatus, final Integer code) { + final ActionStatusCreateBuilder status = ActionStatusCreate.builder().actionId(actionId).status(actionStatus); if (code != null) { - status.code(code.intValue()); + status.code(code); } - controllerManagement - .addUpdateActionStatus(status); + controllerManagement.addUpdateActionStatus(status.build()); assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING, Action.Status.RUNNING, actionStatus, true); } @@ -1938,21 +1933,21 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { private void writeStatus(final Long actionId, final int allowedStatusEntries) { for (int i = 0; i < allowedStatusEntries; i++) { controllerManagement.addInformationalActionStatus( - entityFactory.actionStatus().create(actionId).status(Status.RUNNING).message("test" + i)); + ActionStatusCreate.builder().actionId(actionId).status(Status.RUNNING).messages(List.of("test" + i)).build()); } } private void finishDownloadOnlyUpdateAndSendUpdateActionStatus(final Long actionId, final Status status) { // finishing action controllerManagement - .addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.DOWNLOADED)); + .addUpdateActionStatus(ActionStatusCreate.builder().actionId(actionId).status(Status.DOWNLOADED).build()); - controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(status)); + controllerManagement.addUpdateActionStatus(ActionStatusCreate.builder().actionId(actionId).status(status).build()); assertThat(activeActionExistsForControllerId(DEFAULT_CONTROLLER_ID)).isFalse(); } private void addUpdateActionStatus(final Long actionId, final String controllerId, final Status actionStatus) { - controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(actionStatus)); + controllerManagement.addUpdateActionStatus(ActionStatusCreate.builder().actionId(actionId).status(actionStatus).build()); assertActionStatus(actionId, controllerId, TargetUpdateStatus.IN_SYNC, actionStatus, actionStatus, false); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DeploymentManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DeploymentManagementTest.java index 7f814ec31..5ec1333ac 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DeploymentManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DeploymentManagementTest.java @@ -69,6 +69,7 @@ import org.eclipse.hawkbit.repository.jpa.specifications.ActionSpecifications; import org.eclipse.hawkbit.repository.jpa.specifications.DistributionSetSpecification; import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder; import org.eclipse.hawkbit.repository.model.Action; +import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate; import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.ActionStatus; @@ -270,8 +271,8 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { // one action with one action status is generated final Long actionId = getFirstAssignedActionId(assignDistributionSet(testDs, testTarget)); // create action-status entry with one message - controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(actionId) - .status(Action.Status.FINISHED).messages(Collections.singletonList("finished message"))); + controllerManagement.addUpdateActionStatus(ActionStatusCreate.builder().actionId(actionId) + .status(Action.Status.FINISHED).messages(List.of("finished message")).build()); final Page actionStates = deploymentManagement.findActionStatusByAction(actionId, PAGE); // find newly created action-status entry with message @@ -365,7 +366,8 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { deploymentManagement.cancelAction(secondAction.getId()); secondAction = (JpaAction) deploymentManagement.findActionWithDetails(secondAction.getId()).get(); // confirm cancellation - controllerManagement.addCancelActionStatus(entityFactory.actionStatus().create(secondAction.getId()).status(Status.CANCELED)); + controllerManagement.addCancelActionStatus(ActionStatusCreate.builder() + .actionId(secondAction.getId()).status(Status.CANCELED).build()); assertThat(actionStatusRepository.findAll()).as("wrong size of actions status").hasSize(7); assertThat(deploymentManagement.getAssignedDistributionSet("4712")).as("wrong ds").contains(dsFirst); assertThat(targetManagement.getByControllerId("4712").get().getUpdateStatus()) @@ -377,7 +379,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { firstAction = (JpaAction) deploymentManagement.findActionWithDetails(firstAction.getId()).get(); // confirm cancellation controllerManagement.addCancelActionStatus( - entityFactory.actionStatus().create(firstAction.getId()).status(Status.CANCELED)); + ActionStatusCreate.builder().actionId(firstAction.getId()).status(Status.CANCELED).build()); assertThat(actionStatusRepository.findAll()).as("wrong size of action status").hasSize(9); assertThat(deploymentManagement.getAssignedDistributionSet("4712")).as("wrong assigned ds") .contains(dsInstalled); @@ -414,7 +416,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { // confirm cancellation firstAction = (JpaAction) deploymentManagement.findActionWithDetails(firstAction.getId()).get(); controllerManagement.addCancelActionStatus( - entityFactory.actionStatus().create(firstAction.getId()).status(Status.CANCELED)); + ActionStatusCreate.builder().actionId(firstAction.getId()).status(Status.CANCELED).build()); assertThat(actionStatusRepository.findAll()).as("wrong size of action status").hasSize(7); assertThat(deploymentManagement.getAssignedDistributionSet("4712")).as("wrong assigned ds").contains(dsSecond); assertThat(targetManagement.getByControllerId("4712").get().getUpdateStatus()).as("wrong target update status") @@ -427,7 +429,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { assertThat(deploymentManagement.getAssignedDistributionSet("4712")).as("wrong assigned ds").contains(dsSecond); // confirm cancellation controllerManagement.addCancelActionStatus( - entityFactory.actionStatus().create(secondAction.getId()).status(Status.CANCELED)); + ActionStatusCreate.builder().actionId(secondAction.getId()).status(Status.CANCELED).build()); // cancelled success -> back to dsInstalled assertThat(deploymentManagement.getAssignedDistributionSet("4712")) .as("wrong installed ds") @@ -1444,7 +1446,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { final Slice updAct = findActionsByDistributionSet(PAGE, dsA.getId()); controllerManagement.addUpdateActionStatus( - entityFactory.actionStatus().create(updAct.getContent().get(0).getId()).status(Status.FINISHED)); + ActionStatusCreate.builder().actionId(updAct.getContent().get(0).getId()).status(Status.FINISHED).build()); targ = targetManagement.getByControllerId(targ.getControllerId()).get(); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementFlowTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementFlowTest.java index 8e7b0d3bf..39b9ab0f3 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementFlowTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementFlowTest.java @@ -15,7 +15,7 @@ import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import org.eclipse.hawkbit.repository.OffsetBasedPageRequest; -import org.eclipse.hawkbit.repository.builder.DynamicRolloutGroupTemplate; +import org.eclipse.hawkbit.repository.RolloutManagement; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.jpa.model.JpaAction; import org.eclipse.hawkbit.repository.model.Action; @@ -217,7 +217,7 @@ class RolloutManagementFlowTest extends AbstractJpaIntegrationTest { final Rollout rollout = testdataFactory.createRolloutByVariables(rolloutName, rolloutName, amountGroups, "controllerid==" + targetPrefix + "*", distributionSet, "60", "30", Action.ActionType.FORCED, 1000, false, true, - DynamicRolloutGroupTemplate.builder().nameSuffix("-dyn").targetCount(6).build()); + RolloutManagement.DynamicRolloutGroupTemplate.builder().nameSuffix("-dyn").targetCount(6).build()); // rollout is READY, amountGroups + 1 (dynamic) rollout groups and amountGroups * 3 targets in static groups assertRollout(rollout, true, RolloutStatus.READY, amountGroups + 1, amountGroups * 3); @@ -314,7 +314,7 @@ class RolloutManagementFlowTest extends AbstractJpaIntegrationTest { final Rollout rollout = testdataFactory.createRolloutByVariables(rolloutName, rolloutName, 0, "controllerid==" + targetPrefix + "*", distributionSet, "60", "30", Action.ActionType.FORCED, 1000, false, true, - DynamicRolloutGroupTemplate.builder().nameSuffix("-dyn").targetCount(6).build()); + RolloutManagement.DynamicRolloutGroupTemplate.builder().nameSuffix("-dyn").targetCount(6).build()); // rollout is READY, amountGroups + 1 (dynamic) rollout groups and amountGroups * 3 targets in static groups assertRollout(rollout, true, RolloutStatus.READY, 1, 0); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementSecurityTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementSecurityTest.java index 9c9a1166a..de77490b5 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementSecurityTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementSecurityTest.java @@ -11,19 +11,22 @@ package org.eclipse.hawkbit.repository.jpa.management; import java.util.List; -import jakarta.validation.ConstraintDeclarationException; - import lombok.extern.slf4j.Slf4j; import org.eclipse.hawkbit.im.authentication.SpPermission; import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetTypeManagement; -import org.eclipse.hawkbit.repository.builder.DynamicRolloutGroupTemplate; +import org.eclipse.hawkbit.repository.RolloutManagement; +import org.eclipse.hawkbit.repository.RolloutManagement.Create; +import org.eclipse.hawkbit.repository.RolloutManagement.GroupCreate; +import org.eclipse.hawkbit.repository.RolloutManagement.Update; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.RolloutGroupConditionBuilder; +import org.eclipse.hawkbit.repository.test.util.TestdataFactory; import org.eclipse.hawkbit.repository.test.util.WithUser; import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; /** * Feature: SecurityTests - RolloutManagement
@@ -32,6 +35,9 @@ import org.junit.jupiter.api.Test; @Slf4j class RolloutManagementSecurityTest extends AbstractJpaIntegrationTest { + @Autowired + private TestdataFactory testdataFactory; + /** * Tests ManagementAPI PreAuthorized method with correct and insufficient permissions. */ @@ -133,16 +139,22 @@ class RolloutManagementSecurityTest extends AbstractJpaIntegrationTest { */ @Test void createPermissionsCheck() { - assertPermissions(() -> rolloutManagement.create(entityFactory.rollout().create().distributionSetId(1L), 1, false, - new RolloutGroupConditionBuilder().withDefaults().build()), List.of(SpPermission.CREATE_ROLLOUT, SpPermission.READ_REPOSITORY)); - assertPermissions(() -> rolloutManagement.create(entityFactory.rollout().create().distributionSetId(1L), 1, false, - new RolloutGroupConditionBuilder().withDefaults().build(), DynamicRolloutGroupTemplate.builder().build()), - List.of(SpPermission.CREATE_ROLLOUT, SpPermission.READ_REPOSITORY)); + testdataFactory.createTarget(); // to have matching + final DistributionSet ds = testdataFactory.createDistributionSetLocked("createPermissionsCheck"); + final List permissions = List.of(SpPermission.CREATE_ROLLOUT, SpPermission.READ_TARGET, SpPermission.READ_REPOSITORY); + assertPermissions(() -> rolloutManagement.create( + Create.builder().name("createPermissionsCheck").distributionSet(ds).targetFilterQuery("controllerid==*").build(), + 1, false, new RolloutGroupConditionBuilder().withDefaults().build()), + permissions); + assertPermissions(() -> rolloutManagement.create( + Create.builder().name("createPermissionsCheck2").distributionSet(ds).targetFilterQuery("controllerid==*").dynamic(true).build(), + 1, false, new RolloutGroupConditionBuilder().withDefaults().build(), RolloutManagement.DynamicRolloutGroupTemplate.builder().build()), + permissions); assertPermissions( - () -> rolloutManagement.create(entityFactory.rollout().create().distributionSetId(1L), - List.of(entityFactory.rolloutGroup().create()), - new RolloutGroupConditionBuilder().withDefaults().build()), - List.of(SpPermission.CREATE_ROLLOUT, SpPermission.READ_REPOSITORY)); + () -> rolloutManagement.create( + Create.builder().name("createPermissionsCheck3").distributionSet(ds).targetFilterQuery("controllerid==*").build(), + List.of(GroupCreate.builder().name("group").build()), new RolloutGroupConditionBuilder().withDefaults().build()), + permissions); } /** @@ -191,7 +203,7 @@ class RolloutManagementSecurityTest extends AbstractJpaIntegrationTest { */ @Test void updatePermissionsCheck() { - assertPermissions(() -> rolloutManagement.update(entityFactory.rollout().update(1L)), List.of(SpPermission.UPDATE_ROLLOUT)); + assertPermissions(() -> rolloutManagement.update(Update.builder().id(1L).build()), List.of(SpPermission.UPDATE_ROLLOUT)); } /** @@ -216,25 +228,6 @@ class RolloutManagementSecurityTest extends AbstractJpaIntegrationTest { }, List.of(SpPermission.UPDATE_ROLLOUT)); } - /** - * Tests ManagementAPI PreAuthorized method with correct and insufficient permissions. - */ - @Test// @WithUser(principal = "user", authorities = { SpPermission.CREATE_TARGET, SpPermission.CREATE_ROLLOUT, SpPermission.READ_ROLLOUT, -// SpPermission.READ_TARGET }) - void validateTargetsInGroupsPermissionsCheck() { - try { - assertPermissions( - () -> rolloutManagement.validateTargetsInGroups(List.of(entityFactory.rolloutGroup().create()), "name==dummy", 1L, 1L), - List.of(SpPermission.READ_ROLLOUT, SpPermission.READ_TARGET)); - } catch (Error e) { - if (e.getCause() instanceof ConstraintDeclarationException) { - log.info("ConstraintDeclarationException thrown expected"); - } else { - throw e; - } - } - } - /** * Tests ManagementAPI PreAuthorized method with correct and insufficient permissions. */ diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementTest.java index 60092d166..3518a8a2e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementTest.java @@ -12,10 +12,8 @@ package org.eclipse.hawkbit.repository.jpa.management; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.EnumMap; import java.util.List; import java.util.Map; @@ -23,7 +21,6 @@ import java.util.NoSuchElementException; import java.util.Optional; import java.util.Set; import java.util.UUID; -import java.util.concurrent.TimeUnit; import java.util.stream.Stream; import jakarta.validation.ConstraintViolationException; @@ -31,14 +28,13 @@ import jakarta.validation.ValidationException; import org.assertj.core.api.Assertions; import org.assertj.core.api.Condition; -import org.awaitility.Awaitility; import org.eclipse.hawkbit.im.authentication.SpPermission; import org.eclipse.hawkbit.im.authentication.SpRole; import org.eclipse.hawkbit.repository.Identifiable; import org.eclipse.hawkbit.repository.OffsetBasedPageRequest; -import org.eclipse.hawkbit.repository.builder.RolloutCreate; -import org.eclipse.hawkbit.repository.builder.RolloutGroupCreate; -import org.eclipse.hawkbit.repository.builder.RolloutUpdate; +import org.eclipse.hawkbit.repository.RolloutManagement.Create; +import org.eclipse.hawkbit.repository.RolloutManagement.GroupCreate; +import org.eclipse.hawkbit.repository.RolloutManagement.Update; import org.eclipse.hawkbit.repository.event.remote.RolloutDeletedEvent; import org.eclipse.hawkbit.repository.event.remote.RolloutGroupDeletedEvent; import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent; @@ -65,6 +61,7 @@ import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.jpa.model.JpaAction; import org.eclipse.hawkbit.repository.jpa.model.JpaRollout; import org.eclipse.hawkbit.repository.model.Action; +import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate; import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.DistributionSet; @@ -109,8 +106,6 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { /** * Tests static assignment aspects of the dynamic group assignment filters. - */ - /** * Dynamic group doesn't override newer static group assignments */ @Test @@ -183,16 +178,15 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { void rolloutShouldNotCancelRunningActionWithTheSameDistributionSet() { // manually assign distribution set to target final String knownControllerId = "controller12345"; - final DistributionSet knownDistributionSet = testdataFactory.createDistributionSet(); + final DistributionSet knownDistributionSet = testdataFactory.createDistributionSetLocked(""); testdataFactory.createTarget(knownControllerId); - final DistributionSetAssignmentResult assignmentResult = assignDistributionSet(knownDistributionSet.getId(), - knownControllerId); + final DistributionSetAssignmentResult assignmentResult = assignDistributionSet(knownDistributionSet.getId(), knownControllerId); final Long manuallyAssignedActionId = getFirstAssignedActionId(assignmentResult); // create rollout with the same distribution set already assigned // start rollout - final Rollout rollout = testdataFactory.createRolloutByVariables("rolloutNotCancelRunningAction", "description", - 1, "name==*", knownDistributionSet, "50", "5"); + final Rollout rollout = testdataFactory.createRolloutByVariables( + "rolloutNotCancelRunningAction", "description", 1, "name==*", knownDistributionSet, "50", "5"); rolloutManagement.start(rollout.getId()); rolloutHandler.handleAll(); @@ -325,8 +319,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { verifyThrownExceptionBy(() -> rolloutManagement.resumeRollout(NOT_EXIST_IDL), "Rollout"); verifyThrownExceptionBy(() -> rolloutManagement.start(NOT_EXIST_IDL), "Rollout"); - verifyThrownExceptionBy(() -> rolloutManagement.update(entityFactory.rollout().update(NOT_EXIST_IDL)), - "Rollout"); + verifyThrownExceptionBy(() -> rolloutManagement.update(Update.builder().id(NOT_EXIST_IDL).build()), "Rollout"); verifyThrownExceptionBy(() -> rolloutManagement.triggerNextGroup(NOT_EXIST_IDL), "Rollout"); } @@ -378,8 +371,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { scheduledGroups.forEach(group -> assertThat(group.getStatus()) .as("group which should be in scheduled state is in " + group.getStatus() + " state") .isEqualTo(RolloutGroupStatus.SCHEDULED)); - // verify that the first group actions has been started and are in state - // running + // verify that the first group actions has been started and are in state running final List runningActions = findActionsByRolloutAndStatus(createdRollout, Status.RUNNING); assertThat(runningActions).hasSize(amountTargetsForRollout / amountGroups) .as("Created actions are initiated by rollout creator") @@ -408,7 +400,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { // 50% final JpaAction action = (JpaAction) runningActions.get(0); controllerManagement - .addUpdateActionStatus(entityFactory.actionStatus().create(action.getId()).status(Status.FINISHED)); + .addUpdateActionStatus(ActionStatusCreate.builder().actionId(action.getId()).status(Status.FINISHED).build()); // check running rollouts again, now the finish condition should be hit // and should start the next group @@ -476,7 +468,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { // finish actions with error for (final Action action : runningActions) { controllerManagement - .addUpdateActionStatus(entityFactory.actionStatus().create(action.getId()).status(Status.ERROR)); + .addUpdateActionStatus(ActionStatusCreate.builder().actionId(action.getId()).status(Status.ERROR).build()); } // check running rollouts again, now the error condition should be hit @@ -521,7 +513,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { // finish actions with error for (final Action action : runningActions) { controllerManagement - .addUpdateActionStatus(entityFactory.actionStatus().create(action.getId()).status(Status.ERROR)); + .addUpdateActionStatus(ActionStatusCreate.builder().actionId(action.getId()).status(Status.ERROR).build()); } // check running rollouts again, now the error condition should be hit @@ -1371,8 +1363,6 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { // Run here, because scheduler is disabled during tests rolloutHandler.handleAll(); - awaitRunningState(myRolloutId); - myRollout = getRollout(myRolloutId); assertThat(myRollout.getStatus()).isEqualTo(RolloutStatus.RUNNING); final Map expectedTargetCountStatus = createInitStatusMap(); @@ -1386,7 +1376,6 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { */ @Test void createAndStartRollout() { - final int amountTargetsForRollout = 50; final int amountGroups = 5; final String successCondition = "50"; @@ -1395,30 +1384,24 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { final DistributionSet distributionSet = testdataFactory.createDistributionSet("dsFor" + rolloutName); testdataFactory.createTargets(amountTargetsForRollout, rolloutName + "-", rolloutName); - Rollout myRollout = testdataFactory.createRolloutByVariables(rolloutName, "desc", amountGroups, - "controllerId==" + rolloutName + "-*", distributionSet, successCondition, errorCondition); - + Rollout myRollout = testdataFactory.createRolloutByVariables( + rolloutName, "desc", amountGroups, "controllerId==" + rolloutName + "-*", distributionSet, successCondition, errorCondition); assertThat(myRollout.getStatus()).isEqualTo(RolloutStatus.READY); rolloutHandler.handleAll(); - - final Long myRolloutId = myRollout.getId(); - myRollout = getRollout(myRolloutId); + myRollout = getRollout(myRollout.getId()); assertThat(myRollout.getStatus()).isEqualTo(RolloutStatus.READY); - rolloutManagement.start(myRolloutId); - + rolloutManagement.start(myRollout.getId()); // Run here, because scheduler is disabled during tests rolloutHandler.handleAll(); - - awaitRunningState(myRolloutId); - myRollout = reloadRollout(myRollout); assertThat(myRollout.getStatus()).isEqualTo(RolloutStatus.RUNNING); + final Map expectedTargetCountStatus = createInitStatusMap(); expectedTargetCountStatus.put(TotalTargetCountStatus.Status.RUNNING, 10L); expectedTargetCountStatus.put(TotalTargetCountStatus.Status.SCHEDULED, 40L); - validateRolloutActionStatus(myRolloutId, expectedTargetCountStatus); + validateRolloutActionStatus(myRollout.getId(), expectedTargetCountStatus); } /** @@ -1465,17 +1448,18 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { () -> createRolloutWithStartAt(rolloutName + "_withLongMax", filter, distributionSet, Long.MAX_VALUE)); } - private Rollout createRolloutWithStartAt(final String rolloutName, final String filter, final DistributionSet distributionSet, - final Long startAt) { + private Rollout createRolloutWithStartAt( + final String rolloutName, final String filter, final DistributionSet distributionSet, final Long startAt) { return rolloutManagement.create( - entityFactory.rollout().create() + Create.builder() .name(rolloutName) .description("desc") .targetFilterQuery(filter) - .distributionSetId(distributionSet) + .distributionSet(distributionSet) .weight(1000) .startAt(startAt) - .dynamic(false), + .dynamic(false) + .build(), 5, false, new RolloutGroupConditionBuilder().withDefaults() .successCondition(RolloutGroupSuccessCondition.THRESHOLD, "80") .errorCondition(RolloutGroupErrorCondition.THRESHOLD, "50") @@ -1504,8 +1488,10 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { .errorCondition(RolloutGroupErrorCondition.THRESHOLD, errorCondition) .errorAction(RolloutGroupErrorAction.PAUSE, null).build(); - final RolloutCreate rollout = entityFactory.rollout().create().name(rolloutName).description(rolloutName) - .targetFilterQuery("controllerId==" + targetPrefixName + "-*").distributionSetId(distributionSet); + final Create rollout = Create.builder() + .name(rolloutName).description(rolloutName) + .targetFilterQuery("controllerId==" + targetPrefixName + "-*").distributionSet(distributionSet) + .build(); assertThatExceptionOfType(AssignmentQuotaExceededException.class) .isThrownBy(() -> rolloutManagement.create(rollout, amountGroups, false, conditions)); @@ -1526,37 +1512,36 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { final RolloutGroupConditions conditions = new RolloutGroupConditionBuilder().withDefaults().build(); // create group definitions - final RolloutGroupCreate group1 = entityFactory.rolloutGroup().create().conditions(conditions).name("group1").targetPercentage(50.0F); - final RolloutGroupCreate group2 = entityFactory.rolloutGroup().create().conditions(conditions).name("group2").targetPercentage(50.0F); + final GroupCreate group1 = GroupCreate.builder().conditions(conditions).name("group1").targetPercentage(50.0F).build(); + final GroupCreate group2 = GroupCreate.builder().conditions(conditions).name("group2").targetPercentage(50.0F).build(); // group1 exceeds the quota - final RolloutCreate rolloutCreate = entityFactory.rollout().create() + final Create rolloutCreate = Create.builder() .name(rolloutName) .description(rolloutName) .targetFilterQuery("controllerId==" + rolloutName + "-*") - .distributionSetId(distributionSet); - final List groups = List.of(group1, group2); + .distributionSet(distributionSet) + .build(); + final List groups = List.of(group1, group2); assertThatExceptionOfType(AssignmentQuotaExceededException.class) .isThrownBy(() -> rolloutManagement.create(rolloutCreate, groups, conditions)); // create group definitions - final RolloutGroupCreate group3 = entityFactory.rolloutGroup().create().conditions(conditions).name("group3").targetPercentage(1.0F); - final RolloutGroupCreate group4 = entityFactory.rolloutGroup().create().conditions(conditions).name("group4").targetPercentage(100.0F); + final GroupCreate group3 = GroupCreate.builder().conditions(conditions).name("group3").targetPercentage(1.0F).build(); + final GroupCreate group4 = GroupCreate.builder().conditions(conditions).name("group4").targetPercentage(100.0F).build(); // group4 exceeds the quota - final List groups2 = List.of(group3, group4); + final List groups2 = List.of(group3, group4); assertThatExceptionOfType(AssignmentQuotaExceededException.class) .isThrownBy(() -> rolloutManagement.create(rolloutCreate, groups2, conditions)); // create group definitions - final RolloutGroupCreate group5 = entityFactory.rolloutGroup().create().conditions(conditions).name("group5").targetPercentage(33.3F); - final RolloutGroupCreate group6 = entityFactory.rolloutGroup().create().conditions(conditions).name("group6").targetPercentage(33.3F); - final RolloutGroupCreate group7 = entityFactory.rolloutGroup().create().conditions(conditions).name("group7").targetPercentage(33.3F); + final GroupCreate group5 = GroupCreate.builder().conditions(conditions).name("group5").targetPercentage(33.3F).build(); + final GroupCreate group6 = GroupCreate.builder().conditions(conditions).name("group6").targetPercentage(33.3F).build(); + final GroupCreate group7 = GroupCreate.builder().conditions(conditions).name("group7").targetPercentage(33.3F).build(); // should work fine - assertThat(rolloutManagement.create( - rolloutCreate, - Arrays.asList(group5, group6, group7), conditions)).isNotNull(); + assertThat(rolloutManagement.create(rolloutCreate, Arrays.asList(group5, group6, group7), conditions)).isNotNull(); } /** @@ -1579,8 +1564,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { // schedule rollout auto start into the future final Long myRolloutId = myRollout.getId(); - rolloutManagement - .update(entityFactory.rollout().update(myRolloutId).name("newName").description("newDesc")); + rolloutManagement.update(Update.builder().id(myRolloutId).name("newName").description("newDesc").build()); rolloutHandler.handleAll(); // rollout should not have been started @@ -1593,7 +1577,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { * Verify the creation of a rollout with a groups definition. */ @Test - void createRolloutWithGroupDefinition() throws Exception { + void createRolloutWithGroupDefinition() { final String rolloutName = "rolloutTest3"; final int amountTargetsInGroup1 = 10; @@ -1609,12 +1593,12 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { final RolloutGroupConditions conditions = new RolloutGroupConditionBuilder().withDefaults().build(); // Generate Targets for group 2 and 3 and generate the Rollout - final RolloutCreate rolloutcreate = generateTargetsAndRollout(rolloutName, amountTargetsInGroup2and3); + final Create rolloutcreate = generateTargetsAndRollout(rolloutName, amountTargetsInGroup2and3); // Generate Targets for group 1 testdataFactory.createTargets(amountTargetsInGroup1, rolloutName + "-gr1-", rolloutName); - final List rolloutGroups = new ArrayList<>(3); + final List rolloutGroups = new ArrayList<>(3); rolloutGroups.add(generateRolloutGroup(0, percentTargetsInGroup1, "id==" + rolloutName + "-gr1-*")); rolloutGroups.add(generateRolloutGroup(1, percentTargetsInGroup2, null)); rolloutGroups.add(generateRolloutGroup(2, percentTargetsInGroup3, null)); @@ -1627,9 +1611,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { assertThat(group.getStatus()).isEqualTo(RolloutGroupStatus.CREATING); } - // Generate Targets that must not be addressed by the rollout, because - // they were added after the rollout was created - TimeUnit.SECONDS.sleep(1); + // Generate Targets that must not be addressed by the rollout, because they were added after the rollout was created testdataFactory.createTargets(10, rolloutName + "-notIn-", rolloutName); rolloutHandler.handleAll(); @@ -1648,7 +1630,6 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { assertThat(groups.get(2).getStatus()).isEqualTo(RolloutGroupStatus.READY); assertThat(groups.get(2).getTotalTargets()).isEqualTo(countTargetsInGroup3); - } /** @@ -1663,12 +1644,12 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { final RolloutGroupConditions conditions = new RolloutGroupConditionBuilder().withDefaults().build(); // Generate Targets for group 2 - final RolloutCreate rolloutcreate = generateTargetsAndRollout(rolloutName, amountTargetsInGroup2); + final Create rolloutcreate = generateTargetsAndRollout(rolloutName, amountTargetsInGroup2); // Generate Targets for group 1 testdataFactory.createTargets(amountTargetsInGroup1, rolloutName + "-gr1-", rolloutName); - final List rolloutGroups = new ArrayList<>(3); + final List rolloutGroups = new ArrayList<>(3); rolloutGroups.add(generateRolloutGroup(0, 100, "id==" + rolloutName + "-gr1-*", true)); rolloutGroups.add(generateRolloutGroup(1, 100, null, false)); @@ -1740,9 +1721,9 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { final int percentTargetsInGroup2 = 50; final RolloutGroupConditions conditions = new RolloutGroupConditionBuilder().withDefaults().build(); - final RolloutCreate myRollout = generateTargetsAndRollout(rolloutName, amountTargetsForRollout); + final Create myRollout = generateTargetsAndRollout(rolloutName, amountTargetsForRollout); - final List rolloutGroups = new ArrayList<>(2); + final List rolloutGroups = new ArrayList<>(2); rolloutGroups.add(generateRolloutGroup(0, percentTargetsInGroup1, null)); rolloutGroups.add(generateRolloutGroup(1, percentTargetsInGroup2, null)); @@ -1763,9 +1744,9 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { final int percentTargetsInGroup2 = 50; final RolloutGroupConditions conditions = new RolloutGroupConditionBuilder().withDefaults().build(); - final RolloutCreate myRollout = generateTargetsAndRollout(rolloutName, amountTargetsForRollout); + final Create myRollout = generateTargetsAndRollout(rolloutName, amountTargetsForRollout); - final List rolloutGroups = Arrays.asList( + final List rolloutGroups = Arrays.asList( generateRolloutGroup(0, percentTargetsInGroup1, null), generateRolloutGroup(1, percentTargetsInGroup2, null)); @@ -1785,7 +1766,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { final int maxGroups = quotaManagement.getMaxRolloutGroupsPerRollout(); final RolloutGroupConditions conditions = new RolloutGroupConditionBuilder().withDefaults().build(); - final RolloutCreate rollout = generateTargetsAndRollout(rolloutName, targets); + final Create rollout = generateTargetsAndRollout(rolloutName, targets); assertThatExceptionOfType(AssignmentQuotaExceededException.class) .isThrownBy(() -> rolloutManagement.create(rollout, maxGroups + 1, false, conditions)) @@ -1809,8 +1790,10 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { .successCondition(RolloutGroupSuccessCondition.THRESHOLD, successCondition) .errorCondition(RolloutGroupErrorCondition.THRESHOLD, errorCondition) .errorAction(RolloutGroupErrorAction.PAUSE, null).build(); - final RolloutCreate rolloutToCreate = entityFactory.rollout().create().name(rolloutName) - .description("some description").targetFilterQuery("id==" + rolloutName + "-*").distributionSetId(distributionSet); + final Create rolloutToCreate = Create.builder() + .name(rolloutName).description("some description") + .targetFilterQuery("id==" + rolloutName + "-*").distributionSet(distributionSet) + .build(); Rollout myRollout = rolloutManagement.create(rolloutToCreate, amountGroups, false, conditions); myRollout = getRollout(myRollout.getId()); @@ -1964,7 +1947,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { assertThat(deletedRollout.getStatus()).isEqualTo(RolloutStatus.DELETED); - final RolloutUpdate rolloutUpdate = entityFactory.rollout().update(createdRollout.getId()).description("test"); + final Update rolloutUpdate = Update.builder().id(createdRollout.getId()).description("test").build(); assertThatExceptionOfType(EntityReadOnlyException.class) .isThrownBy(() -> rolloutManagement.update(rolloutUpdate)) .withMessageContaining("" + createdRollout.getId()); @@ -1995,9 +1978,9 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { final RolloutGroupConditions conditions = new RolloutGroupConditionBuilder().withDefaults().build(); final String prefixRolloutRunning = randomString + "1"; - final RolloutCreate rolloutRunningCreate = entityFactory.rollout().create() - .name(prefixRolloutRunning + "-testRollout").targetFilterQuery("name==" + randomString + "*") - .distributionSetId(testDs); + final Create rolloutRunningCreate = Create.builder() + .name(prefixRolloutRunning + "-testRollout").targetFilterQuery("name==" + randomString + "*").distributionSet(testDs) + .build(); Rollout rolloutRunning = rolloutManagement.create(rolloutRunningCreate, 1, false, conditions); // Let the executor handle created Rollout @@ -2009,8 +1992,8 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { rolloutRunning = reloadRollout(rolloutRunning); final String prefixRolloutReady = randomString + "2"; - final RolloutCreate rolloutReadyCreate = entityFactory.rollout().create() - .name(prefixRolloutReady + "-testRollout").targetFilterQuery("name==" + randomString + "*").distributionSetId(testDs); + final Create rolloutReadyCreate = Create.builder() + .name(prefixRolloutReady + "-testRollout").targetFilterQuery("name==" + randomString + "*").distributionSet(testDs).build(); Rollout rolloutReady = rolloutManagement.create(rolloutReadyCreate, 1, false, conditions); // Let the executor handle created Rollout rolloutHandler.handleAll(); @@ -2158,8 +2141,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { targets.addAll(targetsWithoutType); final RolloutGroupConditions conditions = new RolloutGroupConditionBuilder().withDefaults().build(); - final RolloutCreate rolloutToCreate = entityFactory.rollout().create() - .name(rolloutName).targetFilterQuery("name==*").distributionSetId(testDs); + final Create rolloutToCreate = Create.builder().name(rolloutName).targetFilterQuery("name==*").distributionSet(testDs).build(); final Rollout createdRollout = rolloutManagement.create(rolloutToCreate, 1, false, conditions); @@ -2415,26 +2397,26 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { }); } - private RolloutGroupCreate generateRolloutGroup(final int index, final Integer percentage, - final String targetFilter) { + private GroupCreate generateRolloutGroup(final int index, final Integer percentage, final String targetFilter) { return generateRolloutGroup(index, percentage, targetFilter, false); } - private RolloutGroupCreate generateRolloutGroup(final int index, final Integer percentage, + private GroupCreate generateRolloutGroup(final int index, final Integer percentage, final String targetFilter, final boolean confirmationRequired) { - return entityFactory.rolloutGroup().create().name("Group" + index).description("Group" + index + "desc") + return GroupCreate.builder().name("Group" + index).description("Group" + index + "desc") .targetPercentage(Float.valueOf(percentage)).targetFilterQuery(targetFilter) - .confirmationRequired(confirmationRequired); + .confirmationRequired(confirmationRequired).build(); } - private RolloutCreate generateTargetsAndRollout(final String rolloutName, final int amountTargetsForRollout) { + private Create generateTargetsAndRollout(final String rolloutName, final int amountTargetsForRollout) { final DistributionSet distributionSet = testdataFactory.createDistributionSet("dsFor" + rolloutName); testdataFactory.createTargets(amountTargetsForRollout, rolloutName + "-", rolloutName); - return entityFactory.rollout().create().name(rolloutName) - .description("This is a test description for the rollout") - .targetFilterQuery("controllerId==" + rolloutName + "-*").distributionSetId(distributionSet); + return Create.builder() + .name(rolloutName).description("This is a test description for the rollout") + .targetFilterQuery("controllerId==" + rolloutName + "-*").distributionSet(distributionSet) + .build(); } private void validateRolloutGroupActionStatus(final RolloutGroup rolloutGroup, @@ -2479,7 +2461,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { final List runningActions = findActionsByRolloutAndStatus(rollout, Status.RUNNING); for (final Action action : runningActions) { controllerManagement - .addUpdateActionStatus(entityFactory.actionStatus().create(action.getId()).status(status)); + .addUpdateActionStatus(ActionStatusCreate.builder().actionId(action.getId()).status(status).build()); } return runningActions.size(); } @@ -2490,18 +2472,8 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { assertThat(runningActions).hasSizeGreaterThanOrEqualTo(amountOfTargetsToGetChanged); for (int i = 0; i < amountOfTargetsToGetChanged; i++) { controllerManagement.addUpdateActionStatus( - entityFactory.actionStatus().create(runningActions.get(i).getId()).status(status)); + ActionStatusCreate.builder().actionId(runningActions.get(i).getId()).status(status).build()); } return runningActions.size(); } - - private void awaitRunningState(final Long myRolloutId) { - Awaitility.await() - .pollInterval(Duration.ofMillis(500)) - .atMost(Duration.ofSeconds(10)) - .until(() -> SecurityContextSwitch - .callAsPrivileged( - () -> rolloutManagement.get(myRolloutId).orElseThrow(NoSuchElementException::new)) - .getStatus().equals(RolloutStatus.RUNNING)); - } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementSearchTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementSearchTest.java index 6c7f79895..96ec21dd9 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementSearchTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementSearchTest.java @@ -18,6 +18,7 @@ import java.util.Set; import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; +import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate; import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetType; @@ -84,7 +85,8 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest { // set on installed and assign another one assignDistributionSet(installedSet, installedtargets).getAssignedEntity().forEach(action -> - controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(action.getId()).status(Status.FINISHED))); + controllerManagement.addUpdateActionStatus( + ActionStatusCreate.builder().actionId(action.getId()).status(Status.FINISHED).build())); assignDistributionSet(assignedSet, installedtargets); // get final updated version of targets diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementTest.java index 2b29a88ee..efd031f72 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementTest.java @@ -70,6 +70,7 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_; import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility; import org.eclipse.hawkbit.repository.model.Action; +import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate; import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult; @@ -326,7 +327,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { implicitLock(testDs1); controllerManagement.addUpdateActionStatus( - entityFactory.actionStatus().create(getFirstAssignedActionId(result)).status(Status.FINISHED)); + ActionStatusCreate.builder().actionId(getFirstAssignedActionId(result)).status(Status.FINISHED).build()); assignDistributionSet(testDs2.getId(), "4711"); implicitLock(testDs2); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlRolloutFieldTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlRolloutFieldTest.java index e15a830d1..7c32c2408 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlRolloutFieldTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlRolloutFieldTest.java @@ -12,6 +12,7 @@ package org.eclipse.hawkbit.repository.jpa.rsql; import static org.assertj.core.api.Assertions.assertThat; import org.eclipse.hawkbit.repository.RolloutFields; +import org.eclipse.hawkbit.repository.RolloutManagement.Create; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.Rollout; @@ -58,8 +59,9 @@ class RsqlRolloutFieldTest extends AbstractJpaIntegrationTest { private Rollout createRollout(final String name, final int amountGroups, final long distributionSetId, final String targetFilterQuery) { return rolloutManagement.create( - entityFactory.rollout().create().distributionSetId( - distributionSetManagement.get(distributionSetId).get()).name(name).targetFilterQuery(targetFilterQuery), + Create.builder() + .distributionSet(distributionSetManagement.get(distributionSetId).get()).name(name).targetFilterQuery(targetFilterQuery) + .build(), amountGroups, false, new RolloutGroupConditionBuilder().withDefaults().successCondition(RolloutGroupSuccessCondition.THRESHOLD, "100").build()); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlRolloutGroupFieldTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlRolloutGroupFieldTest.java index b5976f56e..eb4b9c9cc 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlRolloutGroupFieldTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlRolloutGroupFieldTest.java @@ -12,6 +12,7 @@ package org.eclipse.hawkbit.repository.jpa.rsql; import static org.assertj.core.api.Assertions.assertThat; import org.eclipse.hawkbit.repository.RolloutGroupFields; +import org.eclipse.hawkbit.repository.RolloutManagement.Create; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.Rollout; @@ -100,8 +101,9 @@ class RsqlRolloutGroupFieldTest extends AbstractJpaIntegrationTest { private Rollout createRollout(final String name, final int amountGroups, final long distributionSetId, final String targetFilterQuery) { return rolloutManagement.create( - entityFactory.rollout().create().distributionSetId(distributionSetManagement.get(distributionSetId).get()).name(name) - .targetFilterQuery(targetFilterQuery), + Create.builder() + .distributionSet(distributionSetManagement.get(distributionSetId).get()).name(name).targetFilterQuery(targetFilterQuery) + .build(), amountGroups, false, new RolloutGroupConditionBuilder().withDefaults() .successCondition(RolloutGroupSuccessCondition.THRESHOLD, "100").build()); } diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java index 06466d21a..a98da7922 100644 --- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java +++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java @@ -39,7 +39,6 @@ import org.eclipse.hawkbit.repository.DistributionSetInvalidationManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetTagManagement; import org.eclipse.hawkbit.repository.DistributionSetTypeManagement; -import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.QuotaManagement; import org.eclipse.hawkbit.repository.RepositoryConstants; import org.eclipse.hawkbit.repository.RolloutGroupManagement; @@ -57,6 +56,7 @@ import org.eclipse.hawkbit.repository.artifact.ArtifactRepository; import org.eclipse.hawkbit.repository.artifact.exception.ArtifactStoreException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.model.Action; +import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate; import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.model.DeploymentRequest; import org.eclipse.hawkbit.repository.model.DistributionSet; @@ -129,8 +129,6 @@ public abstract class AbstractIntegrationTest { */ protected static final int DEFAULT_DS_TYPES = RepositoryConstants.DEFAULT_DS_TYPES_IN_TENANT + 1; - @Autowired - protected EntityFactory entityFactory; @Autowired protected SoftwareModuleManagement softwareModuleManagement; @Autowired @@ -457,9 +455,9 @@ public abstract class AbstractIntegrationTest { } controllerManagement.addUpdateActionStatus( - entityFactory.actionStatus().create(savedAction.getId()).status(Action.Status.RUNNING)); + ActionStatusCreate.builder().actionId(savedAction.getId()).status(Action.Status.RUNNING).build()); controllerManagement.addUpdateActionStatus( - entityFactory.actionStatus().create(savedAction.getId()).status(Action.Status.FINISHED)); + ActionStatusCreate.builder().actionId(savedAction.getId()).status(Action.Status.FINISHED).build()); return controllerManagement.findActionWithDetails(savedAction.getId()) .orElseThrow(() -> new EntityNotFoundException(Action.class, savedAction.getId())); diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestdataFactory.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestdataFactory.java index 49f2a6b1e..5d85f994a 100644 --- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestdataFactory.java +++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestdataFactory.java @@ -38,7 +38,6 @@ import org.eclipse.hawkbit.repository.DistributionSetInvalidationManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetTagManagement; import org.eclipse.hawkbit.repository.DistributionSetTypeManagement; -import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.QuotaManagement; import org.eclipse.hawkbit.repository.RolloutHandler; import org.eclipse.hawkbit.repository.RolloutManagement; @@ -49,8 +48,8 @@ import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.AutoAssignDist import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.TargetTagManagement; import org.eclipse.hawkbit.repository.TargetTypeManagement; -import org.eclipse.hawkbit.repository.builder.DynamicRolloutGroupTemplate; import org.eclipse.hawkbit.repository.model.Action; +import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate; import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.ActionStatus; @@ -161,7 +160,6 @@ public class TestdataFactory { private final RolloutManagement rolloutManagement; private final RolloutHandler rolloutHandler; private final QuotaManagement quotaManagement; - private final EntityFactory entityFactory; private final TenantAware tenantAware; public TestdataFactory( @@ -178,8 +176,7 @@ public class TestdataFactory { final TargetTagManagement targetTagManagement, final DeploymentManagement deploymentManagement, final RolloutManagement rolloutManagement, final RolloutHandler rolloutHandler, - final QuotaManagement quotaManagement, - final EntityFactory entityFactory, final TenantAware tenantAware) { + final QuotaManagement quotaManagement, final TenantAware tenantAware) { this.controllerManagement = controllerManagement; this.softwareModuleManagement = softwareModuleManagement; this.softwareModuleTypeManagement = softwareModuleTypeManagement; @@ -192,7 +189,6 @@ public class TestdataFactory { this.targetTypeManagement = targetTypeManagement; this.targetTagManagement = targetTagManagement; this.deploymentManagement = deploymentManagement; - this.entityFactory = entityFactory; this.artifactManagement = artifactManagement; this.rolloutManagement = rolloutManagement; this.rolloutHandler = rolloutHandler; @@ -229,6 +225,10 @@ public class TestdataFactory { return createDistributionSet(prefix, DEFAULT_VERSION, false); } + public DistributionSet createDistributionSetLocked(final String prefix) { + return distributionSetManagement.lock(createDistributionSet(prefix)); + } + /** * Creates {@link DistributionSet} in repository including three * {@link SoftwareModule}s of types {@link #SM_TYPE_OS}, {@link #SM_TYPE_RT} , @@ -241,6 +241,11 @@ public class TestdataFactory { return createDistributionSet(UUID.randomUUID().toString(), DEFAULT_VERSION, false); } + + public DistributionSet createDistributionSetLocked() { + return distributionSetManagement.lock(createDistributionSet()); + } + /** * Creates {@link DistributionSet} in repository including three * {@link SoftwareModule}s of types {@link #SM_TYPE_OS}, {@link #SM_TYPE_RT} , @@ -1027,21 +1032,22 @@ public class TestdataFactory { final int groupSize, final String filterQuery, final DistributionSet distributionSet, final String successCondition, final String errorCondition, final Action.ActionType actionType, final Integer weight, final boolean confirmationRequired, final boolean dynamic, - final DynamicRolloutGroupTemplate dynamicRolloutGroupTemplate) { + final RolloutManagement.DynamicRolloutGroupTemplate dynamicRolloutGroupTemplate) { final RolloutGroupConditions conditions = new RolloutGroupConditionBuilder().withDefaults() .successCondition(RolloutGroupSuccessCondition.THRESHOLD, successCondition) .errorCondition(RolloutGroupErrorCondition.THRESHOLD, errorCondition) .errorAction(RolloutGroupErrorAction.PAUSE, null).build(); final Rollout rollout = rolloutManagement.create( - entityFactory.rollout().create() + RolloutManagement.Create.builder() .name(rolloutName) .description(rolloutDescription) .targetFilterQuery(filterQuery) - .distributionSetId(distributionSet) - .actionType(actionType) + .distributionSet(distributionSet) + .actionType(actionType == null ? Action.ActionType.FORCED : actionType) .weight(weight) - .dynamic(dynamic), + .dynamic(dynamic) + .build(), groupSize, confirmationRequired, conditions, dynamicRolloutGroupTemplate); // Run here, because Scheduler is disabled during tests @@ -1259,7 +1265,8 @@ public class TestdataFactory { } private Action sendUpdateActionStatusToTarget(final Status status, final Action updActA, final Collection msgs) { - return controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(updActA.getId()).status(status).messages(msgs)); + return controllerManagement.addUpdateActionStatus( + ActionStatusCreate.builder().actionId(updActA.getId()).status(status).messages(msgs).build()); } private Rollout startAndReloadRollout(final Rollout rollout) {