add-mariadb-instance-database-and-user-validations #75

Merged
hsh-michaelhoennig merged 6 commits from add-mariadb-instance-database-and-user-validations into master 2024-07-12 10:54:47 +02:00
10 changed files with 199 additions and 15 deletions
Showing only changes of commit b37cb10e8f - Show all commits

View File

@ -26,6 +26,7 @@ public class HostingAssetEntityValidatorRegistry {
register(DOMAIN_SMTP_SETUP, new HsDomainSmtpSetupHostingAssetValidator()); register(DOMAIN_SMTP_SETUP, new HsDomainSmtpSetupHostingAssetValidator());
register(DOMAIN_MBOX_SETUP, new HsDomainMboxSetupHostingAssetValidator()); register(DOMAIN_MBOX_SETUP, new HsDomainMboxSetupHostingAssetValidator());
register(EMAIL_ADDRESS, new HsEMailAddressHostingAssetValidator()); register(EMAIL_ADDRESS, new HsEMailAddressHostingAssetValidator());
register(MARIADB_INSTANCE, new HsMariaDbInstanceHostingAssetValidator());
} }
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

@ -0,0 +1,37 @@
package net.hostsharing.hsadminng.hs.hosting.asset.validators;
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity;
import java.util.regex.Pattern;
import static java.util.Optional.ofNullable;
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MARIADB_INSTANCE;
class HsMariaDbInstanceHostingAssetValidator extends HostingAssetEntityValidator {
final static String DEFAULT_INSTANCE_IDENTIFIER_SUFFIX = "|MariaDB.default"; // TODO.spec: specify instance naming
public HsMariaDbInstanceHostingAssetValidator() {
super(
MARIADB_INSTANCE,
AlarmContact.isOptional(), // hostmaster alert address is implicitly added
NO_EXTRA_PROPERTIES); // TODO.spec: specify instance properties, e.g. installed extensions
}
@Override
protected Pattern identifierPattern(final HsHostingAssetEntity assetEntity) {
return Pattern.compile(
"^" + Pattern.quote(assetEntity.getParentAsset().getIdentifier()
+ DEFAULT_INSTANCE_IDENTIFIER_SUFFIX)
+ "$");
}
@Override
public void preprocessEntity(final HsHostingAssetEntity entity) {
super.preprocessEntity(entity);
if (entity.getIdentifier() == null) {
ofNullable(entity.getParentAsset()).ifPresent(pa -> entity.setIdentifier(
pa.getIdentifier() + DEFAULT_INSTANCE_IDENTIFIER_SUFFIX));
}
}
}

View File

@ -19,6 +19,7 @@ components:
- EMAIL_ADDRESS - EMAIL_ADDRESS
- PGSQL_USER - PGSQL_USER
- PGSQL_DATABASE - PGSQL_DATABASE
- MARIADB_INSTANCE
- MARIADB_USER - MARIADB_USER
- MARIADB_DATABASE - MARIADB_DATABASE

View File

@ -18,6 +18,7 @@ create type HsHostingAssetType as enum (
'EMAIL_ADDRESS', 'EMAIL_ADDRESS',
'PGSQL_USER', 'PGSQL_USER',
'PGSQL_DATABASE', 'PGSQL_DATABASE',
'MARIADB_INSTANCE',
'MARIADB_USER', 'MARIADB_USER',
'MARIADB_DATABASE' 'MARIADB_DATABASE'
); );
@ -74,6 +75,7 @@ begin
when 'EMAIL_ADDRESS' then 'DOMAIN_MBOX_SETUP' when 'EMAIL_ADDRESS' then 'DOMAIN_MBOX_SETUP'
when 'PGSQL_USER' then 'MANAGED_WEBSPACE' when 'PGSQL_USER' then 'MANAGED_WEBSPACE'
when 'PGSQL_DATABASE' then 'MANAGED_WEBSPACE' when 'PGSQL_DATABASE' then 'MANAGED_WEBSPACE'
when 'MARIADB_INSTANCE' then 'MANAGED_SERVER'
when 'MARIADB_USER' then 'MANAGED_WEBSPACE' when 'MARIADB_USER' then 'MANAGED_WEBSPACE'
when 'MARIADB_DATABASE' then 'MANAGED_WEBSPACE' when 'MARIADB_DATABASE' then 'MANAGED_WEBSPACE'
else raiseException(format('[400] unknown asset type %s', NEW.type::text)) else raiseException(format('[400] unknown asset type %s', NEW.type::text))

View File

@ -25,6 +25,7 @@ declare
webUnixUserUuid uuid; webUnixUserUuid uuid;
domainSetupUuid uuid; domainSetupUuid uuid;
domainMBoxSetupUuid uuid; domainMBoxSetupUuid uuid;
mariaDbInstanceUuid uuid;
begin begin
currentTask := 'creating hosting-asset test-data ' || givenProjectCaption; currentTask := 'creating hosting-asset test-data ' || givenProjectCaption;
call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN'); call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN');
@ -69,22 +70,25 @@ begin
select uuid_generate_v4() into webUnixUserUuid; select uuid_generate_v4() into webUnixUserUuid;
select uuid_generate_v4() into domainSetupUuid; select uuid_generate_v4() into domainSetupUuid;
select uuid_generate_v4() into domainMBoxSetupUuid; select uuid_generate_v4() into domainMBoxSetupUuid;
select uuid_generate_v4() into mariaDbInstanceUuid;
debitorNumberSuffix := relatedDebitor.debitorNumberSuffix; debitorNumberSuffix := relatedDebitor.debitorNumberSuffix;
defaultPrefix := relatedDebitor.defaultPrefix; defaultPrefix := relatedDebitor.defaultPrefix;
insert into hs_hosting_asset insert into hs_hosting_asset
(uuid, bookingitemuuid, type, parentAssetUuid, assignedToAssetUuid, identifier, caption, config) (uuid, bookingitemuuid, type, parentAssetUuid, assignedToAssetUuid, identifier, caption, config)
values (managedServerUuid, 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), values
(uuid_generate_v4(), cloudServerBI.uuid, 'CLOUD_SERVER', null, null, 'vm20' || debitorNumberSuffix, 'another CloudServer', '{}'::jsonb), (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),
(managedWebspaceUuid, managedWebspaceBI.uuid, 'MANAGED_WEBSPACE', managedServerUuid, null, defaultPrefix || '01', 'some Webspace', '{}'::jsonb), (uuid_generate_v4(), cloudServerBI.uuid, 'CLOUD_SERVER', null, null, 'vm20' || debitorNumberSuffix, 'another CloudServer', '{}'::jsonb),
(uuid_generate_v4(), null, 'EMAIL_ALIAS', managedWebspaceUuid, null, defaultPrefix || '01-web', 'some E-Mail-Alias', '{ "target": [ "office@example.org", "archive@example.com" ] }'::jsonb), (mariaDbInstanceUuid, null, 'MARIADB_INSTANCE', managedServerUuid, null, 'vm10' || debitorNumberSuffix || '.MariaDB.default','some default MariaDB instance','{}'::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), (managedWebspaceUuid, managedWebspaceBI.uuid, 'MANAGED_WEBSPACE', managedServerUuid, null, defaultPrefix || '01', 'some Webspace', '{}'::jsonb),
(domainSetupUuid, null, 'DOMAIN_SETUP', null, null, defaultPrefix || '.example.org', 'some Domain-Setup', '{}'::jsonb), (uuid_generate_v4(), null, 'EMAIL_ALIAS', managedWebspaceUuid, null, defaultPrefix || '01-web', 'some E-Mail-Alias', '{ "target": [ "office@example.org", "archive@example.com" ] }'::jsonb),
(uuid_generate_v4(), null, 'DOMAIN_DNS_SETUP', domainSetupUuid, null, defaultPrefix || '.example.org|DNS', 'some Domain-DNS-Setup', '{}'::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', domainSetupUuid, webUnixUserUuid, defaultPrefix || '.example.org|HTTP', 'some Domain-HTTP-Setup', '{ "option-htdocsfallback": true, "use-fcgiphpbin": "/usr/lib/cgi-bin/php", "validsubdomainnames": "*"}'::jsonb), (domainSetupUuid, null, 'DOMAIN_SETUP', null, null, defaultPrefix || '.example.org', 'some Domain-Setup', '{}'::jsonb),
(uuid_generate_v4(), null, 'DOMAIN_SMTP_SETUP', domainSetupUuid, managedWebspaceUuid, defaultPrefix || '.example.org|DNS', 'some Domain-SMPT-Setup', '{}'::jsonb), (uuid_generate_v4(), null, 'DOMAIN_DNS_SETUP', domainSetupUuid, null, defaultPrefix || '.example.org|DNS', 'some Domain-DNS-Setup', '{}'::jsonb),
(domainMBoxSetupUuid, null, 'DOMAIN_MBOX_SETUP', domainSetupUuid, managedWebspaceUuid, defaultPrefix || '.example.org|DNS', 'some Domain-MBOX-Setup', '{}'::jsonb), (uuid_generate_v4(), null, 'DOMAIN_HTTP_SETUP', domainSetupUuid, webUnixUserUuid, defaultPrefix || '.example.org|HTTP', 'some Domain-HTTP-Setup', '{ "option-htdocsfallback": true, "use-fcgiphpbin": "/usr/lib/cgi-bin/php", "validsubdomainnames": "*"}'::jsonb),
(uuid_generate_v4(), null, 'EMAIL_ADDRESS', domainMBoxSetupUuid, null, 'test@' || defaultPrefix || '.example.org', 'some E-Mail-Address', '{}'::jsonb); (uuid_generate_v4(), null, 'DOMAIN_SMTP_SETUP', domainSetupUuid, managedWebspaceUuid, defaultPrefix || '.example.org|DNS', 'some Domain-SMPT-Setup', '{}'::jsonb),
(domainMBoxSetupUuid, null, 'DOMAIN_MBOX_SETUP', domainSetupUuid, managedWebspaceUuid, defaultPrefix || '.example.org|DNS', 'some Domain-MBOX-Setup', '{}'::jsonb),
(uuid_generate_v4(), null, 'EMAIL_ADDRESS', domainMBoxSetupUuid, null, 'test@' || defaultPrefix || '.example.org', 'some E-Mail-Address', '{}'::jsonb);
end; $$; end; $$;
--// --//

View File

@ -30,6 +30,7 @@ import java.util.Map;
import static java.util.Map.entry; 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.booking.item.TestHsBookingItem.TEST_CLOUD_SERVER_BOOKING_ITEM;
import static net.hostsharing.hsadminng.hs.booking.item.TestHsBookingItem.TEST_MANAGED_SERVER_BOOKING_ITEM; import static net.hostsharing.hsadminng.hs.booking.item.TestHsBookingItem.TEST_MANAGED_SERVER_BOOKING_ITEM;
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.hs.hosting.asset.TestHsHostingAssetEntities.TEST_MANAGED_WEBSPACE_HOSTING_ASSET;
import static net.hostsharing.hsadminng.hs.office.contact.TestHsOfficeContact.TEST_CONTACT; import static net.hostsharing.hsadminng.hs.office.contact.TestHsOfficeContact.TEST_CONTACT;
import static net.hostsharing.hsadminng.rbac.test.JsonMatcher.lenientlyEquals; import static net.hostsharing.hsadminng.rbac.test.JsonMatcher.lenientlyEquals;
@ -363,6 +364,25 @@ public class HsHostingAssetControllerRestTest {
} }
} }
] ]
"""),
MARIADB_INSTANCE(
List.of(
HsHostingAssetEntity.builder()
.type(HsHostingAssetType.MARIADB_INSTANCE)
.parentAsset(TEST_MANAGED_SERVER_HOSTING_ASSET)
.identifier("vm1234|MariaDB.default")
.caption("some fake MariaDB instance")
.build()),
"""
[
{
"type": "MARIADB_INSTANCE",
"identifier": "vm1234|MariaDB.default",
"caption": "some fake MariaDB instance",
"alarmContact": null,
"config": {}
}
]
"""); """);
final HsHostingAssetType assetType; final HsHostingAssetType assetType;

View File

@ -41,7 +41,8 @@ class HsHostingAssetPropsControllerAcceptanceTest {
"DOMAIN_HTTP_SETUP", "DOMAIN_HTTP_SETUP",
"DOMAIN_SMTP_SETUP", "DOMAIN_SMTP_SETUP",
"DOMAIN_MBOX_SETUP", "DOMAIN_MBOX_SETUP",
"EMAIL_ADDRESS" "EMAIL_ADDRESS",
"MARIADB_INSTANCE"
] ]
""")); """));
// @formatter:on // @formatter:on

View File

@ -245,7 +245,8 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu
// then // then
exactlyTheseAssetsAreReturned( exactlyTheseAssetsAreReturned(
result, result,
"HsHostingAssetEntity(MANAGED_WEBSPACE, sec01, some Webspace, MANAGED_SERVER:vm1012, D-1000212:D-1000212 default project:separate ManagedWebspace)"); "HsHostingAssetEntity(MANAGED_WEBSPACE, sec01, some Webspace, MANAGED_SERVER:vm1012, D-1000212:D-1000212 default project:separate ManagedWebspace)",
"HsHostingAssetEntity(MARIADB_INSTANCE, vm1012.MariaDB.default, some default MariaDB instance, MANAGED_SERVER:vm1012)");
} }
} }

View File

@ -39,7 +39,8 @@ class HostingAssetEntityValidatorRegistryUnitTest {
HsHostingAssetType.DOMAIN_HTTP_SETUP, HsHostingAssetType.DOMAIN_HTTP_SETUP,
HsHostingAssetType.DOMAIN_SMTP_SETUP, HsHostingAssetType.DOMAIN_SMTP_SETUP,
HsHostingAssetType.DOMAIN_MBOX_SETUP, HsHostingAssetType.DOMAIN_MBOX_SETUP,
HsHostingAssetType.EMAIL_ADDRESS HsHostingAssetType.EMAIL_ADDRESS,
HsHostingAssetType.MARIADB_INSTANCE
); );
} }
} }

View File

@ -0,0 +1,116 @@
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 org.junit.jupiter.api.Test;
import java.util.Map;
import static java.util.Map.entry;
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.DOMAIN_SMTP_SETUP;
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_WEBSPACE;
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MARIADB_INSTANCE;
import static net.hostsharing.hsadminng.hs.hosting.asset.TestHsHostingAssetEntities.TEST_MANAGED_SERVER_HOSTING_ASSET;
import static net.hostsharing.hsadminng.hs.hosting.asset.validators.HsMariaDbInstanceHostingAssetValidator.DEFAULT_INSTANCE_IDENTIFIER_SUFFIX;
import static org.assertj.core.api.Assertions.assertThat;
class HsMariaDbInstanceHostingAssetValidatorUnitTest {
static HsHostingAssetEntityBuilder validEntityBuilder() {
return HsHostingAssetEntity.builder()
.type(MARIADB_INSTANCE)
.parentAsset(TEST_MANAGED_SERVER_HOSTING_ASSET)
.identifier(TEST_MANAGED_SERVER_HOSTING_ASSET.getIdentifier() + DEFAULT_INSTANCE_IDENTIFIER_SUFFIX);
}
@Test
void containsExpectedProperties() {
// when
final var validator = HostingAssetEntityValidatorRegistry.forType(DOMAIN_SMTP_SETUP);
// then
assertThat(validator.properties()).map(Map::toString).isEmpty();
}
@Test
void preprocessesTakesIdentifierFromParent() {
// given
final var givenEntity = validEntityBuilder().build();
assertThat(givenEntity.getParentAsset().getIdentifier()).as("precondition failed").isEqualTo("vm1234");
final var validator = HostingAssetEntityValidatorRegistry.forType(givenEntity.getType());
// when
validator.preprocessEntity(givenEntity);
// then
assertThat(givenEntity.getIdentifier()).isEqualTo("vm1234|MariaDB.default");
}
@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();
}
@Test
void rejectsInvalidIdentifier() {
// given
final var givenEntity = validEntityBuilder().identifier("example.org").build();
final var validator = HostingAssetEntityValidatorRegistry.forType(givenEntity.getType());
// when
final var result = validator.validateEntity(givenEntity);
// then
assertThat(result).containsExactly(
"'identifier' expected to match '^\\Qvm1234|MariaDB.default\\E$', but is 'example.org'"
);
}
@Test
void rejectsInvalidReferencedEntities() {
// given
final var mangedServerHostingAssetEntity = validEntityBuilder()
.bookingItem(HsBookingItemEntity.builder().type(HsBookingItemType.CLOUD_SERVER).build())
.parentAsset(HsHostingAssetEntity.builder().type(MANAGED_WEBSPACE).build())
.assignedToAsset(HsHostingAssetEntity.builder().type(MANAGED_WEBSPACE).build())
.build();
final var validator = HostingAssetEntityValidatorRegistry.forType(mangedServerHostingAssetEntity.getType());
// when
final var result = validator.validateEntity(mangedServerHostingAssetEntity);
// then
assertThat(result).containsExactlyInAnyOrder(
"'MARIADB_INSTANCE:vm1234|MariaDB.default.bookingItem' must be null but is of type CLOUD_SERVER",
"'MARIADB_INSTANCE:vm1234|MariaDB.default.parentAsset' must be of type MANAGED_SERVER but is of type MANAGED_WEBSPACE",
"'MARIADB_INSTANCE:vm1234|MariaDB.default.assignedToAsset' must be null but is of type MANAGED_WEBSPACE");
}
@Test
void rejectsInvalidProperties() {
// given
final var mangedServerHostingAssetEntity = validEntityBuilder()
.config(Map.ofEntries(
entry("any", "false")
))
.build();
final var validator = HostingAssetEntityValidatorRegistry.forType(mangedServerHostingAssetEntity.getType());
// when
final var result = validator.validateEntity(mangedServerHostingAssetEntity);
// then
assertThat(result).containsExactlyInAnyOrder(
"'MARIADB_INSTANCE:vm1234|MariaDB.default.config.any' is not expected but is set to 'false'");
}
}