Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 50 additions & 2 deletions content/reference/components/cf-reactor.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ aliases:
Instead of running policy on a fixed schedule like `cf-agent`, it watches for specific events on the host and runs policy as soon as one happens.

`cf-reactor` keeps the promises made in `reactor` bundles and is affected by the `common` control body.
On event, it runs `agent` bundles.
On event, it runs the bundles of the [`then`][events#then] attribute of the [`events`][events] promise: `reactor` bundles without `events` promises, which behave like `agent` bundles, or `agent` and `common` bundles.
See [Reactor bundles][cf-reactor#Reactor bundles].

**Notes:**

Expand All @@ -31,12 +32,59 @@ On event, it runs `agent` bundles.

See also: [Reactor normal ordering][Policy evaluation#Reactor normal ordering]

## Reactor bundles

There are two kinds of `reactor` bundles, depending on whether they have [`events`][events] promises:

- `reactor` bundles **with** `events` promises set up the events to react to.
Besides `events` promises, they can only have [`meta`][meta], [`vars`][vars] and [`classes`][classes] promises.
`cf-reactor` evaluates them every time it reads the policy, see [Reactor normal ordering][Policy evaluation#Reactor normal ordering].
- `reactor` bundles **without** `events` promises are run on event, from the [`then`][events#then] attribute of `events` promises.
They can have all the promise types of `agent` bundles, including [custom promise types][custom], and `cf-reactor` runs them like `cf-agent` runs `agent` bundles.
They are not evaluated when `cf-reactor` reads the policy.

Having other promise types than `meta`, `vars` and `classes` alongside `events` promises is an error, and so is referring to a `reactor` bundle with `events` promises in a `then` attribute.

With `reactor` bundles without `events` promises, a policy for `cf-reactor` does not need `agent` bundles:

```cf3
body when deleted(file)
{
file_deleted => "$(file)";
}

bundle reactor watch
{
vars:
"file" string => "/tmp/a";

events:
"Keep $(file)"
when => deleted("$(file)"),
then => { create_file("$(file)"), report_restored("$(file)") };
}

bundle reactor create_file(file)
{
files:
"$(file)" create => "true";
}

bundle reactor report_restored(file)
{
reports:
"$(file) was restored";
}
```

**Note:** [`methods`][methods] promises can call `agent` and `common` bundles, but not `reactor` bundles.

## Under the hood

`cf-reactor` reads the policy and sets up event watchers based on the event promises declared in `reactor` bundles.
It then starts a thread that polls for each registered event.
When an event is detected, it is added to an event queue along with the corresponding event promise.
The daemon is then signaled to handle the event and execute the appropriate `agent` bundles, following the same execution model as `cf-agent`.
The daemon is then signaled to handle the event and run the bundles of the `then` attribute of the event promise, following the same execution model as `cf-agent`.

**Notes:**

Expand Down
10 changes: 5 additions & 5 deletions content/reference/language-concepts/policy-evaluation.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -191,18 +191,18 @@ Within a monitor bundle, the normal ordering is:

## Reactor normal ordering

As with the agent, common bundles are executed before any reactor bundles;
following this all reactor bundles are executed (the `bundlesequence` is only
used for cf-agent). Reactor bundles taking parameters are not executed.
Variables and classes are resolved in the same way as the agent.

Within a reactor bundle, the normal ordering is:

1. [meta][meta]
2. [vars][vars]
3. [classes][classes]
4. [events][events]

Reactor bundles without [events][events] promises follow the
[agent normal ordering][Policy evaluation#Agent normal ordering].

See [Reactor bundles][cf-reactor#Reactor bundles] for details.

<!---
### Knowledge normal ordering

Expand Down
31 changes: 17 additions & 14 deletions content/reference/promise-types/_index.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,21 @@ depends on the [bundle][bundles] type:

| Promise type | common | agent | server | monitor | reactor |
| --------------------------------------------------------------------- | :----: | :---: | :----: | :-----: | :------ |
| [defaults][defaults] - a default value for bundle parameters | x | x | x | x | |
| [defaults][defaults] - a default value for bundle parameters | x | x | x | x | x |
| [classes][classes] - a class, representing a state of the system | x | x | x | x | x |
| [meta][meta] - information about promise bundles | x | x | x | x | x |
| [reports][reports] - report a message | x | x | x | x | |
| [reports][reports] - report a message | x | x | x | x | x |
| [vars][vars] - a variable, representing a value | x | x | x | x | x |
| [commands][commands] - execute a command | | x | | | |
| [databases][databases] - configure a database | | x | | | |
| [files][files] - configure a file | | x | | | |
| [packages][packages] - install a package | | x | | | |
| [guest_environments][guest_environments] | | x | | | |
| [methods][methods] - take on a whole bundle of other promises | | x | | | |
| [processes][processes] - start or terminate processes | | x | | | |
| [services][services] - manage services or define new abstractions | | x | | | |
| [storage][storage] - verify attached storage | | x | | | |
| [users][users] - add or remove users | | x | | | |
| [commands][commands] - execute a command | | x | | | x |
| [databases][databases] - configure a database | | x | | | x |
| [files][files] - configure a file | | x | | | x |
| [packages][packages] - install a package | | x | | | x |
| [guest_environments][guest_environments] | | x | | | x |
| [methods][methods] - take on a whole bundle of other promises | | x | | | x |
| [processes][processes] - start or terminate processes | | x | | | x |
| [services][services] - manage services or define new abstractions | | x | | | x |
| [storage][storage] - verify attached storage | | x | | | x |
| [users][users] - add or remove users | | x | | | x |
| [access][access] - grant or deny access to file objects | | | x | | |
| [roles][roles] - allow certain users to activate certain classes | | | x | | |
| [measurements][measurements] - measure or sample data from the system | | | | x | |
Expand All @@ -35,8 +35,11 @@ depends on the [bundle][bundles] type:
See each promise type's reference documentation for detailed lists of available
attributes.

**Note:** `defaults` and `reports` promises are allowed in `reactor` bundles,
but `cf-reactor` ignores them.
**Note:** In a `reactor` bundle, `events` promises can only be combined with
`meta`, `vars` and `classes` promises. The other promise types are for
`reactor` bundles without `events` promises, which `cf-reactor` runs on event
like `cf-agent` runs `agent` bundles, see
[Reactor bundles][cf-reactor#Reactor bundles].

## Common promise attributes

Expand Down
5 changes: 4 additions & 1 deletion content/reference/promise-types/custom.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ If you are interested in shorter tutorials, there are a few different ones avail

A new top level `promise` block (similar to `body`) is used to add new promise types.
After adding a promise type, it is used in the same way as built-in promise types, there is no special syntax.
Custom promise types are only for `cf-agent`, so the `promise` block should always specify the `agent` component, and the promise types should only be used in `agent` bundles.
Custom promise types are only for `cf-agent` and `cf-reactor`, so the `promise` block should specify either the `agent` or the `reactor` component:

- `promise agent` makes the promise type available to both `cf-agent` and `cf-reactor`, so it can be used in `agent` bundles and in `reactor` bundles.
- `promise reactor` is only evaluated by `cf-reactor`, so the promise type can only be used in `reactor` bundles.

### Example of using a promise module

Expand Down
46 changes: 26 additions & 20 deletions content/reference/promise-types/events.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ keywords: [reactor, events]
---

`events` promises describe events for [`cf-reactor`][cf-reactor] to react to: the event to watch for, with the [`when`](#when) body, and the bundles to run when it happens, with the [`then`](#then) attribute.
`events` promises can only be made in `reactor` bundles.
`events` promises can only be made in `reactor` bundles, alongside [`meta`][meta], [`vars`][vars] and [`classes`][classes] promises only.
See [Reactor bundles][cf-reactor#Reactor bundles].

```cf3
bundle agent create_file(file)
bundle reactor create_file(file)
{
files:
"$(file)" create => "true";
Expand Down Expand Up @@ -39,19 +40,19 @@ bundle reactor main
**Description:** The bundle, or the list of bundles, to run in order when the event happens.

```cf3
bundle agent report_deletion(file)
bundle reactor report_deletion(file)
{
reports:
"$(file) was deleted, restoring it";
}

bundle agent create_file(file)
bundle reactor create_file(file)
{
files:
"$(file)" create => "true";
}

bundle agent report_restored(file)
bundle reactor report_restored(file)
{
reports:
"$(file) was restored";
Expand All @@ -70,14 +71,17 @@ bundle reactor main
}
```

All promise types within `agent` bundles behave like in `cf-agent` when executed in response to events.
The bundles can be `reactor` bundles without `events` promises, `agent` bundles or `common` bundles.
A bundle name is looked up among the `agent` bundles first, then the `common` bundles, then the `reactor` bundles.
All promise types within `reactor` bundles without `events` promises and `agent` bundles behave like in `cf-agent` when executed in response to events.

**Notes:**

- variables and classes created in a bundle run on reaction to an event are destroyed right after the execution.
The only exception are persistent classes.
- a `reactor` bundle with `events` promises cannot be run on event, it is an error to refer to one in `then`.

**Type:** `bundle agent` or `bundle common`, or a list of them
**Type:** `bundle reactor` without `events` promises, `bundle agent` or `bundle common`, or a list of them

### when

Expand All @@ -89,6 +93,10 @@ All promise types within `agent` bundles behave like in `cf-agent` when executed

All event types are mutually exclusive in a `when` body.

Event types:

- File events: [`file_deleted`](#file_deleted), [`file_created`](#file_created), [`file_modified`](#file_modified), [`file_content_modified`](#file_content_modified), [`file_permissions_changed`](#file_permissions_changed), [`file_owner_changed`](#file_owner_changed), [`file_size_exceeds`](#file_size_exceeds)

```cf3
body when deleted(file)
{
Expand Down Expand Up @@ -127,9 +135,7 @@ body when deleted_slow(file)

**Default value:** `1`

#### File event type

##### File deleted
#### file_deleted

**Description:** Creates an event when the file at the given path is deleted.

Expand All @@ -147,7 +153,7 @@ body when deleted(file)

**Allowed input range:** (arbitrary string)

##### File created
#### file_created

**Description:** Creates an event when a file is created at the given path.

Expand All @@ -166,7 +172,7 @@ body when created(file)

**Allowed input range:** (arbitrary string)

##### File modified
#### file_modified

**Description:** Creates an event when the modification time of the file at the given path changes.

Expand All @@ -187,14 +193,14 @@ body when modified(file)

**Allowed input range:** (arbitrary string)

**See also:** [`file_content_modified`](#file-content-modified)
**See also:** [`file_content_modified`](#file_content_modified)

##### File content modified
#### file_content_modified

**Description:** Creates an event when the content of the regular file at the given path changes.

The event fires when the path is a regular file at two consecutive checks and the SHA-256 hash of its content differs.
Unlike [`file_modified`](#file-modified), touching the file or replacing it with a file of the same content is not a modification.
Unlike [`file_modified`](#file_modified), touching the file or replacing it with a file of the same content is not a modification.
The file is read on every check, so it is more expensive than `file_modified` for large files.
Directories and symlinks have no content to hash, so they never fire this event.

Expand All @@ -209,7 +215,7 @@ body when content_modified(file)

**Allowed input range:** (arbitrary string)

##### File permissions changed
#### file_permissions_changed

**Description:** Creates an event when the permissions of the file at the given path change.

Expand All @@ -227,7 +233,7 @@ body when permissions_changed(file)

**Allowed input range:** (arbitrary string)

##### File owner changed
#### file_owner_changed

**Description:** Creates an event when the owning user or group of the file at the given path changes.

Expand All @@ -245,7 +251,7 @@ body when owner_changed(file)

**Allowed input range:** (arbitrary string)

##### File size exceeds
#### file_size_exceeds

**Description:** Creates an event when the size of the file at the given path grows above [`size_threshold`](#size_threshold) bytes.

Expand All @@ -265,9 +271,9 @@ body when size_exceeds(file)

**Allowed input range:** (arbitrary string)

##### size_threshold
#### size_threshold

**Description:** The size, in bytes, above which [`file_size_exceeds`](#file-size-exceeds) fires.
**Description:** The size, in bytes, above which [`file_size_exceeds`](#file_size_exceeds) fires.

Required with `file_size_exceeds`, and can't be used with other event types.

Expand Down
Loading