amulet package

amulet.deployer module

class amulet.deployer.Deployment(juju_env=None, series='precise', juju_deployer='juju-deployer', **kw)

A Juju workload.

Use this class to add, configure, relate, and deploy services to a Juju environment.

Variables:Deployment.sentry – A amulet.sentry.Talisman instance that becomes available after a call to setup() (before that, sentry is None.
__init__(juju_env=None, series='precise', juju_deployer='juju-deployer', **kw)

Initialize a deployment.

Parameters:
  • juju_env – Name of the Juju enviroment in which to deploy. If None, the default environment is used.
  • series – The default series of charms to deploy.
  • juju_deployer – Path to juju_deployer binary to use for the deployment.
action_defined(service)

Return list of actions defined for the service.

Parameters:service – Name of service for which to list actions.
Returns:List of actions, as json.

Deprecated since version 1.15: Use amulet.sentry.UnitSentry.list_actions() instead.

action_do(unit, action, action_args=None)

Run action on a unit and return the result UUID.

Parameters:
  • unit – Unit on which to run action, e.g. “wordpress/0”
  • action – Name of action to run.
  • action_args – Dictionary of action parameters.
Return str:

The action UUID.

Deprecated since version 1.15: Use amulet.sentry.UnitSentry.run_action() instead.

action_fetch(action_id, timeout=600, raise_on_timeout=False, full_output=False)

Fetch results for an action.

If the timeout expires and the action is still not complete, an empty dictionary is returned. To raise an exception instead, pass raise_on_timeout=True.

By default, only the ‘results’ dictionary of the action output is returned. To get the full action output instead, pass full_output=True.

Parameters:
  • action_id – UUID of the action.
  • timeout – Length of time to wait for an action to complete.
  • raise_on_timeout – If True, amulet.helpers.TimeoutError will be raised if the action is still running when the timeout expires.
  • full_output – If True, returns the full output from the action. If False, only the ‘results’ dictionary from the action output is returned.
Returns:

Action results, as json.

add(service_name, charm=None, units=1, constraints=None, branch=None, placement=None, series=None, storage=None)

Add a new service to the deployment schema.

Parameters:
  • service_name – Name of the service to deploy.
  • charm – Name of the charm to deploy for this service. If None, defaults to service_name.
  • units – Number of units to deploy.
  • constraints – Dictionary of service constraints.
  • branch – TODO
  • placement

    Placement directive for this service. Examples:

    “1” - Deploy to machine 1 “lxc:1” - Deploy to lxc container on machine 1 “lxc:wordpress/0 - Deploy to lxc container on first wordpress unit

  • series – Series of charm to deploy, e.g. precise, trusty, xenial
  • storage – Storage configuration as a dictionary with key the label and value being the pool,size,count string used by Juju.

Example:

import amulet
d = amulet.Deployment()
d.add('wordpress')
d.add('second-wp', charm='wordpress')
d.add('personal-wp', charm='~marcoceppi/wordpress', units=2)
d.add('postgresql', storage={'pgdata', 'rootfs,50M'})
add_unit(service, units=1, target=None, timeout=300)

Add more units of an existing service after deployment.

Parameters:
  • service – Name of service to which units will be added.
  • units – Number of units to add.
  • target – Placement directive for the added unit(s).

Example:

import amulet
d = amulet.Deployment()
d.add('wordpress')
try:
    d.setup(timeout=900)
except amulet.helpers.TimeoutError:
    # Setup didn't complete before timeout
    pass
d.add_unit('wordpress')
d.add_unit('wordpresss', units=2)
d.add_unit('wordpresss', target="lxc:1")
configure(service, options)

Change configuration options for a service (deployed or not).

Parameters:
  • service – Name of service to configure.
  • options – Dictionary of configuration settings.

Example:

import amulet
d = amulet.Deployment()
d.add('postgresql')
d.configure('postgresql', {
    'autovacuum': True,
    'cluster_name': 'cname',
})
destroy(*units_or_services)

Remove (destroy) one or more already-deployed services or units.

Parameters:units_or_services – One or more service or unit names passed as *args.
destroy_service(*services)

Remove (destroy) one or more already-deployed services.

Parameters:services – One or more service names passed as *args.
destroy_unit(*units)

Remove (destroy) one or more already-deployed units.

Parameters:units – One or more units in the form <service>/<unit_num>, e.g. “wordpress/0”, passed as *args.
expose(service)

Expose a service.

If the service is already deployed it will be exposed immediately, otherwise it will be exposed when deployed.

Parameters:service – Name of the service to expose.

Example:

import amulet
d = amulet.Deployment()
d.add('varnish')
d.expose('varnish')
classmethod from_bundle(bundle_file, deployment_name=None)

Create a Deployment object from a bundle file.

Parameters:
  • bundle_file – Path to the bundle file.
  • deployment_name – Name of the deployment to use. Useful for old-style bundle files that contain multiple named deployments.
Returns:

A new Deployment object.

get_action_output(action_id, timeout=600, raise_on_timeout=False, full_output=False)

Fetch results for an action.

If the timeout expires and the action is still not complete, an empty dictionary is returned. To raise an exception instead, pass raise_on_timeout=True.

By default, only the ‘results’ dictionary of the action output is returned. To get the full action output instead, pass full_output=True.

Parameters:
  • action_id – UUID of the action.
  • timeout – Length of time to wait for an action to complete.
  • raise_on_timeout – If True, amulet.helpers.TimeoutError will be raised if the action is still running when the timeout expires.
  • full_output – If True, returns the full output from the action. If False, only the ‘results’ dictionary from the action output is returned.
Returns:

Action results, as json.

load(deploy_cfg, deployment_name=None)

Load an existing deployment schema (bundle) dictionary.

Parameters:
  • deploy_cfg – The bundle dictionary.
  • deployment_name – Name of the deployment to use. Useful for old-style bundle files that contain multiple named deployments.
load_bundle_file(bundle_file, deployment_name=None)

Load a bundle file from disk.

Parameters:
  • bundle_file – Path to the bundle file.
  • deployment_name – Name of the deployment to use. Useful for old-style bundle files that contain multiple named deployments.
log = <logging.Logger object>
relate(*args)

Relate two or more services together.

If more than two arguments are given, the first service is related to each of the others.

Parameters:args – Services to relate, in the form “service_name:relation_name”.

Example:

import amulet
d = amulet.Deployment()
d.add('postgresql')
d.add('mysql')
d.add('wordpress')
d.add('mediawiki')
d.add('discourse')
d.relate('postgresql:db-admin', 'discourse:db')
d.relate('mysql:db', 'wordpress:db', 'mediawiki:database')
# previous command is equivalent too:
d.relate('mysql:db', 'wordpress:db')
d.relate('mysql:db', 'mediawiki:database')
remove(*units_or_services)

Remove (destroy) one or more already-deployed services or units.

Parameters:units_or_services – One or more service or unit names passed as *args.
remove_application(*services)

Remove (destroy) one or more already-deployed services.

Parameters:services – One or more service names passed as *args.
remove_service(*services)

Remove (destroy) one or more already-deployed services.

Parameters:services – One or more service names passed as *args.
remove_unit(*units)

Remove (destroy) one or more already-deployed units.

Parameters:units – One or more units in the form <service>/<unit_num>, e.g. “wordpress/0”, passed as *args.
schema()

Return the deployment schema (bundle) as a dictionary.

setup(timeout=600, cleanup=True)

Deploy the workload.

If timeout expires before the deployment completes, raises
amulet.helpers.TimeoutError.
Parameters:
  • timeout – Amount of time to wait for deployment to complete. If environment variable AMULET_SETUP_TIMEOUT is set, it overrides this value.
  • cleanup – Set to False to leave the generated deployer file on disk. Useful for debugging.

Example:

import amulet
d = amulet.Deployment()
d.add('wordpress')
d.add('mysql')
d.configure('wordpress', debug=True)
d.relate('wordpress:db', 'mysql:db')
try:
    d.setup(timeout=900)
except amulet.helpers.TimeoutError:
    # Setup didn't complete before timeout
    pass
unrelate(*args)

Remove a relation between two services.

Parameters:args – Services to unrelate, in the form “service_name:relation_name”.

Example:

import amulet
d = amulet.Deployment()
d.add('postgresql')
d.add('mysql')
d.add('wordpress')
d.add('mediawiki')
d.add('discourse')
d.relate('postgresql:db-admin', 'discourse:db')
d.relate('mysql:db', 'wordpress:db', 'mediawiki:database')
# unrelate all the services we just related
d.unrelate('postgresql:db-admin', 'discourse:db')
d.unrelate('mysql:db', 'wordpress:db')
d.unrelate('mysql:db', 'mediawiki:database')

amulet.sentry module

class amulet.sentry.Talisman(services, rel_sentry='relation-sentry', juju_env=None, timeout=300)

Bases: object

A dict-like object containing a collection of UnitSentry objects, one for each unit in the deployment.

Also provides assorted ‘wait_’ methods which will block until the deployment reaches a certain state.

See __getitem__() for details on retrieving the UnitSentry objects.

Note:Under ordinary circumstances this class should not be instantiated manually. It should instead be access through the sentry attribute on an amulet.deployer.Deployment instance.
__getitem__(service)

Return the UnitSentry object(s) for service

Parameters:service – A string in one of two forms:: “service_name” “service_name/unit_num”

If the first form is used, a list (possibly empty) of all the UnitSentry objects for that service is returned.

If the second form is used, a single object, the UnitSentry for the specified unit, is returned.

Raises a KeyError if the unit does not exist.

Returns an empty list if the service does not exist or has no units.

Examples:

>>> d
<amulet.deployer.Deployment object at 0x7fac83ce8438>
>>> d.schema()['local']['services']['meteor']['num_units']
2
>>> # get UnitSentry for specific unit
>>> meteor_0 = d.sentry['meteor/0']
>>> print(meteor_0.info['service'], meteor_0.info['unit'])
meteor 0
>>> # get all UnitSentry objects for a service
>>> for sentry in d.sentry['meteor']:
...     print(sentry.info['service'], sentry.info['unit'])
...
meteor 1
meteor 0
>>>
wait(timeout=300)

Wait for all units to finish running hooks.

Parameters:timeout (int) – Number of seconds to wait before timing-out. If environment variable AMULET_WAIT_TIMEOUT is set, it overrides this value.
Raises:amulet.TimeoutError if the timeout is exceeded.
wait_for_messages(messages, timeout=300)

Wait for specific extended status messages to be set via status-set.

Note that if this is called on an environment that doesn’t support extended status (pre Juju 1.24), it will raise an UnsupportedError exception.

Parameters:
  • messages (dict) – A mapping of services to an exact message, a regular expression, a set of messages or regular expressions, or a list of messages or regular expressions. If a single message is given, all units of the service must match. If a set is given, then each message in the set must match at least one unit. If a list is given, then there must be a one-to-one match between the messages and the units, though the order doesn’t matter.
  • timeout (int) – Number of seconds to wait before timing-out.

Examples:

# wait for all units to report "ready"
t.wait_for_messages({'ubuntu': 'ready'})

# wait for all units to report something like "ready"
t.wait_for_messages({'ubuntu': re.compile('r..dy')})

# wait for at least one unit to report "ready"
t.wait_for_messages({'ubuntu': {'ready'}})

# wait for all units to report either "ready" or "ok"
t.wait_for_messages({'ubuntu': re.compile('ready|ok')})

# wait for at least one unit to report "ready" and at least one
# unit to report "ok"
t.wait_for_messages({'ubuntu': {'ready', 'ok'}})

# wait for one unit to report "ready" and the other to report "ok"
# (must be exactly two units)
t.wait_for_messages({'ubuntu': ['ready', 'ok']})
wait_for_status(juju_env, services, timeout=300)

Return environment status, but only after all units have a public-address assigned and are in a ‘started’ state.

This method is called automatically by __init__(), meaning that initialization of this Talisman object will not complete until this method returns. Under ordinary circumstances you should not need to call this method manually.

Raises if a unit reaches error state, or if public-address not available for all units before timeout expires.

Parameters:
  • juju_env (str) – Name of the juju environment.
  • services (dict) – Dictionary of services in the environment.
  • timeout (int) – Time to wait before timing out. If environment variable AMULET_WAIT_TIMEOUT is set, it overrides this value.
Returns:

Dictionary of juju enviroment status.

class amulet.sentry.UnitSentry(address, port=9001)

Bases: amulet.sentry.Sentry

A proxy to a deployed unit, through which the unit can be manipulated.

Provides methods for running commands on the unit and fetching relation data from units to which this unit is related.

Variables:info (dict) – A dictionary containing ‘unit_name’ (in the form ‘wordpress/0’), ‘service’ (name), ‘unit’ (unit number as string), ‘machine’ (machine number as string), ‘public-address’, and ‘agent-version’.
_run(command, unit=None, timeout=300)

Run an arbitrary command (as root) on the remote unit.

Uses juju run to execute the command, which means the command will be queued to run after already-queued hooks. To avoid this behavior and instead execute the command immediately, see the ssh() method.

Parameters:
  • command (str) – The command to run.
  • unit (str) – Unit on which to run the command, in the form ‘wordpress/0’. If None, defaults to the unit for this UnitSentry.
  • timeout (int) – Seconds to wait before timing out.
Returns:

A 2-tuple containing the output of the command and the exit code of the command.

action_defined()

Return list of actions defined for this unit.

Returns:List of actions, as json.
action_do(action, action_args=None)

Run an action on this unit and return the result UUID.

Parameters:
  • action – Name of action to run.
  • action_args – Dictionary of action parameters.
Return str:

The action UUID.

directory_listing(path)

Get the contents of the directory at path on the remote unit.

Parameters:path (str) – Path of directory on the remote unit.
Returns:Dictionary containing ‘files’ and ‘directories’, both lists.

This method does the equivalent of the following, on the remote unit:

contents = {'files': [], 'directories': []}
for fd in os.listdir(path):
    if os.path.isfile('{}/{}'.format(path, fd)):
        contents['files'].append(fd)
    else:
        contents['directories'].append(fd)
return contents
directory_stat(path)

Run os.stat() against path on the unit.

Parameters:path (str) – Path of directory to stat on the remote unit.
Returns:Dictionary containing mtime, size, uid, gid, and mode of path.
file_contents(filename)

Get the contents of filename on the remote unit.

Parameters:filename (str) – Path of file to stat on the remote unit.
Raises:IOError if the call fails.
Returns:File contents as string.
file_stat(filename)

Run os.stat() against filename on the unit.

Parameters:filename (str) – Path of file to stat on the remote unit.
Returns:Dictionary containing mtime, size, uid, gid, and mode of filename.
list_actions()

Return list of actions defined for this unit.

Returns:List of actions, as json.
relation(from_rel, to_rel)

Get relation data from the remote unit to which we are related, denoted by to_rel.

Parameters:
  • from_rel (str) – The local side of the relation, e.g. ‘website’.
  • to_rel (str) – The remote side of the relation, e.g. ‘haproxy:reverseproxy’.
Returns:

Dictionary containing the results of relation-get, run on the unit on the remote side of the relation.

run(command)

Run an arbitrary command (as root) on the remote unit.

Uses juju run to execute the command, which means the command will be queued to run after already-queued hooks. To avoid this behavior and instead execute the command immediately, see the ssh() method.

Parameters:command (str) – The command to run.
Returns:A 2-tuple containing the output of the command and the exit code of the command.

A default timeout of 5 minutes is imposed on the command. To change this timeout, see the _run() method.

run_action(action, action_args=None)

Run an action on this unit and return the result UUID.

Parameters:
  • action – Name of action to run.
  • action_args – Dictionary of action parameters.
Return str:

The action UUID.

ssh(command, unit=None, raise_on_failure=False)

Run an arbitrary command (as the ubuntu user) against a remote unit, using juju ssh.

Using juju ssh bypasses the Juju execution queue, so it will not be blocked by running hooks. Note, however, that the command is run as the ubuntu user instead of root.

Parameters:
  • command (str) – The command to run.
  • unit (str) – Unit on which to run the command, in the form ‘wordpress/0’. If None, defaults to the unit for this UnitSentry.
  • raise_on_failure (bool) – If True, raises subprocess.CalledProcessError if the command fails.
Returns:

A 2-tuple containing the output of the command and the exit code of the command.