diff --git a/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemEntity.java index 90774110..7961223e 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemEntity.java @@ -34,6 +34,7 @@ import jakarta.persistence.OneToOne; import jakarta.persistence.Table; import jakarta.persistence.Transient; import jakarta.persistence.Version; +import jakarta.validation.constraints.NotNull; import java.io.IOException; import java.time.LocalDate; import java.util.HashMap; @@ -92,6 +93,7 @@ public class HsBookingItemEntity implements Stringifyable, RbacObject { @JoinColumn(name = "parentitemuuid") private HsBookingItemEntity parentItem; + @NotNull @Column(name = "type") @Enumerated(EnumType.STRING) private HsBookingItemType type; diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsCloudServerHostingAssetValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsCloudServerHostingAssetValidator.java new file mode 100644 index 00000000..9144189b --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsCloudServerHostingAssetValidator.java @@ -0,0 +1,23 @@ +package net.hostsharing.hsadminng.hs.hosting.asset.validators; + +import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType; +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; + +import java.util.regex.Pattern; + +class HsCloudServerHostingAssetValidator extends HsHostingAssetEntityValidator { + + HsCloudServerHostingAssetValidator() { + super( + BookingItem.mustBeOfType(HsBookingItemType.CLOUD_SERVER), + ParentAsset.mustBeNull(), + AssignedToAsset.mustBeNull(), + AlarmContact.isOptional(), + NO_EXTRA_PROPERTIES); + } + + @Override + protected Pattern identifierPattern(final HsHostingAssetEntity assetEntity) { + return Pattern.compile("^vm[0-9][0-9][0-9][0-9]$"); + } +} diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsHostingAssetEntityValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsHostingAssetEntityValidator.java index c452d378..0db195f3 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsHostingAssetEntityValidator.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsHostingAssetEntityValidator.java @@ -1,35 +1,80 @@ package net.hostsharing.hsadminng.hs.hosting.asset.validators; import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity; +import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType; import net.hostsharing.hsadminng.hs.booking.item.validators.HsBookingItemEntityValidatorRegistry; import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType; +import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity; import net.hostsharing.hsadminng.hs.validation.HsEntityValidator; import net.hostsharing.hsadminng.hs.validation.ValidatableProperty; +import jakarta.validation.constraints.NotNull; +import java.util.Collections; import java.util.List; import java.util.Objects; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.regex.Pattern; +import java.util.stream.Stream; import static java.util.Arrays.stream; import static java.util.Collections.emptyList; import static java.util.Optional.ofNullable; -public class HsHostingAssetEntityValidator extends HsEntityValidator { +public abstract class HsHostingAssetEntityValidator extends HsEntityValidator { - public HsHostingAssetEntityValidator(final ValidatableProperty... properties) { + static final ValidatableProperty[] NO_EXTRA_PROPERTIES = new ValidatableProperty[0]; + + private final HsHostingAssetEntityValidator.BookingItem bookingItemValidation; + private final HsHostingAssetEntityValidator.ParentAsset parentAssetValidation; + private final HsHostingAssetEntityValidator.AssignedToAsset assignedToAssetValidation; + private final HsHostingAssetEntityValidator.AlarmContact alarmContactValidation; + + HsHostingAssetEntityValidator( + @NotNull final BookingItem bookingItemValidation, + @NotNull final ParentAsset parentAssetValidation, + @NotNull final AssignedToAsset assignedToAssetValidation, + @NotNull final AlarmContact alarmContactValidation, + final ValidatableProperty... properties) { super(properties); + this.bookingItemValidation = bookingItemValidation; + this.parentAssetValidation = parentAssetValidation; + this.assignedToAssetValidation = assignedToAssetValidation; + this.alarmContactValidation = alarmContactValidation; } - @Override public List validate(final HsHostingAssetEntity assetEntity) { return sequentiallyValidate( - () -> validateProperties(assetEntity), + () -> validateEntityReferences(assetEntity), + () -> validateIdentifierPattern(assetEntity), // might need proper parentAsset or billingItem () -> optionallyValidate(assetEntity.getBookingItem()), () -> optionallyValidate(assetEntity.getParentAsset()), () -> validateAgainstSubEntities(assetEntity) ); } + private List validateEntityReferences(final HsHostingAssetEntity assetEntity) { + return Stream.of( + validateReferencedEntity(assetEntity, "bookingItem", bookingItemValidation::validate), + validateReferencedEntity(assetEntity, "parentAsset", parentAssetValidation::validate), + validateReferencedEntity(assetEntity, "assignedToAsset", assignedToAssetValidation::validate), + validateReferencedEntity(assetEntity, "alarmContact", alarmContactValidation::validate), + validateProperties(assetEntity)) + .filter(Objects::nonNull) + .flatMap(List::stream) + .filter(Objects::nonNull) + .toList(); + } + + private List validateReferencedEntity( + final HsHostingAssetEntity assetEntity, + final String referenceFieldName, + final BiFunction> validator) { + return enrich(prefix(assetEntity.toShortString()), validator.apply(assetEntity, referenceFieldName)); + } + private List validateProperties(final HsHostingAssetEntity assetEntity) { return enrich(prefix(assetEntity.toShortString(), "config"), validateProperties(assetEntity.getConfig())); } @@ -73,4 +118,120 @@ public class HsHostingAssetEntityValidator extends HsEntityValidator validateIdentifierPattern(final HsHostingAssetEntity assetEntity) { + final var expectedIdentifierPattern = identifierPattern(assetEntity); + if (!expectedIdentifierPattern.matcher(assetEntity.getIdentifier()).matches()) { + return List.of("'identifier' expected to match '"+expectedIdentifierPattern+"', but is '" + assetEntity.getIdentifier() + "'"); + } + return Collections.emptyList(); + } + + protected abstract Pattern identifierPattern(HsHostingAssetEntity assetEntity); + + static abstract class ReferenceValidator { + + private final Policy policy; + private final T subEntityType; + private final Function subEntityGetter; + private final Function subEntityTypeGetter; + + public ReferenceValidator( + final Policy policy, + final T subEntityType, + final Function subEntityGetter, + final Function subEntityTypeGetter) { + this.policy = policy; + this.subEntityType = subEntityType; + this.subEntityGetter = subEntityGetter; + this.subEntityTypeGetter = subEntityTypeGetter; + } + + public ReferenceValidator( + final Policy policy, + final Function subEntityGetter) { + this.policy = policy; + this.subEntityType = null; + this.subEntityGetter = subEntityGetter; + this.subEntityTypeGetter = e -> null; + } + + enum Policy { + OPTIONAL, FORBIDDEN, REQUIRED + } + + List validate(final HsHostingAssetEntity assetEntity, final String referenceFieldName) { + + final var subEntity = subEntityGetter.apply(assetEntity); + if (policy == Policy.REQUIRED && subEntity == null) { + return List.of(referenceFieldName + "' must not be null but is null"); + } + if (policy == Policy.FORBIDDEN && subEntity != null) { + return List.of(referenceFieldName + "' must not be null but is set to "+ assetEntity.getBookingItem().toShortString()); + } + final var subItemType = subEntity != null ? subEntityTypeGetter.apply(subEntity) : null; + if (subEntityType != null && subItemType != subEntityType) { + return List.of(referenceFieldName + "' must be of type " + subEntityType + " but is of type " + subItemType); + } + return emptyList(); + } + } + + static class BookingItem extends ReferenceValidator { + + BookingItem(final Policy policy, final HsBookingItemType bookingItemType) { + super(policy, bookingItemType, HsHostingAssetEntity::getBookingItem, HsBookingItemEntity::getType); + } + + static BookingItem mustBeNull() { + return new BookingItem(Policy.FORBIDDEN, null); + } + + static BookingItem mustBeOfType(final HsBookingItemType hsBookingItemType) { + return new BookingItem(Policy.REQUIRED, hsBookingItemType); + } + } + + static class ParentAsset extends ReferenceValidator { + + ParentAsset(final ReferenceValidator.Policy policy, final HsHostingAssetType parentAssetType) { + super(policy, parentAssetType, HsHostingAssetEntity::getParentAsset, HsHostingAssetEntity::getType); + } + + static ParentAsset mustBeNull() { + return new ParentAsset(Policy.FORBIDDEN, null); + } + + static ParentAsset mustBeOfType(final HsHostingAssetType hostingAssetType) { + return new ParentAsset(Policy.REQUIRED, hostingAssetType); + } + + static ParentAsset mustBeNullOrOfType(final HsHostingAssetType hostingAssetType) { + return new ParentAsset(Policy.OPTIONAL, hostingAssetType); + } + } + + static class AssignedToAsset extends ReferenceValidator { + + AssignedToAsset(final ReferenceValidator.Policy policy, final HsHostingAssetType assignedToAssetType) { + super(policy, assignedToAssetType, HsHostingAssetEntity::getAssignedToAsset, HsHostingAssetEntity::getType); + } + + static AssignedToAsset mustBeNull() { + return new AssignedToAsset(Policy.FORBIDDEN, null); + } + } + + static class AlarmContact extends ReferenceValidator> { + + AlarmContact(final ReferenceValidator.Policy policy) { + super(policy, HsHostingAssetEntity::getAlarmContact); + } + + static AlarmContact isOptional() { + return new AlarmContact(Policy.OPTIONAL); + } + } + } + diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsHostingAssetEntityValidatorRegistry.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsHostingAssetEntityValidatorRegistry.java index a1cac8e0..39b765f9 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsHostingAssetEntityValidatorRegistry.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsHostingAssetEntityValidatorRegistry.java @@ -14,10 +14,10 @@ public class HsHostingAssetEntityValidatorRegistry { private static final Map, HsEntityValidator> validators = new HashMap<>(); static { - register(CLOUD_SERVER, new HsHostingAssetEntityValidator()); + register(CLOUD_SERVER, new HsCloudServerHostingAssetValidator()); register(MANAGED_SERVER, new HsManagedServerHostingAssetValidator()); register(MANAGED_WEBSPACE, new HsManagedWebspaceHostingAssetValidator()); - register(UNIX_USER, new HsHostingAssetEntityValidator()); + register(UNIX_USER, new HsUnixUserHostingAssetValidator()); } private static void register(final Enum type, final HsEntityValidator validator) { diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsManagedServerHostingAssetValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsManagedServerHostingAssetValidator.java index 00050010..362abf38 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsManagedServerHostingAssetValidator.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsManagedServerHostingAssetValidator.java @@ -1,5 +1,10 @@ package net.hostsharing.hsadminng.hs.hosting.asset.validators; +import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType; +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; + +import java.util.regex.Pattern; + 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.IntegerProperty.integerProperty; @@ -8,6 +13,11 @@ class HsManagedServerHostingAssetValidator extends HsHostingAssetEntityValidator public HsManagedServerHostingAssetValidator() { super( + BookingItem.mustBeOfType(HsBookingItemType.MANAGED_SERVER), + ParentAsset.mustBeNull(), // until we introduce a hosting asset for 'HOST' + AssignedToAsset.mustBeNull(), + AlarmContact.isOptional(), // hostmaster alert address is implicitly added + // monitoring integerProperty("monit_max_cpu_usage").unit("%").min(10).max(100).withDefault(92), integerProperty("monit_max_ram_usage").unit("%").min(10).max(100).withDefault(92), @@ -15,7 +25,6 @@ class HsManagedServerHostingAssetValidator extends HsHostingAssetEntityValidator integerProperty("monit_min_free_ssd").min(1).max(1000).withDefault(5), integerProperty("monit_max_hdd_usage").unit("%").min(10).max(100).withDefault(95), integerProperty("monit_min_free_hdd").min(1).max(4000).withDefault(10), - // stringProperty("monit_alarm_email").unit("GB").optional() TODO.impl: via Contact? // other settings // booleanProperty("fastcgi_small").withDefault(false), TODO.spec: clarify Salt-Grains @@ -45,4 +54,9 @@ class HsManagedServerHostingAssetValidator extends HsHostingAssetEntityValidator booleanProperty("software-imagemagick-ghostscript").withDefault(false) ); } + + @Override + protected Pattern identifierPattern(final HsHostingAssetEntity assetEntity) { + return Pattern.compile("^vm[0-9][0-9][0-9][0-9]$"); + } } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsManagedWebspaceHostingAssetValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsManagedWebspaceHostingAssetValidator.java index 19c9dc24..5b20c6f8 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsManagedWebspaceHostingAssetValidator.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsManagedWebspaceHostingAssetValidator.java @@ -1,29 +1,22 @@ package net.hostsharing.hsadminng.hs.hosting.asset.validators; +import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType; import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType; -import java.util.Collection; -import java.util.stream.Stream; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; +import java.util.regex.Pattern; class HsManagedWebspaceHostingAssetValidator extends HsHostingAssetEntityValidator { public HsManagedWebspaceHostingAssetValidator() { + super(BookingItem.mustBeOfType(HsBookingItemType.MANAGED_WEBSPACE), + ParentAsset.mustBeOfType(HsHostingAssetType.MANAGED_SERVER), // the (shared or private) ManagedServer + AssignedToAsset.mustBeNull(), + AlarmContact.isOptional(), // hostmaster alert address is implicitly added + NO_EXTRA_PROPERTIES); } @Override - public List validate(final HsHostingAssetEntity assetEntity) { - return Stream.of(validateIdentifierPattern(assetEntity), super.validate(assetEntity)) - .flatMap(Collection::stream) - .collect(Collectors.toList()); - } - - private static List validateIdentifierPattern(final HsHostingAssetEntity assetEntity) { - final var expectedIdentifierPattern = "^" + assetEntity.getParentAsset().getBookingItem().getProject().getDebitor().getDefaultPrefix() + "[0-9][0-9]$"; - if ( !assetEntity.getIdentifier().matches(expectedIdentifierPattern)) { - return List.of("'identifier' expected to match '"+expectedIdentifierPattern+"', but is '" + assetEntity.getIdentifier() + "'"); - } - return Collections.emptyList(); + protected Pattern identifierPattern(final HsHostingAssetEntity assetEntity) { + return Pattern.compile("^" + assetEntity.getParentAsset().getBookingItem().getProject().getDebitor().getDefaultPrefix() + "[0-9][0-9]$"); } } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsUnixUserHostingAssetValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsUnixUserHostingAssetValidator.java new file mode 100644 index 00000000..dfe222fc --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsUnixUserHostingAssetValidator.java @@ -0,0 +1,23 @@ +package net.hostsharing.hsadminng.hs.hosting.asset.validators; + +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType; + +import java.util.regex.Pattern; + +class HsUnixUserHostingAssetValidator extends HsHostingAssetEntityValidator { + + HsUnixUserHostingAssetValidator() { + super(BookingItem.mustBeNull(), + ParentAsset.mustBeOfType(HsHostingAssetType.MANAGED_WEBSPACE), + AssignedToAsset.mustBeNull(), + AlarmContact.isOptional(), // TODO.spec: for quota notifications + NO_EXTRA_PROPERTIES); // TODO.spec: yet to be specified + } + + @Override + protected Pattern identifierPattern(final HsHostingAssetEntity assetEntity) { + final var webspaceIdentifier = assetEntity.getParentAsset().getIdentifier(); + return Pattern.compile("^"+webspaceIdentifier+"$|^"+webspaceIdentifier+"-[a-z0-9]+$"); + } +} diff --git a/src/test/java/net/hostsharing/hsadminng/hs/booking/item/TestHsBookingItem.java b/src/test/java/net/hostsharing/hsadminng/hs/booking/item/TestHsBookingItem.java index 00c0d706..0779fa2f 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/booking/item/TestHsBookingItem.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/booking/item/TestHsBookingItem.java @@ -12,13 +12,21 @@ import static net.hostsharing.hsadminng.hs.booking.project.TestHsBookingProject. @UtilityClass public class TestHsBookingItem { - public static final HsBookingItemEntity TEST_BOOKING_ITEM = HsBookingItemEntity.builder() + public static final HsBookingItemEntity TEST_MANAGED_SERVER_BOOKING_ITEM = HsBookingItemEntity.builder() .project(TEST_PROJECT) - .caption("test booking item") + .type(HsBookingItemType.MANAGED_SERVER) + .caption("test project booking item") .resources(Map.ofEntries( entry("someThing", 1), entry("anotherThing", "blue") )) .validity(Range.closedInfinite(LocalDate.of(2020, 1, 15))) .build(); + + public static final HsBookingItemEntity TEST_CLOUD_SERVER_BOOKING_ITEM = HsBookingItemEntity.builder() + .project(TEST_PROJECT) + .type(HsBookingItemType.CLOUD_SERVER) + .caption("test cloud server booking item") + .validity(Range.closedInfinite(LocalDate.of(2020, 1, 15))) + .build(); } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntityPatcherUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntityPatcherUnitTest.java index 890932b4..96728cca 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntityPatcherUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntityPatcherUnitTest.java @@ -15,7 +15,7 @@ import java.util.Map; import java.util.UUID; import java.util.stream.Stream; -import static net.hostsharing.hsadminng.hs.booking.item.TestHsBookingItem.TEST_BOOKING_ITEM; +import static net.hostsharing.hsadminng.hs.booking.item.TestHsBookingItem.TEST_CLOUD_SERVER_BOOKING_ITEM; import static net.hostsharing.hsadminng.mapper.PatchMap.entry; import static net.hostsharing.hsadminng.mapper.PatchMap.patchMap; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; @@ -70,7 +70,7 @@ class HsHostingAssetEntityPatcherUnitTest extends PatchUnitTestBase< protected HsHostingAssetEntity newInitialEntity() { final var entity = new HsHostingAssetEntity(); entity.setUuid(INITIAL_BOOKING_ITEM_UUID); - entity.setBookingItem(TEST_BOOKING_ITEM); + entity.setBookingItem(TEST_CLOUD_SERVER_BOOKING_ITEM); entity.getConfig().putAll(KeyValueMap.from(INITIAL_CONFIG)); entity.setCaption(INITIAL_CAPTION); entity.setAlarmContact(givenInitialContact); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntityUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntityUnitTest.java index e45bdb5b..c53effff 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntityUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntityUnitTest.java @@ -5,13 +5,13 @@ import org.junit.jupiter.api.Test; import java.util.Map; import static java.util.Map.entry; -import static net.hostsharing.hsadminng.hs.booking.item.TestHsBookingItem.TEST_BOOKING_ITEM; +import static net.hostsharing.hsadminng.hs.booking.item.TestHsBookingItem.TEST_CLOUD_SERVER_BOOKING_ITEM; import static org.assertj.core.api.Assertions.assertThat; class HsHostingAssetEntityUnitTest { final HsHostingAssetEntity givenParentAsset = HsHostingAssetEntity.builder() - .bookingItem(TEST_BOOKING_ITEM) + .bookingItem(TEST_CLOUD_SERVER_BOOKING_ITEM) .type(HsHostingAssetType.MANAGED_SERVER) .identifier("vm1234") .caption("some managed asset") @@ -21,7 +21,7 @@ class HsHostingAssetEntityUnitTest { entry("HDD-storage", 2048))) .build(); final HsHostingAssetEntity givenWebspace = HsHostingAssetEntity.builder() - .bookingItem(TEST_BOOKING_ITEM) + .bookingItem(TEST_CLOUD_SERVER_BOOKING_ITEM) .type(HsHostingAssetType.MANAGED_WEBSPACE) .parentAsset(givenParentAsset) .identifier("xyz00") diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsCloudServerHostingAssetValidatorUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsCloudServerHostingAssetValidatorUnitTest.java index ee6644e0..cd872766 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsCloudServerHostingAssetValidatorUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsCloudServerHostingAssetValidatorUnitTest.java @@ -6,6 +6,7 @@ import org.junit.jupiter.api.Test; import java.util.Map; import static java.util.Map.entry; +import static net.hostsharing.hsadminng.hs.booking.item.TestHsBookingItem.TEST_CLOUD_SERVER_BOOKING_ITEM; import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.CLOUD_SERVER; import static org.assertj.core.api.Assertions.assertThat; @@ -28,7 +29,28 @@ class HsCloudServerHostingAssetValidatorUnitTest { final var result = validator.validate(cloudServerHostingAssetEntity); // then - assertThat(result).containsExactly("'CLOUD_SERVER:vm1234.config.RAM' is not expected but is set to '2000'"); + assertThat(result).containsExactlyInAnyOrder( + "'CLOUD_SERVER:vm1234.bookingItem' must not be null but is null", + "'CLOUD_SERVER:vm1234.config.RAM' is not expected but is set to '2000'"); + } + + @Test + void validatesInvalidIdentifier() { + // given + final var cloudServerHostingAssetEntity = HsHostingAssetEntity.builder() + .type(CLOUD_SERVER) + .identifier("xyz99") + .bookingItem(TEST_CLOUD_SERVER_BOOKING_ITEM) + .build(); + final var validator = HsHostingAssetEntityValidatorRegistry.forType(cloudServerHostingAssetEntity.getType()); + + + // when + final var result = validator.validate(cloudServerHostingAssetEntity); + + // then + assertThat(result).containsExactlyInAnyOrder( + "'identifier' expected to match '^vm[0-9][0-9][0-9][0-9]$', but is 'xyz99'"); } @Test diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsHostingAssetEntityValidatorUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsHostingAssetEntityValidatorUnitTest.java index ddceba8e..b3f6d02e 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsHostingAssetEntityValidatorUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsHostingAssetEntityValidatorUnitTest.java @@ -1,6 +1,9 @@ package net.hostsharing.hsadminng.hs.hosting.asset.validators; +import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity; +import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType; import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType; import org.junit.jupiter.api.Test; @@ -16,12 +19,17 @@ class HsHostingAssetEntityValidatorUnitTest { final var managedServerHostingAssetEntity = HsHostingAssetEntity.builder() .type(MANAGED_SERVER) .identifier("vm1234") + .bookingItem(HsBookingItemEntity.builder().type(HsBookingItemType.MANAGED_SERVER).build()) + .parentAsset(HsHostingAssetEntity.builder().type(MANAGED_SERVER).build()) .build(); // when final var result = catchThrowable( ()-> HsHostingAssetEntityValidatorRegistry.validated(managedServerHostingAssetEntity)); // then - assertThat(result).isNull(); // all required properties have defaults + assertThat(result.getMessage()).contains( + "'MANAGED_SERVER:vm1234.parentAsset' must not be null but is set to D-???????-?:null", + "'MANAGED_SERVER:vm1234.assignedToAsset' must not be null but is set to D-???????-?:null" + ); } } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsManagedServerHostingAssetValidatorUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsManagedServerHostingAssetValidatorUnitTest.java index d22ef590..08d2b777 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsManagedServerHostingAssetValidatorUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsManagedServerHostingAssetValidatorUnitTest.java @@ -1,5 +1,7 @@ package net.hostsharing.hsadminng.hs.hosting.asset.validators; +import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity; +import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType; import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; import org.junit.jupiter.api.Test; @@ -17,6 +19,7 @@ class HsManagedServerHostingAssetValidatorUnitTest { final var mangedWebspaceHostingAssetEntity = HsHostingAssetEntity.builder() .type(MANAGED_SERVER) .identifier("vm1234") + .bookingItem(HsBookingItemEntity.builder().type(HsBookingItemType.MANAGED_SERVER).build()) .config(Map.ofEntries( entry("monit_max_hdd_usage", "90"), entry("monit_max_cpu_usage", 2), @@ -30,8 +33,28 @@ class HsManagedServerHostingAssetValidatorUnitTest { // then assertThat(result).containsExactlyInAnyOrder( + "'MANAGED_SERVER:vm1234.parentAsset' must not be null but is set to D-???????-?:null", + "'MANAGED_SERVER:vm1234.assignedToAsset' must not be null but is set to D-???????-?:null", "'MANAGED_SERVER:vm1234.config.monit_max_cpu_usage' is expected to be >= 10 but is 2", "'MANAGED_SERVER:vm1234.config.monit_max_ram_usage' is expected to be <= 100 but is 101", "'MANAGED_SERVER:vm1234.config.monit_max_hdd_usage' is expected to be of type class java.lang.Integer, but is of type 'String'"); } + + @Test + void validatesInvalidIdentifier() { + // given + final var mangedServerHostingAssetEntity = HsHostingAssetEntity.builder() + .type(MANAGED_SERVER) + .identifier("xyz00") + .bookingItem(HsBookingItemEntity.builder().type(HsBookingItemType.MANAGED_SERVER).build()) + .build(); + final var validator = HsHostingAssetEntityValidatorRegistry.forType(mangedServerHostingAssetEntity.getType()); + + // when + final var result = validator.validate(mangedServerHostingAssetEntity); + + // then + assertThat(result).containsExactlyInAnyOrder( + "'identifier' expected to match '^vm[0-9][0-9][0-9][0-9]$', but is 'xyz00'"); + } } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsManagedWebspaceHostingAssetValidatorUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsManagedWebspaceHostingAssetValidatorUnitTest.java index d2e74894..1037e32c 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsManagedWebspaceHostingAssetValidatorUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsManagedWebspaceHostingAssetValidatorUnitTest.java @@ -40,11 +40,12 @@ class HsManagedWebspaceHostingAssetValidatorUnitTest { .build(); @Test - void validatesIdentifier() { + void validatesIdentifierAndReferencedEntities() { // given final var validator = HsHostingAssetEntityValidatorRegistry.forType(MANAGED_WEBSPACE); final var mangedWebspaceHostingAssetEntity = HsHostingAssetEntity.builder() .type(MANAGED_WEBSPACE) + .bookingItem(HsBookingItemEntity.builder().type(HsBookingItemType.MANAGED_WEBSPACE).build()) .parentAsset(mangedServerAssetEntity) .identifier("xyz00") .build(); @@ -62,6 +63,7 @@ class HsManagedWebspaceHostingAssetValidatorUnitTest { final var validator = HsHostingAssetEntityValidatorRegistry.forType(MANAGED_WEBSPACE); final var mangedWebspaceHostingAssetEntity = HsHostingAssetEntity.builder() .type(MANAGED_WEBSPACE) + .bookingItem(HsBookingItemEntity.builder().type(HsBookingItemType.MANAGED_WEBSPACE).build()) .parentAsset(mangedServerAssetEntity) .identifier("abc00") .config(Map.ofEntries( @@ -82,6 +84,7 @@ class HsManagedWebspaceHostingAssetValidatorUnitTest { final var validator = HsHostingAssetEntityValidatorRegistry.forType(MANAGED_WEBSPACE); final var mangedWebspaceHostingAssetEntity = HsHostingAssetEntity.builder() .type(MANAGED_WEBSPACE) + .bookingItem(HsBookingItemEntity.builder().type(HsBookingItemType.MANAGED_WEBSPACE).build()) .parentAsset(mangedServerAssetEntity) .identifier("abc00") .build(); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsUnixUserHostingAssetValidatorUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsUnixUserHostingAssetValidatorUnitTest.java new file mode 100644 index 00000000..427061e5 --- /dev/null +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsUnixUserHostingAssetValidatorUnitTest.java @@ -0,0 +1,27 @@ +package net.hostsharing.hsadminng.hs.hosting.asset.validators; + +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; +import org.junit.jupiter.api.Test; + +import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.UNIX_USER; +import static org.assertj.core.api.Assertions.assertThat; + +class HsUnixUserHostingAssetValidatorUnitTest { + + @Test + void validatesInvalidIdentifier() { + // given + final var unixUserHostingAsset = HsHostingAssetEntity.builder() + .type(UNIX_USER) + .identifier("abc") + .build(); + final var validator = HsHostingAssetEntityValidatorRegistry.forType(unixUserHostingAsset.getType()); + + + // when + final var result = validator.validate(unixUserHostingAsset); + + // then + assertThat(result).containsExactly("'identifier' expected to match '^vm[0-9][0-9][0-9][0-9]$', but is 'xyz99'"); + } +}