hosting-asset-validation-for-cloud-server-to-webspace #54
@ -0,0 +1,42 @@
|
||||
package net.hostsharing.hsadminng.hs.hosting.asset;
|
||||
|
||||
import net.hostsharing.hsadminng.hs.hosting.asset.validator.HsHostingAssetValidator;
|
||||
import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.api.HsHostingAssetPropsApi;
|
||||
import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.model.HsHostingAssetTypeResource;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
@RestController
|
||||
public class HsHostingAssetPropsController implements HsHostingAssetPropsApi {
|
||||
|
||||
@Override
|
||||
public ResponseEntity<List<String>> listAssetTypes() {
|
||||
final var resource = HsHostingAssetValidator.types().stream()
|
||||
.map(Enum::name)
|
||||
.toList();
|
||||
return ResponseEntity.ok(resource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<List<Object>> listAssetTypeProps(
|
||||
final HsHostingAssetTypeResource assetType) {
|
||||
|
||||
final var propValidators = HsHostingAssetValidator.forType(HsHostingAssetType.of(assetType));
|
||||
// final List<Map<String, Object>> resource = propValidators.properties()
|
||||
// .stream()
|
||||
// .map(HsHostingAssetPropsController::simplifyTypeProperty)
|
||||
// .toList();
|
||||
final List<Map<String, Object>> resource = propValidators.properties();
|
||||
return ResponseEntity.ok((List)resource);
|
||||
}
|
||||
|
||||
// private static Map<String, Object> simplifyTypeProperty(Map<String, Object> source) {
|
||||
// final var target = new LinkedHashMap<>(source);
|
||||
// target.put("type", source,)
|
||||
// return target;
|
||||
// }
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package net.hostsharing.hsadminng.hs.hosting.asset.validator;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType;
|
||||
@ -59,6 +60,14 @@ public abstract class HsHostingAssetPropertyValidator<T> {
|
||||
throw new IllegalStateException(typeDef.getKey() + "[" + propertyName + "] not fully initialized, please call either .required() or .optional()" );
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, Object> toMap(final ObjectMapper mapper) {
|
||||
final Map<String, Object> map = mapper.convertValue(this, Map.class);
|
||||
map.put("type", simpleTypeName());
|
||||
return map;
|
||||
}
|
||||
|
||||
protected abstract String simpleTypeName();
|
||||
}
|
||||
|
||||
@Setter
|
||||
@ -90,6 +99,11 @@ class IntegerPropertyValidator extends HsHostingAssetPropertyValidator<Integer>{
|
||||
result.add("'" + propertyName + "' is expected to be multiple of " + step + " but is " + propValue);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String simpleTypeName() {
|
||||
return "integer";
|
||||
}
|
||||
}
|
||||
|
||||
@Setter
|
||||
@ -116,6 +130,11 @@ class EnumPropertyValidator extends HsHostingAssetPropertyValidator<String> {
|
||||
result.add("'" + propertyName + "' is expected to be one of " + Arrays.toString(values) + " but is '" + propValue + "'");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String simpleTypeName() {
|
||||
return "enumeration";
|
||||
}
|
||||
}
|
||||
|
||||
@Setter
|
||||
@ -145,4 +164,9 @@ class BooleanPropertyValidator extends HsHostingAssetPropertyValidator<Boolean>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String simpleTypeName() {
|
||||
return "boolean";
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,16 @@
|
||||
package net.hostsharing.hsadminng.hs.hosting.asset.validator;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity;
|
||||
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.Arrays.stream;
|
||||
import static net.hostsharing.hsadminng.hs.hosting.asset.validator.EnumPropertyValidator.enumProperty;
|
||||
@ -60,6 +65,10 @@ public class HsHostingAssetValidator {
|
||||
propertyValidators = validators;
|
||||
}
|
||||
|
||||
public static Set<HsHostingAssetType> types() {
|
||||
return validators.keySet();
|
||||
}
|
||||
|
||||
public List<String> validate(final HsHostingAssetEntity assetEntity) {
|
||||
final var result = new ArrayList<String>();
|
||||
assetEntity.getConfig().keySet().forEach( givenPropName -> {
|
||||
@ -72,4 +81,19 @@ public class HsHostingAssetValidator {
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> properties() {
|
||||
final var mapper = new ObjectMapper();
|
||||
mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
|
||||
return Arrays.stream(propertyValidators)
|
||||
.map(propertyValidator -> propertyValidator.toMap(mapper))
|
||||
.map(HsHostingAssetValidator::asKeyValueMap)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private static Map<String, Object> asKeyValueMap(final Map map) {
|
||||
return (Map<String, Object>) map;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -80,18 +80,11 @@ components:
|
||||
# forces generating a java.lang.Object containing a Map, instead of class AssetConfiguration
|
||||
anyOf:
|
||||
- type: object
|
||||
properties:
|
||||
CPU:
|
||||
type: integer
|
||||
minimum: 1
|
||||
maximum: 16
|
||||
SSD:
|
||||
type: integer
|
||||
minimum: 16
|
||||
maximum: 4096
|
||||
HDD:
|
||||
type: integer
|
||||
minimum: 16
|
||||
maximum: 4096
|
||||
additionalProperties: true
|
||||
|
||||
HsHostingAssetProps:
|
||||
# FIXME: add proper schema spec
|
||||
anyOf:
|
||||
- type: object
|
||||
additionalProperties: true
|
||||
|
||||
|
@ -0,0 +1,26 @@
|
||||
get:
|
||||
summary: Returns a list of available asset properties for the given type.
|
||||
description: Returns the list of available properties and their validations for a given asset type.
|
||||
tags:
|
||||
- hs-hosting-asset-props
|
||||
operationId: listAssetTypeProps
|
||||
parameters:
|
||||
- name: assetType
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
$ref: 'hs-hosting-asset-schemas.yaml#/components/schemas/HsHostingAssetType'
|
||||
description: The asset type whose properties are to be returned.
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: 'hs-hosting-asset-schemas.yaml#/components/schemas/HsHostingAssetProps'
|
||||
"401":
|
||||
$ref: 'error-responses.yaml#/components/responses/Unauthorized'
|
||||
"403":
|
||||
$ref: 'error-responses.yaml#/components/responses/Forbidden'
|
@ -0,0 +1,19 @@
|
||||
get:
|
||||
summary: Returns a list of available asset types.
|
||||
description: Returns the list of asset types to enable an adaptive UI.
|
||||
tags:
|
||||
- hs-hosting-asset-props
|
||||
operationId: listAssetTypes
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
"401":
|
||||
$ref: 'error-responses.yaml#/components/responses/Unauthorized'
|
||||
"403":
|
||||
$ref: 'error-responses.yaml#/components/responses/Forbidden'
|
@ -13,18 +13,20 @@ get:
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: The UUID of the debitor, whose hosting assets are to be listed.
|
||||
- name: parentAssetUuid
|
||||
in: query
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: The UUID of the parentAsset, whose hosting assets are to be listed.
|
||||
- name: type
|
||||
in: query
|
||||
required: false
|
||||
schema:
|
||||
$ref: 'hs-hosting-asset-schemas.yaml#/components/schemas/HsHostingAssetType'
|
||||
description: The UUID of the debitor, whose hosting assets are to be listed.
|
||||
description: The type of hosting assets to be listed.
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
|
@ -8,10 +8,16 @@ servers:
|
||||
|
||||
paths:
|
||||
|
||||
# Items
|
||||
# Assets
|
||||
|
||||
/api/hs/hosting/assets:
|
||||
$ref: "hs-hosting-assets.yaml"
|
||||
|
||||
/api/hs/hosting/assets/{assetUuid}:
|
||||
$ref: "hs-hosting-assets-with-uuid.yaml"
|
||||
|
||||
/api/hs/hosting/asset-types:
|
||||
$ref: "hs-hosting-asset-types.yaml"
|
||||
|
||||
/api/hs/hosting/asset-types/{assetType}:
|
||||
$ref: "hs-hosting-asset-types-props.yaml"
|
||||
|
@ -0,0 +1,156 @@
|
||||
package net.hostsharing.hsadminng.hs.hosting.asset;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import net.hostsharing.hsadminng.HsadminNgApplication;
|
||||
import net.hostsharing.hsadminng.rbac.test.JpaAttempt;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.web.server.LocalServerPort;
|
||||
|
||||
import static net.hostsharing.hsadminng.rbac.test.JsonMatcher.lenientlyEquals;
|
||||
|
||||
@SpringBootTest(
|
||||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
classes = { HsadminNgApplication.class, JpaAttempt.class }
|
||||
)
|
||||
class HsHostingAssetPropsControllerAcceptanceTest {
|
||||
|
||||
@LocalServerPort
|
||||
private Integer port;
|
||||
|
||||
@Test
|
||||
void anyone_canListAvailableAssetTypes() {
|
||||
|
||||
RestAssured // @formatter:off
|
||||
.given()
|
||||
.port(port)
|
||||
.when()
|
||||
.get("http://localhost/api/hs/hosting/asset-types")
|
||||
.then().log().all().assertThat()
|
||||
.statusCode(200)
|
||||
.contentType("application/json")
|
||||
.body("", lenientlyEquals("""
|
||||
[
|
||||
"MANAGED_SERVER",
|
||||
"MANAGED_WEBSPACE",
|
||||
"CLOUD_SERVER"
|
||||
]
|
||||
"""));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
void globalAdmin_canListPropertiesOfGivenAssetType() {
|
||||
|
||||
RestAssured // @formatter:off
|
||||
.given()
|
||||
.port(port)
|
||||
.when()
|
||||
.get("http://localhost/api/hs/hosting/asset-types/" + HsHostingAssetType.MANAGED_SERVER)
|
||||
.then().log().all().assertThat()
|
||||
.statusCode(200)
|
||||
.contentType("application/json")
|
||||
.body("", lenientlyEquals("""
|
||||
[
|
||||
{
|
||||
"type": "integer",
|
||||
"propertyName": "CPUs",
|
||||
"required": true,
|
||||
"unit": null,
|
||||
"min": 1,
|
||||
"max": 32,
|
||||
"step": null
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"propertyName": "RAM",
|
||||
"required": true,
|
||||
"unit": "GB",
|
||||
"min": 1,
|
||||
"max": 128,
|
||||
"step": null
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"propertyName": "SSD",
|
||||
"required": true,
|
||||
"unit": "GB",
|
||||
"min": 25,
|
||||
"max": 1000,
|
||||
"step": 25
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"propertyName": "HDD",
|
||||
"required": false,
|
||||
"unit": "GB",
|
||||
"min": 0,
|
||||
"max": 4000,
|
||||
"step": 250
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"propertyName": "Traffic",
|
||||
"required": true,
|
||||
"unit": "GB",
|
||||
"min": 250,
|
||||
"max": 10000,
|
||||
"step": 250
|
||||
},
|
||||
{
|
||||
"type": "enumeration",
|
||||
"propertyName": "SLA-Platform",
|
||||
"required": false,
|
||||
"values": [
|
||||
"BASIC",
|
||||
"EXT8H",
|
||||
"EXT4H",
|
||||
"EXT2H"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"propertyName": "SLA-EMail",
|
||||
"required": false,
|
||||
"falseIf": {
|
||||
"SLA-Platform": "BASIC"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"propertyName": "SLA-Maria",
|
||||
"required": false,
|
||||
"falseIf": {
|
||||
"SLA-Platform": "BASIC"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"propertyName": "SLA-PgSQL",
|
||||
"required": false,
|
||||
"falseIf": {
|
||||
"SLA-Platform": "BASIC"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"propertyName": "SLA-Office",
|
||||
"required": false,
|
||||
"falseIf": {
|
||||
"SLA-Platform": "BASIC"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"propertyName": "SLA-Web",
|
||||
"required": false,
|
||||
"falseIf": {
|
||||
"SLA-Platform": "BASIC"
|
||||
}
|
||||
}
|
||||
]
|
||||
"""));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user