Guide
=====

This guide is intended to help understanding basic concepts and as a reference
to behaviour, features, and API of batou. It should answer all questions that
you have when setting up your own deployments.

.. contents::
    :local:

General model
-------------

A deployment (or "service") is split into two parts: the components and
environments.

.. image:: general-model.png
    :width: 400px

**Components** define the general parts that your service consists of: frontend
configuration, your application itself, database configuration, cronjobs, and
additional services and infrastructure support.

They also:

* implement the **configure, verify, update cyle**
* (re)use other components to construct a **hierarchy** for breaking complex
   tasks into smaller pieces
* explicitly determine execution **order** of lower-level components within
  their level of the hierarchy
* can exchange information between each other using the **resource
  API** - a simple in-memory key-value store, modelling dependencies between
  components and determining higher-level execution order
* should generally not have *any* specific hard-coded information
  about hostnames, public addresses, etc.

**Environments** define individual installations of your service by mapping the
service's components to hosts. A service can define any number of environments.
You need at least one environment to actually perform any deployment.

They also:

* can override any attributes on top-level components
* determine the type of the **platform** that is deployed to, activating
  platform-specific components in addition to the services' general model


When **deploying locally** all components of the specific host/environment
combination will be configured in your **working directory**.

When **deploying remotely** all components of all hosts of the specified
environment will be configured on the target machines' working directories.


Components
----------

Components are *the* essential part of batou's model: they describe a part of
your service in the "configure/verify/update" idiom and by creating more complex
parts from a tree of sub-components.

Here's a sample component that we can use to explain most of a component's
anatomy:

.. code-block:: python

    from batou.component import Component
    from batou.lib.file import File


    class CompressedFile(Component):

        namevar = path
        content = ''

        def configure(self):
            self.path = self.map(self.path)
            self.raw_path = self.path + '.raw'
            self += File(raw_path, content=self.content)

        def verify(self):
            self.assert_file_is_current(self.path, [self.raw_path])

        def update(self):
            self.cmd('gzip -c {} > {}'.format(self.raw_path, self.path))

First, you can see that **components are written as Python classes**. The
object-oriented model fits well into Python's OO mechanisms: the class receives
parameters for each instance of the component and encapsulates data and
behaviour.

Instances of components can either be sub-components (like the usage of the
'File' component in the example) or they are instances as referred to by the
environment's host/component mapping (also known as "root components").

A component has a **namevar** attribute which determines the name of the first
parameter when used as a sub-component. This allows specifying one single,
"natural" argument for components, like the filename for the 'File' component.

Components have three methods: **configure, verify, and update**. All the
methods are optional, but in most cases you will implement at least the
``configure`` method.

``configure()``
~~~~~~~~~~~~~~~


The ``configure`` method is used to compute the desired target state for your
deployment.

This computation will leverage input from the framework by using instance
attributes that will be set by parent components or environment-specific
overrides. In turn, you can use the ``+=`` operator to attach sub-components.
Sub-components will be processed in the order they are added to their parent.

``configure`` **will be called by the framework multiple times and in many
locations**: on your local computer, at all target systems, and over and over
again while batou tries to determine the correct order to deploy the root
components.

This has a couple of implications that you need to be aware of when writing
code in the ``configure`` method:

* Do not rely upon any state that you expect on the target machine to exist.
  Corollary: do not open files outside of the definition directory of your
  component.
* Do not make changes to the system.
* Only access "globally" available data: from the batou API and global
  network resources (e.g. DNS).
* Avoid making changes to global resources in the Python interpreter (e.g.
  module-level mutables) or at least be aware that this state will not be reset
  automatically by batou when doing repeated runs of your configure code.

Generally speaking, **treat the configure method as if it would run "in empty
space" with no actual environment except from batou's API**.

While running ``configure`` batou will change its working directory to the
definition directory of the root component that is currently being configured.
This means you can (and should) treat all paths relative to this location and
generally not have to use anything outside this directory.

Finally, we encourage you to delegate **dealing with files** to the pre-defined
``File`` component. In case that you need to directly handle paths , ensure
that you **always use** ``map()`` to avoid cluttering developers' environments
and to support sandboxing and platform-specific remapping.

``verify()`` and ``update()``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

These methods complement the pure "etherical" nature of the ``configure()`` method:

* they are both executed exactly once on the target system
* verify determines whether the target system is curently in compliance with the target state
* update modifies the target system to remedy any non-compliance with the target state

details about component features and API
- access to service, environment, and host objects
- naming rules, multiple components in same definition directory vs. working directory
multiple component


Environments
------------

details about environment features

Standard component library
--------------------------

list of default components

Runners
-------

local, remote
