Integrated Maintenance Window fields in Management API and UI (#677)

* Added Maintenance Window properties to API and UI

* extended Management API with Maintenance Window schedule, duration, timezone and nextAt properties
* extended integration tests for the above properties
* extended Management UI with Maintenance Window column in Action History grid, added tooltip for next execution
* general refactoring

Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch-si.com>

* fixed Sonar issues

Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch-si.com>

* changed the documentation help link for maintenance window

Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch-si.com>

* added licence header, first refactoring after partial PR review

Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch-si.com>

* changes related to PR review findings

Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch-si.com>

* last PR review findings

Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch-si.com>
This commit is contained in:
Bondar Bogdan
2018-05-15 11:12:33 +02:00
committed by Dominic Schabel
parent 1deb47a4db
commit b5114081be
22 changed files with 474 additions and 210 deletions

View File

@@ -55,7 +55,7 @@ public final class MaintenanceScheduleHelper {
* start time of a maintenance window calculated based on the
* cron expression is relative to this time zone.
*
* @return {@link Optional<ZonedDateTime>} of the next available window. In
* @return { @link Optional<ZonedDateTime>} of the next available window. In
* case there is none, or there are maintenance window validation
* errors, returns empty value.
*

View File

@@ -8,6 +8,8 @@
*/
package org.eclipse.hawkbit.repository.model;
import java.time.ZonedDateTime;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
/**
@@ -18,7 +20,7 @@ public interface Action extends TenantAwareBaseEntity {
/**
* Maximum length of controllerId.
*/
int MAINTENANCE_SCHEDULE_CRON_LENGTH = 128;
int MAINTENANCE_WINDOW_SCHEDULE_LENGTH = 128;
/**
* Maximum length of controllerId.
@@ -81,6 +83,21 @@ public interface Action extends TenantAwareBaseEntity {
*/
Rollout getRollout();
/**
* @return maintenance window schedule related to this {@link Action}.
*/
String getMaintenanceWindowSchedule();
/**
* @return maintenance window duration related to this {@link Action}.
*/
String getMaintenanceWindowDuration();
/**
* @return maintenance window time zone related to this {@link Action}.
*/
String getMaintenanceWindowTimeZone();
/**
* checks if the {@link #getForcedTime()} is hit by the given
* {@code hitTimeMillis}, by means if the given milliseconds are greater
@@ -215,6 +232,15 @@ public interface Action extends TenantAwareBaseEntity {
TIMEFORCED;
}
/**
* Returns the start time of next available maintenance window for the
* {@link Action} as {@link ZonedDateTime}. If a maintenance window is
* already active, the start time of currently active window is returned.
*
* @return the start time as { @link Optional<ZonedDateTime>}.
*/
Optional<ZonedDateTime> getMaintenanceWindowStartTime();
/**
* The method checks whether the action has a maintenance schedule defined
* for it. A maintenance schedule defines a set of maintenance windows

View File

@@ -229,7 +229,7 @@ public abstract class AbstractDsAssignmentStrategy {
actionForTarget.setActive(true);
actionForTarget.setTarget(target);
actionForTarget.setDistributionSet(set);
actionForTarget.setMaintenanceSchedule(targetWithActionType.getMaintenanceSchedule());
actionForTarget.setMaintenanceWindowSchedule(targetWithActionType.getMaintenanceSchedule());
actionForTarget.setMaintenanceWindowDuration(targetWithActionType.getMaintenanceWindowDuration());
actionForTarget.setMaintenanceWindowTimeZone(targetWithActionType.getMaintenanceWindowTimeZone());
return actionForTarget;

View File

@@ -117,8 +117,8 @@ public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Actio
@JoinColumn(name = "rollout", updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_action_rollout"))
private JpaRollout rollout;
@Column(name = "maintenance_cron_schedule", updatable = false, length = Action.MAINTENANCE_SCHEDULE_CRON_LENGTH)
private String maintenanceSchedule;
@Column(name = "maintenance_cron_schedule", updatable = false, length = Action.MAINTENANCE_WINDOW_SCHEDULE_LENGTH)
private String maintenanceWindowSchedule;
@Column(name = "maintenance_duration", updatable = false, length = Action.MAINTENANCE_WINDOW_DURATION_LENGTH)
private String maintenanceWindowDuration;
@@ -231,14 +231,24 @@ public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Actio
// there is no action deletion
}
@Override
public String getMaintenanceWindowSchedule() {
return maintenanceWindowSchedule;
}
/**
* Sets the maintenance schedule.
*
* @param maintenanceSchedule
* @param maintenanceWindowSchedule
* is a cron expression to be used for scheduling.
*/
public void setMaintenanceSchedule(final String maintenanceSchedule) {
this.maintenanceSchedule = maintenanceSchedule;
public void setMaintenanceWindowSchedule(final String maintenanceWindowSchedule) {
this.maintenanceWindowSchedule = maintenanceWindowSchedule;
}
@Override
public String getMaintenanceWindowDuration() {
return maintenanceWindowDuration;
}
/**
@@ -252,6 +262,11 @@ public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Actio
this.maintenanceWindowDuration = maintenanceWindowDuration;
}
@Override
public String getMaintenanceWindowTimeZone() {
return maintenanceWindowTimeZone;
}
/**
* Sets the time zone to be used for maintenance window.
*
@@ -265,15 +280,9 @@ public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Actio
this.maintenanceWindowTimeZone = maintenanceWindowTimeZone;
}
/**
* Returns the start time of next available maintenance window for the
* {@link Action} as {@link ZonedDateTime}. If a maintenance window is
* already active, the start time of currently active window is returned.
*
* @return the start time as {@link Optional<ZonedDateTime>}.
*/
@Override
public Optional<ZonedDateTime> getMaintenanceWindowStartTime() {
return MaintenanceScheduleHelper.getNextMaintenanceWindow(maintenanceSchedule, maintenanceWindowDuration,
return MaintenanceScheduleHelper.getNextMaintenanceWindow(maintenanceWindowSchedule, maintenanceWindowDuration,
maintenanceWindowTimeZone);
}
@@ -282,7 +291,7 @@ public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Actio
* the {@link Action} as {@link ZonedDateTime}. If a maintenance window is
* already active, the end time of currently active window is returned.
*
* @return the end time of window as {@link Optional<ZonedDateTime>}.
* @return the end time of window as { @link Optional<ZonedDateTime>}.
*/
private Optional<ZonedDateTime> getMaintenanceWindowEndTime() {
return getMaintenanceWindowStartTime()
@@ -291,7 +300,7 @@ public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Actio
@Override
public boolean hasMaintenanceSchedule() {
return this.maintenanceSchedule != null;
return this.maintenanceWindowSchedule != null;
}
@Override

View File

@@ -225,7 +225,7 @@ public abstract class AbstractIntegrationTest {
}
};
protected DistributionSetAssignmentResult assignDistributionSet(final Long dsID, final String controllerId) {
protected DistributionSetAssignmentResult assignDistributionSet(final long dsID, final String controllerId) {
return deploymentManagement.assignDistributionSet(dsID, Arrays.asList(
new TargetWithActionType(controllerId, ActionType.FORCED, RepositoryModelConstants.NO_FORCE_TIME)));
}
@@ -253,18 +253,26 @@ public abstract class AbstractIntegrationTest {
* start time of a maintenance window calculated based on the
* cron expression is relative to this time zone
*
* @return result of the assignment as
* {@link DistributionSetAssignmentResult}.
* @return result of the assignment as { @link
* DistributionSetAssignmentResult}.
*/
protected DistributionSetAssignmentResult assignDistributionSetWithMaintenanceWindow(final Long dsID,
final String controllerId, final String maintenanceSchedule, final String maintenanceWindowDuration,
protected DistributionSetAssignmentResult assignDistributionSetWithMaintenanceWindow(final long dsID,
final String controllerId, final String maintenanceWindowSchedule, final String maintenanceWindowDuration,
final String maintenanceWindowTimeZone) {
return deploymentManagement.assignDistributionSet(dsID,
Arrays.asList(new TargetWithActionType(controllerId, ActionType.FORCED,
RepositoryModelConstants.NO_FORCE_TIME, maintenanceSchedule, maintenanceWindowDuration,
RepositoryModelConstants.NO_FORCE_TIME, maintenanceWindowSchedule, maintenanceWindowDuration,
maintenanceWindowTimeZone)));
}
protected DistributionSetAssignmentResult assignDistributionSetWithMaintenanceWindowTimeForced(final long dsID,
final String controllerId, final String maintenanceWindowSchedule, final String maintenanceWindowDuration,
final String maintenanceWindowTimeZone) {
return deploymentManagement.assignDistributionSet(dsID,
Arrays.asList(new TargetWithActionType(controllerId, ActionType.TIMEFORCED, System.currentTimeMillis(),
maintenanceWindowSchedule, maintenanceWindowDuration, maintenanceWindowTimeZone)));
}
protected DistributionSetAssignmentResult assignDistributionSet(final DistributionSet pset,
final List<Target> targets) {
return deploymentManagement.assignDistributionSet(pset.getId(),
@@ -275,11 +283,17 @@ public abstract class AbstractIntegrationTest {
return assignDistributionSet(pset, Arrays.asList(target));
}
protected DistributionSetMetadata createDistributionSetMetadata(final Long dsId, final MetaData md) {
protected DistributionSetAssignmentResult assignDistributionSetTimeForced(final DistributionSet pset,
final Target target) {
return deploymentManagement.assignDistributionSet(pset.getId(), Arrays.asList(
new TargetWithActionType(target.getControllerId(), ActionType.TIMEFORCED, System.currentTimeMillis())));
}
protected DistributionSetMetadata createDistributionSetMetadata(final long dsId, final MetaData md) {
return createDistributionSetMetadata(dsId, Collections.singletonList(md)).get(0);
}
protected List<DistributionSetMetadata> createDistributionSetMetadata(final Long dsId, final List<MetaData> md) {
protected List<DistributionSetMetadata> createDistributionSetMetadata(final long dsId, final List<MetaData> md) {
return distributionSetManagement.createMetaData(dsId, md);
}
@@ -378,23 +392,23 @@ public abstract class AbstractIntegrationTest {
*
* @return {@link String} containing a valid cron expression.
*/
public static String getTestSchedule(final int minutesToAdd) {
protected static String getTestSchedule(final int minutesToAdd) {
ZonedDateTime currentTime = ZonedDateTime.now();
currentTime = currentTime.plusMinutes(minutesToAdd);
return String.format("0 %d %d %d %d ? %d", currentTime.getMinute(), currentTime.getHour(),
currentTime.getDayOfMonth(), currentTime.getMonthValue(), currentTime.getYear());
}
public static String getTestDuration(final int duration) {
protected static String getTestDuration(final int duration) {
return String.format("%02d:%02d:00", duration / 60, duration % 60);
}
public static String getTestTimeZone() {
protected static String getTestTimeZone() {
final ZonedDateTime currentTime = ZonedDateTime.now();
return currentTime.getOffset().getId().replace("Z", "+00:00");
}
public static Map<String, String> getMaintenanceWindow(final String schedule, final String duration,
protected static Map<String, String> getMaintenanceWindow(final String schedule, final String duration,
final String timezone) {
final Map<String, String> maintenanceWindowMap = new HashMap<>();
maintenanceWindowMap.put("schedule", schedule);
@@ -402,4 +416,11 @@ public abstract class AbstractIntegrationTest {
maintenanceWindowMap.put("timezone", timezone);
return maintenanceWindowMap;
}
protected static Map<String, String> getMaintenanceWindowWithNextStart(final String schedule, final String duration,
final String timezone, final long nextStartAt) {
final Map<String, String> maintenanceWindowMap = getMaintenanceWindow(schedule, duration, timezone);
maintenanceWindowMap.put("nextStartAt", String.valueOf(nextStartAt));
return maintenanceWindowMap;
}
}