blob: bee29f0baa3b309c5fdf7a799b8e9671f7b8703a [file] [log] [blame] [view]
---
title: Entity Configuration
layout: website-normal
toc: ../guide_toc.json
categories: [use, guide, defining-applications]
---
Within a blueprint or catalog item, entities can be configured. The rules for setting this
configuration, including when composing and extending existing entities, is described in this
section.
### Basic Configuration
Within a YAML file, entity configuration should be supplied within a `brooklyn.config` map. It is
also possible to supply configuration at the top-level of the entity. However, that approach is
discouraged as it can sometimes be ambiguous (e.g. if the config key is called "name" or "type"),
and also it does not work in all contexts such as for an enricher's configuration.
A simple example is shown below:
{% highlight yaml %}
services:
- type: org.apache.brooklyn.entity.webapp.tomcat.TomcatServer
brooklyn.config:
webapp.enabledProtocols: http
http.port: 9080
wars.root: https://search.maven.org/remotecontent?filepath=org/apache/brooklyn/example/brooklyn-example-hello-world-webapp/0.12.0/brooklyn-example-hello-world-webapp-0.12.0.war # BROOKLYN_VERSION
{% endhighlight %}
If no config value is supplied, the default for that config key will be used. For example,
`http.port` would default to 8080 if not explicitly supplied.
Some config keys also have a short-form (e.g. `httpPort` instead of `http.port` would also work
in the YAML example above). However, that approach is discouraged as it does not work in all contexts
such as for inheriting configuration from a parent entity.
### Configuration in a Catalog Item
When defining an entity in the catalog, it can include configuration values like any other
blueprint (i.e. inside the `brooklyn.config` block).
It can also explicitly declare config keys, using the `brooklyn.parameters` block. The example
below illustrates the principle:
{% highlight yaml %}
{% read example_yaml/entity-config-catalog.yaml %}
{% endhighlight yaml %}
Once added to the catalog, it can be used with the simple blueprint below (substituting the location
of your choice). Because no configuration has been overridden, this will use the default value
for `custom.message`, and will use the given values for `launch.command` and `checkRunning.command`:
{% highlight yaml %}
{% read example_yaml/entity-config-app.yaml %}
{% endhighlight yaml %}
For details of how to write and add catalog items, see [Catalog](/guide/blueprints/catalog),
and for a complete reference on the syntax of `brooklyn.parameters` see that section of the [YAML Reference](/guide/blueprints/yaml-reference.md).
#### Config Key Constraints
The config keys in the `brooklyn.parameters` can also have a list of constraints defined, for what values
are valid. If more than one constraint is defined, then they must all be satisfied. The constraints
can be any of:
* `required`: deployment will fail if no value is supplied for this config key
* `regex: <pattern>`: the value must match the regular expression `<pattern>`
* `glob: <pattern>`: the value must match the bash-style wildcard glob `<pattern>`
* `urlExists: <url>`: the server must be able to resolve and access the URL `<url>`
* `forbiddenIf: <key>`: setting a value is disallowed if the config key `<key>` has a value set
* `forbiddenUnless: <key>`: setting a value is disallowed if the config key `<key>` does not have a value set
* `requiredIf: <key>`: a value is required if the config key `<key>` has a value set
* `requiredUnless: <key>`: a value is required if the config key `<key>` does not have a value set
* Any java `Predicate`, declared using the DSL `$brooklyn:object`.
This is illustrated in the example below:
{% highlight yaml %}
{% read example_yaml/entity-constraint-catalog.yaml %}
{% endhighlight yaml %}
An example usage of this toy example, once added to the catalog, is shown below:
{% highlight yaml %}
{% read example_yaml/entity-constraint-app.yaml %}
{% endhighlight yaml %}
### Complex Types in Configuration
Often configuration objects will be "primitives" -- `string`, `integer`, `boolean`, `char`.
But they can be more sophisticated:
* `list` and `map` are supported, and can be declared with generics, e.g. `type: map<string,boolean>`
* a `value-wrapper` that can be a value or can be a Brooklyn DSL expression
* a `port` which allows specifying a range or set of values, eg `8080+` or `80,443,[8000-8999]`
* a `duration` which recognises textual input, eg `2 minutes`
* any type registered with the catalog as a `bean` using `bean-with-type`
(see [Catalog](/guide/blueprints/catalog))
### Inheriting Configuration
Configuration can be inherited from a super-type, and from a parent entity in the runtime
management hierarchy. This applies to entities and locations. In a future release, this will be
extended to also apply to policies and enrichers.
When a blueprint author defines a config key, they can explicitly specify the rules for inheritance
(both for super/sub-types, and for the runtime management hierarchy). This gives great flexibilty,
but should be used with care so as not to surprise users of the blueprint.
The default behaviour is outlined below, along with examples and details of how to explilcitly
define the desired behaviour.
#### Normal Configuration Precedence
There are several places that a configuration value can come from. If different values are
specified in multiple places, then the order of precedence is as listed below:
1. Configuration on the entity itself
2. Inherited configuration from the super-type
3. Inherited configuration from the runtime type hierarchy
4. The config key's default value
#### Inheriting Configuration from Super-type
When using an entity from the catalog, its configuration values can be overridden. For example,
consider the `entity-config-example` added to the catalog in the section
[Configuration in a Catalog Item](#configuration-in-a-catalog-item).
We can override these values. If not overridden, then the existing values from the super-type will be used:
{% highlight yaml %}
{% read example_yaml/entity-config-override-app.yaml %}
{% endhighlight yaml %}
In this example, the `custom.message` overrides the default defined on the config key.
The `launch.command` overrides the original command. The other config (e.g. `checkRunning.command`)
is inherited unchanged.
It will write out: `Sub-type launch command: Goodbye`.
#### Inheriting Configuration from a Parent in the Runtime Management Hierarchy
Configuration passed to an entity is inherited by all child entities, unless explicitly overridden.
In the example below, the `wars.root` config key is inherited by all TomcatServer entities created
under the cluster, so they will use that war:
{% highlight yaml %}
services:
- type: org.apache.brooklyn.entity.group.DynamicCluster
brooklyn.config:
wars.root: https://search.maven.org/remotecontent?filepath=org/apache/brooklyn/example/brooklyn-example-hello-world-webapp/0.12.0/brooklyn-example-hello-world-webapp-0.12.0.war # BROOKLYN_VERSION
dynamiccluster.memberspec:
$brooklyn:entitySpec:
type: org.apache.brooklyn.entity.webapp.tomcat.TomcatServer
{% endhighlight %}
In the above example, it would be better to have specified the `wars.root` configuration in the
`TomcatServer` entity spec, rather than at the top level. This would make it clearer for the reader
what is actually being configured.
The technique of inherited config can simplify some blueprints, but care should be taken.
For more complex (composite) blueprints, this can be difficult to use safely; it relies on
knowledge of the internals of the child components. For example, the inherited config
may impact multiple sub-components, rather than just the specific entity to be changed.
This is particularly true when using complex items from the catalog, and when using common config
values (e.g. `install.version`).
An alternative approach is to declare the expected configuration options at the top level of the
catalog item, and then (within the catalog item) explicitly inject those values into the correct
sub-components. Users of this catalog item would set only those exposed config options, rather
than trying to inject config directly into the nested entities.
#### DSL Evaluation of Inherited Config
When writing blueprints that rely on inheritance from the runtime management hierarchy, it is
important to understand how config keys that use DSL will be evaluated. In particular, when
evaluating a DSL expression, it will be done in the context of the entity declaring the config
value (rather than on the entity using the config value).
For example, consider the config value `$brooklyn:attributeWhenReady("host.name")`
declared on entity X, and inherited by child entity Y. If entity Y uses this config value,
it will get the "host.name" attribute of entity X.
Below is another (contrived!) example of this DSL evaluation. When evaluating `refExampleConfig`,
it retrievies the value of `exampleConfig` which is the DSL expression, and evaluates this in the
context of the parent entity that declares it. Therefore `$brooklyn:config("ownConfig")` returns
the parent's `ownConfig` value, and the final result for `refExampleConfig` is set to "parentValue":
{% highlight yaml %}
services:
- type: org.apache.brooklyn.entity.stock.BasicApplication
brooklyn.config:
ownConfig: parentValue
exampleConfig: $brooklyn:config("ownConfig")
brooklyn.children:
- type: org.apache.brooklyn.entity.stock.BasicEntity
brooklyn.config:
ownConfig: childValue
refExampleConfig: $brooklyn:config("exampleConfig")
{% endhighlight %}
_However, the web-console also shows other misleading (incorrect!) config values for the child
entity. It shows the inherited config value of `exampleConfig` as "childValue" (because the
REST API did not evaluate the DSL in the correct context, when retrieving the value!
See https://issues.apache.org/jira/browse/BROOKLYN-455._
#### Merging Configuration Values
For some configuration values, the most logical behaviour is to merge the configuration value
with that in the super-type. This depends on the type and meaning of the config key, and is thus
an option when defining the config key.
Currently it is only supported for merging config keys of type Map.
Some common config keys will default to merging the values from the super-type. These config keys
include those below. The value is merged with that of its super-type (but will not be merged with
the value on a parent entity):
* `shell.env`: a map of environment variables to pass to the runtime shell
* `files.preinstall`: a mapping of files, to be copied before install, to destination name relative to installDir
* `templates.preinstall`: a mapping of templates, to be filled in and copied before pre-install, to destination name relative to installDir
* `files.install`: a mapping of files, to be copied before install, to destination name relative to installDir
* `templates.install`: a mapping of templates, to be filled in and copied before install, to destination name relative to installDir
* `files.runtime`: a mapping of files, to be copied before customisation, to destination name relative to runDir
* `templates.runtime`: a mapping of templates, to be filled in and copied before customisation, to destination name relative to runDir
* `provisioning.properties`: custom properties to be passed in when provisioning a new machine
A simple example of merging `shell.env` is shown below (building on the `entity-config-example` in
the section [Configuration in a Catalog Item](#configuration-in-a-catalog-item)).
The environment variables will include the `MESSAGE`
set in the super-type and the `MESSAGE2` set here:
{% highlight yaml %}
location: aws-ec2:us-east-1
services:
- type: entity-config-example
brooklyn.config:
shell.env:
MESSAGE2: Goodbye
launch.command: |
echo "Different example launch command: $MESSAGE and $MESSAGE2"
{% endhighlight %}
To explicitly remove a value from the super-type's map (rather than adding to it), a blank entry
can be defined.
#### Entity provisioning.properties: Overriding and Merging
An entity (which extends `SoftwareProcess`) can define a map of `provisioning.properties`. If
the entity then provisions a location, it passes this map of properties to the location for
obtaining the machine. These properties will override and augment the configuration on the location
itself.
When deploying to a jclouds location, one can specify `templateOptions` (of type map). Rather than
overriding, these will be merged with any templateOptions defined on the location.
In the example below, the VM will be provisioned with minimum 2GB RAM and minimum 2 cores. It will
also use the merged template options value of
`{placementGroup: myPlacementGroup, securityGroupIds: sg-000c3a6a}`:
{% highlight yaml %}
location:
aws-ec2:us-east-1:
minRam: 2G
templateOptions:
placementGroup: myPlacementGroup
services:
- type: org.apache.brooklyn.entity.machine.MachineEntity
brooklyn.config:
provisioning.properties:
minCores: 2
templateOptions:
securityGroupIds: sg-000c3a6a
{% endhighlight %}
The merging of `templateOptions` is shallow (i.e. maps within the `templateOptions` are not merged).
In the example below, the `userMetadata` value within `templateOptions` will be overridden by the
entity's value, rather than the maps being merged; the value used when provisioning will be
`{key2: val2}`:
{% highlight yaml %}
location:
aws-ec2:us-east-1:
templateOptions:
userMetadata:
key1: val1
services:
- type: org.apache.brooklyn.entity.machine.MachineEntity
brooklyn.config:
provisioning.properties:
userMetadata:
key2: val2
{% endhighlight %}
#### Re-inherited Versus not Re-inherited
For some configuration values, the most logical behaviour is for an entity to "consume" the config
key's value, and thus not pass it down to children in the runtime type hierarchy. This is called
"not re-inherited".
Some common config keys that will not re-inherited include:
* `install.command` (and the `pre.install.command` and `post.install.command`)
* `customize.command` (and the `pre.customize.command` and `post.customize.command`)
* `launch.command` (and the ``pre.launch.command` and `post.launch.command`)
* `checkRunning.command`
* `stop.command`
* The similar commands for `VanillaWindowsProcess` PowerShell.
* The file and template install config keys (e.g. `files.preinstall`, `templates.preinstall`, etc)
An example is shown below. Here, the "logstash-child" is a sub-type of `VanillaSoftwareProcess`,
and is co-located on the same VM as Tomcat. We don't want the Tomcat's configuration, such as
`install.command`, to be inherited by the logstash child. If it was inherited, the logstash-child
entity might re-execute the Tomcat's install command! Instead, the `install.command` config is
"consumed" by the Tomcat instance and is not re-inherited:
{% highlight yaml %}
services:
- type: org.apache.brooklyn.entity.webapp.tomcat.Tomcat8Server
brooklyn.config:
children.startable.mode: background_late
brooklyn.children:
- type: logstash-child
brooklyn.config:
logstash.elasticsearch.host: $brooklyn:entity("es").attributeWhenReady("urls.http.withBrackets")
...
{% endhighlight %}
"Not re-inherited" differs from "never inherited". The example below illustrates the difference,
though this use is discouraged (it is mostly for backwards compatibility). The `post.install.command`
is not consumed by the `BasicApplication`, so will be inherited by the `Tomcat8Server` which will
consume it. The config value will therefore not be inherited by the `logstash-child`.
{% highlight yaml %}
services:
- type: org.apache.brooklyn.entity.stock.BasicApplication
brooklyn.config:
post.install.command: echo "My post.install command"
brooklyn.children:
- type: org.apache.brooklyn.entity.webapp.tomcat.Tomcat8Server
brooklyn.config:
children.startable.mode: background_late
brooklyn.children:
- type: logstash-child
brooklyn.config:
logstash.elasticsearch.host: $brooklyn:entity("es").attributeWhenReady("urls.http.withBrackets")
...
{% endhighlight %}
#### Never Inherited
For some configuration values, the most logical behaviour is for the value to never be inherited
in the runtime management hierarchy.
Some common config keys that will never inherited include:
* `defaultDisplayName`: this is the name to use for the entity, if an explicit name is not supplied.
This is particularly useful when adding an entity in a catalog item (so if the user does not give
a name, it will get a sensible default). It would not be intuitive for all the children of that
entity to also get that default name.
* `id`: the id of an entity (as supplied in the YAML, to allow references to that entity) is not
inherited. It is the id of that specific entity, so must not be shared by all its children.
#### Inheritance Modes: Deep Dive
The javadoc in the code is useful for anyone who wants to go deep! See
`org.apache.brooklyn.config.BasicConfigInheritance` and `org.apache.brooklyn.config.ConfigInheritances`
in the repo https://github.com/apache/brooklyn-server.
When defining a new config key, the exact semantics for inheritance can be defined. There are
separate options to control config inheritance from the super-type, and config inheritance from the
parent in the runtime management hierarchy.
The possible modes are:
* `NEVER_INHERITED`: indicates that a key's value should never be inherited (even if defined on
an entity that does not know the key). Most usages will prefer `NOT_REINHERITED`.
* `NOT_REINHERITED`: indicates that a config key value (if used) should not be passed down to
children / sub-types. Unlike `NEVER_INHERITED`, these values can be passed down if they are not
used by the entity (i.e. if the entity does not expect it). However, when used by a child,
it will not be passed down any further. If the inheritor also defines a value the parent's
value is ignored irrespective (as in `OVERWRITE`; see `NOT_REINHERITED_ELSE_DEEP_MERGE` if merging
is desired).
* `NOT_REINHERITED_ELSE_DEEP_MERGE`: as `NOT_REINHERITED` but in cases where a value is inherited
because a parent did not recognize it, if the inheritor also defines a value the two values should
be merged.
* `OVERWRITE`: indicates that if a key has a value at both an ancestor and a descendant, the
descendant and his descendants will prefer the value at the descendant.
* `DEEP_MERGE`: indicates that if a key has a value at both an ancestor and a descendant, the
descendant and his descendants should attempt to merge the values. If the values are not mergable,
behaviour is undefined (and often the descendant's value will simply overwrite).
#### Explicit Inheritance Modes
_The YAML support for explicitly defining the inheritance mode is still work-in-progress. The options
documented below will be enhanced in a future version of Brooklyn, to better support the modes described
above._
In a YAML blueprint, within the `brooklyn.parameters` section for declaring new config keys, one can
set the mode for `inheritance.type` and `inheritance.runtime` (i.e. for inheritance from the super-type, and
inheritance in the runtime management hierarchy). The possible values are:
* `deep_merge`: the inherited and the given value should be merged; maps within the map will also be merged
* `always`: the inherited value should be used, unless explicitly overridden by the entity
* `none`: the value should not be inherited; if there is no explicit value on the entity then the default value will be used
Below is a (contrived!) example of inheriting the `example.map` config key. When using this entity
in a blueprint, the entity's config will be merged with that defined in the super-type, and the
parent entity's value will never be inherited:
{% highlight yaml %}
brooklyn.catalog:
items:
- id: entity-config-inheritance-example
version: "1.1.0-SNAPSHOT"
itemType: entity
name: Entity Config Inheritance Example
item:
type: org.apache.brooklyn.entity.machine.MachineEntity
brooklyn.parameters:
- name: example.map
type: java.util.Map
inheritance.type: deep_merge
inheritance.runtime: none
default:
MESSAGE_IN_DEFAULT: InDefault
brooklyn.config:
example.map:
MESSAGE: Hello
{% endhighlight %}
The blueprints below demonstrate the various permutations for setting configuration for the
config `example.map`. This can be inspected by looking at the entity's config. The config
we see for app1 is the inherited `{MESSAGE: "Hello"}`; in app2 we define additional configuration,
which will be merged to give `{MESSAGE: "Hello", MESSAGE_IN_CHILD: "InChild"}`; in app3, the
config from the parent is not inherited because there is an explicit inheritance.runtime of "none",
so it just has the value `{MESSAGE: "Hello"}`; in app4 again the parent's config is ignored,
with the super-type and entity's config being merged to give `{MESSAGE: "Hello", MESSAGE_IN_CHILD: "InChild"}`.
{% highlight yaml %}
location: aws-ec2:us-east-1
services:
- type: org.apache.brooklyn.entity.stock.BasicApplication
name: app1
brooklyn.children:
- type: entity-config-inheritance-example
- type: org.apache.brooklyn.entity.stock.BasicApplication
name: app2
brooklyn.children:
- type: entity-config-inheritance-example
brooklyn.config:
example.map:
MESSAGE_IN_CHILD: InChild
- type: org.apache.brooklyn.entity.stock.BasicApplication
name: app3
brooklyn.config:
example.map:
MESSAGE_IN_PARENT: InParent
brooklyn.children:
- type: entity-config-inheritance-example
- type: org.apache.brooklyn.entity.stock.BasicApplication
name: app4
brooklyn.config:
example.map:
MESSAGE_IN_PARENT: InParent
brooklyn.children:
- type: entity-config-inheritance-example
brooklyn.config:
example.map:
MESSAGE_IN_CHILD: InChild
{% endhighlight %}
A limitations of `inheritance.runtime` is when inheriting values from parent and grandparent
entities: a value specified on the parent will override (rather than be merged with) the
value on the grandparent.
#### Merging Policy and Enricher Configuration Values
A current limitation is that sub-type inheritance is not supported for configuration of
policies and enrichers. The current behaviour is that config is not inherited. The concept of
inheritance from the runtime management hierarchy does not apply for policies and enrichers
(they do not have "parents"; they are attached to an entity).