Ejemplo n.º 1
0
def ensure_db_relation_resources(rel):
    """Create the database resources needed for the relation."""

    master = rel.local

    if "password" not in master:
        return

    hookenv.log("Ensuring database {!r} and user {!r} exist for {}" "".format(master["database"], master["user"], rel))

    # First create the database, if it isn't already.
    postgresql.ensure_database(master["database"])

    # Next, connect to the database to create the rest in a transaction.
    con = postgresql.connect(database=master["database"])

    superuser, replication = _credential_types(rel)
    postgresql.ensure_user(
        con,
        master["user"],
        master["password"],
        superuser=superuser,
        replication=replication,
    )
    if not superuser:
        postgresql.ensure_user(con, master["schema_user"], master["schema_password"])

    # Grant specified privileges on the database to the user. This comes
    # from the PostgreSQL service configuration, as allowing the
    # relation to specify how much access it gets is insecure.
    config = hookenv.config()
    privs = set(filter(None, config["relation_database_privileges"].split(",")))
    postgresql.grant_database_privileges(con, master["user"], master["database"], privs)
    if not superuser:
        postgresql.grant_database_privileges(con, master["schema_user"], master["database"], privs)

    # Reset the roles granted to the user as requested.
    if "roles" in master:
        roles = filter(None, master.get("roles", "").split(","))
        postgresql.grant_user_roles(con, master["user"], roles)

    # Create requested extensions. We never drop extensions, as there
    # may be dependent objects.
    if "extensions" in master:
        extensions = list(filter(None, master.get("extensions", "").split(",")))
        # Convert to the (extension, schema) tuple expected by
        # postgresql.ensure_extensions
        for i in range(0, len(extensions)):
            m = re.search(r"^\s*([^(\s]+)\s*(?:\((\w+)\))?", extensions[i])
            if m is None:
                raise RuntimeError("Invalid extension {}".format(extensions[i]))
            extensions[i] = (m.group(1), m.group(2) or "public")
        postgresql.ensure_extensions(con, extensions)

    con.commit()  # Don't throw away our changes.
Ejemplo n.º 2
0
    def test_ensure_extensions(self, pgidentifier, log):
        con = MagicMock()
        cur = con.cursor()

        pgidentifier.side_effect = lambda d: "q_{}".format(d)

        existing_extensions = set(["extA", "extB"])
        wanted_extensions = set(["extB", "extC"])

        cur.fetchall.return_value = [[x] for x in existing_extensions]
        postgresql.ensure_extensions(con, wanted_extensions)
        cur.execute.assert_has_calls(
            [call("SELECT extname FROM pg_extension"), call("CREATE EXTENSION %s", ("q_extC",))]
        )
Ejemplo n.º 3
0
    def test_ensure_extensions(self, pgidentifier, log):
        con = MagicMock()
        cur = con.cursor()

        pgidentifier.side_effect = lambda d: 'q_{}'.format(d)

        existing_extensions = set([('extA', 'public'), ('extB', 'public')])
        wanted_extensions = set([('extB', 'public'), ('extC', 'custom')])

        cur.fetchall.return_value = [x for x in existing_extensions]
        postgresql.ensure_extensions(con, wanted_extensions)
        cur.execute.assert_has_calls([
            call(
                'SELECT extname, nspname FROM pg_extension, pg_namespace WHERE pg_namespace.oid = extnamespace'
            ),
            call('CREATE SCHEMA IF NOT EXISTS %s', ('q_custom', )),
            call('GRANT USAGE ON SCHEMA %s TO PUBLIC', ('q_custom', )),
            call('CREATE EXTENSION %s WITH SCHEMA %s', ('q_extC', 'q_custom'))
        ])
Ejemplo n.º 4
0
def ensure_db_relation_resources(rel):
    """Create the database resources needed for the relation."""

    master = rel.local

    hookenv.log("Ensuring database {!r} and user {!r} exist for {}" "".format(master["database"], master["user"], rel))

    # First create the database, if it isn't already.
    postgresql.ensure_database(master["database"])

    # Next, connect to the database to create the rest in a transaction.
    con = postgresql.connect(database=master["database"])

    superuser, replication = _credential_types(rel)
    postgresql.ensure_user(con, master["user"], master["password"], superuser=superuser, replication=replication)
    if not superuser:
        postgresql.ensure_user(con, master["schema_user"], master["schema_password"])

    # Grant specified privileges on the database to the user. This comes
    # from the PostgreSQL service configuration, as allowing the
    # relation to specify how much access it gets is insecure.
    config = hookenv.config()
    privs = set(filter(None, config["relation_database_privileges"].split(",")))
    postgresql.grant_database_privileges(con, master["user"], master["database"], privs)
    if not superuser:
        postgresql.grant_database_privileges(con, master["schema_user"], master["database"], privs)

    # Reset the roles granted to the user as requested.
    if "roles" in master:
        roles = filter(None, master.get("roles", "").split(","))
        postgresql.grant_user_roles(con, master["user"], roles)

    # Create requested extensions. We never drop extensions, as there
    # may be dependent objects.
    if "extensions" in master:
        extensions = filter(None, master.get("extensions", "").split(","))
        postgresql.ensure_extensions(con, extensions)

    con.commit()  # Don't throw away our changes.