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.
def test_ensure_database(self, connect): cur = connect().cursor() # If the database exists, nothing happens. cur.fetchone.return_value = sentinel.something postgresql.ensure_database("hello") cur.execute.assert_has_calls([call("SELECT datname FROM pg_database WHERE datname=%s", ("hello",))]) # If the database does not exist, it is created. cur.fetchone.return_value = None postgresql.ensure_database("hello") cur.execute.assert_has_calls( [call("SELECT datname FROM pg_database WHERE datname=%s", ("hello",)), call("CREATE DATABASE %s", (ANY,))] ) # The database name in that last call was correctly quoted. quoted_dbname = cur.execute.call_args[0][1][0] self.assertIsInstance(quoted_dbname, postgresql.AsIs) self.assertEqual(str(quoted_dbname), '"hello"')
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.
def test_ensure_database(self, connect): cur = connect().cursor() # If the database exists, nothing happens. cur.fetchone.return_value = sentinel.something postgresql.ensure_database('hello') cur.execute.assert_has_calls([ call('SELECT datname FROM pg_database WHERE datname=%s', ('hello', )) ]) # If the database does not exist, it is created. cur.fetchone.return_value = None postgresql.ensure_database('hello') cur.execute.assert_has_calls([ call('SELECT datname FROM pg_database WHERE datname=%s', ('hello', )), call('CREATE DATABASE %s OWNER %s', (ANY, ANY)) ]) # The database name in that last call was correctly quoted. quoted_dbname = cur.execute.call_args[0][1][0] self.assertIsInstance(quoted_dbname, postgresql.AsIs) self.assertEqual(str(quoted_dbname), '"hello"')