This is an automated email from the ASF dual-hosted git repository.
algairim pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brooklyn-docs.git
The following commit(s) were added to refs/heads/master by this push:
new 7229d89d add docs for new predicates dsl
new 9f71de4d Merge pull request #358 from ahgittin/predicates-dsl
7229d89d is described below
commit 7229d89d21d749dd2038683fc81bcadda1ec8e78
Author: Alex Heneveld <[email protected]>
AuthorDate: Thu Jun 23 20:11:37 2022 +0100
add docs for new predicates dsl
---
guide/blueprints/yaml-reference.md | 148 ++++++++++++++++++++++++++++++++++++-
1 file changed, 147 insertions(+), 1 deletion(-)
diff --git a/guide/blueprints/yaml-reference.md
b/guide/blueprints/yaml-reference.md
index 72a3e175..dbcbf440 100644
--- a/guide/blueprints/yaml-reference.md
+++ b/guide/blueprints/yaml-reference.md
@@ -259,7 +259,11 @@ concise DSL defined here:
and either `object.fields` or `brooklyn.config` to supply
bean/constructor/flags to create an instance
* `$brooklyn:entitySpec(Map)` returns a new `ServiceSpecification` as defined
by the given `Map`,
but as an `EntitySpec` suitable for setting as the value of
`ConfigKey<EntitySpec>` config items
- (such as `dynamiccluster.memberspec` in `DynamicCluster`)
+ (such as `dynamiccluster.memberspec` in `DynamicCluster`); this is often not
needed,
+ if the `EntitySpec` is expected by context and can be coerced from a map
+ using the simple Jackson deserialization in the `EntitySpec` class
+ (this is similar to CAMP but is not as extensive, and other formats are not
supported in coercion;
+ if there are any issues with a direct map, consider wrapping it in the
`$brooklyn:entitySpec` DSL)
<!-- TODO examples for object and entitySpec -->
@@ -323,3 +327,145 @@ These are:
including `config-widgets` (setting custom widgets to render fields) and
`config-quick-fixes` (proposals for fixing common errors);
see the code for the Blueprint Composer for more details
+## Predicate DSL
+
+In contexts where a `DslPredicate` or `DslEntityPredicate` is expected, the
`$brooklyn:object`
+DSL can be used to construct any suitable implementation, such as using
factory methods from `EntityPredicates`.
+In many cases, however, a simplified YAML DSL can be used,
+as defined by the Jackson deserialization rules on the `DslPredicate`.
+
+In its simplest form this can be a map containing the test or tests, e.g.:
+
+```
+equals: north
+```
+
+This will result in a `Predicate` which returns true if asked to
`test("north")`,
+and false otherwise. The full set of individual tests are:
+
+* `equals: <object>`, to test java object equality, attempting type coercion
if necessary
+* `regex: <string|number>`
+* `glob: <string|number>`
+* `when: <presence>`, where `<presence>` is one of the values described below
+* `less-than: <object>`, for strings and primitives, computed using "natural
ordering",
+ numeric order for numbers and digit sequences within numbers (`"9" < "10"`),
+ and ASCII-lexicographic comparison elsewhere (`"a" < "b"`);
+ otherwise if both arguments are the same type, or one a subtype of the
other, and both comparable,
+ it will use that type's compare method;
+ otherwise if one side side is JSON, it will attempt coercion to the other
argument's type;
+ and otherwise it will return false
+* `greater-than: <object>`, as above
+* `less-than-or-equal-to: <object>` as above
+* `greater-than-or-equal-to: <object>, as above
+* `in-range: <range>`, where `<range>` is a list of two numbers, e.g.
`[0,100]` (always inclusive)
+* `java-instance-of: <string>`, where the `<string>` is a registered type
name, to test
+ type assignment of the underlying java class of the value being tested with
the
+ underlying java class of the registered type referenced
+* `java-type-name: <test>`, where the `<test>` is a `DslPredicate` tested
against the
+ underlying java class name of the value
+
+Two composite tests are supported, both taking a list of other `<test>`
objects
+(as a list of YAML maps):
+
+* `any: <list of tests>`, testing that any of the tests in the list are true
(logical "or")
+* `all: <list of tests>`, testing that all of the tests in the list are true
(logical "and")
+
+
+
+### Presence
+
+The `when` test allows for testing of edge cases, to distinguish between
values which are unavailable
+(e.g. a sensor which has not been published, or a config which is unset),
those which are null,
+and those which are "truthy" (non-empty, non-false, per
`$brooklyn:attributeWhenReady`).
+Permitted values for this test are:
+
+* `absent`: value cannot be resolved (not even as null)
+* `absent_or_null`: value is null or cannot be resolved
+* `present`: value is available, but might be null
+* `present_non_null`: value is available and non-null (but might be 0 or empty)
+* `truthy`: value is available and ready/truthy (eg not false or empty)
+* `falsy`: value is unavailable or not ready/truthy (eg not false or empty)
+* `always`: always returns true
+* `never`: always returns false
+
+
+### Entity Tests
+
+To assist with tests on an `Entity` or `Location`, additional keys are
supported on
+the `DslPredicate` via `DslEntityPredicate`:
+
+* `target: <expression>`: to specify a value to test, resolved relative to the
"context entity"
+ (the one being tested, if appropriate, or otherwise the evaluating entity
where the predicate is defined);
+ this can be a DSL expression such as `$brooklyn:config("key")`
+ or a keyword, currently `location` or `children`, to evaluate
+ against the location(s) or children of that entity
+* `config: <string>`: indicates that the tests should be applied to the value
of config key
+ `<string> on the context entity, location, or policy
+* `sensor: <string>`: indicates that the tests should be applied to the value
of sensor
+ `<string> on the context entity
+* `tag: <test>`: indicates that `<test>` should be applied to the tags on the
context entity, location, or policy
+
+
+### Lists and Flattening Behaviour
+
+To facilitate testing against collections (e.g. `target: location` or `target:
children`, or `tags`,
+or a config key which is a collection), the default behaviour for testing
against any `Iterable`
+is to perform the tests against the `Iterable` itself and, if that fails,
against each
+element therein (and any element in nested `Iterable` elements, recursively.
+The predicate will pass if the `Iterable` or any such member passes all the
tests defined.
+
+This makes it easy to test for the presence of a specific tag of location,
+and is chosen as the default because the majority of test predicates are not
+applicable to collections.
+
+However there may be cases where the predicate needs to run against the
`Iterable`
+and _not_ the nested values. This can be indicated with the special test:
+
+* `unflattened: <test>`: Performs the test against the value prior to
enumeration of
+ members, and if supplied must pass in order for the predicate to return true
+
+
+### Examples
+
+##### Location Config
+
+The following will test whether an entity has any location with config
`region`
+starting with `us-`, for example to filter within a `DynamicGroup`:
+
+```
+target: location
+config: region
+glob: us-*
+```
+
+(Instead of the `glob`, writing `regex: us-.*` would be equivalent.)
+
+
+##### Date Comparison
+
+Given a config `expiry` of type `Instant` (or related date/time type),
+this will check that the date is on or after Jan 1 2000:
+
+```
+config: expiry
+greater-than-or-equal-to: 2000-01-01
+```
+
+
+##### Missing Sensor
+
+This will select entities which have _not_ published the sensor "ready":
+
+```
+sensor: ready
+when: absent
+```
+
+And this will select entities where that sensor is present but null, false, or
empty:
+
+```
+sensor: ready
+all:
+- when: present
+- when: falsy
+```