Improve entity-configuration (for inheritance) The inheritance behaviour changed a lot with Alexâs big PR; this updates the docs to better describe that. There are no doubt a lot more improvements we could also make!
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-docs/repo Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-docs/commit/a22af9d6 Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-docs/tree/a22af9d6 Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-docs/diff/a22af9d6 Branch: refs/heads/master Commit: a22af9d67b3af7604395155bf5f49ee2d7fcdb06 Parents: b7b2523 Author: Aled Sage <aled.s...@gmail.com> Authored: Fri Oct 14 19:16:30 2016 +0100 Committer: Aled Sage <aled.s...@gmail.com> Committed: Fri Oct 14 19:16:30 2016 +0100 ---------------------------------------------------------------------- guide/yaml/entity-configuration.md | 333 +++++++++++++++++++++++--------- 1 file changed, 241 insertions(+), 92 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/a22af9d6/guide/yaml/entity-configuration.md ---------------------------------------------------------------------- diff --git a/guide/yaml/entity-configuration.md b/guide/yaml/entity-configuration.md index b8f0240..b6bef47 100644 --- a/guide/yaml/entity-configuration.md +++ b/guide/yaml/entity-configuration.md @@ -77,31 +77,37 @@ services: {% endhighlight %} -### Inheriting Configuration from a Parent Entity +### Inheriting Configuration -Configuration passed to an entity is inherited by all child entities, unless explicitly overridden. -This can simplify some blueprints, but also care should be taken to ensure default values are not -accidentally overridden. +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. -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: +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 hiearchy). This gives great flexibilty, +but should be used with care so as not to surprise users of the blueprint. -{% highlight yaml %} -services: -- type: org.apache.brooklyn.entity.group.DynamicCluster - brooklyn.config: - wars.root: http://search.maven.org/remotecontent?filepath=org/apache/brooklyn/example/brooklyn-example-hello-world-webapp/0.9.0/brooklyn-example-hello-world-webapp-0.9.0.war - memberSpec: - $brooklyn:entitySpec: - type: org.apache.brooklyn.entity.webapp.tomcat.TomcatServer -{% endhighlight %} +The default behaviour is outlined below, along with examples and details of how to explilcitly +define the desired behaviour. -### Inheriting Configuration from Super-type +#### 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". We can override these values: +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 %} location: aws-ec2:us-east-1 @@ -110,24 +116,53 @@ services: brooklyn.config: custom.message: Goodbye launch.command: | - echo "Different example launch command: $MESSAGE" + echo "Sub-type launch command: $MESSAGE" {% endhighlight %} -If not overridden, then the existing values from the super-type will be used. -### Configuration Precedence +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. -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: +It will write out: `Sub-type launch command: Goodbye`. -1. Configuration on the entity itself -2. Inherited configuration from the super-type -3. Inherited configuration from the parent entity (or grandparent, etc) -4. The config key's default value +#### Inheriting Configuration from a Parent in the Runtime Management Hieararchy + +Configuration passed to an entity is inherited by all child entities, unless explicitly overridden. -### Merging Configuration Values +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: http://search.maven.org/remotecontent?filepath=org/apache/brooklyn/example/brooklyn-example-hello-world-webapp/0.9.0/brooklyn-example-hello-world-webapp-0.9.0.war + 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. + + +#### 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 @@ -149,8 +184,9 @@ the value on a parent entity): * `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 previous section). The environment variables will include the `MESSAGE` set in the super-type -and the `MESSAGE2` set here: +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 @@ -166,10 +202,171 @@ services: 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 2G 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 hiearchy. + +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 for `inheritance.type` and `inheritance.parent` (the former determines how -config inheritance from the super-type is handles; the latter determines how inheritance -from the parent entity is handled. The possible values 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 AMP, 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.parent` (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 @@ -182,10 +379,10 @@ parent entity's value will never be inherited: {% highlight yaml %} brooklyn.catalog: items: - - id: entity-config-example + - id: entity-config-inheritance-example version: "1.1.0-SNAPSHOT" itemType: entity - name: Entity Config Example + name: Entity Config Inheritance Example item: type: org.apache.brooklyn.entity.machine.MachineEntity brooklyn.parameters: @@ -214,12 +411,12 @@ services: - type: org.apache.brooklyn.entity.stock.BasicApplication name: app1 brooklyn.children: - - type: entity-config-example + - type: entity-config-inheritance-example - type: org.apache.brooklyn.entity.stock.BasicApplication name: app2 brooklyn.children: - - type: entity-config-example + - type: entity-config-inheritance-example brooklyn.config: example.map: MESSAGE_IN_CHILD: InChild @@ -230,7 +427,7 @@ services: example.map: MESSAGE_IN_PARENT: InParent brooklyn.children: - - type: entity-config-example + - type: entity-config-inheritance-example - type: org.apache.brooklyn.entity.stock.BasicApplication name: app4 @@ -238,7 +435,7 @@ services: example.map: MESSAGE_IN_PARENT: InParent brooklyn.children: - - type: entity-config-example + - type: entity-config-inheritance-example brooklyn.config: example.map: MESSAGE_IN_CHILD: InChild @@ -249,57 +446,9 @@ entities: a value specified on the parent will override (rather than be merged w value on the grandparent. -### 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 2G 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 %} - - - -### Merging Location, Policy and Enricher Configuration Values +#### Merging Policy and Enricher Configuration Values -A current limitation is that `inheritance.type` is not supported for configuration of locations, -policies and enrichers. The current behaviour is that config is not inherited. +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).