add more examples to `netcat` illustration,
showing port inference, parameters, catalog, and more.
diff --git a/brooklyn-docs/guide/yaml/custom-entities.md b/brooklyn-docs/guide/yaml/custom-entities.md
index 6f21c14..9698aa8 100644
--- a/brooklyn-docs/guide/yaml/custom-entities.md
+++ b/brooklyn-docs/guide/yaml/custom-entities.md
@@ -24,15 +24,26 @@
{% endhighlight %}
This starts a simple `nc` listener on port 4321 which will respond `hello` to the first
-session which connects to it. Test it by running `telnet localhost 4321`.
+session which connects to it. Test it by running `telnet localhost 4321`
+or opening `http://localhost:4321` in a browser.
+
+Note that it only allows you connect once, and after that it fails.
+This is deliberate! We'll repair this later in this example.
+Until then however, in the *Applications* view you can click the server,
+go to the `Effectors` tab, and click `restart` to bring if back to life.
This is just a simple script, but it shows how any script can be easily embedded here,
including a script to download and run other artifacts.
Many artifacts are already packaged such that they can be downloaded and launched
with a simple script, and `VanillaSoftwareProcess` can also be used for them.
-We can specify a `download.url` which downloads artifacts (unpacking TAR, TGZ, and ZIP archives)
+
+
+#### Downloading Files
+
+We can specify a `download.url` which downloads an artifact
+(and automatically unpacking TAR, TGZ, and ZIP archives)
before running `launch.command` relative to where that file is installed (or unpacked),
-with `./start.sh` being the default `launch.command`.
+with the default `launch.command` being `./start.sh`.
So if we create a file `/tmp/netcat-server.tgz` containing just `start.sh` in the root
which consists of the two lines in the previous example,
@@ -42,17 +53,130 @@
{% readj example_yaml/vanilla-bash-netcat-file.yaml %}
{% endhighlight %}
-The one requirement of the script is that it store the process ID (PID) in the file
+
+#### Port Inferencing
+
+If you're deploying to a cloud machine, a firewall might block the port 4321.
+We can tell Brooklyn to open this port explicitly by specifying `inboundPorts: [ 4321 ]`;
+however a more idiomatic way is to specify a config ending with `.port`,
+such as:
+
+{% highlight yaml %}
+{% readj example_yaml/vanilla-bash-netcat-port.yaml %}
+{% endhighlight %}
+
+The regex for ports to be opened can be configured using
+the config `inboundPorts.configRegex` (which has `.*\.port` as the default value).
+
+Config keys of type `org.apache.brooklyn.api.location.PortRange` (aka `port`)
+have special behaviour: when configuring, you can use range notation `8000-8100` or `8000+` to tell Brooklyn
+to find **one** port matching; this is useful when ports might be in use.
+In addition, any such config key will be opened,
+irrespective of whether it matches the `inboundPorts.configRegex`.
+To prevent any inferencing of ports to open, you can set the config `inboundPorts.autoInfer` to `false`.
+
+Note that in the example above, `netcat.port` must be specified in a `brooklyn.config` block.
+This block can be used to hold any config (including for example the `launch.command`),
+but for convenience Brooklyn allows config keys declared on the underlying type
+to be specified up one level, alongside the type.
+However config keys which are *not* declared on the type *must* be declared in the `brooklyn.config` block.
+
+
+#### Declaring New Config Keys
+
+We can define config keys to be presented to the user
+using the `brooklyn.parameters` block:
+
+{% highlight yaml %}
+{% readj example_yaml/vanilla-bash-netcat-port-parameter.yaml %}
+{% endhighlight %}
+
+The example above will allow a user to specify a message to send back
+and the port where netcat will listen.
+The metadata on these parameters is available at runtime in the UI
+and through the API, and is used when populating a catalog.
+
+The example also shows how these values can be passed as environment variables to the launch command.
+The `$brooklyn:config(...)` function returns the config value supplied or default.
+For the type `port`, an attribute sensor is also created to report the *actual* port used after port inference,
+and so the `$brooklyn:attributeWhenReady(...)` function is used.
+(If `$brooklyn:config("netcat.port")` had been used, `4321+` would be passed as `NETCAT_PORT`.)
+
+This gives us quite a bit more power in writing our blueprint:
+
+* Multiple instances of the server can be launched simultaneously on the same host,
+ as the `4321+` syntax enables Brooklyn to assign them different ports
+* If this type is added to the catalog, a user can configure the message and the port;
+ we'll show this in the next section
+
+
+#### Using the Catalog and Clustering
+
+The *Catalog* tab allows you to add blueprints which you can refer to in other blueprints.
+In that tab, click *+* then *YAML*, and enter the following:
+
+{% highlight yaml %}
+{% readj example_yaml/vanilla-bash-netcat-catalog.bom %}
+{% endhighlight %}
+
+This is the same example as in the previous section, wrapped according to the catalog YAML requirements,
+with one new block added defining an enricher. An enricher creates a new sensor from other values;
+in this case it will create a `main.uri` sensor by populating a `printf`-style string `"http://%s:%s"`
+with the sensor values.
+
+With this added to the catalog, we can reference the type `netcat-example` when we deploy an application.
+Return to the *Home* or *Applications* tab, click *+*, and submit this YAML blueprint:
+
+{% highlight yaml %}
+{% readj example_yaml/vanilla-bash-netcat-reference.yaml %}
+{% endhighlight %}
+
+This extends the previous blueprint which we registered in the catalog,
+meaning that we don't need to include it each time.
+Here, we've elected to supply our own message, but we'll use the default port.
+More importantly, we can package it for others to consume -- or take items others have built.
+
+We can go further and use this to deploy a cluster,
+this time giving a custom port as well as a custom message:
+
+{% highlight yaml %}
+{% readj example_yaml/vanilla-bash-netcat-cluster.yaml %}
+{% endhighlight %}
+
+In either of the above examples, if you explore the tree in the *Applications* view
+and look at the *Summary* tab of any of the server instances, you'll now see the URL where netcat is running.
+But remember, netcat will stop after one run, so you'll only be able to use each link once
+before you have to restart it. You can also run `restart` on the cluster,
+and if you haven't yet experimented with `resize` on the cluster you might want to do that.
+
+
+#### Determining Successful Launch
+
+One requirement of the launch script is that it store the process ID (PID) in the file
pointed to by `$PID_FILE`, hence the second line of the script.
-This is because Brooklyn wants to monitor the services under management.
-(There are other options; you can set `checkRunning.command` and `stop.command` instead,
-as documented on the Javadoc of the `VanillaSoftwareProcess` class,
-and those scripts will be used instead of checking and stopping the process whose PID is in `$PID_FILE`.)
+This is because Brooklyn wants to monitor the services under management.
+You'll observe this if you connect to one of the netcat services,
+as the process exits afterwards and Brooklyn sets the entity to an `ON_FIRE` state.
+(You can also test this with a `killall nc` before connecting
+or issueing a `stop` command on the server -- but not on the example,
+as stopping an application root causes it to be removed altogether!)
+
+There are other options for determining launch: you can set `checkRunning.command` and `stop.command` instead,
+as documented on the javadoc and config keys of the {% include java_link.html class_name="VanillaSoftwareProcess" package_path="org/apache/brooklyn/entity/software/base" project_subpath="software/base" %} class,
+and those scripts will be used instead of checking and stopping the process whose PID is in `$PID_FILE`.
+
+{% highlight yaml %}
+{% readj example_yaml/vanilla-bash-netcat-more-commands.yaml %}
+{% endhighlight %}
And indeed, once you've run one `telnet` to the server, you'll see that the
-service has gone "on fire" in Brooklyn -- because the `nc` process has stopped.
+service has gone "on fire" in Brooklyn -- because the `nc` process stops after one run.
+
+
+#### Attaching Policies
+
Besides detecting this failure, Brooklyn policies can be added to the YAML to take appropriate
-action. A simple recovery here might just be to restart the process:
+action. A simple recovery here might just to automatically restart the process:
{% highlight yaml %}
{% readj example_yaml/vanilla-bash-netcat-restarter.yaml %}
@@ -67,6 +191,9 @@
Running with this blueprint, you'll see that the service shows as on fire for 15s after a `telnet`,
before the policy restarts it.
+
+### Sensors and Effectors
+
For an even more interesting way to test it, look at the blueprint defining
[a netcat server and client](example_yaml/vanilla-bash-netcat-w-client.yaml).
This uses `initializers` to define an effector to `sayHiNetcat` on the `Simple Pinger` client,
@@ -100,8 +227,11 @@
period: 1s
command: tail -1 server-input
-This is still a simple example, but worth going through carefully.
-It shows many of the building blocks used in real-world blueprints,
+
+#### Summary
+
+These examples are relatively simple example, but they
+illustrate many of the building blocks used in real-world blueprints,
and how they can often be easily described and combined in Brooklyn YAML blueprints.
Next, if you need to drive off-piste, or you want to write tests against these blueprints,
have a look at, for example, `VanillaBashNetcatYamlTest.java` in the Brooklyn codebase,
diff --git a/brooklyn-docs/guide/yaml/example_yaml/vanilla-bash-netcat-catalog.bom b/brooklyn-docs/guide/yaml/example_yaml/vanilla-bash-netcat-catalog.bom
new file mode 100644
index 0000000..7551818
--- /dev/null
+++ b/brooklyn-docs/guide/yaml/example_yaml/vanilla-bash-netcat-catalog.bom
@@ -0,0 +1,35 @@
+brooklyn.catalog:
+ id: netcat-example
+ version: "1.0"
+ item:
+ type: org.apache.brooklyn.entity.software.base.VanillaSoftwareProcess
+ name: Simple Netcat Server
+
+ launch.command: |
+ echo $MESSAGE | nc -l $NETCAT_PORT &
+ echo $! > $PID_FILE
+
+ env:
+ MESSAGE: $brooklyn:config("message")
+ NETCAT_PORT: $brooklyn:attributeWhenReady("netcat.port")
+
+ brooklyn.parameters:
+ - name: message
+ description: a message to send to the caller
+ default: hello
+ - name: netcat.port
+ type: port
+ description: the port netcat should run on
+ default: 4321+
+
+ brooklyn.enrichers:
+ - type: org.apache.brooklyn.enricher.stock.Transformer
+ brooklyn.config:
+ uniqueTag: main-uri-generator
+ enricher.sourceSensor: $brooklyn:sensor("host.address")
+ enricher.targetSensor: $brooklyn:sensor("main.uri")
+ enricher.targetValue:
+ $brooklyn:formatString:
+ - "http://%s:%s/"
+ - $brooklyn:attributeWhenReady("host.address")
+ - $brooklyn:attributeWhenReady("netcat.port")
diff --git a/brooklyn-docs/guide/yaml/example_yaml/vanilla-bash-netcat-cluster.yaml b/brooklyn-docs/guide/yaml/example_yaml/vanilla-bash-netcat-cluster.yaml
new file mode 100644
index 0000000..70b69af
--- /dev/null
+++ b/brooklyn-docs/guide/yaml/example_yaml/vanilla-bash-netcat-cluster.yaml
@@ -0,0 +1,11 @@
+name: Netcat Cluster Example
+location: localhost
+services:
+- type: org.apache.brooklyn.entity.group.DynamicCluster
+ memberSpec:
+ $brooklyn:entitySpec:
+ type: netcat-example
+ message: hello from cluster member
+ netcat.port: 8000+
+ initialSize: 3
+ restartMode: parallel
diff --git a/brooklyn-docs/guide/yaml/example_yaml/vanilla-bash-netcat-more-commands.yaml b/brooklyn-docs/guide/yaml/example_yaml/vanilla-bash-netcat-more-commands.yaml
new file mode 100644
index 0000000..f4e894f
--- /dev/null
+++ b/brooklyn-docs/guide/yaml/example_yaml/vanilla-bash-netcat-more-commands.yaml
@@ -0,0 +1,16 @@
+name: Netcat Example with Explicit Check and Stop Commands
+location: localhost
+services:
+- type: org.apache.brooklyn.entity.software.base.VanillaSoftwareProcess
+ name: Simple Netcat Server
+ launch.command: |
+ echo hello | nc -l 4321 &
+ echo $! > $PID_FILE
+
+ # The following overrides demonstrate the use of a custom shell environment as well as
+ # check-running and stop commands. These are optional; default behavior will "do the
+ # right thing" with the pid file automatically.
+
+ env: { CHECK_MARKER: "checkRunning", STOP_MARKER: "stop" }
+ checkRunning.command: echo $CHECK_MARKER >> DATE && test -f "$PID_FILE" && ps -p `cat $PID_FILE` >/dev/null
+ stop.command: echo $STOP_MARKER >> DATE && test -f "$PID_FILE" && { kill -9 `cat $PID_FILE`; rm /tmp/vanilla.pid; }
diff --git a/brooklyn-docs/guide/yaml/example_yaml/vanilla-bash-netcat-port-parameter.yaml b/brooklyn-docs/guide/yaml/example_yaml/vanilla-bash-netcat-port-parameter.yaml
new file mode 100644
index 0000000..90f83b4
--- /dev/null
+++ b/brooklyn-docs/guide/yaml/example_yaml/vanilla-bash-netcat-port-parameter.yaml
@@ -0,0 +1,21 @@
+name: Netcat Example with Parameter
+location: localhost
+services:
+- type: org.apache.brooklyn.entity.software.base.VanillaSoftwareProcess
+ name: Simple Netcat Server
+ launch.command: |
+ echo $MESSAGE | nc -l $NETCAT_PORT &
+ echo $! > $PID_FILE
+
+ env:
+ MESSAGE: $brooklyn:config("message")
+ NETCAT_PORT: $brooklyn:attributeWhenReady("netcat.port")
+
+ brooklyn.parameters:
+ - name: message
+ description: a message to send to the caller
+ default: hello
+ - name: netcat.port
+ type: port
+ description: the port netcat should run on
+ default: 4321+
diff --git a/brooklyn-docs/guide/yaml/example_yaml/vanilla-bash-netcat-port.yaml b/brooklyn-docs/guide/yaml/example_yaml/vanilla-bash-netcat-port.yaml
new file mode 100644
index 0000000..3ec0212
--- /dev/null
+++ b/brooklyn-docs/guide/yaml/example_yaml/vanilla-bash-netcat-port.yaml
@@ -0,0 +1,13 @@
+name: Netcat Example with Port Opened
+location: localhost
+services:
+- type: org.apache.brooklyn.entity.software.base.VanillaSoftwareProcess
+ name: Simple Netcat Server
+ launch.command: |
+ echo hello | nc -l 4321 &
+ echo $! > $PID_FILE
+
+ brooklyn.config:
+ # matching the regex `.*\.port` will cause the port to be opened
+ # if in a cloud where configurable security groups are available
+ netcat.port: 4321
diff --git a/brooklyn-docs/guide/yaml/example_yaml/vanilla-bash-netcat-reference.yaml b/brooklyn-docs/guide/yaml/example_yaml/vanilla-bash-netcat-reference.yaml
new file mode 100644
index 0000000..0f10c55
--- /dev/null
+++ b/brooklyn-docs/guide/yaml/example_yaml/vanilla-bash-netcat-reference.yaml
@@ -0,0 +1,5 @@
+name: Netcat Type Reference Example
+location: localhost
+services:
+- type: netcat-example
+ message: hello from netcat using a registered type
diff --git a/brooklyn-docs/guide/yaml/example_yaml/vanilla-bash-netcat-restarter.yaml b/brooklyn-docs/guide/yaml/example_yaml/vanilla-bash-netcat-restarter.yaml
index adaa933..47e54ab 100644
--- a/brooklyn-docs/guide/yaml/example_yaml/vanilla-bash-netcat-restarter.yaml
+++ b/brooklyn-docs/guide/yaml/example_yaml/vanilla-bash-netcat-restarter.yaml
@@ -1,4 +1,4 @@
-name: Simple Netcat Example with Restarter Policy
+name: Netcat Example with Restarter Policy
location: localhost
services:
- type: org.apache.brooklyn.entity.software.base.VanillaSoftwareProcess
diff --git a/brooklyn-docs/guide/yaml/example_yaml/vanilla-bash-netcat-w-client.yaml b/brooklyn-docs/guide/yaml/example_yaml/vanilla-bash-netcat-w-client.yaml
index 8290b79..78ed99e 100644
--- a/brooklyn-docs/guide/yaml/example_yaml/vanilla-bash-netcat-w-client.yaml
+++ b/brooklyn-docs/guide/yaml/example_yaml/vanilla-bash-netcat-w-client.yaml
@@ -1,4 +1,4 @@
-name: Simple Netcat with Client
+name: Netcat Example with Client
location: localhost
diff --git a/brooklyn-docs/guide/yaml/example_yaml/vanilla-bash-netcat.yaml b/brooklyn-docs/guide/yaml/example_yaml/vanilla-bash-netcat.yaml
index 3023038..df616af 100644
--- a/brooklyn-docs/guide/yaml/example_yaml/vanilla-bash-netcat.yaml
+++ b/brooklyn-docs/guide/yaml/example_yaml/vanilla-bash-netcat.yaml
@@ -6,13 +6,3 @@
launch.command: |
echo hello | nc -l 4321 &
echo $! > $PID_FILE
-
- # The following overrides demonstrate the use of a custom shell environment as well as
- # check-running and stop commands. These are optional; default behavior will "do the
- # right thing" with the pid file automatically.
-
- env: { CHECK_MARKER: "checkRunning", STOP_MARKER: "stop" }
- checkRunning.command: echo $CHECK_MARKER >> DATE && test -f "$PID_FILE" && ps -p `cat $PID_FILE` >/dev/null
- stop.command: echo $STOP_MARKER >> DATE && test -f "$PID_FILE" && { kill -9 `cat $PID_FILE`; rm /tmp/vanilla.pid; }
-
-# can also define download.url, in which case the launch command defaults to ./start.sh in that (archive) file
diff --git a/brooklyn-docs/guide/yaml/yaml-reference.md b/brooklyn-docs/guide/yaml/yaml-reference.md
index 36656bb..7a628a0 100644
--- a/brooklyn-docs/guide/yaml/yaml-reference.md
+++ b/brooklyn-docs/guide/yaml/yaml-reference.md
@@ -67,22 +67,32 @@
* `description`: short text describing the parameter behaviour/usage, presented
to the user
* `type`: the type of the parameter, one of `string`, `integer`, `long`, `float`,
- `double`, `timestamp`, `port`, a fully qualified Java type name. Default is `string`.
- * `default`: a default value, converted to the type above
- * `constraints`: a list of constraints the parameter should meet, currently
- `required` is supported
+ `double`, `timestamp`, `duration`, `port`, or a fully qualified Java type name;
+ the default is `string`;
+ obvious coercion is supported so
+ `timestamp` accepts most common ISO date formats, `duration` accepts `5m`, and port accepts `8080+`
+ * `default`: a default value; this will be coerced to the declared `type`
+ * `constraints`: a list of constraints the parameter should meet;
+ currently `required` is supported, with the default being not required
- A shorthand notation is also supported where the name of the parameter is directly
- passed as an item in the list. For example:
+ A shorthand notation is also supported where just the name of the parameter is 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:
~~~ yaml
brooklyn.parameters:
-- displayName
-- name: user.name
- constraints:
- - required
+# user.age parameter is required, and fully specified
- name: user.age
type: integer
+ label: Age
+ description: the age of the user
+ constraints:
+ - required
+# user.name is optional, and has a default
+- name: user.name
+ default: You
+# shorthand notation: displayName will be an optional config of type string with no default
+- displayName
~~~
Entities, policies, and initializers may accept additional key-value pairs,