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:
committed by
Stefan Behl
parent
1cbde47370
commit
0cf4f8e8b9
@@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort fields for TargetMetadata.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public enum TargetMetadataFields implements FieldNameProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The value field.
|
||||||
|
*/
|
||||||
|
VALUE("value"),
|
||||||
|
/**
|
||||||
|
* The key field.
|
||||||
|
*/
|
||||||
|
KEY("key");
|
||||||
|
|
||||||
|
private final String fieldName;
|
||||||
|
|
||||||
|
TargetMetadataFields(final String fieldName) {
|
||||||
|
this.fieldName = fieldName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFieldName() {
|
||||||
|
return fieldName;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -43,7 +43,8 @@ public interface EntityFactory {
|
|||||||
DistributionSetBuilder distributionSet();
|
DistributionSetBuilder distributionSet();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates an {@link MetaData} element without persisting it.
|
* Generates an {@link MetaData} element for distribution set without
|
||||||
|
* persisting it.
|
||||||
*
|
*
|
||||||
* @param key
|
* @param key
|
||||||
* {@link MetaData#getKey()}
|
* {@link MetaData#getKey()}
|
||||||
@@ -52,7 +53,20 @@ public interface EntityFactory {
|
|||||||
*
|
*
|
||||||
* @return {@link MetaData} object
|
* @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);
|
@Size(max = MetaData.VALUE_MAX_SIZE) String value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -53,6 +53,11 @@ public interface QuotaManagement {
|
|||||||
*/
|
*/
|
||||||
int getMaxMetaDataEntriesPerDistributionSet();
|
int getMaxMetaDataEntriesPerDistributionSet();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return maximum number of meta data entries per target
|
||||||
|
*/
|
||||||
|
int getMaxMetaDataEntriesPerTarget();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return maximum number of software modules per distribution set
|
* @return maximum number of software modules per distribution set
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -23,13 +23,16 @@ import org.eclipse.hawkbit.repository.builder.TargetCreate;
|
|||||||
import org.eclipse.hawkbit.repository.builder.TargetUpdate;
|
import org.eclipse.hawkbit.repository.builder.TargetUpdate;
|
||||||
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
||||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
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.RSQLParameterSyntaxException;
|
||||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
|
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
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.RolloutGroup;
|
||||||
import org.eclipse.hawkbit.repository.model.Tag;
|
import org.eclipse.hawkbit.repository.model.Tag;
|
||||||
import org.eclipse.hawkbit.repository.model.Target;
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
|
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.TargetTag;
|
||||||
import org.eclipse.hawkbit.repository.model.TargetTagAssignmentResult;
|
import org.eclipse.hawkbit.repository.model.TargetTagAssignmentResult;
|
||||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||||
@@ -650,4 +653,116 @@ public interface TargetManagement {
|
|||||||
* {@code false}: update of controller attributes not requested.
|
* {@code false}: update of controller attributes not requested.
|
||||||
*/
|
*/
|
||||||
boolean isControllerAttributesRequested(@NotEmpty String controllerId);
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,11 +70,25 @@ public class EntityNotFoundException extends AbstractServerRtException {
|
|||||||
* @param type
|
* @param type
|
||||||
* of the entity that was not found
|
* of the entity that was not found
|
||||||
*
|
*
|
||||||
* @param enityId
|
* @param entityId
|
||||||
* of the {@link BaseEntity}
|
* of the {@link BaseEntity}
|
||||||
*/
|
*/
|
||||||
public EntityNotFoundException(final Class<? extends BaseEntity> type, final Object enityId) {
|
public EntityNotFoundException(final Class<? extends BaseEntity> type, final Object entityId) {
|
||||||
this(type.getSimpleName() + " with given identifier {" + enityId + "} does not exist.");
|
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
|
* @param key
|
||||||
* for the {@link MetaData} entry
|
* 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.");
|
this(type.getSimpleName() + " for given entity {" + enityId + "} and with key {" + key + "} does not exist.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -58,6 +58,11 @@ public class PropertiesQuotaManagement implements QuotaManagement {
|
|||||||
return securityProperties.getDos().getMaxMetaDataEntriesPerDistributionSet();
|
return securityProperties.getDos().getMaxMetaDataEntriesPerDistributionSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxMetaDataEntriesPerTarget() {
|
||||||
|
return securityProperties.getDos().getMaxMetaDataEntriesPerTarget();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMaxSoftwareModulesPerDistributionSet() {
|
public int getMaxSoftwareModulesPerDistributionSet() {
|
||||||
return securityProperties.getDos().getMaxSoftwareModulesPerDistributionSet();
|
return securityProperties.getDos().getMaxSoftwareModulesPerDistributionSet();
|
||||||
|
|||||||
@@ -457,7 +457,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public List<DistributionSetMetadata> createMetaData(final long dsId, final Collection<MetaData> md) {
|
public List<DistributionSetMetadata> createMetaData(final long dsId, final Collection<MetaData> md) {
|
||||||
|
|
||||||
md.forEach(meta -> checkAndThrowAlreadyIfDistributionSetMetadataExists(
|
md.forEach(meta -> checkAndThrowIfDistributionSetMetadataAlreadyExists(
|
||||||
new DsMetadataCompositeKey(dsId, meta.getKey())));
|
new DsMetadataCompositeKey(dsId, meta.getKey())));
|
||||||
|
|
||||||
assertMetaDataQuota(dsId, md.size());
|
assertMetaDataQuota(dsId, md.size());
|
||||||
@@ -478,8 +478,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
|
|
||||||
private void assertSoftwareModuleQuota(final Long id, final int requested) {
|
private void assertSoftwareModuleQuota(final Long id, final int requested) {
|
||||||
QuotaHelper.assertAssignmentQuota(id, requested, quotaManagement.getMaxSoftwareModulesPerDistributionSet(),
|
QuotaHelper.assertAssignmentQuota(id, requested, quotaManagement.getMaxSoftwareModulesPerDistributionSet(),
|
||||||
SoftwareModule.class, DistributionSet.class,
|
SoftwareModule.class, DistributionSet.class, softwareModuleRepository::countByAssignedToId);
|
||||||
softwareModuleRepository::countByAssignedToId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -676,7 +675,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
return distributionSetRepository.findAll(SpecificationsBuilder.combineWithAnd(specList), pageable);
|
return distributionSetRepository.findAll(SpecificationsBuilder.combineWithAnd(specList), pageable);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkAndThrowAlreadyIfDistributionSetMetadataExists(final DsMetadataCompositeKey metadataId) {
|
private void checkAndThrowIfDistributionSetMetadataAlreadyExists(final DsMetadataCompositeKey metadataId) {
|
||||||
if (distributionSetMetadataRepository.exists(metadataId)) {
|
if (distributionSetMetadataRepository.exists(metadataId)) {
|
||||||
throw new EntityAlreadyExistsException(
|
throw new EntityAlreadyExistsException(
|
||||||
"Metadata entry with key '" + metadataId.getKey() + "' already exists");
|
"Metadata entry with key '" + metadataId.getKey() + "' already exists");
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import org.eclipse.hawkbit.repository.jpa.builder.JpaSoftwareModuleTypeBuilder;
|
|||||||
import org.eclipse.hawkbit.repository.jpa.builder.JpaTagBuilder;
|
import org.eclipse.hawkbit.repository.jpa.builder.JpaTagBuilder;
|
||||||
import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetBuilder;
|
import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetBuilder;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetMetadata;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetMetadata;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetMetadata;
|
||||||
import org.eclipse.hawkbit.repository.model.MetaData;
|
import org.eclipse.hawkbit.repository.model.MetaData;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
@@ -57,10 +58,15 @@ public class JpaEntityFactory implements EntityFactory {
|
|||||||
private SoftwareModuleMetadataBuilder softwareModuleMetadataBuilder;
|
private SoftwareModuleMetadataBuilder softwareModuleMetadataBuilder;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MetaData generateMetadata(final String key, final String value) {
|
public MetaData generateDsMetadata(final String key, final String value) {
|
||||||
return new JpaDistributionSetMetadata(key, StringUtils.trimWhitespace(value));
|
return new JpaDistributionSetMetadata(key, StringUtils.trimWhitespace(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MetaData generateTargetMetadata(final String key, final String value) {
|
||||||
|
return new JpaTargetMetadata(key, StringUtils.trimWhitespace(value));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DistributionSetTypeBuilder distributionSetType() {
|
public DistributionSetTypeBuilder distributionSetType() {
|
||||||
return distributionSetTypeBuilder;
|
return distributionSetTypeBuilder;
|
||||||
|
|||||||
@@ -26,13 +26,16 @@ import javax.persistence.criteria.Predicate;
|
|||||||
import javax.persistence.criteria.Root;
|
import javax.persistence.criteria.Root;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.repository.FilterParams;
|
import org.eclipse.hawkbit.repository.FilterParams;
|
||||||
|
import org.eclipse.hawkbit.repository.QuotaManagement;
|
||||||
import org.eclipse.hawkbit.repository.TargetFields;
|
import org.eclipse.hawkbit.repository.TargetFields;
|
||||||
import org.eclipse.hawkbit.repository.TargetManagement;
|
import org.eclipse.hawkbit.repository.TargetManagement;
|
||||||
|
import org.eclipse.hawkbit.repository.TargetMetadataFields;
|
||||||
import org.eclipse.hawkbit.repository.TimestampCalculator;
|
import org.eclipse.hawkbit.repository.TimestampCalculator;
|
||||||
import org.eclipse.hawkbit.repository.builder.TargetCreate;
|
import org.eclipse.hawkbit.repository.builder.TargetCreate;
|
||||||
import org.eclipse.hawkbit.repository.builder.TargetUpdate;
|
import org.eclipse.hawkbit.repository.builder.TargetUpdate;
|
||||||
import org.eclipse.hawkbit.repository.event.remote.TargetDeletedEvent;
|
|
||||||
import org.eclipse.hawkbit.repository.event.remote.TargetAttributesRequestedEvent;
|
import org.eclipse.hawkbit.repository.event.remote.TargetAttributesRequestedEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.event.remote.TargetDeletedEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
||||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||||
import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetCreate;
|
import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetCreate;
|
||||||
import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetUpdate;
|
import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetUpdate;
|
||||||
@@ -40,15 +43,21 @@ import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
|||||||
import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor;
|
import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetMetadata;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetMetadata_;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.TargetMetadataCompositeKey;
|
||||||
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
|
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
|
||||||
import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder;
|
import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder;
|
||||||
import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications;
|
import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
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.RolloutGroup;
|
||||||
import org.eclipse.hawkbit.repository.model.Target;
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
|
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.TargetTag;
|
||||||
import org.eclipse.hawkbit.repository.model.TargetTagAssignmentResult;
|
import org.eclipse.hawkbit.repository.model.TargetTagAssignmentResult;
|
||||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||||
@@ -83,8 +92,12 @@ public class JpaTargetManagement implements TargetManagement {
|
|||||||
|
|
||||||
private final EntityManager entityManager;
|
private final EntityManager entityManager;
|
||||||
|
|
||||||
|
private final QuotaManagement quotaManagement;
|
||||||
|
|
||||||
private final TargetRepository targetRepository;
|
private final TargetRepository targetRepository;
|
||||||
|
|
||||||
|
private final TargetMetadataRepository targetMetadataRepository;
|
||||||
|
|
||||||
private final RolloutGroupRepository rolloutGroupRepository;
|
private final RolloutGroupRepository rolloutGroupRepository;
|
||||||
|
|
||||||
private final DistributionSetRepository distributionSetRepository;
|
private final DistributionSetRepository distributionSetRepository;
|
||||||
@@ -107,7 +120,8 @@ public class JpaTargetManagement implements TargetManagement {
|
|||||||
|
|
||||||
private final Database database;
|
private final Database database;
|
||||||
|
|
||||||
JpaTargetManagement(final EntityManager entityManager, final TargetRepository targetRepository,
|
JpaTargetManagement(final EntityManager entityManager, final QuotaManagement quotaManagement,
|
||||||
|
final TargetRepository targetRepository, final TargetMetadataRepository targetMetadataRepository,
|
||||||
final RolloutGroupRepository rolloutGroupRepository,
|
final RolloutGroupRepository rolloutGroupRepository,
|
||||||
final DistributionSetRepository distributionSetRepository,
|
final DistributionSetRepository distributionSetRepository,
|
||||||
final TargetFilterQueryRepository targetFilterQueryRepository,
|
final TargetFilterQueryRepository targetFilterQueryRepository,
|
||||||
@@ -116,7 +130,9 @@ public class JpaTargetManagement implements TargetManagement {
|
|||||||
final TenantAware tenantAware, final AfterTransactionCommitExecutor afterCommit,
|
final TenantAware tenantAware, final AfterTransactionCommitExecutor afterCommit,
|
||||||
final VirtualPropertyReplacer virtualPropertyReplacer, final Database database) {
|
final VirtualPropertyReplacer virtualPropertyReplacer, final Database database) {
|
||||||
this.entityManager = entityManager;
|
this.entityManager = entityManager;
|
||||||
|
this.quotaManagement = quotaManagement;
|
||||||
this.targetRepository = targetRepository;
|
this.targetRepository = targetRepository;
|
||||||
|
this.targetMetadataRepository = targetMetadataRepository;
|
||||||
this.rolloutGroupRepository = rolloutGroupRepository;
|
this.rolloutGroupRepository = rolloutGroupRepository;
|
||||||
this.distributionSetRepository = distributionSetRepository;
|
this.distributionSetRepository = distributionSetRepository;
|
||||||
this.targetFilterQueryRepository = targetFilterQueryRepository;
|
this.targetFilterQueryRepository = targetFilterQueryRepository;
|
||||||
@@ -135,6 +151,11 @@ public class JpaTargetManagement implements TargetManagement {
|
|||||||
return targetRepository.findByControllerId(controllerId);
|
return targetRepository.findByControllerId(controllerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private JpaTarget getByControllerIdAndThrowIfNotFound(final String controllerId) {
|
||||||
|
return targetRepository.findByControllerId(controllerId).map(JpaTarget.class::cast)
|
||||||
|
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Target> getByControllerID(final Collection<String> controllerIDs) {
|
public List<Target> getByControllerID(final Collection<String> controllerIDs) {
|
||||||
return Collections.unmodifiableList(
|
return Collections.unmodifiableList(
|
||||||
@@ -146,6 +167,121 @@ public class JpaTargetManagement implements TargetManagement {
|
|||||||
return targetRepository.count();
|
return targetRepository.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
|
public List<TargetMetadata> createMetaData(final String controllerId, final Collection<MetaData> md) {
|
||||||
|
|
||||||
|
final JpaTarget target = getByControllerIdAndThrowIfNotFound(controllerId);
|
||||||
|
|
||||||
|
md.forEach(meta -> checkAndThrowIfTargetMetadataAlreadyExists(
|
||||||
|
new TargetMetadataCompositeKey(target.getId(), meta.getKey())));
|
||||||
|
|
||||||
|
assertMetaDataQuota(target.getId(), md.size());
|
||||||
|
|
||||||
|
final JpaTarget updatedTarget = touch(target);
|
||||||
|
|
||||||
|
return Collections.unmodifiableList(md.stream()
|
||||||
|
.map(meta -> targetMetadataRepository
|
||||||
|
.save(new JpaTargetMetadata(meta.getKey(), meta.getValue(), updatedTarget)))
|
||||||
|
.collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkAndThrowIfTargetMetadataAlreadyExists(final TargetMetadataCompositeKey metadataId) {
|
||||||
|
if (targetMetadataRepository.exists(metadataId)) {
|
||||||
|
throw new EntityAlreadyExistsException(
|
||||||
|
"Metadata entry with key '" + metadataId.getKey() + "' already exists");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertMetaDataQuota(final Long targetId, final int requested) {
|
||||||
|
QuotaHelper.assertAssignmentQuota(targetId, requested, quotaManagement.getMaxMetaDataEntriesPerTarget(),
|
||||||
|
TargetMetadata.class, Target.class, targetMetadataRepository::countByTargetId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private JpaTarget touch(final JpaTarget target) {
|
||||||
|
|
||||||
|
// merge base target so optLockRevision gets updated and audit
|
||||||
|
// log written because modifying metadata is modifying the base
|
||||||
|
// target itself for auditing purposes.
|
||||||
|
final JpaTarget result = entityManager.merge(target);
|
||||||
|
result.setLastModifiedAt(0L);
|
||||||
|
|
||||||
|
return targetRepository.save(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private JpaTarget touch(final String controllerId) {
|
||||||
|
return touch(getByControllerIdAndThrowIfNotFound(controllerId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
|
public TargetMetadata updateMetaData(final String controllerId, final MetaData md) {
|
||||||
|
|
||||||
|
// check if exists otherwise throw entity not found exception
|
||||||
|
final JpaTargetMetadata toUpdate = (JpaTargetMetadata) getMetaDataByControllerId(controllerId, md.getKey())
|
||||||
|
.orElseThrow(() -> new EntityNotFoundException(TargetMetadata.class, controllerId, md.getKey()));
|
||||||
|
toUpdate.setValue(md.getValue());
|
||||||
|
// touch it to update the lock revision because we are modifying the
|
||||||
|
// target indirectly
|
||||||
|
touch(controllerId);
|
||||||
|
return targetMetadataRepository.save(toUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
|
public void deleteMetaData(final String controllerId, final String key) {
|
||||||
|
final JpaTargetMetadata metadata = (JpaTargetMetadata) getMetaDataByControllerId(controllerId, key)
|
||||||
|
.orElseThrow(() -> new EntityNotFoundException(TargetMetadata.class, controllerId, key));
|
||||||
|
|
||||||
|
touch(controllerId);
|
||||||
|
targetMetadataRepository.delete(metadata.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Page<TargetMetadata> findMetaDataByControllerId(final Pageable pageable, final String controllerId) {
|
||||||
|
final Long targetId = getByControllerIdAndThrowIfNotFound(controllerId).getId();
|
||||||
|
|
||||||
|
return convertMdPage(
|
||||||
|
targetMetadataRepository
|
||||||
|
.findAll(
|
||||||
|
(Specification<JpaTargetMetadata>) (root, query, cb) -> cb
|
||||||
|
.equal(root.get(JpaTargetMetadata_.target).get(JpaTarget_.id), targetId),
|
||||||
|
pageable),
|
||||||
|
pageable);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Page<TargetMetadata> convertMdPage(final Page<JpaTargetMetadata> findAll, final Pageable pageable) {
|
||||||
|
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Page<TargetMetadata> findMetaDataByControllerIdAndRsql(final Pageable pageable, final String controllerId,
|
||||||
|
final String rsqlParam) {
|
||||||
|
|
||||||
|
final Long targetId = getByControllerIdAndThrowIfNotFound(controllerId).getId();
|
||||||
|
|
||||||
|
final Specification<JpaTargetMetadata> spec = RSQLUtility.parse(rsqlParam, TargetMetadataFields.class,
|
||||||
|
virtualPropertyReplacer, database);
|
||||||
|
|
||||||
|
return convertMdPage(targetMetadataRepository.findAll((Specification<JpaTargetMetadata>) (root, query, cb) -> cb
|
||||||
|
.and(cb.equal(root.get(JpaTargetMetadata_.target).get(JpaTarget_.id), targetId),
|
||||||
|
spec.toPredicate(root, query, cb)),
|
||||||
|
pageable), pageable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<TargetMetadata> getMetaDataByControllerId(final String controllerId, final String key) {
|
||||||
|
final Long targetId = getByControllerIdAndThrowIfNotFound(controllerId).getId();
|
||||||
|
|
||||||
|
return Optional.ofNullable(targetMetadataRepository.findOne(new TargetMetadataCompositeKey(targetId, key)));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Slice<Target> findAll(final Pageable pageable) {
|
public Slice<Target> findAll(final Pageable pageable) {
|
||||||
return convertPage(criteriaNoCountDao.findAll(pageable, JpaTarget.class), pageable);
|
return convertPage(criteriaNoCountDao.findAll(pageable, JpaTarget.class), pageable);
|
||||||
@@ -178,8 +314,7 @@ public class JpaTargetManagement implements TargetManagement {
|
|||||||
public Target update(final TargetUpdate u) {
|
public Target update(final TargetUpdate u) {
|
||||||
final JpaTargetUpdate update = (JpaTargetUpdate) u;
|
final JpaTargetUpdate update = (JpaTargetUpdate) u;
|
||||||
|
|
||||||
final JpaTarget target = (JpaTarget) targetRepository.findByControllerId(update.getControllerId())
|
final JpaTarget target = getByControllerIdAndThrowIfNotFound(update.getControllerId());
|
||||||
.orElseThrow(() -> new EntityNotFoundException(Target.class, update.getControllerId()));
|
|
||||||
|
|
||||||
update.getName().ifPresent(target::setName);
|
update.getName().ifPresent(target::setName);
|
||||||
update.getDescription().ifPresent(target::setDescription);
|
update.getDescription().ifPresent(target::setDescription);
|
||||||
@@ -214,8 +349,7 @@ public class JpaTargetManagement implements TargetManagement {
|
|||||||
@Retryable(include = {
|
@Retryable(include = {
|
||||||
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public void deleteByControllerID(final String controllerID) {
|
public void deleteByControllerID(final String controllerID) {
|
||||||
final Target target = targetRepository.findByControllerId(controllerID)
|
final Target target = getByControllerIdAndThrowIfNotFound(controllerID);
|
||||||
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerID));
|
|
||||||
|
|
||||||
targetRepository.delete(target.getId());
|
targetRepository.delete(target.getId());
|
||||||
}
|
}
|
||||||
@@ -418,8 +552,7 @@ public class JpaTargetManagement implements TargetManagement {
|
|||||||
@Retryable(include = {
|
@Retryable(include = {
|
||||||
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public Target unAssignTag(final String controllerID, final long targetTagId) {
|
public Target unAssignTag(final String controllerID, final long targetTagId) {
|
||||||
final JpaTarget target = (JpaTarget) targetRepository.findByControllerId(controllerID)
|
final JpaTarget target = getByControllerIdAndThrowIfNotFound(controllerID);
|
||||||
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerID));
|
|
||||||
|
|
||||||
final TargetTag tag = targetTagRepository.findById(targetTagId)
|
final TargetTag tag = targetTagRepository.findById(targetTagId)
|
||||||
.orElseThrow(() -> new EntityNotFoundException(TargetTag.class, targetTagId));
|
.orElseThrow(() -> new EntityNotFoundException(TargetTag.class, targetTagId));
|
||||||
@@ -635,16 +768,14 @@ public class JpaTargetManagement implements TargetManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, String> getControllerAttributes(final String controllerId) {
|
public Map<String, String> getControllerAttributes(final String controllerId) {
|
||||||
final JpaTarget target = (JpaTarget) getByControllerID(controllerId)
|
final JpaTarget target = getByControllerIdAndThrowIfNotFound(controllerId);
|
||||||
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
|
|
||||||
|
|
||||||
return target.getControllerAttributes();
|
return target.getControllerAttributes();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void requestControllerAttributes(final String controllerId) {
|
public void requestControllerAttributes(final String controllerId) {
|
||||||
final JpaTarget target = (JpaTarget) getByControllerID(controllerId)
|
final JpaTarget target = getByControllerIdAndThrowIfNotFound(controllerId);
|
||||||
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
|
|
||||||
|
|
||||||
target.setRequestControllerAttributes(true);
|
target.setRequestControllerAttributes(true);
|
||||||
|
|
||||||
@@ -655,8 +786,7 @@ public class JpaTargetManagement implements TargetManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isControllerAttributesRequested(final String controllerId) {
|
public boolean isControllerAttributesRequested(final String controllerId) {
|
||||||
final JpaTarget target = (JpaTarget) getByControllerID(controllerId)
|
final JpaTarget target = getByControllerIdAndThrowIfNotFound(controllerId);
|
||||||
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
|
|
||||||
|
|
||||||
return target.isRequestControllerAttributes();
|
return target.isRequestControllerAttributes();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -449,7 +449,8 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
|||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
TargetManagement targetManagement(final EntityManager entityManager, final TargetRepository targetRepository,
|
TargetManagement targetManagement(final EntityManager entityManager, final QuotaManagement quotaManagement,
|
||||||
|
final TargetRepository targetRepository, final TargetMetadataRepository targetMetadataRepository,
|
||||||
final RolloutGroupRepository rolloutGroupRepository,
|
final RolloutGroupRepository rolloutGroupRepository,
|
||||||
final DistributionSetRepository distributionSetRepository,
|
final DistributionSetRepository distributionSetRepository,
|
||||||
final TargetFilterQueryRepository targetFilterQueryRepository,
|
final TargetFilterQueryRepository targetFilterQueryRepository,
|
||||||
@@ -457,10 +458,10 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
|||||||
final ApplicationEventPublisher eventPublisher, final ApplicationContext applicationContext,
|
final ApplicationEventPublisher eventPublisher, final ApplicationContext applicationContext,
|
||||||
final TenantAware tenantAware, final AfterTransactionCommitExecutor afterCommit,
|
final TenantAware tenantAware, final AfterTransactionCommitExecutor afterCommit,
|
||||||
final VirtualPropertyReplacer virtualPropertyReplacer, final JpaProperties properties) {
|
final VirtualPropertyReplacer virtualPropertyReplacer, final JpaProperties properties) {
|
||||||
return new JpaTargetManagement(entityManager, targetRepository, rolloutGroupRepository,
|
return new JpaTargetManagement(entityManager, quotaManagement, targetRepository, targetMetadataRepository,
|
||||||
distributionSetRepository, targetFilterQueryRepository, targetTagRepository, criteriaNoCountDao,
|
rolloutGroupRepository, distributionSetRepository, targetFilterQueryRepository, targetTagRepository,
|
||||||
eventPublisher, applicationContext, tenantAware, afterCommit, virtualPropertyReplacer,
|
criteriaNoCountDao, eventPublisher, applicationContext, tenantAware, afterCommit,
|
||||||
properties.getDatabase());
|
virtualPropertyReplacer, properties.getDatabase());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015 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.jpa;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetMetadata;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.TargetMetadataCompositeKey;
|
||||||
|
import org.eclipse.hawkbit.repository.model.TargetMetadata;
|
||||||
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||||
|
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link TargetMetadata} repository.
|
||||||
|
*/
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public interface TargetMetadataRepository
|
||||||
|
extends PagingAndSortingRepository<JpaTargetMetadata, TargetMetadataCompositeKey>,
|
||||||
|
JpaSpecificationExecutor<JpaTargetMetadata> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Counts the meta data entries that match the given target ID.
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
* of the target.
|
||||||
|
*
|
||||||
|
* @return The number of matching meta data entries.
|
||||||
|
*/
|
||||||
|
long countByTargetId(@Param("id") Long id);
|
||||||
|
}
|
||||||
@@ -54,6 +54,7 @@ import org.eclipse.hawkbit.repository.model.Action;
|
|||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
import org.eclipse.hawkbit.repository.model.PollStatus;
|
import org.eclipse.hawkbit.repository.model.PollStatus;
|
||||||
import org.eclipse.hawkbit.repository.model.Target;
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
|
import org.eclipse.hawkbit.repository.model.TargetMetadata;
|
||||||
import org.eclipse.hawkbit.repository.model.TargetTag;
|
import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||||
import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder;
|
import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder;
|
||||||
@@ -167,6 +168,10 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Target, EventAw
|
|||||||
@Column(name = "request_controller_attributes", nullable = false)
|
@Column(name = "request_controller_attributes", nullable = false)
|
||||||
private boolean requestControllerAttributes = true;
|
private boolean requestControllerAttributes = true;
|
||||||
|
|
||||||
|
@CascadeOnDelete
|
||||||
|
@OneToMany(mappedBy = "target", fetch = FetchType.LAZY, targetEntity = JpaTargetMetadata.class)
|
||||||
|
private List<TargetMetadata> metadata;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
@@ -351,6 +356,14 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Target, EventAw
|
|||||||
return requestControllerAttributes;
|
return requestControllerAttributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<TargetMetadata> getMetadata() {
|
||||||
|
if (metadata == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Collections.unmodifiableList(metadata);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "JpaTarget [controllerId=" + controllerId + ", revision=" + getOptLockRevision() + ", id=" + getId()
|
return "JpaTarget [controllerId=" + controllerId + ", revision=" + getOptLockRevision() + ", id=" + getId()
|
||||||
|
|||||||
@@ -0,0 +1,109 @@
|
|||||||
|
/**
|
||||||
|
* 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.jpa.model;
|
||||||
|
|
||||||
|
import javax.persistence.ConstraintMode;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.ForeignKey;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.IdClass;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
|
import org.eclipse.hawkbit.repository.model.TargetMetadata;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Meta data for {@link Target}.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@IdClass(TargetMetadataCompositeKey.class)
|
||||||
|
@Entity
|
||||||
|
@Table(name = "sp_target_metadata")
|
||||||
|
public class JpaTargetMetadata extends AbstractJpaMetaData implements TargetMetadata {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY, optional = false)
|
||||||
|
@JoinColumn(name = "target_id", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_metadata_target"))
|
||||||
|
private JpaTarget target;
|
||||||
|
|
||||||
|
public JpaTargetMetadata() {
|
||||||
|
// default public constructor for JPA
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a single metadata entry with the given key and value.
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* of the meta data entry
|
||||||
|
* @param value
|
||||||
|
* of the meta data entry
|
||||||
|
*/
|
||||||
|
public JpaTargetMetadata(final String key, final String value) {
|
||||||
|
super(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a single metadata entry with the given key and value for the
|
||||||
|
* given {@link Target}.
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* of the meta data entry
|
||||||
|
* @param value
|
||||||
|
* of the meta data entry
|
||||||
|
* @param target
|
||||||
|
* the meta data entry is associated with
|
||||||
|
*/
|
||||||
|
public JpaTargetMetadata(final String key, final String value, final Target target) {
|
||||||
|
super(key, value);
|
||||||
|
this.target = (JpaTarget) target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TargetMetadataCompositeKey getId() {
|
||||||
|
return new TargetMetadataCompositeKey(target.getId(), getKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTarget(final Target target) {
|
||||||
|
this.target = (JpaTarget) target;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Target getTarget() {
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = super.hashCode();
|
||||||
|
result = prime * result + ((target == null) ? 0 : target.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
// exception squid:S2259 - obj is checked for null in super
|
||||||
|
@SuppressWarnings("squid:S2259")
|
||||||
|
public boolean equals(final Object obj) {
|
||||||
|
if (!super.equals(obj)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final JpaTargetMetadata other = (JpaTargetMetadata) obj;
|
||||||
|
if (target == null) {
|
||||||
|
if (other.target != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (!target.equals(other.target)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
/**
|
||||||
|
* 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.jpa.model;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Target Metadata composite key which contains the meta data key and the ID
|
||||||
|
* of the Target itself.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public final class TargetMetadataCompositeKey implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private String key;
|
||||||
|
|
||||||
|
private Long target;
|
||||||
|
|
||||||
|
public TargetMetadataCompositeKey() {
|
||||||
|
// Default constructor for JPA.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param target
|
||||||
|
* the target Id for this meta data
|
||||||
|
* @param key
|
||||||
|
* the key of the meta data
|
||||||
|
*/
|
||||||
|
public TargetMetadataCompositeKey(final Long target, final String key) {
|
||||||
|
this.target = target;
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKey(final String key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getTargetId() {
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTargetId(final Long target) {
|
||||||
|
this.target = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(target, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final TargetMetadataCompositeKey other = (TargetMetadataCompositeKey) obj;
|
||||||
|
if (target == null) {
|
||||||
|
if (other.target != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (!target.equals(other.target)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (key == null) {
|
||||||
|
if (other.key != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (!key.equals(other.key)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
CREATE TABLE sp_target_metadata
|
||||||
|
(
|
||||||
|
meta_key VARCHAR(128) NOT NULL,
|
||||||
|
meta_value VARCHAR(4000),
|
||||||
|
target_id BIGINT NOT NULL,
|
||||||
|
PRIMARY KEY (meta_key, target_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
ALTER TABLE sp_target_metadata ADD CONSTRAINT fk_metadata_target FOREIGN KEY (target_id) REFERENCES sp_target (id) ON DELETE CASCADE;
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
create table sp_target_metadata (
|
||||||
|
meta_key varchar(128) not null,
|
||||||
|
meta_value varchar(4000),
|
||||||
|
target_id bigint not null,
|
||||||
|
primary key (target_id, meta_key)
|
||||||
|
);
|
||||||
|
|
||||||
|
alter table sp_target_metadata
|
||||||
|
add constraint fk_metadata_target
|
||||||
|
foreign key (target_id)
|
||||||
|
references sp_target
|
||||||
|
on delete cascade;
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
create table sp_target_metadata (
|
||||||
|
meta_key varchar(128) not null,
|
||||||
|
meta_value varchar(4000),
|
||||||
|
target_id bigint not null,
|
||||||
|
primary key (target_id, meta_key)
|
||||||
|
);
|
||||||
|
|
||||||
|
alter table sp_target_metadata
|
||||||
|
add constraint fk_metadata_target
|
||||||
|
foreign key (target_id)
|
||||||
|
references sp_target (id)
|
||||||
|
on delete cascade;
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
CREATE TABLE sp_target_metadata
|
||||||
|
(
|
||||||
|
meta_key VARCHAR(128) NOT NULL,
|
||||||
|
meta_value VARCHAR(4000) NULL,
|
||||||
|
target_id NUMERIC(19) NOT NULL,
|
||||||
|
PRIMARY KEY (meta_key, target_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
ALTER TABLE sp_target_metadata ADD CONSTRAINT fk_metadata_target FOREIGN KEY (target_id) REFERENCES sp_target (id) ON DELETE CASCADE;
|
||||||
@@ -136,7 +136,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
"DistributionSetType");
|
"DistributionSetType");
|
||||||
|
|
||||||
verifyThrownExceptionBy(() -> distributionSetManagement.createMetaData(NOT_EXIST_IDL,
|
verifyThrownExceptionBy(() -> distributionSetManagement.createMetaData(NOT_EXIST_IDL,
|
||||||
Arrays.asList(entityFactory.generateMetadata("123", "123"))), "DistributionSet");
|
Arrays.asList(entityFactory.generateDsMetadata("123", "123"))), "DistributionSet");
|
||||||
|
|
||||||
verifyThrownExceptionBy(() -> distributionSetManagement.delete(Arrays.asList(NOT_EXIST_IDL)),
|
verifyThrownExceptionBy(() -> distributionSetManagement.delete(Arrays.asList(NOT_EXIST_IDL)),
|
||||||
"DistributionSet");
|
"DistributionSet");
|
||||||
@@ -167,10 +167,10 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
"DistributionSet");
|
"DistributionSet");
|
||||||
|
|
||||||
verifyThrownExceptionBy(() -> distributionSetManagement.updateMetaData(NOT_EXIST_IDL,
|
verifyThrownExceptionBy(() -> distributionSetManagement.updateMetaData(NOT_EXIST_IDL,
|
||||||
entityFactory.generateMetadata("xxx", "xxx")), "DistributionSet");
|
entityFactory.generateDsMetadata("xxx", "xxx")), "DistributionSet");
|
||||||
|
|
||||||
verifyThrownExceptionBy(() -> distributionSetManagement.updateMetaData(set.getId(),
|
verifyThrownExceptionBy(() -> distributionSetManagement.updateMetaData(set.getId(),
|
||||||
entityFactory.generateMetadata(NOT_EXIST_ID, "xxx")), "DistributionSetMetadata");
|
entityFactory.generateDsMetadata(NOT_EXIST_ID, "xxx")), "DistributionSetMetadata");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -553,7 +553,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
|
|
||||||
// update the DS metadata
|
// update the DS metadata
|
||||||
final JpaDistributionSetMetadata updated = (JpaDistributionSetMetadata) distributionSetManagement
|
final JpaDistributionSetMetadata updated = (JpaDistributionSetMetadata) distributionSetManagement
|
||||||
.updateMetaData(ds.getId(), entityFactory.generateMetadata(knownKey, knownUpdateValue));
|
.updateMetaData(ds.getId(), entityFactory.generateDsMetadata(knownKey, knownUpdateValue));
|
||||||
// we are updating the sw meta data so also modifying the base software
|
// we are updating the sw meta data so also modifying the base software
|
||||||
// module so opt lock
|
// module so opt lock
|
||||||
// revision must be three
|
// revision must be three
|
||||||
|
|||||||
@@ -41,13 +41,17 @@ import org.eclipse.hawkbit.repository.event.remote.entity.TargetTagCreatedEvent;
|
|||||||
import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent;
|
import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent;
|
||||||
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
||||||
import org.eclipse.hawkbit.repository.exception.InvalidTargetAddressException;
|
import org.eclipse.hawkbit.repository.exception.InvalidTargetAddressException;
|
||||||
|
import org.eclipse.hawkbit.repository.exception.QuotaExceededException;
|
||||||
import org.eclipse.hawkbit.repository.exception.TenantNotExistException;
|
import org.eclipse.hawkbit.repository.exception.TenantNotExistException;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetMetadata;
|
||||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult;
|
import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult;
|
||||||
|
import org.eclipse.hawkbit.repository.model.MetaData;
|
||||||
import org.eclipse.hawkbit.repository.model.Tag;
|
import org.eclipse.hawkbit.repository.model.Tag;
|
||||||
import org.eclipse.hawkbit.repository.model.Target;
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
|
import org.eclipse.hawkbit.repository.model.TargetMetadata;
|
||||||
import org.eclipse.hawkbit.repository.model.TargetTag;
|
import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||||
import org.eclipse.hawkbit.repository.test.matcher.Expect;
|
import org.eclipse.hawkbit.repository.test.matcher.Expect;
|
||||||
import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
|
import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
|
||||||
@@ -73,10 +77,12 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
@Test
|
@Test
|
||||||
@Description("Verifies that management get access react as specified on calls for non existing entities by means "
|
@Description("Verifies that management get access react as specified on calls for non existing entities by means "
|
||||||
+ "of Optional not present.")
|
+ "of Optional not present.")
|
||||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1) })
|
||||||
public void nonExistingEntityAccessReturnsNotPresent() {
|
public void nonExistingEntityAccessReturnsNotPresent() {
|
||||||
|
final Target target = testdataFactory.createTarget();
|
||||||
assertThat(targetManagement.getByControllerID(NOT_EXIST_ID)).isNotPresent();
|
assertThat(targetManagement.getByControllerID(NOT_EXIST_ID)).isNotPresent();
|
||||||
assertThat(targetManagement.get(NOT_EXIST_IDL)).isNotPresent();
|
assertThat(targetManagement.get(NOT_EXIST_IDL)).isNotPresent();
|
||||||
|
assertThat(targetManagement.getMetaDataByControllerId(target.getControllerId(), NOT_EXIST_ID)).isNotPresent();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -89,8 +95,10 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
final Target target = testdataFactory.createTarget();
|
final Target target = testdataFactory.createTarget();
|
||||||
|
|
||||||
verifyThrownExceptionBy(
|
verifyThrownExceptionBy(
|
||||||
() -> targetManagement.assignTag(Collections.singletonList(target.getControllerId()), NOT_EXIST_IDL), "TargetTag");
|
() -> targetManagement.assignTag(Collections.singletonList(target.getControllerId()), NOT_EXIST_IDL),
|
||||||
verifyThrownExceptionBy(() -> targetManagement.assignTag(Collections.singletonList(NOT_EXIST_ID), tag.getId()), "Target");
|
"TargetTag");
|
||||||
|
verifyThrownExceptionBy(() -> targetManagement.assignTag(Collections.singletonList(NOT_EXIST_ID), tag.getId()),
|
||||||
|
"Target");
|
||||||
|
|
||||||
verifyThrownExceptionBy(() -> targetManagement.findByTag(PAGE, NOT_EXIST_IDL), "TargetTag");
|
verifyThrownExceptionBy(() -> targetManagement.findByTag(PAGE, NOT_EXIST_IDL), "TargetTag");
|
||||||
verifyThrownExceptionBy(() -> targetManagement.findByRsqlAndTag(PAGE, "name==*", NOT_EXIST_IDL), "TargetTag");
|
verifyThrownExceptionBy(() -> targetManagement.findByRsqlAndTag(PAGE, "name==*", NOT_EXIST_IDL), "TargetTag");
|
||||||
@@ -123,16 +131,31 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
() -> targetManagement.findByInstalledDistributionSetAndRsql(PAGE, NOT_EXIST_IDL, "name==*"),
|
() -> targetManagement.findByInstalledDistributionSetAndRsql(PAGE, NOT_EXIST_IDL, "name==*"),
|
||||||
"DistributionSet");
|
"DistributionSet");
|
||||||
|
|
||||||
|
verifyThrownExceptionBy(() -> targetManagement
|
||||||
|
.toggleTagAssignment(Collections.singletonList(target.getControllerId()), NOT_EXIST_ID), "TargetTag");
|
||||||
verifyThrownExceptionBy(
|
verifyThrownExceptionBy(
|
||||||
() -> targetManagement.toggleTagAssignment(Collections.singletonList(target.getControllerId()), NOT_EXIST_ID),
|
() -> targetManagement.toggleTagAssignment(Collections.singletonList(NOT_EXIST_ID), tag.getName()),
|
||||||
"TargetTag");
|
|
||||||
verifyThrownExceptionBy(() -> targetManagement.toggleTagAssignment(Collections.singletonList(NOT_EXIST_ID), tag.getName()),
|
|
||||||
"Target");
|
"Target");
|
||||||
|
|
||||||
verifyThrownExceptionBy(() -> targetManagement.unAssignTag(NOT_EXIST_ID, tag.getId()), "Target");
|
verifyThrownExceptionBy(() -> targetManagement.unAssignTag(NOT_EXIST_ID, tag.getId()), "Target");
|
||||||
verifyThrownExceptionBy(() -> targetManagement.unAssignTag(target.getControllerId(), NOT_EXIST_IDL),
|
verifyThrownExceptionBy(() -> targetManagement.unAssignTag(target.getControllerId(), NOT_EXIST_IDL),
|
||||||
"TargetTag");
|
"TargetTag");
|
||||||
verifyThrownExceptionBy(() -> targetManagement.update(entityFactory.target().update(NOT_EXIST_ID)), "Target");
|
verifyThrownExceptionBy(() -> targetManagement.update(entityFactory.target().update(NOT_EXIST_ID)), "Target");
|
||||||
|
|
||||||
|
verifyThrownExceptionBy(() -> targetManagement.createMetaData(NOT_EXIST_ID,
|
||||||
|
Arrays.asList(entityFactory.generateTargetMetadata("123", "123"))), "Target");
|
||||||
|
verifyThrownExceptionBy(() -> targetManagement.deleteMetaData(NOT_EXIST_ID, "xxx"), "Target");
|
||||||
|
verifyThrownExceptionBy(() -> targetManagement.deleteMetaData(target.getControllerId(), NOT_EXIST_ID),
|
||||||
|
"TargetMetadata");
|
||||||
|
verifyThrownExceptionBy(() -> targetManagement.getMetaDataByControllerId(NOT_EXIST_ID, "xxx"), "Target");
|
||||||
|
verifyThrownExceptionBy(() -> targetManagement.findMetaDataByControllerId(PAGE, NOT_EXIST_ID), "Target");
|
||||||
|
verifyThrownExceptionBy(() -> targetManagement.findMetaDataByControllerIdAndRsql(PAGE, NOT_EXIST_ID, "name==*"),
|
||||||
|
"Target");
|
||||||
|
verifyThrownExceptionBy(
|
||||||
|
() -> targetManagement.updateMetaData(NOT_EXIST_ID, entityFactory.generateTargetMetadata("xxx", "xxx")),
|
||||||
|
"Target");
|
||||||
|
verifyThrownExceptionBy(() -> targetManagement.updateMetaData(target.getControllerId(),
|
||||||
|
entityFactory.generateTargetMetadata(NOT_EXIST_ID, "xxx")), "TargetMetadata");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -143,8 +166,9 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
.create(entityFactory.target().create().controllerId("targetWithSecurityToken").securityToken("token"));
|
.create(entityFactory.target().create().controllerId("targetWithSecurityToken").securityToken("token"));
|
||||||
|
|
||||||
// retrieve security token only with READ_TARGET_SEC_TOKEN permission
|
// retrieve security token only with READ_TARGET_SEC_TOKEN permission
|
||||||
final String securityTokenWithReadPermission = securityRule.runAs(WithSpringAuthorityRule
|
final String securityTokenWithReadPermission = securityRule.runAs(
|
||||||
.withUser("OnlyTargetReadPermission", false, SpPermission.READ_TARGET_SEC_TOKEN), createdTarget::getSecurityToken);
|
WithSpringAuthorityRule.withUser("OnlyTargetReadPermission", false, SpPermission.READ_TARGET_SEC_TOKEN),
|
||||||
|
createdTarget::getSecurityToken);
|
||||||
|
|
||||||
// retrieve security token as system code execution
|
// retrieve security token as system code execution
|
||||||
final String securityTokenAsSystemCode = systemSecurityContext.runAsSystem(createdTarget::getSecurityToken);
|
final String securityTokenAsSystemCode = systemSecurityContext.runAsSystem(createdTarget::getSecurityToken);
|
||||||
@@ -889,4 +913,138 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
assertThat(targetManagement.isControllerAttributesRequested(knownTargetId)).isTrue();
|
assertThat(targetManagement.isControllerAttributesRequested(knownTargetId)).isTrue();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Checks that metadata for a target can be created.")
|
||||||
|
public void createTargetMetadata() {
|
||||||
|
final String knownKey = "targetMetaKnownKey";
|
||||||
|
final String knownValue = "targetMetaKnownValue";
|
||||||
|
|
||||||
|
final Target target = testdataFactory.createTarget("targetIdWithMetadata");
|
||||||
|
final JpaTargetMetadata createdMetadata = insertTargetMetadata(knownKey, target, knownValue);
|
||||||
|
|
||||||
|
assertThat(createdMetadata).isNotNull();
|
||||||
|
assertThat(createdMetadata.getId().getKey()).isEqualTo(knownKey);
|
||||||
|
assertThat(createdMetadata.getTarget().getControllerId()).isEqualTo(target.getControllerId());
|
||||||
|
assertThat(createdMetadata.getTarget().getId()).isEqualTo(target.getId());
|
||||||
|
assertThat(createdMetadata.getValue()).isEqualTo(knownValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
private JpaTargetMetadata insertTargetMetadata(final String knownKey, final Target target,
|
||||||
|
final String knownValue) {
|
||||||
|
final JpaTargetMetadata metadata = new JpaTargetMetadata(knownKey, knownValue, target);
|
||||||
|
return (JpaTargetMetadata) targetManagement
|
||||||
|
.createMetaData(target.getControllerId(), Collections.singletonList(metadata)).get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Verifies the enforcement of the metadata quota per target.")
|
||||||
|
public void createTargetMetadataUntilQuotaIsExceeded() {
|
||||||
|
|
||||||
|
// add meta data one by one
|
||||||
|
final Target target1 = testdataFactory.createTarget("target1");
|
||||||
|
final int maxMetaData = quotaManagement.getMaxMetaDataEntriesPerTarget();
|
||||||
|
for (int i = 0; i < maxMetaData; ++i) {
|
||||||
|
assertThat(insertTargetMetadata("k" + i, target1, "v" + i)).isNotNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
// quota exceeded
|
||||||
|
assertThatExceptionOfType(QuotaExceededException.class)
|
||||||
|
.isThrownBy(() -> insertTargetMetadata("k" + maxMetaData, target1, "v" + maxMetaData));
|
||||||
|
|
||||||
|
// add multiple meta data entries at once
|
||||||
|
final Target target2 = testdataFactory.createTarget("target2");
|
||||||
|
final List<MetaData> metaData2 = new ArrayList<>();
|
||||||
|
for (int i = 0; i < maxMetaData + 1; ++i) {
|
||||||
|
metaData2.add(new JpaTargetMetadata("k" + i, "v" + i, target2));
|
||||||
|
}
|
||||||
|
// verify quota is exceeded
|
||||||
|
assertThatExceptionOfType(QuotaExceededException.class)
|
||||||
|
.isThrownBy(() -> targetManagement.createMetaData(target2.getControllerId(), metaData2));
|
||||||
|
|
||||||
|
// add some meta data entries
|
||||||
|
final Target target3 = testdataFactory.createTarget("target3");
|
||||||
|
final int firstHalf = Math.round(maxMetaData / 2);
|
||||||
|
for (int i = 0; i < firstHalf; ++i) {
|
||||||
|
insertTargetMetadata("k" + i, target3, "v" + i);
|
||||||
|
}
|
||||||
|
// add too many data entries
|
||||||
|
final int secondHalf = maxMetaData - firstHalf;
|
||||||
|
final List<MetaData> metaData3 = new ArrayList<>();
|
||||||
|
for (int i = 0; i < secondHalf + 1; ++i) {
|
||||||
|
metaData3.add(new JpaTargetMetadata("kk" + i, "vv" + i, target3));
|
||||||
|
}
|
||||||
|
// verify quota is exceeded
|
||||||
|
assertThatExceptionOfType(QuotaExceededException.class)
|
||||||
|
.isThrownBy(() -> targetManagement.createMetaData(target3.getControllerId(), metaData3));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@WithUser(allSpPermissions = true)
|
||||||
|
@Description("Checks that metadata for a target can be updated.")
|
||||||
|
public void updateTargetMetadata() throws InterruptedException {
|
||||||
|
final String knownKey = "myKnownKey";
|
||||||
|
final String knownValue = "myKnownValue";
|
||||||
|
final String knownUpdateValue = "myNewUpdatedValue";
|
||||||
|
|
||||||
|
// create a target
|
||||||
|
final Target target = testdataFactory.createTarget("target1");
|
||||||
|
// initial opt lock revision must be zero
|
||||||
|
assertThat(target.getOptLockRevision()).isEqualTo(1);
|
||||||
|
|
||||||
|
// create target meta data entry
|
||||||
|
insertTargetMetadata(knownKey, target, knownValue);
|
||||||
|
|
||||||
|
Target changedLockRevisionTarget = targetManagement.get(target.getId()).get();
|
||||||
|
assertThat(changedLockRevisionTarget.getOptLockRevision()).isEqualTo(2);
|
||||||
|
|
||||||
|
Thread.sleep(100);
|
||||||
|
|
||||||
|
// update the target metadata
|
||||||
|
final JpaTargetMetadata updated = (JpaTargetMetadata) targetManagement.updateMetaData(target.getControllerId(),
|
||||||
|
entityFactory.generateTargetMetadata(knownKey, knownUpdateValue));
|
||||||
|
// we are updating the target meta data so also modifying the base
|
||||||
|
// software
|
||||||
|
// module so opt lock
|
||||||
|
// revision must be three
|
||||||
|
changedLockRevisionTarget = targetManagement.get(target.getId()).get();
|
||||||
|
assertThat(changedLockRevisionTarget.getOptLockRevision()).isEqualTo(3);
|
||||||
|
assertThat(changedLockRevisionTarget.getLastModifiedAt()).isGreaterThan(0L);
|
||||||
|
|
||||||
|
// verify updated meta data contains the updated value
|
||||||
|
assertThat(updated).isNotNull();
|
||||||
|
assertThat(updated.getValue()).isEqualTo(knownUpdateValue);
|
||||||
|
assertThat(updated.getId().getKey()).isEqualTo(knownKey);
|
||||||
|
assertThat(updated.getTarget().getControllerId()).isEqualTo(target.getControllerId());
|
||||||
|
assertThat(updated.getTarget().getId()).isEqualTo(target.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Queries and loads the metadata related to a given target.")
|
||||||
|
public void findAllTargetMetadataByControllerId() {
|
||||||
|
// create targets
|
||||||
|
final Target target1 = testdataFactory.createTarget("target1");
|
||||||
|
final Target target2 = testdataFactory.createTarget("target2");
|
||||||
|
|
||||||
|
for (int index = 0; index < 10; index++) {
|
||||||
|
insertTargetMetadata("key" + index, target1, "value" + index);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int index = 0; index < 8; index++) {
|
||||||
|
insertTargetMetadata("key" + index, target2, "value" + index);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Page<TargetMetadata> metadataOfTarget1 = targetManagement
|
||||||
|
.findMetaDataByControllerId(new PageRequest(0, 100), target1.getControllerId());
|
||||||
|
|
||||||
|
final Page<TargetMetadata> metadataOfTarget2 = targetManagement
|
||||||
|
.findMetaDataByControllerId(new PageRequest(0, 100), target2.getControllerId());
|
||||||
|
|
||||||
|
assertThat(metadataOfTarget1.getNumberOfElements()).isEqualTo(10);
|
||||||
|
assertThat(metadataOfTarget1.getTotalElements()).isEqualTo(10);
|
||||||
|
|
||||||
|
assertThat(metadataOfTarget2.getNumberOfElements()).isEqualTo(8);
|
||||||
|
assertThat(metadataOfTarget2.getTotalElements()).isEqualTo(8);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,12 +37,12 @@ public class RSQLDistributionSetFieldTest extends AbstractJpaIntegrationTest {
|
|||||||
|
|
||||||
DistributionSet ds = testdataFactory.createDistributionSet("DS");
|
DistributionSet ds = testdataFactory.createDistributionSet("DS");
|
||||||
ds = distributionSetManagement.update(entityFactory.distributionSet().update(ds.getId()).description("DS"));
|
ds = distributionSetManagement.update(entityFactory.distributionSet().update(ds.getId()).description("DS"));
|
||||||
createDistributionSetMetadata(ds.getId(), entityFactory.generateMetadata("metaKey", "metaValue"));
|
createDistributionSetMetadata(ds.getId(), entityFactory.generateDsMetadata("metaKey", "metaValue"));
|
||||||
|
|
||||||
DistributionSet ds2 = testdataFactory.createDistributionSets("NewDS", 3).get(0);
|
DistributionSet ds2 = testdataFactory.createDistributionSets("NewDS", 3).get(0);
|
||||||
|
|
||||||
ds2 = distributionSetManagement.update(entityFactory.distributionSet().update(ds2.getId()).description("DS%"));
|
ds2 = distributionSetManagement.update(entityFactory.distributionSet().update(ds2.getId()).description("DS%"));
|
||||||
createDistributionSetMetadata(ds2.getId(), entityFactory.generateMetadata("metaKey", "value"));
|
createDistributionSetMetadata(ds2.getId(), entityFactory.generateDsMetadata("metaKey", "value"));
|
||||||
|
|
||||||
final DistributionSetTag targetTag = distributionSetTagManagement
|
final DistributionSetTag targetTag = distributionSetTagManagement
|
||||||
.create(entityFactory.tag().create().name("Tag1"));
|
.create(entityFactory.tag().create().name("Tag1"));
|
||||||
|
|||||||
@@ -41,13 +41,13 @@ public class RSQLDistributionSetMetadataFieldsTest extends AbstractJpaIntegratio
|
|||||||
|
|
||||||
final List<MetaData> metadata = new ArrayList<>(5);
|
final List<MetaData> metadata = new ArrayList<>(5);
|
||||||
for (int i = 0; i < 5; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
metadata.add(entityFactory.generateMetadata("" + i, "" + i));
|
metadata.add(entityFactory.generateDsMetadata("" + i, "" + i));
|
||||||
}
|
}
|
||||||
|
|
||||||
distributionSetManagement.createMetaData(distributionSetId, metadata);
|
distributionSetManagement.createMetaData(distributionSetId, metadata);
|
||||||
|
|
||||||
distributionSetManagement.createMetaData(distributionSetId,
|
distributionSetManagement.createMetaData(distributionSetId,
|
||||||
Arrays.asList(entityFactory.generateMetadata("emptyValueTest", null)));
|
Arrays.asList(entityFactory.generateDsMetadata("emptyValueTest", null)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015 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.jpa.rsql;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.TargetMetadataFields;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
||||||
|
import org.eclipse.hawkbit.repository.model.MetaData;
|
||||||
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
|
import org.eclipse.hawkbit.repository.model.TargetMetadata;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.PageRequest;
|
||||||
|
|
||||||
|
import io.qameta.allure.Description;
|
||||||
|
import io.qameta.allure.Feature;
|
||||||
|
import io.qameta.allure.Story;
|
||||||
|
|
||||||
|
@Feature("Component Tests - Repository")
|
||||||
|
@Story("RSQL filter target metadata")
|
||||||
|
public class RSQLTargetMetadataFieldsTest extends AbstractJpaIntegrationTest {
|
||||||
|
private String controllerId;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setupBeforeTest() {
|
||||||
|
final Target target = testdataFactory.createTarget("target");
|
||||||
|
controllerId = target.getControllerId();
|
||||||
|
|
||||||
|
final List<MetaData> metadata = new ArrayList<>(5);
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
metadata.add(entityFactory.generateTargetMetadata("" + i, "" + i));
|
||||||
|
}
|
||||||
|
|
||||||
|
targetManagement.createMetaData(controllerId, metadata);
|
||||||
|
|
||||||
|
targetManagement.createMetaData(controllerId,
|
||||||
|
Arrays.asList(entityFactory.generateTargetMetadata("emptyValueTest", null)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Test filter target metadata by key")
|
||||||
|
public void testFilterByParameterKey() {
|
||||||
|
assertRSQLQuery(TargetMetadataFields.KEY.name() + "==1", 1);
|
||||||
|
assertRSQLQuery(TargetMetadataFields.KEY.name() + "!=1", 5);
|
||||||
|
assertRSQLQuery(TargetMetadataFields.KEY.name() + "=in=(1,2)", 2);
|
||||||
|
assertRSQLQuery(TargetMetadataFields.KEY.name() + "=out=(1,2)", 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Test filter target metadata by value")
|
||||||
|
public void testFilterByParameterValue() {
|
||||||
|
assertRSQLQuery(TargetMetadataFields.VALUE.name() + "==''", 1);
|
||||||
|
assertRSQLQuery(TargetMetadataFields.VALUE.name() + "!=''", 5);
|
||||||
|
assertRSQLQuery(TargetMetadataFields.VALUE.name() + "==1", 1);
|
||||||
|
assertRSQLQuery(TargetMetadataFields.VALUE.name() + "!=1", 4);
|
||||||
|
assertRSQLQuery(TargetMetadataFields.VALUE.name() + "=in=(1,2)", 2);
|
||||||
|
assertRSQLQuery(TargetMetadataFields.VALUE.name() + "=out=(1,2)", 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertRSQLQuery(final String rsqlParam, final long expectedEntities) {
|
||||||
|
|
||||||
|
final Page<TargetMetadata> findEnitity = targetManagement
|
||||||
|
.findMetaDataByControllerIdAndRsql(new PageRequest(0, 100), controllerId, rsqlParam);
|
||||||
|
final long countAllEntities = findEnitity.getTotalElements();
|
||||||
|
assertThat(findEnitity).isNotNull();
|
||||||
|
assertThat(countAllEntities).isEqualTo(expectedEntities);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,6 +10,8 @@ package org.eclipse.hawkbit.mgmt.rest.api;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.mgmt.json.model.MgmtMetadata;
|
||||||
|
import org.eclipse.hawkbit.mgmt.json.model.MgmtMetadataBodyPut;
|
||||||
import org.eclipse.hawkbit.mgmt.json.model.PagedList;
|
import org.eclipse.hawkbit.mgmt.json.model.PagedList;
|
||||||
import org.eclipse.hawkbit.mgmt.json.model.action.MgmtAction;
|
import org.eclipse.hawkbit.mgmt.json.model.action.MgmtAction;
|
||||||
import org.eclipse.hawkbit.mgmt.json.model.action.MgmtActionRequestBodyPut;
|
import org.eclipse.hawkbit.mgmt.json.model.action.MgmtActionRequestBodyPut;
|
||||||
@@ -37,13 +39,13 @@ public interface MgmtTargetRestApi {
|
|||||||
/**
|
/**
|
||||||
* Handles the GET request of retrieving a single target.
|
* Handles the GET request of retrieving a single target.
|
||||||
*
|
*
|
||||||
* @param controllerId
|
* @param targetId
|
||||||
* the ID of the target to retrieve
|
* the ID of the target to retrieve
|
||||||
* @return a single target with status OK.
|
* @return a single target with status OK.
|
||||||
*/
|
*/
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/{controllerId}", produces = { MediaTypes.HAL_JSON_VALUE,
|
@RequestMapping(method = RequestMethod.GET, value = "/{targetId}", produces = { MediaTypes.HAL_JSON_VALUE,
|
||||||
MediaType.APPLICATION_JSON_VALUE })
|
MediaType.APPLICATION_JSON_VALUE })
|
||||||
ResponseEntity<MgmtTarget> getTarget(@PathVariable("controllerId") String controllerId);
|
ResponseEntity<MgmtTarget> getTarget(@PathVariable("targetId") String targetId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the GET request of retrieving all targets.
|
* Handles the GET request of retrieving all targets.
|
||||||
@@ -94,7 +96,7 @@ public interface MgmtTargetRestApi {
|
|||||||
* path of the request. A given ID in the request body is ignored. It's not
|
* path of the request. A given ID in the request body is ignored. It's not
|
||||||
* possible to set fields to {@code null} values.
|
* possible to set fields to {@code null} values.
|
||||||
*
|
*
|
||||||
* @param controllerId
|
* @param targetId
|
||||||
* the path parameter which contains the ID of the target
|
* the path parameter which contains the ID of the target
|
||||||
* @param targetRest
|
* @param targetRest
|
||||||
* the request body which contains the fields which should be
|
* the request body which contains the fields which should be
|
||||||
@@ -103,40 +105,40 @@ public interface MgmtTargetRestApi {
|
|||||||
* @return the updated target response which contains all fields also fields
|
* @return the updated target response which contains all fields also fields
|
||||||
* which have not updated
|
* which have not updated
|
||||||
*/
|
*/
|
||||||
@RequestMapping(method = RequestMethod.PUT, value = "/{controllerId}", consumes = { MediaTypes.HAL_JSON_VALUE,
|
@RequestMapping(method = RequestMethod.PUT, value = "/{targetId}", consumes = { MediaTypes.HAL_JSON_VALUE,
|
||||||
MediaType.APPLICATION_JSON_VALUE }, produces = { MediaTypes.HAL_JSON_VALUE,
|
MediaType.APPLICATION_JSON_VALUE }, produces = { MediaTypes.HAL_JSON_VALUE,
|
||||||
MediaType.APPLICATION_JSON_VALUE })
|
MediaType.APPLICATION_JSON_VALUE })
|
||||||
ResponseEntity<MgmtTarget> updateTarget(@PathVariable("controllerId") String controllerId,
|
ResponseEntity<MgmtTarget> updateTarget(@PathVariable("targetId") String targetId,
|
||||||
MgmtTargetRequestBody targetRest);
|
MgmtTargetRequestBody targetRest);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the DELETE request of deleting a target.
|
* Handles the DELETE request of deleting a target.
|
||||||
*
|
*
|
||||||
* @param controllerId
|
* @param targetId
|
||||||
* the ID of the target to be deleted
|
* the ID of the target to be deleted
|
||||||
* @return If the given controllerId could exists and could be deleted Http
|
* @return If the given targetId could exists and could be deleted Http OK.
|
||||||
* OK. In any failure the JsonResponseExceptionHandler is handling
|
* In any failure the JsonResponseExceptionHandler is handling the
|
||||||
* the response.
|
* response.
|
||||||
*/
|
*/
|
||||||
@RequestMapping(method = RequestMethod.DELETE, value = "/{controllerId}")
|
@RequestMapping(method = RequestMethod.DELETE, value = "/{targetId}")
|
||||||
ResponseEntity<Void> deleteTarget(@PathVariable("controllerId") String controllerId);
|
ResponseEntity<Void> deleteTarget(@PathVariable("targetId") String targetId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the GET request of retrieving the attributes of a specific
|
* Handles the GET request of retrieving the attributes of a specific
|
||||||
* target.
|
* target.
|
||||||
*
|
*
|
||||||
* @param controllerId
|
* @param targetId
|
||||||
* the ID of the target to retrieve the attributes.
|
* the ID of the target to retrieve the attributes.
|
||||||
* @return the target attributes as map response with status OK
|
* @return the target attributes as map response with status OK
|
||||||
*/
|
*/
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/{controllerId}/attributes", produces = {
|
@RequestMapping(method = RequestMethod.GET, value = "/{targetId}/attributes", produces = {
|
||||||
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
||||||
ResponseEntity<MgmtTargetAttributes> getAttributes(@PathVariable("controllerId") String controllerId);
|
ResponseEntity<MgmtTargetAttributes> getAttributes(@PathVariable("targetId") String targetId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the GET request of retrieving the Actions of a specific target.
|
* Handles the GET request of retrieving the Actions of a specific target.
|
||||||
*
|
*
|
||||||
* @param controllerId
|
* @param targetId
|
||||||
* to load actions for
|
* to load actions for
|
||||||
* @param pagingOffsetParam
|
* @param pagingOffsetParam
|
||||||
* the offset of list of targets for pagination, might not be
|
* the offset of list of targets for pagination, might not be
|
||||||
@@ -154,9 +156,9 @@ public interface MgmtTargetRestApi {
|
|||||||
* status OK. The response is always paged. In any failure the
|
* status OK. The response is always paged. In any failure the
|
||||||
* JsonResponseExceptionHandler is handling the response.
|
* JsonResponseExceptionHandler is handling the response.
|
||||||
*/
|
*/
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/{controllerId}/actions", produces = {
|
@RequestMapping(method = RequestMethod.GET, value = "/{targetId}/actions", produces = {
|
||||||
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
||||||
ResponseEntity<PagedList<MgmtAction>> getActionHistory(@PathVariable("controllerId") String controllerId,
|
ResponseEntity<PagedList<MgmtAction>> getActionHistory(@PathVariable("targetId") String targetId,
|
||||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) int pagingOffsetParam,
|
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) int pagingOffsetParam,
|
||||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) int pagingLimitParam,
|
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) int pagingLimitParam,
|
||||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SORTING, required = false) String sortParam,
|
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SORTING, required = false) String sortParam,
|
||||||
@@ -166,22 +168,22 @@ public interface MgmtTargetRestApi {
|
|||||||
* Handles the GET request of retrieving a specific Actions of a specific
|
* Handles the GET request of retrieving a specific Actions of a specific
|
||||||
* Target.
|
* Target.
|
||||||
*
|
*
|
||||||
* @param controllerId
|
* @param targetId
|
||||||
* to load the action for
|
* to load the action for
|
||||||
* @param actionId
|
* @param actionId
|
||||||
* to load
|
* to load
|
||||||
* @return the action
|
* @return the action
|
||||||
*/
|
*/
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/{controllerId}/actions/{actionId}", produces = {
|
@RequestMapping(method = RequestMethod.GET, value = "/{targetId}/actions/{actionId}", produces = {
|
||||||
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
||||||
ResponseEntity<MgmtAction> getAction(@PathVariable("controllerId") String controllerId,
|
ResponseEntity<MgmtAction> getAction(@PathVariable("targetId") String targetId,
|
||||||
@PathVariable("actionId") Long actionId);
|
@PathVariable("actionId") Long actionId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the DELETE request of canceling an specific Actions of a specific
|
* Handles the DELETE request of canceling an specific Actions of a specific
|
||||||
* Target.
|
* Target.
|
||||||
*
|
*
|
||||||
* @param controllerId
|
* @param targetId
|
||||||
* the ID of the target in the URL path parameter
|
* the ID of the target in the URL path parameter
|
||||||
* @param actionId
|
* @param actionId
|
||||||
* the ID of the action in the URL path parameter
|
* the ID of the action in the URL path parameter
|
||||||
@@ -189,15 +191,15 @@ public interface MgmtTargetRestApi {
|
|||||||
* optional parameter, which indicates a force cancel
|
* optional parameter, which indicates a force cancel
|
||||||
* @return status no content in case cancellation was successful
|
* @return status no content in case cancellation was successful
|
||||||
*/
|
*/
|
||||||
@RequestMapping(method = RequestMethod.DELETE, value = "/{controllerId}/actions/{actionId}")
|
@RequestMapping(method = RequestMethod.DELETE, value = "/{targetId}/actions/{actionId}")
|
||||||
ResponseEntity<Void> cancelAction(@PathVariable("controllerId") String controllerId,
|
ResponseEntity<Void> cancelAction(@PathVariable("targetId") String targetId,
|
||||||
@PathVariable("actionId") Long actionId,
|
@PathVariable("actionId") Long actionId,
|
||||||
@RequestParam(value = "force", required = false, defaultValue = "false") boolean force);
|
@RequestParam(value = "force", required = false, defaultValue = "false") boolean force);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the PUT update request to switch an action from soft to forced.
|
* Handles the PUT update request to switch an action from soft to forced.
|
||||||
*
|
*
|
||||||
* @param controllerId
|
* @param targetId
|
||||||
* the ID of the target in the URL path parameter
|
* the ID of the target in the URL path parameter
|
||||||
* @param actionId
|
* @param actionId
|
||||||
* the ID of the action in the URL path parameter
|
* the ID of the action in the URL path parameter
|
||||||
@@ -205,17 +207,17 @@ public interface MgmtTargetRestApi {
|
|||||||
* to update the action
|
* to update the action
|
||||||
* @return status no content in case cancellation was successful
|
* @return status no content in case cancellation was successful
|
||||||
*/
|
*/
|
||||||
@RequestMapping(method = RequestMethod.PUT, value = "/{controllerId}/actions/{actionId}", consumes = {
|
@RequestMapping(method = RequestMethod.PUT, value = "/{targetId}/actions/{actionId}", consumes = {
|
||||||
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }, produces = { MediaTypes.HAL_JSON_VALUE,
|
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }, produces = { MediaTypes.HAL_JSON_VALUE,
|
||||||
MediaType.APPLICATION_JSON_VALUE })
|
MediaType.APPLICATION_JSON_VALUE })
|
||||||
ResponseEntity<MgmtAction> updateAction(@PathVariable("controllerId") String controllerId,
|
ResponseEntity<MgmtAction> updateAction(@PathVariable("targetId") String targetId,
|
||||||
@PathVariable("actionId") Long actionId, MgmtActionRequestBodyPut actionUpdate);
|
@PathVariable("actionId") Long actionId, MgmtActionRequestBodyPut actionUpdate);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the GET request of retrieving the ActionStatus of a specific
|
* Handles the GET request of retrieving the ActionStatus of a specific
|
||||||
* target and action.
|
* target and action.
|
||||||
*
|
*
|
||||||
* @param controllerId
|
* @param targetId
|
||||||
* of the the action
|
* of the the action
|
||||||
* @param actionId
|
* @param actionId
|
||||||
* of the status we are intend to load
|
* of the status we are intend to load
|
||||||
@@ -232,9 +234,9 @@ public interface MgmtTargetRestApi {
|
|||||||
* with status OK. The response is always paged. In any failure the
|
* with status OK. The response is always paged. In any failure the
|
||||||
* JsonResponseExceptionHandler is handling the response.
|
* JsonResponseExceptionHandler is handling the response.
|
||||||
*/
|
*/
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/{controllerId}/actions/{actionId}/status", produces = {
|
@RequestMapping(method = RequestMethod.GET, value = "/{targetId}/actions/{actionId}/status", produces = {
|
||||||
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
||||||
ResponseEntity<PagedList<MgmtActionStatus>> getActionStatusList(@PathVariable("controllerId") String controllerId,
|
ResponseEntity<PagedList<MgmtActionStatus>> getActionStatusList(@PathVariable("targetId") String targetId,
|
||||||
@PathVariable("actionId") Long actionId,
|
@PathVariable("actionId") Long actionId,
|
||||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) int pagingOffsetParam,
|
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) int pagingOffsetParam,
|
||||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) int pagingLimitParam,
|
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) int pagingLimitParam,
|
||||||
@@ -244,20 +246,20 @@ public interface MgmtTargetRestApi {
|
|||||||
* Handles the GET request of retrieving the assigned distribution set of an
|
* Handles the GET request of retrieving the assigned distribution set of an
|
||||||
* specific target.
|
* specific target.
|
||||||
*
|
*
|
||||||
* @param controllerId
|
* @param targetId
|
||||||
* the ID of the target to retrieve the assigned distribution
|
* the ID of the target to retrieve the assigned distribution
|
||||||
*
|
*
|
||||||
* @return the assigned distribution set with status OK, if none is assigned
|
* @return the assigned distribution set with status OK, if none is assigned
|
||||||
* than {@code null} content (e.g. "{}")
|
* than {@code null} content (e.g. "{}")
|
||||||
*/
|
*/
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/{controllerId}/assignedDS", produces = {
|
@RequestMapping(method = RequestMethod.GET, value = "/{targetId}/assignedDS", produces = {
|
||||||
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
||||||
ResponseEntity<MgmtDistributionSet> getAssignedDistributionSet(@PathVariable("controllerId") String controllerId);
|
ResponseEntity<MgmtDistributionSet> getAssignedDistributionSet(@PathVariable("targetId") String targetId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes the assigned distribution set of a target.
|
* Changes the assigned distribution set of a target.
|
||||||
*
|
*
|
||||||
* @param controllerId
|
* @param targetId
|
||||||
* of the target to change
|
* of the target to change
|
||||||
* @param dsId
|
* @param dsId
|
||||||
* of the distributionset that is to be assigned
|
* of the distributionset that is to be assigned
|
||||||
@@ -269,24 +271,113 @@ public interface MgmtTargetRestApi {
|
|||||||
* complex return body which contains information about the assigned
|
* complex return body which contains information about the assigned
|
||||||
* targets and the already assigned targets counters
|
* targets and the already assigned targets counters
|
||||||
*/
|
*/
|
||||||
@RequestMapping(method = RequestMethod.POST, value = "/{controllerId}/assignedDS", consumes = {
|
@RequestMapping(method = RequestMethod.POST, value = "/{targetId}/assignedDS", consumes = {
|
||||||
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }, produces = { MediaTypes.HAL_JSON_VALUE,
|
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }, produces = { MediaTypes.HAL_JSON_VALUE,
|
||||||
MediaType.APPLICATION_JSON_VALUE })
|
MediaType.APPLICATION_JSON_VALUE })
|
||||||
ResponseEntity<MgmtTargetAssignmentResponseBody> postAssignedDistributionSet(
|
ResponseEntity<MgmtTargetAssignmentResponseBody> postAssignedDistributionSet(
|
||||||
@PathVariable("controllerId") String controllerId, MgmtDistributionSetAssignment dsId,
|
@PathVariable("targetId") String targetId, MgmtDistributionSetAssignment dsId,
|
||||||
@RequestParam(value = "offline", required = false) boolean offline);
|
@RequestParam(value = "offline", required = false) boolean offline);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the GET request of retrieving the installed distribution set of
|
* Handles the GET request of retrieving the installed distribution set of
|
||||||
* an specific target.
|
* an specific target.
|
||||||
*
|
*
|
||||||
* @param controllerId
|
* @param targetId
|
||||||
* the ID of the target to retrieve
|
* the ID of the target to retrieve
|
||||||
* @return the assigned installed set with status OK, if none is installed
|
* @return the assigned installed set with status OK, if none is installed
|
||||||
* than {@code null} content (e.g. "{}")
|
* than {@code null} content (e.g. "{}")
|
||||||
*/
|
*/
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/{controllerId}/installedDS", produces = {
|
@RequestMapping(method = RequestMethod.GET, value = "/{targetId}/installedDS", produces = {
|
||||||
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
||||||
ResponseEntity<MgmtDistributionSet> getInstalledDistributionSet(@PathVariable("controllerId") String controllerId);
|
ResponseEntity<MgmtDistributionSet> getInstalledDistributionSet(@PathVariable("targetId") String targetId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a paged list of meta data for a target.
|
||||||
|
*
|
||||||
|
* @param targetId
|
||||||
|
* the ID of the target for the meta data
|
||||||
|
* @param pagingOffsetParam
|
||||||
|
* the offset of list of targets for pagination, might not be
|
||||||
|
* present in the rest request then default value will be applied
|
||||||
|
* @param pagingLimitParam
|
||||||
|
* the limit of the paged request, might not be present in the
|
||||||
|
* rest request then default value will be applied
|
||||||
|
* @param sortParam
|
||||||
|
* the sorting parameter in the request URL, syntax
|
||||||
|
* {@code field:direction, field:direction}
|
||||||
|
* @param rsqlParam
|
||||||
|
* the search parameter in the request URL, syntax
|
||||||
|
* {@code q=key==abc}
|
||||||
|
* @return status OK if get request is successful with the paged list of
|
||||||
|
* meta data
|
||||||
|
*/
|
||||||
|
@RequestMapping(method = RequestMethod.GET, value = "/{targetId}/metadata", produces = {
|
||||||
|
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
||||||
|
ResponseEntity<PagedList<MgmtMetadata>> getMetadata(@PathVariable("targetId") String targetId,
|
||||||
|
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) int pagingOffsetParam,
|
||||||
|
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) int pagingLimitParam,
|
||||||
|
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SORTING, required = false) String sortParam,
|
||||||
|
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SEARCH, required = false) String rsqlParam);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a single meta data value for a specific key of a target.
|
||||||
|
*
|
||||||
|
* @param targetId
|
||||||
|
* the ID of the target to get the meta data from
|
||||||
|
* @param metadataKey
|
||||||
|
* the key of the meta data entry to retrieve the value from
|
||||||
|
* @return status OK if get request is successful with the value of the meta
|
||||||
|
* data
|
||||||
|
*/
|
||||||
|
@RequestMapping(method = RequestMethod.GET, value = "/{targetId}/metadata/{metadataKey}", produces = {
|
||||||
|
MediaType.APPLICATION_JSON_VALUE })
|
||||||
|
ResponseEntity<MgmtMetadata> getMetadataValue(@PathVariable("targetId") String targetId,
|
||||||
|
@PathVariable("metadataKey") String metadataKey);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates a single meta data value of a target.
|
||||||
|
*
|
||||||
|
* @param targetId
|
||||||
|
* the ID of the target to update the meta data entry
|
||||||
|
* @param metadataKey
|
||||||
|
* the key of the meta data to update the value
|
||||||
|
* @param metadata
|
||||||
|
* update body
|
||||||
|
* @return status OK if the update request is successful and the updated
|
||||||
|
* meta data result
|
||||||
|
*/
|
||||||
|
@RequestMapping(method = RequestMethod.PUT, value = "/{targetId}/metadata/{metadataKey}", produces = {
|
||||||
|
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
||||||
|
ResponseEntity<MgmtMetadata> updateMetadata(@PathVariable("targetId") String targetId,
|
||||||
|
@PathVariable("metadataKey") String metadataKey, MgmtMetadataBodyPut metadata);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a single meta data entry from the target.
|
||||||
|
*
|
||||||
|
* @param targetId
|
||||||
|
* the ID of the target to delete the meta data entry
|
||||||
|
* @param metadataKey
|
||||||
|
* the key of the meta data to delete
|
||||||
|
* @return status OK if the delete request is successful
|
||||||
|
*/
|
||||||
|
@RequestMapping(method = RequestMethod.DELETE, value = "/{targetId}/metadata/{metadataKey}")
|
||||||
|
ResponseEntity<Void> deleteMetadata(@PathVariable("targetId") String targetId,
|
||||||
|
@PathVariable("metadataKey") String metadataKey);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a list of meta data for a specific target.
|
||||||
|
*
|
||||||
|
* @param targetId
|
||||||
|
* the ID of the targetId to create meta data for
|
||||||
|
* @param metadataRest
|
||||||
|
* the list of meta data entries to create
|
||||||
|
* @return status created if post request is successful with the value of
|
||||||
|
* the created meta data
|
||||||
|
*/
|
||||||
|
@RequestMapping(method = RequestMethod.POST, value = "/{targetId}/metadata", consumes = {
|
||||||
|
MediaType.APPLICATION_JSON_VALUE,
|
||||||
|
MediaTypes.HAL_JSON_VALUE }, produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
||||||
|
ResponseEntity<List<MgmtMetadata>> createMetadata(@PathVariable("targetId") String targetId,
|
||||||
|
List<MgmtMetadata> metadataRest);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ public final class MgmtDistributionSetMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return metadata.stream()
|
return metadata.stream()
|
||||||
.map(metadataRest -> entityFactory.generateMetadata(metadataRest.getKey(), metadataRest.getValue()))
|
.map(metadataRest -> entityFactory.generateDsMetadata(metadataRest.getKey(), metadataRest.getValue()))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -321,7 +321,7 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi {
|
|||||||
// check if distribution set exists otherwise throw exception
|
// check if distribution set exists otherwise throw exception
|
||||||
// immediately
|
// immediately
|
||||||
final DistributionSetMetadata updated = distributionSetManagement.updateMetaData(distributionSetId,
|
final DistributionSetMetadata updated = distributionSetManagement.updateMetaData(distributionSetId,
|
||||||
entityFactory.generateMetadata(metadataKey, metadata.getValue()));
|
entityFactory.generateDsMetadata(metadataKey, metadata.getValue()));
|
||||||
return ResponseEntity.ok(MgmtDistributionSetMapper.toResponseDsMetadata(updated));
|
return ResponseEntity.ok(MgmtDistributionSetMapper.toResponseDsMetadata(updated));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import java.util.List;
|
|||||||
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;
|
||||||
|
import org.eclipse.hawkbit.mgmt.json.model.MgmtMetadata;
|
||||||
import org.eclipse.hawkbit.mgmt.json.model.MgmtPollStatus;
|
import org.eclipse.hawkbit.mgmt.json.model.MgmtPollStatus;
|
||||||
import org.eclipse.hawkbit.mgmt.json.model.action.MgmtAction;
|
import org.eclipse.hawkbit.mgmt.json.model.action.MgmtAction;
|
||||||
import org.eclipse.hawkbit.mgmt.json.model.action.MgmtActionStatus;
|
import org.eclipse.hawkbit.mgmt.json.model.action.MgmtActionStatus;
|
||||||
@@ -36,8 +37,10 @@ import org.eclipse.hawkbit.repository.builder.TargetCreate;
|
|||||||
import org.eclipse.hawkbit.repository.model.Action;
|
import org.eclipse.hawkbit.repository.model.Action;
|
||||||
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||||
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
||||||
|
import org.eclipse.hawkbit.repository.model.MetaData;
|
||||||
import org.eclipse.hawkbit.repository.model.PollStatus;
|
import org.eclipse.hawkbit.repository.model.PollStatus;
|
||||||
import org.eclipse.hawkbit.repository.model.Target;
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
|
import org.eclipse.hawkbit.repository.model.TargetMetadata;
|
||||||
import org.eclipse.hawkbit.rest.data.ResponseList;
|
import org.eclipse.hawkbit.rest.data.ResponseList;
|
||||||
import org.eclipse.hawkbit.rest.data.SortDirection;
|
import org.eclipse.hawkbit.rest.data.SortDirection;
|
||||||
import org.eclipse.hawkbit.util.IpUtil;
|
import org.eclipse.hawkbit.util.IpUtil;
|
||||||
@@ -71,6 +74,9 @@ public final class MgmtTargetMapper {
|
|||||||
MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT_VALUE,
|
MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT_VALUE,
|
||||||
ActionFields.ID.getFieldName() + ":" + SortDirection.DESC, null))
|
ActionFields.ID.getFieldName() + ":" + SortDirection.DESC, null))
|
||||||
.withRel(MgmtRestConstants.TARGET_V1_ACTIONS).expand());
|
.withRel(MgmtRestConstants.TARGET_V1_ACTIONS).expand());
|
||||||
|
response.add(linkTo(methodOn(MgmtTargetRestApi.class).getMetadata(response.getControllerId(),
|
||||||
|
MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET_VALUE,
|
||||||
|
MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT_VALUE, null, null)).withRel("metadata"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void addPollStatus(final Target target, final MgmtTarget targetRest) {
|
static void addPollStatus(final Target target, final MgmtTarget targetRest) {
|
||||||
@@ -167,6 +173,17 @@ public final class MgmtTargetMapper {
|
|||||||
.address(targetRest.getAddress());
|
.address(targetRest.getAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static List<MetaData> fromRequestTargetMetadata(final List<MgmtMetadata> metadata,
|
||||||
|
final EntityFactory entityFactory) {
|
||||||
|
if (metadata == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return metadata.stream().map(
|
||||||
|
metadataRest -> entityFactory.generateTargetMetadata(metadataRest.getKey(), metadataRest.getValue()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
static List<MgmtActionStatus> toActionStatusRestResponse(final Collection<ActionStatus> actionStatus,
|
static List<MgmtActionStatus> toActionStatusRestResponse(final Collection<ActionStatus> actionStatus,
|
||||||
final DeploymentManagement deploymentManagement) {
|
final DeploymentManagement deploymentManagement) {
|
||||||
if (actionStatus == null) {
|
if (actionStatus == null) {
|
||||||
@@ -261,4 +278,15 @@ public final class MgmtTargetMapper {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static MgmtMetadata toResponseTargetMetadata(final TargetMetadata metadata) {
|
||||||
|
final MgmtMetadata metadataRest = new MgmtMetadata();
|
||||||
|
metadataRest.setKey(metadata.getKey());
|
||||||
|
metadataRest.setValue(metadata.getValue());
|
||||||
|
return metadataRest;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<MgmtMetadata> toResponseTargetMetadata(final List<TargetMetadata> metadata) {
|
||||||
|
return metadata.stream().map(MgmtTargetMapper::toResponseTargetMetadata).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ import java.util.Map;
|
|||||||
import javax.validation.ValidationException;
|
import javax.validation.ValidationException;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.mgmt.json.model.MgmtMaintenanceWindowRequestBody;
|
import org.eclipse.hawkbit.mgmt.json.model.MgmtMaintenanceWindowRequestBody;
|
||||||
|
import org.eclipse.hawkbit.mgmt.json.model.MgmtMetadata;
|
||||||
|
import org.eclipse.hawkbit.mgmt.json.model.MgmtMetadataBodyPut;
|
||||||
import org.eclipse.hawkbit.mgmt.json.model.PagedList;
|
import org.eclipse.hawkbit.mgmt.json.model.PagedList;
|
||||||
import org.eclipse.hawkbit.mgmt.json.model.action.MgmtAction;
|
import org.eclipse.hawkbit.mgmt.json.model.action.MgmtAction;
|
||||||
import org.eclipse.hawkbit.mgmt.json.model.action.MgmtActionRequestBodyPut;
|
import org.eclipse.hawkbit.mgmt.json.model.action.MgmtActionRequestBodyPut;
|
||||||
@@ -38,6 +40,7 @@ import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
|||||||
import org.eclipse.hawkbit.repository.model.Action;
|
import org.eclipse.hawkbit.repository.model.Action;
|
||||||
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
||||||
import org.eclipse.hawkbit.repository.model.Target;
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
|
import org.eclipse.hawkbit.repository.model.TargetMetadata;
|
||||||
import org.eclipse.hawkbit.repository.model.TargetWithActionType;
|
import org.eclipse.hawkbit.repository.model.TargetWithActionType;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -70,8 +73,8 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
|
|||||||
private EntityFactory entityFactory;
|
private EntityFactory entityFactory;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResponseEntity<MgmtTarget> getTarget(@PathVariable("controllerId") final String controllerId) {
|
public ResponseEntity<MgmtTarget> getTarget(@PathVariable("targetId") final String targetId) {
|
||||||
final Target findTarget = findTargetWithExceptionIfNotFound(controllerId);
|
final Target findTarget = findTargetWithExceptionIfNotFound(targetId);
|
||||||
// to single response include poll status
|
// to single response include poll status
|
||||||
final MgmtTarget response = MgmtTargetMapper.toResponse(findTarget);
|
final MgmtTarget response = MgmtTargetMapper.toResponse(findTarget);
|
||||||
MgmtTargetMapper.addPollStatus(findTarget, response);
|
MgmtTargetMapper.addPollStatus(findTarget, response);
|
||||||
@@ -117,22 +120,21 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResponseEntity<MgmtTarget> updateTarget(@PathVariable("controllerId") final String controllerId,
|
public ResponseEntity<MgmtTarget> updateTarget(@PathVariable("targetId") final String targetId,
|
||||||
@RequestBody final MgmtTargetRequestBody targetRest) {
|
@RequestBody final MgmtTargetRequestBody targetRest) {
|
||||||
|
|
||||||
if (targetRest.isRequestAttributes() != null) {
|
if (targetRest.isRequestAttributes() != null) {
|
||||||
if (targetRest.isRequestAttributes()) {
|
if (targetRest.isRequestAttributes()) {
|
||||||
targetManagement.requestControllerAttributes(controllerId);
|
targetManagement.requestControllerAttributes(targetId);
|
||||||
} else {
|
} else {
|
||||||
return ResponseEntity.badRequest().build();
|
return ResponseEntity.badRequest().build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final Target updateTarget = this.targetManagement.update(entityFactory.target().update(controllerId)
|
final Target updateTarget = this.targetManagement.update(entityFactory.target().update(targetId)
|
||||||
.name(targetRest.getName()).description(targetRest.getDescription()).address(targetRest.getAddress())
|
.name(targetRest.getName()).description(targetRest.getDescription()).address(targetRest.getAddress())
|
||||||
.securityToken(targetRest.getSecurityToken()).requestAttributes(targetRest.isRequestAttributes()));
|
.securityToken(targetRest.getSecurityToken()).requestAttributes(targetRest.isRequestAttributes()));
|
||||||
|
|
||||||
|
|
||||||
final MgmtTarget response = MgmtTargetMapper.toResponse(updateTarget);
|
final MgmtTarget response = MgmtTargetMapper.toResponse(updateTarget);
|
||||||
MgmtTargetMapper.addPollStatus(updateTarget, response);
|
MgmtTargetMapper.addPollStatus(updateTarget, response);
|
||||||
MgmtTargetMapper.addTargetLinks(response);
|
MgmtTargetMapper.addTargetLinks(response);
|
||||||
@@ -141,15 +143,15 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResponseEntity<Void> deleteTarget(@PathVariable("controllerId") final String controllerId) {
|
public ResponseEntity<Void> deleteTarget(@PathVariable("targetId") final String targetId) {
|
||||||
this.targetManagement.deleteByControllerID(controllerId);
|
this.targetManagement.deleteByControllerID(targetId);
|
||||||
LOG.debug("{} target deleted, return status {}", controllerId, HttpStatus.OK);
|
LOG.debug("{} target deleted, return status {}", targetId, HttpStatus.OK);
|
||||||
return ResponseEntity.ok().build();
|
return ResponseEntity.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResponseEntity<MgmtTargetAttributes> getAttributes(@PathVariable("controllerId") final String controllerId) {
|
public ResponseEntity<MgmtTargetAttributes> getAttributes(@PathVariable("targetId") final String targetId) {
|
||||||
final Map<String, String> controllerAttributes = targetManagement.getControllerAttributes(controllerId);
|
final Map<String, String> controllerAttributes = targetManagement.getControllerAttributes(targetId);
|
||||||
if (controllerAttributes.isEmpty()) {
|
if (controllerAttributes.isEmpty()) {
|
||||||
return ResponseEntity.noContent().build();
|
return ResponseEntity.noContent().build();
|
||||||
}
|
}
|
||||||
@@ -162,13 +164,13 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResponseEntity<PagedList<MgmtAction>> getActionHistory(
|
public ResponseEntity<PagedList<MgmtAction>> getActionHistory(
|
||||||
@PathVariable("controllerId") final String controllerId,
|
@PathVariable("targetId") final String targetId,
|
||||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
|
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
|
||||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
|
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
|
||||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam,
|
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam,
|
||||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SEARCH, required = false) final String rsqlParam) {
|
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SEARCH, required = false) final String rsqlParam) {
|
||||||
|
|
||||||
findTargetWithExceptionIfNotFound(controllerId);
|
findTargetWithExceptionIfNotFound(targetId);
|
||||||
|
|
||||||
final int sanitizedOffsetParam = PagingUtility.sanitizeOffsetParam(pagingOffsetParam);
|
final int sanitizedOffsetParam = PagingUtility.sanitizeOffsetParam(pagingOffsetParam);
|
||||||
final int sanitizedLimitParam = PagingUtility.sanitizePageLimitParam(pagingLimitParam);
|
final int sanitizedLimitParam = PagingUtility.sanitizePageLimitParam(pagingLimitParam);
|
||||||
@@ -178,40 +180,41 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
|
|||||||
final Slice<Action> activeActions;
|
final Slice<Action> activeActions;
|
||||||
final Long totalActionCount;
|
final Long totalActionCount;
|
||||||
if (rsqlParam != null) {
|
if (rsqlParam != null) {
|
||||||
activeActions = this.deploymentManagement.findActionsByTarget(rsqlParam, controllerId, pageable);
|
activeActions = this.deploymentManagement.findActionsByTarget(rsqlParam, targetId, pageable);
|
||||||
totalActionCount = this.deploymentManagement.countActionsByTarget(rsqlParam, controllerId);
|
totalActionCount = this.deploymentManagement.countActionsByTarget(rsqlParam, targetId);
|
||||||
} else {
|
} else {
|
||||||
activeActions = this.deploymentManagement.findActionsByTarget(controllerId, pageable);
|
activeActions = this.deploymentManagement.findActionsByTarget(targetId, pageable);
|
||||||
totalActionCount = this.deploymentManagement.countActionsByTarget(controllerId);
|
totalActionCount = this.deploymentManagement.countActionsByTarget(targetId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResponseEntity.ok(new PagedList<>(MgmtTargetMapper.toResponse(controllerId, activeActions.getContent()),
|
return ResponseEntity.ok(
|
||||||
|
new PagedList<>(MgmtTargetMapper.toResponse(targetId, activeActions.getContent()),
|
||||||
totalActionCount));
|
totalActionCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResponseEntity<MgmtAction> getAction(@PathVariable("controllerId") final String controllerId,
|
public ResponseEntity<MgmtAction> getAction(@PathVariable("targetId") final String targetId,
|
||||||
@PathVariable("actionId") final Long actionId) {
|
@PathVariable("actionId") final Long actionId) {
|
||||||
|
|
||||||
final Action action = deploymentManagement.findAction(actionId)
|
final Action action = deploymentManagement.findAction(actionId)
|
||||||
.orElseThrow(() -> new EntityNotFoundException(Action.class, actionId));
|
.orElseThrow(() -> new EntityNotFoundException(Action.class, actionId));
|
||||||
if (!action.getTarget().getControllerId().equals(controllerId)) {
|
if (!action.getTarget().getControllerId().equals(targetId)) {
|
||||||
LOG.warn("given action ({}) is not assigned to given target ({}).", action.getId(), controllerId);
|
LOG.warn("given action ({}) is not assigned to given target ({}).", action.getId(), targetId);
|
||||||
return ResponseEntity.notFound().build();
|
return ResponseEntity.notFound().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResponseEntity.ok(MgmtTargetMapper.toResponseWithLinks(controllerId, action));
|
return ResponseEntity.ok(MgmtTargetMapper.toResponseWithLinks(targetId, action));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResponseEntity<Void> cancelAction(@PathVariable("controllerId") final String controllerId,
|
public ResponseEntity<Void> cancelAction(@PathVariable("targetId") final String targetId,
|
||||||
@PathVariable("actionId") final Long actionId,
|
@PathVariable("actionId") final Long actionId,
|
||||||
@RequestParam(value = "force", required = false, defaultValue = "false") final boolean force) {
|
@RequestParam(value = "force", required = false, defaultValue = "false") final boolean force) {
|
||||||
final Action action = deploymentManagement.findAction(actionId)
|
final Action action = deploymentManagement.findAction(actionId)
|
||||||
.orElseThrow(() -> new EntityNotFoundException(Action.class, actionId));
|
.orElseThrow(() -> new EntityNotFoundException(Action.class, actionId));
|
||||||
|
|
||||||
if (!action.getTarget().getControllerId().equals(controllerId)) {
|
if (!action.getTarget().getControllerId().equals(targetId)) {
|
||||||
LOG.warn("given action ({}) is not assigned to given target ({}).", actionId, controllerId);
|
LOG.warn("given action ({}) is not assigned to given target ({}).", actionId, targetId);
|
||||||
return ResponseEntity.notFound().build();
|
return ResponseEntity.notFound().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,12 +231,12 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResponseEntity<PagedList<MgmtActionStatus>> getActionStatusList(
|
public ResponseEntity<PagedList<MgmtActionStatus>> getActionStatusList(
|
||||||
@PathVariable("controllerId") final String controllerId, @PathVariable("actionId") final Long actionId,
|
@PathVariable("targetId") final String targetId, @PathVariable("actionId") final Long actionId,
|
||||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
|
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
|
||||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
|
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
|
||||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam) {
|
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam) {
|
||||||
|
|
||||||
final Target target = findTargetWithExceptionIfNotFound(controllerId);
|
final Target target = findTargetWithExceptionIfNotFound(targetId);
|
||||||
|
|
||||||
final Action action = deploymentManagement.findAction(actionId)
|
final Action action = deploymentManagement.findAction(actionId)
|
||||||
.orElseThrow(() -> new EntityNotFoundException(Action.class, actionId));
|
.orElseThrow(() -> new EntityNotFoundException(Action.class, actionId));
|
||||||
@@ -258,8 +261,8 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResponseEntity<MgmtDistributionSet> getAssignedDistributionSet(
|
public ResponseEntity<MgmtDistributionSet> getAssignedDistributionSet(
|
||||||
@PathVariable("controllerId") final String controllerId) {
|
@PathVariable("targetId") final String targetId) {
|
||||||
final MgmtDistributionSet distributionSetRest = deploymentManagement.getAssignedDistributionSet(controllerId)
|
final MgmtDistributionSet distributionSetRest = deploymentManagement.getAssignedDistributionSet(targetId)
|
||||||
.map(ds -> {
|
.map(ds -> {
|
||||||
final MgmtDistributionSet response = MgmtDistributionSetMapper.toResponse(ds);
|
final MgmtDistributionSet response = MgmtDistributionSetMapper.toResponse(ds);
|
||||||
MgmtDistributionSetMapper.addLinks(ds, response);
|
MgmtDistributionSetMapper.addLinks(ds, response);
|
||||||
@@ -275,21 +278,21 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResponseEntity<MgmtTargetAssignmentResponseBody> postAssignedDistributionSet(
|
public ResponseEntity<MgmtTargetAssignmentResponseBody> postAssignedDistributionSet(
|
||||||
@PathVariable("controllerId") final String controllerId,
|
@PathVariable("targetId") final String targetId,
|
||||||
@RequestBody final MgmtDistributionSetAssignment dsId,
|
@RequestBody final MgmtDistributionSetAssignment dsId,
|
||||||
@RequestParam(value = "offline", required = false) final boolean offline) {
|
@RequestParam(value = "offline", required = false) final boolean offline) {
|
||||||
|
|
||||||
if (offline) {
|
if (offline) {
|
||||||
return ResponseEntity.ok(MgmtDistributionSetMapper.toResponse(
|
return ResponseEntity.ok(MgmtDistributionSetMapper.toResponse(
|
||||||
deploymentManagement.offlineAssignedDistributionSet(dsId.getId(), Arrays.asList(controllerId))));
|
deploymentManagement.offlineAssignedDistributionSet(dsId.getId(), Arrays.asList(targetId))));
|
||||||
}
|
}
|
||||||
|
|
||||||
findTargetWithExceptionIfNotFound(controllerId);
|
findTargetWithExceptionIfNotFound(targetId);
|
||||||
final MgmtMaintenanceWindowRequestBody maintenanceWindow = dsId.getMaintenanceWindow();
|
final MgmtMaintenanceWindowRequestBody maintenanceWindow = dsId.getMaintenanceWindow();
|
||||||
|
|
||||||
if (maintenanceWindow == null) {
|
if (maintenanceWindow == null) {
|
||||||
return ResponseEntity.ok(MgmtDistributionSetMapper.toResponse(this.deploymentManagement
|
return ResponseEntity.ok(MgmtDistributionSetMapper.toResponse(this.deploymentManagement
|
||||||
.assignDistributionSet(dsId.getId(), Arrays.asList(new TargetWithActionType(controllerId,
|
.assignDistributionSet(dsId.getId(), Arrays.asList(new TargetWithActionType(targetId,
|
||||||
MgmtRestModelMapper.convertActionType(dsId.getType()), dsId.getForcetime())))));
|
MgmtRestModelMapper.convertActionType(dsId.getType()), dsId.getForcetime())))));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,7 +304,7 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
|
|||||||
|
|
||||||
return ResponseEntity
|
return ResponseEntity
|
||||||
.ok(MgmtDistributionSetMapper.toResponse(this.deploymentManagement.assignDistributionSet(dsId.getId(),
|
.ok(MgmtDistributionSetMapper.toResponse(this.deploymentManagement.assignDistributionSet(dsId.getId(),
|
||||||
Arrays.asList(new TargetWithActionType(controllerId,
|
Arrays.asList(new TargetWithActionType(targetId,
|
||||||
MgmtRestModelMapper.convertActionType(dsId.getType()), dsId.getForcetime(),
|
MgmtRestModelMapper.convertActionType(dsId.getType()), dsId.getForcetime(),
|
||||||
cronSchedule, duration, timezone)))));
|
cronSchedule, duration, timezone)))));
|
||||||
|
|
||||||
@@ -309,8 +312,8 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResponseEntity<MgmtDistributionSet> getInstalledDistributionSet(
|
public ResponseEntity<MgmtDistributionSet> getInstalledDistributionSet(
|
||||||
@PathVariable("controllerId") final String controllerId) {
|
@PathVariable("targetId") final String targetId) {
|
||||||
final MgmtDistributionSet distributionSetRest = deploymentManagement.getInstalledDistributionSet(controllerId)
|
final MgmtDistributionSet distributionSetRest = deploymentManagement.getInstalledDistributionSet(targetId)
|
||||||
.map(set -> {
|
.map(set -> {
|
||||||
final MgmtDistributionSet response = MgmtDistributionSetMapper.toResponse(set);
|
final MgmtDistributionSet response = MgmtDistributionSetMapper.toResponse(set);
|
||||||
MgmtDistributionSetMapper.addLinks(set, response);
|
MgmtDistributionSetMapper.addLinks(set, response);
|
||||||
@@ -325,19 +328,19 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
|
|||||||
return ResponseEntity.ok(distributionSetRest);
|
return ResponseEntity.ok(distributionSetRest);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Target findTargetWithExceptionIfNotFound(final String controllerId) {
|
private Target findTargetWithExceptionIfNotFound(final String targetId) {
|
||||||
return targetManagement.getByControllerID(controllerId)
|
return targetManagement.getByControllerID(targetId)
|
||||||
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
|
.orElseThrow(() -> new EntityNotFoundException(Target.class, targetId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResponseEntity<MgmtAction> updateAction(@PathVariable("controllerId") final String controllerId,
|
public ResponseEntity<MgmtAction> updateAction(@PathVariable("targetId") final String targetId,
|
||||||
@PathVariable("actionId") final Long actionId, @RequestBody final MgmtActionRequestBodyPut actionUpdate) {
|
@PathVariable("actionId") final Long actionId, @RequestBody final MgmtActionRequestBodyPut actionUpdate) {
|
||||||
|
|
||||||
Action action = deploymentManagement.findAction(actionId)
|
Action action = deploymentManagement.findAction(actionId)
|
||||||
.orElseThrow(() -> new EntityNotFoundException(Action.class, actionId));
|
.orElseThrow(() -> new EntityNotFoundException(Action.class, actionId));
|
||||||
if (!action.getTarget().getControllerId().equals(controllerId)) {
|
if (!action.getTarget().getControllerId().equals(targetId)) {
|
||||||
LOG.warn("given action ({}) is not assigned to given target ({}).", action.getId(), controllerId);
|
LOG.warn("given action ({}) is not assigned to given target ({}).", action.getId(), targetId);
|
||||||
return ResponseEntity.notFound().build();
|
return ResponseEntity.notFound().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -347,7 +350,62 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
|
|||||||
|
|
||||||
action = deploymentManagement.forceTargetAction(actionId);
|
action = deploymentManagement.forceTargetAction(actionId);
|
||||||
|
|
||||||
return ResponseEntity.ok(MgmtTargetMapper.toResponseWithLinks(controllerId, action));
|
return ResponseEntity.ok(MgmtTargetMapper.toResponseWithLinks(targetId, action));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResponseEntity<PagedList<MgmtMetadata>> getMetadata(@PathVariable("targetId") final String targetId,
|
||||||
|
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
|
||||||
|
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
|
||||||
|
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam,
|
||||||
|
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SEARCH, required = false) final String rsqlParam) {
|
||||||
|
|
||||||
|
final int sanitizedOffsetParam = PagingUtility.sanitizeOffsetParam(pagingOffsetParam);
|
||||||
|
final int sanitizedLimitParam = PagingUtility.sanitizePageLimitParam(pagingLimitParam);
|
||||||
|
final Sort sorting = PagingUtility.sanitizeDistributionSetMetadataSortParam(sortParam);
|
||||||
|
|
||||||
|
final Pageable pageable = new OffsetBasedPageRequest(sanitizedOffsetParam, sanitizedLimitParam, sorting);
|
||||||
|
final Page<TargetMetadata> metaDataPage;
|
||||||
|
|
||||||
|
if (rsqlParam != null) {
|
||||||
|
metaDataPage = targetManagement.findMetaDataByControllerIdAndRsql(pageable, targetId, rsqlParam);
|
||||||
|
} else {
|
||||||
|
metaDataPage = targetManagement.findMetaDataByControllerId(pageable, targetId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResponseEntity.ok(new PagedList<>(MgmtTargetMapper.toResponseTargetMetadata(metaDataPage.getContent()),
|
||||||
|
metaDataPage.getTotalElements()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResponseEntity<MgmtMetadata> getMetadataValue(@PathVariable("targetId") final String targetId,
|
||||||
|
@PathVariable("metadataKey") final String metadataKey) {
|
||||||
|
final TargetMetadata findOne = targetManagement.getMetaDataByControllerId(targetId, metadataKey)
|
||||||
|
.orElseThrow(() -> new EntityNotFoundException(TargetMetadata.class, targetId, metadataKey));
|
||||||
|
return ResponseEntity.ok(MgmtTargetMapper.toResponseTargetMetadata(findOne));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResponseEntity<MgmtMetadata> updateMetadata(@PathVariable("targetId") final String targetId,
|
||||||
|
@PathVariable("metadataKey") final String metadataKey, @RequestBody final MgmtMetadataBodyPut metadata) {
|
||||||
|
final TargetMetadata updated = targetManagement.updateMetaData(targetId,
|
||||||
|
entityFactory.generateTargetMetadata(metadataKey, metadata.getValue()));
|
||||||
|
return ResponseEntity.ok(MgmtTargetMapper.toResponseTargetMetadata(updated));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResponseEntity<Void> deleteMetadata(@PathVariable("targetId") final String targetId,
|
||||||
|
@PathVariable("metadataKey") final String metadataKey) {
|
||||||
|
targetManagement.deleteMetaData(targetId, metadataKey);
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResponseEntity<List<MgmtMetadata>> createMetadata(@PathVariable("targetId") final String targetId,
|
||||||
|
@RequestBody final List<MgmtMetadata> metadataRest) {
|
||||||
|
final List<TargetMetadata> created = targetManagement.createMetaData(targetId,
|
||||||
|
MgmtTargetMapper.fromRequestTargetMetadata(metadataRest, entityFactory));
|
||||||
|
return new ResponseEntity<>(MgmtTargetMapper.toResponseTargetMetadata(created), HttpStatus.CREATED);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1036,7 +1036,7 @@ public class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegr
|
|||||||
final String updateValue = "valueForUpdate";
|
final String updateValue = "valueForUpdate";
|
||||||
|
|
||||||
final DistributionSet testDS = testdataFactory.createDistributionSet("one");
|
final DistributionSet testDS = testdataFactory.createDistributionSet("one");
|
||||||
createDistributionSetMetadata(testDS.getId(), entityFactory.generateMetadata(knownKey, knownValue));
|
createDistributionSetMetadata(testDS.getId(), entityFactory.generateDsMetadata(knownKey, knownValue));
|
||||||
|
|
||||||
final JSONObject jsonObject = new JSONObject().put("key", knownKey).put("value", updateValue);
|
final JSONObject jsonObject = new JSONObject().put("key", knownKey).put("value", updateValue);
|
||||||
|
|
||||||
@@ -1060,7 +1060,7 @@ public class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegr
|
|||||||
final String knownValue = "knownValue";
|
final String knownValue = "knownValue";
|
||||||
|
|
||||||
final DistributionSet testDS = testdataFactory.createDistributionSet("one");
|
final DistributionSet testDS = testdataFactory.createDistributionSet("one");
|
||||||
createDistributionSetMetadata(testDS.getId(), entityFactory.generateMetadata(knownKey, knownValue));
|
createDistributionSetMetadata(testDS.getId(), entityFactory.generateDsMetadata(knownKey, knownValue));
|
||||||
|
|
||||||
mvc.perform(delete("/rest/v1/distributionsets/{dsId}/metadata/{key}", testDS.getId(), knownKey))
|
mvc.perform(delete("/rest/v1/distributionsets/{dsId}/metadata/{key}", testDS.getId(), knownKey))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||||
@@ -1076,7 +1076,7 @@ public class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegr
|
|||||||
final String knownValue = "knownValue";
|
final String knownValue = "knownValue";
|
||||||
|
|
||||||
final DistributionSet testDS = testdataFactory.createDistributionSet("one");
|
final DistributionSet testDS = testdataFactory.createDistributionSet("one");
|
||||||
createDistributionSetMetadata(testDS.getId(), entityFactory.generateMetadata(knownKey, knownValue));
|
createDistributionSetMetadata(testDS.getId(), entityFactory.generateDsMetadata(knownKey, knownValue));
|
||||||
|
|
||||||
mvc.perform(delete("/rest/v1/distributionsets/{dsId}/metadata/XXX", testDS.getId(), knownKey))
|
mvc.perform(delete("/rest/v1/distributionsets/{dsId}/metadata/XXX", testDS.getId(), knownKey))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||||
@@ -1094,7 +1094,7 @@ public class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegr
|
|||||||
final String knownKey = "knownKey";
|
final String knownKey = "knownKey";
|
||||||
final String knownValue = "knownValue";
|
final String knownValue = "knownValue";
|
||||||
final DistributionSet testDS = testdataFactory.createDistributionSet("one");
|
final DistributionSet testDS = testdataFactory.createDistributionSet("one");
|
||||||
createDistributionSetMetadata(testDS.getId(), entityFactory.generateMetadata(knownKey, knownValue));
|
createDistributionSetMetadata(testDS.getId(), entityFactory.generateDsMetadata(knownKey, knownValue));
|
||||||
|
|
||||||
mvc.perform(get("/rest/v1/distributionsets/{dsId}/metadata/{key}", testDS.getId(), knownKey))
|
mvc.perform(get("/rest/v1/distributionsets/{dsId}/metadata/{key}", testDS.getId(), knownKey))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
@@ -1113,7 +1113,7 @@ public class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegr
|
|||||||
final DistributionSet testDS = testdataFactory.createDistributionSet("one");
|
final DistributionSet testDS = testdataFactory.createDistributionSet("one");
|
||||||
for (int index = 0; index < totalMetadata; index++) {
|
for (int index = 0; index < totalMetadata; index++) {
|
||||||
createDistributionSetMetadata(testDS.getId(),
|
createDistributionSetMetadata(testDS.getId(),
|
||||||
entityFactory.generateMetadata(knownKeyPrefix + index, knownValuePrefix + index));
|
entityFactory.generateDsMetadata(knownKeyPrefix + index, knownValuePrefix + index));
|
||||||
}
|
}
|
||||||
|
|
||||||
mvc.perform(get("/rest/v1/distributionsets/{dsId}/metadata?offset=" + offsetParam + "&limit=" + limitParam,
|
mvc.perform(get("/rest/v1/distributionsets/{dsId}/metadata?offset=" + offsetParam + "&limit=" + limitParam,
|
||||||
@@ -1189,7 +1189,7 @@ public class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegr
|
|||||||
final DistributionSet testDS = testdataFactory.createDistributionSet("one");
|
final DistributionSet testDS = testdataFactory.createDistributionSet("one");
|
||||||
for (int index = 0; index < totalMetadata; index++) {
|
for (int index = 0; index < totalMetadata; index++) {
|
||||||
createDistributionSetMetadata(testDS.getId(),
|
createDistributionSetMetadata(testDS.getId(),
|
||||||
entityFactory.generateMetadata(knownKeyPrefix + index, knownValuePrefix + index));
|
entityFactory.generateDsMetadata(knownKeyPrefix + index, knownValuePrefix + index));
|
||||||
}
|
}
|
||||||
|
|
||||||
final String rsqlSearchValue1 = "value==knownValue1";
|
final String rsqlSearchValue1 = "value==knownValue1";
|
||||||
|
|||||||
@@ -26,8 +26,10 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
|||||||
|
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -45,8 +47,10 @@ import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
|||||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||||
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
|
import org.eclipse.hawkbit.repository.model.MetaData;
|
||||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||||
import org.eclipse.hawkbit.repository.model.Target;
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
|
import org.eclipse.hawkbit.repository.model.TargetMetadata;
|
||||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||||
import org.eclipse.hawkbit.repository.test.util.WithUser;
|
import org.eclipse.hawkbit.repository.test.util.WithUser;
|
||||||
import org.eclipse.hawkbit.rest.exception.MessageNotReadableException;
|
import org.eclipse.hawkbit.rest.exception.MessageNotReadableException;
|
||||||
@@ -54,6 +58,7 @@ import org.eclipse.hawkbit.rest.json.model.ExceptionInfo;
|
|||||||
import org.eclipse.hawkbit.rest.util.JsonBuilder;
|
import org.eclipse.hawkbit.rest.util.JsonBuilder;
|
||||||
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
|
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
|
||||||
import org.eclipse.hawkbit.util.IpUtil;
|
import org.eclipse.hawkbit.util.IpUtil;
|
||||||
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.data.domain.PageRequest;
|
import org.springframework.data.domain.PageRequest;
|
||||||
@@ -1564,8 +1569,8 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
|||||||
final String body = new JSONObject().put("requestAttributes", true).toString();
|
final String body = new JSONObject().put("requestAttributes", true).toString();
|
||||||
|
|
||||||
mvc.perform(put(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId).content(body)
|
mvc.perform(put(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId).content(body)
|
||||||
.contentType(MediaType.APPLICATION_JSON))
|
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
.andExpect(status().isOk());
|
||||||
|
|
||||||
assertThat(targetManagement.isControllerAttributesRequested(knownTargetId)).isTrue();
|
assertThat(targetManagement.isControllerAttributesRequested(knownTargetId)).isTrue();
|
||||||
}
|
}
|
||||||
@@ -1575,8 +1580,8 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
|||||||
final String body = new JSONObject().put("description", "verify attribute can be missing").toString();
|
final String body = new JSONObject().put("description", "verify attribute can be missing").toString();
|
||||||
|
|
||||||
mvc.perform(put(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId).content(body)
|
mvc.perform(put(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId).content(body)
|
||||||
.contentType(MediaType.APPLICATION_JSON))
|
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
.andExpect(status().isOk());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Step
|
@Step
|
||||||
@@ -1584,8 +1589,8 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
|||||||
final String body = new JSONObject().put("requestAttributes", false).toString();
|
final String body = new JSONObject().put("requestAttributes", false).toString();
|
||||||
|
|
||||||
mvc.perform(put(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId).content(body)
|
mvc.perform(put(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId).content(body)
|
||||||
.contentType(MediaType.APPLICATION_JSON))
|
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest());
|
.andExpect(status().isBadRequest());
|
||||||
|
|
||||||
assertThat(targetManagement.isControllerAttributesRequested(knownTargetId)).isTrue();
|
assertThat(targetManagement.isControllerAttributesRequested(knownTargetId)).isTrue();
|
||||||
}
|
}
|
||||||
@@ -1649,4 +1654,193 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
|||||||
assertThat(actionsByTarget.getContent()).hasSize(1);
|
assertThat(actionsByTarget.getContent()).hasSize(1);
|
||||||
return targetManagement.getByControllerID(tA.getControllerId()).get();
|
return targetManagement.getByControllerID(tA.getControllerId()).get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Ensures that the metadata creation through API is reflected by the repository.")
|
||||||
|
public void createMetadata() throws Exception {
|
||||||
|
final String knownControllerId = "targetIdWithMetadata";
|
||||||
|
testdataFactory.createTarget(knownControllerId);
|
||||||
|
|
||||||
|
final String knownKey1 = "knownKey1";
|
||||||
|
final String knownKey2 = "knownKey2";
|
||||||
|
|
||||||
|
final String knownValue1 = "knownValue1";
|
||||||
|
final String knownValue2 = "knownValue2";
|
||||||
|
|
||||||
|
final JSONArray metaData1 = new JSONArray();
|
||||||
|
metaData1.put(new JSONObject().put("key", knownKey1).put("value", knownValue1));
|
||||||
|
metaData1.put(new JSONObject().put("key", knownKey2).put("value", knownValue2));
|
||||||
|
|
||||||
|
mvc.perform(
|
||||||
|
post("/rest/v1/targets/{targetId}/metadata", knownControllerId).accept(MediaType.APPLICATION_JSON)
|
||||||
|
.contentType(MediaType.APPLICATION_JSON).content(metaData1.toString()))
|
||||||
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated())
|
||||||
|
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||||
|
.andExpect(jsonPath("[0]key", equalTo(knownKey1))).andExpect(jsonPath("[0]value", equalTo(knownValue1)))
|
||||||
|
.andExpect(jsonPath("[1]key", equalTo(knownKey2)))
|
||||||
|
.andExpect(jsonPath("[1]value", equalTo(knownValue2)));
|
||||||
|
|
||||||
|
final TargetMetadata metaKey1 = targetManagement.getMetaDataByControllerId(knownControllerId, knownKey1).get();
|
||||||
|
final TargetMetadata metaKey2 = targetManagement.getMetaDataByControllerId(knownControllerId, knownKey2).get();
|
||||||
|
|
||||||
|
assertThat(metaKey1.getValue()).isEqualTo(knownValue1);
|
||||||
|
assertThat(metaKey2.getValue()).isEqualTo(knownValue2);
|
||||||
|
|
||||||
|
// verify quota enforcement
|
||||||
|
final int maxMetaData = quotaManagement.getMaxMetaDataEntriesPerTarget();
|
||||||
|
|
||||||
|
final JSONArray metaData2 = new JSONArray();
|
||||||
|
for (int i = 0; i < maxMetaData - metaData1.length() + 1; ++i) {
|
||||||
|
metaData2.put(new JSONObject().put("key", knownKey1 + i).put("value", knownValue1 + i));
|
||||||
|
}
|
||||||
|
|
||||||
|
mvc.perform(
|
||||||
|
post("/rest/v1/targets/{targetId}/metadata", knownControllerId).accept(MediaType.APPLICATION_JSON)
|
||||||
|
.contentType(MediaType.APPLICATION_JSON).content(metaData2.toString()))
|
||||||
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isForbidden());
|
||||||
|
|
||||||
|
// verify that the number of meta data entries has not changed
|
||||||
|
// (we cannot use the PAGE constant here as it tries to sort by ID)
|
||||||
|
assertThat(targetManagement.findMetaDataByControllerId(new PageRequest(0, Integer.MAX_VALUE), knownControllerId)
|
||||||
|
.getTotalElements()).isEqualTo(metaData1.length());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Ensures that a metadata update through API is reflected by the repository.")
|
||||||
|
public void updateMetadata() throws Exception {
|
||||||
|
final String knownControllerId = "targetIdWithMetadata";
|
||||||
|
|
||||||
|
// prepare and create metadata for update
|
||||||
|
final String knownKey = "knownKey";
|
||||||
|
final String knownValue = "knownValue";
|
||||||
|
final String updateValue = "valueForUpdate";
|
||||||
|
|
||||||
|
setupTargetWithMetadata(knownControllerId, knownKey, knownValue);
|
||||||
|
|
||||||
|
final JSONObject jsonObject = new JSONObject().put("key", knownKey).put("value", updateValue);
|
||||||
|
|
||||||
|
mvc.perform(put("/rest/v1/targets/{targetId}/metadata/{key}", knownControllerId, knownKey)
|
||||||
|
.accept(MediaType.APPLICATION_JSON).contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.content(jsonObject.toString())).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
|
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||||
|
.andExpect(jsonPath("key", equalTo(knownKey))).andExpect(jsonPath("value", equalTo(updateValue)));
|
||||||
|
|
||||||
|
final TargetMetadata updatedTargetMetadata = targetManagement
|
||||||
|
.getMetaDataByControllerId(knownControllerId, knownKey).get();
|
||||||
|
assertThat(updatedTargetMetadata.getValue()).isEqualTo(updateValue);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupTargetWithMetadata(final String knownControllerId, final String knownKey,
|
||||||
|
final String knownValue) {
|
||||||
|
testdataFactory.createTarget(knownControllerId);
|
||||||
|
targetManagement.createMetaData(knownControllerId,
|
||||||
|
Collections.singletonList(entityFactory.generateTargetMetadata(knownKey, knownValue)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Ensures that a metadata entry deletion through API is reflected by the repository.")
|
||||||
|
public void deleteMetadata() throws Exception {
|
||||||
|
final String knownControllerId = "targetIdWithMetadata";
|
||||||
|
|
||||||
|
// prepare and create metadata for deletion
|
||||||
|
final String knownKey = "knownKey";
|
||||||
|
final String knownValue = "knownValue";
|
||||||
|
|
||||||
|
setupTargetWithMetadata(knownControllerId, knownKey, knownValue);
|
||||||
|
|
||||||
|
mvc.perform(delete("/rest/v1/targets/{targetId}/metadata/{key}", knownControllerId, knownKey))
|
||||||
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||||
|
|
||||||
|
assertThat(targetManagement.getMetaDataByControllerId(knownControllerId, knownKey)).isNotPresent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Ensures that target metadata deletion request to API on an entity that does not exist results in NOT_FOUND.")
|
||||||
|
public void deleteMetadataThatDoesNotExistLeadsToNotFound() throws Exception {
|
||||||
|
final String knownControllerId = "targetIdWithMetadata";
|
||||||
|
|
||||||
|
// prepare and create metadata for deletion
|
||||||
|
final String knownKey = "knownKey";
|
||||||
|
final String knownValue = "knownValue";
|
||||||
|
|
||||||
|
setupTargetWithMetadata(knownControllerId, knownKey, knownValue);
|
||||||
|
|
||||||
|
mvc.perform(delete("/rest/v1/targets/{targetId}/metadata/XXX", knownControllerId))
|
||||||
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||||
|
|
||||||
|
mvc.perform(delete("/rest/v1/targets/1234/metadata/{key}", knownKey)).andDo(MockMvcResultPrinter.print())
|
||||||
|
.andExpect(status().isNotFound());
|
||||||
|
|
||||||
|
assertThat(targetManagement.getMetaDataByControllerId(knownControllerId, knownKey)).isPresent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Ensures that a metadata entry selection through API reflectes the repository content.")
|
||||||
|
public void getSingleMetadata() throws Exception {
|
||||||
|
final String knownControllerId = "targetIdWithMetadata";
|
||||||
|
|
||||||
|
// prepare and create metadata for deletion
|
||||||
|
final String knownKey = "knownKey";
|
||||||
|
final String knownValue = "knownValue";
|
||||||
|
|
||||||
|
setupTargetWithMetadata(knownControllerId, knownKey, knownValue);
|
||||||
|
|
||||||
|
mvc.perform(get("/rest/v1/targets/{targetId}/metadata/{key}", knownControllerId, knownKey))
|
||||||
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("key", equalTo(knownKey))).andExpect(jsonPath("value", equalTo(knownValue)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Ensures that a metadata entry paged list selection through API reflectes the repository content.")
|
||||||
|
public void getPagedListOfMetadata() throws Exception {
|
||||||
|
final String knownControllerId = "targetIdWithMetadata";
|
||||||
|
|
||||||
|
final int totalMetadata = 10;
|
||||||
|
final int limitParam = 5;
|
||||||
|
final String offsetParam = "0";
|
||||||
|
final String knownKeyPrefix = "knownKey";
|
||||||
|
final String knownValuePrefix = "knownValue";
|
||||||
|
|
||||||
|
setupTargetWithMetadata(knownControllerId, knownKeyPrefix, knownValuePrefix, totalMetadata);
|
||||||
|
|
||||||
|
mvc.perform(get("/rest/v1/targets/{targetId}/metadata?offset=" + offsetParam + "&limit=" + limitParam,
|
||||||
|
knownControllerId)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("size", equalTo(limitParam))).andExpect(jsonPath("total", equalTo(totalMetadata)))
|
||||||
|
.andExpect(jsonPath("content[0].key", equalTo("knownKey0")))
|
||||||
|
.andExpect(jsonPath("content[0].value", equalTo("knownValue0")));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupTargetWithMetadata(final String knownControllerId, final String knownKeyPrefix,
|
||||||
|
final String knownValuePrefix, final int totalMetadata) {
|
||||||
|
testdataFactory.createTarget(knownControllerId);
|
||||||
|
|
||||||
|
final List<MetaData> targetMetadataEntries = new LinkedList<>();
|
||||||
|
for (int index = 0; index < totalMetadata; index++) {
|
||||||
|
targetMetadataEntries
|
||||||
|
.add(entityFactory.generateTargetMetadata(knownKeyPrefix + index, knownValuePrefix + index));
|
||||||
|
}
|
||||||
|
targetManagement.createMetaData(knownControllerId, targetMetadataEntries);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Ensures that a target metadata filtered query with value==knownValue1 parameter returns only the metadata entries with that value.")
|
||||||
|
public void searchDistributionSetMetadataRsql() throws Exception {
|
||||||
|
final String knownControllerId = "targetIdWithMetadata";
|
||||||
|
|
||||||
|
final int totalMetadata = 10;
|
||||||
|
final String knownKeyPrefix = "knownKey";
|
||||||
|
final String knownValuePrefix = "knownValue";
|
||||||
|
|
||||||
|
setupTargetWithMetadata(knownControllerId, knownKeyPrefix, knownValuePrefix, totalMetadata);
|
||||||
|
|
||||||
|
final String rsqlSearchValue1 = "value==knownValue1";
|
||||||
|
|
||||||
|
mvc.perform(get("/rest/v1/targets/{targetId}/metadata?q=" + rsqlSearchValue1, knownControllerId))
|
||||||
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()).andExpect(jsonPath("size", equalTo(1)))
|
||||||
|
.andExpect(jsonPath("total", equalTo(1))).andExpect(jsonPath("content[0].key", equalTo("knownKey1")))
|
||||||
|
.andExpect(jsonPath("content[0].value", equalTo("knownValue1")));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -683,6 +683,241 @@ include::../errors/406.adoc[]
|
|||||||
include::../errors/429.adoc[]
|
include::../errors/429.adoc[]
|
||||||
|===
|
|===
|
||||||
|
|
||||||
|
== GET /rest/v1/targets/{targetId}/metadata
|
||||||
|
|
||||||
|
=== Implementation Notes
|
||||||
|
|
||||||
|
Get a paged list of meta data for a target. Required permission: READ_REPOSITORY
|
||||||
|
|
||||||
|
=== Get a paged list of meta data
|
||||||
|
|
||||||
|
==== Curl
|
||||||
|
|
||||||
|
include::{snippets}/targets/get-metadata/curl-request.adoc[]
|
||||||
|
|
||||||
|
==== Request URL
|
||||||
|
|
||||||
|
include::{snippets}/targets/get-metadata/http-request.adoc[]
|
||||||
|
|
||||||
|
==== Request path parameter
|
||||||
|
|
||||||
|
include::{snippets}/targets/get-metadata/path-parameters.adoc[]
|
||||||
|
|
||||||
|
==== Request query parameter
|
||||||
|
|
||||||
|
include::{snippets}/targets/get-metadata-with-parameters/request-parameters.adoc[]
|
||||||
|
|
||||||
|
==== Request parameter example
|
||||||
|
|
||||||
|
include::{snippets}/targets/get-metadata-with-parameters/http-request.adoc[]
|
||||||
|
|
||||||
|
=== Response (Status 200)
|
||||||
|
|
||||||
|
==== Response fields
|
||||||
|
|
||||||
|
include::{snippets}/targets/get-metadata/response-fields.adoc[]
|
||||||
|
|
||||||
|
==== Response example
|
||||||
|
|
||||||
|
include::{snippets}/targets/get-metadata/http-response.adoc[]
|
||||||
|
|
||||||
|
=== Error responses
|
||||||
|
|
||||||
|
|===
|
||||||
|
| HTTP Status Code | Reason | Response Model
|
||||||
|
|
||||||
|
include::../errors/400.adoc[]
|
||||||
|
include::../errors/401.adoc[]
|
||||||
|
include::../errors/403.adoc[]
|
||||||
|
include::../errors/405.adoc[]
|
||||||
|
include::../errors/406.adoc[]
|
||||||
|
include::../errors/429.adoc[]
|
||||||
|
|===
|
||||||
|
|
||||||
|
== POST /rest/v1/targets/{targetId}/metadata
|
||||||
|
|
||||||
|
=== Implementation Notes
|
||||||
|
|
||||||
|
Create a list of meta data entries Required permissions: READ_REPOSITORY and UPDATE_TARGET
|
||||||
|
|
||||||
|
=== Create a list of meta data entries
|
||||||
|
|
||||||
|
|
||||||
|
==== CURL
|
||||||
|
|
||||||
|
include::{snippets}/targets/create-metadata/curl-request.adoc[]
|
||||||
|
|
||||||
|
==== Request URL
|
||||||
|
|
||||||
|
include::{snippets}/targets/create-metadata/http-request.adoc[]
|
||||||
|
|
||||||
|
==== Request path parameter
|
||||||
|
|
||||||
|
include::{snippets}/targets/create-metadata/path-parameters.adoc[]
|
||||||
|
|
||||||
|
==== Request fields
|
||||||
|
|
||||||
|
include::{snippets}/targets/create-metadata/request-fields.adoc[]
|
||||||
|
|
||||||
|
=== Response (Status 200)
|
||||||
|
|
||||||
|
==== Response example
|
||||||
|
|
||||||
|
include::{snippets}/targets/create-metadata/http-response.adoc[]
|
||||||
|
|
||||||
|
=== Error responses
|
||||||
|
|
||||||
|
|===
|
||||||
|
| HTTP Status Code | Reason | Response Model
|
||||||
|
|
||||||
|
include::../errors/400.adoc[]
|
||||||
|
include::../errors/401.adoc[]
|
||||||
|
include::../errors/403.adoc[]
|
||||||
|
include::../errors/404.adoc[]
|
||||||
|
include::../errors/405.adoc[]
|
||||||
|
include::../errors/406.adoc[]
|
||||||
|
include::../errors/409.adoc[]
|
||||||
|
include::../errors/415.adoc[]
|
||||||
|
include::../errors/429.adoc[]
|
||||||
|
|===
|
||||||
|
|
||||||
|
|
||||||
|
== DELETE /rest/v1/targets/{targetId}/metadata/{metadataKey}
|
||||||
|
|
||||||
|
|
||||||
|
=== Implementation Notes
|
||||||
|
|
||||||
|
Delete a single meta data. Required permission: UPDATE_REPOSITORY
|
||||||
|
|
||||||
|
=== Delete a single meta data
|
||||||
|
|
||||||
|
==== CURL
|
||||||
|
|
||||||
|
include::{snippets}/targets/delete-metadata/curl-request.adoc[]
|
||||||
|
|
||||||
|
==== Request URL
|
||||||
|
|
||||||
|
include::{snippets}/targets/delete-metadata/http-request.adoc[]
|
||||||
|
|
||||||
|
==== Request path parameter
|
||||||
|
|
||||||
|
include::{snippets}/targets/delete-metadata/path-parameters.adoc[]
|
||||||
|
|
||||||
|
=== Response (Status 200)
|
||||||
|
|
||||||
|
==== Response example
|
||||||
|
|
||||||
|
include::{snippets}/targets/delete-metadata/http-response.adoc[]
|
||||||
|
|
||||||
|
=== Error responses
|
||||||
|
|
||||||
|
|===
|
||||||
|
| HTTP Status Code | Reason | Response Model
|
||||||
|
|
||||||
|
include::../errors/400.adoc[]
|
||||||
|
include::../errors/401.adoc[]
|
||||||
|
include::../errors/403.adoc[]
|
||||||
|
include::../errors/404.adoc[]
|
||||||
|
include::../errors/405.adoc[]
|
||||||
|
include::../errors/406.adoc[]
|
||||||
|
include::../errors/429.adoc[]
|
||||||
|
|===
|
||||||
|
|
||||||
|
|
||||||
|
== GET /rest/v1/targets/{targetId}/metadata/{metadataKey}
|
||||||
|
|
||||||
|
|
||||||
|
=== Implementation Notes
|
||||||
|
|
||||||
|
Get a single meta data value for a meta data key. Required permission: READ_REPOSITORY
|
||||||
|
|
||||||
|
=== Get a single meta data value
|
||||||
|
|
||||||
|
==== Curl
|
||||||
|
|
||||||
|
include::{snippets}/targets/get-metadata-value/curl-request.adoc[]
|
||||||
|
|
||||||
|
==== Request URL
|
||||||
|
|
||||||
|
include::{snippets}/targets/get-metadata-value/http-request.adoc[]
|
||||||
|
|
||||||
|
==== Request path parameter
|
||||||
|
|
||||||
|
include::{snippets}/targets/get-metadata-value/path-parameters.adoc[]
|
||||||
|
|
||||||
|
=== Response (Status 200)
|
||||||
|
|
||||||
|
==== Response fields
|
||||||
|
|
||||||
|
include::{snippets}/targets/get-metadata-value/response-fields.adoc[]
|
||||||
|
|
||||||
|
==== Response example
|
||||||
|
|
||||||
|
include::{snippets}/targets/get-metadata-value/http-response.adoc[]
|
||||||
|
|
||||||
|
=== Error responses
|
||||||
|
|
||||||
|
|===
|
||||||
|
| HTTP Status Code | Reason | Response Model
|
||||||
|
|
||||||
|
include::../errors/400.adoc[]
|
||||||
|
include::../errors/401.adoc[]
|
||||||
|
include::../errors/403.adoc[]
|
||||||
|
include::../errors/405.adoc[]
|
||||||
|
include::../errors/406.adoc[]
|
||||||
|
include::../errors/429.adoc[]
|
||||||
|
|===
|
||||||
|
|
||||||
|
== PUT /rest/v1/targets/{targetId}/metadata/{metadataKey}
|
||||||
|
|
||||||
|
|
||||||
|
=== Implementation Notes
|
||||||
|
|
||||||
|
Update a single meta data value for speficic key. Required permission: UPDATE_REPOSITORY
|
||||||
|
|
||||||
|
=== Update a single meta data value
|
||||||
|
|
||||||
|
==== Curl
|
||||||
|
|
||||||
|
include::{snippets}/targets/update-metadata/curl-request.adoc[]
|
||||||
|
|
||||||
|
==== Request URL
|
||||||
|
|
||||||
|
include::{snippets}/targets/update-metadata/http-request.adoc[]
|
||||||
|
|
||||||
|
==== Request path parameter
|
||||||
|
|
||||||
|
include::{snippets}/targets/update-metadata/path-parameters.adoc[]
|
||||||
|
|
||||||
|
==== Request fields
|
||||||
|
|
||||||
|
include::{snippets}/targets/update-metadata/request-fields.adoc[]
|
||||||
|
|
||||||
|
=== Response (Status 200)
|
||||||
|
|
||||||
|
==== Response fields
|
||||||
|
|
||||||
|
include::{snippets}/targets/update-metadata/response-fields.adoc[]
|
||||||
|
|
||||||
|
==== Response example
|
||||||
|
|
||||||
|
include::{snippets}/targets/update-metadata/http-response.adoc[]
|
||||||
|
|
||||||
|
=== Error responses
|
||||||
|
|
||||||
|
|===
|
||||||
|
| HTTP Status Code | Reason | Response Model
|
||||||
|
|
||||||
|
include::../errors/400.adoc[]
|
||||||
|
include::../errors/401.adoc[]
|
||||||
|
include::../errors/403.adoc[]
|
||||||
|
include::../errors/404.adoc[]
|
||||||
|
include::../errors/405.adoc[]
|
||||||
|
include::../errors/406.adoc[]
|
||||||
|
include::../errors/409.adoc[]
|
||||||
|
include::../errors/415.adoc[]
|
||||||
|
include::../errors/429.adoc[]
|
||||||
|
|===
|
||||||
|
|
||||||
== Additional content
|
== Additional content
|
||||||
|
|
||||||
|
|||||||
@@ -248,7 +248,9 @@ public abstract class AbstractApiRestDocumentation extends AbstractRestIntegrati
|
|||||||
fieldWithPath(fieldArrayPrefix + "_links.attributes")
|
fieldWithPath(fieldArrayPrefix + "_links.attributes")
|
||||||
.description(MgmtApiModelProperties.LINKS_ATTRIBUTES),
|
.description(MgmtApiModelProperties.LINKS_ATTRIBUTES),
|
||||||
fieldWithPath(fieldArrayPrefix + "_links.actions")
|
fieldWithPath(fieldArrayPrefix + "_links.actions")
|
||||||
.description(MgmtApiModelProperties.LINKS_ACTIONS)));
|
.description(MgmtApiModelProperties.LINKS_ACTIONS),
|
||||||
|
fieldWithPath(fieldArrayPrefix + "_links.metadata").description(MgmtApiModelProperties.META_DATA)));
|
||||||
|
|
||||||
}
|
}
|
||||||
fields.addAll(Arrays.asList(descriptors));
|
fields.addAll(Arrays.asList(descriptors));
|
||||||
|
|
||||||
|
|||||||
@@ -504,7 +504,7 @@ public class DistributionSetsDocumentationTest extends AbstractApiRestDocumentat
|
|||||||
final DistributionSet testDS = testdataFactory.createDistributionSet("one");
|
final DistributionSet testDS = testdataFactory.createDistributionSet("one");
|
||||||
for (int index = 0; index < totalMetadata; index++) {
|
for (int index = 0; index < totalMetadata; index++) {
|
||||||
distributionSetManagement.createMetaData(testDS.getId(), Lists
|
distributionSetManagement.createMetaData(testDS.getId(), Lists
|
||||||
.newArrayList(entityFactory.generateMetadata(knownKeyPrefix + index, knownValuePrefix + index)));
|
.newArrayList(entityFactory.generateDsMetadata(knownKeyPrefix + index, knownValuePrefix + index)));
|
||||||
}
|
}
|
||||||
|
|
||||||
mockMvc.perform(get(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/metadata",
|
mockMvc.perform(get(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/metadata",
|
||||||
@@ -532,7 +532,7 @@ public class DistributionSetsDocumentationTest extends AbstractApiRestDocumentat
|
|||||||
final DistributionSet testDS = testdataFactory.createDistributionSet("one");
|
final DistributionSet testDS = testdataFactory.createDistributionSet("one");
|
||||||
for (int index = 0; index < totalMetadata; index++) {
|
for (int index = 0; index < totalMetadata; index++) {
|
||||||
distributionSetManagement.createMetaData(testDS.getId(), Lists
|
distributionSetManagement.createMetaData(testDS.getId(), Lists
|
||||||
.newArrayList(entityFactory.generateMetadata(knownKeyPrefix + index, knownValuePrefix + index)));
|
.newArrayList(entityFactory.generateDsMetadata(knownKeyPrefix + index, knownValuePrefix + index)));
|
||||||
}
|
}
|
||||||
|
|
||||||
mockMvc.perform(get(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{dsId}/metadata", testDS.getId())
|
mockMvc.perform(get(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{dsId}/metadata", testDS.getId())
|
||||||
@@ -564,7 +564,7 @@ public class DistributionSetsDocumentationTest extends AbstractApiRestDocumentat
|
|||||||
final String knownValue = "knownValue";
|
final String knownValue = "knownValue";
|
||||||
final DistributionSet testDS = testdataFactory.createDistributionSet("one");
|
final DistributionSet testDS = testdataFactory.createDistributionSet("one");
|
||||||
distributionSetManagement.createMetaData(testDS.getId(),
|
distributionSetManagement.createMetaData(testDS.getId(),
|
||||||
Arrays.asList(entityFactory.generateMetadata(knownKey, knownValue)));
|
Arrays.asList(entityFactory.generateDsMetadata(knownKey, knownValue)));
|
||||||
|
|
||||||
mockMvc.perform(get(
|
mockMvc.perform(get(
|
||||||
MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/metadata/{metadatakey}",
|
MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/metadata/{metadatakey}",
|
||||||
@@ -588,7 +588,7 @@ public class DistributionSetsDocumentationTest extends AbstractApiRestDocumentat
|
|||||||
|
|
||||||
final DistributionSet testDS = testdataFactory.createDistributionSet("one");
|
final DistributionSet testDS = testdataFactory.createDistributionSet("one");
|
||||||
distributionSetManagement.createMetaData(testDS.getId(),
|
distributionSetManagement.createMetaData(testDS.getId(),
|
||||||
Arrays.asList(entityFactory.generateMetadata(knownKey, knownValue)));
|
Arrays.asList(entityFactory.generateDsMetadata(knownKey, knownValue)));
|
||||||
|
|
||||||
final JSONObject jsonObject = new JSONObject().put("key", knownKey).put("value", updateValue);
|
final JSONObject jsonObject = new JSONObject().put("key", knownKey).put("value", updateValue);
|
||||||
|
|
||||||
@@ -616,7 +616,7 @@ public class DistributionSetsDocumentationTest extends AbstractApiRestDocumentat
|
|||||||
|
|
||||||
final DistributionSet testDS = testdataFactory.createDistributionSet("one");
|
final DistributionSet testDS = testdataFactory.createDistributionSet("one");
|
||||||
distributionSetManagement.createMetaData(testDS.getId(),
|
distributionSetManagement.createMetaData(testDS.getId(),
|
||||||
Arrays.asList(entityFactory.generateMetadata(knownKey, knownValue)));
|
Arrays.asList(entityFactory.generateDsMetadata(knownKey, knownValue)));
|
||||||
|
|
||||||
mockMvc.perform(
|
mockMvc.perform(
|
||||||
delete(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/metadata/{key}",
|
delete(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/metadata/{key}",
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import static org.springframework.restdocs.request.RequestDocumentation.paramete
|
|||||||
import static org.springframework.restdocs.request.RequestDocumentation.pathParameters;
|
import static org.springframework.restdocs.request.RequestDocumentation.pathParameters;
|
||||||
import static org.springframework.restdocs.request.RequestDocumentation.requestParameters;
|
import static org.springframework.restdocs.request.RequestDocumentation.requestParameters;
|
||||||
import static org.springframework.restdocs.snippet.Attributes.key;
|
import static org.springframework.restdocs.snippet.Attributes.key;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
@@ -28,6 +29,7 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.im.authentication.SpPermission;
|
||||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
||||||
import org.eclipse.hawkbit.repository.ActionStatusFields;
|
import org.eclipse.hawkbit.repository.ActionStatusFields;
|
||||||
import org.eclipse.hawkbit.repository.model.Action;
|
import org.eclipse.hawkbit.repository.model.Action;
|
||||||
@@ -38,6 +40,7 @@ import org.eclipse.hawkbit.rest.documentation.AbstractApiRestDocumentation;
|
|||||||
import org.eclipse.hawkbit.rest.documentation.ApiModelPropertiesGeneric;
|
import org.eclipse.hawkbit.rest.documentation.ApiModelPropertiesGeneric;
|
||||||
import org.eclipse.hawkbit.rest.documentation.MgmtApiModelProperties;
|
import org.eclipse.hawkbit.rest.documentation.MgmtApiModelProperties;
|
||||||
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
|
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
|
||||||
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -47,6 +50,7 @@ import org.springframework.http.MediaType;
|
|||||||
import org.springframework.restdocs.payload.JsonFieldType;
|
import org.springframework.restdocs.payload.JsonFieldType;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import io.qameta.allure.Description;
|
import io.qameta.allure.Description;
|
||||||
import io.qameta.allure.Feature;
|
import io.qameta.allure.Feature;
|
||||||
@@ -60,7 +64,7 @@ import io.qameta.allure.Story;
|
|||||||
@Story("Target Resource")
|
@Story("Target Resource")
|
||||||
public class TargetResourceDocumentationTest extends AbstractApiRestDocumentation {
|
public class TargetResourceDocumentationTest extends AbstractApiRestDocumentation {
|
||||||
|
|
||||||
private final String controllerId = "137";
|
private final String targetId = "137";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Before
|
@Before
|
||||||
@@ -72,7 +76,7 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
|
|||||||
@Test
|
@Test
|
||||||
@Description("Handles the GET request of retrieving all targets within SP. Required Permission: READ_TARGET.")
|
@Description("Handles the GET request of retrieving all targets within SP. Required Permission: READ_TARGET.")
|
||||||
public void getTargets() throws Exception {
|
public void getTargets() throws Exception {
|
||||||
createTargetByGivenNameWithAttributes(controllerId, createDistributionSet());
|
createTargetByGivenNameWithAttributes(targetId, createDistributionSet());
|
||||||
|
|
||||||
mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING)).andExpect(status().isOk())
|
mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING)).andExpect(status().isOk())
|
||||||
.andDo(MockMvcResultPrinter.print())
|
.andDo(MockMvcResultPrinter.print())
|
||||||
@@ -90,7 +94,8 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
|
|||||||
.type("enum").attributes(
|
.type("enum").attributes(
|
||||||
key("value").value("['error', 'in_sync', 'pending', 'registered', 'unknown']")),
|
key("value").value("['error', 'in_sync', 'pending', 'registered', 'unknown']")),
|
||||||
fieldWithPath("content[].securityToken").description(MgmtApiModelProperties.SECURITY_TOKEN),
|
fieldWithPath("content[].securityToken").description(MgmtApiModelProperties.SECURITY_TOKEN),
|
||||||
fieldWithPath("content[].requestAttributes").description(MgmtApiModelProperties.REQUEST_ATTRIBUTES),
|
fieldWithPath("content[].requestAttributes")
|
||||||
|
.description(MgmtApiModelProperties.REQUEST_ATTRIBUTES),
|
||||||
fieldWithPath("content[].installedAt").description(MgmtApiModelProperties.INSTALLED_AT),
|
fieldWithPath("content[].installedAt").description(MgmtApiModelProperties.INSTALLED_AT),
|
||||||
fieldWithPath("content[].lastModifiedAt")
|
fieldWithPath("content[].lastModifiedAt")
|
||||||
.description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT).type("Number"),
|
.description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT).type("Number"),
|
||||||
@@ -142,67 +147,71 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
|
|||||||
.attributes(key("value")
|
.attributes(key("value")
|
||||||
.value("['error', 'in_sync', 'pending', 'registered', 'unknown']")),
|
.value("['error', 'in_sync', 'pending', 'registered', 'unknown']")),
|
||||||
fieldWithPath("[]securityToken").description(MgmtApiModelProperties.SECURITY_TOKEN),
|
fieldWithPath("[]securityToken").description(MgmtApiModelProperties.SECURITY_TOKEN),
|
||||||
fieldWithPath("[]requestAttributes").description(MgmtApiModelProperties.REQUEST_ATTRIBUTES),
|
fieldWithPath("[]requestAttributes")
|
||||||
|
.description(MgmtApiModelProperties.REQUEST_ATTRIBUTES),
|
||||||
fieldWithPath("[]_links.self").ignored())));
|
fieldWithPath("[]_links.self").ignored())));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Handles the DELETE request of deleting a single target within SP. Required Permission: DELETE_TARGET.")
|
@Description("Handles the DELETE request of deleting a single target within SP. Required Permission: DELETE_TARGET.")
|
||||||
public void deleteTarget() throws Exception {
|
public void deleteTarget() throws Exception {
|
||||||
final Target target = testdataFactory.createTarget(controllerId);
|
final Target target = testdataFactory.createTarget(targetId);
|
||||||
|
|
||||||
mockMvc.perform(
|
mockMvc.perform(
|
||||||
delete(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{controllerId}", target.getControllerId()))
|
delete(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}", target.getControllerId()))
|
||||||
.andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()).andDo(this.document.document(
|
.andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()).andDo(this.document.document(
|
||||||
pathParameters(parameterWithName("controllerId").description(ApiModelPropertiesGeneric.NAME))));
|
pathParameters(parameterWithName("targetId").description(ApiModelPropertiesGeneric.ITEM_ID))));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Handles the GET request of retrieving a single target within SP. Required Permission: READ_TARGET.")
|
@Description("Handles the GET request of retrieving a single target within SP. Required Permission: READ_TARGET.")
|
||||||
public void getTarget() throws Exception {
|
public void getTarget() throws Exception {
|
||||||
final Target target = createTargetByGivenNameWithAttributes(controllerId, createDistributionSet());
|
final Target target = createTargetByGivenNameWithAttributes(targetId, createDistributionSet());
|
||||||
|
|
||||||
mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{controllerId}", target.getControllerId()))
|
mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}", target.getControllerId()))
|
||||||
.andExpect(status().isOk()).andDo(MockMvcResultPrinter.print())
|
.andExpect(status().isOk()).andDo(MockMvcResultPrinter.print())
|
||||||
.andDo(this.document.document(
|
.andDo(this.document.document(
|
||||||
pathParameters(
|
pathParameters(
|
||||||
parameterWithName("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID)),
|
parameterWithName("targetId").description(ApiModelPropertiesGeneric.ITEM_ID)),
|
||||||
getResponseFieldTarget(false)));
|
getResponseFieldTarget(false)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Handles the PUT request of updating a target within SP. Required Permission: UPDATE_TARGET.")
|
@Description("Handles the PUT request of updating a target within SP. Required Permission: UPDATE_TARGET.")
|
||||||
public void putTarget() throws Exception {
|
public void putTarget() throws Exception {
|
||||||
final Target target = createTargetByGivenNameWithAttributes(controllerId, createDistributionSet());
|
final Target target = createTargetByGivenNameWithAttributes(targetId, createDistributionSet());
|
||||||
final String targetAsJson = createJsonTarget(controllerId, "newTargetName", "I've been updated");
|
final String targetAsJson = createJsonTarget(targetId, "newTargetName", "I've been updated");
|
||||||
|
|
||||||
mockMvc.perform(put(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{controllerId}", target.getControllerId())
|
mockMvc.perform(put(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}", target.getControllerId())
|
||||||
.contentType(MediaType.APPLICATION_JSON_UTF8).content(targetAsJson)).andExpect(status().isOk())
|
.contentType(MediaType.APPLICATION_JSON_UTF8).content(targetAsJson)).andExpect(status().isOk())
|
||||||
.andDo(MockMvcResultPrinter.print())
|
.andDo(MockMvcResultPrinter.print())
|
||||||
.andDo(this.document.document(
|
.andDo(this.document.document(
|
||||||
pathParameters(
|
pathParameters(
|
||||||
parameterWithName("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID)),
|
parameterWithName("targetId").description(ApiModelPropertiesGeneric.ITEM_ID)),
|
||||||
requestFields(optionalRequestFieldWithPath("name").description(ApiModelPropertiesGeneric.NAME),
|
requestFields(optionalRequestFieldWithPath("name").description(ApiModelPropertiesGeneric.NAME),
|
||||||
optionalRequestFieldWithPath("description").description(ApiModelPropertiesGeneric.DESCRPTION),
|
optionalRequestFieldWithPath("description")
|
||||||
optionalRequestFieldWithPath("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID),
|
.description(ApiModelPropertiesGeneric.DESCRPTION),
|
||||||
|
optionalRequestFieldWithPath("controllerId")
|
||||||
|
.description(ApiModelPropertiesGeneric.ITEM_ID),
|
||||||
optionalRequestFieldWithPath("address").description(MgmtApiModelProperties.ADDRESS),
|
optionalRequestFieldWithPath("address").description(MgmtApiModelProperties.ADDRESS),
|
||||||
optionalRequestFieldWithPath("securityToken")
|
optionalRequestFieldWithPath("securityToken")
|
||||||
.description(MgmtApiModelProperties.SECURITY_TOKEN),
|
.description(MgmtApiModelProperties.SECURITY_TOKEN),
|
||||||
optionalRequestFieldWithPath("requestAttributes").description(MgmtApiModelProperties.REQUEST_ATTRIBUTES)),
|
optionalRequestFieldWithPath("requestAttributes")
|
||||||
|
.description(MgmtApiModelProperties.REQUEST_ATTRIBUTES)),
|
||||||
getResponseFieldTarget(false)));
|
getResponseFieldTarget(false)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Handles the GET request of retrieving the full action history of a specific target. Required Permission: READ_TARGET.")
|
@Description("Handles the GET request of retrieving the full action history of a specific target. Required Permission: READ_TARGET.")
|
||||||
public void getActionsFromTarget() throws Exception {
|
public void getActionsFromTarget() throws Exception {
|
||||||
generateActionForTarget(controllerId);
|
generateActionForTarget(targetId);
|
||||||
|
|
||||||
mockMvc.perform(get(
|
mockMvc.perform(get(
|
||||||
MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{controllerId}/" + MgmtRestConstants.TARGET_V1_ACTIONS,
|
MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/" + MgmtRestConstants.TARGET_V1_ACTIONS,
|
||||||
controllerId)).andExpect(status().isOk()).andDo(MockMvcResultPrinter.print())
|
targetId)).andExpect(status().isOk()).andDo(MockMvcResultPrinter.print())
|
||||||
.andDo(this.document.document(
|
.andDo(this.document.document(
|
||||||
pathParameters(
|
pathParameters(
|
||||||
parameterWithName("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID)),
|
parameterWithName("targetId").description(ApiModelPropertiesGeneric.ITEM_ID)),
|
||||||
responseFields(
|
responseFields(
|
||||||
fieldWithPath("size").type(JsonFieldType.NUMBER)
|
fieldWithPath("size").type(JsonFieldType.NUMBER)
|
||||||
.description(ApiModelPropertiesGeneric.SIZE),
|
.description(ApiModelPropertiesGeneric.SIZE),
|
||||||
@@ -227,14 +236,14 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
|
|||||||
@Test
|
@Test
|
||||||
@Description("Handles the GET request of retrieving the full action history of a specific target with maintenance window. Required Permission: READ_TARGET.")
|
@Description("Handles the GET request of retrieving the full action history of a specific target with maintenance window. Required Permission: READ_TARGET.")
|
||||||
public void getActionsFromTargetWithMaintenanceWindow() throws Exception {
|
public void getActionsFromTargetWithMaintenanceWindow() throws Exception {
|
||||||
generateActionForTarget(controllerId, true, false, getTestSchedule(2), getTestDuration(1), getTestTimeZone());
|
generateActionForTarget(targetId, true, false, getTestSchedule(2), getTestDuration(1), getTestTimeZone());
|
||||||
|
|
||||||
mockMvc.perform(get(
|
mockMvc.perform(get(
|
||||||
MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{controllerId}/" + MgmtRestConstants.TARGET_V1_ACTIONS,
|
MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/" + MgmtRestConstants.TARGET_V1_ACTIONS,
|
||||||
controllerId)).andExpect(status().isOk()).andDo(MockMvcResultPrinter.print())
|
targetId)).andExpect(status().isOk()).andDo(MockMvcResultPrinter.print())
|
||||||
.andDo(this.document.document(
|
.andDo(this.document.document(
|
||||||
pathParameters(
|
pathParameters(
|
||||||
parameterWithName("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID)),
|
parameterWithName("targetId").description(ApiModelPropertiesGeneric.ITEM_ID)),
|
||||||
responseFields(
|
responseFields(
|
||||||
fieldWithPath("size").type(JsonFieldType.NUMBER)
|
fieldWithPath("size").type(JsonFieldType.NUMBER)
|
||||||
.description(ApiModelPropertiesGeneric.SIZE),
|
.description(ApiModelPropertiesGeneric.SIZE),
|
||||||
@@ -269,9 +278,9 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
|
|||||||
@Test
|
@Test
|
||||||
@Description("Handles the GET request of retrieving all targets within SP based by parameter. Required Permission: READ_TARGET.")
|
@Description("Handles the GET request of retrieving all targets within SP based by parameter. Required Permission: READ_TARGET.")
|
||||||
public void getActionsFromTargetWithParameters() throws Exception {
|
public void getActionsFromTargetWithParameters() throws Exception {
|
||||||
generateActionForTarget(controllerId);
|
generateActionForTarget(targetId);
|
||||||
|
|
||||||
mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + controllerId + "/"
|
mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + targetId + "/"
|
||||||
+ MgmtRestConstants.TARGET_V1_ACTIONS + "?limit=10&sort=id:ASC&offset=0&q=status==pending"))
|
+ MgmtRestConstants.TARGET_V1_ACTIONS + "?limit=10&sort=id:ASC&offset=0&q=status==pending"))
|
||||||
.andExpect(status().isOk()).andDo(MockMvcResultPrinter.print())
|
.andExpect(status().isOk()).andDo(MockMvcResultPrinter.print())
|
||||||
.andDo(this.document.document(requestParameters(
|
.andDo(this.document.document(requestParameters(
|
||||||
@@ -285,22 +294,22 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
|
|||||||
@Test
|
@Test
|
||||||
@Description("Cancels an active action, only active actions can be deleted. Required Permission: UPDATE_TARGET.")
|
@Description("Cancels an active action, only active actions can be deleted. Required Permission: UPDATE_TARGET.")
|
||||||
public void deleteActionFromTarget() throws Exception {
|
public void deleteActionFromTarget() throws Exception {
|
||||||
final Action actions = generateActionForTarget(controllerId, false);
|
final Action actions = generateActionForTarget(targetId, false);
|
||||||
|
|
||||||
mockMvc.perform(delete(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{controllerId}/"
|
mockMvc.perform(delete(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/"
|
||||||
+ MgmtRestConstants.TARGET_V1_ACTIONS + "/{actionId}", controllerId, actions.getId()))
|
+ MgmtRestConstants.TARGET_V1_ACTIONS + "/{actionId}", targetId, actions.getId()))
|
||||||
.andExpect(status().isNoContent()).andDo(MockMvcResultPrinter.print())
|
.andExpect(status().isNoContent()).andDo(MockMvcResultPrinter.print())
|
||||||
.andDo(this.document.document(
|
.andDo(this.document.document(
|
||||||
pathParameters(parameterWithName("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID),
|
pathParameters(parameterWithName("targetId").description(ApiModelPropertiesGeneric.ITEM_ID),
|
||||||
parameterWithName("actionId").description(ApiModelPropertiesGeneric.ITEM_ID))));
|
parameterWithName("actionId").description(ApiModelPropertiesGeneric.ITEM_ID))));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Handles the GET request of retrieving all targets within SP based by parameter. Required Permission: READ_TARGET.")
|
@Description("Handles the GET request of retrieving all targets within SP based by parameter. Required Permission: READ_TARGET.")
|
||||||
public void deleteActionsFromTargetWithParameters() throws Exception {
|
public void deleteActionsFromTargetWithParameters() throws Exception {
|
||||||
generateActionForTarget(controllerId);
|
generateActionForTarget(targetId);
|
||||||
|
|
||||||
mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + controllerId + "/"
|
mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + targetId + "/"
|
||||||
+ MgmtRestConstants.TARGET_V1_ACTIONS + "?force=true")).andExpect(status().isOk())
|
+ MgmtRestConstants.TARGET_V1_ACTIONS + "?force=true")).andExpect(status().isOk())
|
||||||
.andDo(MockMvcResultPrinter.print()).andDo(this.document.document(
|
.andDo(MockMvcResultPrinter.print()).andDo(this.document.document(
|
||||||
requestParameters(parameterWithName("force").description(MgmtApiModelProperties.FORCE))));
|
requestParameters(parameterWithName("force").description(MgmtApiModelProperties.FORCE))));
|
||||||
@@ -309,15 +318,15 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
|
|||||||
@Test
|
@Test
|
||||||
@Description("Handles the GET request of retrieving a specific action on a specific target. Required Permission: READ_TARGET.")
|
@Description("Handles the GET request of retrieving a specific action on a specific target. Required Permission: READ_TARGET.")
|
||||||
public void getActionFromTarget() throws Exception {
|
public void getActionFromTarget() throws Exception {
|
||||||
final Action action = generateActionForTarget(controllerId, true, true);
|
final Action action = generateActionForTarget(targetId, true, true);
|
||||||
assertThat(deploymentManagement.findAction(action.getId()).get().getActionType())
|
assertThat(deploymentManagement.findAction(action.getId()).get().getActionType())
|
||||||
.isEqualTo(ActionType.TIMEFORCED);
|
.isEqualTo(ActionType.TIMEFORCED);
|
||||||
|
|
||||||
mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{controllerId}/"
|
mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/"
|
||||||
+ MgmtRestConstants.TARGET_V1_ACTIONS + "/{actionId}", controllerId, action.getId()))
|
+ MgmtRestConstants.TARGET_V1_ACTIONS + "/{actionId}", targetId, action.getId()))
|
||||||
.andExpect(status().isOk()).andDo(MockMvcResultPrinter.print())
|
.andExpect(status().isOk()).andDo(MockMvcResultPrinter.print())
|
||||||
.andDo(this.document.document(
|
.andDo(this.document.document(
|
||||||
pathParameters(parameterWithName("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID),
|
pathParameters(parameterWithName("targetId").description(ApiModelPropertiesGeneric.ITEM_ID),
|
||||||
parameterWithName("actionId").description(ApiModelPropertiesGeneric.ITEM_ID)),
|
parameterWithName("actionId").description(ApiModelPropertiesGeneric.ITEM_ID)),
|
||||||
responseFields(fieldWithPath("createdBy").description(ApiModelPropertiesGeneric.CREATED_BY),
|
responseFields(fieldWithPath("createdBy").description(ApiModelPropertiesGeneric.CREATED_BY),
|
||||||
fieldWithPath("createdAt").description(ApiModelPropertiesGeneric.CREATED_AT),
|
fieldWithPath("createdAt").description(ApiModelPropertiesGeneric.CREATED_AT),
|
||||||
@@ -343,14 +352,14 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
|
|||||||
@Test
|
@Test
|
||||||
@Description("Handles the GET request of retrieving a specific action on a specific target. Required Permission: READ_TARGET.")
|
@Description("Handles the GET request of retrieving a specific action on a specific target. Required Permission: READ_TARGET.")
|
||||||
public void getActionFromTargetWithMaintenanceWindow() throws Exception {
|
public void getActionFromTargetWithMaintenanceWindow() throws Exception {
|
||||||
final Action action = generateActionForTarget(controllerId, true, true, getTestSchedule(2), getTestDuration(1),
|
final Action action = generateActionForTarget(targetId, true, true, getTestSchedule(2), getTestDuration(1),
|
||||||
getTestTimeZone());
|
getTestTimeZone());
|
||||||
|
|
||||||
mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{controllerId}/"
|
mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/"
|
||||||
+ MgmtRestConstants.TARGET_V1_ACTIONS + "/{actionId}", controllerId, action.getId()))
|
+ MgmtRestConstants.TARGET_V1_ACTIONS + "/{actionId}", targetId, action.getId()))
|
||||||
.andExpect(status().isOk()).andDo(MockMvcResultPrinter.print())
|
.andExpect(status().isOk()).andDo(MockMvcResultPrinter.print())
|
||||||
.andDo(this.document.document(
|
.andDo(this.document.document(
|
||||||
pathParameters(parameterWithName("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID),
|
pathParameters(parameterWithName("targetId").description(ApiModelPropertiesGeneric.ITEM_ID),
|
||||||
parameterWithName("actionId").description(ApiModelPropertiesGeneric.ITEM_ID)),
|
parameterWithName("actionId").description(ApiModelPropertiesGeneric.ITEM_ID)),
|
||||||
responseFields(fieldWithPath("createdBy").description(ApiModelPropertiesGeneric.CREATED_BY),
|
responseFields(fieldWithPath("createdBy").description(ApiModelPropertiesGeneric.CREATED_BY),
|
||||||
fieldWithPath("createdAt").description(ApiModelPropertiesGeneric.CREATED_AT),
|
fieldWithPath("createdAt").description(ApiModelPropertiesGeneric.CREATED_AT),
|
||||||
@@ -386,7 +395,7 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
|
|||||||
@Test
|
@Test
|
||||||
@Description("Handles the PUT request to switch an action from soft to forced. Required Permission: UPDATE_TARGET.")
|
@Description("Handles the PUT request to switch an action from soft to forced. Required Permission: UPDATE_TARGET.")
|
||||||
public void switchActionToForced() throws Exception {
|
public void switchActionToForced() throws Exception {
|
||||||
final Target target = testdataFactory.createTarget(controllerId);
|
final Target target = testdataFactory.createTarget(targetId);
|
||||||
final DistributionSet set = testdataFactory.createDistributionSet();
|
final DistributionSet set = testdataFactory.createDistributionSet();
|
||||||
final Long actionId = deploymentManagement
|
final Long actionId = deploymentManagement
|
||||||
.assignDistributionSet(set.getId(), ActionType.SOFT, 0, Arrays.asList(target.getControllerId()))
|
.assignDistributionSet(set.getId(), ActionType.SOFT, 0, Arrays.asList(target.getControllerId()))
|
||||||
@@ -396,13 +405,13 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
|
|||||||
final Map<String, Object> body = new HashMap<>();
|
final Map<String, Object> body = new HashMap<>();
|
||||||
body.put("forceType", "forced");
|
body.put("forceType", "forced");
|
||||||
|
|
||||||
mockMvc.perform(put(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{controllerId}/"
|
mockMvc.perform(put(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/"
|
||||||
+ MgmtRestConstants.TARGET_V1_ACTIONS + "/{actionId}", controllerId, actionId)
|
+ MgmtRestConstants.TARGET_V1_ACTIONS + "/{actionId}", targetId, actionId)
|
||||||
.content(this.objectMapper.writeValueAsString(body))
|
.content(this.objectMapper.writeValueAsString(body))
|
||||||
.contentType(MediaType.APPLICATION_JSON_UTF8))
|
.contentType(MediaType.APPLICATION_JSON_UTF8))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andDo(this.document.document(
|
.andDo(this.document.document(
|
||||||
pathParameters(parameterWithName("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID),
|
pathParameters(parameterWithName("targetId").description(ApiModelPropertiesGeneric.ITEM_ID),
|
||||||
parameterWithName("actionId").description(ApiModelPropertiesGeneric.ITEM_ID)),
|
parameterWithName("actionId").description(ApiModelPropertiesGeneric.ITEM_ID)),
|
||||||
requestFields(
|
requestFields(
|
||||||
requestFieldWithPath("forceType").description(MgmtApiModelProperties.ACTION_FORCED)),
|
requestFieldWithPath("forceType").description(MgmtApiModelProperties.ACTION_FORCED)),
|
||||||
@@ -428,13 +437,13 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
|
|||||||
@Test
|
@Test
|
||||||
@Description("Handles the GET request of retrieving a specific action on a specific target. Required Permission: READ_TARGET.")
|
@Description("Handles the GET request of retrieving a specific action on a specific target. Required Permission: READ_TARGET.")
|
||||||
public void getStatusFromAction() throws Exception {
|
public void getStatusFromAction() throws Exception {
|
||||||
final Action action = generateActionForTarget(controllerId);
|
final Action action = generateActionForTarget(targetId);
|
||||||
|
|
||||||
mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{controllerId}/"
|
mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/"
|
||||||
+ MgmtRestConstants.TARGET_V1_ACTIONS + "/{actionId}/" + MgmtRestConstants.TARGET_V1_ACTION_STATUS,
|
+ MgmtRestConstants.TARGET_V1_ACTIONS + "/{actionId}/" + MgmtRestConstants.TARGET_V1_ACTION_STATUS,
|
||||||
controllerId, action.getId())).andExpect(status().isOk()).andDo(MockMvcResultPrinter.print())
|
targetId, action.getId())).andExpect(status().isOk()).andDo(MockMvcResultPrinter.print())
|
||||||
.andDo(this.document.document(
|
.andDo(this.document.document(
|
||||||
pathParameters(parameterWithName("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID),
|
pathParameters(parameterWithName("targetId").description(ApiModelPropertiesGeneric.ITEM_ID),
|
||||||
parameterWithName("actionId").description(ApiModelPropertiesGeneric.ITEM_ID)),
|
parameterWithName("actionId").description(ApiModelPropertiesGeneric.ITEM_ID)),
|
||||||
responseFields(
|
responseFields(
|
||||||
fieldWithPath("size").type(JsonFieldType.NUMBER)
|
fieldWithPath("size").type(JsonFieldType.NUMBER)
|
||||||
@@ -454,9 +463,9 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
|
|||||||
@Test
|
@Test
|
||||||
@Description("Handles the GET request of retrieving all targets within SP based by parameter. Required Permission: READ_TARGET.")
|
@Description("Handles the GET request of retrieving all targets within SP based by parameter. Required Permission: READ_TARGET.")
|
||||||
public void getStatusFromActionWithParameters() throws Exception {
|
public void getStatusFromActionWithParameters() throws Exception {
|
||||||
final Action action = generateActionForTarget(controllerId);
|
final Action action = generateActionForTarget(targetId);
|
||||||
|
|
||||||
mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + controllerId + "/"
|
mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + targetId + "/"
|
||||||
+ MgmtRestConstants.TARGET_V1_ACTIONS + "/" + action.getId() + "/"
|
+ MgmtRestConstants.TARGET_V1_ACTIONS + "/" + action.getId() + "/"
|
||||||
+ MgmtRestConstants.TARGET_V1_ACTION_STATUS + "?limit=10&sort=id:ASC&offset=0"))
|
+ MgmtRestConstants.TARGET_V1_ACTION_STATUS + "?limit=10&sort=id:ASC&offset=0"))
|
||||||
.andExpect(status().isOk()).andDo(MockMvcResultPrinter.print())
|
.andExpect(status().isOk()).andDo(MockMvcResultPrinter.print())
|
||||||
@@ -469,21 +478,21 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
|
|||||||
@Test
|
@Test
|
||||||
@Description("Handles the GET request of retrieving the assigned distribution set of an specific target. Required Permission: READ_TARGET.")
|
@Description("Handles the GET request of retrieving the assigned distribution set of an specific target. Required Permission: READ_TARGET.")
|
||||||
public void getAssignedDistributionSetFromAction() throws Exception {
|
public void getAssignedDistributionSetFromAction() throws Exception {
|
||||||
generateActionForTarget(controllerId);
|
generateActionForTarget(targetId);
|
||||||
|
|
||||||
mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{controllerId}/"
|
mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/"
|
||||||
+ MgmtRestConstants.TARGET_V1_ASSIGNED_DISTRIBUTION_SET, controllerId)).andExpect(status().isOk())
|
+ MgmtRestConstants.TARGET_V1_ASSIGNED_DISTRIBUTION_SET, targetId)).andExpect(status().isOk())
|
||||||
.andDo(MockMvcResultPrinter.print())
|
.andDo(MockMvcResultPrinter.print())
|
||||||
.andDo(this.document.document(
|
.andDo(this.document.document(
|
||||||
pathParameters(
|
pathParameters(
|
||||||
parameterWithName("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID)),
|
parameterWithName("targetId").description(ApiModelPropertiesGeneric.ITEM_ID)),
|
||||||
getResponseFieldsDistributionSet(false)));
|
getResponseFieldsDistributionSet(false)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Handles the POST request for assigning a distribution set to a specific target. Required Permission: READ_REPOSITORY and UPDATE_TARGET.")
|
@Description("Handles the POST request for assigning a distribution set to a specific target. Required Permission: READ_REPOSITORY and UPDATE_TARGET.")
|
||||||
public void postAssignDistributionSetToTarget() throws Exception {
|
public void postAssignDistributionSetToTarget() throws Exception {
|
||||||
testdataFactory.createTarget(controllerId);
|
testdataFactory.createTarget(targetId);
|
||||||
final DistributionSet set = testdataFactory.createDistributionSet("one");
|
final DistributionSet set = testdataFactory.createDistributionSet("one");
|
||||||
|
|
||||||
final long forceTime = System.currentTimeMillis();
|
final long forceTime = System.currentTimeMillis();
|
||||||
@@ -492,13 +501,13 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
|
|||||||
getMaintenanceWindow(getTestSchedule(10), getTestDuration(10), getTestTimeZone()))
|
getMaintenanceWindow(getTestSchedule(10), getTestDuration(10), getTestTimeZone()))
|
||||||
.toString();
|
.toString();
|
||||||
|
|
||||||
mockMvc.perform(post(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{controllerId}/"
|
mockMvc.perform(post(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/"
|
||||||
+ MgmtRestConstants.TARGET_V1_ASSIGNED_DISTRIBUTION_SET, controllerId).content(body)
|
+ MgmtRestConstants.TARGET_V1_ASSIGNED_DISTRIBUTION_SET, targetId).content(body)
|
||||||
.contentType(MediaType.APPLICATION_JSON_UTF8))
|
.contentType(MediaType.APPLICATION_JSON_UTF8))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andDo(this.document.document(
|
.andDo(this.document.document(
|
||||||
pathParameters(
|
pathParameters(
|
||||||
parameterWithName("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID)),
|
parameterWithName("targetId").description(ApiModelPropertiesGeneric.ITEM_ID)),
|
||||||
requestParameters(parameterWithName("offline")
|
requestParameters(parameterWithName("offline")
|
||||||
.description(MgmtApiModelProperties.OFFLINE_UPDATE).optional()),
|
.description(MgmtApiModelProperties.OFFLINE_UPDATE).optional()),
|
||||||
requestFields(requestFieldWithPath("forcetime").description(MgmtApiModelProperties.FORCETIME),
|
requestFields(requestFieldWithPath("forcetime").description(MgmtApiModelProperties.FORCETIME),
|
||||||
@@ -528,32 +537,193 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
|
|||||||
final Map<String, String> knownControllerAttrs = new HashMap<>();
|
final Map<String, String> knownControllerAttrs = new HashMap<>();
|
||||||
knownControllerAttrs.put("a", "1");
|
knownControllerAttrs.put("a", "1");
|
||||||
knownControllerAttrs.put("b", "2");
|
knownControllerAttrs.put("b", "2");
|
||||||
final Target target = testdataFactory.createTarget(controllerId);
|
final Target target = testdataFactory.createTarget(targetId);
|
||||||
controllerManagement.updateControllerAttributes(controllerId, knownControllerAttrs, null);
|
controllerManagement.updateControllerAttributes(targetId, knownControllerAttrs, null);
|
||||||
|
|
||||||
// test query target over rest resource
|
// test query target over rest resource
|
||||||
mockMvc.perform(
|
mockMvc.perform(
|
||||||
get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{controllerId}/attributes", target.getName()))
|
get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/attributes", target.getName()))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().is2xxSuccessful())
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().is2xxSuccessful())
|
||||||
.andExpect(jsonPath("$.a", equalTo("1"))).andExpect(jsonPath("$.b", equalTo("2")))
|
.andExpect(jsonPath("$.a", equalTo("1"))).andExpect(jsonPath("$.b", equalTo("2")))
|
||||||
.andDo(this.document.document(pathParameters(
|
.andDo(this.document.document(pathParameters(
|
||||||
parameterWithName("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID))));
|
parameterWithName("targetId").description(ApiModelPropertiesGeneric.ITEM_ID))));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Handles the GET request of retrieving the installed distribution set of an specific target. Required Permission: READ_TARGET.")
|
@Description("Handles the GET request of retrieving the installed distribution set of an specific target. Required Permission: READ_TARGET.")
|
||||||
public void getInstalledDistributionSetFromTarget() throws Exception {
|
public void getInstalledDistributionSetFromTarget() throws Exception {
|
||||||
final Target target = createTargetByGivenNameWithAttributes(controllerId, createDistributionSet());
|
final Target target = createTargetByGivenNameWithAttributes(targetId, createDistributionSet());
|
||||||
|
|
||||||
mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{controllerId}/"
|
mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/"
|
||||||
+ MgmtRestConstants.TARGET_V1_INSTALLED_DISTRIBUTION_SET, target.getName())).andExpect(status().isOk())
|
+ MgmtRestConstants.TARGET_V1_INSTALLED_DISTRIBUTION_SET, target.getName())).andExpect(status().isOk())
|
||||||
.andDo(MockMvcResultPrinter.print())
|
.andDo(MockMvcResultPrinter.print())
|
||||||
.andDo(this.document.document(
|
.andDo(this.document.document(
|
||||||
pathParameters(
|
pathParameters(
|
||||||
parameterWithName("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID)),
|
parameterWithName("targetId").description(ApiModelPropertiesGeneric.ITEM_ID)),
|
||||||
getResponseFieldsDistributionSet(false)));
|
getResponseFieldsDistributionSet(false)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Get a paged list of meta data for a target with standard page size." + " Required Permission: "
|
||||||
|
+ SpPermission.READ_REPOSITORY)
|
||||||
|
public void getMetadata() throws Exception {
|
||||||
|
final int totalMetadata = 4;
|
||||||
|
final String knownKeyPrefix = "knownKey";
|
||||||
|
final String knownValuePrefix = "knownValue";
|
||||||
|
final Target testTarget = testdataFactory.createTarget(targetId);
|
||||||
|
for (int index = 0; index < totalMetadata; index++) {
|
||||||
|
targetManagement.createMetaData(testTarget.getControllerId(), Lists.newArrayList(
|
||||||
|
entityFactory.generateTargetMetadata(knownKeyPrefix + index, knownValuePrefix + index)));
|
||||||
|
}
|
||||||
|
|
||||||
|
mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/metadata",
|
||||||
|
testTarget.getControllerId())).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
|
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF))
|
||||||
|
.andDo(this.document.document(
|
||||||
|
pathParameters(
|
||||||
|
parameterWithName("targetId").description(ApiModelPropertiesGeneric.ITEM_ID)),
|
||||||
|
responseFields(fieldWithPath("total").description(ApiModelPropertiesGeneric.TOTAL_ELEMENTS),
|
||||||
|
fieldWithPath("size").type(JsonFieldType.NUMBER)
|
||||||
|
.description(ApiModelPropertiesGeneric.SIZE),
|
||||||
|
fieldWithPath("content").description(MgmtApiModelProperties.META_DATA),
|
||||||
|
fieldWithPath("content[].key").description(MgmtApiModelProperties.META_DATA_KEY),
|
||||||
|
fieldWithPath("content[].value").description(MgmtApiModelProperties.META_DATA_VALUE))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Get a paged list of meta data for a target with defined page size and sorting by name descending and key starting with 'known'."
|
||||||
|
+ " Required Permission: " + SpPermission.READ_REPOSITORY)
|
||||||
|
public void getMetadataWithParameters() throws Exception {
|
||||||
|
final int totalMetadata = 4;
|
||||||
|
|
||||||
|
final String knownKeyPrefix = "knownKey";
|
||||||
|
final String knownValuePrefix = "knownValue";
|
||||||
|
final Target testTarget = testdataFactory.createTarget(targetId);
|
||||||
|
for (int index = 0; index < totalMetadata; index++) {
|
||||||
|
targetManagement.createMetaData(testTarget.getControllerId(), Lists.newArrayList(
|
||||||
|
entityFactory.generateTargetMetadata(knownKeyPrefix + index, knownValuePrefix + index)));
|
||||||
|
}
|
||||||
|
|
||||||
|
mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/metadata",
|
||||||
|
testTarget.getControllerId()).param("offset", "1").param("limit", "2").param("sort", "key:DESC")
|
||||||
|
.param("q", "key==known*"))
|
||||||
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
|
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF))
|
||||||
|
.andDo(this.document.document(
|
||||||
|
requestParameters(
|
||||||
|
parameterWithName("limit").attributes(key("type").value("query"))
|
||||||
|
.description(ApiModelPropertiesGeneric.LIMIT),
|
||||||
|
parameterWithName("sort").description(ApiModelPropertiesGeneric.SORT),
|
||||||
|
parameterWithName("offset").description(ApiModelPropertiesGeneric.OFFSET),
|
||||||
|
parameterWithName("q").description(ApiModelPropertiesGeneric.FIQL)),
|
||||||
|
responseFields(fieldWithPath("total").description(ApiModelPropertiesGeneric.TOTAL_ELEMENTS),
|
||||||
|
fieldWithPath("size").type(JsonFieldType.NUMBER)
|
||||||
|
.description(ApiModelPropertiesGeneric.SIZE),
|
||||||
|
fieldWithPath("content").description(MgmtApiModelProperties.META_DATA),
|
||||||
|
fieldWithPath("content[].key").description(MgmtApiModelProperties.META_DATA_KEY),
|
||||||
|
fieldWithPath("content[].value").description(MgmtApiModelProperties.META_DATA_VALUE))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Get a single meta data value for a meta data key." + " Required Permission: "
|
||||||
|
+ SpPermission.READ_REPOSITORY)
|
||||||
|
public void getMetadataValue() throws Exception {
|
||||||
|
|
||||||
|
// prepare and create metadata
|
||||||
|
final String knownKey = "knownKey";
|
||||||
|
final String knownValue = "knownValue";
|
||||||
|
final Target testTarget = testdataFactory.createTarget(targetId);
|
||||||
|
targetManagement.createMetaData(testTarget.getControllerId(),
|
||||||
|
Arrays.asList(entityFactory.generateTargetMetadata(knownKey, knownValue)));
|
||||||
|
|
||||||
|
mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/metadata/{metadatakey}",
|
||||||
|
testTarget.getControllerId(), knownKey)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
|
.andDo(this.document.document(
|
||||||
|
pathParameters(parameterWithName("targetId").description(ApiModelPropertiesGeneric.ITEM_ID),
|
||||||
|
parameterWithName("metadatakey").description(ApiModelPropertiesGeneric.ITEM_ID)),
|
||||||
|
responseFields(fieldWithPath("key").description(MgmtApiModelProperties.META_DATA_KEY),
|
||||||
|
fieldWithPath("value").description(MgmtApiModelProperties.META_DATA_VALUE))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Update a single meta data value for specific key." + " Required Permission: "
|
||||||
|
+ SpPermission.UPDATE_REPOSITORY)
|
||||||
|
public void updateMetadata() throws Exception {
|
||||||
|
// prepare and create metadata for update
|
||||||
|
final String knownKey = "knownKey";
|
||||||
|
final String knownValue = "knownValue";
|
||||||
|
final String updateValue = "valueForUpdate";
|
||||||
|
|
||||||
|
final Target testTarget = testdataFactory.createTarget(targetId);
|
||||||
|
targetManagement.createMetaData(testTarget.getControllerId(),
|
||||||
|
Arrays.asList(entityFactory.generateTargetMetadata(knownKey, knownValue)));
|
||||||
|
|
||||||
|
final JSONObject jsonObject = new JSONObject().put("key", knownKey).put("value", updateValue);
|
||||||
|
|
||||||
|
mockMvc.perform(put(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/metadata/{metadatakey}",
|
||||||
|
testTarget.getControllerId(), knownKey)
|
||||||
|
.contentType(MediaType.APPLICATION_JSON_UTF8).content(jsonObject.toString()))
|
||||||
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
|
.andDo(this.document.document(
|
||||||
|
pathParameters(parameterWithName("targetId").description(ApiModelPropertiesGeneric.ITEM_ID),
|
||||||
|
parameterWithName("metadatakey").description(ApiModelPropertiesGeneric.ITEM_ID)),
|
||||||
|
requestFields(requestFieldWithPath("key").description(MgmtApiModelProperties.META_DATA_KEY),
|
||||||
|
requestFieldWithPath("value").description(MgmtApiModelProperties.META_DATA_VALUE)),
|
||||||
|
responseFields(fieldWithPath("key").description(MgmtApiModelProperties.META_DATA_KEY),
|
||||||
|
fieldWithPath("value").description(MgmtApiModelProperties.META_DATA_VALUE))));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Delete a single meta data." + " Required Permission: " + SpPermission.UPDATE_REPOSITORY)
|
||||||
|
public void deleteMetadata() throws Exception {
|
||||||
|
// prepare and create metadata for deletion
|
||||||
|
final String knownKey = "knownKey";
|
||||||
|
final String knownValue = "knownValue";
|
||||||
|
|
||||||
|
final Target testTarget = testdataFactory.createTarget(targetId);
|
||||||
|
targetManagement.createMetaData(testTarget.getControllerId(),
|
||||||
|
Arrays.asList(entityFactory.generateTargetMetadata(knownKey, knownValue)));
|
||||||
|
|
||||||
|
mockMvc.perform(delete(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/metadata/{key}",
|
||||||
|
testTarget.getControllerId(), knownKey)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
|
.andDo(this.document.document(
|
||||||
|
pathParameters(parameterWithName("targetId").description(ApiModelPropertiesGeneric.ITEM_ID),
|
||||||
|
parameterWithName("key").description(ApiModelPropertiesGeneric.ITEM_ID))));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Create a list of meta data entries" + " Required Permission: " + SpPermission.READ_REPOSITORY
|
||||||
|
+ " and " + SpPermission.UPDATE_TARGET)
|
||||||
|
public void createMetadata() throws Exception {
|
||||||
|
|
||||||
|
final Target testTarget = testdataFactory.createTarget(targetId);
|
||||||
|
|
||||||
|
final String knownKey1 = "knownKey1";
|
||||||
|
final String knownKey2 = "knownKey2";
|
||||||
|
|
||||||
|
final String knownValue1 = "knownValue1";
|
||||||
|
final String knownValue2 = "knownValue2";
|
||||||
|
|
||||||
|
final JSONArray jsonArray = new JSONArray();
|
||||||
|
jsonArray.put(new JSONObject().put("key", knownKey1).put("value", knownValue1));
|
||||||
|
jsonArray.put(new JSONObject().put("key", knownKey2).put("value", knownValue2));
|
||||||
|
|
||||||
|
mockMvc.perform(
|
||||||
|
post(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/metadata",
|
||||||
|
testTarget.getControllerId()).contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||||
|
.content(jsonArray.toString()))
|
||||||
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated())
|
||||||
|
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF))
|
||||||
|
.andDo(this.document.document(
|
||||||
|
pathParameters(
|
||||||
|
parameterWithName("targetId").description(ApiModelPropertiesGeneric.ITEM_ID)),
|
||||||
|
requestFields(requestFieldWithPath("[]key").description(MgmtApiModelProperties.META_DATA_KEY),
|
||||||
|
optionalRequestFieldWithPath("[]value")
|
||||||
|
.description(MgmtApiModelProperties.META_DATA_VALUE))));
|
||||||
|
}
|
||||||
|
|
||||||
private String createTargetJsonForPostRequest(final String controllerId, final String name,
|
private String createTargetJsonForPostRequest(final String controllerId, final String name,
|
||||||
final String description) throws JsonProcessingException {
|
final String description) throws JsonProcessingException {
|
||||||
final Map<String, Object> target = new HashMap<>();
|
final Map<String, Object> target = new HashMap<>();
|
||||||
|
|||||||
@@ -124,6 +124,11 @@ public class HawkbitSecurityProperties {
|
|||||||
*/
|
*/
|
||||||
private int maxMetaDataEntriesPerDistributionSet = 100;
|
private int maxMetaDataEntriesPerDistributionSet = 100;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum number of meta data entries per target
|
||||||
|
*/
|
||||||
|
private int maxMetaDataEntriesPerTarget = 100;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maximum number of software modules per distribution set
|
* Maximum number of software modules per distribution set
|
||||||
*/
|
*/
|
||||||
@@ -230,6 +235,14 @@ public class HawkbitSecurityProperties {
|
|||||||
this.maxMetaDataEntriesPerDistributionSet = maxMetaDataEntriesPerDistributionSet;
|
this.maxMetaDataEntriesPerDistributionSet = maxMetaDataEntriesPerDistributionSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMaxMetaDataEntriesPerTarget() {
|
||||||
|
return maxMetaDataEntriesPerTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxMetaDataEntriesPerTarget(final int maxMetaDataEntriesPerTarget) {
|
||||||
|
this.maxMetaDataEntriesPerTarget = maxMetaDataEntriesPerTarget;
|
||||||
|
}
|
||||||
|
|
||||||
public int getMaxSoftwareModulesPerDistributionSet() {
|
public int getMaxSoftwareModulesPerDistributionSet() {
|
||||||
return maxSoftwareModulesPerDistributionSet;
|
return maxSoftwareModulesPerDistributionSet;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ public class DsMetadataPopupLayout extends AbstractMetadataPopupLayout<Distribut
|
|||||||
protected DistributionSetMetadata createMetadata(final DistributionSet entity, final String key,
|
protected DistributionSetMetadata createMetadata(final DistributionSet entity, final String key,
|
||||||
final String value) {
|
final String value) {
|
||||||
final DistributionSetMetadata dsMetaData = distributionSetManagement
|
final DistributionSetMetadata dsMetaData = distributionSetManagement
|
||||||
.createMetaData(entity.getId(), Arrays.asList(entityFactory.generateMetadata(key, value))).get(0);
|
.createMetaData(entity.getId(), Arrays.asList(entityFactory.generateDsMetadata(key, value))).get(0);
|
||||||
setSelectedEntity(dsMetaData.getDistributionSet());
|
setSelectedEntity(dsMetaData.getDistributionSet());
|
||||||
return dsMetaData;
|
return dsMetaData;
|
||||||
}
|
}
|
||||||
@@ -61,7 +61,7 @@ public class DsMetadataPopupLayout extends AbstractMetadataPopupLayout<Distribut
|
|||||||
protected DistributionSetMetadata updateMetadata(final DistributionSet entity, final String key,
|
protected DistributionSetMetadata updateMetadata(final DistributionSet entity, final String key,
|
||||||
final String value) {
|
final String value) {
|
||||||
final DistributionSetMetadata dsMetaData = distributionSetManagement.updateMetaData(entity.getId(),
|
final DistributionSetMetadata dsMetaData = distributionSetManagement.updateMetaData(entity.getId(),
|
||||||
entityFactory.generateMetadata(key, value));
|
entityFactory.generateDsMetadata(key, value));
|
||||||
setSelectedEntity(dsMetaData.getDistributionSet());
|
setSelectedEntity(dsMetaData.getDistributionSet());
|
||||||
return dsMetaData;
|
return dsMetaData;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user