Provides: PostgreSQL

Example Usage

This is what a charm using this relation would look like:

# in the postgres charm:
from charmhelpers.core import hookenv  # noqa
from charmhelpers.core import unitdata
from charmhelpers.core.reactive import when
from common import (
    user_name,
    create_user,
    reset_user_roles,
    ensure_database,
    get_service_port,
)


@when('db.roles.requested')
def update_roles(pgsql):
    for service, roles in pgsql.requested_roles():
        user = user_name(pgsql.relation_name(), service)
        reset_user_roles(user, roles)
        pgsql.ack_roles(service, roles)


@when('db.database.requested')
def provide_database(pgsql):
    for service, database in pgsql.requested_databases():
        if not database:
            database = service
        roles = pgsql.requested_roles(service)

        user = user_name(pgsql.relation_name(), service)  # generate username
        password = create_user(user)  # get-or-create user
        schema_user = "{}_schema".format(user)
        schema_password = create_user(schema_user)

        reset_user_roles(user, roles)
        ensure_database(user, schema_user, database)

        pgsql.provide_database(
            service=service,
            host=hookenv.unit_private_ip(),
            port=get_service_port(),
            database=database,
            state=unitdata.kv().get('pgsql.state'),  # master, hot standby, standalone
            user=user,
            password=password,
            schema_user=schema_user,
            schema_password=schema_password,
        )

Reference

class provides.PostgreSQL(relation_name, conversations=None)[source]
ack_roles(*args, **kwargs)[source]

Acknowledge that a set of roles have been given to a service’s user.

Parameters:service (str) – The service which requested the roles, as returned by requested_roles().
joined_changed()[source]

Handles the relation-joined and relation-changed hook.

Depending on the state of the conversation, this can trigger one of the following states:

  • {relation_name}.database.requested This state will be activated if the remote service has requested a different database name than the one it has been provided. This state should be resolved by calling provide_database(). See also requested_databases().
  • {relation_name}.roles.requested This state will be activated if the remote service has requested a specific set of roles for its user. This state should be resolved by calling ack_roles(). See also requrested_roles().
previous_database(service)[source]

Return the roles previously requested, if different from the currently requested roles.

previous_roles(service)[source]

Return the roles previously requested, if different from the currently requested roles.

provide_database(*args, **kwargs)[source]

Provide a database to a requesting service.

Parameters:
  • service (str) – The service which requested the database, as returned by requested_databases().
  • host (str) – The host where the database can be reached (e.g., the charm’s private or public-address).
  • port (int) – The port where the database can be reached.
  • database (str) – The name of the database being provided.
  • user (str) – The username to be used to access the database.
  • password (str) – The password to be used to access the database.
  • schema_user (str) – The username to be used to admin the database.
  • schema_password (str) – The password to be used to admin the database.
  • state (str) – I have no idea what this is for. TODO: Document this better
requested_database(service)[source]

Return the database name requested by the given service. If the given service has not requested a specific database name, an empty string is returned, indicating that the database name should be generated.

requested_databases()[source]

Return a list of tuples mapping a service name to the database name requested by that service. If a given service has not requested a specific database name, an empty string is returned, indicating that the database name should be generated.

Example usage:

for service, database in pgsql.requested_databases():
    database = database or generate_dbname(service)
    pgsql.provide_database(**create_database(database))
requested_roles(service=None)[source]

Return the roles requested by all or a single given service.

Parameters:service (str) – The name of a service requesting roles, as provided by either requested_roles() (with no args) or requested_databases().
Returns:If no service name is given, then a list of (service, roles) tuples are returned, mapping service names to their requested roles. If a service name is given, a list of the roles requested for that service is returned.

Example usage:

for service, roles in pgsql.requested_roles():
    set_roles(username_from_service(service), roles)
    pgsql.ack_roles(service, roles)