osdir.com


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: PROPOSAL: conditional config constraints


Hi Aled,

I'd say go for it, that looks like something that could be valuable in
various cases.
I take it your example of "exactly one of config X or config Y" would be
expressed
along the lines of a parallel set of constraints between each config -

On X:
     constraints:
       - requiredUnless("Y")
       - forbiddenIf("Y")

On Y:
     constraints:
       - requiredUnless("X")
       - forbiddenIf("X")

Geoff


On Tue, 18 Sep 2018 at 17:05 Aled Sage <aled.sage@xxxxxxxxx> wrote:

> Hi all,
>
> I'd like to add support for more sophisticated config constraints, where
> there are inter-dependencies between config keys. I'd like the blueprint
> composer web-console to understand (a small number of) these, and thus
> to give feedback to the user about what is required and whether their
> blueprint is valid.
>
> For example, a blueprint that requires exactly one of config X or config
> Y. Another example: config X2 is required if and only if config X1 is
> supplied.
>
> There are a few questions / decision points:
>
>   1. What constraints should we support out-of-the-box?
>   2. What naming convention do we use, so that the UI can parse +
> understand these?
>   3. Should we support multiple constraints (we do in the REST api, but
> not currently in the Java API or in the Blueprint Composer UI)
>
> ---
> I suggest we support things like:
>
>      constraints:
>        - requiredUnless("Y")
>        - forbiddenIf("Y")
>
> and:
>
>      constraints:
>        - requiredIf("X1")
>        - forbiddenUnless("X1")
>
> The structure of this string would be:
>
>      {required,forbidden}{If,Unless}("<config>")
>
>      requiredIf("X1"):      value is required if config X1 is set;
> otherwise optional.
>      forbiddenUnless("X1"): value must be null if config X1 is not set;
> otherwise optional.
>      requiredUnless("Y"):   value is required if config Y is not set;
> otherwise optional.
>      forbiddenIf("Y"):      value must be null if config Y is set;
> otherwise optional.
>
> I don't think we want to get too sophisticated. For example, do *not*
> support "must match regex '[a-z]+' unless config Y is present". I don't
> think we should create a full-blown DSL for this!
>
> ---
> Implementation notes:
>
> We already have the basis of this in our Java code. We support a
> predicate of type
> `org.apache.brooklyn.core.objs.BrooklynObjectPredicate`, which has the
> additional method `boolean apply(T input, BrooklynObject context)`. The
> `BrooklynObject` could be an entity, or location, etc. An implementation
> of this predicate can therefore lookup other config key's values, when
> validating the value.
>
> For the UI, the Blueprint Composer calls:
>
> http://localhost:8081/v1/catalog/bundles/
> <bundle>/<version>/types/<blueprint>/latest
>
> This returns things like:
>
>      "config": [
>        {
>          "name": "myPredicate",
>          "type": "java.lang.String",
>          "reconfigurable": false,
>          "label": "myPredicate",
>          "pinned": false,
>          "constraints": [
>            "MyPredicateToString()"
>          ],
>          "links": {}
>        },
>        ...
>
> The constraint returned here is the toString() of the predicate.
>
> In the UI [1], there is currently some very simple logic to interpret
> this string for particular types of constraint.
>
> Aled
>
> [1]
>
> brooklyn-ui/ui-modules/blueprint-composer/app/components/providers/blueprint-service.provider.js
>
>