This is an automated email from the ASF dual-hosted git repository. heneveld 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 a37e17ce docs for new workflow transforms, tidy up tips including foreach example a37e17ce is described below commit a37e17ce6071356d1f8546d391cd5bdd50c643cb Author: Alex Heneveld <a...@cloudsoft.io> AuthorDate: Tue Oct 10 14:35:22 2023 +0100 docs for new workflow transforms, tidy up tips including foreach example --- guide/blueprints/workflow/defining.md | 3 ++ guide/blueprints/workflow/settings.md | 29 ++---------- guide/blueprints/workflow/steps/steps.yaml | 43 ++++++++++++------ guide/blueprints/workflow/tips.md | 72 ++++++++++++++++++++++++++++++ guide/ops/configuration/brooklyn_cfg.md | 17 ++++--- 5 files changed, 120 insertions(+), 44 deletions(-) diff --git a/guide/blueprints/workflow/defining.md b/guide/blueprints/workflow/defining.md index bba29825..7bee711f 100644 --- a/guide/blueprints/workflow/defining.md +++ b/guide/blueprints/workflow/defining.md @@ -92,6 +92,9 @@ The config to define the sensor feed is: if on the local entity, or a map of `sensor` containing the name and `entity` containing the entity or entity ID where the sensor should be listened for, or if just a single local sensor, that sensor name supplied as a string * `period`: whether the feed should run periodically +* `skip_initial_run`: by default sensors and policies will run when created (if any `condition` is met); + this can be set `true` to prevent that, + ensuring it is only run after the initial `period` or when one of the `triggers` fires In addition to defining the `sensor` name, at least one of `triggers` or `period` must be supplied. The `steps` must also be defined, as per `workflow-effector` above, diff --git a/guide/blueprints/workflow/settings.md b/guide/blueprints/workflow/settings.md index 2f76ff31..ab7af87c 100644 --- a/guide/blueprints/workflow/settings.md +++ b/guide/blueprints/workflow/settings.md @@ -10,7 +10,7 @@ Some of the common properties permitted on [steps](common.md) also apply to work including `condition`, `timeout`, and `on-error`. This rest of this section describes the remaining properties for more advanced use cases -including mutex locking and resilient workflows with replay points, and some tips on optimizing. +including mutex locking and resilient workflows with replay points. ## Locks and Mutual Exclusion Behavior @@ -309,10 +309,11 @@ complicated replay or retention needs. * **`idempotent`** * when defining a workflow, as `idempotent: <value>` - * **`all`**: means that all external steps in this workflow will be resumable unless explicitly declared otherwise ( - by default, per below, external steps are not resumable); this includes steps in explicit sub-workflows (where the + * **`all`**: means that all external steps in this workflow will be resumable unless explicitly declared otherwise + (by default, per below, external steps are not resumable); this includes steps in explicit sub-workflows (where the workflow definition has a `workflow` with `steps`) but not sub-workflows which are references (effectors or registered workflow types) + * the empty string or null (the default): means normal idempotency determination applies * on a step as a key, as `idempotent: <value>` * **`yes`**: the step is idempotent and the workflow can replay resuming at this step if interrupted there * **`no`**: the step is not idempotent and should not resumed at this step; if interrupted there, replay resuming @@ -476,25 +477,3 @@ on-error: # finally restore default retention per parent or system, as details are now stored on the entity - workflow retention parent ``` - -## Optimizing for Workflows - -Workflows can generate a huge amount of data which can impact memory usage, persistence, and the UI. -The REST API and UI do some filtering (e.g. in the body of the `internal` sensors used by workflow), -but when working with large `ssh` `output` and `http` `content` payloads, and with `update-children`, -performance can be dramatically improved by following these tips: - -* Optimize external calls to return the minimal amount of information needed - * Use `jq` to filter when using `ssh` or `container` steps - * Pass filter arguments to `http` endpoints that accept them - * Loop over small page sizes (e.g. 20 records per cycle from `http`) using `retry from` steps - -* Optimize the data which is stored - * Override the `output` on `ssh` and `http` steps to remove unnecessary objects; - for example `http` returns several `content*` fields, and often just one is needed. - Simply settings `output: { content: ${content} }` will achieve this. - * Set `retention: 1` or `retention: 0` on workflows that use a large amount of information - and can simply be replayed from the start; additionally `retention: disabled` can be used - to prevent any persistence (even for ongoing workflows), but only for workflows that do - not acquire any `lock` - diff --git a/guide/blueprints/workflow/steps/steps.yaml b/guide/blueprints/workflow/steps/steps.yaml index a62d7dd8..e84fba15 100644 --- a/guide/blueprints/workflow/steps/steps.yaml +++ b/guide/blueprints/workflow/steps/steps.yaml @@ -43,21 +43,16 @@ - name: transform summary: Applies a transformation to a variable or expression - shorthand: '`transform [TYPE] [ "value" ] VARIABLE_NAME [ = VALUE ] | TRANSFORM`' - input: | - * `variable`: either a string, being the workflow variable name, or a map, containing the `name` and optionally the `type`; - if `value` is supplied, this variable will be set to the result of all transforms and then coercion to any indicated type, - e.g. to force conversion to an integer or to a bean registered type; - if `value` is not supplied, the name is treated as a variable name to resolve and coerce to any indicated type - (i.e. wrapping the name in `${...}`; this is suppressed if the type is the special keyword `value`, and `name` is resolved as a normal expression) - and then used for the transform with the result being returned; - `name` here can be of the form `x.key` where `x` is an existing map variable, to user or set a specific `key` within it - * `value_is_initial`: a boolean, implied in shorthand by the word "value", means to treat the variable name as a value rather than a variable name, - evaluating it as a normal expression rather than wraping it in `${...}`; this cannot be used it a `value` is supplied - * `value`: the value to set, with some limited evaluation prior to transforms as described [here](../variables.html); - if not supplied, the `variable` is evaluated per the above and used as the input for the transform + shorthand: '`transform [TYPE] [ VALUE | "value" VALUE | "variable" VARIABLE_NAME | VARIABLE_NAME "=" VALUE ] "|" TRANSFORM`' + input: | + * `variable`: either a string, being the workflow variable name, or a map, containing a `name` and/or a `type`; + if a variable name is supplied, it is set as the result of the transform, + and if `value` is not supplied, its initial value is used as the input to the transform (update in place) + * `value`: the value to start with; if omitted a `variable` is required and its value used as the starting value; + where the value might be confused with a variable name it must be explicitly offset with the keyword `"value"`; + more information is [here](../variables.html) * `transform`: a string indicating a transform, or multiple transforms separated by `|`, where a transform can be - * `trim` to remove leading and trailing whitespace on strings, null values from lists or sets, and any entry with a null key or null value in a map + * `trim` to remove leading and trailing whitespace on strings, null and empty string values from lists or sets, and any entry with a null key or null value in a map * `replace MODE PATTERN REPLACEMENT` to replace a pattern in a string with a replacement, supporting mode `regex`, `glob`, or `literal` * `merge [list|set|map] [deep] [wait] [lax]` to treat the words in the value as expressions to be combined; indicates the value will be a space-separated list of values, with quotes significant, usually including `$(vars)`; @@ -66,6 +61,8 @@ if `wait`, unavailable sensor values are blocked on before merging; if `lax` then nulls, and if not waiting unavailable sensors, are silently removed * `prepend <item>` and `append <item>` to add `<item>` at the start or end, respectively, when the input to the transform is a list or a string + * `join [<separator>]` to concatenate stringable items from a list + * `split [limit <limit>] [keep_delimiters] [literal|regex] <delimiter>` to split a string around the given `<delimiter>`, optionally including the delimiters or limiting the count * `slice <start-index> <optional-end-index>` to take a list and return the sublist; a negative index is taken from the end * `remove <item-or-index>` to remove an entry given a key (for a map, ignoring if not found) or an index (for a list, negative index taken from the end, failing if out of bounds) * `wait` to wait on values (such as `${entity.attributeWhenReady...}`); must precede any expression that has to resolve values, such as `trim`) @@ -83,6 +80,8 @@ * `to_string`, `to_upper_case`, and `to_lower_case` are accepted for strings * `resolve_expression` to trigger a re-resolution of the value being transformed, eg if it has nested variable references that need resolution or has been explicitly prepended and appended with `${` and `}`; this is not done immediately but on the next step (or at the end), so the value can be piped to `wait` if desired + * `get [<modifier>]` to get the unwrapped value of a supplier (if no arguments) or get a specific indexed value or modifier sequence, + such as `get 0` or `get [0]` to get the first element of a list, or `get .key.subkey[0]` to take an element `key` in a map, an element `subkey` in the resulting map, and the first element of that list * `set VAR` to set the workflow variable `VAR` to the the value at that point in the transformation * `return` to return the result of the transformation (not compatible with supplying a `value` to set in a variable) * any other word is looked up as a registered type of type `org.apache.brooklyn.core.workflow.steps.transform.WorkflowTransform` (or `WorkflowTransformWithContext` to get the context or arguments) @@ -142,6 +141,7 @@ input: | * `message`: a string to report in the exception * `rethrow`: whether to include any error in scope (if being used within an `on-error` step) + * `value`: on optional value that can be included in the failure, and for callers to inspect additional context output: _none_ (throws exception) - name: retry @@ -292,6 +292,21 @@ * `content_json`: the content, parsed as JSON if possible to return a map, list, string, or primitive (null if not valid json) * `duration`: how long the request took + - name: shell + summary: Runs a command using the local system shell + shorthand: '`shell COMMAND`' + input: | + * `command`: the command to run + * `env`: a map of string keys with values whose JSON is taken and passed to the command be executed + * `exit_code`: the word `any`, a number, or a predicate DSL expression (e.g. `less-than: 32`) + * `output_max_size`: by default output from commands is limited to 100k, truncating to keep the end; this can be increased or decreased, + or disabled with `-1` (assuming Apache Brooklyn has sufficient memory to hold the data) + * `interpolation_mode` and `interpolation_errors`: as per `let` and `load`, with defaults `full` and `ignore` so that applicable values are resolved and others deferred + output: | + * `stdout` + * `stderr` + * `exit_code` + - name: ssh summary: Runs a command over ssh shorthand: '`ssh COMMAND`' diff --git a/guide/blueprints/workflow/tips.md b/guide/blueprints/workflow/tips.md new file mode 100644 index 00000000..611956ce --- /dev/null +++ b/guide/blueprints/workflow/tips.md @@ -0,0 +1,72 @@ +--- +title: Tips and Tricks +layout: website-normal +--- + +## Filtering Lists + +There are many `transform` filters available, but none will filter lists. +Removing elements from a list is easily be done by using `foreach`` with a `condition`, +returning elements that meet the condition. + +For example, to filter out non-empty strings from a list: + +``` +- let list_to_filter = [ "word1", "", "word2" ] +- step: foreach item in ${list_to_filter} + condition: + size: { greater-than: 0 } + steps: + - return ${item} +``` + +The output from the `foreach` step is the list of results, +so this results in the filtered list `["word1", "word2"]`. + +(This condition uses `size` to find the length of the string. +The `condition: { not: { equals: "" } }` could just as well be used, +or using the fact that `equals` can be made implicit, simply +`condition: { not: "" }`.) + +Here is a more complicated example which filters comma-separated words +to return known fruits and proper names: + +``` +- let requested_foods = "apple, banana, Nutella, invalid" +- transform value ${requested_foods} | split regex \S*,\S* | trim +- let list known_fruits = [ "apple", "orange", "banana" ] +- step: foreach item in ${output} + condition: + any: + - regex: [A-Z].* # match proper name + - target: ${known_fruits} # match known fruits + contains: ${item} + steps: + - return ${item} +``` + +The above will return the list of `apple`, `banana`, and `Nutella`, dropping `invalid`. + + + +## Optimizing for Workflows + +Workflows can generate a huge amount of data which can impact memory usage, persistence, and the UI. +The REST API and UI do some filtering (e.g. in the body of the `internal` sensors used by workflow), +but when working with large `ssh` `output` and `http` `content` payloads, and with `update-children`, +performance can be dramatically improved by following these tips: + +* Optimize external calls to return the minimal amount of information needed + * Use `jq` to filter when using `ssh` or `container` steps + * Pass filter arguments to `http` endpoints that accept them + * Loop over small page sizes (e.g. 20 records per cycle from `http`) using `retry from` steps + +* Optimize the data which is stored + * Override the `output` on `ssh` and `http` steps to remove unnecessary objects; + for example `http` returns several `content*` fields, and often just one is needed. + Simply settings `output: { content: ${content} }` will achieve this. + * Set `retention: 1` or `retention: 0` on workflows that use a large amount of information + and can simply be replayed from the start; additionally `retention: disabled` can be used + to prevent any persistence (even for ongoing workflows), but only for workflows that do + not acquire any `lock` + diff --git a/guide/ops/configuration/brooklyn_cfg.md b/guide/ops/configuration/brooklyn_cfg.md index 7b22351e..0000af1f 100644 --- a/guide/ops/configuration/brooklyn_cfg.md +++ b/guide/ops/configuration/brooklyn_cfg.md @@ -187,10 +187,10 @@ brooklyn.entitlements.global=<class> The default entitlement manager is one which responds to per-user entitlement rules, and understands: -* `root`: full access, including to the Groovy console -* `poweruser`: full access, excluding to the Groovy console -* `user`: access to everything but actions that affect the server itself. Such actions include the - Groovy console, stopping the server and retrieving management context configuration +* `root`: full access, including local scripts and the Groovy console +* `poweruser`: full access apart from local shell scripts and Groovy scripts +* `user`: access to everything but actions that affect the server itself. Such actions include scripts, + stopping the server and retrieving management context configuration * `blueprintAuthor`: same as user but cannot install bundles containing jar or class files * `readonly`: read-only access to almost all information * `minimal`: access only to server stats, for use by monitoring systems @@ -268,9 +268,16 @@ brooklyn.webconsole.security.login.form=brooklyn-ui-login ## SSH and Script Defaults -Default values for SSH and script execution behaviour can be set in this file +Default values for SSH connection and script execution behaviour can be set in this file using the prefix `brooklyn.ssh.config.`, as described in [Locations](/guide/locations#os-setup). +Local shell access via the `shell` workflow step, available only to users with `root`-level entitlement, +can be disabled altogether using the following setting: + +``` +brooklyn.security.shell.workflow_step.disabled=true +``` + ## Certificate Validation