1
0

ceate bookingitems for domain-setup hostingassets (#95)

Co-authored-by: Michael Hoennig <michael@hoennig.de>
Reviewed-on: https://dev.hostsharing.net/hostsharing/hs.hsadmin.ng/pulls/95
Reviewed-by: Marc Sandlus <marc.sandlus@hostsharing.net>
This commit is contained in:
Michael Hoennig
2024-09-04 11:15:37 +02:00
parent e57f4bf0c8
commit fbd17a21e2
12 changed files with 159 additions and 63 deletions

View File

@@ -8,6 +8,7 @@ import org.junit.jupiter.api.Test;
import jakarta.persistence.EntityManager;
import jakarta.validation.ValidationException;
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.DOMAIN_SETUP;
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.PRIVATE_CLOUD;
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.CLOUD_SERVER;
import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.MANAGED_SERVER;
@@ -53,6 +54,6 @@ class HsBookingItemEntityValidatorUnitTest {
final var result = HsBookingItemEntityValidatorRegistry.types();
// then
assertThat(result).containsExactlyInAnyOrder(PRIVATE_CLOUD, CLOUD_SERVER, MANAGED_SERVER, MANAGED_WEBSPACE);
assertThat(result).containsExactlyInAnyOrder(PRIVATE_CLOUD, CLOUD_SERVER, MANAGED_SERVER, MANAGED_WEBSPACE, DOMAIN_SETUP);
}
}

View File

@@ -249,6 +249,15 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
void globalAdmin_canAddTopLevelAsset() {
context.define("superuser-alex@hostsharing.net");
final var givenProject = realProjectRepo.findByCaption("D-1000111 default project").stream()
.findAny().orElseThrow();
final var bookingItem = givenSomeTemporaryBookingItem(() ->
HsBookingItemRealEntity.builder()
.project(givenProject)
.type(HsBookingItemType.DOMAIN_SETUP)
.caption("some temp domain setup booking item")
.build()
);
final var location = RestAssured // @formatter:off
.given()
@@ -256,12 +265,13 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
.contentType(ContentType.JSON)
.body("""
{
"bookingItemUuid": "%s",
"type": "DOMAIN_SETUP",
"identifier": "example.com",
"caption": "some unrelated domain-setup",
"config": {}
}
""")
""".formatted(bookingItem.getUuid()))
.port(port)
.when()
.post("http://localhost/api/hs/hosting/assets")
@@ -729,6 +739,13 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
}).assertSuccessful().returnedValue();
}
private HsBookingItemRealEntity givenSomeTemporaryBookingItem(final Supplier<HsBookingItemRealEntity> newBookingItem) {
return jpaAttempt.transacted(() -> {
context.define("superuser-alex@hostsharing.net"); // needed to determine creator
return toCleanup(realBookingItemRepo.save(newBookingItem.get()));
}).assertSuccessful().returnedValue();
}
HsHostingAssetRealEntity givenParentAsset(final HsHostingAssetType assetType, final String assetIdentifier) {
final var givenAsset = realAssetRepo.findByIdentifier(assetIdentifier).stream()
.filter(a -> a.getType() == assetType)

View File

@@ -15,18 +15,19 @@ class HsHostingAssetTypeUnitTest {
### Server+Webspace
```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
entity BI_DOMAIN_SETUP
}
package Hosting #feb28c{
package Server #99bcdb {
entity HA_CLOUD_SERVER
@@ -34,19 +35,19 @@ class HsHostingAssetTypeUnitTest {
entity HA_IPV4_NUMBER
entity HA_IPV6_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
@@ -59,7 +60,7 @@ class HsHostingAssetTypeUnitTest {
HA_IPV6_NUMBER o..> HA_CLOUD_SERVER
HA_IPV6_NUMBER o..> HA_MANAGED_SERVER
HA_IPV6_NUMBER o..> HA_MANAGED_WEBSPACE
package Legend #white {
SUB_ENTITY1 *--> REQUIRED_PARENT_ENTITY
SUB_ENTITY2 *..> OPTIONAL_PARENT_ENTITY
@@ -68,20 +69,21 @@ class HsHostingAssetTypeUnitTest {
}
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
entity BI_DOMAIN_SETUP
}
package Hosting #feb28c{
package Domain #99bcdb {
entity HA_DOMAIN_SETUP
@@ -91,22 +93,23 @@ class HsHostingAssetTypeUnitTest {
entity HA_DOMAIN_MBOX_SETUP
entity HA_EMAIL_ADDRESS
}
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_MANAGED_WEBSPACE *==> BI_MANAGED_WEBSPACE
HA_UNIX_USER *==> HA_MANAGED_WEBSPACE
HA_EMAIL_ALIAS *==> HA_MANAGED_WEBSPACE
HA_DOMAIN_SETUP *..> BI_DOMAIN_SETUP
HA_DOMAIN_SETUP o..> HA_DOMAIN_SETUP
HA_DOMAIN_DNS_SETUP *==> HA_DOMAIN_SETUP
HA_DOMAIN_DNS_SETUP o--> HA_MANAGED_WEBSPACE
@@ -117,7 +120,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
package Legend #white {
SUB_ENTITY1 *--> REQUIRED_PARENT_ENTITY
SUB_ENTITY2 *..> OPTIONAL_PARENT_ENTITY
@@ -126,46 +129,47 @@ 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
entity BI_DOMAIN_SETUP
}
package Hosting #feb28c{
package MariaDB #99bcdb {
entity HA_MARIADB_INSTANCE
entity HA_MARIADB_USER
entity HA_MARIADB_DATABASE
}
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_MANAGED_WEBSPACE *==> BI_MANAGED_WEBSPACE
HA_UNIX_USER *==> HA_MANAGED_WEBSPACE
HA_EMAIL_ALIAS *==> HA_MANAGED_WEBSPACE
HA_MARIADB_USER *==> HA_MANAGED_WEBSPACE
HA_MARIADB_USER o--> HA_MARIADB_INSTANCE
HA_MARIADB_DATABASE *==> HA_MARIADB_USER
package Legend #white {
SUB_ENTITY1 *--> REQUIRED_PARENT_ENTITY
SUB_ENTITY2 *..> OPTIONAL_PARENT_ENTITY
@@ -174,46 +178,47 @@ 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
entity BI_DOMAIN_SETUP
}
package Hosting #feb28c{
package PostgreSQL #99bcdb {
entity HA_PGSQL_INSTANCE
entity HA_PGSQL_USER
entity HA_PGSQL_DATABASE
}
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_MANAGED_WEBSPACE *==> BI_MANAGED_WEBSPACE
HA_UNIX_USER *==> HA_MANAGED_WEBSPACE
HA_EMAIL_ALIAS *==> 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
SUB_ENTITY2 *..> OPTIONAL_PARENT_ENTITY
@@ -222,7 +227,7 @@ class HsHostingAssetTypeUnitTest {
}
Booking -down[hidden]->Legend
```
This code generated was by HsHostingAssetType.main, do not amend manually.
""");
}

View File

@@ -20,6 +20,7 @@ class HsDomainSetupHostingAssetValidatorUnitTest {
static HsHostingAssetRbacEntity.HsHostingAssetRbacEntityBuilder<?, ?> validEntityBuilder() {
return HsHostingAssetRbacEntity.builder()
.type(DOMAIN_SETUP)
.bookingItem(HsBookingItemRealEntity.builder().type(HsBookingItemType.DOMAIN_SETUP).build())
.identifier("example.org");
}
@@ -93,20 +94,33 @@ class HsDomainSetupHostingAssetValidatorUnitTest {
@Test
void validatesReferencedEntities() {
// given
final var mangedServerHostingAssetEntity = validEntityBuilder()
final var domainSetupHostingAssetEntity = validEntityBuilder()
.parentAsset(HsHostingAssetRealEntity.builder().type(CLOUD_SERVER).build())
.assignedToAsset(HsHostingAssetRealEntity.builder().type(MANAGED_SERVER).build())
.bookingItem(HsBookingItemRealEntity.builder().type(HsBookingItemType.CLOUD_SERVER).build())
.build();
final var validator = HostingAssetEntityValidatorRegistry.forType(mangedServerHostingAssetEntity.getType());
final var validator = HostingAssetEntityValidatorRegistry.forType(domainSetupHostingAssetEntity.getType());
// when
final var result = validator.validateEntity(mangedServerHostingAssetEntity);
final var result = validator.validateEntity(domainSetupHostingAssetEntity);
// then
assertThat(result).containsExactlyInAnyOrder(
"'DOMAIN_SETUP:example.org.bookingItem' must be null but is of type CLOUD_SERVER",
"'DOMAIN_SETUP:example.org.bookingItem' or parentItem must be null but is of type CLOUD_SERVER",
"'DOMAIN_SETUP:example.org.parentAsset' must be null or of type DOMAIN_SETUP but is of type CLOUD_SERVER",
"'DOMAIN_SETUP:example.org.assignedToAsset' must be null but is of type MANAGED_SERVER");
}
@Test
void expectsEitherParentAssetOrBookingItem() {
// given
final var domainSetupHostingAssetEntity = validEntityBuilder().build();
final var validator = HostingAssetEntityValidatorRegistry.forType(domainSetupHostingAssetEntity.getType());
// when
final var result = validator.validateEntity(domainSetupHostingAssetEntity);
// then
assertThat(result).isEmpty();
}
}

View File

@@ -513,15 +513,15 @@ public class ImportHostingAssets extends BaseOfficeDataImport {
assertThat(firstOfEach(12, domainSetupAssets)).isEqualToIgnoringWhitespace("""
{
4531=HsHostingAsset(DOMAIN_SETUP, l-u-g.org, l-u-g.org),
4532=HsHostingAsset(DOMAIN_SETUP, linuxfanboysngirls.de, linuxfanboysngirls.de),
4534=HsHostingAsset(DOMAIN_SETUP, lug-mars.de, lug-mars.de),
4581=HsHostingAsset(DOMAIN_SETUP, 1981.ist-im-netz.de, 1981.ist-im-netz.de, DOMAIN_SETUP:ist-im-netz.de),
4587=HsHostingAsset(DOMAIN_SETUP, mellis.de, mellis.de),
4589=HsHostingAsset(DOMAIN_SETUP, ist-im-netz.de, ist-im-netz.de),
4600=HsHostingAsset(DOMAIN_SETUP, waera.de, waera.de),
4604=HsHostingAsset(DOMAIN_SETUP, xn--wra-qla.de, wära.de),
7662=HsHostingAsset(DOMAIN_SETUP, dph-netzwerk.de, dph-netzwerk.de)
4531=HsHostingAsset(DOMAIN_SETUP, l-u-g.org, l-u-g.org, D-1000300:mim default project:BI l-u-g.org),
4532=HsHostingAsset(DOMAIN_SETUP, linuxfanboysngirls.de, linuxfanboysngirls.de, D-1000300:mim default project:BI linuxfanboysngirls.de),
4534=HsHostingAsset(DOMAIN_SETUP, lug-mars.de, lug-mars.de, D-1000300:mim default project:BI lug-mars.de),
4581=HsHostingAsset(DOMAIN_SETUP, 1981.ist-im-netz.de, 1981.ist-im-netz.de, DOMAIN_SETUP:ist-im-netz.de),
4587=HsHostingAsset(DOMAIN_SETUP, mellis.de, mellis.de, D-1000300:mim default project:BI mellis.de),
4589=HsHostingAsset(DOMAIN_SETUP, ist-im-netz.de, ist-im-netz.de, D-1000300:mim default project:BI ist-im-netz.de),
4600=HsHostingAsset(DOMAIN_SETUP, waera.de, waera.de, D-1000300:mim default project:BI waera.de),
4604=HsHostingAsset(DOMAIN_SETUP, xn--wra-qla.de, wära.de, D-1000300:mim default project:BI xn--wra-qla.de),
7662=HsHostingAsset(DOMAIN_SETUP, dph-netzwerk.de, dph-netzwerk.de, D-1101900:dph default project:BI dph-netzwerk.de)
}
""");
@@ -1441,6 +1441,7 @@ public class ImportHostingAssets extends BaseOfficeDataImport {
// Domain Setup
final var domainSetupAsset = HsHostingAssetRealEntity.builder()
// .bookingItem(bookingItem) are set once we've collected all domains
.type(DOMAIN_SETUP)
// .parentAsset(parentDomainSetupAsset) are set once we've collected all of them
.identifier(domain_name)
@@ -1542,10 +1543,27 @@ public class ImportHostingAssets extends BaseOfficeDataImport {
final var parentDomainSetup = domainSetupsByName.get(parentDomainName);
if (parentDomainSetup != null) {
domainSetup.setParentAsset(parentDomainSetup);
} else {
final var relatedProject = domainSetup.getSubHostingAssets().stream()
.map(ha -> ha.getAssignedToAsset() != null ? ha.getAssignedToAsset().getRelatedProject() : null)
.findAny().orElseThrow();
final var bookingItem = HsBookingItemRealEntity.builder()
.type(HsBookingItemType.DOMAIN_SETUP)
.caption("BI " + domainSetup.getIdentifier())
.project((HsBookingProjectRealEntity) relatedProject)
//.validity(toPostgresDateRange(created, cancelled))
.build();
domainSetup.setBookingItem(bookingItem);
bookingItems.put(nextAvailableBookingItemId(), bookingItem);
}
});
}
private static @NotNull Integer nextAvailableBookingItemId() {
return bookingItems.keySet().stream().max(Long::compare).map(id -> id + 1).orElseThrow();
}
private String withDefault(final String givenValue, final Object defaultValue) {
if (defaultValue instanceof String defaultStringValue) {
return givenValue != null && !givenValue.isBlank() ? givenValue : defaultStringValue;