osdir.com


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

PROPOSAL: conditional config constraints


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