quarkusio / quarkus

Quarkus: Supersonic Subatomic Java.
https://quarkus.io
Apache License 2.0
13.64k stars 2.64k forks source link

Add way for extensions to alternatively describe their configuration for use by tools #5229

Open maxandersen opened 4 years ago

maxandersen commented 4 years ago

Description In #1655 and in https://github.com/redhat-developer/vscode-quarkus/issues/129 its been discussed it would be great if extensions have an ability to self-document their properties/config structure in cases where the config model is not possible to be described via @ConfigRoot and @ConfigProperty

maxandersen commented 4 years ago

having an extra optional descriptor file in extensions manifest.mf metadata could be an option - but I would still say tools should read the annotations if they can and only take the metadata if present.

angelozerr commented 4 years ago

In Quarkus LS, here information that we collection with JDT Search in JSON format for quarkus.datasource.driver:

{
    "propertyName": "quarkus.datasource.driver",
    "type": "java.util.Optional\u003cjava.lang.String\u003e",
    "docs": "The datasource driver class name",
    "extensionName": "quarkus-agroal",
    "location": "C:/Users/azerr/.m2/repository/io/quarkus/quarkus-agroal/0.21.1/quarkus-agroal-0.21.1.jar",
    "source": "io.quarkus.agroal.runtime.DataSourceBuildTimeConfig#driver",
    "required": false,
    "phase": 2
}

In other words we need list of Quarkus properties name and for each name, we need:

When property is bound to enum like quarkus.log.console.async.overflow, we have that:

{
    "propertyName": "quarkus.log.console.async.overflow",
    "type": "org.jboss.logmanager.handlers.AsyncHandler$OverflowAction",
    "defaultValue": "block",
    "docs": "Determine whether to block the publisher (rather than drop the message) when the queue is full",
    "extensionName": "quarkus-core",
    "location": "C:/Users/azerr/.m2/repository/io/quarkus/quarkus-core/0.21.1/quarkus-core-0.21.1.jar",
    "source": "io.quarkus.runtime.logging.AsyncConfig#overflow",
    "phase": 3,
    "enums": [
        {
            "name": "BLOCK"
        },
        {
            "name": "DISCARD"
        }
    ]
}

in other words:

"enums": [
        {
            "name": "BLOCK",
            "docs": "BLOCK documentation"
        },
        {
            "name": "DISCARD",
            "docs": "DISCARD documentation"
        }
]

And when it's a mapped property we use {*} like quarkus.datasource.{*}.driver

{
    "propertyName": "quarkus.datasource.{*}.driver",
    "type": "java.util.Optional\u003cjava.lang.String\u003e",
    "docs": "The datasource driver class name",
    "extensionName": "quarkus-agroal",
    "location": "C:/Users/azerr/.m2/repository/io/quarkus/quarkus-agroal/0.21.1/quarkus-agroal-0.21.1.jar",
    "source": "io.quarkus.agroal.runtime.DataSourceBuildTimeConfig#driver",
    "required": false,
    "phase": 2
},

But I think it should be better to use a nameinstead of using * like quarkus.datasource.{datasource-name}.driver, but perhaps we could manage that in Quarkus LS side (get datasource and concat with -name) if it's every time like this?

maxandersen commented 4 years ago

since this would be stored per extension and in a jar you are not going to get extensionName, nor location those are not relevant for the extension to state afaics.

I don't grok what you are needing source for exactly - since you can't locate them already what is it that expect to actually get here ? what is its usecase for you ?

Here is my initial suggestion for a descriptor of these:

quarkus.log.console.async.overflow:
  type: string 
  required: false
  description: "The datasource driver class name"
  phase: 2 .   // would prefer a name here but not sure which one it is ;)
angelozerr commented 4 years ago

since this would be stored per extension and in a jar you are not going to get extensionName, nor location those are not relevant for the extension to state afaics.

We need extensionName (to display it), but quarkus-extensions.yaml or quarkus-extensions.json seems contains this information. See https://github.com/redhat-developer/quarkus-ls/issues/133 Let's give up this information for the new metatada.

I don't grok what you are needing source for exactly - since you can't locate them already what is it that expect to actually get here ? what is its usecase for you ?

Ctrl+click on property defined in application.properties open the proper Java file and set the cursor to the proper field/method. Without this source information we cannot manage definition.

Here is my initial suggestion for a descriptor of these:

It's a good start, but we need to clarify:

maxandersen commented 4 years ago
  • source : without this information definition will not be available.

yes, I'm still struggling to see the value of this but source would then just be the fully qualified name.

  • enums: it is used for managing complation, hover, validation for property value which is IMHO very helpful.

what are you asking for here ? an enum is a type and you can resolve types, right ?

  • please manage mapped property too.

can you please describe what is missing here for that ? I'm not sure I'm following the issue.

maxandersen commented 4 years ago

I was talking with Claus Ibsen on how they did configuration properties for their camel components and they actually utilized Springs metadata config format as outlined here.

Looking at that format actually seem to cover a lot of the concerns here so maybe we should just adopt the same ? especially since it allows for optional additions like what is the case for the kubernetes resource format.

let me know if that format would work for you @angelozerr ?

angelozerr commented 4 years ago

Looking at that format actually seem to cover a lot of the concerns here so maybe we should just adopt the same ?

I read documentation and it seems it's very good. It exists sourceType, sourceMethod but what about sourceField? Perhaps the source field name in Spring Boot is get from the last suffix of the property name?

angelozerr commented 4 years ago

@maxandersen I'm refactoring our JDT Quarkus LS extension to use the Spring format. Here a sample:

{
    "type": "java.util.Optional\u003cjava.lang.String\u003e",
    "sourceField": "keyStoreFileType",
    "extensionName": "quarkus-undertow",
    "required": false,
    "phase": 3,
    "name": "quarkus.http.ssl.certificate.key-store-file-type",
    "description": "An optional parameter to specify type of the key store file. If not given, the type is automatically detected\n based on the file name.",
        "sourceType": "io.quarkus.runtime.configuration.ssl.CertificateConfig",
        "binary": true
    }

As you can notice we have extra fields compared to Spring configuration metadata:

maxandersen commented 4 years ago

sourceField - why not just have that encoded in source ? isn't that just a fully qualified reference ? like `io.quarkus.kubernetes.Config#myField" ?

if not - then sure, could be added as separate value.

please note we haven't yet solidified using this format in all extensions; but its more likely than any other custom format ;)

angelozerr commented 4 years ago

sourceField - why not just have that encoded in source ? isn't that just a fully qualified reference ? like `io.quarkus.kubernetes.Config#myField"

I have followed Spring format and they have sourceType (class or interface) and sourceMethod but they have not sourceField, that's why I have added it.

please note we haven't yet solidified using this format in all extensions; but its more likely than any other custom format ;)

When you will have something, please ping me, thanks!