hierarchical-validation-baseline #59
@ -111,12 +111,10 @@ 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
|
||||||
|
@ -67,7 +67,7 @@ public class HsBookingItemEntityValidator extends HsEntityValidator<HsBookingIte
|
|||||||
return sequentiallyValidate(
|
return sequentiallyValidate(
|
||||||
() -> enrich(prefix(bookingItem.toShortString(), "resources"), validateProperties(bookingItem.getResources())),
|
() -> enrich(prefix(bookingItem.toShortString(), "resources"), validateProperties(bookingItem.getResources())),
|
||||||
() -> enrich(prefix(bookingItem.toShortString(), "parentItem"), optionallyValidate(bookingItem.getParentItem())),
|
() -> enrich(prefix(bookingItem.toShortString(), "parentItem"), optionallyValidate(bookingItem.getParentItem())),
|
||||||
() -> validateSubEntities(bookingItem)
|
() -> validateAgainstSubEntities(bookingItem)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ public class HsBookingItemEntityValidator extends HsEntityValidator<HsBookingIte
|
|||||||
return bookingItem != null ? HsBookingItemEntityValidator.doValidate(bookingItem) : emptyList();
|
return bookingItem != null ? HsBookingItemEntityValidator.doValidate(bookingItem) : emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List<String> validateSubEntities(final HsBookingItemEntity bookingItem) {
|
protected List<String> validateAgainstSubEntities(final HsBookingItemEntity bookingItem) {
|
||||||
return Stream.concat(
|
return Stream.concat(
|
||||||
stream(propertyValidators)
|
stream(propertyValidators)
|
||||||
.map(propDef -> propDef.validateTotals(bookingItem))
|
.map(propDef -> propDef.validateTotals(bookingItem))
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package net.hostsharing.hsadminng.hs.booking.item.validators;
|
package net.hostsharing.hsadminng.hs.booking.item.validators;
|
||||||
|
|
||||||
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static net.hostsharing.hsadminng.hs.validation.BooleanProperty.booleanProperty;
|
import static net.hostsharing.hsadminng.hs.validation.BooleanProperty.booleanProperty;
|
||||||
import static net.hostsharing.hsadminng.hs.validation.EnumerationProperty.enumerationProperty;
|
import static net.hostsharing.hsadminng.hs.validation.EnumerationProperty.enumerationProperty;
|
||||||
@ -25,11 +23,4 @@ class HsManagedServerBookingItemValidator extends HsBookingItemEntityValidator {
|
|||||||
booleanProperty("SLA-Web").falseIf("SLA-Platform", "BASIC").optional()
|
booleanProperty("SLA-Web").falseIf("SLA-Platform", "BASIC").optional()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<String> validate(final HsBookingItemEntity managedServerBookingItem) {
|
|
||||||
final var selfValidation = super.validate(managedServerBookingItem);
|
|
||||||
return !selfValidation.isEmpty() ? selfValidation : validateParentEntities(managedServerBookingItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ 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).withDefault(1)
|
integerProperty("Multi").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())
|
||||||
|
@ -14,13 +14,10 @@ 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;
|
||||||
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.CLOUD_SERVER;
|
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.*;
|
||||||
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_SERVER;
|
|
||||||
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_WEBSPACE;
|
|
||||||
|
|
||||||
public class HsHostingAssetEntityValidator extends HsEntityValidator<HsHostingAssetEntity> {
|
public class HsHostingAssetEntityValidator extends HsEntityValidator<HsHostingAssetEntity> {
|
||||||
|
|
||||||
@ -29,6 +26,7 @@ public class HsHostingAssetEntityValidator extends HsEntityValidator<HsHostingAs
|
|||||||
register(CLOUD_SERVER, new HsHostingAssetEntityValidator());
|
register(CLOUD_SERVER, new HsHostingAssetEntityValidator());
|
||||||
register(MANAGED_SERVER, new HsManagedServerHostingAssetValidator());
|
register(MANAGED_SERVER, new HsManagedServerHostingAssetValidator());
|
||||||
register(MANAGED_WEBSPACE, new HsManagedWebspaceHostingAssetValidator());
|
register(MANAGED_WEBSPACE, new HsManagedWebspaceHostingAssetValidator());
|
||||||
|
register(UNIX_USER, new HsHostingAssetEntityValidator());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void register(final Enum<HsHostingAssetType> type, final HsEntityValidator<HsHostingAssetEntity> validator) {
|
private static void register(final Enum<HsHostingAssetType> type, final HsEntityValidator<HsHostingAssetEntity> validator) {
|
||||||
|
@ -2,8 +2,11 @@ package net.hostsharing.hsadminng.hs.hosting.asset.validators;
|
|||||||
|
|
||||||
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity;
|
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
class HsManagedWebspaceHostingAssetValidator extends HsHostingAssetEntityValidator {
|
class HsManagedWebspaceHostingAssetValidator extends HsHostingAssetEntityValidator {
|
||||||
public HsManagedWebspaceHostingAssetValidator() {
|
public HsManagedWebspaceHostingAssetValidator() {
|
||||||
@ -11,16 +14,16 @@ class HsManagedWebspaceHostingAssetValidator extends HsHostingAssetEntityValidat
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> validate(final HsHostingAssetEntity assetEntity) {
|
public List<String> validate(final HsHostingAssetEntity assetEntity) {
|
||||||
final var result = super.validate(assetEntity);
|
return Stream.of(validateIdentifierPattern(assetEntity), super.validate(assetEntity))
|
||||||
validateIdentifierPattern(result, assetEntity);
|
.flatMap(Collection::stream)
|
||||||
|
.collect(Collectors.toList());
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void validateIdentifierPattern(final List<String> result, final HsHostingAssetEntity assetEntity) {
|
private static List<String> validateIdentifierPattern(final HsHostingAssetEntity assetEntity) {
|
||||||
final var expectedIdentifierPattern = "^" + assetEntity.getParentAsset().getBookingItem().getProject().getDebitor().getDefaultPrefix() + "[0-9][0-9]$";
|
final var expectedIdentifierPattern = "^" + assetEntity.getParentAsset().getBookingItem().getProject().getDebitor().getDefaultPrefix() + "[0-9][0-9]$";
|
||||||
if ( !assetEntity.getIdentifier().matches(expectedIdentifierPattern)) {
|
if ( !assetEntity.getIdentifier().matches(expectedIdentifierPattern)) {
|
||||||
result.add("'identifier' expected to match '"+expectedIdentifierPattern+"', but is '" + assetEntity.getIdentifier() + "'");
|
return List.of("'identifier' expected to match '"+expectedIdentifierPattern+"', but is '" + assetEntity.getIdentifier() + "'");
|
||||||
}
|
}
|
||||||
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -167,11 +167,6 @@ public abstract class ValidatableProperty<T> {
|
|||||||
.map(v -> v.apply(bookingItem))
|
.map(v -> v.apply(bookingItem))
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.flatMap(Collection::stream)
|
.flatMap(Collection::stream)
|
||||||
.map(v -> wrap(v))
|
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String wrap(final String v) {
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -37,9 +37,9 @@ begin
|
|||||||
(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, '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, "SSD": 750, "Traffic": 500 }'::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, "SSD": 1000, "Traffic": 500 }'::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, "SSD": 512, "Traffic": 500 }'::jsonb),
|
(managedServerUuid, relatedProject.uuid, 'MANAGED_SERVER', null, 'separate ManagedServer', daterange('20221001', null, '[]'), '{ "CPUs": 2, "RAM": 8, "SSD": 500, "Traffic": 500 }'::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(), null, 'MANAGED_WEBSPACE', managedServerUuid, 'some ManagedWebspace', daterange('20221001', null, '[]'), '{ "SSD": 50, "Traffic": 20, "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);
|
(uuid_generate_v4(), relatedProject.uuid, 'MANAGED_WEBSPACE', null, 'separate ManagedWebspace', daterange('20221001', null, '[]'), '{ "SSD": 100, "Traffic": 50, "Daemons": 0, "Multi": 1 }'::jsonb);
|
||||||
end; $$;
|
end; $$;
|
||||||
--//
|
--//
|
||||||
|
|
||||||
|
@ -75,10 +75,10 @@ begin
|
|||||||
end);
|
end);
|
||||||
|
|
||||||
if expectedParentType is not null and actualParentType is null then
|
if expectedParentType is not null and actualParentType is null then
|
||||||
raise exception '[400] % must have % as parent, but got <NULL>',
|
raise exception '[400] HostingAsset % must have % as parent, but got <NULL>',
|
||||||
NEW.type, expectedParentType;
|
NEW.type, expectedParentType;
|
||||||
elsif expectedParentType is not null and actualParentType <> expectedParentType then
|
elsif expectedParentType is not null and actualParentType <> expectedParentType then
|
||||||
raise exception '[400] % must have % as parent, but got %s',
|
raise exception '[400] HostingAsset % must have % as parent, but got %s',
|
||||||
NEW.type, expectedParentType, actualParentType;
|
NEW.type, expectedParentType, actualParentType;
|
||||||
end if;
|
end if;
|
||||||
return NEW;
|
return NEW;
|
||||||
@ -100,27 +100,23 @@ create or replace function hs_hosting_asset_booking_item_hierarchy_check_tf()
|
|||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
declare
|
declare
|
||||||
actualBookingItemType HsBookingItemType;
|
actualBookingItemType HsBookingItemType;
|
||||||
expectedBookingItemTypes HsBookingItemType[];
|
expectedBookingItemType HsBookingItemType;
|
||||||
begin
|
begin
|
||||||
actualBookingItemType := (select type
|
actualBookingItemType := (select type
|
||||||
from hs_booking_item
|
from hs_booking_item
|
||||||
where NEW.bookingItemUuid = uuid);
|
where NEW.bookingItemUuid = uuid);
|
||||||
|
|
||||||
if NEW.type = 'CLOUD_SERVER' then
|
if NEW.type = 'CLOUD_SERVER' then
|
||||||
expectedBookingItemTypes := ARRAY['PRIVATE_CLOUD', 'CLOUD_SERVER'];
|
expectedBookingItemType := 'CLOUD_SERVER';
|
||||||
elsif NEW.type = 'MANAGED_SERVER' then
|
elsif NEW.type = 'MANAGED_SERVER' then
|
||||||
expectedBookingItemTypes := ARRAY['PRIVATE_CLOUD', 'MANAGED_SERVER'];
|
expectedBookingItemType := 'MANAGED_SERVER';
|
||||||
elsif NEW.type = 'MANAGED_WEBSPACE' then
|
elsif NEW.type = 'MANAGED_WEBSPACE' then
|
||||||
if NEW.parentAssetUuid is null then
|
expectedBookingItemType := 'MANAGED_WEBSPACE';
|
||||||
expectedBookingItemTypes := ARRAY['MANAGED_WEBSPACE'];
|
|
||||||
else
|
|
||||||
expectedBookingItemTypes := ARRAY['PRIVATE_CLOUD', 'MANAGED_SERVER'];
|
|
||||||
end if;
|
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
if not actualBookingItemType = any(expectedBookingItemTypes) then
|
if not actualBookingItemType = expectedBookingItemType then
|
||||||
raise exception '[400] % % must have any of % as booking-item, but got %',
|
raise exception '[400] HostingAsset % % must have % as booking-item, but got %',
|
||||||
NEW.type, NEW.identifier, expectedBookingItemTypes, actualBookingItemType;
|
NEW.type, NEW.identifier, expectedBookingItemType, actualBookingItemType;
|
||||||
end if;
|
end if;
|
||||||
return NEW;
|
return NEW;
|
||||||
end; $$;
|
end; $$;
|
||||||
|
@ -11,16 +11,18 @@
|
|||||||
create or replace procedure createHsHostingAssetTestData(givenProjectCaption varchar)
|
create or replace procedure createHsHostingAssetTestData(givenProjectCaption varchar)
|
||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
declare
|
declare
|
||||||
currentTask varchar;
|
currentTask varchar;
|
||||||
relatedProject hs_booking_project;
|
relatedProject hs_booking_project;
|
||||||
relatedDebitor hs_office_debitor;
|
relatedDebitor hs_office_debitor;
|
||||||
relatedPrivateCloudBookingItem hs_booking_item;
|
relatedPrivateCloudBookingItem hs_booking_item;
|
||||||
relatedManagedServerBookingItem hs_booking_item;
|
relatedManagedServerBookingItem hs_booking_item;
|
||||||
debitorNumberSuffix varchar;
|
relatedCloudServerBookingItem hs_booking_item;
|
||||||
defaultPrefix varchar;
|
relatedManagedWebspaceBookingItem hs_booking_item;
|
||||||
managedServerUuid uuid;
|
debitorNumberSuffix varchar;
|
||||||
managedWebspaceUuid uuid;
|
defaultPrefix varchar;
|
||||||
webUnixUserUuid uuid;
|
managedServerUuid uuid;
|
||||||
|
managedWebspaceUuid uuid;
|
||||||
|
webUnixUserUuid uuid;
|
||||||
begin
|
begin
|
||||||
currentTask := 'creating hosting-asset test-data ' || givenProjectCaption;
|
currentTask := 'creating hosting-asset test-data ' || givenProjectCaption;
|
||||||
call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN');
|
call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN');
|
||||||
@ -38,7 +40,7 @@ begin
|
|||||||
|
|
||||||
select item.* into relatedPrivateCloudBookingItem
|
select item.* into relatedPrivateCloudBookingItem
|
||||||
from hs_booking_item item
|
from hs_booking_item item
|
||||||
where item.projectUuid = relatedProject.uuid
|
where item.projectUuid = relatedProject.uuid
|
||||||
and item.type = 'PRIVATE_CLOUD';
|
and item.type = 'PRIVATE_CLOUD';
|
||||||
assert relatedPrivateCloudBookingItem.uuid is not null, 'relatedPrivateCloudBookingItem for "' || givenProjectCaption|| '" must not be null';
|
assert relatedPrivateCloudBookingItem.uuid is not null, 'relatedPrivateCloudBookingItem for "' || givenProjectCaption|| '" must not be null';
|
||||||
|
|
||||||
@ -48,6 +50,18 @@ begin
|
|||||||
and item.type = 'MANAGED_SERVER';
|
and item.type = 'MANAGED_SERVER';
|
||||||
assert relatedManagedServerBookingItem.uuid is not null, 'relatedManagedServerBookingItem for "' || givenProjectCaption|| '" must not be null';
|
assert relatedManagedServerBookingItem.uuid is not null, 'relatedManagedServerBookingItem for "' || givenProjectCaption|| '" must not be null';
|
||||||
|
|
||||||
|
select item.* into relatedCloudServerBookingItem
|
||||||
|
from hs_booking_item item
|
||||||
|
where item.parentItemuuid = relatedPrivateCloudBookingItem.uuid
|
||||||
|
and item.type = 'CLOUD_SERVER';
|
||||||
|
assert relatedCloudServerBookingItem.uuid is not null, 'relatedCloudServerBookingItem for "' || givenProjectCaption|| '" must not be null';
|
||||||
|
|
||||||
|
select item.* into relatedManagedWebspaceBookingItem
|
||||||
|
from hs_booking_item item
|
||||||
|
where item.projectUuid = relatedProject.uuid
|
||||||
|
and item.type = 'MANAGED_WEBSPACE';
|
||||||
|
assert relatedManagedWebspaceBookingItem.uuid is not null, 'relatedManagedWebspaceBookingItem for "' || givenProjectCaption|| '" must not be null';
|
||||||
|
|
||||||
select uuid_generate_v4() into managedServerUuid;
|
select uuid_generate_v4() into managedServerUuid;
|
||||||
select uuid_generate_v4() into managedWebspaceUuid;
|
select uuid_generate_v4() into managedWebspaceUuid;
|
||||||
select uuid_generate_v4() into webUnixUserUuid;
|
select uuid_generate_v4() into webUnixUserUuid;
|
||||||
@ -55,12 +69,12 @@ begin
|
|||||||
defaultPrefix := relatedDebitor.defaultPrefix;
|
defaultPrefix := relatedDebitor.defaultPrefix;
|
||||||
|
|
||||||
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', '{ "monit_max_cpu_usage": 90, "monit_max_ram_usage": 80, "monit_max_ssd_usage": 70 }'::jsonb),
|
values (managedServerUuid, relatedManagedServerBookingItem.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', '{}'::jsonb),
|
(uuid_generate_v4(), relatedCloudServerBookingItem.uuid, 'CLOUD_SERVER', null, null, 'vm20' || debitorNumberSuffix, 'another CloudServer', '{}'::jsonb),
|
||||||
(managedWebspaceUuid, relatedManagedServerBookingItem.uuid, 'MANAGED_WEBSPACE', managedServerUuid, null, defaultPrefix || '01', 'some Webspace', '{}'::jsonb),
|
(managedWebspaceUuid, relatedManagedWebspaceBookingItem.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"}'::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": "*"}'::jsonb);
|
||||||
end; $$;
|
end; $$;
|
||||||
--//
|
--//
|
||||||
|
|
||||||
|
@ -77,14 +77,14 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"type": "MANAGED_WEBSPACE",
|
"type": "MANAGED_WEBSPACE",
|
||||||
"caption": "some ManagedWebspace",
|
"caption": "separate ManagedWebspace",
|
||||||
"validFrom": "2022-10-01",
|
"validFrom": "2022-10-01",
|
||||||
"validTo": null,
|
"validTo": null,
|
||||||
"resources": {
|
"resources": {
|
||||||
"SSD": 512,
|
"SSD": 100,
|
||||||
"Multi": 4,
|
"Multi": 1,
|
||||||
"Daemons": 2,
|
"Daemons": 0,
|
||||||
"Traffic": 12
|
"Traffic": 50
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -94,7 +94,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
"validTo": null,
|
"validTo": null,
|
||||||
"resources": {
|
"resources": {
|
||||||
"RAM": 8,
|
"RAM": 8,
|
||||||
"SSD": 512,
|
"SSD": 500,
|
||||||
"CPUs": 2,
|
"CPUs": 2,
|
||||||
"Traffic": 500
|
"Traffic": 500
|
||||||
}
|
}
|
||||||
@ -105,8 +105,9 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
"validFrom": "2024-04-01",
|
"validFrom": "2024-04-01",
|
||||||
"validTo": null,
|
"validTo": null,
|
||||||
"resources": {
|
"resources": {
|
||||||
"SSD": 4000,
|
|
||||||
"HDD": 10000,
|
"HDD": 10000,
|
||||||
|
"RAM": 32,
|
||||||
|
"SSD": 4000,
|
||||||
"CPUs": 10,
|
"CPUs": 10,
|
||||||
"Traffic": 2000
|
"Traffic": 2000
|
||||||
}
|
}
|
||||||
@ -174,7 +175,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
@Test
|
@Test
|
||||||
void globalAdmin_canGetArbitraryBookingItem() {
|
void globalAdmin_canGetArbitraryBookingItem() {
|
||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
final var givenBookingItemUuid = bookingItemRepo.findByCaption("some ManagedWebspace").stream()
|
final var givenBookingItemUuid = bookingItemRepo.findByCaption("separate ManagedWebspace").stream()
|
||||||
.filter(bi -> belongsToDebitorWithDefaultPrefix(bi, "fir"))
|
.filter(bi -> belongsToDebitorWithDefaultPrefix(bi, "fir"))
|
||||||
.map(HsBookingItemEntity::getUuid)
|
.map(HsBookingItemEntity::getUuid)
|
||||||
.findAny().orElseThrow();
|
.findAny().orElseThrow();
|
||||||
@ -191,14 +192,14 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
.body("", lenientlyEquals("""
|
.body("", lenientlyEquals("""
|
||||||
{
|
{
|
||||||
"type": "MANAGED_WEBSPACE",
|
"type": "MANAGED_WEBSPACE",
|
||||||
"caption": "some ManagedWebspace",
|
"caption": "separate ManagedWebspace",
|
||||||
"validFrom": "2022-10-01",
|
"validFrom": "2022-10-01",
|
||||||
"validTo": null,
|
"validTo": null,
|
||||||
"resources": {
|
"resources": {
|
||||||
"SSD": 512,
|
"SSD": 100,
|
||||||
"Multi": 4,
|
"Multi": 1,
|
||||||
"Daemons": 2,
|
"Daemons": 0,
|
||||||
"Traffic": 12
|
"Traffic": 50
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""")); // @formatter:on
|
""")); // @formatter:on
|
||||||
@ -251,7 +252,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
"validTo": null,
|
"validTo": null,
|
||||||
"resources": {
|
"resources": {
|
||||||
"RAM": 8,
|
"RAM": 8,
|
||||||
"SSD": 512,
|
"SSD": 500,
|
||||||
"CPUs": 2,
|
"CPUs": 2,
|
||||||
"Traffic": 500
|
"Traffic": 500
|
||||||
}
|
}
|
||||||
|
@ -174,8 +174,8 @@ 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, SSD: 512, Traffic: 12 })",
|
"HsBookingItemEntity(D-1000212:D-1000212 default project, MANAGED_WEBSPACE, [2022-10-01,), separate ManagedWebspace, { Daemons: 0, Multi: 1, SSD: 100, Traffic: 50 })",
|
||||||
"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, MANAGED_SERVER, [2022-10-01,), separate ManagedServer, { CPUs: 2, RAM: 8, SSD: 500, Traffic: 500 })",
|
||||||
"HsBookingItemEntity(D-1000212:D-1000212 default project, PRIVATE_CLOUD, [2024-04-01,), some PrivateCloud, { CPUs: 10, HDD: 10000, RAM: 32, SSD: 4000, Traffic: 2000 })");
|
"HsBookingItemEntity(D-1000212:D-1000212 default project, PRIVATE_CLOUD, [2024-04-01,), some PrivateCloud, { CPUs: 10, HDD: 10000, RAM: 32, SSD: 4000, Traffic: 2000 })");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,8 +194,8 @@ 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, SSD: 512, Traffic: 500 })",
|
"HsBookingItemEntity(D-1000111:D-1000111 default project, MANAGED_SERVER, [2022-10-01,), separate ManagedServer, { CPUs: 2, RAM: 8, SSD: 500, Traffic: 500 })",
|
||||||
"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, MANAGED_WEBSPACE, [2022-10-01,), separate ManagedWebspace, { Daemons: 0, Multi: 1, SSD: 100, Traffic: 50 })",
|
||||||
"HsBookingItemEntity(D-1000111:D-1000111 default project, PRIVATE_CLOUD, [2024-04-01,), some PrivateCloud, { CPUs: 10, HDD: 10000, RAM: 32, SSD: 4000, Traffic: 2000 })");
|
"HsBookingItemEntity(D-1000111:D-1000111 default project, PRIVATE_CLOUD, [2024-04-01,), some PrivateCloud, { CPUs: 10, HDD: 10000, RAM: 32, SSD: 4000, Traffic: 2000 })");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,7 +137,7 @@ class HsManagedServerBookingItemValidatorUnitTest {
|
|||||||
.resources(ofEntries(
|
.resources(ofEntries(
|
||||||
entry("SSD", 100),
|
entry("SSD", 100),
|
||||||
entry("Traffic", 1000),
|
entry("Traffic", 1000),
|
||||||
entry("MultiOptions", 1)
|
entry("Multi", 1)
|
||||||
))
|
))
|
||||||
.subHostingAssets(of(
|
.subHostingAssets(of(
|
||||||
HsHostingAssetEntity.builder()
|
HsHostingAssetEntity.builder()
|
||||||
@ -167,10 +167,10 @@ class HsManagedServerBookingItemValidatorUnitTest {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(result).containsExactlyInAnyOrder(
|
assertThat(result).containsExactlyInAnyOrder(
|
||||||
"MultiOptions=1 allows at maximum 25 unix users, but 26 found",
|
"Multi=1 allows at maximum 25 unix users, but 26 found",
|
||||||
"MultiOptions=1 allows at maximum 5 database users, but 6 found",
|
"Multi=1 allows at maximum 5 database users, but 6 found",
|
||||||
"MultiOptions=1 allows at maximum 5 databases, but 9 found",
|
"Multi=1 allows at maximum 5 databases, but 9 found",
|
||||||
"MultiOptions=1 allows at maximum 250 databases, but 260 found"
|
"Multi=1 allows at maximum 250 databases, but 260 found"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ 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=false, defaultValue=1, isTotalsValidator=false}",
|
"{type=integer, propertyName=Multi, min=1, max=100, step=1, required=false, defaultValue=1, isTotalsValidator=false}",
|
||||||
"{type=integer, propertyName=Daemons, min=0, max=10, required=false, defaultValue=0, 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, defaultValue=BASIC, isTotalsValidator=false}");
|
"{type=enumeration, propertyName=SLA-Platform, values=[BASIC, EXT24H], required=false, defaultValue=BASIC, isTotalsValidator=false}");
|
||||||
|
@ -5,6 +5,7 @@ import io.restassured.http.ContentType;
|
|||||||
import net.hostsharing.hsadminng.HsadminNgApplication;
|
import net.hostsharing.hsadminng.HsadminNgApplication;
|
||||||
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity;
|
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity;
|
||||||
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemRepository;
|
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemRepository;
|
||||||
|
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType;
|
||||||
import net.hostsharing.hsadminng.hs.booking.project.HsBookingProjectRepository;
|
import net.hostsharing.hsadminng.hs.booking.project.HsBookingProjectRepository;
|
||||||
import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorRepository;
|
import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorRepository;
|
||||||
import net.hostsharing.hsadminng.rbac.test.ContextBasedTestWithCleanup;
|
import net.hostsharing.hsadminng.rbac.test.ContextBasedTestWithCleanup;
|
||||||
@ -21,6 +22,8 @@ import java.util.UUID;
|
|||||||
|
|
||||||
import static java.util.Map.entry;
|
import static java.util.Map.entry;
|
||||||
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.HsHostingAssetType.MANAGED_WEBSPACE;
|
||||||
|
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.UNIX_USER;
|
||||||
import static net.hostsharing.hsadminng.rbac.test.JsonMatcher.lenientlyEquals;
|
import static net.hostsharing.hsadminng.rbac.test.JsonMatcher.lenientlyEquals;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.hamcrest.Matchers.matchesRegex;
|
import static org.hamcrest.Matchers.matchesRegex;
|
||||||
@ -103,47 +106,47 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
|
|
||||||
RestAssured // @formatter:off
|
RestAssured // @formatter:off
|
||||||
.given()
|
.given()
|
||||||
.header("current-user", "superuser-alex@hostsharing.net")
|
.header("current-user", "superuser-alex@hostsharing.net")
|
||||||
.port(port)
|
.port(port)
|
||||||
.when()
|
.when()
|
||||||
.get("http://localhost/api/hs/hosting/assets?type=" + MANAGED_SERVER)
|
. get("http://localhost/api/hs/hosting/assets?type=" + MANAGED_SERVER)
|
||||||
.then().log().all().assertThat()
|
.then().log().all().assertThat()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.contentType("application/json")
|
.contentType("application/json")
|
||||||
.body("", lenientlyEquals("""
|
.body("", lenientlyEquals("""
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"type": "MANAGED_SERVER",
|
"type": "MANAGED_SERVER",
|
||||||
"identifier": "vm1011",
|
"identifier": "vm1011",
|
||||||
"caption": "some ManagedServer",
|
"caption": "some ManagedServer",
|
||||||
"config": {
|
"config": {
|
||||||
"monit_max_cpu_usage": 90,
|
"monit_max_cpu_usage": 90,
|
||||||
"monit_max_ram_usage": 80,
|
"monit_max_ram_usage": 80,
|
||||||
"monit_max_ssd_usage": 70
|
"monit_max_ssd_usage": 70
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "MANAGED_SERVER",
|
||||||
|
"identifier": "vm1012",
|
||||||
|
"caption": "some ManagedServer",
|
||||||
|
"config": {
|
||||||
|
"monit_max_cpu_usage": 90,
|
||||||
|
"monit_max_ram_usage": 80,
|
||||||
|
"monit_max_ssd_usage": 70
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "MANAGED_SERVER",
|
||||||
|
"identifier": "vm1013",
|
||||||
|
"caption": "some ManagedServer",
|
||||||
|
"config": {
|
||||||
|
"monit_max_cpu_usage": 90,
|
||||||
|
"monit_max_ram_usage": 80,
|
||||||
|
"monit_max_ssd_usage": 70
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
]
|
||||||
{
|
"""));
|
||||||
"type": "MANAGED_SERVER",
|
|
||||||
"identifier": "vm1012",
|
|
||||||
"caption": "some ManagedServer",
|
|
||||||
"config": {
|
|
||||||
"monit_max_cpu_usage": 90,
|
|
||||||
"monit_max_ram_usage": 80,
|
|
||||||
"monit_max_ssd_usage": 70
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "MANAGED_SERVER",
|
|
||||||
"identifier": "vm1013",
|
|
||||||
"caption": "some ManagedServer",
|
|
||||||
"config": {
|
|
||||||
"monit_max_cpu_usage": 90,
|
|
||||||
"monit_max_ram_usage": 80,
|
|
||||||
"monit_max_ssd_usage": 70
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
"""));
|
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -155,7 +158,14 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
void globalAdmin_canAddBookedAsset() {
|
void globalAdmin_canAddBookedAsset() {
|
||||||
|
|
||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
final var givenBookingItem = givenBookingItem("D-1000111 default project", "some PrivateCloud");
|
final var givenBookingItem = newBookingItem("D-1000111 default project",
|
||||||
|
HsBookingItemType.MANAGED_WEBSPACE, "separate ManagedWebspace BI",
|
||||||
|
Map.ofEntries(
|
||||||
|
entry("SSD", 50),
|
||||||
|
entry("Traffic", 50)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
final var givenParentAsset = givenParentAsset(MANAGED_SERVER, "vm1011");
|
||||||
|
|
||||||
final var location = RestAssured // @formatter:off
|
final var location = RestAssured // @formatter:off
|
||||||
.given()
|
.given()
|
||||||
@ -164,12 +174,13 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
.body("""
|
.body("""
|
||||||
{
|
{
|
||||||
"bookingItemUuid": "%s",
|
"bookingItemUuid": "%s",
|
||||||
"type": "MANAGED_SERVER",
|
"type": "MANAGED_WEBSPACE",
|
||||||
"identifier": "vm1400",
|
"identifier": "fir10",
|
||||||
"caption": "some new ManagedServer",
|
"parentAssetUuid": "%s",
|
||||||
"config": { "monit_max_ssd_usage": 80, "monit_max_cpu_usage": 90, "monit_max_ram_usage": 70 }
|
"caption": "some separate ManagedWebspace HA",
|
||||||
|
"config": {}
|
||||||
}
|
}
|
||||||
""".formatted(givenBookingItem.getUuid()))
|
""".formatted(givenBookingItem.getUuid(), givenParentAsset.getUuid()))
|
||||||
.port(port)
|
.port(port)
|
||||||
.when()
|
.when()
|
||||||
.post("http://localhost/api/hs/hosting/assets")
|
.post("http://localhost/api/hs/hosting/assets")
|
||||||
@ -178,10 +189,10 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
.contentType(ContentType.JSON)
|
.contentType(ContentType.JSON)
|
||||||
.body("", lenientlyEquals("""
|
.body("", lenientlyEquals("""
|
||||||
{
|
{
|
||||||
"type": "MANAGED_SERVER",
|
"type": "MANAGED_WEBSPACE",
|
||||||
"identifier": "vm1400",
|
"identifier": "fir10",
|
||||||
"caption": "some new ManagedServer",
|
"caption": "some separate ManagedWebspace HA",
|
||||||
"config": { "monit_max_ssd_usage": 80, "monit_max_cpu_usage": 90, "monit_max_ram_usage": 70 }
|
"config": {}
|
||||||
}
|
}
|
||||||
"""))
|
"""))
|
||||||
.header("Location", matchesRegex("http://localhost:[1-9][0-9]*/api/hs/hosting/assets/[^/]*"))
|
.header("Location", matchesRegex("http://localhost:[1-9][0-9]*/api/hs/hosting/assets/[^/]*"))
|
||||||
@ -191,6 +202,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
final var newUserUuid = UUID.fromString(
|
final var newUserUuid = UUID.fromString(
|
||||||
location.substring(location.lastIndexOf('/') + 1));
|
location.substring(location.lastIndexOf('/') + 1));
|
||||||
assertThat(newUserUuid).isNotNull();
|
assertThat(newUserUuid).isNotNull();
|
||||||
|
toCleanup(HsHostingAssetEntity.class, newUserUuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -239,7 +251,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void additionalValidationsArePerformend_whenAddingAsset() {
|
void propertyValidationsArePerformend_whenAddingAsset() {
|
||||||
|
|
||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
final var givenBookingItem = givenBookingItem("D-1000111 default project", "some PrivateCloud");
|
final var givenBookingItem = givenBookingItem("D-1000111 default project", "some PrivateCloud");
|
||||||
@ -275,6 +287,58 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
}
|
}
|
||||||
""".replaceAll(" +<<<", ""))); // @formatter:on
|
""".replaceAll(" +<<<", ""))); // @formatter:on
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void totalsLimitValidationsArePerformend_whenAddingAsset() {
|
||||||
|
|
||||||
|
context.define("superuser-alex@hostsharing.net");
|
||||||
|
final var givenHostingAsset = givenHostingAsset(MANAGED_WEBSPACE, "fir01");
|
||||||
|
assertThat(givenHostingAsset.getBookingItem().getResources().get("Multi"))
|
||||||
|
.as("precondition failed")
|
||||||
|
.isEqualTo(1);
|
||||||
|
|
||||||
|
jpaAttempt.transacted(() -> {
|
||||||
|
context.define("superuser-alex@hostsharing.net");
|
||||||
|
for (int n = 0; n < 25; ++n ) {
|
||||||
|
toCleanup(assetRepo.save(
|
||||||
|
HsHostingAssetEntity.builder()
|
||||||
|
.type(UNIX_USER)
|
||||||
|
.parentAsset(givenHostingAsset)
|
||||||
|
.identifier("fir01-%2d".formatted(n))
|
||||||
|
.caption("Test UnixUser fir01-%2d".formatted(n))
|
||||||
|
.build()));
|
||||||
|
}
|
||||||
|
}).assertSuccessful();
|
||||||
|
|
||||||
|
RestAssured // @formatter:off
|
||||||
|
.given()
|
||||||
|
.header("current-user", "superuser-alex@hostsharing.net")
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body("""
|
||||||
|
{
|
||||||
|
"parentAssetUuid": "%s",
|
||||||
|
"type": "UNIX_USER",
|
||||||
|
"identifier": "fir01-extra",
|
||||||
|
"caption": "some extra UnixUser",
|
||||||
|
"config": { }
|
||||||
|
}
|
||||||
|
""".formatted(givenHostingAsset.getUuid()))
|
||||||
|
.port(port)
|
||||||
|
.when()
|
||||||
|
.post("http://localhost/api/hs/hosting/assets")
|
||||||
|
.then().log().all().assertThat()
|
||||||
|
.statusCode(400)
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body("", lenientlyEquals("""
|
||||||
|
{
|
||||||
|
"statusPhrase": "Bad Request",
|
||||||
|
"message": "[
|
||||||
|
<<<UNIX_USER:fir01-extra.parentAsset.MANAGED_WEBSPACE:fir01.bookingItem.Multi=1 allows at maximum 25 unix users, but 26 found
|
||||||
|
<<<]"
|
||||||
|
}
|
||||||
|
""".replaceAll(" +<<<", ""))); // @formatter:on
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@ -443,6 +507,29 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HsHostingAssetEntity givenHostingAsset(final HsHostingAssetType type, final String identifier) {
|
||||||
|
return assetRepo.findByIdentifier(identifier).stream()
|
||||||
|
.filter(ha -> ha.getType()==type)
|
||||||
|
.findAny().orElseThrow();
|
||||||
|
}
|
||||||
|
|
||||||
|
HsBookingItemEntity newBookingItem(
|
||||||
|
final String projectCaption,
|
||||||
|
final HsBookingItemType type, final String bookingItemCaption, final Map<String, Object> resources) {
|
||||||
|
return jpaAttempt.transacted(() -> {
|
||||||
|
context.define("superuser-alex@hostsharing.net");
|
||||||
|
final var project = projectRepo.findByCaption(projectCaption).stream()
|
||||||
|
.findAny().orElseThrow();
|
||||||
|
final var bookingItem = HsBookingItemEntity.builder()
|
||||||
|
.project(project)
|
||||||
|
.type(type)
|
||||||
|
.caption(bookingItemCaption)
|
||||||
|
.resources(resources)
|
||||||
|
.build();
|
||||||
|
return toCleanup(bookingItemRepo.save(bookingItem));
|
||||||
|
}).assertSuccessful().returnedValue();
|
||||||
|
}
|
||||||
|
|
||||||
HsBookingItemEntity givenBookingItem(final String projectCaption, final String bookingItemCaption) {
|
HsBookingItemEntity givenBookingItem(final String projectCaption, final String bookingItemCaption) {
|
||||||
return bookingItemRepo.findByCaption(bookingItemCaption).stream()
|
return bookingItemRepo.findByCaption(bookingItemCaption).stream()
|
||||||
.filter(bi -> bi.getRelatedProject().getCaption().contains(projectCaption))
|
.filter(bi -> bi.getRelatedProject().getCaption().contains(projectCaption))
|
||||||
|
@ -33,7 +33,8 @@ class HsHostingAssetPropsControllerAcceptanceTest {
|
|||||||
[
|
[
|
||||||
"MANAGED_SERVER",
|
"MANAGED_SERVER",
|
||||||
"MANAGED_WEBSPACE",
|
"MANAGED_WEBSPACE",
|
||||||
"CLOUD_SERVER"
|
"CLOUD_SERVER",
|
||||||
|
"UNIX_USER"
|
||||||
]
|
]
|
||||||
"""));
|
"""));
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
|
@ -3,6 +3,7 @@ package net.hostsharing.hsadminng.hs.hosting.asset;
|
|||||||
import net.hostsharing.hsadminng.context.Context;
|
import net.hostsharing.hsadminng.context.Context;
|
||||||
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity;
|
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity;
|
||||||
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemRepository;
|
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemRepository;
|
||||||
|
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType;
|
||||||
import net.hostsharing.hsadminng.hs.booking.project.HsBookingProjectRepository;
|
import net.hostsharing.hsadminng.hs.booking.project.HsBookingProjectRepository;
|
||||||
import net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantRepository;
|
import net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantRepository;
|
||||||
import net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleRepository;
|
import net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleRepository;
|
||||||
@ -70,12 +71,13 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu
|
|||||||
// given
|
// given
|
||||||
context("superuser-alex@hostsharing.net");
|
context("superuser-alex@hostsharing.net");
|
||||||
final var count = assetRepo.count();
|
final var count = assetRepo.count();
|
||||||
final var givenManagedServer = givenManagedServer("D-1000111 default project", MANAGED_SERVER);
|
final var givenManagedServer = givenHostingAsset("D-1000111 default project", MANAGED_SERVER);
|
||||||
|
final var newWebspaceBookingItem = newBookingItem(givenManagedServer.getBookingItem(), HsBookingItemType.MANAGED_WEBSPACE, "fir01");
|
||||||
|
|
||||||
// when
|
// when
|
||||||
final var result = attempt(em, () -> {
|
final var result = attempt(em, () -> {
|
||||||
final var newAsset = HsHostingAssetEntity.builder()
|
final var newAsset = HsHostingAssetEntity.builder()
|
||||||
.bookingItem(givenManagedServer.getBookingItem())
|
.bookingItem(newWebspaceBookingItem)
|
||||||
.parentAsset(givenManagedServer)
|
.parentAsset(givenManagedServer)
|
||||||
.caption("some new managed webspace")
|
.caption("some new managed webspace")
|
||||||
.type(MANAGED_WEBSPACE)
|
.type(MANAGED_WEBSPACE)
|
||||||
@ -95,18 +97,19 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu
|
|||||||
public void createsAndGrantsRoles() {
|
public void createsAndGrantsRoles() {
|
||||||
// given
|
// given
|
||||||
context("superuser-alex@hostsharing.net");
|
context("superuser-alex@hostsharing.net");
|
||||||
|
final var givenManagedServer = givenHostingAsset("D-1000111 default project", MANAGED_SERVER);
|
||||||
|
final var newWebspaceBookingItem = newBookingItem(givenManagedServer.getBookingItem(), HsBookingItemType.MANAGED_WEBSPACE, "fir01");
|
||||||
|
em.flush();
|
||||||
final var initialRoleNames = distinctRoleNamesOf(rawRoleRepo.findAll());
|
final var initialRoleNames = distinctRoleNamesOf(rawRoleRepo.findAll());
|
||||||
final var initialGrantNames = distinctGrantDisplaysOf(rawGrantRepo.findAll()).stream()
|
final var initialGrantNames = distinctGrantDisplaysOf(rawGrantRepo.findAll());
|
||||||
.map(s -> s.replace("hs_office_", ""))
|
|
||||||
.toList();
|
|
||||||
final var givenBookingItem = givenBookingItem("D-1000111 default project", "some PrivateCloud");
|
|
||||||
|
|
||||||
// when
|
// when
|
||||||
final var result = attempt(em, () -> {
|
final var result = attempt(em, () -> {
|
||||||
final var newAsset = HsHostingAssetEntity.builder()
|
final var newAsset = HsHostingAssetEntity.builder()
|
||||||
.bookingItem(givenBookingItem)
|
.bookingItem(newWebspaceBookingItem)
|
||||||
.type(HsHostingAssetType.MANAGED_SERVER)
|
.parentAsset(givenManagedServer)
|
||||||
.identifier("vm9000")
|
.type(HsHostingAssetType.MANAGED_WEBSPACE)
|
||||||
|
.identifier("fir00")
|
||||||
.caption("some new managed webspace")
|
.caption("some new managed webspace")
|
||||||
.build();
|
.build();
|
||||||
return toCleanup(assetRepo.save(newAsset));
|
return toCleanup(assetRepo.save(newAsset));
|
||||||
@ -117,29 +120,33 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu
|
|||||||
final var all = rawRoleRepo.findAll();
|
final var all = rawRoleRepo.findAll();
|
||||||
assertThat(distinctRoleNamesOf(all)).containsExactlyInAnyOrder(Array.from(
|
assertThat(distinctRoleNamesOf(all)).containsExactlyInAnyOrder(Array.from(
|
||||||
initialRoleNames,
|
initialRoleNames,
|
||||||
"hs_hosting_asset#vm9000:OWNER",
|
"hs_hosting_asset#fir00:ADMIN",
|
||||||
"hs_hosting_asset#vm9000:ADMIN",
|
"hs_hosting_asset#fir00:AGENT",
|
||||||
"hs_hosting_asset#vm9000:AGENT",
|
"hs_hosting_asset#fir00:OWNER",
|
||||||
"hs_hosting_asset#vm9000:TENANT"));
|
"hs_hosting_asset#fir00:TENANT"));
|
||||||
assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll()))
|
assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll()))
|
||||||
.map(s -> s.replace("hs_office_", ""))
|
|
||||||
.containsExactlyInAnyOrder(fromFormatted(
|
.containsExactlyInAnyOrder(fromFormatted(
|
||||||
initialGrantNames,
|
initialGrantNames,
|
||||||
|
|
||||||
// owner
|
// owner
|
||||||
"{ grant role:hs_hosting_asset#vm9000:OWNER to role:hs_booking_item#somePrivateCloud:ADMIN by system and assume }",
|
"{ grant role:hs_hosting_asset#fir00:OWNER to role:hs_booking_item#fir01:ADMIN by system and assume }",
|
||||||
"{ grant perm:hs_hosting_asset#vm9000:DELETE to role:hs_hosting_asset#vm9000:OWNER by system and assume }",
|
"{ grant role:hs_hosting_asset#fir00:OWNER to role:hs_hosting_asset#vm1011:ADMIN by system and assume }",
|
||||||
"{ grant role:hs_hosting_asset#vm9000:ADMIN to role:hs_hosting_asset#vm9000:OWNER by system and assume }",
|
"{ grant perm:hs_hosting_asset#fir00:DELETE to role:hs_hosting_asset#fir00:OWNER by system and assume }",
|
||||||
|
|
||||||
// admin
|
// admin
|
||||||
"{ grant perm:hs_hosting_asset#vm9000:INSERT>hs_hosting_asset to role:hs_hosting_asset#vm9000:ADMIN by system and assume }",
|
"{ grant role:hs_hosting_asset#fir00:ADMIN to role:hs_hosting_asset#fir00:OWNER by system and assume }",
|
||||||
"{ grant perm:hs_hosting_asset#vm9000:UPDATE to role:hs_hosting_asset#vm9000:ADMIN by system and assume }",
|
"{ grant role:hs_hosting_asset#fir00:ADMIN to role:hs_booking_item#fir01:AGENT by system and assume }",
|
||||||
"{ grant role:hs_hosting_asset#vm9000:ADMIN to role:hs_booking_item#somePrivateCloud:AGENT by system and assume }",
|
"{ grant perm:hs_hosting_asset#fir00:INSERT>hs_hosting_asset to role:hs_hosting_asset#fir00:ADMIN by system and assume }",
|
||||||
"{ grant role:hs_hosting_asset#vm9000:TENANT to role:hs_hosting_asset#vm9000:AGENT by system and assume }",
|
"{ grant perm:hs_hosting_asset#fir00:UPDATE to role:hs_hosting_asset#fir00:ADMIN by system and assume }",
|
||||||
"{ grant role:hs_hosting_asset#vm9000:AGENT to role:hs_hosting_asset#vm9000:ADMIN by system and assume }",
|
|
||||||
|
// agent
|
||||||
|
"{ grant role:hs_hosting_asset#fir00:ADMIN to role:hs_hosting_asset#vm1011:AGENT by system and assume }",
|
||||||
|
"{ grant role:hs_hosting_asset#fir00:AGENT to role:hs_hosting_asset#fir00:ADMIN by system and assume }",
|
||||||
|
|
||||||
// tenant
|
// tenant
|
||||||
"{ grant role:hs_booking_item#somePrivateCloud:TENANT to role:hs_hosting_asset#vm9000:TENANT by system and assume }",
|
"{ grant role:hs_booking_item#fir01:TENANT to role:hs_hosting_asset#fir00:TENANT by system and assume }",
|
||||||
|
"{ grant role:hs_hosting_asset#fir00:TENANT to role:hs_hosting_asset#fir00:AGENT by system and assume }",
|
||||||
|
"{ grant role:hs_hosting_asset#vm1011:TENANT to role:hs_hosting_asset#fir00:TENANT by system and assume }",
|
||||||
|
|
||||||
null));
|
null));
|
||||||
}
|
}
|
||||||
@ -164,9 +171,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)",
|
"HsHostingAssetEntity(MANAGED_WEBSPACE, sec01, some Webspace, MANAGED_SERVER:vm1012, D-1000212:D-1000212 default project:separate ManagedWebspace)",
|
||||||
"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 ManagedWebspace)",
|
||||||
"HsHostingAssetEntity(MANAGED_WEBSPACE, fir01, some Webspace, MANAGED_SERVER:vm1011, D-1000111:D-1000111 default project:separate ManagedServer)");
|
"HsHostingAssetEntity(MANAGED_WEBSPACE, thi01, some Webspace, MANAGED_SERVER:vm1013, D-1000313:D-1000313 default project:separate ManagedWebspace)");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -182,9 +189,8 @@ 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)",
|
"HsHostingAssetEntity(MANAGED_WEBSPACE, fir01, some Webspace, MANAGED_SERVER:vm1011, D-1000111:D-1000111 default project:separate ManagedWebspace)",
|
||||||
"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(MANAGED_SERVER, vm1011, some ManagedServer, D-1000111:D-1000111 default project:separate ManagedServer, { 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)");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -200,7 +206,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)");
|
"HsHostingAssetEntity(MANAGED_WEBSPACE, sec01, some Webspace, MANAGED_SERVER:vm1012, D-1000212:D-1000212 default project:separate ManagedWebspace)");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -351,7 +357,7 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu
|
|||||||
private HsHostingAssetEntity givenSomeTemporaryAsset(final String projectCaption, final String identifier) {
|
private HsHostingAssetEntity givenSomeTemporaryAsset(final String projectCaption, final String identifier) {
|
||||||
return jpaAttempt.transacted(() -> {
|
return jpaAttempt.transacted(() -> {
|
||||||
context("superuser-alex@hostsharing.net");
|
context("superuser-alex@hostsharing.net");
|
||||||
final var givenBookingItem = givenBookingItem("D-1000111 default project", "some PrivateCloud");
|
final var givenBookingItem = givenBookingItem("D-1000111 default project", "test CloudServer");
|
||||||
final var newAsset = HsHostingAssetEntity.builder()
|
final var newAsset = HsHostingAssetEntity.builder()
|
||||||
.bookingItem(givenBookingItem)
|
.bookingItem(givenBookingItem)
|
||||||
.type(CLOUD_SERVER)
|
.type(CLOUD_SERVER)
|
||||||
@ -367,20 +373,30 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu
|
|||||||
}
|
}
|
||||||
|
|
||||||
HsBookingItemEntity givenBookingItem(final String projectCaption, final String bookingItemCaption) {
|
HsBookingItemEntity givenBookingItem(final String projectCaption, final String bookingItemCaption) {
|
||||||
final var givenProject = projectRepo.findByCaption(projectCaption).stream()
|
return bookingItemRepo.findByCaption(bookingItemCaption).stream()
|
||||||
.findAny().orElseThrow();
|
.filter(i -> i.getRelatedProject().getCaption().equals(projectCaption))
|
||||||
return bookingItemRepo.findAllByProjectUuid(givenProject.getUuid()).stream()
|
|
||||||
.filter(i -> i.getCaption().equals(bookingItemCaption))
|
|
||||||
.findAny().orElseThrow();
|
.findAny().orElseThrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
HsHostingAssetEntity givenManagedServer(final String projectCaption, final HsHostingAssetType type) {
|
HsHostingAssetEntity givenHostingAsset(final String projectCaption, final HsHostingAssetType type) {
|
||||||
final var givenProject = projectRepo.findByCaption(projectCaption).stream()
|
final var givenProject = projectRepo.findByCaption(projectCaption).stream()
|
||||||
.findAny().orElseThrow();
|
.findAny().orElseThrow();
|
||||||
return assetRepo.findAllByCriteria(givenProject.getUuid(), null, type).stream()
|
return assetRepo.findAllByCriteria(givenProject.getUuid(), null, type).stream()
|
||||||
.findAny().orElseThrow();
|
.findAny().orElseThrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HsBookingItemEntity newBookingItem(
|
||||||
|
final HsBookingItemEntity parentBookingItem,
|
||||||
|
final HsBookingItemType type,
|
||||||
|
final String caption) {
|
||||||
|
final var newBookingItem = HsBookingItemEntity.builder()
|
||||||
|
.parentItem(parentBookingItem)
|
||||||
|
.type(type)
|
||||||
|
.caption(caption)
|
||||||
|
.build();
|
||||||
|
return toCleanup(bookingItemRepo.save(newBookingItem));
|
||||||
|
}
|
||||||
|
|
||||||
void exactlyTheseAssetsAreReturned(
|
void exactlyTheseAssetsAreReturned(
|
||||||
final List<HsHostingAssetEntity> actualResult,
|
final List<HsHostingAssetEntity> actualResult,
|
||||||
final String... serverNames) {
|
final String... serverNames) {
|
||||||
|
Loading…
Reference in New Issue
Block a user