hierarchical-validation-baseline #59

Merged
hsh-michaelhoennig merged 18 commits from hierarchical-validation-baseline into master 2024-06-14 16:48:01 +02:00
17 changed files with 273 additions and 173 deletions
Showing only changes of commit 5d15968e3c - Show all commits

View File

@ -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

View File

@ -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))

View File

@ -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);
}
} }

View File

@ -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())

View File

@ -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) {

View File

@ -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();
} }
} }

View File

@ -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;
}
} }

View File

@ -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; $$;
--// --//

View File

@ -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; $$;

View File

@ -16,6 +16,8 @@ declare
relatedDebitor hs_office_debitor; relatedDebitor hs_office_debitor;
relatedPrivateCloudBookingItem hs_booking_item; relatedPrivateCloudBookingItem hs_booking_item;
relatedManagedServerBookingItem hs_booking_item; relatedManagedServerBookingItem hs_booking_item;
relatedCloudServerBookingItem hs_booking_item;
relatedManagedWebspaceBookingItem hs_booking_item;
debitorNumberSuffix varchar; debitorNumberSuffix varchar;
defaultPrefix varchar; defaultPrefix varchar;
managedServerUuid uuid; managedServerUuid uuid;
@ -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;
@ -56,11 +70,11 @@ 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', '{ "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; $$;
--// --//

View File

@ -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
} }

View File

@ -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 })");
} }
} }

View File

@ -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"
); );
} }

View File

@ -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}");

View File

@ -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;
@ -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))

View File

@ -33,7 +33,8 @@ class HsHostingAssetPropsControllerAcceptanceTest {
[ [
"MANAGED_SERVER", "MANAGED_SERVER",
"MANAGED_WEBSPACE", "MANAGED_WEBSPACE",
"CLOUD_SERVER" "CLOUD_SERVER",
"UNIX_USER"
] ]
""")); """));
// @formatter:on // @formatter:on

View File

@ -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) {