From e5db6ebe56ef0455012c24c825716c472cd2f5ce Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Mon, 15 Jul 2024 17:37:30 +0200 Subject: [PATCH] add IPV6_NUMBER/HsIPv6NumberHostingAssetValidator and separate PlantUML for Webspace+Server --- doc/hs-hosting-asset-type-structure.md | 99 +++++++------ .../hs/booking/item/HsBookingItemType.java | 8 +- .../hsadminng/hs/booking/item/Node.java | 4 +- .../hs/hosting/asset/HsHostingAssetType.java | 39 +++-- .../HostingAssetEntityValidatorRegistry.java | 1 + .../HsIPv4NumberHostingAssetValidator.java | 2 +- .../HsIPv6NumberHostingAssetValidator.java | 49 +++++++ .../hs-hosting/hs-hosting-asset-schemas.yaml | 1 + .../7010-hs-hosting-asset.sql | 4 +- .../HsHostingAssetControllerRestTest.java | 19 +++ ...ingAssetPropsControllerAcceptanceTest.java | 3 +- .../asset/HsHostingAssetTypeUnitTest.java | 137 +++++++++--------- ...gAssetEntityValidatorRegistryUnitTest.java | 3 +- ...v6NumberHostingAssetValidatorUnitTest.java | 120 +++++++++++++++ 14 files changed, 356 insertions(+), 133 deletions(-) create mode 100644 src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsIPv6NumberHostingAssetValidator.java create mode 100644 src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsIPv6NumberHostingAssetValidatorUnitTest.java diff --git a/doc/hs-hosting-asset-type-structure.md b/doc/hs-hosting-asset-type-structure.md index f7310316..a64e2ff0 100644 --- a/doc/hs-hosting-asset-type-structure.md +++ b/doc/hs-hosting-asset-type-structure.md @@ -1,6 +1,49 @@ ## HostingAsset Type Structure +### Webspace+Server + +```plantuml +@startuml +left to right direction + +package Booking #feb28c { + entity BI_PRIVATE_CLOUD + entity BI_CLOUD_SERVER + entity BI_MANAGED_SERVER + entity BI_MANAGED_WEBSPACE +} + +package Hosting #feb28c{ + package Server #99bcdb { + entity HA_CLOUD_SERVER + entity HA_MANAGED_SERVER + entity HA_IPV4_NUMBER + entity HA_IPV6_NUMBER + } + +} + +BI_CLOUD_SERVER *--> BI_PRIVATE_CLOUD +BI_MANAGED_SERVER *--> BI_PRIVATE_CLOUD +BI_MANAGED_WEBSPACE *--> BI_MANAGED_SERVER + +HA_CLOUD_SERVER *==> BI_CLOUD_SERVER +HA_MANAGED_SERVER *==> BI_MANAGED_SERVER +HA_IPV4_NUMBER o..> HA_CLOUD_SERVER +HA_IPV4_NUMBER o..> HA_MANAGED_SERVER +HA_IPV6_NUMBER o..> HA_CLOUD_SERVER +HA_IPV6_NUMBER o..> HA_MANAGED_SERVER + +package Legend #white { + SUB_ENTITY1 *--> REQUIRED_PARENT_ENTITY + SUB_ENTITY2 *..> OPTIONAL_PARENT_ENTITY + ASSIGNED_ENTITY1 o--> REQUIRED_ASSIGNED_TO_ENTITY1 + ASSIGNED_ENTITY2 o..> OPTIONAL_ASSIGNED_TO_ENTITY2 +} +Booking -down[hidden]->Legend +``` + ### Domain ```plantuml @@ -24,12 +67,6 @@ package Hosting #feb28c{ entity HA_EMAIL_ADDRESS } - package Server #99bcdb { - entity HA_CLOUD_SERVER - entity HA_MANAGED_SERVER - entity HA_IP_NUMBER - } - package Webspace #99bcdb { entity HA_MANAGED_WEBSPACE entity HA_UNIX_USER @@ -42,25 +79,19 @@ BI_CLOUD_SERVER *--> BI_PRIVATE_CLOUD BI_MANAGED_SERVER *--> BI_PRIVATE_CLOUD BI_MANAGED_WEBSPACE *--> BI_MANAGED_SERVER -HA_CLOUD_SERVER *==> BI_CLOUD_SERVER -HA_MANAGED_SERVER *==> BI_MANAGED_SERVER HA_MANAGED_WEBSPACE *==> BI_MANAGED_WEBSPACE -HA_MANAGED_WEBSPACE o..> HA_MANAGED_SERVER HA_UNIX_USER *==> HA_MANAGED_WEBSPACE HA_EMAIL_ALIAS *==> HA_MANAGED_WEBSPACE HA_DOMAIN_SETUP o..> HA_DOMAIN_SETUP HA_DOMAIN_DNS_SETUP *==> HA_DOMAIN_SETUP -HA_DOMAIN_DNS_SETUP o..> HA_MANAGED_WEBSPACE +HA_DOMAIN_DNS_SETUP o--> HA_MANAGED_WEBSPACE HA_DOMAIN_HTTP_SETUP *==> HA_DOMAIN_SETUP -HA_DOMAIN_HTTP_SETUP o..> HA_UNIX_USER +HA_DOMAIN_HTTP_SETUP o--> HA_UNIX_USER HA_DOMAIN_SMTP_SETUP *==> HA_DOMAIN_SETUP -HA_DOMAIN_SMTP_SETUP o..> HA_MANAGED_WEBSPACE +HA_DOMAIN_SMTP_SETUP o--> HA_MANAGED_WEBSPACE HA_DOMAIN_MBOX_SETUP *==> HA_DOMAIN_SETUP -HA_DOMAIN_MBOX_SETUP o..> HA_MANAGED_WEBSPACE +HA_DOMAIN_MBOX_SETUP o--> HA_MANAGED_WEBSPACE HA_EMAIL_ADDRESS *==> HA_DOMAIN_MBOX_SETUP -HA_IP_NUMBER o..> HA_CLOUD_SERVER -HA_IP_NUMBER o..> HA_MANAGED_SERVER -HA_IP_NUMBER o..> HA_MANAGED_WEBSPACE package Legend #white { SUB_ENTITY1 *--> REQUIRED_PARENT_ENTITY @@ -91,12 +122,6 @@ package Hosting #feb28c{ entity HA_MARIADB_DATABASE } - package Server #99bcdb { - entity HA_CLOUD_SERVER - entity HA_MANAGED_SERVER - entity HA_IP_NUMBER - } - package Webspace #99bcdb { entity HA_MANAGED_WEBSPACE entity HA_UNIX_USER @@ -109,20 +134,12 @@ BI_CLOUD_SERVER *--> BI_PRIVATE_CLOUD BI_MANAGED_SERVER *--> BI_PRIVATE_CLOUD BI_MANAGED_WEBSPACE *--> BI_MANAGED_SERVER -HA_CLOUD_SERVER *==> BI_CLOUD_SERVER -HA_MANAGED_SERVER *==> BI_MANAGED_SERVER HA_MANAGED_WEBSPACE *==> BI_MANAGED_WEBSPACE -HA_MANAGED_WEBSPACE o..> HA_MANAGED_SERVER HA_UNIX_USER *==> HA_MANAGED_WEBSPACE HA_EMAIL_ALIAS *==> HA_MANAGED_WEBSPACE -HA_MARIADB_INSTANCE *==> HA_MANAGED_SERVER HA_MARIADB_USER *==> HA_MANAGED_WEBSPACE -HA_MARIADB_USER o..> HA_MARIADB_INSTANCE +HA_MARIADB_USER o--> HA_MARIADB_INSTANCE HA_MARIADB_DATABASE *==> HA_MARIADB_USER -HA_MARIADB_DATABASE o..> HA_MARIADB_INSTANCE -HA_IP_NUMBER o..> HA_CLOUD_SERVER -HA_IP_NUMBER o..> HA_MANAGED_SERVER -HA_IP_NUMBER o..> HA_MANAGED_WEBSPACE package Legend #white { SUB_ENTITY1 *--> REQUIRED_PARENT_ENTITY @@ -153,12 +170,6 @@ package Hosting #feb28c{ entity HA_PGSQL_DATABASE } - package Server #99bcdb { - entity HA_CLOUD_SERVER - entity HA_MANAGED_SERVER - entity HA_IP_NUMBER - } - package Webspace #99bcdb { entity HA_MANAGED_WEBSPACE entity HA_UNIX_USER @@ -171,20 +182,12 @@ BI_CLOUD_SERVER *--> BI_PRIVATE_CLOUD BI_MANAGED_SERVER *--> BI_PRIVATE_CLOUD BI_MANAGED_WEBSPACE *--> BI_MANAGED_SERVER -HA_CLOUD_SERVER *==> BI_CLOUD_SERVER -HA_MANAGED_SERVER *==> BI_MANAGED_SERVER HA_MANAGED_WEBSPACE *==> BI_MANAGED_WEBSPACE -HA_MANAGED_WEBSPACE o..> HA_MANAGED_SERVER HA_UNIX_USER *==> HA_MANAGED_WEBSPACE HA_EMAIL_ALIAS *==> HA_MANAGED_WEBSPACE -HA_PGSQL_INSTANCE *==> HA_MANAGED_SERVER -HA_PGSQL_USER *==> HA_PGSQL_INSTANCE -HA_PGSQL_USER o..> HA_MANAGED_WEBSPACE -HA_PGSQL_DATABASE *==> HA_MANAGED_WEBSPACE -HA_PGSQL_DATABASE o..> HA_PGSQL_INSTANCE -HA_IP_NUMBER o..> HA_CLOUD_SERVER -HA_IP_NUMBER o..> HA_MANAGED_SERVER -HA_IP_NUMBER o..> HA_MANAGED_WEBSPACE +HA_PGSQL_USER *==> HA_MANAGED_WEBSPACE +HA_PGSQL_USER o--> HA_PGSQL_INSTANCE +HA_PGSQL_DATABASE *==> HA_PGSQL_USER package Legend #white { SUB_ENTITY1 *--> REQUIRED_PARENT_ENTITY diff --git a/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemType.java b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemType.java index 8b51def8..9defc478 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemType.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemType.java @@ -1,6 +1,7 @@ package net.hostsharing.hsadminng.hs.booking.item; import java.util.List; +import java.util.Set; import static java.util.Optional.ofNullable; @@ -21,12 +22,17 @@ public enum HsBookingItemType implements Node { } @Override - public List edges() { + public List edges(final Set inGroups) { return ofNullable(parentItemType) .map(p -> (nodeName() + " *--> " + p.nodeName())) .stream().toList(); } + @Override + public boolean belongsToAny(final Set groups) { + return true; + } + @Override public String nodeName() { return "BI_" + name(); diff --git a/src/main/java/net/hostsharing/hsadminng/hs/booking/item/Node.java b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/Node.java index cca14f5a..139fa05f 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/booking/item/Node.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/Node.java @@ -1,9 +1,11 @@ package net.hostsharing.hsadminng.hs.booking.item; import java.util.List; +import java.util.Set; public interface Node { String nodeName(); - List edges(); + boolean belongsToAny(Set groups); + List edges(final Set inGroup); } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetType.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetType.java index e9e42918..de7f937b 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetType.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetType.java @@ -5,7 +5,6 @@ import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity; import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType; import net.hostsharing.hsadminng.hs.booking.item.Node; -import jakarta.validation.constraints.NotNull; import javax.naming.NamingException; import java.io.IOException; import java.nio.file.Files; @@ -30,7 +29,6 @@ import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.Rela import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.RelationType.ASSIGNED_TO_ASSET; import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.RelationType.BOOKING_ITEM; import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.RelationType.PARENT_ASSET; -import static net.hostsharing.hsadminng.mapper.Array.emptyArray; public enum HsHostingAssetType implements Node { SAME_TYPE, // pseudo-type for recursive references @@ -116,22 +114,27 @@ public enum HsHostingAssetType implements Node { IPV4_NUMBER( inGroup("Server"), optionallyAssignedTo(CLOUD_SERVER).or(MANAGED_SERVER).or(MANAGED_WEBSPACE) + ), + + IPV6_NUMBER( + inGroup("Server"), + optionallyAssignedTo(CLOUD_SERVER).or(MANAGED_SERVER).or(MANAGED_WEBSPACE) ); private final String groupName; private final EntityTypeRelation[] relations; HsHostingAssetType( - String groupName, - @NotNull final EntityTypeRelation... relations - ) { + final String groupName, + final EntityTypeRelation... relations + ) { this.groupName = groupName; this.relations = relations; } HsHostingAssetType() { this.groupName = null; - this.relations = emptyArray(EntityTypeRelation.class); + this.relations = null; } /// just syntactic sugar @@ -200,14 +203,22 @@ public enum HsHostingAssetType implements Node { } @Override - public List edges() { + public List edges(final Set inGroups) { return stream(relations) - .map(r -> r.relatedTypes(this).stream().map(x -> nodeName() + r.edge + x.nodeName()).toList()) + .map(r -> r.relatedTypes(this).stream() + .filter(x -> x.belongsToAny(inGroups)) + .map(x -> nodeName() + r.edge + x.nodeName()) + .toList()) .flatMap(List::stream) .sorted() .toList(); } + @Override + public boolean belongsToAny(final Set groups) { + return groups.contains(this.groupName); + } + @Override public String nodeName() { return "HA_" + name(); @@ -233,12 +244,12 @@ public enum HsHostingAssetType implements Node { .map(t -> "entity " + t.nodeName()) .collect(joining("\n")); final String bookingItemEdges = stream(HsBookingItemType.values()) - .map(HsBookingItemType::edges) + .map(t -> t.edges(includedHostingGroups)) .flatMap(Collection::stream) .collect(joining("\n")); final String hostingAssetEdges = stream(HsHostingAssetType.values()) .filter(t -> t.isInGroups(includedHostingGroups)) - .map(HsHostingAssetType::edges) + .map(t -> t.edges(includedHostingGroups)) .flatMap(Collection::stream) .collect(joining("\n")); return """ @@ -304,9 +315,11 @@ public enum HsHostingAssetType implements Node { .map(t -> t.groupName) .collect(toSet())); - markdown.append(renderAsPlantUML("Domain", Set.of("Domain", "Webspace", "Server"))) - .append(renderAsPlantUML("MariaDB", Set.of("MariaDB", "Webspace", "Server"))) - .append(renderAsPlantUML("PostgreSQL", Set.of("PostgreSQL", "Webspace", "Server"))); + markdown + .append(renderAsPlantUML("Webspace+Server", Set.of("Server"))) + .append(renderAsPlantUML("Domain", Set.of("Domain", "Webspace"))) + .append(renderAsPlantUML("MariaDB", Set.of("MariaDB", "Webspace"))) + .append(renderAsPlantUML("PostgreSQL", Set.of("PostgreSQL", "Webspace"))); markdown.append(""" diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HostingAssetEntityValidatorRegistry.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HostingAssetEntityValidatorRegistry.java index 93247466..696beafe 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HostingAssetEntityValidatorRegistry.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HostingAssetEntityValidatorRegistry.java @@ -33,6 +33,7 @@ public class HostingAssetEntityValidatorRegistry { register(PGSQL_USER, new HsPostgreSqlUserHostingAssetValidator()); register(PGSQL_DATABASE, new HsPostgreSqlDatabaseHostingAssetValidator()); register(IPV4_NUMBER, new HsIPv4NumberHostingAssetValidator()); + register(IPV6_NUMBER, new HsIPv6NumberHostingAssetValidator()); } private static void register(final Enum type, final HsEntityValidator validator) { diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsIPv4NumberHostingAssetValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsIPv4NumberHostingAssetValidator.java index b4889fe0..235a32c2 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsIPv4NumberHostingAssetValidator.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsIPv4NumberHostingAssetValidator.java @@ -8,7 +8,7 @@ import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.IPV4 class HsIPv4NumberHostingAssetValidator extends HostingAssetEntityValidator { - public static Pattern IPV4_REGEX = Pattern.compile("^((25[0-5]|(2[0-4]|1\\d|[1-9]|)\\d)\\.?\\b){4}$"); + private static final Pattern IPV4_REGEX = Pattern.compile("^((25[0-5]|(2[0-4]|1\\d|[1-9]|)\\d)\\.?\\b){4}$"); HsIPv4NumberHostingAssetValidator() { super( diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsIPv6NumberHostingAssetValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsIPv6NumberHostingAssetValidator.java new file mode 100644 index 00000000..b910ea82 --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsIPv6NumberHostingAssetValidator.java @@ -0,0 +1,49 @@ +package net.hostsharing.hsadminng.hs.hosting.asset.validators; + +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.List; +import java.util.regex.Pattern; + +import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.IPV6_NUMBER; + +class HsIPv6NumberHostingAssetValidator extends HostingAssetEntityValidator { + + // simplified pattern, the real check is done by letting Java parse the address + private static final Pattern IPV6_REGEX = Pattern.compile("([a-f0-9:]+:+)+[a-f0-9]+"); + + HsIPv6NumberHostingAssetValidator() { + super( + IPV6_NUMBER, + AlarmContact.isOptional(), + + NO_EXTRA_PROPERTIES + ); + } + + @Override + public List validateEntity(final HsHostingAssetEntity assetEntity) { + final var violations = super.validateEntity(assetEntity); + + if (!isValidIPv6Address(assetEntity.getIdentifier())) { + violations.add("'identifier' expected to be a valid IPv6 address, but is '" + assetEntity.getIdentifier() + "'"); + } + + return violations; + } + + @Override + protected Pattern identifierPattern(final HsHostingAssetEntity assetEntity) { + return IPV6_REGEX; + } + + private boolean isValidIPv6Address(final String identifier) { + try { + return InetAddress.getByName(identifier) instanceof java.net.Inet6Address; + } catch (UnknownHostException e) { + return false; + } + } +} diff --git a/src/main/resources/api-definition/hs-hosting/hs-hosting-asset-schemas.yaml b/src/main/resources/api-definition/hs-hosting/hs-hosting-asset-schemas.yaml index da0fec1e..b65a8a51 100644 --- a/src/main/resources/api-definition/hs-hosting/hs-hosting-asset-schemas.yaml +++ b/src/main/resources/api-definition/hs-hosting/hs-hosting-asset-schemas.yaml @@ -24,6 +24,7 @@ components: - MARIADB_USER - MARIADB_DATABASE - IPV4_NUMBER + - IPV6_NUMBER HsHostingAsset: type: object diff --git a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7010-hs-hosting-asset.sql b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7010-hs-hosting-asset.sql index c218a701..b54629ee 100644 --- a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7010-hs-hosting-asset.sql +++ b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7010-hs-hosting-asset.sql @@ -22,7 +22,8 @@ create type HsHostingAssetType as enum ( 'MARIADB_INSTANCE', 'MARIADB_USER', 'MARIADB_DATABASE', - 'IPV4_NUMBER' + 'IPV4_NUMBER', + 'IPV6_NUMBER' ); CREATE CAST (character varying as HsHostingAssetType) WITH INOUT AS IMPLICIT; @@ -88,6 +89,7 @@ begin when 'MARIADB_DATABASE' then 'MARIADB_USER' when 'IPV4_NUMBER' then null + when 'IPV6_NUMBER' then null else raiseException(format('[400] unknown asset type %s', NEW.type::text)) end); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetControllerRestTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetControllerRestTest.java index a1842e0f..3faaed22 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetControllerRestTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetControllerRestTest.java @@ -507,6 +507,25 @@ public class HsHostingAssetControllerRestTest { "config": {} } ] + """), + IPV6_NUMBER( + List.of( + HsHostingAssetEntity.builder() + .type(HsHostingAssetType.IPV4_NUMBER) + .assignedToAsset(TEST_MANAGED_SERVER_HOSTING_ASSET) + .identifier("2001:db8:3333:4444:5555:6666:7777:8888") + .caption("some fake IPv6 number") + .build()), + """ + [ + { + "type": "IPV4_NUMBER", + "identifier": "2001:db8:3333:4444:5555:6666:7777:8888", + "caption": "some fake IPv6 number", + "alarmContact": null, + "config": {} + } + ] """); final HsHostingAssetType assetType; diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetPropsControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetPropsControllerAcceptanceTest.java index 41518b2e..6b9188e6 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetPropsControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetPropsControllerAcceptanceTest.java @@ -48,7 +48,8 @@ class HsHostingAssetPropsControllerAcceptanceTest { "PGSQL_INSTANCE", "PGSQL_USER", "PGSQL_DATABASE", - "IPV4_NUMBER" + "IPV4_NUMBER", + "IPV6_NUMBER" ] """)); // @formatter:on diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetTypeUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetTypeUnitTest.java index 3d29dc3c..c0b97d1f 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetTypeUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetTypeUnitTest.java @@ -14,19 +14,62 @@ class HsHostingAssetTypeUnitTest { ## HostingAsset Type Structure - ### Domain - + ### Webspace+Server + ```plantuml @startuml left to right direction - + package Booking #feb28c { entity BI_PRIVATE_CLOUD entity BI_CLOUD_SERVER entity BI_MANAGED_SERVER entity BI_MANAGED_WEBSPACE } - + + package Hosting #feb28c{ + package Server #99bcdb { + entity HA_CLOUD_SERVER + entity HA_MANAGED_SERVER + entity HA_IPV4_NUMBER + entity HA_IPV6_NUMBER + } + + } + + BI_CLOUD_SERVER *--> BI_PRIVATE_CLOUD + BI_MANAGED_SERVER *--> BI_PRIVATE_CLOUD + BI_MANAGED_WEBSPACE *--> BI_MANAGED_SERVER + + HA_CLOUD_SERVER *==> BI_CLOUD_SERVER + HA_MANAGED_SERVER *==> BI_MANAGED_SERVER + HA_IPV4_NUMBER o..> HA_CLOUD_SERVER + HA_IPV4_NUMBER o..> HA_MANAGED_SERVER + HA_IPV6_NUMBER o..> HA_CLOUD_SERVER + HA_IPV6_NUMBER o..> HA_MANAGED_SERVER + + package Legend #white { + SUB_ENTITY1 *--> REQUIRED_PARENT_ENTITY + SUB_ENTITY2 *..> OPTIONAL_PARENT_ENTITY + ASSIGNED_ENTITY1 o--> REQUIRED_ASSIGNED_TO_ENTITY1 + ASSIGNED_ENTITY2 o..> OPTIONAL_ASSIGNED_TO_ENTITY2 + } + Booking -down[hidden]->Legend + ``` + + ### Domain + + ```plantuml + @startuml + left to right direction + + package Booking #feb28c { + entity BI_PRIVATE_CLOUD + entity BI_CLOUD_SERVER + entity BI_MANAGED_SERVER + entity BI_MANAGED_WEBSPACE + } + package Hosting #feb28c{ package Domain #99bcdb { entity HA_DOMAIN_SETUP @@ -36,29 +79,20 @@ class HsHostingAssetTypeUnitTest { entity HA_DOMAIN_MBOX_SETUP entity HA_EMAIL_ADDRESS } - - package Server #99bcdb { - entity HA_CLOUD_SERVER - entity HA_MANAGED_SERVER - entity HA_IPV4_NUMBER - } - + package Webspace #99bcdb { entity HA_MANAGED_WEBSPACE entity HA_UNIX_USER entity HA_EMAIL_ALIAS } - + } - + BI_CLOUD_SERVER *--> BI_PRIVATE_CLOUD BI_MANAGED_SERVER *--> BI_PRIVATE_CLOUD BI_MANAGED_WEBSPACE *--> BI_MANAGED_SERVER - - HA_CLOUD_SERVER *==> BI_CLOUD_SERVER - HA_MANAGED_SERVER *==> BI_MANAGED_SERVER + HA_MANAGED_WEBSPACE *==> BI_MANAGED_WEBSPACE - HA_MANAGED_WEBSPACE o..> HA_MANAGED_SERVER HA_UNIX_USER *==> HA_MANAGED_WEBSPACE HA_EMAIL_ALIAS *==> HA_MANAGED_WEBSPACE HA_DOMAIN_SETUP o..> HA_DOMAIN_SETUP @@ -71,10 +105,7 @@ class HsHostingAssetTypeUnitTest { HA_DOMAIN_MBOX_SETUP *==> HA_DOMAIN_SETUP HA_DOMAIN_MBOX_SETUP o--> HA_MANAGED_WEBSPACE HA_EMAIL_ADDRESS *==> HA_DOMAIN_MBOX_SETUP - HA_IPV4_NUMBER o..> HA_CLOUD_SERVER - HA_IPV4_NUMBER o..> HA_MANAGED_SERVER - HA_IPV4_NUMBER o..> HA_MANAGED_WEBSPACE - + package Legend #white { SUB_ENTITY1 *--> REQUIRED_PARENT_ENTITY SUB_ENTITY2 *..> OPTIONAL_PARENT_ENTITY @@ -83,59 +114,46 @@ class HsHostingAssetTypeUnitTest { } Booking -down[hidden]->Legend ``` - + ### MariaDB - + ```plantuml @startuml left to right direction - + package Booking #feb28c { entity BI_PRIVATE_CLOUD entity BI_CLOUD_SERVER entity BI_MANAGED_SERVER entity BI_MANAGED_WEBSPACE } - + package Hosting #feb28c{ package MariaDB #99bcdb { entity HA_MARIADB_INSTANCE entity HA_MARIADB_USER entity HA_MARIADB_DATABASE } - - package Server #99bcdb { - entity HA_CLOUD_SERVER - entity HA_MANAGED_SERVER - entity HA_IPV4_NUMBER - } - + package Webspace #99bcdb { entity HA_MANAGED_WEBSPACE entity HA_UNIX_USER entity HA_EMAIL_ALIAS } - + } - + BI_CLOUD_SERVER *--> BI_PRIVATE_CLOUD BI_MANAGED_SERVER *--> BI_PRIVATE_CLOUD BI_MANAGED_WEBSPACE *--> BI_MANAGED_SERVER - - HA_CLOUD_SERVER *==> BI_CLOUD_SERVER - HA_MANAGED_SERVER *==> BI_MANAGED_SERVER + HA_MANAGED_WEBSPACE *==> BI_MANAGED_WEBSPACE - HA_MANAGED_WEBSPACE o..> HA_MANAGED_SERVER HA_UNIX_USER *==> HA_MANAGED_WEBSPACE HA_EMAIL_ALIAS *==> HA_MANAGED_WEBSPACE - HA_MARIADB_INSTANCE *==> HA_MANAGED_SERVER HA_MARIADB_USER *==> HA_MANAGED_WEBSPACE HA_MARIADB_USER o--> HA_MARIADB_INSTANCE HA_MARIADB_DATABASE *==> HA_MARIADB_USER - HA_IPV4_NUMBER o..> HA_CLOUD_SERVER - HA_IPV4_NUMBER o..> HA_MANAGED_SERVER - HA_IPV4_NUMBER o..> HA_MANAGED_WEBSPACE - + package Legend #white { SUB_ENTITY1 *--> REQUIRED_PARENT_ENTITY SUB_ENTITY2 *..> OPTIONAL_PARENT_ENTITY @@ -144,59 +162,46 @@ class HsHostingAssetTypeUnitTest { } Booking -down[hidden]->Legend ``` - + ### PostgreSQL - + ```plantuml @startuml left to right direction - + package Booking #feb28c { entity BI_PRIVATE_CLOUD entity BI_CLOUD_SERVER entity BI_MANAGED_SERVER entity BI_MANAGED_WEBSPACE } - + package Hosting #feb28c{ package PostgreSQL #99bcdb { entity HA_PGSQL_INSTANCE entity HA_PGSQL_USER entity HA_PGSQL_DATABASE } - - package Server #99bcdb { - entity HA_CLOUD_SERVER - entity HA_MANAGED_SERVER - entity HA_IPV4_NUMBER - } - + package Webspace #99bcdb { entity HA_MANAGED_WEBSPACE entity HA_UNIX_USER entity HA_EMAIL_ALIAS } - + } - + BI_CLOUD_SERVER *--> BI_PRIVATE_CLOUD BI_MANAGED_SERVER *--> BI_PRIVATE_CLOUD BI_MANAGED_WEBSPACE *--> BI_MANAGED_SERVER - - HA_CLOUD_SERVER *==> BI_CLOUD_SERVER - HA_MANAGED_SERVER *==> BI_MANAGED_SERVER + HA_MANAGED_WEBSPACE *==> BI_MANAGED_WEBSPACE - HA_MANAGED_WEBSPACE o..> HA_MANAGED_SERVER HA_UNIX_USER *==> HA_MANAGED_WEBSPACE HA_EMAIL_ALIAS *==> HA_MANAGED_WEBSPACE - HA_PGSQL_INSTANCE *==> HA_MANAGED_SERVER HA_PGSQL_USER *==> HA_MANAGED_WEBSPACE HA_PGSQL_USER o--> HA_PGSQL_INSTANCE HA_PGSQL_DATABASE *==> HA_PGSQL_USER - HA_IPV4_NUMBER o..> HA_CLOUD_SERVER - HA_IPV4_NUMBER o..> HA_MANAGED_SERVER - HA_IPV4_NUMBER o..> HA_MANAGED_WEBSPACE - + package Legend #white { SUB_ENTITY1 *--> REQUIRED_PARENT_ENTITY SUB_ENTITY2 *..> OPTIONAL_PARENT_ENTITY @@ -205,7 +210,7 @@ class HsHostingAssetTypeUnitTest { } Booking -down[hidden]->Legend ``` - + This code generated was by HsHostingAssetType.main, do not amend manually. """); } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HostingAssetEntityValidatorRegistryUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HostingAssetEntityValidatorRegistryUnitTest.java index 3840b426..f6f9a510 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HostingAssetEntityValidatorRegistryUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HostingAssetEntityValidatorRegistryUnitTest.java @@ -46,7 +46,8 @@ class HostingAssetEntityValidatorRegistryUnitTest { HsHostingAssetType.PGSQL_INSTANCE, HsHostingAssetType.PGSQL_USER, HsHostingAssetType.PGSQL_DATABASE, - HsHostingAssetType.IPV4_NUMBER + HsHostingAssetType.IPV4_NUMBER, + HsHostingAssetType.IPV6_NUMBER ); } } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsIPv6NumberHostingAssetValidatorUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsIPv6NumberHostingAssetValidatorUnitTest.java new file mode 100644 index 00000000..51d86986 --- /dev/null +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsIPv6NumberHostingAssetValidatorUnitTest.java @@ -0,0 +1,120 @@ +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.HsHostingAssetEntity.HsHostingAssetEntityBuilder; +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; +import org.junit.jupiter.params.provider.ValueSource; + +import java.util.Map; + +import static java.util.Map.entry; +import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.IPV6_NUMBER; +import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_WEBSPACE; +import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.UNIX_USER; +import static org.assertj.core.api.Assertions.assertThat; + +class HsIPv6NumberHostingAssetValidatorUnitTest { + + static HsHostingAssetEntityBuilder validEntityBuilder() { + return HsHostingAssetEntity.builder() + .type(IPV6_NUMBER) + .identifier("2001:db8:3333:4444:5555:6666:7777:8888"); + } + + @Test + void containsExpectedProperties() { + // when + final var validator = HostingAssetEntityValidatorRegistry.forType(IPV6_NUMBER); + + // then + assertThat(validator.properties()).map(Map::toString).isEmpty(); + } + + @Test + void acceptsValidEntity() { + // given + final var givenEntity = validEntityBuilder().build(); + final var validator = HostingAssetEntityValidatorRegistry.forType(givenEntity.getType()); + + // when + final var result = validator.validateEntity(givenEntity); + + // then + assertThat(result).isEmpty(); + } + + @ParameterizedTest + @ValueSource(strings = {"83.223.95", "2a01:37:1000::53df:5f91:0:123::123"}) + void rejectsInvalidIdentifier(final String givenIdentifier) { + // given + final var givenEntity = validEntityBuilder().identifier(givenIdentifier).build(); + final var validator = HostingAssetEntityValidatorRegistry.forType(givenEntity.getType()); + + // when + final var result = validator.validateEntity(givenEntity); + + // then + assertThat(result).contains( + "'identifier' expected to be a valid IPv6 address, but is '" + givenIdentifier + "'" + ); + } + + @ParameterizedTest + @EnumSource(value = HsHostingAssetType.class, names = { "CLOUD_SERVER", "MANAGED_SERVER", "MANAGED_WEBSPACE" }) + void acceptsValidReferencedEntity(final HsHostingAssetType givenAssignedToAssetType) { + // given + final var ipNumberHostingAssetEntity = validEntityBuilder() + .assignedToAsset(HsHostingAssetEntity.builder().type(givenAssignedToAssetType).build()) + .build(); + final var validator = HostingAssetEntityValidatorRegistry.forType(ipNumberHostingAssetEntity.getType()); + + // when + final var result = validator.validateEntity(ipNumberHostingAssetEntity); + + // then + assertThat(result).isEmpty(); + } + + @Test + void rejectsInvalidReferencedEntities() { + // given + final var ipNumberHostingAssetEntity = validEntityBuilder() + .bookingItem(HsBookingItemEntity.builder().type(HsBookingItemType.CLOUD_SERVER).build()) + .parentAsset(HsHostingAssetEntity.builder().type(MANAGED_WEBSPACE).build()) + .assignedToAsset(HsHostingAssetEntity.builder().type(UNIX_USER).build()) + .build(); + final var validator = HostingAssetEntityValidatorRegistry.forType(ipNumberHostingAssetEntity.getType()); + + // when + final var result = validator.validateEntity(ipNumberHostingAssetEntity); + + // then + assertThat(result).containsExactlyInAnyOrder( + "'IPV6_NUMBER:2001:db8:3333:4444:5555:6666:7777:8888.bookingItem' must be null but is of type CLOUD_SERVER", + "'IPV6_NUMBER:2001:db8:3333:4444:5555:6666:7777:8888.parentAsset' must be null but is of type MANAGED_WEBSPACE", + "'IPV6_NUMBER:2001:db8:3333:4444:5555:6666:7777:8888.assignedToAsset' must be null or of type CLOUD_SERVER or MANAGED_SERVER or MANAGED_WEBSPACE but is of type UNIX_USER"); + } + + @Test + void rejectsInvalidProperties() { + // given + final var ipNumberHostingAssetEntity = validEntityBuilder() + .config(Map.ofEntries( + entry("any", "false") + )) + .build(); + final var validator = HostingAssetEntityValidatorRegistry.forType(ipNumberHostingAssetEntity.getType()); + + // when + final var result = validator.validateEntity(ipNumberHostingAssetEntity); + + // then + assertThat(result).containsExactlyInAnyOrder( + "'IPV6_NUMBER:2001:db8:3333:4444:5555:6666:7777:8888.config.any' is not expected but is set to 'false'"); + } +}