Hosts
=====

The HOSTATTRS list
------------------

This is a plist of lists, such that for each keyword symbol identifying a type
of static informational attribute ("hostattr"), there is a list of entries.
Property ``:HOSTATTRS`` subroutines may only push new entries to the front of
each such sublist, using the function ``PUSH-HOSTATTR``.  Use
``GET-HOSTATTRS`` and ``GET-HOSTATTRS-CAR`` to access the lists.

The relationship between older and newer entries in the sublist for each type
of static informational attribute is attribute-dependent.  For example, for
the ``:DATA`` attribute, the order of entries does not matter and each item is
equally a piece of prerequisite data required by the host's properties.  For
other kinds of attribute, it might be that later entries supercede earlier
ones, or that the entries should be combined in some way.  Property ``:APPLY``
subroutines decide how to interpret each type of static informational
attribute.

Reserved names for static informational attributes
--------------------------------------------------

For attributes that will only be used among a co-ordinating group of
properties, use a non-keyword symbol, whose package is one in which some or
all of those properties are defined.  This minimises the risk of any clashes.
Many attributes, however, will be shared across properties, and should use
keyword symbols.  The semantics of these attributes are documented here:

- ``:HOSTNAME``: the host's hostname -- if the host has a domain name, then
  the FQDN, not just the part before the first dot

- ``:ALIASES``: see ``NETWORK:ALIASES``

- ``:IPV4``: the host's public IPv4 addresses

- ``:IPV6``: the host's public IPv6 addresses

- ``:DATA``: items of prerequisite data required by the host

- ``:OS``: the operating system of the host

- ``:APT.MIRRORS``: for hosts running Debian or a Debian derivative, the
  host's preferred apt mirrors

Host designators
----------------

A string designates a host with that hostname and no properties.  Using
strings to designate hosts is not valid in all contexts -- some macros and
properties where it might be useful to pass a string instead of a ``HOST``
object call ``ENSURE-HOST`` to convert, but this is not done everywhere.

API reference
-------------

Hosts
~~~~~

Class: ``HOST``
^^^^^^^^^^^^^^^

Abstract superclass for hosts.  Do not instantiate.

Class: ``UNPREPROCESSED-HOST``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

A host whose :PREPROCESS and :HOSTATTRS subroutines have not been run.

Generic function: ``ENSURE-HOST``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

``(ensure-host host)``

Return the HOST value designated by HOST.

Macro: ``WITH-PRESERVE-HOSTATTRS``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

``(with-preserve-hostattrs &body forms)``

Evaluate FORMS then throw away any newly added hostattrs.
Useful in property combinators when you need to run some :HOSTATTRS
subroutines but ignore any new hostattrs they may push.  Shouldn't be used in
properties.

Generic function: ``PREPROCESS-HOST``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

``(preprocess-host host)``

Convert a host into a fresh preprocessed host if necessary, and
unconditionally perform a shallow copy of the plist of static information
attributes, so that implementations of ESTABLISH-CONNECTION can push new
attributes (typically to request prerequisite data) without disturbing host
values higher up the call stack.

Function: ``MAKE-HOST``
^^^^^^^^^^^^^^^^^^^^^^^

``(make-host &key hostattrs propspec deploy)``

Function: ``MAKE-CHILD-HOST``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

``(make-child-host &key hostattrs propspec)``

Make a host object to represent a chroot, container or the like.
Called by properties which set up such subhosts, like CHROOT:OS-BOOTSTRAPPED.

Macro: ``DEFHOST``
^^^^^^^^^^^^^^^^^^

``(defhost hostname &key &body properties)``

Define a host with hostname HOSTNAME and properties PROPERTIES.
HOSTNAME can be a string or a symbol.  In either case, the host will get a
static informational property with its hostname as a string, and the symbol
whose name is the hostname will be bound to the host object.

DEPLOY represents the usual way you'll connect to the host to deploy
properties, and if specified, a function named HOSTNAME will be defined to
deploy the host using that connection chain.  This is an optional convenience
feature; you can always use DEPLOY and DEPLOY-THESE to apply properties to the
host using an arbitrary chain of connections.

If the first entry in PROPERTIES is a string, it will be considered a
human-readable description of the host.  Otherwise, PROPERTIES is an
unevaluated property application specification.  Recall that for atomic
entries (PROPERTY . ARGS), PROPERTY refers to the property that symbol names
in the global environment, not whatever it may name in the current dynamic
and/or lexical environments.  Property application specifications cannot
close over globally anonymous properties.

The order of PROPERTIES matters: deployments will apply properties to the host
in the order specified here, so later properties implicitly depend on earlier
ones.  In addition, static informational attributes set by later properties
are allowed to override any attributes with the same name set by earlier
entries.

Property: ``HAS-HOSTATTRS``
^^^^^^^^^^^^^^^^^^^^^^^^^^^

``(has-hostattrs k &rest vs)``

Push hostattrs VS of type K.
