From 079f1e216a8b4c37c6839c3dda35058ccf20be70 Mon Sep 17 00:00:00 2001 From: Jeremy Whiting Date: Mon, 28 Oct 2024 16:38:18 +0000 Subject: [PATCH] Add discriminator for Datastore. --- docs/site/content/en/openapi/openapi.yaml | 14 +++++++--- .../data/datastore/BaseDatastoreConfig.java | 6 ++++- .../horreum/api/data/datastore/Datastore.java | 13 ++++++---- .../datastore/PostgresDatastoreConfig.java | 4 +++ horreum-web/src/domain/admin/Datastores.tsx | 11 ++++---- .../admin/datastore/ModifyDatastoreModal.tsx | 26 +++++++++---------- 6 files changed, 46 insertions(+), 28 deletions(-) diff --git a/docs/site/content/en/openapi/openapi.yaml b/docs/site/content/en/openapi/openapi.yaml index a5983eef1..874bb38e4 100644 --- a/docs/site/content/en/openapi/openapi.yaml +++ b/docs/site/content/en/openapi/openapi.yaml @@ -3219,10 +3219,14 @@ components: type: boolean example: false config: + required: + - builtIn type: object - oneOf: - - $ref: "#/components/schemas/ElasticsearchDatastoreConfig" - - $ref: "#/components/schemas/PostgresDatastoreConfig" + properties: + builtIn: + description: Built In + type: boolean + example: ElasticsearchDatastoreConfig type: description: Type of backend datastore enum: @@ -3231,6 +3235,8 @@ components: - COLLECTORAPI type: string example: ELASTICSEARCH + discriminator: + propertyName: type DatastoreTestResponse: type: object properties: @@ -3246,6 +3252,8 @@ components: - COLLECTORAPI type: string example: ELASTICSEARCH + discriminator: + propertyName: type EDivisiveDetectionConfig: required: - builtIn diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/BaseDatastoreConfig.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/BaseDatastoreConfig.java index 929e92ebf..0be9c0b14 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/BaseDatastoreConfig.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/BaseDatastoreConfig.java @@ -8,11 +8,15 @@ public abstract class BaseDatastoreConfig { @Schema(type = SchemaType.BOOLEAN, required = true, description = "Built In") public Boolean builtIn = true; + // @Schema(type = SchemaType.STRING, required = true, description = "type information") + // public String type = ""; + public BaseDatastoreConfig() { } - public BaseDatastoreConfig(Boolean builtIn) { + public BaseDatastoreConfig(Boolean builtIn/* , String type */) { this.builtIn = builtIn; + // this.type = type; } public abstract String validateConfig(); diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/Datastore.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/Datastore.java index 4f63bb9c6..65f029d09 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/Datastore.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/Datastore.java @@ -3,6 +3,7 @@ import jakarta.validation.constraints.NotNull; import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; +import org.eclipse.microprofile.openapi.annotations.media.DiscriminatorMapping; import org.eclipse.microprofile.openapi.annotations.media.Schema; import com.fasterxml.jackson.annotation.JsonProperty; @@ -11,6 +12,7 @@ import io.hyperfoil.tools.horreum.api.data.ProtectedType; @Schema(type = SchemaType.OBJECT, required = true, description = "Type of backend datastore") + public class Datastore extends ProtectedType { @JsonProperty(required = true) @Schema(description = "Unique Datastore id", example = "101") @@ -28,15 +30,16 @@ public class Datastore extends ProtectedType { @NotNull @JsonProperty(required = true) - @Schema(type = SchemaType.OBJECT, oneOf = { - ElasticsearchDatastoreConfig.class, - PostgresDatastoreConfig.class - }) + @Schema(type = SchemaType.OBJECT, implementation = BaseDatastoreConfig.class, example = "ElasticsearchDatastoreConfig") public ObjectNode config; @NotNull @JsonProperty(required = true) - @Schema(type = SchemaType.STRING, implementation = DatastoreType.class, example = "ELASTICSEARCH") + @Schema(type = SchemaType.STRING, implementation = DatastoreType.class, example = "ELASTICSEARCH", discriminatorProperty = "type", discriminatorMapping = { + @DiscriminatorMapping(value = "ELASTICSEARCH", schema = String.class), + @DiscriminatorMapping(value = "POSTGRES", schema = String.class), + @DiscriminatorMapping(value = "COLLECTORAPI", schema = String.class) + }) public DatastoreType type; public void pruneSecrets() { diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/PostgresDatastoreConfig.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/PostgresDatastoreConfig.java index 2082f764d..fb869f605 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/PostgresDatastoreConfig.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/PostgresDatastoreConfig.java @@ -6,6 +6,10 @@ @Schema(type = SchemaType.OBJECT, required = true, description = "Built in backend datastore") public class PostgresDatastoreConfig extends BaseDatastoreConfig { + public PostgresDatastoreConfig() { + super(false); + } + @Override public String validateConfig() { return null; diff --git a/horreum-web/src/domain/admin/Datastores.tsx b/horreum-web/src/domain/admin/Datastores.tsx index d7c028c73..357f74607 100644 --- a/horreum-web/src/domain/admin/Datastores.tsx +++ b/horreum-web/src/domain/admin/Datastores.tsx @@ -25,8 +25,8 @@ import { CollectorApiDatastoreConfig, configApi, Datastore, - DatastoreTypeEnum, - ElasticsearchDatastoreConfig + DatastoreType, + ElasticsearchDatastoreConfig, PostgresDatastoreConfig } from "../../api"; import {AppContext} from "../../context/appContext"; import {AppContextType} from "../../context/@types/appContextTypes"; @@ -66,9 +66,8 @@ const DatastoresTable = ( props: dataStoreTableProps) => { }, ]; - const newBackendConfig: ElasticsearchDatastoreConfig | CollectorApiDatastoreConfig = { - url: "", - apiKey: "", + const newBackendConfig: ({ type: "ELASTICSEARCH";} & ElasticsearchDatastoreConfig) | ({ type: "COLLECTORAPI"; } & CollectorApiDatastoreConfig ) | ({ type: "POSTGRES"; } & PostgresDatastoreConfig)= { + type: DatastoreType.Postgres, builtIn: false } @@ -79,7 +78,7 @@ const DatastoresTable = ( props: dataStoreTableProps) => { builtIn: false, access: Access.Private, config: newBackendConfig, - type: DatastoreTypeEnum.Postgres + type: DatastoreType.Postgres } const [deleteModalOpen, setDeleteModalOpen] = useState(false); diff --git a/horreum-web/src/domain/admin/datastore/ModifyDatastoreModal.tsx b/horreum-web/src/domain/admin/datastore/ModifyDatastoreModal.tsx index c21104af4..e2d66f6a7 100644 --- a/horreum-web/src/domain/admin/datastore/ModifyDatastoreModal.tsx +++ b/horreum-web/src/domain/admin/datastore/ModifyDatastoreModal.tsx @@ -9,25 +9,25 @@ import { Modal, TextInput } from "@patternfly/react-core" import { - Datastore, - DatastoreTypeEnum, ElasticsearchDatastoreConfig, + Datastore, DatastoreConfig, + DatastoreType, ElasticsearchDatastoreConfig } from "../../../api"; import {AppContext} from "../../../context/appContext"; import {AppContextType} from "../../../context/@types/appContextTypes"; type ConfirmDeleteModalProps = { isOpen: boolean - dataStore: Datastore + dataStore: ({type: 'ELASTICSEARCH', config: DatastoreConfig} & Datastore) | ({type: 'POSTGRES', config: DatastoreConfig} & Datastore) | ({type: 'COLLECTORAPI', config: DatastoreConfig} & Datastore), onClose(): void onDelete(): Promise - updateDatastore(datastore: Datastore): void + updateDatastore(datastore: ({type: 'ELASTICSEARCH', config: DatastoreConfig} & Datastore) | ({type: 'POSTGRES', config: DatastoreConfig} & Datastore) | ({type: 'COLLECTORAPI', config: DatastoreConfig} & Datastore) ): void persistDatastore: (datastore: Datastore) => Promise description: string extra?: string } interface datastoreOption { - value: DatastoreTypeEnum, + value: DatastoreType, label: string, disabled: boolean, urlDisabled: boolean, @@ -79,9 +79,9 @@ export default function ModifyDatastoreModal({isOpen, onClose, persistDatastore, } const options : datastoreOption[] = [ - { value: DatastoreTypeEnum.Postgres, label: 'Please select...', disabled: true, urlDisabled: true, usernameDisable: true, tokenDisbaled: true }, - { value: DatastoreTypeEnum.Elasticsearch, label: 'Elasticsearch', disabled: false, urlDisabled: false, usernameDisable: false, tokenDisbaled: false }, - { value: DatastoreTypeEnum.Collectorapi, label: 'Collector API', disabled: false, urlDisabled: false, usernameDisable: true, tokenDisbaled: false }, + { value: DatastoreType.Postgres, label: 'Please select...', disabled: true, urlDisabled: true, usernameDisable: true, tokenDisbaled: true }, + { value: DatastoreType.Elasticsearch, label: 'Elasticsearch', disabled: false, urlDisabled: false, usernameDisable: false, tokenDisbaled: false }, + { value: DatastoreType.Collectorapi, label: 'Collector API', disabled: false, urlDisabled: false, usernameDisable: true, tokenDisbaled: false }, ]; const actionButtons = [ @@ -132,12 +132,12 @@ export default function ModifyDatastoreModal({isOpen, onClose, persistDatastore, fieldId="horizontal-form-name" > { const config :ElasticsearchDatastoreConfig = dataStore.config as ElasticsearchDatastoreConfig; config.url = value updateDatastore({...dataStore, config: config}) - }} + }} isDisabled={enabledURL} type="text" id="horizontal-form-url" @@ -155,7 +155,7 @@ export default function ModifyDatastoreModal({isOpen, onClose, persistDatastore, fieldId="horizontal-form-token" > { const config :ElasticsearchDatastoreConfig = dataStore.config as ElasticsearchDatastoreConfig; config.apiKey = value @@ -178,7 +178,7 @@ export default function ModifyDatastoreModal({isOpen, onClose, persistDatastore, fieldId="horizontal-form-token" > { const config :ElasticsearchDatastoreConfig = dataStore.config as ElasticsearchDatastoreConfig; config.username = value @@ -200,7 +200,7 @@ export default function ModifyDatastoreModal({isOpen, onClose, persistDatastore, fieldId="horizontal-form-token" > { const config :ElasticsearchDatastoreConfig = dataStore.config as ElasticsearchDatastoreConfig; config.password = value