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).

Reply via email to