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
commit ddfef71ea9c7e8031dfee51392f5c10fd62a61f2 Author: Alex Heneveld <[email protected]> AuthorDate: Mon Oct 31 13:51:00 2022 +0000 add workflow examples --- guide/blueprints/workflow/defining.md | 23 ++++++------ .../ansible-bash}/example-ansible-and-bash.yaml | 17 --------- .../workflow/examples/ansible-bash/index.md | 12 +++++++ .../workflow/examples/git-latest/git-latest.bom | 41 ++++++++++++++++++++++ .../workflow/examples/git-latest/index.md | 24 +++++++++++++ guide/blueprints/workflow/examples/index.md | 14 ++++++++ guide/blueprints/workflow/examples/oauth/index.md | 28 +++++++++++++++ .../workflow/{ => examples/oauth}/oauth.yaml | 17 --------- guide/blueprints/workflow/index.md | 6 ++-- .../workflow/{steps.md => steps/index.md} | 0 guide/blueprints/yaml-reference.md | 31 +++++++++------- 11 files changed, 151 insertions(+), 62 deletions(-) diff --git a/guide/blueprints/workflow/defining.md b/guide/blueprints/workflow/defining.md index a7d879a3..d67775be 100644 --- a/guide/blueprints/workflow/defining.md +++ b/guide/blueprints/workflow/defining.md @@ -7,7 +7,7 @@ Let's start by discussing _why_ workflow is introduced and where it can and shou The Apache Brooklyn Workflow is designed to make it easy to describe behaviour of effectors, sensors, and policies in blueprints. It has the sophistication of a programming language including [conditions, loops, and error-handling](common.md) and [variables](variables.md), -but more important are the [steps](steps.md) which delegate to other systems, +but more important are the [steps](steps/) which delegate to other systems, such as containers or SSH or HTTP endpoints. Complex programming logic will typically be done in another system, such as a container; but where effectors and sensors need to interact with Brooklyn, such as reading and setting sensors, or invoking effectors, @@ -144,20 +144,21 @@ As an example: brooklyn.config: install.workflow: steps: - - ssh yum update - - ssh yum install ... + - ssh yum update + - ssh yum install ... launch.workflow: steps: - - ssh java ... + - let PORT = 4321 + - 'ssh { echo hello | nc -l ${PORT} & } ; echo $! > /tmp/brooklyn-nc.pid' + - 'set-sensor main.uri = http://localhost:${PORT}/' checkRunning.workflow: steps: - - ssh ps aux | grep java - - set-sensor check-running-detail = ${output.stdout} - - return true - on-error: - - type: no-op - output: false + - step: ssh ps -p `cat /tmp/brooklyn-nc.pid` + timeout: 10s + on-error: + - return false + - return true stop.workflow: steps: - - ssh killall java + - ssh kill -9 `cat /tmp/brooklyn-nc.pid` ``` diff --git a/guide/blueprints/workflow/example-ansible-and-bash.yaml b/guide/blueprints/workflow/examples/ansible-bash/example-ansible-and-bash.yaml similarity index 70% rename from guide/blueprints/workflow/example-ansible-and-bash.yaml rename to guide/blueprints/workflow/examples/ansible-bash/example-ansible-and-bash.yaml index 00e1b048..b95f7661 100644 --- a/guide/blueprints/workflow/example-ansible-and-bash.yaml +++ b/guide/blueprints/workflow/examples/ansible-bash/example-ansible-and-bash.yaml @@ -1,20 +1,3 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - name: Ansible+SSH HTTPD Web App # most any CentOS/RHEL environment should work diff --git a/guide/blueprints/workflow/examples/ansible-bash/index.md b/guide/blueprints/workflow/examples/ansible-bash/index.md new file mode 100644 index 00000000..2e550c83 --- /dev/null +++ b/guide/blueprints/workflow/examples/ansible-bash/index.md @@ -0,0 +1,12 @@ +--- +title: Ansible and BASH over SSH for a Web Server +title_in_menu: SSH/Ansible Entity +layout: website-normal +--- + +The following code defines an entity which uses Ansible and BASH on a CentOS server +to configure and run a web server (Apache `httpd`) running a simple HTML site. + +{% highlight yaml %} +{% readj example-ansible-and-bash.yaml %} +{% endhighlight %} diff --git a/guide/blueprints/workflow/examples/git-latest/git-latest.bom b/guide/blueprints/workflow/examples/git-latest/git-latest.bom new file mode 100644 index 00000000..83c17993 --- /dev/null +++ b/guide/blueprints/workflow/examples/git-latest/git-latest.bom @@ -0,0 +1,41 @@ +brooklyn.catalog: + bundle: git-workflow-utils + version: 1.0.0-SNAPSHOT + items: + - id: ssh-git-latest + format: bean-with-type + item: + type: workflow + shorthand: ${repo_url} [ " in " ${dir_name} ] + parameters: + repo_url: {} + dir_name: {} + steps: + - let dir_name = ${dir_name} ?? "" # allow this parameter to be optional + - type: ssh + command: | + + # move to this dir for cleanliness + mkdir -p managed-gits/ + cd managed-gits/ + + # install to this dir, relative or absolute, if specified + DIR="${dir_name}" + if [ -z "$DIR" ] ; then + + # if not specified infer from url name + DIR=`echo ${repo_url} | sed -E 's/(.git)?\/*$//g' | sed -E 's/.*\///'` + if [ -z "$DIR" ] ; then + echo Unable to infer directory + exit 1 + fi + fi + + if ( cd $DIR && git pull ) ; then + echo Successfully updated + else + rm -rf $DIR/ + git clone ${repo_url} $DIR + echo Successfully cloned + fi + output: ${stdout} \ No newline at end of file diff --git a/guide/blueprints/workflow/examples/git-latest/index.md b/guide/blueprints/workflow/examples/git-latest/index.md new file mode 100644 index 00000000..705b1519 --- /dev/null +++ b/guide/blueprints/workflow/examples/git-latest/index.md @@ -0,0 +1,24 @@ +--- +title: Custom Step to Retrieve a Git Repository +title_in_menu: Git Custom Step +layout: website-normal +--- + +This BOM file can be added to the catalog (download and run `br catalog add <file>`) to +enable a workflow step `ssh-git-latest REPO_URL`, which will connect to a target server over SSH, +then checkout or update a Git repository. + +This shows how easy it is to define custom workflow steps, +including your own custom shorthand syntax. + +The first time the step is run, the repository will be cloned. +Subsequently it will be updated. +This allows the step to be used flexibly and efficiently, irresepctive of whether it has been run before. +This type of idempotent workflow step is strongly recommended to make workflows easier to work with. + +The catalog blueprint is as follows: + +{% highlight yaml %} +{% readj git-latest.bom %} +{% endhighlight %} + diff --git a/guide/blueprints/workflow/examples/index.md b/guide/blueprints/workflow/examples/index.md new file mode 100644 index 00000000..3ea6c5ad --- /dev/null +++ b/guide/blueprints/workflow/examples/index.md @@ -0,0 +1,14 @@ +--- +title: Workflow Examples +title_in_menu: Examples +layout: website-normal +children: +- ansible-bash/ +- git-latest/ +- oauth/ +--- + +The following examples are available: + +{% include list-children.html %} + diff --git a/guide/blueprints/workflow/examples/oauth/index.md b/guide/blueprints/workflow/examples/oauth/index.md new file mode 100644 index 00000000..e62cbf3e --- /dev/null +++ b/guide/blueprints/workflow/examples/oauth/index.md @@ -0,0 +1,28 @@ +--- +title: OAuth web request workflow +title_in_menu: OAuth +layout: website-normal +--- + +The following code defines an entity with a workflow which makes web requests, +automatically refreshing with an OAuth token if the error message indicates that it should, +and using backoff/retry strategies. + +The blueprint assumes that a Google App requiring OAuth is set up. +This is easy done at Google, or the code should be straightforward to adapt for any other OAuth-based site. +The blueprint expects the following three values from an [externalized config provider](/guide/ops/externalized-config.md) +called `google-oauth`: + +* `google_client_id` - the client ID for the Google App (created when the App is created there) +* `google_client_secret` - the client secret for the Google App (created when the App is created there) +* `google_refresh_token` - a refersh token acquired for the app for a logged in user; + because this interaction is intended to be automated, it expects to be configured with a valid refresh token + (rather than redirect a user to a webpage); this is not a token for accessing the API directly, + but for acquiring a token to do so, and can be retrieved by interacting with the OAuth API ahead of time + or by inspecting the traffic for a UI-based log-in + +The blueprint is as follows: + +{% highlight yaml %} +{% readj oauth.yaml %} +{% endhighlight %} \ No newline at end of file diff --git a/guide/blueprints/workflow/oauth.yaml b/guide/blueprints/workflow/examples/oauth/oauth.yaml similarity index 78% rename from guide/blueprints/workflow/oauth.yaml rename to guide/blueprints/workflow/examples/oauth/oauth.yaml index a7dbd230..0ac6a735 100644 --- a/guide/blueprints/workflow/oauth.yaml +++ b/guide/blueprints/workflow/examples/oauth/oauth.yaml @@ -1,20 +1,3 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - name: google_oauth_example services: diff --git a/guide/blueprints/workflow/index.md b/guide/blueprints/workflow/index.md index 0d5b2304..8a84c90e 100644 --- a/guide/blueprints/workflow/index.md +++ b/guide/blueprints/workflow/index.md @@ -8,6 +8,7 @@ children: - steps.md - variables.md - nested-workflow.md +- examples/ --- Apache Brooklyn has a powerful workflow engine and syntax for defining entities, effectors, sensors, and policies. @@ -28,7 +29,4 @@ This can be used within [most Apache Brooklyn resources](defining.md). The syntax supports [longhand, conditions, loops, error-handling](common.md), [variables](variables.md), a large set of [built-in step types](steps.md), and the ability to [define custom step types](nested-workflow.md). -You can also get started by looking at examples: - -* [Ansible/BASH for a web server](example-ansible-and-bash.yaml) -* [OAuth web request workflow](oauth.yaml) +You can also get started by looking at a variety [examples](examples/). diff --git a/guide/blueprints/workflow/steps.md b/guide/blueprints/workflow/steps/index.md similarity index 100% rename from guide/blueprints/workflow/steps.md rename to guide/blueprints/workflow/steps/index.md diff --git a/guide/blueprints/yaml-reference.md b/guide/blueprints/yaml-reference.md index 13d3bc38..6a4d1d97 100644 --- a/guide/blueprints/yaml-reference.md +++ b/guide/blueprints/yaml-reference.md @@ -241,23 +241,31 @@ concise DSL defined here: can be used to supply config at the root which is used in multiple places in the plan * `$brooklyn:sensor("sensor.name")` returns the given sensor on the current entity if found, or an untyped (Object) sensor; `$brooklyn:sensor("com.acme.brooklyn.ContainingEntityClass", "sensor.name")` returns the strongly typed sensor defined in the given class -* `$brooklyn:entity("ID")` refers to a Brooklyn entity with the given ID; you can then access the following subfields, + +* `$brooklyn:entity("ID")` refers to a Brooklyn entity with the given ID; + you can then access the following subfields, using the same syntax as defined above but with a different reference entity, e.g. `$brooklyn:entity("ID").attributeWhenReady("sensor")`: * `.attributeWhenReady("sensor")` * `.config("key")` * `.sensor("sensor.name")` -* `$brooklyn:component("scope", "ID")` is also supported, to limit scope to any of - * `global`: looks for the `ID` anywhere in the plan - * `child`: looks for the `ID` anywhere in the child only - * `descendant`: looks for the `ID` anywhere in children or their descendants - * `sibling`: looks for the `ID` anywhere among children of the parent entity - * `parent`: returns the parent entity (ignores the `ID`) - * `this`: returns this entity (ignores the `ID`) +* `$brooklyn:component("ID")` is also supported as a synonym for the above + (optionally taking a scope in the first argument but this is deprecated from the DSL as the scope is + redundant with the methods below); note methods prefer matching entities nearer the origin, + and only look in the same application unless otherwise noted (e.g. `application("ID")`), + and can be chained, e.g. `application("other_app").entity("node_in_other_app").config("key_there")` +* `$brooklyn:self()` will return the current entity +* `$brooklyn:parent()` will return the entity's parent, failing if it is an application * `$brooklyn:root()` will return the topmost entity (the application) * `$brooklyn:scopeRoot()` will return the root entity in the current plan scope. For catalog items it's the topmost entity in the plan, for application plans it is the same as `$brooklyn:root()`. +* `$brooklyn:child("ID")`: looks for any immediate child with the given `ID` +* `$brooklyn:application("ID")`: looks for any application (root) with the given `ID` +* `$brooklyn:descendant("ID")`: looks for any descendant excluding members with the given `ID` +* `$brooklyn:member("ID")`: looks for any descendant including members with the given `ID` +* `$brooklyn:sibling("ID")`: looks for any child of the entity's parent with the given `ID` + * `$brooklyn:formatString("pattern e.g. %s %s", "field 1", "field 2")` returns a future which creates the formatted string with the given parameters, where parameters may be strings *or* other tasks such as `attributeWhenReady` * `$brooklyn:external("provider", "token")` return the value stored for `token` in the externalized configuration store identified as `provider` @@ -276,8 +284,6 @@ concise DSL defined here: (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 --> - Parameters above can be supplied either as strings or as lists and maps in YAML, and the `$brooklyn:` syntax can be used within those parameters. **Note:** The DSL is always supported for the values of config keys on entities. The DSL is supported in many other places also, but not all, depending on how the value is used there. For instance some aspects of a location or initializer may need to be retrieved without an entity context and so do not support DSL. @@ -289,11 +295,10 @@ All entities support configuration via YAML, but these entities in particular have been designed for general purpose use from YAML. Consult the Javadoc for these elements for more information: +* **Workflow Software** in `WorkflowSoftwareProcess`: makes it very easy to build entities + using workflow to install, launch, stop, and check running * **Vanilla Software** in `VanillaSoftwareProcess`: makes it very easy to build entities which use `bash` commands to install and the PID to stop and restart -* **Chef** in `ChefSoftwareProcess`: makes it easy to use Chef cookbooks to build entities, - either with recipes following conventions or with configuration in the `ServiceSpecification` - to use arbitrary recipes * `DynamicCluster`: provides resizable clusters given a `dynamiccluster.memberspec` set with `$brooklyn.entitySpec(Map)` as described above * `DynamicFabric`: provides a set of homogeneous instances started in different locations, with an effector to `addLocation`, i.e. add a new instance in a given location, at runtime
