Feature target type entity (#1162)

* Added Target Type model

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Added Target Type JPA model

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Added Target Type repository model classes

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Removed the name entity from Target Type

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Refactored the Target Type models

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Added the DB migration script and updated the Target Type models

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Added target type in target Mapper

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Changed the target type ID to Long

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Added MYSQL DB migration script and removed the deleted column for target type

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Updated the DB migration script for target table

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Added manyToMany reltation between target type and Ds type

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Added POSTGRESQL DB migration script

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Added MSSQL SERVER DB migration script

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Added DB2 DB migration script

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Added missing license header and java docs

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Added on delete cascade in DB migration script

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Added Target Type specification

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Removed the delete cascade and Added type API
Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* fixed API doc build

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Added target type management test

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Added target type events test

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Added target type update and unassign to target

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Added API tests for assigning target type to target

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Added missing license header

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Added missing docs

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Fixed sonar issues

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Fixed license header build issue

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Updated the attribute name to target type

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Fixed the review comments

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Removed unused error status variable

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Added target API to assign target type

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Added the tests for assigning target type to target

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Fixed the review comments for null check

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>
This commit is contained in:
Anand Kumar
2021-08-25 12:13:27 +02:00
committed by GitHub
parent 2574581b2c
commit 3fa1dd1be4
76 changed files with 4915 additions and 41 deletions

View File

@@ -67,7 +67,7 @@ final class MgmtDistributionSetTypeMapper {
.orElse(Collections.emptyList());
}
static List<MgmtDistributionSetType> toListResponse(final List<DistributionSetType> types) {
static List<MgmtDistributionSetType> toListResponse(final Collection<DistributionSetType> types) {
if (types == null) {
return Collections.emptyList();
}

View File

@@ -17,6 +17,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import org.eclipse.hawkbit.mgmt.json.model.MgmtMaintenanceWindow;
@@ -30,6 +31,7 @@ import org.eclipse.hawkbit.mgmt.rest.api.MgmtDistributionSetRestApi;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRolloutRestApi;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetRestApi;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetTypeRestApi;
import org.eclipse.hawkbit.repository.ActionFields;
import org.eclipse.hawkbit.repository.ActionStatusFields;
import org.eclipse.hawkbit.repository.DeploymentManagement;
@@ -79,6 +81,10 @@ public final class MgmtTargetMapper {
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"));
if (response.getTargetType() != null) {
response.add(linkTo(methodOn(MgmtTargetTypeRestApi.class)
.getTargetType(response.getTargetType())).withRel(MgmtRestConstants.TARGET_V1_ASSIGNED_TARGET_TYPE));
}
}
static void addPollStatus(final Target target, final MgmtTarget targetRest) {
@@ -153,6 +159,9 @@ public final class MgmtTargetMapper {
if (installationDate != null) {
targetRest.setInstalledAt(installationDate);
}
if (target.getTargetType() != null){
targetRest.setTargetType(target.getTargetType().getId());
}
targetRest.add(linkTo(methodOn(MgmtTargetRestApi.class).getTarget(target.getControllerId())).withSelfRel());
@@ -172,7 +181,7 @@ public final class MgmtTargetMapper {
private static TargetCreate fromRequest(final EntityFactory entityFactory, final MgmtTargetRequestBody targetRest) {
return entityFactory.target().create().controllerId(targetRest.getControllerId()).name(targetRest.getName())
.description(targetRest.getDescription()).securityToken(targetRest.getSecurityToken())
.address(targetRest.getAddress());
.address(targetRest.getAddress()).targetType(targetRest.getTargetType());
}
static List<MetaData> fromRequestTargetMetadata(final List<MgmtMetadata> metadata,

View File

@@ -18,6 +18,7 @@ import java.util.stream.Collectors;
import javax.validation.Valid;
import javax.validation.ValidationException;
import org.eclipse.hawkbit.mgmt.json.model.MgmtId;
import org.eclipse.hawkbit.mgmt.json.model.MgmtMetadata;
import org.eclipse.hawkbit.mgmt.json.model.MgmtMetadataBodyPut;
import org.eclipse.hawkbit.mgmt.json.model.PagedList;
@@ -140,7 +141,8 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
final Target updateTarget = this.targetManagement.update(entityFactory.target().update(targetId)
.name(targetRest.getName()).description(targetRest.getDescription()).address(targetRest.getAddress())
.securityToken(targetRest.getSecurityToken()).requestAttributes(targetRest.isRequestAttributes()));
.targetType(targetRest.getTargetType()).securityToken(targetRest.getSecurityToken())
.requestAttributes(targetRest.isRequestAttributes()));
final MgmtTarget response = MgmtTargetMapper.toResponse(updateTarget);
MgmtTargetMapper.addPollStatus(updateTarget, response);
@@ -156,6 +158,18 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
return ResponseEntity.ok().build();
}
@Override
public ResponseEntity<Void> unassignTargetType(@PathVariable("targetId") final String targetId) {
this.targetManagement.unAssignType(targetId);
return ResponseEntity.ok().build();
}
@Override
public ResponseEntity<Void> assignTargetType(@PathVariable("targetId") final String targetId, @RequestBody final MgmtId targetTypeId) {
this.targetManagement.assignType(targetId, targetTypeId.getId());
return ResponseEntity.ok().build();
}
@Override
public ResponseEntity<MgmtTargetAttributes> getAttributes(@PathVariable("targetId") final String targetId) {
final Map<String, String> controllerAttributes = targetManagement.getControllerAttributes(targetId);

View File

@@ -0,0 +1,81 @@
/**
* Copyright (c) 2021 Bosch.IO 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.mgmt.rest.resource;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.eclipse.hawkbit.mgmt.json.model.distributionsettype.MgmtDistributionSetTypeAssignment;
import org.eclipse.hawkbit.mgmt.json.model.targettype.MgmtTargetType;
import org.eclipse.hawkbit.mgmt.json.model.targettype.MgmtTargetTypeRequestBodyPost;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetTypeRestApi;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.builder.TargetTypeCreate;
import org.eclipse.hawkbit.repository.model.TargetType;
import org.eclipse.hawkbit.rest.data.ResponseList;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;
/**
* A mapper which maps repository model to RESTful model representation and
* back.
*
*/
public final class MgmtTargetTypeMapper {
// private constructor, utility class
private MgmtTargetTypeMapper() {
}
static List<TargetTypeCreate> targetFromRequest(final EntityFactory entityFactory,
final Collection<MgmtTargetTypeRequestBodyPost> targetTypesRest) {
if (targetTypesRest == null) {
return Collections.emptyList();
}
return targetTypesRest.stream().map(targetRest -> fromRequest(entityFactory, targetRest)).collect(Collectors.toList());
}
private static TargetTypeCreate fromRequest(final EntityFactory entityFactory,
final MgmtTargetTypeRequestBodyPost targetTypesRest) {
return entityFactory.targetType().create().name(targetTypesRest.getName()).description(targetTypesRest.getDescription())
.colour(targetTypesRest.getColour()).compatible(getDistributionSets(targetTypesRest));
}
private static Collection<Long> getDistributionSets(final MgmtTargetTypeRequestBodyPost targetTypesRest) {
return Optional.ofNullable(targetTypesRest.getCompatibleDsTypes())
.map(ds -> ds.stream().map(MgmtDistributionSetTypeAssignment::getId).collect(Collectors.toList()))
.orElse(Collections.emptyList());
}
static List<MgmtTargetType> toListResponse(final List<TargetType> types) {
if (types == null) {
return Collections.emptyList();
}
return new ResponseList<>(types.stream().map(MgmtTargetTypeMapper::toResponse).collect(Collectors.toList()));
}
static MgmtTargetType toResponse(final TargetType type) {
final MgmtTargetType result = new MgmtTargetType();
MgmtRestModelMapper.mapNamedToNamed(result, type);
result.setTypeId(type.getId());
result.setColour(type.getColour());
result.add(linkTo(methodOn(MgmtTargetTypeRestApi.class).getTargetType(result.getTypeId())).withSelfRel());
return result;
}
static void addLinks(final MgmtTargetType result) {
result.add(linkTo(methodOn(MgmtTargetTypeRestApi.class).getCompatibleDistributionSets(result.getTypeId()))
.withRel(MgmtRestConstants.TARGETTYPE_V1_DS_TYPES));
}
}

View File

@@ -0,0 +1,148 @@
/**
* Copyright (c) 2021 Bosch.IO 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.mgmt.rest.resource;
import java.util.List;
import java.util.stream.Collectors;
import org.eclipse.hawkbit.mgmt.json.model.PagedList;
import org.eclipse.hawkbit.mgmt.json.model.distributionsettype.MgmtDistributionSetType;
import org.eclipse.hawkbit.mgmt.json.model.distributionsettype.MgmtDistributionSetTypeAssignment;
import org.eclipse.hawkbit.mgmt.json.model.targettype.MgmtTargetType;
import org.eclipse.hawkbit.mgmt.json.model.targettype.MgmtTargetTypeRequestBodyPost;
import org.eclipse.hawkbit.mgmt.json.model.targettype.MgmtTargetTypeRequestBodyPut;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetTypeRestApi;
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.OffsetBasedPageRequest;
import org.eclipse.hawkbit.repository.TargetTypeManagement;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.model.TargetType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* REST Resource handling for {@link TargetType} CRUD operations.
*/
@RestController
public class MgmtTargetTypeResource implements MgmtTargetTypeRestApi {
private static final Logger LOG = LoggerFactory.getLogger(MgmtTargetTypeResource.class);
private final TargetTypeManagement targetTypeManagement;
private final EntityFactory entityFactory;
public MgmtTargetTypeResource(TargetTypeManagement targetTypeManagement, final EntityFactory entityFactory) {
this.targetTypeManagement = targetTypeManagement;
this.entityFactory = entityFactory;
}
@Override
public ResponseEntity<PagedList<MgmtTargetType>> getTargetTypes(
@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.sanitizeTargetTypeSortParam(sortParam);
final Pageable pageable = new OffsetBasedPageRequest(sanitizedOffsetParam, sanitizedLimitParam, sorting);
final Page<TargetType> findTargetTypesAll;
long countTargetTypesAll;
if (rsqlParam != null) {
findTargetTypesAll= targetTypeManagement.findByRsql(pageable, rsqlParam);
} else {
findTargetTypesAll = targetTypeManagement.findAll(pageable);
}
countTargetTypesAll = findTargetTypesAll.getTotalElements();
final List<MgmtTargetType> rest = MgmtTargetTypeMapper.toListResponse(findTargetTypesAll.getContent());
return ResponseEntity.ok(new PagedList<>(rest, countTargetTypesAll));
}
@Override
public ResponseEntity<MgmtTargetType> getTargetType(@PathVariable("targetTypeId") final Long targetTypeId) {
final TargetType foundType = findTargetTypeWithExceptionIfNotFound(targetTypeId);
final MgmtTargetType response = MgmtTargetTypeMapper.toResponse(foundType);
MgmtTargetTypeMapper.addLinks(response);
return ResponseEntity.ok(response);
}
@Override
public ResponseEntity<Void> deleteTargetType(@PathVariable("targetTypeId") final Long targetTypeId) {
LOG.debug("Delete {} target type", targetTypeId);
targetTypeManagement.delete(targetTypeId);
return ResponseEntity.ok().build();
}
@Override
public ResponseEntity<MgmtTargetType> updateTargetType(@PathVariable("targetTypeId") final Long targetTypeId,
@RequestBody final MgmtTargetTypeRequestBodyPut restTargetType) {
final TargetType updated = targetTypeManagement
.update(entityFactory.targetType().update(targetTypeId).name(restTargetType.getName())
.description(restTargetType.getDescription()).colour(restTargetType.getColour()));
final MgmtTargetType response = MgmtTargetTypeMapper.toResponse(updated);
MgmtTargetTypeMapper.addLinks(response);
return ResponseEntity.ok(response);
}
@Override
public ResponseEntity<List<MgmtTargetType>> createTargetTypes(
@RequestBody final List<MgmtTargetTypeRequestBodyPost> targetTypes) {
final List<TargetType> createdTargetTypes = targetTypeManagement
.create(MgmtTargetTypeMapper.targetFromRequest(entityFactory, targetTypes));
return ResponseEntity.status(HttpStatus.CREATED).body(MgmtTargetTypeMapper.toListResponse(createdTargetTypes));
}
@Override
public ResponseEntity<List<MgmtDistributionSetType>> getCompatibleDistributionSets(
@PathVariable("targetTypeId") final Long targetTypeId) {
final TargetType foundType = findTargetTypeWithExceptionIfNotFound(targetTypeId);
return ResponseEntity
.ok(MgmtDistributionSetTypeMapper.toListResponse(foundType.getCompatibleDistributionSetTypes()));
}
@Override
public ResponseEntity<Void> removeCompatibleDistributionSet(@PathVariable("targetTypeId") final Long targetTypeId,
@PathVariable("distributionSetTypeId") final Long distributionSetTypeId) {
targetTypeManagement.unassignDistributionSetType(targetTypeId, distributionSetTypeId);
return ResponseEntity.ok().build();
}
@Override
public ResponseEntity<Void> addCompatibleDistributionSets(@PathVariable("targetTypeId") final Long targetTypeId,
@RequestBody final List<MgmtDistributionSetTypeAssignment> distributionSetTypeIds) {
targetTypeManagement.assignCompatibleDistributionSetTypes(targetTypeId,
distributionSetTypeIds.stream().map(MgmtDistributionSetTypeAssignment::getId).collect(Collectors.toList()));
return ResponseEntity.ok().build();
}
private TargetType findTargetTypeWithExceptionIfNotFound(final Long targetTypeId) {
return targetTypeManagement.get(targetTypeId)
.orElseThrow(() -> new EntityNotFoundException(TargetType.class, targetTypeId));
}
}

View File

@@ -22,6 +22,7 @@ import org.eclipse.hawkbit.repository.SoftwareModuleTypeFields;
import org.eclipse.hawkbit.repository.TagFields;
import org.eclipse.hawkbit.repository.TargetFields;
import org.eclipse.hawkbit.repository.TargetFilterQueryFields;
import org.eclipse.hawkbit.repository.TargetTypeFields;
import org.eclipse.hawkbit.rest.util.SortUtility;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
@@ -61,6 +62,14 @@ public final class PagingUtility {
return Sort.by(SortUtility.parse(TargetFields.class, sortParam));
}
static Sort sanitizeTargetTypeSortParam(final String sortParam) {
if (sortParam == null) {
// default
return Sort.by(Direction.ASC, TargetTypeFields.ID.getFieldName());
}
return Sort.by(SortUtility.parse(TargetFields.class, sortParam));
}
static Sort sanitizeTagSortParam(final String sortParam) {
if (sortParam == null) {
// default

View File

@@ -33,6 +33,7 @@ import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.validation.ConstraintViolationException;
@@ -56,6 +57,7 @@ import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetMetadata;
import org.eclipse.hawkbit.repository.model.TargetType;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.repository.test.util.WithUser;
import org.eclipse.hawkbit.rest.exception.MessageNotReadableException;
@@ -63,6 +65,7 @@ import org.eclipse.hawkbit.rest.json.model.ExceptionInfo;
import org.eclipse.hawkbit.rest.util.JsonBuilder;
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
import org.eclipse.hawkbit.util.IpUtil;
import org.hamcrest.Matchers;
import org.json.JSONArray;
import org.json.JSONObject;
import org.junit.jupiter.api.Test;
@@ -105,6 +108,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
private static final String JSON_PATH_FIELD_SIZE = ".size";
private static final String JSON_PATH_FIELD_TOTAL = ".total";
private static final String JSON_PATH_FIELD_LAST_REQUEST_AT = ".lastControllerRequestAt";
private static final String JSON_PATH_FIELD_TARGET_TYPE = ".targetType";
// target
// $.field
@@ -117,6 +121,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
private static final String JSON_PATH_CONTROLLERID = JSON_PATH_ROOT + JSON_PATH_FIELD_CONTROLLERID;
private static final String JSON_PATH_DESCRIPTION = JSON_PATH_ROOT + JSON_PATH_FIELD_DESCRIPTION;
private static final String JSON_PATH_LAST_REQUEST_AT = JSON_PATH_ROOT + JSON_PATH_FIELD_LAST_REQUEST_AT;
private static final String JSON_PATH_TYPE = JSON_PATH_ROOT + JSON_PATH_FIELD_TARGET_TYPE;
@Autowired
private JpaProperties jpaProperties;
@@ -2075,4 +2080,192 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
"$._links.rollout.href", containsString("/rest/v1/rollouts/" + rollout.getId().intValue())));
}
@Test
@Description("Ensures that a post request for creating targets with target type works.")
public void createTargetsWithTargetType() throws Exception {
final TargetType type1 = testdataFactory.createTargetType("typeWithDs", Collections.singletonList(standardDsType));
final TargetType type2 = testdataFactory.createTargetType("typeWithOutDs", Collections.singletonList(standardDsType));
final Target test1 = entityFactory.target().create().controllerId("id1").name("targetWithoutType")
.securityToken("token").address("amqp://test123/foobar").description("testid1").build();
final Target test2 = entityFactory.target().create().controllerId("id2").name("targetOfType1")
.targetType(type1.getId()).description("testid2").build();
final Target test3 = entityFactory.target().create().controllerId("id3").name("targetOfType2")
.targetType(type2.getId()).description("testid3").build();
final String hrefType1 = "http://localhost/rest/v1/targettypes/" + type1.getId();
final List<Target> targets = Arrays.asList(test1, test2, test3);
final MvcResult mvcPostResult = mvc
.perform(post("/rest/v1/targets/").content(JsonBuilder.targets(targets, true))
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
.andExpect(jsonPath("[0].name", equalTo("targetWithoutType")))
.andExpect(jsonPath("[0].controllerId", equalTo("id1")))
.andExpect(jsonPath("[0].description", equalTo("testid1")))
.andExpect(jsonPath("[0].createdAt", not(equalTo(0))))
.andExpect(jsonPath("[0].createdBy", equalTo("bumlux")))
.andExpect(jsonPath("[0].securityToken", equalTo("token")))
.andExpect(jsonPath("[0].address", equalTo("amqp://test123/foobar")))
.andExpect(jsonPath("[0].targetType").doesNotExist())
.andExpect(jsonPath("[1].name", equalTo("targetOfType1")))
.andExpect(jsonPath("[1].createdBy", equalTo("bumlux")))
.andExpect(jsonPath("[1].controllerId", equalTo("id2")))
.andExpect(jsonPath("[1].description", equalTo("testid2")))
.andExpect(jsonPath("[1].createdAt", not(equalTo(0))))
.andExpect(jsonPath("[1].createdBy", equalTo("bumlux")))
.andExpect(jsonPath("[1].targetType", equalTo(type1.getId().intValue())))
.andExpect(jsonPath("[2].name", equalTo("targetOfType2")))
.andExpect(jsonPath("[2].controllerId", equalTo("id3")))
.andExpect(jsonPath("[2].description", equalTo("testid3")))
.andExpect(jsonPath("[2].createdAt", not(equalTo(0))))
.andExpect(jsonPath("[2].createdBy", equalTo("bumlux")))
.andExpect(jsonPath("[2].targetType", equalTo(type2.getId().intValue())))
.andReturn();
mvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + test2.getControllerId()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(jsonPath(JSON_PATH_NAME, equalTo("targetOfType1")))
.andExpect(jsonPath(JSON_PATH_CONTROLLERID, equalTo("id2")))
.andExpect(jsonPath(JSON_PATH_TYPE, equalTo(type1.getId().intValue())))
.andExpect(jsonPath(JSON_PATH_DESCRIPTION, equalTo("testid2")))
.andExpect(jsonPath("$._links.targetType.href", equalTo(hrefType1))).andReturn();
assertThat(targetManagement.getByControllerID("id1")).isNotNull();
assertThat(targetManagement.getByControllerID("id1").get().getName()).isEqualTo("targetWithoutType");
assertThat(targetManagement.getByControllerID("id1").get().getDescription()).isEqualTo("testid1");
assertThat(targetManagement.getByControllerID("id1").get().getTargetType()).isNull();
assertThat(targetManagement.getByControllerID("id1").get().getSecurityToken()).isEqualTo("token");
assertThat(targetManagement.getByControllerID("id1").get().getAddress().toString())
.isEqualTo("amqp://test123/foobar");
assertThat(targetManagement.getByControllerID("id2")).isNotNull();
assertThat(targetManagement.getByControllerID("id2").get().getName()).isEqualTo("targetOfType1");
assertThat(targetManagement.getByControllerID("id2").get().getDescription()).isEqualTo("testid2");
assertThat(targetManagement.getByControllerID("id2").get().getTargetType().getName()).isEqualTo("typeWithDs");
assertThat(targetManagement.getByControllerID("id3")).isNotNull();
assertThat(targetManagement.getByControllerID("id3").get().getName()).isEqualTo("targetOfType2");
assertThat(targetManagement.getByControllerID("id3").get().getDescription()).isEqualTo("testid3");
assertThat(targetManagement.getByControllerID("id3").get().getTargetType().getName()).isEqualTo("typeWithOutDs");
}
@Test
@Description("Ensures that a post request for creating target with target type works.")
public void createTargetWithExistingTargetType() throws Exception {
// create target type
List<TargetType> targetTypes = testdataFactory.createTargetTypes("targettype",1);
assertThat(targetTypes).hasSize(1);
final Target target = entityFactory.target().create().controllerId("targetcontroller").name("testtarget").targetType(targetTypes.get(0).getId()).build();
final String targetList = JsonBuilder.targets(Collections.singletonList(target), false);
// test query target over rest resource
mvc.perform(post(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING).content(targetList)
.contentType(MediaType.APPLICATION_JSON)).andExpect(status().isCreated())
.andExpect(jsonPath("[0].controllerId", equalTo("targetcontroller")))
.andExpect(jsonPath("[0].targetType", equalTo(targetTypes.get(0).getId().intValue())));
assertThat(targetManagement.getByControllerID("targetcontroller").get().getTargetType().getId()).isEqualTo(targetTypes.get(0).getId());
}
@Test
@Description("Ensures that a put request for updating targets with target type works.")
public void updateTargetTypeInTarget() throws Exception {
// create target type
List<TargetType> targetTypes = testdataFactory.createTargetTypes("targettype",2);
assertThat(targetTypes).hasSize(2);
String controllerId = "targetcontroller";
Target target = testdataFactory.createTarget(controllerId, "testtarget", targetTypes.get(0).getId());
assertThat(target).isNotNull();
assertThat(target.getTargetType().getId()).isEqualTo(targetTypes.get(0).getId());
// update target over rest resource
final String body = new JSONObject().put("targetType", targetTypes.get(1).getId().intValue()).toString();
mvc.perform(put(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + controllerId).content(body)
.contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk())
.andExpect(jsonPath("controllerId", equalTo(controllerId)))
.andExpect(jsonPath("targetType", equalTo(targetTypes.get(1).getId().intValue())));
}
@Test
@Description("Ensures that a post request for creating targets with unknown target type fails.")
public void addingNonExistingTargetTypeInTargetShouldFail() throws Exception {
long unknownTargetTypeId = 999;
String errorMsg = String.format("TargetType with given identifier {%s} does not exist.", unknownTargetTypeId);
Optional<TargetType> targetType = targetTypeManagement.get(unknownTargetTypeId);
assertThat(targetType).isNotPresent();
String controllerId = "targetcontroller";
final Target target = entityFactory.target().create().controllerId(controllerId).name("testtarget").build();
final String targetList = JsonBuilder.targets(Collections.singletonList(target), false, unknownTargetTypeId);
// post target over rest resource
mvc.perform(post(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING).content(targetList)
.contentType(MediaType.APPLICATION_JSON)).andExpect(status().isNotFound())
.andExpect(jsonPath("message", Matchers.containsString(errorMsg)));
}
@Test
@Description("Ensures that a post request for assign target type to target works.")
public void assignTargetTypeToTarget() throws Exception {
// create target type
TargetType targetType = testdataFactory.findOrCreateTargetType("targettype");
assertThat(targetType).isNotNull();
// create target
String targetControllerId = "targetcontroller";
Target target = testdataFactory.createTarget(targetControllerId, "testtarget");
assertThat(target).isNotNull();
// assign target type over rest resource
mvc.perform(post(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + targetControllerId + "/targettype")
.content("{\"id\":" + targetType.getId() + "}").contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
assertThat(targetManagement.getByControllerID(targetControllerId).get().getTargetType().getId()).isEqualTo(targetType.getId());
}
@Test
@Description("Ensures that a post request for assign a invalid target type to target fails.")
public void assignInvalidTargetTypeToTargetFails() throws Exception {
// Invalid target type ID
long invalidTargetTypeId = 999;
// create target
String targetControllerId = "targetcontroller";
Target target = testdataFactory.createTarget(targetControllerId, "testtarget");
assertThat(target).isNotNull();
// assign invalid target type over rest resource
mvc.perform(post(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + targetControllerId + "/targettype")
.content("{\"id\":" + invalidTargetTypeId + "}").contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
}
@Test
@Description("Ensures that a delete request for unassign target type from target works.")
public void unassignTargetTypeFromTarget() throws Exception {
// create target type
List<TargetType> targetTypes = testdataFactory.createTargetTypes("targettype",1);
assertThat(targetTypes).hasSize(1);
String targetControllerId = "targetcontroller";
Target target = testdataFactory.createTarget(targetControllerId, "testtarget", targetTypes.get(0).getId());
assertThat(target).isNotNull();
assertThat(target.getTargetType().getId()).isEqualTo(targetTypes.get(0).getId());
// unassign target type over rest resource
mvc.perform(delete(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + targetControllerId + "/targettype")
.contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk());
assertThat(targetManagement.getByControllerID(targetControllerId).get().getTargetType()).isNull();
}
}

View File

@@ -0,0 +1,616 @@
/**
* Copyright (c) 2021 Bosch.IO 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.mgmt.rest.resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import com.jayway.jsonpath.JsonPath;
import io.qameta.allure.Description;
import io.qameta.allure.Feature;
import io.qameta.allure.Step;
import io.qameta.allure.Story;
import org.apache.commons.lang3.RandomStringUtils;
import org.eclipse.hawkbit.im.authentication.SpPermission;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
import org.eclipse.hawkbit.repository.builder.TargetTypeCreate;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.repository.model.TargetType;
import org.eclipse.hawkbit.repository.test.util.WithUser;
import org.eclipse.hawkbit.rest.util.JsonBuilder;
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
import org.json.JSONObject;
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.ResultActions;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.hasToString;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.startsWith;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
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.status;
/**
* Spring MVC Tests against the MgmtTargetTypeResource.
*
*/
@Feature("Component Tests - Management API")
@Story("Target Type Resource")
class MgmtTargetTypeResourceTest extends AbstractManagementApiIntegrationTest {
private final static String TARGETTYPES_ENDPOINT = MgmtRestConstants.TARGETTYPE_V1_REQUEST_MAPPING;
private final static String TARGETTYPE_SINGLE_ENDPOINT = MgmtRestConstants.TARGETTYPE_V1_REQUEST_MAPPING
+ "/{typeid}";
private final static String TARGETTYPE_DSTYPES_ENDPOINT = TARGETTYPE_SINGLE_ENDPOINT + "/"
+ MgmtRestConstants.TARGETTYPE_V1_DS_TYPES;
private final static String TARGETTYPE_DSTYPE_SINGLE_ENDPOINT = TARGETTYPE_DSTYPES_ENDPOINT + "/{dstypeid}";
private final static String TEST_USER = "targetTypeTester";
@Test
@WithUser(principal = "targetTypeTester", allSpPermissions = true, removeFromAllPermission = { SpPermission.READ_TARGET })
@Description("GET targettypes returns Forbidden when permission is missing")
void getTargetTypesWithoutPermission() throws Exception {
mvc.perform(get(TARGETTYPES_ENDPOINT).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isForbidden());
}
@Test
@WithUser(principal = TEST_USER, allSpPermissions = true)
@Description("Checks the correct behaviour of /rest/v1/targettypes/{id} GET request.")
void getTargetType() throws Exception {
String typeName = "TestTypeGET";
TargetType testType = createTestTargetTypeInDB(typeName);
Long typeId = testType.getId();
mvc.perform(get(TARGETTYPE_SINGLE_ENDPOINT, typeId).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
.andExpect(jsonPath("$.id", is(typeId), Long.class)).andExpect(jsonPath("$.name", equalTo(typeName)))
.andExpect(jsonPath("$.colour", is("#000000")))
.andExpect(jsonPath("$.description", equalTo(typeName + " description")))
.andExpect(jsonPath("$.createdBy", equalTo(TEST_USER)))
.andExpect(jsonPath("$.createdAt", equalTo(testType.getCreatedAt())))
.andExpect(jsonPath("$.lastModifiedBy", equalTo(TEST_USER)))
.andExpect(jsonPath("$.lastModifiedAt", equalTo(testType.getLastModifiedAt())))
.andExpect(jsonPath("$._links.self.href", equalTo("http://localhost/rest/v1/targettypes/" + typeId)))
.andExpect(jsonPath("$.deleted").doesNotExist())
.andExpect(jsonPath("$.key").doesNotExist())
.andExpect(jsonPath("$._links.compatibledistributionsettypes.href",
equalTo("http://localhost/rest/v1/targettypes/" + typeId + "/compatibledistributionsettypes")));
}
@Test
@WithUser(principal = TEST_USER, allSpPermissions = true)
@Description("Checks the correct behaviour of /rest/v1/targettypes GET requests.")
void getTargetTypes() throws Exception {
String typeName = "TestTypeGET";
int count = 5;
List<TargetType> testTypes = createTestTargetTypesInDB(typeName, count);
ResultActions resultActions = mvc.perform(get(TARGETTYPES_ENDPOINT).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print());
for (int index = 0; index < count; index++) {
Long typeId = testTypes.get(index).getId();
resultActions.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
.andExpect(jsonPath("$.content.[?(@.id=='" + typeId + "')].id", contains(typeId.intValue())))
.andExpect(jsonPath("$.content.[?(@.id=='" + typeId + "')].name", contains(typeName + index)))
.andExpect(jsonPath("$.content.[?(@.id=='" + typeId + "')].colour", contains("#000000")))
.andExpect(jsonPath("$.content.[?(@.id=='" + typeId + "')].description",
contains(typeName + " description")))
.andExpect(jsonPath("$.content.[?(@.id=='" + typeId + "')].createdBy", contains(TEST_USER)))
.andExpect(jsonPath("$.content.[?(@.id=='" + typeId + "')].createdAt",
contains(testTypes.get(index).getCreatedAt())))
.andExpect(jsonPath("$.content.[?(@.id=='" + typeId + "')].lastModifiedBy", contains(TEST_USER)))
.andExpect(jsonPath("$.content.[?(@.id=='" + typeId + "')].lastModifiedAt",
contains(testTypes.get(index).getLastModifiedAt())))
.andExpect(jsonPath("$.content.[?(@.id=='" + typeId + "')].deleted").doesNotExist())
.andExpect(jsonPath("$.content.[?(@.id=='" + typeId + "')].key").doesNotExist())
.andExpect(jsonPath("$.content.[?(@.id=='" + typeId + "')]._links.self.href",
contains("http://localhost/rest/v1/targettypes/" + typeId)))
.andExpect(
jsonPath("$.content.[?(@.id=='" + typeId + "')]._links.compatibledistributionsettypes.href")
.doesNotExist())
.andExpect(jsonPath("$.total", equalTo(count))).andExpect(jsonPath("$.size", equalTo(count)));
}
}
@Test
@WithUser(principal = TEST_USER, allSpPermissions = true)
@Description("Checks the correct behaviour of /rest/v1/targettypes GET requests without prior created target types.")
void getDefaultTargetTypes() throws Exception {
// 0 types overall (no default types are created)
final int types = 0;
mvc.perform(get(TARGETTYPES_ENDPOINT)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(jsonPath(MgmtTargetResourceTest.JSON_PATH_PAGED_LIST_TOTAL, equalTo(types)))
.andExpect(jsonPath(MgmtTargetResourceTest.JSON_PATH_PAGED_LIST_SIZE, equalTo(types)))
.andExpect(jsonPath(MgmtTargetResourceTest.JSON_PATH_PAGED_LIST_CONTENT, hasSize(types)));
}
@Test
@WithUser(principal = TEST_USER, allSpPermissions = true)
@Description("Checks the correct behaviour of /rest/v1/targettypes GET requests with sorting by name.")
void getTargetTypesSortedByName() throws Exception {
String typeNameA = "ATestTypeGETsorted";
String typeNameB = "BTestTypeGETsorted";
String typeNameC = "CTestTypeGETsorted";
TargetType testTypeB = createTestTargetTypeInDB(typeNameB);
TargetType testTypeC = createTestTargetTypeInDB(typeNameC);
TargetType testTypeA = createTestTargetTypeInDB(typeNameA);
testTypeA = targetTypeManagement
.update(entityFactory.targetType().update(testTypeA.getId()).description("Updated description"));
// descending
mvc.perform(get(TARGETTYPES_ENDPOINT).accept(MediaType.APPLICATION_JSON)
.param(MgmtRestConstants.REQUEST_PARAMETER_SORTING, "name:DESC")).andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
.andExpect(jsonPath("$.content.[0].id", equalTo(testTypeC.getId().intValue())))
.andExpect(jsonPath("$.content.[0].name", equalTo(typeNameC)))
.andExpect(jsonPath("$.content.[0].colour", equalTo("#000000")))
.andExpect(jsonPath("$.content.[0].description", equalTo(typeNameC + " description")))
.andExpect(jsonPath("$.content.[0].createdBy", equalTo(TEST_USER)))
.andExpect(jsonPath("$.content.[0].createdAt", equalTo(testTypeC.getCreatedAt())))
.andExpect(jsonPath("$.content.[0].lastModifiedBy", equalTo(TEST_USER)))
.andExpect(jsonPath("$.content.[0].lastModifiedAt", equalTo(testTypeC.getLastModifiedAt())))
.andExpect(jsonPath("$.content.[0].deleted").doesNotExist())
.andExpect(jsonPath("$.content.[0].key").doesNotExist())
.andExpect(jsonPath("$.content.[0]._links.self.href",
equalTo("http://localhost/rest/v1/targettypes/" + testTypeC.getId())))
.andExpect(jsonPath("$.content.[0]._links.compatibledistributionsettypes.href").doesNotExist())
.andExpect(jsonPath("$.total", equalTo(3))).andExpect(jsonPath("$.size", equalTo(3)))
.andExpect(jsonPath("$.content.[1].name", equalTo(typeNameB)))
.andExpect(jsonPath("$.content.[2].name", equalTo(typeNameA)));
// ascending
mvc.perform(get(TARGETTYPES_ENDPOINT).accept(MediaType.APPLICATION_JSON)
.param(MgmtRestConstants.REQUEST_PARAMETER_SORTING, "name:ASC")).andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
.andExpect(jsonPath("$.content.[0].id", equalTo(testTypeA.getId().intValue())))
.andExpect(jsonPath("$.content.[0].name", equalTo(typeNameA)))
.andExpect(jsonPath("$.content.[0].description", equalTo("Updated description")))
.andExpect(jsonPath("$.content.[0].colour", equalTo("#000000")))
.andExpect(jsonPath("$.content.[0].createdBy", equalTo(TEST_USER)))
.andExpect(jsonPath("$.content.[0].createdAt", equalTo(testTypeA.getCreatedAt())))
.andExpect(jsonPath("$.content.[0].lastModifiedBy", equalTo(TEST_USER)))
.andExpect(jsonPath("$.content.[0].lastModifiedAt", equalTo(testTypeA.getLastModifiedAt())))
.andExpect(jsonPath("$.content.[0].deleted").doesNotExist())
.andExpect(jsonPath("$.content.[0].key").doesNotExist())
.andExpect(jsonPath("$.content.[0]._links.self.href",
equalTo("http://localhost/rest/v1/targettypes/" + testTypeA.getId())))
.andExpect(jsonPath("$.content.[0]._links.compatibledistributionsettypes.href").doesNotExist())
.andExpect(jsonPath("$.total", equalTo(3))).andExpect(jsonPath("$.size", equalTo(3)))
.andExpect(jsonPath("$.content.[1].name", equalTo(typeNameB)))
.andExpect(jsonPath("$.content.[2].name", equalTo(typeNameC)));
}
@Test
@WithUser(principal = TEST_USER, allSpPermissions = true)
@Description("Checks the correct behaviour of /rest/v1/targettypes GET requests with paging.")
void getTargetTypesWithPagingLimitRequestParameter() throws Exception {
final String typePrefix = "TestTypeGETPaging";
final int count = 10;
final int limit = 3;
createTestTargetTypesInDB(typePrefix, count);
mvc.perform(get(TARGETTYPES_ENDPOINT).param(MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT,
String.valueOf(limit))).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(jsonPath(MgmtTargetResourceTest.JSON_PATH_PAGED_LIST_TOTAL, equalTo(count)))
.andExpect(jsonPath(MgmtTargetResourceTest.JSON_PATH_PAGED_LIST_SIZE, equalTo(limit)))
.andExpect(jsonPath(MgmtTargetResourceTest.JSON_PATH_PAGED_LIST_CONTENT, hasSize(limit)));
}
@Test
@WithUser(principal = TEST_USER, allSpPermissions = true)
@Description("Checks the correct behaviour of /rest/v1/targettypes GET requests with paging and offset.")
void getTargetTypesWithPagingLimitAndOffsetRequestParameter() throws Exception {
final int count = 10;
final int offset = 2;
final int expectedSize = count - offset;
final String typePrefix = "TestTypeGETPaging";
createTestTargetTypesInDB(typePrefix, count);
mvc.perform(get(TARGETTYPES_ENDPOINT)
.param(MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, String.valueOf(offset))
.param(MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(count)))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(jsonPath(MgmtTargetResourceTest.JSON_PATH_PAGED_LIST_TOTAL, equalTo(count)))
.andExpect(jsonPath(MgmtTargetResourceTest.JSON_PATH_PAGED_LIST_SIZE, equalTo(expectedSize)))
.andExpect(jsonPath(MgmtTargetResourceTest.JSON_PATH_PAGED_LIST_CONTENT, hasSize(expectedSize)));
}
@Test
@WithUser(principal = TEST_USER, allSpPermissions = true)
@Description("Checks the correct behaviour of /rest/v1/targettypes/{ID} PUT requests.")
void updateTargetType() throws Exception {
String typeName = "TestTypePUT";
final TargetType testType = createTestTargetTypeInDB(typeName);
final String body = new JSONObject().put("id", testType.getId()).put("description", "updated description")
.put("name", "TestTypePUTupdated").put("colour", "#ffffff").toString();
mvc.perform(
put(TARGETTYPE_SINGLE_ENDPOINT, testType.getId()).content(body).contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(jsonPath("$.id", equalTo(testType.getId().intValue())))
.andExpect(jsonPath("$.description", equalTo("updated description")))
.andExpect(jsonPath("$.name", equalTo("TestTypePUTupdated")))
.andExpect(jsonPath("$.colour", equalTo("#ffffff"))).andReturn();
}
@Test
@WithUser(principal = TEST_USER, allSpPermissions = true)
@Description("Checks the correct behaviour of /rest/v1/targettypes/{id} GET requests.")
void getUpdatedTargetType() throws Exception {
TargetType testType = createTestTargetTypeInDB("TestTypeGET");
String typeNameUpdated = "TestTypeGETupdated";
testType = targetTypeManagement.update(entityFactory.targetType().update(testType.getId()).name(typeNameUpdated)
.description("Updated Description").colour("#ffffff"));
mvc.perform(get(TARGETTYPE_SINGLE_ENDPOINT, testType.getId()).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
.andExpect(jsonPath("$.name", equalTo(typeNameUpdated)))
.andExpect(jsonPath("$.description", equalTo("Updated Description")))
.andExpect(jsonPath("$.colour", equalTo("#ffffff")))
.andExpect(jsonPath("$.createdBy", equalTo(TEST_USER)))
.andExpect(jsonPath("$.createdAt", equalTo(testType.getCreatedAt())))
.andExpect(jsonPath("$.lastModifiedBy", equalTo(TEST_USER)))
.andExpect(jsonPath("$.lastModifiedAt", equalTo(testType.getLastModifiedAt())))
.andExpect(jsonPath("$.deleted").doesNotExist())
.andExpect(jsonPath("$.key").doesNotExist());
}
@Test
@WithUser(principal = TEST_USER, allSpPermissions = true)
@Description("Checks the correct behaviour of /rest/v1/targettypes POST requests.")
void createTargetTypes() throws Exception {
String typeName = "TestTypePOST";
final List<TargetType> types = buildTestTargetTypesWithoutDsTypes(typeName, 5);
runPostTargetTypeAndVerify(types);
}
@Test
@WithUser(principal = TEST_USER, allSpPermissions = true)
@Description("Checks the correct behaviour of /rest/v1/targettypes/{ID}/compatibledistributionsettypes POST requests.")
void addDistributionSetTypeToTargetType() throws Exception {
String typeName = "TestTypeAddDs";
TargetType testType = createTestTargetTypeInDB(typeName);
assertThat(testType.getOptLockRevision()).isEqualTo(1);
mvc.perform(post(TARGETTYPE_DSTYPES_ENDPOINT, testType.getId())
.content("[{\"id\":" + standardDsType.getId() + "}]").contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
testType = targetTypeManagement.get(testType.getId()).get();
assertThat(testType.getLastModifiedBy()).isEqualTo(TEST_USER);
assertThat(testType.getOptLockRevision()).isEqualTo(2);
assertThat(testType.getCompatibleDistributionSetTypes()).containsExactly(standardDsType);
}
@Test
@WithUser(principal = TEST_USER, allSpPermissions = true)
@Description("Checks the correct behaviour of /rest/v1/targettypes/{ID}/compatibledistributionsettypes GET requests.")
void getDistributionSetsOfTargetType() throws Exception {
String typeName = "TestTypeGetDs";
final TargetType testType = createTestTargetTypeInDB(typeName, Collections.singletonList(standardDsType));
mvc.perform(get(TARGETTYPE_DSTYPES_ENDPOINT, testType.getId()).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
.andExpect(jsonPath("$[0].name", equalTo(standardDsType.getName())))
.andExpect(jsonPath("$[0].description", equalTo(standardDsType.getDescription())))
.andExpect(jsonPath("$[0].key", equalTo("test_default_ds_type")))
.andExpect(jsonPath("$[0]._links.self.href",
equalTo("http://localhost/rest/v1/distributionsettypes/" + standardDsType.getId())));
}
@Test
@WithUser(principal = TEST_USER, allSpPermissions = true)
@Description("Checks the correct behaviour of /rest/v1/targettypes/{ID}/compatibledistributionsettypes/{ID} GET requests.")
void getDistributionSetOfTargetTypeReturnsNotAllowed() throws Exception {
String typeName = "TestTypeAddDs";
final TargetType testType = createTestTargetTypeInDB(typeName);
mvc.perform(get(TARGETTYPE_DSTYPE_SINGLE_ENDPOINT, testType.getId(), standardDsType.getId())
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed());
}
@Test
@WithUser(principal = TEST_USER, allSpPermissions = true)
@Description("Checks the correct behaviour of /rest/v1/targettypes/{ID}/compatibledistributionsettypes/{ID} DELETE requests.")
void removeDsTypeFromTargetType() throws Exception {
String typeName = "TestTypeRemoveDs";
TargetType testType = createTestTargetTypeInDB(typeName, Collections.singletonList(standardDsType));
mvc.perform(delete(TARGETTYPE_DSTYPE_SINGLE_ENDPOINT, testType.getId(), standardDsType.getId())
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
testType = targetTypeManagement.get(testType.getId()).get();
assertThat(testType.getLastModifiedBy()).isEqualTo(TEST_USER);
assertThat(testType.getOptLockRevision()).isEqualTo(2);
assertThat(testType.getCompatibleDistributionSetTypes()).isEmpty();
}
@Test
@WithUser(principal = TEST_USER, allSpPermissions = true)
@Description("Checks the correct behaviour of /rest/v1/distributionsettypes/{ID} DELETE requests.")
void deletingDsTypeRemovesAssignmentFromTargetType() throws Exception {
String typeName = "TestTypeRemoveDs";
TargetType testType = createTestTargetTypeInDB(typeName, Collections.singletonList(standardDsType));
assertThat(testType.getCompatibleDistributionSetTypes()).hasSize(1);
assertThat(distributionSetTypeManagement.getByKey(standardDsType.getKey())).isNotEmpty();
mvc.perform(delete(MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_REQUEST_MAPPING + "/" + standardDsType.getId()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
testType = targetTypeManagement.get(testType.getId()).get();
assertThat(testType.getLastModifiedBy()).isEqualTo(TEST_USER);
assertThat(testType.getOptLockRevision()).isEqualTo(2);
assertThat(testType.getCompatibleDistributionSetTypes()).isEmpty();
assertThat(distributionSetTypeManagement.getByKey(standardDsType.getKey())).isEmpty();
}
@Test
@WithUser(principal = TEST_USER, allSpPermissions = true)
@Description("Checks the correct behaviour of /rest/v1/targettypes/{ID} DELETE requests - Deletion when not in use.")
void deleteTargetTypeUnused() throws Exception {
String typeName = "TestTypeUnusedDelete";
final TargetType testType = createTestTargetTypeInDB(typeName);
assertThat(targetTypeManagement.count()).isEqualTo(1);
mvc.perform(delete(TARGETTYPE_SINGLE_ENDPOINT, testType.getId())).andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
assertThat(targetTypeManagement.count()).isZero();
}
@Test
@WithUser(principal = TEST_USER, allSpPermissions = true)
@Description("Checks the correct behaviour of /rest/v1/targettypes/{ID} DELETE requests - Deletion not possible when in use.")
void deleteTargetTypeUsed() throws Exception {
String typeName = "TestTypeUsedDelete";
final TargetType testType = createTestTargetTypeInDB(typeName);
targetManagement.create(entityFactory.target().create().controllerId("target").name("TargetOfTestType")
.description("target description").targetType(testType.getId()));
assertThat(targetTypeManagement.count()).isEqualTo(1);
assertThat(targetManagement.count()).isEqualTo(1);
mvc.perform(delete(TARGETTYPE_SINGLE_ENDPOINT, testType.getId())).andDo(MockMvcResultPrinter.print())
.andExpect(status().isConflict());
assertThat(targetManagement.count()).isEqualTo(1);
assertThat(targetTypeManagement.count()).isEqualTo(1);
}
@Test
@WithUser(principal = TEST_USER, allSpPermissions = true)
@Description("Ensures that target type deletion request to API on an entity that does not exist results in NOT_FOUND.")
void deleteTargetTypeThatDoesNotExistLeadsToNotFound() throws Exception {
mvc.perform(delete(TARGETTYPE_SINGLE_ENDPOINT, 1234)).andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound());
}
@Test
@WithUser(principal = TEST_USER, allSpPermissions = true)
@Description("Tests the update of the deletion flag. It is verified that the target type can't be marked as deleted through update operation.")
void updateTargetTypeDeletedFlag() throws Exception {
String typeName = "TestTypePUT";
final TargetType testType = createTestTargetTypeInDB(typeName);
final String body = new JSONObject().put("id", testType.getId()).put("deleted", true).toString();
mvc.perform(
put(TARGETTYPE_SINGLE_ENDPOINT, testType.getId()).content(body).contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(jsonPath("$.id", equalTo(testType.getId().intValue())))
.andExpect(jsonPath("$.deleted").doesNotExist());
}
@Test
@Description("Ensures that the server is behaving as expected on invalid requests (wrong media type, wrong ID etc.).")
void invalidRequestsOnTargetTypesResource() throws Exception {
String typeName = "TestTypeInvalidReq";
final TargetType testType = createTestTargetTypeInDB(typeName, Collections.singletonList(standardDsType));
// target type does not exist
mvc.perform(get(TARGETTYPE_SINGLE_ENDPOINT, 12345678)).andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound());
mvc.perform(get(TARGETTYPE_DSTYPES_ENDPOINT, 123456789)).andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound());
mvc.perform(delete(TARGETTYPE_SINGLE_ENDPOINT, 123456789)).andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound());
// target types at creation time invalid
final TargetType testNewType = createTestTargetTypeInDB(typeName + "Another",
Collections.singletonList(standardDsType));
mvc.perform(post(TARGETTYPES_ENDPOINT).content(JsonBuilder.targetTypes(Collections.singletonList(testNewType)))
.contentType(MediaType.APPLICATION_OCTET_STREAM)).andDo(MockMvcResultPrinter.print())
.andExpect(status().isUnsupportedMediaType());
// bad request - no content
mvc.perform(post(TARGETTYPES_ENDPOINT).contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest());
// bad request - bad content
mvc.perform(post(TARGETTYPES_ENDPOINT).content("sdfjsdlkjfskdjf".getBytes())
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
.andExpect(status().isBadRequest());
// Missing mandatory field name
mvc.perform(post(TARGETTYPES_ENDPOINT).content("[{\"description\":\"Desc123\"}]")
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
.andExpect(status().isBadRequest());
final TargetType tooLongName = entityFactory.targetType().create()
.name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1)).build();
mvc.perform(post(TARGETTYPES_ENDPOINT).content(JsonBuilder.targetTypes(Collections.singletonList(tooLongName)))
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
.andExpect(status().isBadRequest());
// ds types
mvc.perform(get(TARGETTYPE_DSTYPES_ENDPOINT, testType.getId())).andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
mvc.perform(delete(TARGETTYPE_DSTYPE_SINGLE_ENDPOINT, testType.getId(), 565765))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
mvc.perform(post(TARGETTYPE_DSTYPES_ENDPOINT, testType.getId()).content("{\"id\":1}")
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
.andExpect(status().isBadRequest());
mvc.perform(post(TARGETTYPE_DSTYPES_ENDPOINT, testType.getId()).content("[{\"id\":44456}]")
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound());
// not allowed methods
mvc.perform(put(TARGETTYPES_ENDPOINT)).andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed());
mvc.perform(delete(TARGETTYPES_ENDPOINT)).andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed());
mvc.perform(put(TARGETTYPE_DSTYPES_ENDPOINT, testType.getId())).andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed());
mvc.perform(delete(TARGETTYPE_DSTYPES_ENDPOINT, testType.getId(), 565765)).andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed());
mvc.perform(put(TARGETTYPE_DSTYPE_SINGLE_ENDPOINT, testType.getId(), 565765))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed());
mvc.perform(post(TARGETTYPE_DSTYPE_SINGLE_ENDPOINT, testType.getId(), 565765)
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed());
mvc.perform(get(TARGETTYPE_DSTYPE_SINGLE_ENDPOINT, testType.getId(), 565765))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed());
}
@Test
@Description("Search request of target types.")
void searchTargetTypeRsql() throws Exception {
targetTypeManagement.create(entityFactory.targetType().create().name("TestName123"));
targetTypeManagement.create(entityFactory.targetType().create().name("TestName1234"));
final String rsqlFindLikeDs1OrDs2 = "name==TestName123,name==TestName1234";
mvc.perform(get(TARGETTYPES_ENDPOINT + "?q=" + rsqlFindLikeDs1OrDs2)).andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()).andExpect(jsonPath("size", equalTo(2)))
.andExpect(jsonPath("total", equalTo(2))).andExpect(jsonPath("content[0].name", equalTo("TestName123")))
.andExpect(jsonPath("content[1].name", equalTo("TestName1234")));
}
@Step
private TargetType buildTestTargetTypeBody(String name) {
return prepareTestTargetType(name, null).build();
}
private TargetTypeCreate prepareTestTargetType(String name, Collection<DistributionSetType> dsTypes) {
TargetTypeCreate create = entityFactory.targetType().create().name(name)
.description("Description of the test type").colour("#aaaaaa");
if (dsTypes != null && !dsTypes.isEmpty()) {
create.compatible(Collections.singletonList(standardDsType.getId()));
}
return create;
}
@Step
private List<TargetType> createTestTargetTypesInDB(String namePrefix, int count) {
return testdataFactory.createTargetTypes(namePrefix, count);
}
@Step
private TargetType createTestTargetTypeInDB(String name) {
return testdataFactory.findOrCreateTargetType(name);
}
@Step
private TargetType createTestTargetTypeInDB(String name, List<DistributionSetType> dsTypes) {
TargetType targetType = testdataFactory.createTargetType(name, dsTypes);
assertThat(targetType.getOptLockRevision()).isEqualTo(1);
return targetType;
}
@Step
private List<TargetType> buildTestTargetTypesWithoutDsTypes(String namePrefix, int count) {
final List<TargetType> types = new ArrayList<>();
for (int index = 0; index < count; index++) {
types.add(buildTestTargetTypeBody(namePrefix + index));
}
return types;
}
@Step
private void runPostTargetTypeAndVerify(final List<TargetType> types) throws Exception {
int size = types.size();
ResultActions resultActions = mvc
.perform(post(TARGETTYPES_ENDPOINT).content(JsonBuilder.targetTypes(types))
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print());
for (int index = 0; index < size; index++) {
resultActions.andExpect(status().isCreated()).andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
.andExpect(jsonPath("$[" + index + "].id").exists())
.andExpect(jsonPath("$[" + index + "].name", startsWith("TestTypePOST")))
.andExpect(jsonPath("$[" + index + "].colour", hasToString("#aaaaaa")))
.andExpect(jsonPath("$[" + index + "].description",
equalTo("Description of the test type")))
.andExpect(jsonPath("$[" + index + "].createdBy", equalTo(TEST_USER)))
.andExpect(jsonPath("$[" + index + "].createdAt").exists())
.andExpect(jsonPath("$[" + index + "].lastModifiedBy", equalTo(TEST_USER)))
.andExpect(jsonPath("$[" + index + "].lastModifiedAt").exists())
.andExpect(jsonPath("$[" + index + "].key").doesNotExist())
.andExpect(jsonPath("$[" + index + "].deleted").doesNotExist())
.andExpect(jsonPath("$[" + index + "]._links.self.href",
startsWith("http://localhost/rest/v1/targettypes/")))
.andExpect(
jsonPath("$[" + index + "]._links.compatibledistributionsettypes.href")
.doesNotExist());
}
MvcResult mvcResult = resultActions.andReturn();
for (int index = 0; index < size; index++) {
String name = "TestTypePOST" + index;
final TargetType created = targetTypeManagement.getByName(name).get();
assertThat(JsonPath.compile("$[ ?(@.name=='" + name + "') ].id")
.read(mvcResult.getResponse().getContentAsString()).toString()).contains(String.valueOf(created.getId()));
assertThat(JsonPath.compile("$[ ?(@.name=='" + name + "') ]._links.self.href")
.read(mvcResult.getResponse().getContentAsString()).toString()).contains("/"+created.getId());
}
assertThat(targetTypeManagement.count()).isEqualTo(size);
}
}