Feature target metadata (#757)

* Defined the model for target matadata and the corresponding repository layer/management
* Added target metadata quotas incl enforcement
* Extended Target Mgmt REST API to allow for metadata CRUD operations
* Added migration scripts for each database
* Added back reference to target metadata in JpaTarget
* Added tests for target management, Mgmt REST API, target metadata RSQL, and REST documentation
* Updated asciidocs for target rest documentation
* Fix Allure imports and annotations
* Fix review findings

Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch-si.com>
Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com>
This commit is contained in:
Bondar Bogdan
2018-10-29 11:28:34 +01:00
committed by Stefan Behl
parent 1cbde47370
commit 0cf4f8e8b9
37 changed files with 1886 additions and 216 deletions

View File

@@ -43,7 +43,8 @@ public interface EntityFactory {
DistributionSetBuilder distributionSet();
/**
* Generates an {@link MetaData} element without persisting it.
* Generates an {@link MetaData} element for distribution set without
* persisting it.
*
* @param key
* {@link MetaData#getKey()}
@@ -52,7 +53,20 @@ public interface EntityFactory {
*
* @return {@link MetaData} object
*/
MetaData generateMetadata(@Size(min = 1, max = MetaData.KEY_MAX_SIZE) @NotNull String key,
MetaData generateDsMetadata(@Size(min = 1, max = MetaData.KEY_MAX_SIZE) @NotNull String key,
@Size(max = MetaData.VALUE_MAX_SIZE) String value);
/**
* Generates an {@link MetaData} element for target without persisting it.
*
* @param key
* {@link MetaData#getKey()}
* @param value
* {@link MetaData#getValue()}
*
* @return {@link MetaData} object
*/
MetaData generateTargetMetadata(@Size(min = 1, max = MetaData.KEY_MAX_SIZE) @NotNull String key,
@Size(max = MetaData.VALUE_MAX_SIZE) String value);
/**

View File

@@ -53,6 +53,11 @@ public interface QuotaManagement {
*/
int getMaxMetaDataEntriesPerDistributionSet();
/**
* @return maximum number of meta data entries per target
*/
int getMaxMetaDataEntriesPerTarget();
/**
* @return maximum number of software modules per distribution set
*/

View File

@@ -23,13 +23,16 @@ import org.eclipse.hawkbit.repository.builder.TargetCreate;
import org.eclipse.hawkbit.repository.builder.TargetUpdate;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
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.DistributionSet;
import org.eclipse.hawkbit.repository.model.MetaData;
import org.eclipse.hawkbit.repository.model.RolloutGroup;
import org.eclipse.hawkbit.repository.model.Tag;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
import org.eclipse.hawkbit.repository.model.TargetMetadata;
import org.eclipse.hawkbit.repository.model.TargetTag;
import org.eclipse.hawkbit.repository.model.TargetTagAssignmentResult;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
@@ -650,4 +653,116 @@ public interface TargetManagement {
* {@code false}: update of controller attributes not requested.
*/
boolean isControllerAttributesRequested(@NotEmpty String controllerId);
/**
* Creates a list of target meta data entries.
*
* @param controllerId
* {@link Target} controller id the metadata has to be created
* for
* @param metadata
* the meta data entries to create or update
* @return the updated or created target meta data entries
*
* @throws EntityNotFoundException
* if given target does not exist
*
* @throws EntityAlreadyExistsException
* in case one of the meta data entry already exists for the
* specific key
*
* @throws QuotaExceededException
* if the maximum number of {@link MetaData} entries is exceeded
* for the addressed {@link Target}
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
List<TargetMetadata> createMetaData(@NotEmpty String controllerId, @NotEmpty Collection<MetaData> metadata);
/**
* Deletes a target meta data entry.
*
* @param controllerId
* where meta data has to be deleted
* @param key
* of the meta data element
*
* @throws EntityNotFoundException
* if given target does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
void deleteMetaData(@NotEmpty String controllerId, @NotEmpty String key);
/**
* Finds all meta data by the given target id.
*
* @param pageable
* the page request to page the result
* @param controllerId
* the controller id to retrieve the meta data from
*
* @return a paged result of all meta data entries for a given target id
*
* @throws EntityNotFoundException
* if target with given ID does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
Page<TargetMetadata> findMetaDataByControllerId(@NotNull Pageable pageable, @NotEmpty String controllerId);
/**
* Finds all meta data by the given target id and query.
*
* @param pageable
* the page request to page the result
* @param controllerId
* the controller id to retrieve the meta data from
* @param rsqlParam
* rsql query string
*
* @return a paged result of all meta data entries for a given target id
*
* @throws RSQLParameterUnsupportedFieldException
* if a field in the RSQL string is used but not provided by the
* given {@code fieldNameProvider}
*
* @throws RSQLParameterSyntaxException
* if the RSQL syntax is wrong
*
* @throws EntityNotFoundException
* if target with given ID does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
Page<TargetMetadata> findMetaDataByControllerIdAndRsql(@NotNull Pageable pageable, @NotEmpty String controllerId,
@NotNull String rsqlParam);
/**
* Finds a single target meta data by its id.
*
* @param controllerId
* of the {@link Target}
* @param key
* of the meta data element
* @return the found TargetMetadata
*
* @throws EntityNotFoundException
* if target with given ID does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
Optional<TargetMetadata> getMetaDataByControllerId(@NotEmpty String controllerId, @NotEmpty String key);
/**
* Updates a target meta data value if corresponding entry exists.
*
* @param controllerId
* {@link Target} controller id of the meta data entry to be
* updated
* @param metadata
* meta data entry to be updated
* @return the updated meta data entry
*
* @throws EntityNotFoundException
* in case the meta data entry does not exists and cannot be
* updated
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
TargetMetadata updateMetaData(@NotEmpty String controllerId, @NotNull MetaData metadata);
}

View File

@@ -70,11 +70,25 @@ public class EntityNotFoundException extends AbstractServerRtException {
* @param type
* of the entity that was not found
*
* @param enityId
* @param entityId
* of the {@link BaseEntity}
*/
public EntityNotFoundException(final Class<? extends BaseEntity> type, final Object enityId) {
this(type.getSimpleName() + " with given identifier {" + enityId + "} does not exist.");
public EntityNotFoundException(final Class<? extends BaseEntity> type, final Object entityId) {
this(type.getSimpleName() + " with given identifier {" + entityId + "} does not exist.");
}
/**
* Parameterized constructor for {@link MetaData} not found.
*
* @param type
* of the entity that was not found
* @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 Long entityId, final String key) {
this(type.getSimpleName() + " for given entity {" + entityId + "} and with key {" + key + "} does not exist.");
}
/**
@@ -87,7 +101,7 @@ public class EntityNotFoundException extends AbstractServerRtException {
* @param key
* for the {@link MetaData} entry
*/
public EntityNotFoundException(final Class<? extends MetaData> type, final Long enityId, final String key) {
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.");
}

View File

@@ -0,0 +1,26 @@
/**
* 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.model;
/**
* {@link MetaData} of a {@link Target}.
*
*/
public interface TargetMetadata extends MetaData {
/**
* @return {@link Target} of this {@link MetaData} entry.
*/
Target getTarget();
@Override
default Long getEntityId() {
return getTarget().getId();
}
}