Compare commits
3 Commits
6455f89e5b
...
5cae64af4c
Author | SHA1 | Date | |
---|---|---|---|
|
5cae64af4c | ||
|
0045c62a27 | ||
|
5f28f12676 |
@ -9,7 +9,7 @@ import org.springframework.web.context.request.WebRequest;
|
|||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
class CustomErrorResponse {
|
public class CustomErrorResponse {
|
||||||
|
|
||||||
static ResponseEntity<CustomErrorResponse> errorResponse(
|
static ResponseEntity<CustomErrorResponse> errorResponse(
|
||||||
final WebRequest request,
|
final WebRequest request,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package net.hostsharing.hsadminng.errors;
|
package net.hostsharing.hsadminng.errors;
|
||||||
|
|
||||||
|
import net.hostsharing.hsadminng.hs.validation.MultiValidationException;
|
||||||
import org.iban4j.Iban4jException;
|
import org.iban4j.Iban4jException;
|
||||||
import org.springframework.core.NestedExceptionUtils;
|
import org.springframework.core.NestedExceptionUtils;
|
||||||
import org.springframework.dao.DataIntegrityViolationException;
|
import org.springframework.dao.DataIntegrityViolationException;
|
||||||
@ -75,7 +76,8 @@ public class RestResponseEntityExceptionHandler
|
|||||||
@ExceptionHandler({ Iban4jException.class, ValidationException.class })
|
@ExceptionHandler({ Iban4jException.class, ValidationException.class })
|
||||||
protected ResponseEntity<CustomErrorResponse> handleIbanAndBicExceptions(
|
protected ResponseEntity<CustomErrorResponse> handleIbanAndBicExceptions(
|
||||||
final Throwable exc, final WebRequest request) {
|
final Throwable exc, final WebRequest request) {
|
||||||
final var message = line(NestedExceptionUtils.getMostSpecificCause(exc).getMessage(), 0);
|
final String fullMessage = NestedExceptionUtils.getMostSpecificCause(exc).getMessage();
|
||||||
|
final var message = exc instanceof MultiValidationException ? fullMessage : line(fullMessage, 0);
|
||||||
return errorResponse(request, HttpStatus.BAD_REQUEST, message);
|
return errorResponse(request, HttpStatus.BAD_REQUEST, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,11 +13,13 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
|
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
|
||||||
|
|
||||||
|
import jakarta.persistence.EntityManager;
|
||||||
|
import jakarta.persistence.PersistenceContext;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
import static net.hostsharing.hsadminng.hs.booking.item.validators.HsBookingItemEntityValidator.valid;
|
import static net.hostsharing.hsadminng.hs.booking.item.validators.HsBookingItemEntityValidator.validated;
|
||||||
import static net.hostsharing.hsadminng.mapper.PostgresDateRange.toPostgresDateRange;
|
import static net.hostsharing.hsadminng.mapper.PostgresDateRange.toPostgresDateRange;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@ -32,6 +34,9 @@ public class HsBookingItemController implements HsBookingItemsApi {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private HsBookingItemRepository bookingItemRepo;
|
private HsBookingItemRepository bookingItemRepo;
|
||||||
|
|
||||||
|
@PersistenceContext
|
||||||
|
private EntityManager em;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
public ResponseEntity<List<HsBookingItemResource>> listBookingItemsByProjectUuid(
|
public ResponseEntity<List<HsBookingItemResource>> listBookingItemsByProjectUuid(
|
||||||
@ -57,7 +62,7 @@ public class HsBookingItemController implements HsBookingItemsApi {
|
|||||||
|
|
||||||
final var entityToSave = mapper.map(body, HsBookingItemEntity.class, RESOURCE_TO_ENTITY_POSTMAPPER);
|
final var entityToSave = mapper.map(body, HsBookingItemEntity.class, RESOURCE_TO_ENTITY_POSTMAPPER);
|
||||||
|
|
||||||
final var saved = bookingItemRepo.save(valid(entityToSave));
|
final var saved = validated(bookingItemRepo.save(entityToSave));
|
||||||
|
|
||||||
final var uri =
|
final var uri =
|
||||||
MvcUriComponentsBuilder.fromController(getClass())
|
MvcUriComponentsBuilder.fromController(getClass())
|
||||||
@ -78,6 +83,7 @@ public class HsBookingItemController implements HsBookingItemsApi {
|
|||||||
context.define(currentUser, assumedRoles);
|
context.define(currentUser, assumedRoles);
|
||||||
|
|
||||||
final var result = bookingItemRepo.findByUuid(bookingItemUuid);
|
final var result = bookingItemRepo.findByUuid(bookingItemUuid);
|
||||||
|
result.ifPresent(entity -> em.detach(entity));
|
||||||
return result
|
return result
|
||||||
.map(bookingItemEntity -> ResponseEntity.ok(
|
.map(bookingItemEntity -> ResponseEntity.ok(
|
||||||
mapper.map(bookingItemEntity, HsBookingItemResource.class, ENTITY_TO_RESOURCE_POSTMAPPER)))
|
mapper.map(bookingItemEntity, HsBookingItemResource.class, ENTITY_TO_RESOURCE_POSTMAPPER)))
|
||||||
@ -112,7 +118,7 @@ public class HsBookingItemController implements HsBookingItemsApi {
|
|||||||
|
|
||||||
new HsBookingItemEntityPatcher(current).apply(body);
|
new HsBookingItemEntityPatcher(current).apply(body);
|
||||||
|
|
||||||
final var saved = bookingItemRepo.save(valid(current));
|
final var saved = bookingItemRepo.save(validated(current));
|
||||||
final var mapped = mapper.map(saved, HsBookingItemResource.class, ENTITY_TO_RESOURCE_POSTMAPPER);
|
final var mapped = mapper.map(saved, HsBookingItemResource.class, ENTITY_TO_RESOURCE_POSTMAPPER);
|
||||||
return ResponseEntity.ok(mapped);
|
return ResponseEntity.ok(mapped);
|
||||||
}
|
}
|
||||||
|
@ -88,6 +88,7 @@ public class HsBookingItemEntity implements Stringifyable, RbacObject {
|
|||||||
|
|
||||||
@ManyToOne
|
@ManyToOne
|
||||||
@JoinColumn(name = "parentitemuuid")
|
@JoinColumn(name = "parentitemuuid")
|
||||||
|
// @Transient
|
||||||
private HsBookingItemEntity parentItem;
|
private HsBookingItemEntity parentItem;
|
||||||
|
|
||||||
@Column(name = "type")
|
@Column(name = "type")
|
||||||
@ -110,10 +111,12 @@ public class HsBookingItemEntity implements Stringifyable, RbacObject {
|
|||||||
|
|
||||||
@OneToMany(cascade = CascadeType.REFRESH, orphanRemoval = true)
|
@OneToMany(cascade = CascadeType.REFRESH, orphanRemoval = true)
|
||||||
@JoinColumn(name="parentitemuuid", referencedColumnName="uuid")
|
@JoinColumn(name="parentitemuuid", referencedColumnName="uuid")
|
||||||
|
// @Transient
|
||||||
private List<HsBookingItemEntity> subBookingItems;
|
private List<HsBookingItemEntity> subBookingItems;
|
||||||
|
|
||||||
@OneToMany(cascade = CascadeType.REFRESH, orphanRemoval = true)
|
@OneToMany(cascade = CascadeType.REFRESH, orphanRemoval = true)
|
||||||
@JoinColumn(name="bookingitemuuid", referencedColumnName="uuid")
|
@JoinColumn(name="bookingitemuuid", referencedColumnName="uuid")
|
||||||
|
// @Transient
|
||||||
private List<HsHostingAssetEntity> subHostingAssets;
|
private List<HsHostingAssetEntity> subHostingAssets;
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
|
@ -3,14 +3,16 @@ package net.hostsharing.hsadminng.hs.booking.item.validators;
|
|||||||
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity;
|
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity;
|
||||||
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType;
|
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType;
|
||||||
import net.hostsharing.hsadminng.hs.validation.HsEntityValidator;
|
import net.hostsharing.hsadminng.hs.validation.HsEntityValidator;
|
||||||
|
import net.hostsharing.hsadminng.hs.validation.MultiValidationException;
|
||||||
import net.hostsharing.hsadminng.hs.validation.ValidatableProperty;
|
import net.hostsharing.hsadminng.hs.validation.ValidatableProperty;
|
||||||
|
|
||||||
import jakarta.validation.ValidationException;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import static java.util.Arrays.stream;
|
import static java.util.Arrays.stream;
|
||||||
import static java.util.Collections.emptyList;
|
import static java.util.Collections.emptyList;
|
||||||
@ -52,11 +54,8 @@ public class HsBookingItemEntityValidator extends HsEntityValidator<HsBookingIte
|
|||||||
return HsBookingItemEntityValidator.forType(bookingItem.getType()).validate(bookingItem);
|
return HsBookingItemEntityValidator.forType(bookingItem.getType()).validate(bookingItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static HsBookingItemEntity valid(final HsBookingItemEntity entityToSave) {
|
public static HsBookingItemEntity validated(final HsBookingItemEntity entityToSave) {
|
||||||
final var violations = doValidate(entityToSave);
|
MultiValidationException.throwInvalid(doValidate(entityToSave));
|
||||||
if (!violations.isEmpty()) {
|
|
||||||
throw new ValidationException(violations.toString());
|
|
||||||
}
|
|
||||||
return entityToSave;
|
return entityToSave;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,14 +76,18 @@ public class HsBookingItemEntityValidator extends HsEntityValidator<HsBookingIte
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected List<String> validateSubEntities(final HsBookingItemEntity bookingItem) {
|
protected List<String> validateSubEntities(final HsBookingItemEntity bookingItem) {
|
||||||
return stream(propertyValidators)
|
return Stream.concat(
|
||||||
.filter(ValidatableProperty::isTotalsValidator)
|
stream(propertyValidators)
|
||||||
.map(prop -> validateMaxTotalValue(bookingItem, prop))
|
.map(propDef -> propDef.validateTotals(bookingItem))
|
||||||
.filter(Objects::nonNull)
|
.flatMap(Collection::stream),
|
||||||
.toList();
|
stream(propertyValidators)
|
||||||
|
.filter(ValidatableProperty::isTotalsValidator)
|
||||||
|
.map(prop -> validateMaxTotalValue(bookingItem, prop))
|
||||||
|
).filter(Objects::nonNull).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String validateMaxTotalValue(
|
// FIXME: convert into generic shape like multi-options validator
|
||||||
|
private static String validateMaxTotalValue(
|
||||||
final HsBookingItemEntity bookingItem,
|
final HsBookingItemEntity bookingItem,
|
||||||
final ValidatableProperty<?> propDef) {
|
final ValidatableProperty<?> propDef) {
|
||||||
final var propName = propDef.propertyName();
|
final var propName = propDef.propertyName();
|
||||||
|
@ -25,21 +25,22 @@ class HsManagedWebspaceBookingItemValidator extends HsBookingItemEntityValidator
|
|||||||
integerProperty("SSD").unit("GB").min(1).max(100).step(1).required(),
|
integerProperty("SSD").unit("GB").min(1).max(100).step(1).required(),
|
||||||
integerProperty("HDD").unit("GB").min(0).max(250).step(10).optional(),
|
integerProperty("HDD").unit("GB").min(0).max(250).step(10).optional(),
|
||||||
integerProperty("Traffic").unit("GB").min(10).max(1000).step(10).required(),
|
integerProperty("Traffic").unit("GB").min(10).max(1000).step(10).required(),
|
||||||
integerProperty("MultiOptions").min(1).max(100).step(1).required()
|
integerProperty("MultiOptions").min(1).max(100).step(1).withDefault(1)
|
||||||
.eachComprising( 25, unixUsers())
|
.eachComprising( 25, unixUsers())
|
||||||
.eachComprising( 5, databaseUsers())
|
.eachComprising( 5, databaseUsers())
|
||||||
.eachComprising( 5, databases())
|
.eachComprising( 5, databases())
|
||||||
.eachComprising(250, eMailAddresses()),
|
.eachComprising(250, eMailAddresses()),
|
||||||
integerProperty("Daemons").min(0).max(10).optional(),
|
integerProperty("Daemons").min(0).max(10).withDefault(0),
|
||||||
booleanProperty("Online Office Server").optional(),
|
booleanProperty("Online Office Server").optional(),
|
||||||
enumerationProperty("SLA-Platform").values("BASIC", "EXT24H").optional()
|
enumerationProperty("SLA-Platform").values("BASIC", "EXT24H").withDefault("BASIC")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TriFunction<HsBookingItemEntity, IntegerProperty, Integer, List<String>> unixUsers() {
|
private static TriFunction<HsBookingItemEntity, IntegerProperty, Integer, List<String>> unixUsers() {
|
||||||
return (final HsBookingItemEntity entity, final IntegerProperty prop, final Integer factor) -> {
|
return (final HsBookingItemEntity entity, final IntegerProperty prop, final Integer factor) -> {
|
||||||
final var unixUserCount = entity.getSubHostingAssets().stream()
|
final var unixUserCount = entity.getSubHostingAssets().stream()
|
||||||
.filter(bi -> bi.getType() == UNIX_USER)
|
.flatMap(ha -> ha.getSubHostingAssets().stream())
|
||||||
|
.filter(ha -> ha.getType() == UNIX_USER)
|
||||||
.count();
|
.count();
|
||||||
final long limitingValue = prop.getValue(entity.getResources());
|
final long limitingValue = prop.getValue(entity.getResources());
|
||||||
if (unixUserCount > factor*limitingValue) {
|
if (unixUserCount > factor*limitingValue) {
|
||||||
@ -52,6 +53,7 @@ class HsManagedWebspaceBookingItemValidator extends HsBookingItemEntityValidator
|
|||||||
private static TriFunction<HsBookingItemEntity, IntegerProperty, Integer, List<String>> databaseUsers() {
|
private static TriFunction<HsBookingItemEntity, IntegerProperty, Integer, List<String>> databaseUsers() {
|
||||||
return (final HsBookingItemEntity entity, final IntegerProperty prop, final Integer factor) -> {
|
return (final HsBookingItemEntity entity, final IntegerProperty prop, final Integer factor) -> {
|
||||||
final var unixUserCount = entity.getSubHostingAssets().stream()
|
final var unixUserCount = entity.getSubHostingAssets().stream()
|
||||||
|
.flatMap(ha -> ha.getSubHostingAssets().stream())
|
||||||
.filter(bi -> bi.getType() == PGSQL_USER || bi.getType() == MARIADB_USER )
|
.filter(bi -> bi.getType() == PGSQL_USER || bi.getType() == MARIADB_USER )
|
||||||
.count();
|
.count();
|
||||||
final long limitingValue = prop.getValue(entity.getResources());
|
final long limitingValue = prop.getValue(entity.getResources());
|
||||||
@ -65,6 +67,7 @@ class HsManagedWebspaceBookingItemValidator extends HsBookingItemEntityValidator
|
|||||||
private static TriFunction<HsBookingItemEntity, IntegerProperty, Integer, List<String>> databases() {
|
private static TriFunction<HsBookingItemEntity, IntegerProperty, Integer, List<String>> databases() {
|
||||||
return (final HsBookingItemEntity entity, final IntegerProperty prop, final Integer factor) -> {
|
return (final HsBookingItemEntity entity, final IntegerProperty prop, final Integer factor) -> {
|
||||||
final var unixUserCount = entity.getSubHostingAssets().stream()
|
final var unixUserCount = entity.getSubHostingAssets().stream()
|
||||||
|
.flatMap(ha -> ha.getSubHostingAssets().stream())
|
||||||
.filter(bi -> bi.getType()==PGSQL_USER || bi.getType()==MARIADB_USER )
|
.filter(bi -> bi.getType()==PGSQL_USER || bi.getType()==MARIADB_USER )
|
||||||
.flatMap(domainEMailSetup -> domainEMailSetup.getSubHostingAssets().stream()
|
.flatMap(domainEMailSetup -> domainEMailSetup.getSubHostingAssets().stream()
|
||||||
.filter(ha -> ha.getType()==PGSQL_DATABASE || ha.getType()==MARIADB_DATABASE))
|
.filter(ha -> ha.getType()==PGSQL_DATABASE || ha.getType()==MARIADB_DATABASE))
|
||||||
@ -80,6 +83,7 @@ class HsManagedWebspaceBookingItemValidator extends HsBookingItemEntityValidator
|
|||||||
private static TriFunction<HsBookingItemEntity, IntegerProperty, Integer, List<String>> eMailAddresses() {
|
private static TriFunction<HsBookingItemEntity, IntegerProperty, Integer, List<String>> eMailAddresses() {
|
||||||
return (final HsBookingItemEntity entity, final IntegerProperty prop, final Integer factor) -> {
|
return (final HsBookingItemEntity entity, final IntegerProperty prop, final Integer factor) -> {
|
||||||
final var unixUserCount = entity.getSubHostingAssets().stream()
|
final var unixUserCount = entity.getSubHostingAssets().stream()
|
||||||
|
.flatMap(ha -> ha.getSubHostingAssets().stream())
|
||||||
.filter(bi -> bi.getType() == DOMAIN_EMAIL_SETUP)
|
.filter(bi -> bi.getType() == DOMAIN_EMAIL_SETUP)
|
||||||
.flatMap(domainEMailSetup -> domainEMailSetup.getSubHostingAssets().stream()
|
.flatMap(domainEMailSetup -> domainEMailSetup.getSubHostingAssets().stream()
|
||||||
.filter(ha -> ha.getType()==EMAIL_ADDRESS))
|
.filter(ha -> ha.getType()==EMAIL_ADDRESS))
|
||||||
|
@ -20,7 +20,7 @@ import java.util.List;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
import static net.hostsharing.hsadminng.hs.hosting.asset.validators.HsHostingAssetEntityValidator.valid;
|
import static net.hostsharing.hsadminng.hs.hosting.asset.validators.HsHostingAssetEntityValidator.validated;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
public class HsHostingAssetController implements HsHostingAssetsApi {
|
public class HsHostingAssetController implements HsHostingAssetsApi {
|
||||||
@ -62,7 +62,7 @@ public class HsHostingAssetController implements HsHostingAssetsApi {
|
|||||||
|
|
||||||
final var entityToSave = mapper.map(body, HsHostingAssetEntity.class, RESOURCE_TO_ENTITY_POSTMAPPER);
|
final var entityToSave = mapper.map(body, HsHostingAssetEntity.class, RESOURCE_TO_ENTITY_POSTMAPPER);
|
||||||
|
|
||||||
final var saved = assetRepo.save(valid(entityToSave));
|
final var saved = validated(assetRepo.save(entityToSave));
|
||||||
|
|
||||||
final var uri =
|
final var uri =
|
||||||
MvcUriComponentsBuilder.fromController(getClass())
|
MvcUriComponentsBuilder.fromController(getClass())
|
||||||
@ -117,7 +117,7 @@ public class HsHostingAssetController implements HsHostingAssetsApi {
|
|||||||
|
|
||||||
new HsHostingAssetEntityPatcher(current).apply(body);
|
new HsHostingAssetEntityPatcher(current).apply(body);
|
||||||
|
|
||||||
final var saved = assetRepo.save(valid(current));
|
final var saved = validated(assetRepo.save(current));
|
||||||
final var mapped = mapper.map(saved, HsHostingAssetResource.class);
|
final var mapped = mapper.map(saved, HsHostingAssetResource.class);
|
||||||
return ResponseEntity.ok(mapped);
|
return ResponseEntity.ok(mapped);
|
||||||
}
|
}
|
||||||
|
@ -5,15 +5,16 @@ import net.hostsharing.hsadminng.hs.booking.item.validators.HsBookingItemEntityV
|
|||||||
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity;
|
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity;
|
||||||
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType;
|
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType;
|
||||||
import net.hostsharing.hsadminng.hs.validation.HsEntityValidator;
|
import net.hostsharing.hsadminng.hs.validation.HsEntityValidator;
|
||||||
|
import net.hostsharing.hsadminng.hs.validation.MultiValidationException;
|
||||||
import net.hostsharing.hsadminng.hs.validation.ValidatableProperty;
|
import net.hostsharing.hsadminng.hs.validation.ValidatableProperty;
|
||||||
|
|
||||||
import jakarta.validation.ValidationException;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static java.lang.String.join;
|
||||||
import static java.util.Arrays.stream;
|
import static java.util.Arrays.stream;
|
||||||
import static java.util.Collections.emptyList;
|
import static java.util.Collections.emptyList;
|
||||||
import static java.util.Optional.ofNullable;
|
import static java.util.Optional.ofNullable;
|
||||||
@ -52,11 +53,8 @@ public class HsHostingAssetEntityValidator extends HsEntityValidator<HsHostingAs
|
|||||||
return HsHostingAssetEntityValidator.forType(hostingAsset.getType()).validate(hostingAsset);
|
return HsHostingAssetEntityValidator.forType(hostingAsset.getType()).validate(hostingAsset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static HsHostingAssetEntity valid(final HsHostingAssetEntity entityToSave) {
|
public static HsHostingAssetEntity validated(final HsHostingAssetEntity entityToSave) {
|
||||||
final var violations = doValidate(entityToSave);
|
MultiValidationException.throwInvalid(doValidate(entityToSave));
|
||||||
if (!violations.isEmpty()) {
|
|
||||||
throw new ValidationException(violations.toString());
|
|
||||||
}
|
|
||||||
return entityToSave;
|
return entityToSave;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ public class HsOfficeCoopAssetsTransactionController implements HsOfficeCoopAsse
|
|||||||
validateCreditTransaction(requestBody, violations);
|
validateCreditTransaction(requestBody, violations);
|
||||||
validateAssetValue(requestBody, violations);
|
validateAssetValue(requestBody, violations);
|
||||||
if (violations.size() > 0) {
|
if (violations.size() > 0) {
|
||||||
throw new ValidationException("[" + join(", ", violations) + "]");
|
throw new ValidationException("[" + join(",\n", violations) + "]"); // FIXME: move the join into an exception subclass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ public class HsOfficeCoopSharesTransactionController implements HsOfficeCoopShar
|
|||||||
validateCancellationTransaction(requestBody, violations);
|
validateCancellationTransaction(requestBody, violations);
|
||||||
validateshareCount(requestBody, violations);
|
validateshareCount(requestBody, violations);
|
||||||
if (violations.size() > 0) {
|
if (violations.size() > 0) {
|
||||||
throw new ValidationException("[" + join(", ", violations) + "]");
|
throw new ValidationException("[" + join(",\n", violations) + "]"); // FIXME: move the join into an exception subclass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
package net.hostsharing.hsadminng.hs.validation;
|
||||||
|
|
||||||
|
import jakarta.validation.ValidationException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static java.lang.String.join;
|
||||||
|
|
||||||
|
public class MultiValidationException extends ValidationException {
|
||||||
|
|
||||||
|
private MultiValidationException(final List<String> violations) {
|
||||||
|
super("[\n" + join(",\n", violations) + "\n]");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void throwInvalid(final List<String> violations) {
|
||||||
|
if (!violations.isEmpty()) {
|
||||||
|
throw new MultiValidationException(violations);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -8,14 +8,17 @@ import net.hostsharing.hsadminng.mapper.Array;
|
|||||||
import org.apache.commons.lang3.function.TriFunction;
|
import org.apache.commons.lang3.function.TriFunction;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import static java.lang.Boolean.FALSE;
|
import static java.lang.Boolean.FALSE;
|
||||||
import static java.lang.Boolean.TRUE;
|
import static java.lang.Boolean.TRUE;
|
||||||
|
import static java.util.Collections.emptyList;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public abstract class ValidatableProperty<T> {
|
public abstract class ValidatableProperty<T> {
|
||||||
@ -64,7 +67,7 @@ public abstract class ValidatableProperty<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isTotalsValidator() {
|
public boolean isTotalsValidator() {
|
||||||
return isTotalsValidator;
|
return isTotalsValidator || asTotalLimitValidators != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer thresholdPercentage() {
|
public Integer thresholdPercentage() {
|
||||||
@ -155,4 +158,20 @@ public abstract class ValidatableProperty<T> {
|
|||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<String> validateTotals(final HsBookingItemEntity bookingItem) {
|
||||||
|
if (asTotalLimitValidators==null) {
|
||||||
|
return emptyList();
|
||||||
|
}
|
||||||
|
return asTotalLimitValidators.stream()
|
||||||
|
.map(v -> v.apply(bookingItem))
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.flatMap(Collection::stream)
|
||||||
|
.map(v -> wrap(v))
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String wrap(final String v) {
|
||||||
|
return v;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,6 +62,8 @@ public class RbacGrantsDiagramService {
|
|||||||
@PersistenceContext
|
@PersistenceContext
|
||||||
private EntityManager em;
|
private EntityManager em;
|
||||||
|
|
||||||
|
private Map<UUID, List<RawRbacGrantEntity>> descendantsByUuid = new HashMap<>();
|
||||||
|
|
||||||
public String allGrantsToCurrentUser(final EnumSet<Include> includes) {
|
public String allGrantsToCurrentUser(final EnumSet<Include> includes) {
|
||||||
final var graph = new LimitedHashSet<RawRbacGrantEntity>();
|
final var graph = new LimitedHashSet<RawRbacGrantEntity>();
|
||||||
for ( UUID subjectUuid: context.currentSubjectsUuids() ) {
|
for ( UUID subjectUuid: context.currentSubjectsUuids() ) {
|
||||||
@ -102,7 +104,7 @@ public class RbacGrantsDiagramService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void traverseGrantsFrom(final Set<RawRbacGrantEntity> graph, final UUID refUuid, final EnumSet<Include> option) {
|
private void traverseGrantsFrom(final Set<RawRbacGrantEntity> graph, final UUID refUuid, final EnumSet<Include> option) {
|
||||||
final var grants = rawGrantRepo.findByDescendantUuid(refUuid);
|
final var grants = findDescendantsByUuid(refUuid);
|
||||||
grants.forEach(g -> {
|
grants.forEach(g -> {
|
||||||
if (!option.contains(USERS) && g.getAscendantIdName().startsWith("user:")) {
|
if (!option.contains(USERS) && g.getAscendantIdName().startsWith("user:")) {
|
||||||
return;
|
return;
|
||||||
@ -114,6 +116,11 @@ public class RbacGrantsDiagramService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<RawRbacGrantEntity> findDescendantsByUuid(final UUID refUuid) {
|
||||||
|
// TODO.impl: if that UUID already got processed, do we need to return anything at all?
|
||||||
|
return descendantsByUuid.computeIfAbsent(refUuid, uuid -> rawGrantRepo.findByDescendantUuid(uuid));
|
||||||
|
}
|
||||||
|
|
||||||
private String toMermaidFlowchart(final HashSet<RawRbacGrantEntity> graph, final EnumSet<Include> includes) {
|
private String toMermaidFlowchart(final HashSet<RawRbacGrantEntity> graph, final EnumSet<Include> includes) {
|
||||||
final var entities =
|
final var entities =
|
||||||
includes.contains(DETAILS)
|
includes.contains(DETAILS)
|
||||||
|
@ -33,13 +33,13 @@ begin
|
|||||||
managedServerUuid := uuid_generate_v4();
|
managedServerUuid := uuid_generate_v4();
|
||||||
insert
|
insert
|
||||||
into hs_booking_item (uuid, projectuuid, type, parentitemuuid, caption, validity, resources)
|
into hs_booking_item (uuid, projectuuid, type, parentitemuuid, caption, validity, resources)
|
||||||
values (privateCloudUuid, relatedProject.uuid, 'PRIVATE_CLOUD', null, 'some PrivateCloud', daterange('20240401', null, '[]'), '{ "CPUs": 10, "SDD": 10240, "HDD": 10240, "Traffic": 42 }'::jsonb),
|
values (privateCloudUuid, relatedProject.uuid, 'PRIVATE_CLOUD', null, 'some PrivateCloud', daterange('20240401', null, '[]'), '{ "CPUs": 10, "RAM": 32, "SSD": 4000, "HDD": 10000, "Traffic": 2000 }'::jsonb),
|
||||||
(uuid_generate_v4(), null, 'MANAGED_SERVER', privateCloudUuid, 'some ManagedServer', daterange('20230115', '20240415', '[)'), '{ "CPUs": 2, "RAM": 4, "HDD": 1024, "Traffic": 42 }'::jsonb),
|
(uuid_generate_v4(), null, 'MANAGED_SERVER', privateCloudUuid, 'some ManagedServer', daterange('20230115', '20240415', '[)'), '{ "CPUs": 2, "RAM": 4, "SSD": 500, "Traffic": 500 }'::jsonb),
|
||||||
(uuid_generate_v4(), null, 'CLOUD_SERVER', privateCloudUuid, 'test CloudServer', daterange('20230115', '20240415', '[)'), '{ "CPUs": 2, "RAM": 4, "HDD": 1024, "Traffic": 42 }'::jsonb),
|
(uuid_generate_v4(), null, 'CLOUD_SERVER', privateCloudUuid, 'test CloudServer', daterange('20230115', '20240415', '[)'), '{ "CPUs": 2, "RAM": 4, "SSD": 750, "Traffic": 500 }'::jsonb),
|
||||||
(uuid_generate_v4(), null, 'CLOUD_SERVER', privateCloudUuid, 'prod CloudServer', daterange('20230115', '20240415', '[)'), '{ "CPUs": 4, "RAM": 16, "HDD": 2924, "Traffic": 420 }'::jsonb),
|
(uuid_generate_v4(), null, 'CLOUD_SERVER', privateCloudUuid, 'prod CloudServer', daterange('20230115', '20240415', '[)'), '{ "CPUs": 4, "RAM": 16, "SSD": 1000, "Traffic": 500 }'::jsonb),
|
||||||
(managedServerUuid, relatedProject.uuid, 'MANAGED_SERVER', null, 'separate ManagedServer', daterange('20221001', null, '[]'), '{ "CPUs": 2, "RAM": 8, "SDD": 512, "Traffic": 42 }'::jsonb),
|
(managedServerUuid, relatedProject.uuid, 'MANAGED_SERVER', null, 'separate ManagedServer', daterange('20221001', null, '[]'), '{ "CPUs": 2, "RAM": 8, "SSD": 512, "Traffic": 500 }'::jsonb),
|
||||||
(uuid_generate_v4(), null, 'MANAGED_WEBSPACE', managedServerUuid, 'some ManagedWebspace', daterange('20221001', null, '[]'), '{ "SDD": 512, "Traffic": 12, "Daemons": 2, "Multi": 4 }'::jsonb),
|
(uuid_generate_v4(), null, 'MANAGED_WEBSPACE', managedServerUuid, 'some ManagedWebspace', daterange('20221001', null, '[]'), '{ "SSD": 512, "Traffic": 12, "Daemons": 2, "Multi": 4 }'::jsonb),
|
||||||
(uuid_generate_v4(), relatedProject.uuid, 'MANAGED_WEBSPACE', null, 'some ManagedWebspace', daterange('20221001', null, '[]'), '{ "SDD": 512, "Traffic": 12, "Daemons": 2, "Multi": 4 }'::jsonb);
|
(uuid_generate_v4(), relatedProject.uuid, 'MANAGED_WEBSPACE', null, 'some ManagedWebspace', daterange('20221001', null, '[]'), '{ "SSD": 512, "Traffic": 12, "Daemons": 2, "Multi": 4 }'::jsonb);
|
||||||
end; $$;
|
end; $$;
|
||||||
--//
|
--//
|
||||||
|
|
||||||
|
@ -56,9 +56,9 @@ begin
|
|||||||
|
|
||||||
insert into hs_hosting_asset
|
insert into hs_hosting_asset
|
||||||
(uuid, bookingitemuuid, type, parentAssetUuid, assignedToAssetUuid, identifier, caption, config)
|
(uuid, bookingitemuuid, type, parentAssetUuid, assignedToAssetUuid, identifier, caption, config)
|
||||||
values (managedServerUuid, relatedPrivateCloudBookingItem.uuid, 'MANAGED_SERVER', null, null, 'vm10' || debitorNumberSuffix, 'some ManagedServer', '{ "extra": 42 }'::jsonb),
|
values (managedServerUuid, relatedPrivateCloudBookingItem.uuid, 'MANAGED_SERVER', null, null, 'vm10' || debitorNumberSuffix, 'some ManagedServer', '{ "monit_max_cpu_usage": 90, "monit_max_ram_usage": 80, "monit_max_ssd_usage": 70 }'::jsonb),
|
||||||
(uuid_generate_v4(), relatedPrivateCloudBookingItem.uuid, 'CLOUD_SERVER', null, null, 'vm20' || debitorNumberSuffix, 'another CloudServer', '{ "extra": 42 }'::jsonb),
|
(uuid_generate_v4(), relatedPrivateCloudBookingItem.uuid, 'CLOUD_SERVER', null, null, 'vm20' || debitorNumberSuffix, 'another CloudServer', '{}'::jsonb),
|
||||||
(managedWebspaceUuid, relatedManagedServerBookingItem.uuid, 'MANAGED_WEBSPACE', managedServerUuid, null, defaultPrefix || '01', 'some Webspace', '{ "extra": 42 }'::jsonb),
|
(managedWebspaceUuid, relatedManagedServerBookingItem.uuid, 'MANAGED_WEBSPACE', managedServerUuid, null, defaultPrefix || '01', 'some Webspace', '{}'::jsonb),
|
||||||
(webUnixUserUuid, null, 'UNIX_USER', managedWebspaceUuid, null, defaultPrefix || '01-web', 'some UnixUser for Website', '{ "SSD-soft-quota": "128", "SSD-hard-quota": "256", "HDD-soft-quota": "512", "HDD-hard-quota": "1024", "extra": 42 }'::jsonb),
|
(webUnixUserUuid, null, 'UNIX_USER', managedWebspaceUuid, null, defaultPrefix || '01-web', 'some UnixUser for Website', '{ "SSD-soft-quota": "128", "SSD-hard-quota": "256", "HDD-soft-quota": "512", "HDD-hard-quota": "1024", "extra": 42 }'::jsonb),
|
||||||
(uuid_generate_v4(), null, 'DOMAIN_HTTP_SETUP', managedWebspaceUuid, webUnixUserUuid, defaultPrefix || '.example.org', 'some Domain-HTTP-Setup', '{ "option-htdocsfallback": true, "use-fcgiphpbin": "/usr/lib/cgi-bin/php", "validsubdomainnames": "*", "extra": 42 }'::jsonb);
|
(uuid_generate_v4(), null, 'DOMAIN_HTTP_SETUP', managedWebspaceUuid, webUnixUserUuid, defaultPrefix || '.example.org', 'some Domain-HTTP-Setup', '{ "option-htdocsfallback": true, "use-fcgiphpbin": "/usr/lib/cgi-bin/php", "validsubdomainnames": "*", "extra": 42 }'::jsonb);
|
||||||
end; $$;
|
end; $$;
|
||||||
|
@ -81,7 +81,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
"validFrom": "2022-10-01",
|
"validFrom": "2022-10-01",
|
||||||
"validTo": null,
|
"validTo": null,
|
||||||
"resources": {
|
"resources": {
|
||||||
"SDD": 512,
|
"SSD": 512,
|
||||||
"Multi": 4,
|
"Multi": 4,
|
||||||
"Daemons": 2,
|
"Daemons": 2,
|
||||||
"Traffic": 12
|
"Traffic": 12
|
||||||
@ -94,9 +94,9 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
"validTo": null,
|
"validTo": null,
|
||||||
"resources": {
|
"resources": {
|
||||||
"RAM": 8,
|
"RAM": 8,
|
||||||
"SDD": 512,
|
"SSD": 512,
|
||||||
"CPUs": 2,
|
"CPUs": 2,
|
||||||
"Traffic": 42
|
"Traffic": 500
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -105,10 +105,10 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
"validFrom": "2024-04-01",
|
"validFrom": "2024-04-01",
|
||||||
"validTo": null,
|
"validTo": null,
|
||||||
"resources": {
|
"resources": {
|
||||||
"HDD": 10240,
|
"SSD": 4000,
|
||||||
"SDD": 10240,
|
"HDD": 10000,
|
||||||
"CPUs": 10,
|
"CPUs": 10,
|
||||||
"Traffic": 42
|
"Traffic": 2000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -195,7 +195,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
"validFrom": "2022-10-01",
|
"validFrom": "2022-10-01",
|
||||||
"validTo": null,
|
"validTo": null,
|
||||||
"resources": {
|
"resources": {
|
||||||
"SDD": 512,
|
"SSD": 512,
|
||||||
"Multi": 4,
|
"Multi": 4,
|
||||||
"Daemons": 2,
|
"Daemons": 2,
|
||||||
"Traffic": 12
|
"Traffic": 12
|
||||||
@ -227,14 +227,16 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
void projectAdmin_canGetRelatedBookingItem() {
|
void projectAdmin_canGetRelatedBookingItem() {
|
||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
final var givenBookingItemUuid = bookingItemRepo.findByCaption("separate ManagedServer").stream()
|
final var givenBookingItemUuid = bookingItemRepo.findByCaption("separate ManagedServer").stream()
|
||||||
.filter(bi -> belongsToDebitorWithDefaultPrefix(bi, "thi"))
|
.filter(bi -> belongsToDebitorWithDefaultPrefix(bi, "sec"))
|
||||||
.map(HsBookingItemEntity::getUuid)
|
.map(HsBookingItemEntity::getUuid)
|
||||||
.findAny().orElseThrow();
|
.findAny().orElseThrow();
|
||||||
|
|
||||||
|
generateRbacDiagramForObjectPermission(givenBookingItemUuid, "SELECT", "select");
|
||||||
|
|
||||||
RestAssured // @formatter:off
|
RestAssured // @formatter:off
|
||||||
.given()
|
.given()
|
||||||
.header("current-user", "superuser-alex@hostsharing.net")
|
.header("current-user", "superuser-alex@hostsharing.net")
|
||||||
.header("assumed-roles", "hs_booking_project#D-1000313-D-1000313defaultproject:ADMIN")
|
.header("assumed-roles", "hs_booking_project#D-1000212-D-1000212defaultproject:ADMIN")
|
||||||
.port(port)
|
.port(port)
|
||||||
.when()
|
.when()
|
||||||
.get("http://localhost/api/hs/booking/items/" + givenBookingItemUuid)
|
.get("http://localhost/api/hs/booking/items/" + givenBookingItemUuid)
|
||||||
@ -249,9 +251,9 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
"validTo": null,
|
"validTo": null,
|
||||||
"resources": {
|
"resources": {
|
||||||
"RAM": 8,
|
"RAM": 8,
|
||||||
"SDD": 512,
|
"SSD": 512,
|
||||||
"CPUs": 2,
|
"CPUs": 2,
|
||||||
"Traffic": 42
|
"Traffic": 500
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""")); // @formatter:on
|
""")); // @formatter:on
|
||||||
@ -261,7 +263,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
return ofNullable(bi)
|
return ofNullable(bi)
|
||||||
.map(HsBookingItemEntity::getProject)
|
.map(HsBookingItemEntity::getProject)
|
||||||
.map(HsBookingProjectEntity::getDebitor)
|
.map(HsBookingProjectEntity::getDebitor)
|
||||||
.map(bd -> bd.getDefaultPrefix().equals(defaultPrefix))
|
.filter(bd -> bd.getDefaultPrefix().equals(defaultPrefix))
|
||||||
.isPresent();
|
.isPresent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,11 +44,11 @@ class HsBookingItemEntityPatcherUnitTest extends PatchUnitTestBase<
|
|||||||
private static final Map<String, Object> PATCH_RESOURCES = patchMap(
|
private static final Map<String, Object> PATCH_RESOURCES = patchMap(
|
||||||
entry("CPU", 2),
|
entry("CPU", 2),
|
||||||
entry("HDD", null),
|
entry("HDD", null),
|
||||||
entry("SDD", 256)
|
entry("SSD", 256)
|
||||||
);
|
);
|
||||||
private static final Map<String, Object> PATCHED_RESOURCES = patchMap(
|
private static final Map<String, Object> PATCHED_RESOURCES = patchMap(
|
||||||
entry("CPU", 2),
|
entry("CPU", 2),
|
||||||
entry("SDD", 256),
|
entry("SSD", 256),
|
||||||
entry("MEM", 64)
|
entry("MEM", 64)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -174,9 +174,9 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup
|
|||||||
// then
|
// then
|
||||||
allTheseBookingItemsAreReturned(
|
allTheseBookingItemsAreReturned(
|
||||||
result,
|
result,
|
||||||
"HsBookingItemEntity(D-1000212:D-1000212 default project, MANAGED_WEBSPACE, [2022-10-01,), some ManagedWebspace, { Daemons: 2, Multi: 4, SDD: 512, Traffic: 12 })",
|
"HsBookingItemEntity(D-1000212:D-1000212 default project, MANAGED_WEBSPACE, [2022-10-01,), some ManagedWebspace, { Daemons: 2, Multi: 4, SSD: 512, Traffic: 12 })",
|
||||||
"HsBookingItemEntity(D-1000212:D-1000212 default project, MANAGED_SERVER, [2022-10-01,), separate ManagedServer, { CPUs: 2, RAM: 8, SDD: 512, Traffic: 42 })",
|
"HsBookingItemEntity(D-1000212:D-1000212 default project, MANAGED_SERVER, [2022-10-01,), separate ManagedServer, { CPUs: 2, RAM: 8, SSD: 512, Traffic: 500 })",
|
||||||
"HsBookingItemEntity(D-1000212:D-1000212 default project, PRIVATE_CLOUD, [2024-04-01,), some PrivateCloud, { CPUs: 10, HDD: 10240, SDD: 10240, Traffic: 42 })");
|
"HsBookingItemEntity(D-1000212:D-1000212 default project, PRIVATE_CLOUD, [2024-04-01,), some PrivateCloud, { CPUs: 10, HDD: 10000, RAM: 32, SSD: 4000, Traffic: 2000 })");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -194,9 +194,9 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup
|
|||||||
// then:
|
// then:
|
||||||
exactlyTheseBookingItemsAreReturned(
|
exactlyTheseBookingItemsAreReturned(
|
||||||
result,
|
result,
|
||||||
"HsBookingItemEntity(D-1000111:D-1000111 default project, MANAGED_SERVER, [2022-10-01,), separate ManagedServer, { CPUs: 2, RAM: 8, SDD: 512, Traffic: 42 })",
|
"HsBookingItemEntity(D-1000111:D-1000111 default project, MANAGED_SERVER, [2022-10-01,), separate ManagedServer, { CPUs: 2, RAM: 8, SSD: 512, Traffic: 500 })",
|
||||||
"HsBookingItemEntity(D-1000111:D-1000111 default project, MANAGED_WEBSPACE, [2022-10-01,), some ManagedWebspace, { Daemons: 2, Multi: 4, SDD: 512, Traffic: 12 })",
|
"HsBookingItemEntity(D-1000111:D-1000111 default project, MANAGED_WEBSPACE, [2022-10-01,), some ManagedWebspace, { Daemons: 2, Multi: 4, SSD: 512, Traffic: 12 })",
|
||||||
"HsBookingItemEntity(D-1000111:D-1000111 default project, PRIVATE_CLOUD, [2024-04-01,), some PrivateCloud, { CPUs: 10, HDD: 10240, SDD: 10240, Traffic: 42 })");
|
"HsBookingItemEntity(D-1000111:D-1000111 default project, PRIVATE_CLOUD, [2024-04-01,), some PrivateCloud, { CPUs: 10, HDD: 10000, RAM: 32, SSD: 4000, Traffic: 2000 })");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.PRIVAT
|
|||||||
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.CLOUD_SERVER;
|
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.CLOUD_SERVER;
|
||||||
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.MANAGED_SERVER;
|
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.MANAGED_SERVER;
|
||||||
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.MANAGED_WEBSPACE;
|
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.MANAGED_WEBSPACE;
|
||||||
import static net.hostsharing.hsadminng.hs.booking.item.validators.HsBookingItemEntityValidator.valid;
|
import static net.hostsharing.hsadminng.hs.booking.item.validators.HsBookingItemEntityValidator.validated;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.catchThrowable;
|
import static org.assertj.core.api.Assertions.catchThrowable;
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ class HsBookingItemEntityValidatorUnitTest {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
// when
|
// when
|
||||||
final var result = catchThrowable( ()-> valid(cloudServerBookingItemEntity) );
|
final var result = catchThrowable( ()-> validated(cloudServerBookingItemEntity) );
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(result).isInstanceOf(ValidationException.class)
|
assertThat(result).isInstanceOf(ValidationException.class)
|
||||||
|
@ -3,15 +3,23 @@ package net.hostsharing.hsadminng.hs.booking.item.validators;
|
|||||||
import net.hostsharing.hsadminng.hs.booking.debitor.HsBookingDebitorEntity;
|
import net.hostsharing.hsadminng.hs.booking.debitor.HsBookingDebitorEntity;
|
||||||
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity;
|
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity;
|
||||||
import net.hostsharing.hsadminng.hs.booking.project.HsBookingProjectEntity;
|
import net.hostsharing.hsadminng.hs.booking.project.HsBookingProjectEntity;
|
||||||
|
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity;
|
||||||
|
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
import static java.util.Arrays.stream;
|
||||||
import static java.util.List.of;
|
import static java.util.List.of;
|
||||||
import static java.util.Map.entry;
|
import static java.util.Map.entry;
|
||||||
import static java.util.Map.ofEntries;
|
import static java.util.Map.ofEntries;
|
||||||
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.CLOUD_SERVER;
|
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.CLOUD_SERVER;
|
||||||
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.MANAGED_SERVER;
|
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.MANAGED_SERVER;
|
||||||
|
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.MANAGED_WEBSPACE;
|
||||||
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.PRIVATE_CLOUD;
|
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.PRIVATE_CLOUD;
|
||||||
import static net.hostsharing.hsadminng.hs.booking.item.validators.HsBookingItemEntityValidator.forType;
|
import static net.hostsharing.hsadminng.hs.booking.item.validators.HsBookingItemEntityValidator.forType;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
@ -119,4 +127,102 @@ class HsManagedServerBookingItemValidatorUnitTest {
|
|||||||
"D-12345:Test-Project:null.parentItem.total Traffic is 5500 GB exceeds max total Traffic 5000 GB"
|
"D-12345:Test-Project:null.parentItem.total Traffic is 5500 GB exceeds max total Traffic 5000 GB"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void validatesExceedingTotals() {
|
||||||
|
// given
|
||||||
|
final var managedWebspaceBookingItem = HsBookingItemEntity.builder()
|
||||||
|
.type(MANAGED_WEBSPACE)
|
||||||
|
.caption("test Managed-Webspace")
|
||||||
|
.resources(ofEntries(
|
||||||
|
entry("SSD", 100),
|
||||||
|
entry("Traffic", 1000),
|
||||||
|
entry("MultiOptions", 1)
|
||||||
|
))
|
||||||
|
.subHostingAssets(of(
|
||||||
|
HsHostingAssetEntity.builder()
|
||||||
|
.type(HsHostingAssetType.MANAGED_WEBSPACE)
|
||||||
|
.identifier("abc00")
|
||||||
|
.subHostingAssets(concat(
|
||||||
|
generate(26, HsHostingAssetType.UNIX_USER, "xyz00-%c%c"),
|
||||||
|
generateDbUsersWithDatabases(3, HsHostingAssetType.PGSQL_USER,
|
||||||
|
"xyz00_%c%c",
|
||||||
|
1, HsHostingAssetType.PGSQL_DATABASE
|
||||||
|
),
|
||||||
|
generateDbUsersWithDatabases(3, HsHostingAssetType.MARIADB_USER,
|
||||||
|
"xyz00_%c%c",
|
||||||
|
2, HsHostingAssetType.MARIADB_DATABASE
|
||||||
|
),
|
||||||
|
generateDomainEmailSetupsWithEMailAddresses(26, HsHostingAssetType.DOMAIN_EMAIL_SETUP,
|
||||||
|
"%c%c.example.com",
|
||||||
|
10, HsHostingAssetType.EMAIL_ADDRESS
|
||||||
|
)
|
||||||
|
))
|
||||||
|
.build()
|
||||||
|
))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// when
|
||||||
|
final var result = HsBookingItemEntityValidator.doValidate(managedWebspaceBookingItem);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(result).containsExactlyInAnyOrder(
|
||||||
|
"MultiOptions=1 allows at maximum 25 unix users, but 26 found",
|
||||||
|
"MultiOptions=1 allows at maximum 5 database users, but 6 found",
|
||||||
|
"MultiOptions=1 allows at maximum 5 databases, but 9 found",
|
||||||
|
"MultiOptions=1 allows at maximum 250 databases, but 260 found"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SafeVarargs
|
||||||
|
private List<HsHostingAssetEntity> concat(final List<HsHostingAssetEntity>... hostingAssets) {
|
||||||
|
return stream(hostingAssets)
|
||||||
|
.flatMap(Collection::stream)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<HsHostingAssetEntity> generate(final int count, final HsHostingAssetType hostingAssetType,
|
||||||
|
final String identifierPattern) {
|
||||||
|
return IntStream.range(0, count)
|
||||||
|
.mapToObj(number -> HsHostingAssetEntity.builder()
|
||||||
|
.type(hostingAssetType)
|
||||||
|
.identifier(identifierPattern.formatted((number/'a')+'a', (number%'a')+'a'))
|
||||||
|
.build())
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<HsHostingAssetEntity> generateDbUsersWithDatabases(
|
||||||
|
final int userCount,
|
||||||
|
final HsHostingAssetType directAssetType,
|
||||||
|
final String directAssetIdentifierFormat,
|
||||||
|
final int dbCount,
|
||||||
|
final HsHostingAssetType subAssetType) {
|
||||||
|
return IntStream.range(0, userCount)
|
||||||
|
.mapToObj(n -> HsHostingAssetEntity.builder()
|
||||||
|
.type(directAssetType)
|
||||||
|
.identifier(directAssetIdentifierFormat.formatted((n/'a')+'a', (n%'a')+'a'))
|
||||||
|
.subHostingAssets(
|
||||||
|
generate(dbCount, subAssetType, "%c%c.example.com".formatted((n/'a')+'a', (n%'a')+'a'))
|
||||||
|
)
|
||||||
|
.build())
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<HsHostingAssetEntity> generateDomainEmailSetupsWithEMailAddresses(
|
||||||
|
final int domainCount,
|
||||||
|
final HsHostingAssetType directAssetType,
|
||||||
|
final String directAssetIdentifierFormat,
|
||||||
|
final int emailAddressCount,
|
||||||
|
final HsHostingAssetType subAssetType) {
|
||||||
|
return IntStream.range(0, domainCount)
|
||||||
|
.mapToObj(n -> HsHostingAssetEntity.builder()
|
||||||
|
.type(directAssetType)
|
||||||
|
.identifier(directAssetIdentifierFormat.formatted((n/'a')+'a', (n%'a')+'a'))
|
||||||
|
.subHostingAssets(
|
||||||
|
generate(emailAddressCount, subAssetType, "xyz00_%c%c%%c%%c".formatted((n/'a')+'a', (n%'a')+'a'))
|
||||||
|
)
|
||||||
|
.build())
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,6 @@ class HsManagedWebspaceBookingItemValidatorUnitTest {
|
|||||||
.resources(Map.ofEntries(
|
.resources(Map.ofEntries(
|
||||||
entry("CPUs", 2),
|
entry("CPUs", 2),
|
||||||
entry("RAM", 25),
|
entry("RAM", 25),
|
||||||
entry("SSD", 25),
|
|
||||||
entry("Traffic", 250),
|
entry("Traffic", 250),
|
||||||
entry("SLA-EMail", true)
|
entry("SLA-EMail", true)
|
||||||
))
|
))
|
||||||
@ -42,10 +41,11 @@ class HsManagedWebspaceBookingItemValidatorUnitTest {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(result).containsExactlyInAnyOrder(
|
assertThat(result).containsExactlyInAnyOrder(
|
||||||
"D-12345:Test-Project:Test Managed-Webspace.resources.SLA-EMail is not expected but is set to 'true'",
|
|
||||||
"D-12345:Test-Project:Test Managed-Webspace.resources.CPUs is not expected but is set to '2'",
|
"D-12345:Test-Project:Test Managed-Webspace.resources.CPUs is not expected but is set to '2'",
|
||||||
"D-12345:Test-Project:Test Managed-Webspace.resources.RAM is not expected but is set to '25'",
|
"D-12345:Test-Project:Test Managed-Webspace.resources.RAM is not expected but is set to '25'",
|
||||||
"D-12345:Test-Project:Test Managed-Webspace.resources.MultiOptions is required but missing");
|
"D-12345:Test-Project:Test Managed-Webspace.resources.SSD is required but missing",
|
||||||
|
"D-12345:Test-Project:Test Managed-Webspace.resources.SLA-EMail is not expected but is set to 'true'"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -58,9 +58,9 @@ class HsManagedWebspaceBookingItemValidatorUnitTest {
|
|||||||
"{type=integer, propertyName=SSD, unit=GB, min=1, max=100, step=1, required=true, isTotalsValidator=false}",
|
"{type=integer, propertyName=SSD, unit=GB, min=1, max=100, step=1, required=true, isTotalsValidator=false}",
|
||||||
"{type=integer, propertyName=HDD, unit=GB, min=0, max=250, step=10, required=false, isTotalsValidator=false}",
|
"{type=integer, propertyName=HDD, unit=GB, min=0, max=250, step=10, required=false, isTotalsValidator=false}",
|
||||||
"{type=integer, propertyName=Traffic, unit=GB, min=10, max=1000, step=10, required=true, isTotalsValidator=false}",
|
"{type=integer, propertyName=Traffic, unit=GB, min=10, max=1000, step=10, required=true, isTotalsValidator=false}",
|
||||||
"{type=integer, propertyName=MultiOptions, min=1, max=100, step=1, required=true, isTotalsValidator=false}",
|
"{type=integer, propertyName=MultiOptions, min=1, max=100, step=1, required=false, defaultValue=1, isTotalsValidator=false}",
|
||||||
"{type=integer, propertyName=Daemons, min=0, max=10, required=false, isTotalsValidator=false}",
|
"{type=integer, propertyName=Daemons, min=0, max=10, required=false, defaultValue=0, isTotalsValidator=false}",
|
||||||
"{type=boolean, propertyName=Online Office Server, required=false, isTotalsValidator=false}",
|
"{type=boolean, propertyName=Online Office Server, required=false, isTotalsValidator=false}",
|
||||||
"{type=enumeration, propertyName=SLA-Platform, values=[BASIC, EXT24H], required=false, isTotalsValidator=false}");
|
"{type=enumeration, propertyName=SLA-Platform, values=[BASIC, EXT24H], required=false, defaultValue=BASIC, isTotalsValidator=false}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,25 +76,19 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
"type": "MANAGED_WEBSPACE",
|
"type": "MANAGED_WEBSPACE",
|
||||||
"identifier": "sec01",
|
"identifier": "sec01",
|
||||||
"caption": "some Webspace",
|
"caption": "some Webspace",
|
||||||
"config": {
|
"config": {}
|
||||||
"extra": 42
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "MANAGED_WEBSPACE",
|
"type": "MANAGED_WEBSPACE",
|
||||||
"identifier": "fir01",
|
"identifier": "fir01",
|
||||||
"caption": "some Webspace",
|
"caption": "some Webspace",
|
||||||
"config": {
|
"config": {}
|
||||||
"extra": 42
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "MANAGED_WEBSPACE",
|
"type": "MANAGED_WEBSPACE",
|
||||||
"identifier": "thi01",
|
"identifier": "thi01",
|
||||||
"caption": "some Webspace",
|
"caption": "some Webspace",
|
||||||
"config": {
|
"config": {}
|
||||||
"extra": 42
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
"""));
|
"""));
|
||||||
@ -123,7 +117,9 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
"identifier": "vm1011",
|
"identifier": "vm1011",
|
||||||
"caption": "some ManagedServer",
|
"caption": "some ManagedServer",
|
||||||
"config": {
|
"config": {
|
||||||
"extra": 42
|
"monit_max_cpu_usage": 90,
|
||||||
|
"monit_max_ram_usage": 80,
|
||||||
|
"monit_max_ssd_usage": 70
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -131,7 +127,9 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
"identifier": "vm1012",
|
"identifier": "vm1012",
|
||||||
"caption": "some ManagedServer",
|
"caption": "some ManagedServer",
|
||||||
"config": {
|
"config": {
|
||||||
"extra": 42
|
"monit_max_cpu_usage": 90,
|
||||||
|
"monit_max_ram_usage": 80,
|
||||||
|
"monit_max_ssd_usage": 70
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -139,7 +137,9 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
"identifier": "vm1013",
|
"identifier": "vm1013",
|
||||||
"caption": "some ManagedServer",
|
"caption": "some ManagedServer",
|
||||||
"config": {
|
"config": {
|
||||||
"extra": 42
|
"monit_max_cpu_usage": 90,
|
||||||
|
"monit_max_ram_usage": 80,
|
||||||
|
"monit_max_ssd_usage": 70
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -266,9 +266,14 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
.body("", lenientlyEquals("""
|
.body("", lenientlyEquals("""
|
||||||
{
|
{
|
||||||
"statusPhrase": "Bad Request",
|
"statusPhrase": "Bad Request",
|
||||||
"message": "['config.extra' is not expected but is set to '42', 'config.monit_max_ssd_usage' is expected to be >= 10 but is 0, 'config.monit_max_cpu_usage' is expected to be <= 100 but is 101, 'config.monit_max_ram_usage' is required but missing]"
|
"message": "[
|
||||||
|
<<<MANAGED_SERVER:vm1400.config.extra is not expected but is set to '42',
|
||||||
|
<<<MANAGED_SERVER:vm1400.config.monit_max_ssd_usage is expected to be >= 10 but is 0,
|
||||||
|
<<<MANAGED_SERVER:vm1400.config.monit_max_cpu_usage is expected to be <= 100 but is 101,
|
||||||
|
<<<MANAGED_SERVER:vm1400.config.monit_max_ram_usage is required but missing
|
||||||
|
<<<]"
|
||||||
}
|
}
|
||||||
""")); // @formatter:on
|
""".replaceAll(" +<<<", ""))); // @formatter:on
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,9 +299,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
.body("", lenientlyEquals("""
|
.body("", lenientlyEquals("""
|
||||||
{
|
{
|
||||||
"caption": "some ManagedServer",
|
"caption": "some ManagedServer",
|
||||||
"config": {
|
"config": {}
|
||||||
"extra": 42
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
""")); // @formatter:on
|
""")); // @formatter:on
|
||||||
}
|
}
|
||||||
@ -339,9 +342,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
{
|
{
|
||||||
"identifier": "vm1013",
|
"identifier": "vm1013",
|
||||||
"caption": "some ManagedServer",
|
"caption": "some ManagedServer",
|
||||||
"config": {
|
"config": {}
|
||||||
"extra": 42
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
""")); // @formatter:on
|
""")); // @formatter:on
|
||||||
}
|
}
|
||||||
|
@ -40,11 +40,11 @@ class HsHostingAssetEntityPatcherUnitTest extends PatchUnitTestBase<
|
|||||||
private static final Map<String, Object> PATCH_CONFIG = patchMap(
|
private static final Map<String, Object> PATCH_CONFIG = patchMap(
|
||||||
entry("CPU", 2),
|
entry("CPU", 2),
|
||||||
entry("HDD", null),
|
entry("HDD", null),
|
||||||
entry("SDD", 256)
|
entry("SSD", 256)
|
||||||
);
|
);
|
||||||
private static final Map<String, Object> PATCHED_CONFIG = patchMap(
|
private static final Map<String, Object> PATCHED_CONFIG = patchMap(
|
||||||
entry("CPU", 2),
|
entry("CPU", 2),
|
||||||
entry("SDD", 256),
|
entry("SSD", 256),
|
||||||
entry("MEM", 64)
|
entry("MEM", 64)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -55,56 +55,54 @@ class HsHostingAssetPropsControllerAcceptanceTest {
|
|||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"propertyName": "monit_min_free_ssd",
|
"propertyName": "monit_min_free_ssd",
|
||||||
"required": false,
|
|
||||||
"unit": null,
|
|
||||||
"min": 1,
|
"min": 1,
|
||||||
"max": 1000,
|
"max": 1000,
|
||||||
"step": null
|
"required": false,
|
||||||
|
"isTotalsValidator": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"propertyName": "monit_min_free_hdd",
|
"propertyName": "monit_min_free_hdd",
|
||||||
"required": false,
|
|
||||||
"unit": null,
|
|
||||||
"min": 1,
|
"min": 1,
|
||||||
"max": 4000,
|
"max": 4000,
|
||||||
"step": null
|
"required": false,
|
||||||
|
"isTotalsValidator": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"propertyName": "monit_max_ssd_usage",
|
"propertyName": "monit_max_ssd_usage",
|
||||||
"required": true,
|
|
||||||
"unit": "%",
|
"unit": "%",
|
||||||
"min": 10,
|
"min": 10,
|
||||||
"max": 100,
|
"max": 100,
|
||||||
"step": null
|
"required": true,
|
||||||
|
"isTotalsValidator": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"propertyName": "monit_max_hdd_usage",
|
"propertyName": "monit_max_hdd_usage",
|
||||||
"required": false,
|
|
||||||
"unit": "%",
|
"unit": "%",
|
||||||
"min": 10,
|
"min": 10,
|
||||||
"max": 100,
|
"max": 100,
|
||||||
"step": null
|
"required": false,
|
||||||
|
"isTotalsValidator": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"propertyName": "monit_max_cpu_usage",
|
"propertyName": "monit_max_cpu_usage",
|
||||||
"required": true,
|
|
||||||
"unit": "%",
|
"unit": "%",
|
||||||
"min": 10,
|
"min": 10,
|
||||||
"max": 100,
|
"max": 100,
|
||||||
"step": null
|
"required": true,
|
||||||
|
"isTotalsValidator": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"propertyName": "monit_max_ram_usage",
|
"propertyName": "monit_max_ram_usage",
|
||||||
"required": true,
|
|
||||||
"unit": "%",
|
"unit": "%",
|
||||||
"min": 10,
|
"min": 10,
|
||||||
"max": 100,
|
"max": 100,
|
||||||
"step": null
|
"required": true,
|
||||||
|
"isTotalsValidator": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
"""));
|
"""));
|
||||||
|
@ -164,9 +164,9 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu
|
|||||||
// then
|
// then
|
||||||
allTheseServersAreReturned(
|
allTheseServersAreReturned(
|
||||||
result,
|
result,
|
||||||
"HsHostingAssetEntity(MANAGED_WEBSPACE, sec01, some Webspace, MANAGED_SERVER:vm1012, D-1000212:D-1000212 default project:separate ManagedServer, { extra: 42 })",
|
"HsHostingAssetEntity(MANAGED_WEBSPACE, sec01, some Webspace, MANAGED_SERVER:vm1012, D-1000212:D-1000212 default project:separate ManagedServer)",
|
||||||
"HsHostingAssetEntity(MANAGED_WEBSPACE, thi01, some Webspace, MANAGED_SERVER:vm1013, D-1000313:D-1000313 default project:separate ManagedServer, { extra: 42 })",
|
"HsHostingAssetEntity(MANAGED_WEBSPACE, thi01, some Webspace, MANAGED_SERVER:vm1013, D-1000313:D-1000313 default project:separate ManagedServer)",
|
||||||
"HsHostingAssetEntity(MANAGED_WEBSPACE, fir01, some Webspace, MANAGED_SERVER:vm1011, D-1000111:D-1000111 default project:separate ManagedServer, { extra: 42 })");
|
"HsHostingAssetEntity(MANAGED_WEBSPACE, fir01, some Webspace, MANAGED_SERVER:vm1011, D-1000111:D-1000111 default project:separate ManagedServer)");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -182,9 +182,9 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu
|
|||||||
// then:
|
// then:
|
||||||
exactlyTheseAssetsAreReturned(
|
exactlyTheseAssetsAreReturned(
|
||||||
result,
|
result,
|
||||||
"HsHostingAssetEntity(MANAGED_WEBSPACE, fir01, some Webspace, MANAGED_SERVER:vm1011, D-1000111:D-1000111 default project:separate ManagedServer, { extra: 42 })",
|
"HsHostingAssetEntity(MANAGED_WEBSPACE, fir01, some Webspace, MANAGED_SERVER:vm1011, D-1000111:D-1000111 default project:separate ManagedServer)",
|
||||||
"HsHostingAssetEntity(MANAGED_SERVER, vm1011, some ManagedServer, D-1000111:D-1000111 default project:some PrivateCloud, { extra: 42 })",
|
"HsHostingAssetEntity(MANAGED_SERVER, vm1011, some ManagedServer, D-1000111:D-1000111 default project:some PrivateCloud, { monit_max_cpu_usage: 90, monit_max_ram_usage: 80, monit_max_ssd_usage: 70 })",
|
||||||
"HsHostingAssetEntity(CLOUD_SERVER, vm2011, another CloudServer, D-1000111:D-1000111 default project:some PrivateCloud, { extra: 42 })");
|
"HsHostingAssetEntity(CLOUD_SERVER, vm2011, another CloudServer, D-1000111:D-1000111 default project:some PrivateCloud)");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -200,7 +200,7 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu
|
|||||||
// then
|
// then
|
||||||
allTheseServersAreReturned(
|
allTheseServersAreReturned(
|
||||||
result,
|
result,
|
||||||
"HsHostingAssetEntity(MANAGED_WEBSPACE, thi01, some Webspace, MANAGED_SERVER:vm1013, D-1000313:D-1000313 default project:separate ManagedServer, { extra: 42 })");
|
"HsHostingAssetEntity(MANAGED_WEBSPACE, thi01, some Webspace, MANAGED_SERVER:vm1013, D-1000313:D-1000313 default project:separate ManagedServer)");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ import org.junit.jupiter.api.Test;
|
|||||||
import jakarta.validation.ValidationException;
|
import jakarta.validation.ValidationException;
|
||||||
|
|
||||||
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_SERVER;
|
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_SERVER;
|
||||||
import static net.hostsharing.hsadminng.hs.hosting.asset.validators.HsHostingAssetEntityValidator.valid;
|
import static net.hostsharing.hsadminng.hs.hosting.asset.validators.HsHostingAssetEntityValidator.validated;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.catchThrowable;
|
import static org.assertj.core.api.Assertions.catchThrowable;
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ class HsHostingAssetEntityValidatorUnitTest {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
// when
|
// when
|
||||||
final var result = catchThrowable( ()-> valid(managedServerHostingAssetEntity) );
|
final var result = catchThrowable( ()-> validated(managedServerHostingAssetEntity) );
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(result).isInstanceOf(ValidationException.class)
|
assertThat(result).isInstanceOf(ValidationException.class)
|
||||||
|
Loading…
Reference in New Issue
Block a user