charmhelpers.core.charmframework

Manager Manage all hooks, based on a set of charm component definitions.
helpers.HttpRelation Relation subclass for handling relations using the http interface protocol.
helpers.MySQLRelation Relation subclass for handling relations using the mysql interface protocol.
helpers.Relation Base class for relation handler classes.
helpers.all_ready_units Returns the unit name and data for all ready untis on the given relation, sorted by unit name.
helpers.any_ready_unit Returns the unit name and data for any single ready unit on the given relation.
helpers.close_ports Callback helper that will close the given ports when called.
helpers.config_eq Predicate helper that asserts that the given config option is equal to the given value.
helpers.config_is_set Predicate helper that asserts that the given config option is set to a non-empty / non-None value.
helpers.config_ne Predicate helper that asserts that the given config option is not equal to the given value.
helpers.config_not_default Predicate helper that asserts that the given config option is not equal to its default value.
helpers.open_ports Callback helper that will open the given ports when called.
helpers.render_template Callback helper that will render a Jinja2 template.
helpers.service_reload Callback helper that will reload the given service.
helpers.service_restart Callback helper that will restart the given service.
helpers.service_stop Callback helper that will stop the given service.
class charmhelpers.core.charmframework.base.Manager(components)

Bases: object

Manage all hooks, based on a set of charm component definitions.

Component definitions are dicts in the following format (all fields are optional):

{
    "name": <name of component>,
    "provides": <list of providers>,
    "requires": <list of predicates>,
    "callbacks": <list of callbacks>,
    "cleanup": <list of callbacks>,
}
Variables:
  • name (str) – Descriptive name
  • provides (list) – Data providers, most likely subclasses of Relation, although any object (or class) which has a relation_name attribute and a provide method which accepts the remote service name and a flag indicating whether the callbacks have been fired, and which returns a dict of data to send to that remote service.
  • requires (list) – Predicates, all of which must pass for the callbacks to be fired. Relation subclasses or instances can be used as predicates in addition to simple no-argument functions which return a bool. Any Relation subclass or instance will have its store_data() method called. See helpers for several helpers that can be used to construct predicates.
  • callbacks (list) – Callbacks that are fired if all requires predicates pass. They will be passed no arguments. See helpers for several helpers that can be used to construct callbacks.
  • cleanup (list) – Callbacks that are fired when stopping the service.

Examples:

The following registers a component which depends on a mongodb relation and a password option being changed from its default value, and which runs a custom db_migrate function, adds a system user, renders a couple of templates, starts the system service ‘myservice’, and finally opens a couple of ports:

from charmhelpers.core import charmframework
from charmhelpers.core import host
from functools import partial

class MongoRelation(charmframework.helpers.Relation):
    relation_name = 'mongo'
    required_keys = ['hostname', 'port']

manager = charmframework.Manager([
    {
        'provides': [
            HttpRelation,
        ],
        'requires': [
            MongoRelation,
            charmframwork.helpers.config_not_default('password'),
        ],
        'callbacks': [
            db_migrate,
            partial(host.adduser, 'myuser'),
            charmframework.helpers.render_template(source='myservice.conf'),
            charmframework.helpers.render_template(source='myservice.ini',
                                                   target='/etc/myservice.ini',
                                                   owner='myuser', perms=0400),
            charmframework.helpers.service_restart('myservice'),
            charmframework.helpers.open_ports(80, 443),
        ],
        'cleanup': [
            charmframework.helpers.close_ports(80, 443),
            charmframework.helpers.service_stop('myservice'),
        ],
    },
])
manager.manage()
fire_event(event_name, component)

Fire an actions, or cleanup event on a given component.

is_ready(component)

Determine if a registered component is ready, by checking its requires items.

manage()

Handle the current hook by doing The Right Thing with the registered components.

not_ready(*args, **kwargs)
provide_data()

Set the relation data for each provider in the provides list.

A provider can be a class or an instance, and must have a relation_name attribute, which indicates which relation is applies to, and a provide(remote_service, all_ready) method, where remote_service is the name of the Juju service on the other end of the relation, and all_ready is a boolean indicating whether all of the requirements for the component were satisfied and the callbacks were run.

Note that the providers are called after the requirements are checked and the callbacks (possibly) run, since the callbacks may generate some of the data to be provided.

run_callbacks()

Check all components’ requires predicates and run either callbacks or cleanup actions.

run_cleanup()

Unconditionally run all components’ cleanup actions.

save_lost(component)

Save an indicator that the given component is no longer ready.

save_ready(component)

Save an indicator that the given component is now ready.

store_data(component)
was_ready(component)

Determine if the given component was previously ready.

charmhelpers.core.charmframework.helpers

class charmhelpers.core.charmframework.helpers.HttpRelation(**kwargs)

Bases: charmhelpers.core.charmframework.helpers.Relation

Relation subclass for handling relations using the http interface protocol.

As mentioned in Relation, all variables (including port) can be overridden when instantiating the class.

port = 80

Port upon which this service is listening.

provide(remote_service, all_ready)
relation_name = 'website'
required_keys = ['host', 'port']
class charmhelpers.core.charmframework.helpers.MySQLRelation(**kwargs)

Bases: charmhelpers.core.charmframework.helpers.Relation

Relation subclass for handling relations using the mysql interface protocol.

As mentioned in Relation, all variables (including dsn_format) can be overridden when instantiating the class.

dsn_format = 'mysql://{user}:{password}@{host}/{database}'

In addition to the required_keys, a dsn value is constructed, based on this format string, and added to the filtered_data().

filtered_data(remote_service=None)

Get the filtered data, as per Relation.filtered_data(), and add a dsn entry constructed from the other values.

relation_name = 'db'
required_keys = ['host', 'user', 'password', 'database']
class charmhelpers.core.charmframework.helpers.Relation(**kwargs)

Bases: object

Base class for relation handler classes.

Note: The default constructor allows any pre-defined class attribute to be overridden via kwargs during instantiation. Thus, the above variables can be set or overridden when constructing the relation or a subclass. For example, the following will override both the optional flag and the port:

class MyRelation(Relation):
    relation_name = 'foo'
    port = 80

rel = MyRelation(optional=True, port=8080)
connected_units()

Returns a list of the names of all units connected on this relation.

filtered_data(remote_service=None)

Get the data from unfiltered_data() and filter it to only include units which have set all of the required_keys.

Parameters:remote_service (str) – If given, additionally filter to only include data for units of a single service (useful in provide() methods).
Returns:Mapping (dict) of unit name to that unit’s data dict.
is_ready()

Determine if this relation is “ready”.

A relation is ready if it is not optional and there is at least one unit that satisfies all of the required_keys. (Optional relations are always considered ready.)

Note: A Relation instance can also be evaluated directly (e.g., via bool()) to test its readiness.

optional = False

Whether the relation is optional. An optional relation always passes when used as a predicate, even if no units are connected. However, it is still useful to include them in the requires section, because it is both informative when reading the definition and allows the framework to automatically call store_data().

provide(remote_service, all_ready)

Provide data to the other side of the relation.

This should be implemented by subclasses.

Parameters:
  • remote_service (str) – Name of the remote service to which this relation will be providing data
  • all_ready (bool) – Whether all requires predicates for this Charm component have been met and the callbacks run
relation_name = None

Name (not interface) of the relation to manage.

required_keys = []

List of keys that must be set on the relation for it to be considered ready (i.e., pass when used as a requires predicate). If no keys are defined, then a relation is considered ready if a unit is attached.

store_data()

Store all filtered relation data is stored in unitdata under relations.ready.

The data can be retrieved using:

from charmhelpers.core import unitdata
data = unitdata.kv.get('relations.ready')[relation_name][unit_name]

However, it is generally recommended to use one of any_ready_unit() or all_ready_units().

This method is called automatically for all Relation subclasses as predicates in the required section of a definition.

unfiltered_data()

Get all relation data for any unit connected to this relation.

Returns:Mapping (dict) of unit name to that unit’s data dict.
charmhelpers.core.charmframework.helpers.all_ready_units(relation_name)

Returns the unit name and data for all ready untis on the given relation, sorted by unit name.

This requires that Relation.store_data() has been called for the given relation, which is done automatically by charmhelpers.core.charmframework.base.Manager.

Parameters:relation_name (str) – Name of the relation
Return list:List of tuples containing (unit_name, unit_data), or an empty list if no units are ready for the given relation
charmhelpers.core.charmframework.helpers.any_ready_unit(relation_name)

Returns the unit name and data for any single ready unit on the given relation.

If more than one unit is attached and ready, this is not guaranteed to return the same unit each time it is called. It is recommended that you use all_ready_units() if you ever expect more than one service or unit to be attached.

This requires that Relation.store_data() has been called for the given relation, which is done automatically by Manager.

Parameters:relation_name (str) – Name of the relation
Returns:Tuple containing (unit_name, unit_data), or (None, None) if no units are ready for the given relation
charmhelpers.core.charmframework.helpers.close_ports(*ports)

Callback helper that will close the given ports when called.

Roughly equivalent to:

lambda: map(hookenv.open_port, ports)

However, ports can be given as individual ports (close_ports(80, 443)), or a list of ports (close_ports([80, 443])).

charmhelpers.core.charmframework.helpers.config_eq(option, value)

Predicate helper that asserts that the given config option is equal to the given value.

Values of None are normalized to empty strings, since it is impossible to properly “unset” a config value once it has been set; it can only be set to an empty string.

For example:

Manager([
    {
        'requires': [config_eq('unstable', False)],
        'callbacks': [install_stable],
    },
    {
        'requires': [config_eq('unstable', True)],
        'callbacks': [install_unstable],
    },
])

In this case, only one of install_stable or install_unstable will ever be called, depending on the value of the ‘unstable’ config option.

charmhelpers.core.charmframework.helpers.config_is_set(option)

Predicate helper that asserts that the given config option is set to a non-empty / non-None value.

This is equivalent to config_ne(option, ''), but can be a bit more clear.

charmhelpers.core.charmframework.helpers.config_ne(option, value)

Predicate helper that asserts that the given config option is not equal to the given value.

Values of None are normalized to empty strings, since it is impossible to properly “unset” a config value once it has been set; it can only be set to an empty string.

charmhelpers.core.charmframework.helpers.config_not_default(option)

Predicate helper that asserts that the given config option is not equal to its default value.

Values of None are normalized to empty strings, since it is impossible to properly “unset” a config value once it has been set; it can only be set to an empty string.

charmhelpers.core.charmframework.helpers.open_ports(*ports)

Callback helper that will open the given ports when called.

Roughly equivalent to:

lambda: map(hookenv.open_port, ports)

However, ports can be given as individual ports (open_ports(80, 443)), or a list of ports (open_ports([80, 443])).

charmhelpers.core.charmframework.helpers.render_template(source, target, context=None, owner='root', group='root', perms=292)

Callback helper that will render a Jinja2 template.

The template is provided a context which contains these items by default:

Parameters:
  • source (str) – The template source file, relative to $CHARM_DIR/templates
  • target (str) – The target to write the rendered template to
  • context (dict) – Additional context to be provided to the template
  • owner (str) – The owner of the rendered file (default: root)
  • group (str) – The group of the rendered file (default: root)
  • perms (int) – The permissions of the rendered file (default 0o444)
charmhelpers.core.charmframework.helpers.service_reload(service_name)

Callback helper that will reload the given service.

Equivalent to:

functools.partial(hookenv.service_reload, service_name)
charmhelpers.core.charmframework.helpers.service_restart(service_name)

Callback helper that will restart the given service.

Equivalent to:

functools.partial(hookenv.service_restart, service_name)
charmhelpers.core.charmframework.helpers.service_stop(service_name)

Callback helper that will stop the given service.

Equivalent to:

functools.partial(hookenv.service_stop, service_name)