YAML Blueprint Reference
Root Elements
name
: human readable namesservices
: a list ofServiceSpecification
elementslocation
(orlocations
taking a list): aLocationSpecification
element as a string or a map
Service Specification Elements
Within the services
block, a list of maps should be supplied, with each map
defining a ServiceSpecification
. Each ServiceSpecification
should declare the
service type
(synonyms serviceType
and service_type
), indicating what type of
service is being specified there. The following formats are supported for
defining types:
com.acme.brooklyn.package.JavaEntityClass
java:com.acme.brooklyn.package.JavaEntityClass
java-entity-class
(where this has been added to the catalog)
A reference of some of the common service type
instances used is included in a section below.
Within the ServiceSpecification
, other key-value pairs can be supplied to customize
the entity being defined, with these being the most common:
-
id
: an ID string, used to refer to this service -
location
(orlocations
): as defined in the root element -
brooklyn.config
: configuration key-value pairs passed to the service entity being created; complex values are supported if they are JSON-deserializable beans that have been added as registered types -
brooklyn.children
: a list ofServiceSpecifications
which will be configured as children of this entity -
brooklyn.policies
: a list of policies, each as a map described with theirtype
and theirbrooklyn.config
as keys -
brooklyn.enrichers
: a list of enrichers, each as a map described with theirtype
and theirbrooklyn.config
as keys; see the keys declared on individual enrichers; also see this enricher example for a detailed and commented illustration -
brooklyn.initializers
: a list ofEntityInitializer
instances to be constructed and run against the entity, each as a map described with theirtype
(Java or a registered type in the catalog) and JSON-serializable fields.An
EntityInitializer
can perform arbitrary customization to an entity whilst it is being constructed, such as adding dynamic sensors and effectors.Some common initializers are:
-
org.apache.brooklyn.core.effector.ssh.SshCommandEffector
: takes aname
andcommand
, and optionally a map of namedparameters
to theirdescription
anddefaultValue
, to define an effector with the given name implemented by the given SSH command (on an entity which as an ssh-able machine) -
org.apache.brooklyn.core.sensor.ssh.SshCommandSensor
: takes aname
andcommand
, and optionally aperiod
(e.g.1h
) ortriggers
(a sensor name, or list containing sensor names or maps of the form{entity: id, sensor: name}
), to create a sensor feed which populates the sensor with the given name by running the given command (on an entity which as an ssh-able machine); this also takes an optionaltype
to coerce the output from YAML or JSON (if the---
document separator is used, only the output after the last such separator is coerced, allowing output to be verbose until the final section) -
org.apache.brooklyn.tasks.kubectl.ContainerSensor
: takes aname
andimage
, and optionally eitherbashScript
orcommand
, and optionally the sameperiod
andtriggers
andtype
asSshCommandSensor
, to create a sensor feed which runs the given container to populate the sensor -
org.apache.brooklyn.core.sensor.windows.WinRmCommandSensor
: For a command supplied via WinRm. Takes aname
,command
, and optionally aperiod
ortriggers
, and optionallyexecutionDir
, to create a sensor feed which populates the sensor with the given name by running the given command (on an entity which as an WinRM-able machine);"~"
will use the default execution directory for the WinRm session which is usually%USERPROFILE%
When specifying the type of an initializer, registered types (added to the catalog) are preferred, but Java types are permitted.
Advanced note: When implementing an initializer in Java, it is preferred to rely on standard Jackson serialization techniques to initialize fields, i.e. have a no-arg constructor and fields which can be specified in YAML. However it is permitted for backwards compatibility, to supply configuration under a
brooklyn.config
key; via a public constructor taking a singleConfigBag
(or sometimes aMap
) where thebrooklyn.config
key-values are passed in. This approach has several constraints however. The config inheritance modes which are used on entities and other spec types are not recognised here. If the type is added to the catalog and referred to by its registered type name, or if registered types are being passed as config, the class must support JSON deserialization ofbrooklyn.config
, and that is strongly recommended since Cloudsoft AMP v1.1. This can be done by ensuring a no-arg constructor is defined and supplying a@JsonSetter("brooklyn.config") initializeConfig(Map<String,Object)
method. There are convenience abstract classes inEntityInitializers
which can be useful for more complicated configurations. -
brooklyn.parameters
: documents a list of typed parameters the entity accepts. These define config keys exposed on the type, including metadata for prompting a user to supply them. All config keys inherited from supertypes are available as parameters by default, and their properties (e.g. default values) can be overridden. Parameters (config keys) have the following properties:name
(required): identifier by which to reference the parameter when setting or retrieving its valuelabel
: an identifier string to present to the user when prompting for a value, same asname
if emptydescription
: short text describing the parameter behaviour/usage, presented to the usertype
: the type of the parameter, one ofstring
,integer
,long
,float
,double
,timestamp
,duration
,port
, or a fully qualified Java type name; the default isstring
; obvious coercion is supported sotimestamp
accepts most common ISO date formats,duration
accepts5m
, and port accepts8080+
default
: a default value; this will be coerced to the declaredtype
pinned
: mark the parameter as pinned (always displayed) for the UI. The default istrue
(unless an ancestor sets false; config keys from Java types are not pinned)constraints
: a list of constraints the parameter should meet; for details, see Entity Configuration.
A shorthand notation is also supported where just the name of the parameter can be supplied as an item in the list, with the other values being unset or the default. See
displayName
in the following example for an illustration of this:brooklyn.parameters: # user.age parameter is required, pinned and fully specified - name: user.age type: integer label: Age description: the age of the user pinned: true constraints: - required # user.name is optional, is not pinned and has a default - name: user.name default: You pinned: false # shorthand notation: displayName will be an optional config of type string with no default - displayName
Referencing the parameters from within java classes is identical to using config keys. In yaml it’s usually referenced using
$brooklyn:scopeRoot().config("displayName")
. See below for more details on scopes.brooklyn.tags
: a list of tag objects which should be attached to the entity.
Entities (and policies and enrichers) will typically accept additional key-value pairs
as per the config keys (parameters) they expose. In some cases they may accept other fields
(where fields in a Java class are annotated @SetFromFlag
although this is discouraged),
but undeclared config is only accepted in the brooklyn.config
map.
Global config can be passed in either at the root of the ServiceSpecification
or in a root brooklyn.config
section.
Initializers and custom types used as config/parameters are treated as beans, with fields at the root.
However in many cases initializers also accept configuration passed in a brooklyn.config
section.
To accept expressions using the AMP DSL ($brooklyn:xxx
) in fields of beans,
the field type should be declared as a WrappedValue<T>
, where T
is the desired type.
(Config key values will always accept the AMP DSL without this, but fields will not.)
Location Specification Elements
In brief, location specs are supplied as follows, either for the entire application (at the root)
or for a specific ServiceSpecification
:
location:
jclouds:aws-ec2:
region: us-east-1
identity: AKA_YOUR_ACCESS_KEY_ID
credential: <access-key-hex-digits>
Or in many cases it can be in-lined:
location: localhost
location: named:my_openstack
location: aws-ec2:us-west-1
For the first immediately, you’ll need password-less ssh access to localhost.
For the second, you’ll need to define a named location in brooklyn.properties
,
using brooklyn.location.named.my_openstack....
properties.
For the third, you’ll need to have the identity and credentials defined in
brooklyn.properties
, using brooklyn.location.jclouds.aws-ec2....
properties.
If specifying multiple locations, e.g. for a fabric:
locations:
- localhost
- named:my_openstack
- aws-ec2:us-east-2 # if credentials defined in `brooklyn.properties
- jclouds:aws-ec2:
region: us-east-1
identity: AKA_YOUR_ACCESS_KEY_ID
credential: <access-key-hex-digits>
If you have pre-existing nodes, you can use the byon
provider, either in this format:
location:
byon:
user: root
privateKeyFile: ~/.ssh/key.pem
hosts:
- 11.22.33.44
- 11.22.33.45
- brooklyn@55.66.77.88
- brooklyn@55.66.77.89
or:
location:
byon:
user: root
privateKeyFile: ~/.ssh/key.pem
hosts: "{11.22.33.{44,45},brooklyn@55.66.77.{88-89}"
You cannot use glob expansions with the list notation, nor can you specify per-host
information apart from user within a single byon
declaration.
However you can combine locations using multi
:
location:
multi:
targets:
- byon:
user: root
privateKeyFile: ~/.ssh/key.pem
hosts:
- 11.22.33.44
- 11.22.33.45
- byon:
privateKeyFile: ~/.ssh/brooklyn_key.pem
hosts: brooklyn@55.66.77{88-89}
DSL Commands
Dependency injection other powerful references and types can be built up within the YAML using the concise DSL defined here:
$brooklyn:attributeWhenReady("sensor")
will store a future which will be blocked when it is accessed, until the givensensor
from this entity “truthy” (i.e. non-trivial, non-empty, non-zero) value (see below oncomponent
for looking up values on other sensors); this can take a second argument being a map of optionstimeout
,timeout_if_down
,abort_if_on_fire
(defaulttrue
), andwait_for_truthy
(defaulttrue
); the default is{ $brooklyn:attributeWhenReady: [ "sensor", { timeout: "forever", timeouf_if_down: "1m" } ] }
$brooklyn:config("key")
will insert the value set against the given key at this entity (or nearest ancestor); 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 an AMP 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("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 givenID
$brooklyn:application("ID")
: looks for any application (root) with the givenID
$brooklyn:descendant("ID")
: looks for any descendant excluding members with the givenID
$brooklyn:member("ID")
: looks for any descendant including members with the givenID
-
$brooklyn:sibling("ID")
: looks for any child of the entity’s parent with the givenID
$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 asattributeWhenReady
$brooklyn:external("provider", "token")
return the value stored fortoken
in the externalized configuration store identified asprovider
$brooklyn:urlEncode("val")
returns a future which creates a string with the characters escaped so it is a valid part of a URL. The parameter can be a string or another task. For example,$brooklyn:urlEncode($brooklyn:config(\"mykey\"))
. It uses “www-form-urlencoded” for the encoding, which is appropriate for query parameters but not for some other parts of the URL (e.g. space is encoded as'+'
).$brooklyn:literal("string")
returns the given string as a literal (suppressing any$brooklyn:
expansion)$brooklyn:object(Map)
creates an object, using keystype
to define the java type, and eitherobject.fields
orbrooklyn.config
to supply bean/constructor/flags to create an instance$brooklyn:entitySpec(Map)
returns a newServiceSpecification
as defined by the givenMap
, but as anEntitySpec
suitable for setting as the value ofConfigKey<EntitySpec>
config items (such asdynamiccluster.memberspec
inDynamicCluster
); this is often not needed, if theEntitySpec
is expected by context and can be coerced from a map using the simple Jackson deserialization in theEntitySpec
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)$brooklyn:chain: [ dsl, chained_function ]
allows chaining anotherdsl
expression with a function on the result of that expression, identical to usingdsl.chained_function
but for cases where one or the other requires list or maps
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.
Some Powerful YAML Entities
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 usebash
commands to install and the PID to stop and restart DynamicCluster
: provides resizable clusters given adynamiccluster.memberspec
set with$brooklyn.entitySpec(Map)
as described aboveDynamicFabric
: provides a set of homogeneous instances started in different locations, with an effector toaddLocation
, i.e. add a new instance in a given location, at runtime
Notable Tags
Some tags are used by convention and in the UI for special purposes. These are:
-
ui-composer-annotation
: text (interpreted as markdown without HTML support) which will be displayed on a node in the Blueprint Composer, or a map containing a key with thetext
and optionally any/all of{x, y, width, height, background, style, styleInnerDiv}
for displaying it. The display of these can be toggled in the Blueprint Composer by selecting “Layers > Annotations”. This is illustrated in the following blueprint:name: Annotation Sample services: - type: server brooklyn.tags: - ui-composer-annotation: A simple default annotation - ui-composer-annotation: text: >- Shown below, yellow text, centered with CSS. Because it's long, scroll bars horizontally and vertically shown when needed. styleInnerDiv: 'margin: auto; color: yellow;' y: 120 - type: server brooklyn.tags: - ui-composer-annotation: text: | ## Big Example A **red** tag at _right_, using markdown, in a big box. width: 300 height: 200 x: 220 y: 0 background: '#ffcccc' style: 'font-size: 9px;'
-
ui-composer-hints
: a collection of tags typically on an entity definitiion providing hints to composers, includingconfig-widgets
(setting custom widgets to render fields) andconfig-quick-fixes
(proposals for fixing common errors); see the code for the Blueprint Composer for more details -
ui-effector-hints
: a tag containing a single-entry map with this key will constrain how effectors are presented in the UI. The value should be a map containing one or more of the following keys:exclude-regex
: a regex string matched against effector names to exclude them from listing in the “Effectors” taginclude-regex
: a regex string per above to explicitly include matching names which would be excluded by the above
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 necessaryregex: <string|number>
glob: <string|number>
not: <test>
, to return whether the indicated<test>
failscheck: <test>
, to apply the indicated<test>
(mainly useful to structure checks involving retargeting, e.g. nestedkey
lookups)when: <presence>
, where<presence>
is one of the values described belowassert: <presence|test>
, to cause the test to fail fast if the value does not meet the indicated<presence>
or<test>
, throwing an exception with details rather than merely returning falseless-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 falsegreater-than: <object>
, as aboveless-than-or-equal-to: <object>
as abovegreater-than-or-equal-to: <object>
, as abovesize: <test>
, for lists, maps, and strings, to apply the<test>
to the size/length, e.g.size: 0
for empty,size: { greater-than: 0 }
ornot: { size: 0 }
for non-emptyhas-element: <test>
, for lists, checks whether any entry satisifes the<test>
(same for sets; and for maps, applying<test>
to each key-value entry as a two-element list)in-range: <range>
, where<range>
is a list of two numbers, e.g.[0,100]
(always inclusive)java-instance-of: <test|registered-type>
, where the<test>
is applied to the underlying java class of the value being tested and all super-classes and super-interfaces, allowing strings to match the fully qualified or simple name of the class or any super, and string tests (e.g. glob, regex) applied to the fully-qualified class name; if the argument is a string it is also tested as a registered type and instance-of applied against the the type assignment of the underlying java class of the value being tested with the underlying java type of that registered type
Where a <test>
is required, unless otherwise indicated a string or integer can be supplied to imply an equals
test.
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, When, and Assert
The <presence>
object allows for testing of edge case values,
to distinguish between values which are unavailable
(e.g. a sensor which has not been published, or a config which is unset),
values which are null,
and values 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 resolvedpresent
: value is available, but might be nullpresent_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 truenever
: always returns false
The key when
can be used with any of these values to cause the check to return false
if the presence requirement is not met.
The key assert
can be used with any of these values to cause the check to fail immediately,
throwing an exception with details, if the presence requirement is not met.
This key can also take a nested condition (but not an implicit equals).
Typically assert
is used to ensure that the condition is testing the right target
and to provide feedback in the form of an error message if some conditions are not met.
Whereas the other keys will simply return false with little or feedback
unless trace
logging is enabled, a <presence>
or <test>
in an assert
key
will provide information about why the condition has failed.
This can be useful to inform the user if they provided invalid input and for debugging
(to make it easier to see why conditions are returning false).
As an example, consider the following condition:
condition:
index: 0
glob: a*
assert: present_not_null
If given a list with at least one element, it will return true if the first element starts with a
,
and false if there is a first element which does not start with a
.
If the input is an empty list, or not a list, or contains null
as the first entry,
the assert: present_not_null
line causes it to throw an exception saying which of these is the case.
(Without this line the condition will simply return false
in any of these cases.)
Error Handling
Two additional options are available for checking errors or any Java Throwable
type:
error-field: <name>
, to retarget the test against the value of the field<name>
on the throwable, trying first withtarget.getName()
then withtarget.name
; this is useful for inspecting themessage
or other fields such asstatusCode
that might be present on an error classerror-cause: <test>
, to retarget the test against the throwable or its cause, recursively, finding the first instance which matches the test; this is useful where exceptions have been wrapped at the point where they need to test
These are especially powerful in conjunction with java-instance-of
and regex
or glob
.
For example the following will match any exception which is, or is caused by, an
HttpResponseException
whose toString (message) contains www.acme.com
and where the getStatusCode()
method returns an HTTP error code (400 or higher).
This could be used, for instance, to retry workflow steps in the case of specific
errors on specific servers.
condition:
error-cause:
java-instance-of: HttpResponseException
glob: *www.acme.com*
check:
error-field: statusCode
greater-than-or-equal-to: 400
Entity Tests
To assist with tests on an Entity
or Location
, additional keys are supported on
the DslPredicate
via DslEntityPredicate
, which allow “retargetting” the expression under test.
These expressions change the focus of the tests defined in the predicate as follows:
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, currentlylocations
orchildren
ortags
, to evaluate the tests against the location(s) or children of that entity, and the singular (location
,child
, ortag
) to check any child on the current test (implicitly wrapping all other fields inhas-element
, so long ashas-element
isn’t implicitly set)config: <string>
: indicates that the tests should be applied to the value of config key<string>
on the context entity, location, or policysensor: <string>
: indicates that the tests should be applied to the value of sensor<string>
on the context entity
For either config
or sensor
, there is a default test for truthiness (cf DSL availableWhenReady
).
For everything else, it is an error if a test is omitted.
Additionally on entities and locations, there is a test:
tag: <test>
: indicates that<test>
should be applied to all tags on the context entity, location, or policy, passing if any tag passes the test; this is an alternative to specifyingtag
ortags
as thetarget
(if that is supplied along with atag: <test>
, the predicate will check whether any tag has a tag)
Lists, Maps and JSON Behaviour
To facilitate testing against collections (e.g. target: locations
, or a map or complex type)
the following retargetting keys are supported:
key: <object>
: retargets the tests to the value at the indicated key in a mapfilter: <test>
: retargets the tests to be a sub-list of entries matching<test>
(for lists and sets, and with maps treated as perhas-element
)index: <integer>
: retargets the tests to the value at the indicated index in a list or set or map (for maps returning a two-element list, perhas-element
)jsonpath: <string>
: applies the given JSON-Path<string>
, e.g.key.subkey[1].list[0]
, to the JSON serialization of the value under test, and retargets to the resulting value, or list of values if..
or*
is used (some strict JSON-Path expressions require a$.
prefix before key names and$
before[
expressions; they are accepted but are unnecessary and will be inferred if omitted)
Examples
Entity Config
The following will test whether an entity has a config region
starting with us-
, for example to filter within a DynamicGroup
:
config: region
glob: us-*
(Instead of the glob
, writing regex: us-.*
would be equivalent.)
Location Config
Sometimes we may wish to apply a similar filter, but for entities where any location matches the test.
We can use a target
and the has-element
test:
target: locations
has-element:
config: region
glob: us-*
We can instead use the shorthand location
which implies has-element
:
target: location
config: region
glob: us-*
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
Present, Absent, and Null Sensors
This will select entities which have a non-trivial (“truthy”) value for the sensor “ready”:
sensor: ready
This will select entities which have not published the sensor “ready”:
sensor: ready
when: absent
And this will select entities where that sensor has been published, but its value is null, false, or empty.
sensor: ready
all:
- when: present
- when: falsy