Feature soft autoassignment (#789)

* Repository layer and database migration
* Changed target filter management to update auto assignment action type together with distribution set, extended mgmt API, adapted auto assign checker/scheduler, changed auto assign distribution set select table to combobox, added filter functionality (needs refactoring)
* Refactored auto assignment dialog window, added soft/forced option group, restructured action type option group layout
* Added forced icon to target filter table autoassignment cell for the forced auto assign actions
* First working draft of distribution set select combobox for auto assignment window
* Optimised filtering queries, added alphabetical sorting on distribution set name and version
* Refactoring of distribution bean query for lazy loading
* Distribution set combobox refactoring and comments
* Added verification of auto assign distribution set validity (completed, not deleted), exdended target filter query fields with auto assign action type field, added rsql filter tests, added repository layer tests
* Added mgmt API tests
* Changed target filter rest docu tests to include auto-assignment type
* Updated hawkbit docs with auto-assignment description
* Added debouncing to key and value input fields of metadata popup layout to get rid of unnecessary value change events, removed redundant set value call in common dialog window, minimizing the repaint components calls
* Fixed sonar findings
* Reverted changes of common dialog window validaton, setting the value of the field explicitly as before, until we rethink the whole concept of validaton mechanism
* Fixed review findings
* Removed rsql filtering by filter auto-assign action type, due to missing conversion of disallowed timeforced action type
* Small fix regarding usage of page request
* Updated sql script version for flyway
* Extended tests for soft deleted distribution sets for auto-assignment and filter string within distribution set specification builder

Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch-si.com>
This commit is contained in:
Bondar Bogdan
2019-03-13 13:35:22 +01:00
committed by Stefan Behl
parent 185f88e19b
commit 664c467920
63 changed files with 1891 additions and 750 deletions

View File

@@ -23,7 +23,6 @@ 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.model.BaseEntity;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
@@ -56,7 +55,7 @@ public interface RepositoryManagement<T, C, U> {
List<T> create(@NotNull @Valid Collection<C> creates);
/**
* Creates new {@link SoftwareModuleType}.
* Creates new {@link BaseEntity}.
*
* @param create
* to create

View File

@@ -18,9 +18,12 @@ import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryCreate;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryUpdate;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.InvalidAutoAssignActionTypeException;
import org.eclipse.hawkbit.repository.exception.InvalidAutoAssignDistributionSetException;
import org.eclipse.hawkbit.repository.exception.QuotaExceededException;
import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException;
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
import org.springframework.data.domain.Page;
@@ -213,13 +216,14 @@ public interface TargetFilterQueryManagement {
TargetFilterQuery update(@NotNull @Valid TargetFilterQueryUpdate update);
/**
* Updates the the auto-assign {@link DistributionSet} of the addressed
* {@link TargetFilterQuery}.
* Updates the the auto-assign {@link DistributionSet} and sets default
* (FORCED) {@link ActionType} of the addressed {@link TargetFilterQuery}.
*
* @param queryId
* of the target filter query to be updated
* @param dsId
* to be updated or <code>null</code> in order to remove it
* together with the auto-assign {@link ActionType}
*
* @return the updated {@link TargetFilterQuery}
*
@@ -230,8 +234,47 @@ public interface TargetFilterQueryManagement {
* @throws QuotaExceededException
* if the query that is already associated with this filter
* query addresses too many targets (auto-assignments only)
*
* @throws InvalidAutoAssignDistributionSetException
* if the provided auto-assign {@link DistributionSet} is not
* valid (incomplete or soft deleted)
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
TargetFilterQuery updateAutoAssignDS(long queryId, Long dsId);
default TargetFilterQuery updateAutoAssignDS(final long queryId, final Long dsId) {
return updateAutoAssignDSWithActionType(queryId, dsId, null);
}
/**
* Updates the the auto-assign {@link DistributionSet} and
* {@link ActionType} of the addressed {@link TargetFilterQuery}.
*
* @param queryId
* of the target filter query to be updated
* @param dsId
* to be updated or <code>null</code> in order to remove it
* together with the auto-assign {@link ActionType}
* @param actionType
* to be updated or <code>null</code> for default (FORCED) if
* distribution set Id is present
*
* @return the updated {@link TargetFilterQuery}
*
* @throws EntityNotFoundException
* if either {@link TargetFilterQuery} and/or autoAssignDs are
* provided but not found
*
* @throws QuotaExceededException
* if the query that is already associated with this filter
* query addresses too many targets (auto-assignments only)
*
* @throws InvalidAutoAssignActionTypeException
* if the provided auto-assign {@link ActionType} is not valid
* (neither FORCED, nor SOFT)
*
* @throws InvalidAutoAssignDistributionSetException
* if the provided auto-assign {@link DistributionSet} is not
* valid (incomplete or soft deleted)
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
TargetFilterQuery updateAutoAssignDSWithActionType(long queryId, Long dsId, ActionType actionType);
}

View File

@@ -13,6 +13,7 @@ import java.util.Optional;
import javax.validation.constraints.NotNull;
import javax.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;
@@ -40,20 +41,27 @@ public interface TargetFilterQueryCreate {
TargetFilterQueryCreate query(@Size(min = 1, max = TargetFilterQuery.QUERY_MAX_SIZE) @NotNull String query);
/**
* @param set
* @param distributionSet
* for {@link TargetFilterQuery#getAutoAssignDistributionSet()}
* @return updated builder instance
*/
default TargetFilterQueryCreate set(final DistributionSet set) {
return set(Optional.ofNullable(set).map(DistributionSet::getId).orElse(null));
default TargetFilterQueryCreate autoAssignDistributionSet(final DistributionSet distributionSet) {
return autoAssignDistributionSet(Optional.ofNullable(distributionSet).map(DistributionSet::getId).orElse(null));
}
/**
* @param setId
* @param dsId
* for {@link TargetFilterQuery#getAutoAssignDistributionSet()}
* @return updated builder instance
*/
TargetFilterQueryCreate set(long setId);
TargetFilterQueryCreate autoAssignDistributionSet(Long dsId);
/**
* @param actionType
* for {@link TargetFilterQuery#getAutoAssignActionType()}
* @return updated builder instance
*/
TargetFilterQueryCreate autoAssignActionType(ActionType actionType);
/**
* @return peek on current state of {@link TargetFilterQuery} in the builder

View File

@@ -88,7 +88,7 @@ public class EntityNotFoundException extends AbstractServerRtException {
* for the {@link MetaData} entry
*/
public EntityNotFoundException(final Class<? extends MetaData> type, final Long entityId, final String key) {
this(type.getSimpleName() + " for given entity {" + entityId + "} and with key {" + key + "} does not exist.");
this(type, String.valueOf(entityId), key);
}
/**
@@ -96,13 +96,13 @@ public class EntityNotFoundException extends AbstractServerRtException {
*
* @param type
* of the entity that was not found
* @param enityId
* @param entityId
* of the {@link BaseEntity} the {@link MetaData} was for
* @param key
* for the {@link MetaData} entry
*/
public EntityNotFoundException(final Class<? extends MetaData> type, final String enityId, final String key) {
this(type.getSimpleName() + " for given entity {" + enityId + "} and with key {" + key + "} does not exist.");
public EntityNotFoundException(final Class<? extends MetaData> type, final String entityId, final String key) {
this(type.getSimpleName() + " for given entity {" + entityId + "} and with key {" + key + "} does not exist.");
}
/**

View File

@@ -0,0 +1,29 @@
/**
* Copyright (c) 2018 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.repository.exception;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
/**
* Thrown if an action type for auto-assignment is neither 'forced', nor 'soft'.
*/
public class InvalidAutoAssignActionTypeException extends AbstractServerRtException {
private static final long serialVersionUID = 1L;
private static final SpServerError THIS_ERROR = SpServerError.SP_AUTO_ASSIGN_ACTION_TYPE_INVALID;
/**
* Default constructor.
*/
public InvalidAutoAssignActionTypeException() {
super(THIS_ERROR);
}
}

View File

@@ -0,0 +1,30 @@
/**
* Copyright (c) 2019 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.repository.exception;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
/**
* Thrown if a distribution set for auto-assignment is incomplete (i.e.
* mandatory modules are missing) or soft deleted.
*/
public class InvalidAutoAssignDistributionSetException extends AbstractServerRtException {
private static final long serialVersionUID = 1L;
private static final SpServerError THIS_ERROR = SpServerError.SP_AUTO_ASSIGN_DISTRIBUTION_SET_INVALID;
/**
* Default constructor.
*/
public InvalidAutoAssignDistributionSetException() {
super(THIS_ERROR);
}
}

View File

@@ -22,6 +22,7 @@ public final class DistributionSetFilter {
private Boolean isComplete;
private DistributionSetType type;
private String searchText;
private String filterString;
private Boolean selectDSWithNoTag;
private Collection<String> tagNames;
private String assignedTargetId;
@@ -61,6 +62,11 @@ public final class DistributionSetFilter {
return this;
}
public DistributionSetFilterBuilder setFilterString(final String filterString) {
this.filterString = filterString;
return this;
}
public DistributionSetFilterBuilder setSelectDSWithNoTag(final Boolean selectDSWithNoTag) {
this.selectDSWithNoTag = selectDSWithNoTag;
return this;
@@ -82,6 +88,7 @@ public final class DistributionSetFilter {
private final Boolean isComplete;
private final DistributionSetType type;
private final String searchText;
private final String filterString;
private final Boolean selectDSWithNoTag;
private final Collection<String> tagNames;
private final String assignedTargetId;
@@ -99,6 +106,7 @@ public final class DistributionSetFilter {
this.isComplete = builder.isComplete;
this.type = builder.type;
this.searchText = builder.searchText;
this.filterString = builder.filterString;
this.selectDSWithNoTag = builder.selectDSWithNoTag;
this.tagNames = builder.tagNames;
this.assignedTargetId = builder.assignedTargetId;
@@ -125,6 +133,10 @@ public final class DistributionSetFilter {
return searchText;
}
public String getFilterString() {
return filterString;
}
public Boolean getSelectDSWithNoTag() {
return selectDSWithNoTag;
}

View File

@@ -8,6 +8,12 @@
*/
package org.eclipse.hawkbit.repository.model;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Set;
import org.eclipse.hawkbit.repository.model.Action.ActionType;
/**
* Managed filter entity.
*
@@ -38,6 +44,12 @@ public interface TargetFilterQuery extends TenantAwareBaseEntity {
*/
int QUERY_MAX_SIZE = 1024;
/**
* Allowed values for auto-assign action type
*/
Set<ActionType> ALLOWED_AUTO_ASSIGN_ACTION_TYPES = Collections
.unmodifiableSet(EnumSet.of(ActionType.FORCED, ActionType.SOFT));
/**
* @return name of the {@link TargetFilterQuery}.
*/
@@ -53,4 +65,9 @@ public interface TargetFilterQuery extends TenantAwareBaseEntity {
*/
DistributionSet getAutoAssignDistributionSet();
/**
* @return the auto assign {@link ActionType} if given.
*/
ActionType getAutoAssignActionType();
}