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 0054974b..669c4ca1 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 @@ -105,8 +105,8 @@ public enum HsHostingAssetType implements Node { MARIADB_DATABASE( // named e.g. xyz00_abc inGroup("MariaDB"), - requiredParent(MANAGED_WEBSPACE), // TODO.spec: or MARIADB_USER? - assignedTo(MARIADB_INSTANCE)), // TODO.spec: or swapping parent+assignedTo? + requiredParent(MARIADB_INSTANCE), // TODO.spec: or MARIADB_USER? + assignedTo(MARIADB_USER)), // TODO.spec: or swapping parent+assignedTo? IP_NUMBER( inGroup("Server"), 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 bf93e19f..be6778cb 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 @@ -28,6 +28,7 @@ public class HostingAssetEntityValidatorRegistry { register(EMAIL_ADDRESS, new HsEMailAddressHostingAssetValidator()); register(MARIADB_INSTANCE, new HsMariaDbInstanceHostingAssetValidator()); register(MARIADB_USER, new HsMariaDbUserHostingAssetValidator()); + register(MARIADB_DATABASE, new HsMariaDbDatabaseHostingAssetValidator()); } private static void register(final Enum type, final HsEntityValidator validator) { diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsMariaDbDatabaseHostingAssetValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsMariaDbDatabaseHostingAssetValidator.java new file mode 100644 index 00000000..593556e6 --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsMariaDbDatabaseHostingAssetValidator.java @@ -0,0 +1,26 @@ +package net.hostsharing.hsadminng.hs.hosting.asset.validators; + +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; + +import java.util.regex.Pattern; + +import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MARIADB_DATABASE; +import static net.hostsharing.hsadminng.hs.validation.StringProperty.stringProperty; + +class HsMariaDbDatabaseHostingAssetValidator extends HostingAssetEntityValidator { + + public HsMariaDbDatabaseHostingAssetValidator() { + super( + MARIADB_DATABASE, + AlarmContact.isOptional(), + + stringProperty("encoding").matchesRegEx("[a-z0-9_]+").maxLength(24).provided("latin2", "utf8").withDefault("utf8"), + stringProperty("collation").matchesRegEx("[a-z0-9_]+").maxLength(24).provided("latin2", "utf8").withDefault("utf8")); + } + + @Override + protected Pattern identifierPattern(final HsHostingAssetEntity assetEntity) { + final var webspaceIdentifier = assetEntity.getAssignedToAsset().getAssignedToAsset().getIdentifier(); + return Pattern.compile("^"+webspaceIdentifier+"$|^"+webspaceIdentifier+"_[a-z0-9]+$"); + } +} diff --git a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7018-hs-hosting-asset-test-data.sql b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7018-hs-hosting-asset-test-data.sql index efc76846..c7fc4450 100644 --- a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7018-hs-hosting-asset-test-data.sql +++ b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7018-hs-hosting-asset-test-data.sql @@ -26,6 +26,7 @@ declare domainSetupUuid uuid; domainMBoxSetupUuid uuid; mariaDbInstanceUuid uuid; + mariaDbUserUuid uuid; begin currentTask := 'creating hosting-asset test-data ' || givenProjectCaption; call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN'); @@ -71,6 +72,7 @@ begin select uuid_generate_v4() into domainSetupUuid; select uuid_generate_v4() into domainMBoxSetupUuid; select uuid_generate_v4() into mariaDbInstanceUuid; + select uuid_generate_v4() into mariaDbUserUuid; debitorNumberSuffix := relatedDebitor.debitorNumberSuffix; defaultPrefix := relatedDebitor.defaultPrefix; @@ -79,9 +81,10 @@ begin values (managedServerUuid, managedServerBI.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(), cloudServerBI.uuid, 'CLOUD_SERVER', null, null, 'vm20' || debitorNumberSuffix, 'another CloudServer', '{}'::jsonb), - (mariaDbInstanceUuid, null, 'MARIADB_INSTANCE', managedServerUuid, null, 'vm10' || debitorNumberSuffix || '.MariaDB.default', 'some default MariaDB instance','{}'::jsonb), - (uuid_generate_v4(), null, 'MARIADB_USER', mariaDbInstanceUuid, null, defaultPrefix || '01_web', 'some default MariaDB user', '{ "password": " HA_MANAGED_SERVER HA_MARIADB_USER *==> HA_MARIADB_INSTANCE HA_MARIADB_USER o..> HA_MANAGED_WEBSPACE - HA_MARIADB_DATABASE *==> HA_MANAGED_WEBSPACE - HA_MARIADB_DATABASE o..> HA_MARIADB_INSTANCE + HA_MARIADB_DATABASE *==> HA_MARIADB_INSTANCE + HA_MARIADB_DATABASE o..> HA_MARIADB_USER HA_IP_NUMBER o..> HA_CLOUD_SERVER HA_IP_NUMBER o..> HA_MANAGED_SERVER HA_IP_NUMBER o..> HA_MANAGED_WEBSPACE 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 00f07198..61bf0ea8 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 @@ -41,7 +41,8 @@ class HostingAssetEntityValidatorRegistryUnitTest { HsHostingAssetType.DOMAIN_MBOX_SETUP, HsHostingAssetType.EMAIL_ADDRESS, HsHostingAssetType.MARIADB_INSTANCE, - HsHostingAssetType.MARIADB_USER + HsHostingAssetType.MARIADB_USER, + HsHostingAssetType.MARIADB_DATABASE ); } } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsMariaDbDatabaseHostingAssetValidatorUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsMariaDbDatabaseHostingAssetValidatorUnitTest.java new file mode 100644 index 00000000..c75a135f --- /dev/null +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsMariaDbDatabaseHostingAssetValidatorUnitTest.java @@ -0,0 +1,121 @@ +package net.hostsharing.hsadminng.hs.hosting.asset.validators; + +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity.HsHostingAssetEntityBuilder; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.stream.Stream; + +import static java.util.Map.ofEntries; +import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MARIADB_DATABASE; +import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MARIADB_INSTANCE; +import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MARIADB_USER; +import static net.hostsharing.hsadminng.hs.hosting.asset.TestHsHostingAssetEntities.TEST_MANAGED_SERVER_HOSTING_ASSET; +import static net.hostsharing.hsadminng.hs.hosting.asset.TestHsHostingAssetEntities.TEST_MANAGED_WEBSPACE_HOSTING_ASSET; +import static net.hostsharing.hsadminng.mapper.PatchMap.entry; +import static org.assertj.core.api.Assertions.assertThat; + +class HsMariaDbDatabaseHostingAssetValidatorUnitTest { + + private static final HsHostingAssetEntity GIVEN_MARIADB_INSTANCE = HsHostingAssetEntity.builder() + .type(MARIADB_INSTANCE) + .parentAsset(TEST_MANAGED_SERVER_HOSTING_ASSET) + .identifier("vm1234|MariaDB.default") + .caption("some valid test MariaDB-Instance") + .build(); + + private static final HsHostingAssetEntity GIVEN_MARIADB_USER = HsHostingAssetEntity.builder() + .type(MARIADB_USER) + .parentAsset(GIVEN_MARIADB_INSTANCE) + .assignedToAsset(TEST_MANAGED_WEBSPACE_HOSTING_ASSET) + .identifier("xyz00_temp") + .caption("some valid test MariaDB-User") + .config(new HashMap<>(ofEntries( + entry("password", "Hallo Datenbank, lass mich rein!") + ))) + .build(); + + private static HsHostingAssetEntityBuilder givenValidMariaDbDatabaseBuilder() { + return HsHostingAssetEntity.builder() + .type(MARIADB_DATABASE) + .parentAsset(GIVEN_MARIADB_INSTANCE) + .assignedToAsset(GIVEN_MARIADB_USER) + .identifier("xyz00_temp") + .caption("some valid test MariaDB-Database") + .config(new HashMap<>(ofEntries( + entry("encoding", "latin1"), + entry("collation", "latin1") + ))); + } + + @Test + void describesItsProperties() { + // given + final var validator = HostingAssetEntityValidatorRegistry.forType(givenValidMariaDbDatabaseBuilder().build().getType()); + + // when + final var props = validator.properties(); + + // then + assertThat(props).extracting(Object::toString).containsExactlyInAnyOrder( + "{type=string, propertyName=encoding, matchesRegEx=[[a-z0-9_]+], maxLength=24, provided=[latin2, utf8], defaultValue=utf8}", + "{type=string, propertyName=collation, matchesRegEx=[[a-z0-9_]+], maxLength=24, provided=[latin2, utf8], defaultValue=utf8}" + ); + } + + @Test + void validatesValidEntity() { + // given + final var givenMariaDbUserHostingAsset = givenValidMariaDbDatabaseBuilder().build(); + final var validator = HostingAssetEntityValidatorRegistry.forType(givenMariaDbUserHostingAsset.getType()); + + // when + final var result = Stream.concat( + validator.validateEntity(givenMariaDbUserHostingAsset).stream(), + validator.validateContext(givenMariaDbUserHostingAsset).stream() + ).toList(); + + // then + assertThat(result).isEmpty(); + } + + @Test + void rejectsInvalidProperties() { + // given + final var givenMariaDbUserHostingAsset = givenValidMariaDbDatabaseBuilder() + .config(ofEntries( + entry("unknown", "wrong"), + entry("encoding", 10), + entry("collation", 20) + )) + .build(); + final var validator = HostingAssetEntityValidatorRegistry.forType(givenMariaDbUserHostingAsset.getType()); + + // when + final var result = validator.validateEntity(givenMariaDbUserHostingAsset); + + // then + assertThat(result).containsExactlyInAnyOrder( + "'MARIADB_DATABASE:xyz00_temp.config.unknown' is not expected but is set to 'wrong'", + "'MARIADB_DATABASE:xyz00_temp.config.encoding' is expected to be of type String, but is of type Integer", + "'MARIADB_DATABASE:xyz00_temp.config.collation' is expected to be of type String, but is of type Integer" + ); + } + + @Test + void rejectsInvalidIdentifier() { + // given + final var givenMariaDbUserHostingAsset = givenValidMariaDbDatabaseBuilder() + .identifier("xyz99-temp") + .build(); + final var validator = HostingAssetEntityValidatorRegistry.forType(givenMariaDbUserHostingAsset.getType()); + + // when + final var result = validator.validateEntity(givenMariaDbUserHostingAsset); + + // then + assertThat(result).containsExactly( + "'identifier' expected to match '^xyz00$|^xyz00_[a-z0-9]+$', but is 'xyz99-temp'"); + } +}