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