Skip to content
Closed
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
11 changes: 11 additions & 0 deletions content/overview/_index.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ All machines, whether they are policy servers or hosts, will have these three im
- [/var/cfengine/bin/cf-serverd][Overview#cf-serverd]
- [/var/cfengine/bin/cf-monitord][Overview#cf-monitord]

On hosts using systemd, [`cf-reactor`][Overview#cf-reactor] runs as well, to
react to events described in policy.

#### cf-execd

`cf-execd` is the scheduling daemon for `cf-agent`, similar to cron. It executes and collects the output of `cf-agent` and
Expand Down Expand Up @@ -95,6 +98,14 @@ See also: [cf-serverd][cf-serverd] reference documentation.

See also: [cf-monitord][cf-monitord] reference documentation.

#### cf-reactor

`cf-reactor` is the event reaction daemon for CFEngine. It watches for events described in policy using `events` type promises, such as the deletion of a file, and runs bundles of promises as soon as they happen, without waiting for the next `cf-agent` run.

`cf-reactor` keeps the promises made in `common` and `reactor` bundles, and is affected by the `common` control body.

See also: [cf-reactor][cf-reactor] reference documentation.

### Other component applications

- [/var/cfengine/bin/cf-agent][Overview#cf-agent]
Expand Down
2 changes: 2 additions & 0 deletions content/overview/directory-structure.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ The CFEngine application is fully contained within the /var/cfengine directory t

- `cf-execd`: Starts the cf-agent process at a specified time interval.
- `cf-monitord`: Collects system statistics
- `cf-reactor`: Reacts to events described in policy
- `cf-serverd`: Provides network services; used to distribute policy and data files
- `runalerts.sh`: Updates Mission Portal status and activates alert actions (Enterprise only)
- `cf-hub`: Responsible for collecting reports from remote agents. (CFEngine Enterprise only)
Expand Down Expand Up @@ -181,6 +182,7 @@ _pid files_ in the work directory.
- `cf-execd.pid`
- `cf-hub.pid`
- `cf-monitord.pid`
- `cf-reactor.pid`
- `cf-serverd.pid`

## Sockets in /var/cfengine
Expand Down
200 changes: 189 additions & 11 deletions content/reference/components/cf-reactor.markdown
Original file line number Diff line number Diff line change
@@ -1,29 +1,207 @@
---
layout: default
title: cf-reactor
keywords: [reactor]
keywords: [reactor, events]
aliases:
- "/reference-components-cf-reactor.html"
---

`cf-reactor` is the CFEngine event reaction daemon.
We are currently working on making `cf-reactor` respond to events specified in policy language, using `when` bodies and `reactor` bundles.
This feature is coming in 3.29.0 and will be further documented here in the future.
`cf-reactor` is the CFEngine event reaction daemon. It watches for the events
described by [`events`][events] promises in `reactor` bundles, and as soon as
an event happens, it runs the bundles promised for it, without waiting for the
next scheduled `cf-agent` run.

**Notes:**
`cf-reactor` keeps the promises made in `common` and `reactor` bundles, and is
affected by the `common` control body.

```cf3
bundle agent main
{
methods:
"motd" usebundle => motd;
}

bundle agent motd
{
files:
"/etc/motd" content => "This host is managed by CFEngine$(const.n)";
}

bundle reactor motd_watch
{
events:
"motd_deleted"
when => deleted("/etc/motd"),
then => motd;
}

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

- In CFEngine Enterprise `cf-reactor` has some extra responsibilities, where it listens to `NOTIFY` events in the PostgreSQL database and performs actions when those events occur.
One example of such events is refreshing the `host_specific.json` files whenever there is an event in the `cmdb_refresh` channel.
In this example, `cf-agent` creates `/etc/motd` on its regular runs, and
whenever the file is deleted, `cf-reactor` runs the `motd` bundle right away to
restore it:

- In the future, the daemon should also take care of inventory refresh for hosts
(now part of `cf-hub`) and many DB maintenance tasks that are now promises in
the Masterfiles Policy Framework policy under `/cfe_internal/enterprise`.
```output
info: Registering a file_deleted watcher for events promise 'motd_deleted', on file '/etc/motd'
notice: Reactor watcher 'motd_deleted' fired
info: Created file '/etc/motd', mode 0600
```

**Notes:**

- `cf-reactor` always considers the class `reactor` to be defined.
- This daemon reloads its policy when the SIGHUP signal is received.
- `SIGUSR1` sets the log level to debug.
- `SIGUSR2` sets the log level to notice.
- On CFEngine Enterprise hubs, `cf-reactor` has extra responsibilities, see
[Enterprise hub tasks][cf-reactor#Enterprise hub tasks].

**History:**

- In 3.18.2 / 3.20.0 `cf-reactor` was introduced as an Enterprise-only hub component.
- In 3.29.0 `cf-reactor` was moved to CFEngine community to be used as the daemon for event driven CFEngine policy.
- In 3.29.0 `cf-reactor` was moved to CFEngine community, and `reactor` bundles
and [`events`][events] promises were introduced for event driven CFEngine
policy.

## Command reference

{{< CFEngine_include_snippet(cf-reactor.help, [\s]*--[a-z], ^$) >}}

## Reactor bundles

Bundles of type `reactor` describe the events `cf-reactor` watches for, with
[`events`][events] promises. `cf-reactor` evaluates all the `reactor` bundles of
the policy, so there is no need to list them in a `bundlesequence`. Reactor
bundles taking parameters are not evaluated: `cf-reactor` logs a warning about
them instead.

In a reactor bundle, `cf-reactor` keeps the `meta`, `vars`, `classes` and
`events` promises, in that order. `defaults` and `reports` promises are allowed,
but ignored. Other components, like `cf-agent`, ignore reactor bundles.

Like the other components, `cf-reactor` also evaluates the `vars` and `classes`
promises of `common` bundles, so their variables and classes can be used in
reactor bundles.

Classes defined in reactor bundles are bundle scoped by default, as in agent
bundles. To use a class of a reactor bundle in the bundles run on events, or to
guard `events` promises, define it with [`scope`][classes#scope] `namespace`:

```cf3
bundle reactor watch_nginx_config
{
classes:
"nginx_installed"
expression => fileexists("/usr/sbin/nginx"),
scope => "namespace";

events:
nginx_installed::
"nginx_config_deleted"
when => deleted("/etc/nginx/nginx.conf"),
then => nginx_config_deleted;
}

bundle agent nginx_config_deleted
{
reports:
"/etc/nginx/nginx.conf was deleted";
}

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

**Note:** Currently, the classes guarding `events` promises, with class
expressions or with [`if`][Promise types#if] and
[`unless`][Promise types#unless], must be namespace scoped (or hard classes).
When an `events` promise is guarded by a bundle scoped class, its event is
detected, but the [`then`][events#then] bundles are not run.

## Running bundles on events

`cf-reactor` checks for the events of the `events` promises every second. When
an event happens, it runs the bundles of the [`then`][events#then] attribute of
the `events` promise, in order, like a `bundlesequence`. Events are handled one
at a time: the events happening while bundles run are handled next.

Each event gets a fresh run of the bundles:

- Promises act every time: the default [`ifelapsed`][Promise types#ifelapsed] of
the bundles run on events is `0`, so the promise locks of previous runs don't
apply. Promises setting `ifelapsed` in their `action` body are still locked
for that long.
- Functions are evaluated again: their results are not cached between events.
- Classes and variables defined by the run are undone once the event is handled,
except persistent classes (see [`persistence`][classes#persistence]), which
stay defined until they expire, as in `cf-agent`.
- Time classes are updated for each event. The other hard classes, and the
variables like [`sys.date`][sys#sys.date], are discovered when `cf-reactor`
loads its policy, and are not updated for each event. Use functions like
[`now()`][now] to get the time of the event.

The bundles run by `cf-reactor` are not part of a `cf-agent` run:

- Only the bundles of the `then` attribute are run, not the `bundlesequence`.
- The class `reactor` is defined, the class `agent` is not.
- `body agent control` does not apply.
- The output of the bundles, like their reports, is in the output of
`cf-reactor`. When it runs as a systemd service, see `journalctl -u cf-reactor`.

## Policy updates

Like the other daemons, `cf-reactor` reloads its policy when new policy is
validated, which it checks for every 5 minutes. It also reloads its policy when
it receives the SIGHUP signal.

The new policy is validated with `cf-promises` first: if it has errors,
`cf-reactor` logs them and keeps its previous policy, still watching for the
same events. If the policy has errors when `cf-reactor` starts, it falls back to
the failsafe policy, like the other components. The failsafe policy has no
`events` promises, so `cf-reactor` doesn't watch for any event until the policy
is fixed.

When the policy is reloaded, `cf-reactor` stops watching for the events of the
`events` promises that were removed, and starts watching for those of the new
ones. The `events` promises that didn't change keep watching for their events,
without missing those happening while the policy is reloaded.

## Running cf-reactor

Since 3.29.0, `cf-reactor` is installed by all CFEngine packages, Community and
Enterprise, on hubs and clients.

On hosts using systemd, `cf-reactor` runs as the `cf-reactor` service, which is
part of the `cfengine3` service. The Masterfiles Policy Framework ensures
`cf-reactor` is running on Enterprise hubs.

To try out policy with `cf-reactor`, stop the `cf-reactor` service, as only one
instance of `cf-reactor` can run at a time, and run `cf-reactor` in the
foreground with the policy file to test:

```command
systemctl stop cf-reactor
cf-reactor --no-fork --inform --file ./reactor_test.cf
```

**Note:** On Enterprise hubs, the [Enterprise hub tasks][cf-reactor#Enterprise hub tasks]
are not performed while the `cf-reactor` service is stopped.

## Enterprise hub tasks

On CFEngine Enterprise hubs, `cf-reactor` also listens to `NOTIFY` events in the
PostgreSQL database and performs actions when those events occur, and runs
periodic hub tasks:

- Refreshing the `host_specific.json` files whenever there is an event in the
`cmdb_refresh` channel.
- Refreshing the inventory of hosts.
- Handling the requests of the Build application (cfbs requests and responses).
- Running alerts, scheduled reports, the cleanup of hosts, and the update of
health failures.
2 changes: 2 additions & 0 deletions content/reference/language-concepts/bundles.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ Currently, these are the possible _bundle types_:
- `agent`: Bundle of promises specific to the `cf-agent` binary.
- `server`: Bundle of promises specific to the `cf-serverd` binary.
- `monitor`: Bundle of promises specific to the `cf-monitord` binary.
- `reactor`: Bundle of promises specific to the `cf-reactor` binary, see
[Reactor bundles][cf-reactor#Reactor bundles].
- `common`: Bundle of promises shared among the different binaries / components.
- `edit_line`: Bunde of promises used in a `files` promise with the `edit_line` attribute.

Expand Down
1 change: 1 addition & 0 deletions content/reference/language-concepts/classes.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ reserved hard class 'cfengine' in post-condition classes`.
- `cf-runagent` :: `runagent`
- `cf-key` :: `keygenerator`
- `cf-hub` :: `hub`
- `cf-reactor` :: `reactor`
- `cf-promises` :: `common`
- Operating System Classes (note that the presence of these classes doesn't imply platform support)
- Operating System Architecture - `arista`, `big_ip`, `debian`, `eos`, `fedora`, `Mandrake`, `Mandriva`, `oracle`, `redhat`, `slackware`, `smartmachine`, `smartos`, `solarisx86`, `sun4`, `SuSE`, `ubuntu`, `ultrix`, the always-favorite `unknown_ostype`, etc.
Expand Down
44 changes: 24 additions & 20 deletions content/reference/promise-types/_index.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,34 @@ Within a bundle, the promise types are executed in a round-robin fashion in the
following [normal order][Policy evaluation]. Which promise types are available
depends on the [bundle][bundles] type:

| Promise type | common | agent | server | monitor |
| --------------------------------------------------------------------- | :----: | :---: | :----: | :------ |
| [defaults][defaults] - a default value for bundle parameters | x | x | x | x |
| [classes][classes] - a class, representing a state of the system | x | x | x | x |
| [meta][meta] - information about promise bundles | x | x | x | x |
| [reports][reports] - report a message | x | x | x | x |
| [vars][vars] - a variable, representing a value | 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 | | |
| [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 |
| Promise type | common | agent | server | monitor | reactor |
| --------------------------------------------------------------------- | :----: | :---: | :----: | :-----: | :------ |
| [defaults][defaults] - a default value for bundle parameters | 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 | |
| [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 | | | |
| [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 | |
| [events][events] - react to an event | | | | | x |

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, see [Reactor bundles][cf-reactor#Reactor bundles].

## Common promise attributes

The following attributes are available to all promise types.
Expand Down
Loading
Loading