# Realbook Basics

A Realbook is a fundamentally a shorthand way of specifying
an Elixir `Module`.  Anything you could write inside a `Kernel.defmodule/2` clause you can write inside of a realbook, and in fact your realbook
script will wrapped inside of a `defmodule` statement.

A realbook (or set of realbooks) executes linearly in a single BEAM
process.

## Bridging the imperative with declarative

The realbook script itself should be considered a unit of declarative
provisioning.  In order to bridge imperative code and declarative Realbook
provides three pre-imported macros:

- `Realbook.Macros.requires/1` (optional) lets you declare a list of
  other realbook scripts which must be run prior to the current one
  to guarantee successful execution.

- `Realbook.Macros.verify/1` (required) specifies instructions which
  are run prior to execution; if `verify` passes, the `Realbook.Macros.play/1`
  contents will not be executed.  After executing the `play` contents,
  `verify` will be rerun to assess the overall success of the provision.

- `Realbook.Macros.play/1` (required) specifies instructions to actually
  be run.

## Checking variable existence prior to running.

Realbook scripts provide way of sharing configuration variables between
scripts.  It may also be the case that a script could optionally define
a variable to be used by a downstream script.  Two pre-imported macros help
you share configuration variables:

- `Realbook.Commands.get/1` lets you retrieve a configuration variable
  using an atom key.

- `Realbook.Commands.set/1` lets you set a configuration variable from
  within a script.

Realbook modules perform code analysis at compile time, and remember which
configuration variables must be set prior to running.  If a necessary
configuration variable has not been set, then the script will not enter the
first `verify`, and will raise with an error warning that the variable hasn't
been set.

To set a variable prior to executing the module, use the `Realbook.set/1`
function.

Note that Realbook variables are threadsafe, they aren't shared between
concurrently running Realbook processes.  That also means that you must
set them on a process-by-process basis.

## Provisioning connections and commands

A process running a realbook script is associated with a *provisioning
conn*.  This is a connection value representing the communication between
the provisioning host (that is running realbook) and the provisioning
target.  Use `Realbook.connect!/1` (typically outside of the realbook
script).  See [running a realbook](3-running_a_realbook.html).

Once you are in, the following pre-imported commands can be used to
perform imperative functions on the target (these should typically be in
either the `verify` or the ):

- To run commands directly, use:
  - `Realbook.Commands.run/1`
  - `Realbook.Commands.run!/1`
- Or if you need to be superuser:
  - `Realbook.Commands.sudo_run/1`
  - `Realbook.Commands.sudo_run!/1`

Note that the bang! versions of the functions will raise if a non-zero
return code (failure) is emitted by the program.  If you are expecting a
non-zero code or need to take decisions based on more detailed information,
use the non-bang versions, which will return `{:ok, stdout}` or
`{:error, stderr, return_code}`.  The non-bang functions will still raise if
there's a connection error between the host and the target.

- To send files to the target, use:
  - `Realbook.Commands.send!/2` and
  - `Realbook.Commands.sudo_send!/2` if you need to be superuser.

- To append to files on the target, use:
  - `Realbook.Commands.append!/2` and
  - `Realbook.Commands.sudo_append!/2` if you need to be superuser.
