Add PollStatus to result of list targets via REST API (#1734)

Signed-off-by: Marinov Avgustin <Avgustin.Marinov@bosch.com>
This commit is contained in:
Avgustin Marinov
2024-05-22 11:02:21 +03:00
committed by GitHub
parent deb524d438
commit 7d62e81515
5 changed files with 50 additions and 31 deletions

View File

@@ -10,11 +10,18 @@
package org.eclipse.hawkbit.repository; package org.eclipse.hawkbit.repository;
import java.io.Serializable; import java.io.Serializable;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Map; import java.util.Map;
import java.util.function.Function;
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions; import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
import org.eclipse.hawkbit.repository.model.TenantConfiguration; import org.eclipse.hawkbit.repository.model.PollStatus;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue; import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
import org.eclipse.hawkbit.tenancy.configuration.DurationHelper;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
import org.eclipse.hawkbit.tenancy.configuration.validator.TenantConfigurationValidatorException; import org.eclipse.hawkbit.tenancy.configuration.validator.TenantConfigurationValidatorException;
import org.springframework.core.convert.ConversionFailedException; import org.springframework.core.convert.ConversionFailedException;
@@ -142,4 +149,26 @@ public interface TenantConfigurationManagement {
*/ */
@PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION_READ) @PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION_READ)
<T> T getGlobalConfigurationValue(String configurationKeyName, Class<T> propertyType); <T> T getGlobalConfigurationValue(String configurationKeyName, Class<T> propertyType);
// PreAuthorize for TENANT_CONFIGURATION_READ won't be applied but actually we want just read target
@PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_READ_TARGET)
default Function<Target, PollStatus> pollStatusResolver() {
final Duration pollTime = DurationHelper.formattedStringToDuration(
getConfigurationValue(TenantConfigurationKey.POLLING_TIME_INTERVAL, String.class).getValue());
final Duration overdueTime = DurationHelper.formattedStringToDuration(
getConfigurationValue(TenantConfigurationKey.POLLING_OVERDUE_TIME_INTERVAL, String.class)
.getValue());
return target -> {
final Long lastTargetQuery = target.getLastTargetQuery();
if (lastTargetQuery == null) {
return null;
}
final LocalDateTime currentDate = LocalDateTime.now();
final LocalDateTime lastPollDate = LocalDateTime.ofInstant(Instant.ofEpochMilli(lastTargetQuery),
ZoneId.systemDefault());
final LocalDateTime nextPollDate = lastPollDate.plus(pollTime);
final LocalDateTime overdueDate = nextPollDate.plus(overdueTime);
return new PollStatus(lastPollDate, nextPollDate, overdueDate, currentDate);
};
}
} }

View File

@@ -13,9 +13,12 @@ import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationPrope
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.USER_CONFIRMATION_ENABLED; import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.USER_CONFIRMATION_ENABLED;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.model.PollStatus;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.security.SystemSecurityContext;
import java.io.Serializable; import java.io.Serializable;
import java.util.function.Function;
/** /**
* A collection of static helper methods for the tenant configuration * A collection of static helper methods for the tenant configuration
@@ -67,4 +70,8 @@ public final class TenantConfigHelper {
public boolean isConfirmationFlowEnabled() { public boolean isConfirmationFlowEnabled() {
return getConfigValue(USER_CONFIRMATION_ENABLED, Boolean.class); return getConfigValue(USER_CONFIRMATION_ENABLED, Boolean.class);
} }
public Function<Target, PollStatus> pollStatusResolver() {
return tenantConfigurationManagement.pollStatusResolver();
}
} }

View File

@@ -11,10 +11,6 @@ package org.eclipse.hawkbit.repository.jpa.model;
import java.io.Serial; import java.io.Serial;
import java.net.URI; import java.net.URI;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
@@ -65,8 +61,6 @@ import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder;
import org.eclipse.hawkbit.repository.model.helper.SystemSecurityContextHolder; import org.eclipse.hawkbit.repository.model.helper.SystemSecurityContextHolder;
import org.eclipse.hawkbit.repository.model.helper.TenantConfigurationManagementHolder; import org.eclipse.hawkbit.repository.model.helper.TenantConfigurationManagementHolder;
import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.tenancy.configuration.DurationHelper;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
import org.eclipse.persistence.annotations.CascadeOnDelete; import org.eclipse.persistence.annotations.CascadeOnDelete;
import org.eclipse.persistence.annotations.ConversionValue; import org.eclipse.persistence.annotations.ConversionValue;
import org.eclipse.persistence.annotations.Convert; import org.eclipse.persistence.annotations.Convert;
@@ -361,24 +355,12 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Target, EventAw
*/ */
@Override @Override
public PollStatus getPollStatus() { public PollStatus getPollStatus() {
// skip creating resolver
if (lastTargetQuery == null) { if (lastTargetQuery == null) {
return null; return null;
} }
return SystemSecurityContextHolder.getInstance().getSystemSecurityContext().runAsSystem(() -> { return TenantConfigurationManagementHolder.getInstance().getTenantConfigurationManagement()
final Duration pollTime = DurationHelper.formattedStringToDuration(TenantConfigurationManagementHolder .pollStatusResolver().apply(this);
.getInstance().getTenantConfigurationManagement()
.getConfigurationValue(TenantConfigurationKey.POLLING_TIME_INTERVAL, String.class).getValue());
final Duration overdueTime = DurationHelper.formattedStringToDuration(
TenantConfigurationManagementHolder.getInstance().getTenantConfigurationManagement()
.getConfigurationValue(TenantConfigurationKey.POLLING_OVERDUE_TIME_INTERVAL, String.class)
.getValue());
final LocalDateTime currentDate = LocalDateTime.now();
final LocalDateTime lastPollDate = LocalDateTime.ofInstant(Instant.ofEpochMilli(lastTargetQuery),
ZoneId.systemDefault());
final LocalDateTime nextPollDate = lastPollDate.plus(pollTime);
final LocalDateTime overdueDate = nextPollDate.plus(overdueTime);
return new PollStatus(lastPollDate, nextPollDate, overdueDate, currentDate);
});
} }
@Override @Override

View File

@@ -18,6 +18,7 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.eclipse.hawkbit.mgmt.json.model.MgmtMaintenanceWindow; import org.eclipse.hawkbit.mgmt.json.model.MgmtMaintenanceWindow;
@@ -114,8 +115,8 @@ public final class MgmtTargetMapper {
return response; return response;
} }
static void addPollStatus(final Target target, final MgmtTarget targetRest) { private static void addPollStatus(final Target target, final MgmtTarget targetRest, final Function<Target, PollStatus> pollStatusResolver) {
final PollStatus pollStatus = target.getPollStatus(); final PollStatus pollStatus = pollStatusResolver == null ? target.getPollStatus() : pollStatusResolver.apply(target);
if (pollStatus != null) { if (pollStatus != null) {
final MgmtPollStatus pollStatusRest = new MgmtPollStatus(); final MgmtPollStatus pollStatusRest = new MgmtPollStatus();
pollStatusRest.setLastRequestAt( pollStatusRest.setLastRequestAt(
@@ -139,8 +140,9 @@ public final class MgmtTargetMapper {
return Collections.emptyList(); return Collections.emptyList();
} }
final Function<Target, PollStatus> pollStatusResolver = configHelper.pollStatusResolver();
return new ResponseList<>( return new ResponseList<>(
targets.stream().map(target -> toResponse(target, configHelper)).collect(Collectors.toList())); targets.stream().map(target -> toResponse(target, configHelper, pollStatusResolver)).collect(Collectors.toList()));
} }
/** /**
@@ -150,7 +152,7 @@ public final class MgmtTargetMapper {
* the target * the target
* @return the response * @return the response
*/ */
public static MgmtTarget toResponse(final Target target, final TenantConfigHelper configHelper) { public static MgmtTarget toResponse(final Target target, final TenantConfigHelper configHelper, final Function<Target, PollStatus> pollStatusResolver) {
if (target == null) { if (target == null) {
return null; return null;
} }
@@ -198,6 +200,8 @@ public final class MgmtTargetMapper {
targetRest.add( targetRest.add(
linkTo(methodOn(MgmtTargetRestApi.class).getTarget(target.getControllerId())).withSelfRel().expand()); linkTo(methodOn(MgmtTargetRestApi.class).getTarget(target.getControllerId())).withSelfRel().expand());
addPollStatus(target, targetRest, pollStatusResolver == null ? configHelper.pollStatusResolver() : pollStatusResolver);
return targetRest; return targetRest;
} }

View File

@@ -17,7 +17,6 @@ import java.util.Map.Entry;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import jakarta.validation.Valid;
import jakarta.validation.ValidationException; import jakarta.validation.ValidationException;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -99,8 +98,7 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
public ResponseEntity<MgmtTarget> getTarget(@PathVariable("targetId") final String targetId) { public ResponseEntity<MgmtTarget> getTarget(@PathVariable("targetId") final String targetId) {
final Target findTarget = findTargetWithExceptionIfNotFound(targetId); final Target findTarget = findTargetWithExceptionIfNotFound(targetId);
// to single response include poll status // to single response include poll status
final MgmtTarget response = MgmtTargetMapper.toResponse(findTarget, tenantConfigHelper); final MgmtTarget response = MgmtTargetMapper.toResponse(findTarget, tenantConfigHelper, null);
MgmtTargetMapper.addPollStatus(findTarget, response);
MgmtTargetMapper.addTargetLinks(response); MgmtTargetMapper.addTargetLinks(response);
return ResponseEntity.ok(response); return ResponseEntity.ok(response);
@@ -172,8 +170,7 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
} }
final MgmtTarget response = MgmtTargetMapper.toResponse(updateTarget, tenantConfigHelper); final MgmtTarget response = MgmtTargetMapper.toResponse(updateTarget, tenantConfigHelper, null);
MgmtTargetMapper.addPollStatus(updateTarget, response);
MgmtTargetMapper.addTargetLinks(response); MgmtTargetMapper.addTargetLinks(response);
return ResponseEntity.ok(response); return ResponseEntity.ok(response);