mirror of
https://github.com/postgresml/pgcat.git
synced 2026-03-23 01:16:30 +00:00
174 lines
5.5 KiB
Ruby
174 lines
5.5 KiB
Ruby
|
|
module Helpers
|
||
|
|
module AuthQuery
|
||
|
|
def self.single_shard_auth_query(
|
||
|
|
pg_user:,
|
||
|
|
config_user:,
|
||
|
|
pool_name:,
|
||
|
|
extra_conf: {},
|
||
|
|
log_level: 'debug',
|
||
|
|
wait_until_ready: true
|
||
|
|
)
|
||
|
|
|
||
|
|
user = {
|
||
|
|
"pool_size" => 10,
|
||
|
|
"statement_timeout" => 0,
|
||
|
|
}
|
||
|
|
|
||
|
|
pgcat = PgcatProcess.new(log_level)
|
||
|
|
pgcat_cfg = pgcat.current_config.deep_merge(extra_conf)
|
||
|
|
|
||
|
|
primary = PgInstance.new(5432, pg_user["username"], pg_user["password"], "shard0")
|
||
|
|
replica = PgInstance.new(10432, pg_user["username"], pg_user["password"], "shard0")
|
||
|
|
|
||
|
|
# Main proxy configs
|
||
|
|
pgcat_cfg["pools"] = {
|
||
|
|
"#{pool_name}" => {
|
||
|
|
"default_role" => "any",
|
||
|
|
"pool_mode" => "transaction",
|
||
|
|
"load_balancing_mode" => "random",
|
||
|
|
"primary_reads_enabled" => false,
|
||
|
|
"query_parser_enabled" => false,
|
||
|
|
"sharding_function" => "pg_bigint_hash",
|
||
|
|
"shards" => {
|
||
|
|
"0" => {
|
||
|
|
"database" => "shard0",
|
||
|
|
"servers" => [
|
||
|
|
["localhost", primary.port.to_s, "primary"],
|
||
|
|
["localhost", replica.port.to_s, "replica"],
|
||
|
|
]
|
||
|
|
},
|
||
|
|
},
|
||
|
|
"users" => { "0" => user.merge(config_user) }
|
||
|
|
}
|
||
|
|
}
|
||
|
|
pgcat_cfg["general"]["port"] = pgcat.port
|
||
|
|
pgcat.update_config(pgcat_cfg)
|
||
|
|
pgcat.start
|
||
|
|
|
||
|
|
pgcat.wait_until_ready(
|
||
|
|
pgcat.connection_string(
|
||
|
|
"sharded_db",
|
||
|
|
pg_user['username'],
|
||
|
|
pg_user['password']
|
||
|
|
)
|
||
|
|
) if wait_until_ready
|
||
|
|
|
||
|
|
OpenStruct.new.tap do |struct|
|
||
|
|
struct.pgcat = pgcat
|
||
|
|
struct.primary = primary
|
||
|
|
struct.replicas = [replica]
|
||
|
|
struct.all_databases = [primary]
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
def self.two_pools_auth_query(
|
||
|
|
pg_user:,
|
||
|
|
config_user:,
|
||
|
|
pool_names:,
|
||
|
|
extra_conf: {},
|
||
|
|
log_level: 'debug'
|
||
|
|
)
|
||
|
|
|
||
|
|
user = {
|
||
|
|
"pool_size" => 10,
|
||
|
|
"statement_timeout" => 0,
|
||
|
|
}
|
||
|
|
|
||
|
|
pgcat = PgcatProcess.new(log_level)
|
||
|
|
pgcat_cfg = pgcat.current_config
|
||
|
|
|
||
|
|
primary = PgInstance.new(5432, pg_user["username"], pg_user["password"], "shard0")
|
||
|
|
replica = PgInstance.new(10432, pg_user["username"], pg_user["password"], "shard0")
|
||
|
|
|
||
|
|
pool_template = Proc.new do |database|
|
||
|
|
{
|
||
|
|
"default_role" => "any",
|
||
|
|
"pool_mode" => "transaction",
|
||
|
|
"load_balancing_mode" => "random",
|
||
|
|
"primary_reads_enabled" => false,
|
||
|
|
"query_parser_enabled" => false,
|
||
|
|
"sharding_function" => "pg_bigint_hash",
|
||
|
|
"shards" => {
|
||
|
|
"0" => {
|
||
|
|
"database" => database,
|
||
|
|
"servers" => [
|
||
|
|
["localhost", primary.port.to_s, "primary"],
|
||
|
|
["localhost", replica.port.to_s, "replica"],
|
||
|
|
]
|
||
|
|
},
|
||
|
|
},
|
||
|
|
"users" => { "0" => user.merge(config_user) }
|
||
|
|
}
|
||
|
|
end
|
||
|
|
# Main proxy configs
|
||
|
|
pgcat_cfg["pools"] = {
|
||
|
|
"#{pool_names[0]}" => pool_template.call("shard0"),
|
||
|
|
"#{pool_names[1]}" => pool_template.call("shard1")
|
||
|
|
}
|
||
|
|
|
||
|
|
pgcat_cfg["general"]["port"] = pgcat.port
|
||
|
|
pgcat.update_config(pgcat_cfg.deep_merge(extra_conf))
|
||
|
|
pgcat.start
|
||
|
|
|
||
|
|
pgcat.wait_until_ready(pgcat.connection_string("sharded_db0", pg_user['username'], pg_user['password']))
|
||
|
|
|
||
|
|
OpenStruct.new.tap do |struct|
|
||
|
|
struct.pgcat = pgcat
|
||
|
|
struct.primary = primary
|
||
|
|
struct.replicas = [replica]
|
||
|
|
struct.all_databases = [primary]
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
def self.create_query_auth_function(user)
|
||
|
|
return <<-SQL
|
||
|
|
CREATE OR REPLACE FUNCTION public.user_lookup(in i_username text, out uname text, out phash text)
|
||
|
|
RETURNS record AS $$
|
||
|
|
BEGIN
|
||
|
|
SELECT usename, passwd FROM pg_catalog.pg_shadow
|
||
|
|
WHERE usename = i_username INTO uname, phash;
|
||
|
|
RETURN;
|
||
|
|
END;
|
||
|
|
$$ LANGUAGE plpgsql SECURITY DEFINER;
|
||
|
|
|
||
|
|
GRANT EXECUTE ON FUNCTION public.user_lookup(text) TO #{user};
|
||
|
|
SQL
|
||
|
|
end
|
||
|
|
|
||
|
|
def self.exec_in_instances(query:, instance_ports: [ 5432, 10432 ], database: 'postgres', user: 'postgres', password: 'postgres')
|
||
|
|
instance_ports.each do |port|
|
||
|
|
c = PG.connect("postgres://#{user}:#{password}@localhost:#{port}/#{database}")
|
||
|
|
c.exec(query)
|
||
|
|
c.close
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
def self.set_up_auth_query_for_user(user:, password:, instance_ports: [ 5432, 10432 ], database: 'shard0' )
|
||
|
|
instance_ports.each do |port|
|
||
|
|
connection = PG.connect("postgres://postgres:postgres@localhost:#{port}/#{database}")
|
||
|
|
connection.exec(self.drop_query_auth_function(user)) rescue PG::UndefinedFunction
|
||
|
|
connection.exec("DROP ROLE #{user}") rescue PG::UndefinedObject
|
||
|
|
connection.exec("CREATE ROLE #{user} ENCRYPTED PASSWORD '#{password}' LOGIN;")
|
||
|
|
connection.exec(self.create_query_auth_function(user))
|
||
|
|
connection.close
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
def self.tear_down_auth_query_for_user(user:, password:, instance_ports: [ 5432, 10432 ], database: 'shard0' )
|
||
|
|
instance_ports.each do |port|
|
||
|
|
connection = PG.connect("postgres://postgres:postgres@localhost:#{port}/#{database}")
|
||
|
|
connection.exec(self.drop_query_auth_function(user)) rescue PG::UndefinedFunction
|
||
|
|
connection.exec("DROP ROLE #{user}")
|
||
|
|
connection.close
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
def self.drop_query_auth_function(user)
|
||
|
|
return <<-SQL
|
||
|
|
REVOKE ALL ON FUNCTION public.user_lookup(text) FROM public, #{user};
|
||
|
|
DROP FUNCTION public.user_lookup(in i_username text, out uname text, out phash text);
|
||
|
|
SQL
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|