Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions pgdog/src/admin/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ pub enum Error {

#[error("address is not valid")]
InvalidAddress,

#[error("{0}")]
Toml(#[from] toml::ser::Error),
}

impl From<crate::backend::Error> for Error {
Expand Down
1 change: 1 addition & 0 deletions pgdog/src/admin/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub mod setup_schema;
pub mod show_client_memory;
pub mod show_clients;
pub mod show_config;
pub mod show_config_file;
pub mod show_instance_id;
pub mod show_lists;
pub mod show_mirrors;
Expand Down
38 changes: 31 additions & 7 deletions pgdog/src/admin/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ use super::{
prelude::Message, probe::Probe, reconnect::Reconnect, reload::Reload,
reset_query_cache::ResetQueryCache, set::Set, setup_schema::SetupSchema,
show_client_memory::ShowClientMemory, show_clients::ShowClients, show_config::ShowConfig,
show_instance_id::ShowInstanceId, show_lists::ShowLists, show_mirrors::ShowMirrors,
show_peers::ShowPeers, show_pools::ShowPools, show_prepared_statements::ShowPreparedStatements,
show_query_cache::ShowQueryCache, show_replication::ShowReplication,
show_server_memory::ShowServerMemory, show_servers::ShowServers, show_stats::ShowStats,
show_transactions::ShowTransactions, show_version::ShowVersion, shutdown::Shutdown, Command,
Error,
show_config_file::ShowConfigFile, show_instance_id::ShowInstanceId, show_lists::ShowLists,
show_mirrors::ShowMirrors, show_peers::ShowPeers, show_pools::ShowPools,
show_prepared_statements::ShowPreparedStatements, show_query_cache::ShowQueryCache,
show_replication::ShowReplication, show_server_memory::ShowServerMemory,
show_servers::ShowServers, show_stats::ShowStats, show_transactions::ShowTransactions,
show_version::ShowVersion, shutdown::Shutdown, Command, Error,
};

use tracing::debug;
Expand All @@ -23,6 +23,7 @@ pub enum ParseResult {
Reload(Reload),
ShowPools(ShowPools),
ShowConfig(ShowConfig),
ShowConfigFile(ShowConfigFile),
ShowServers(ShowServers),
ShowPeers(ShowPeers),
ShowQueryCache(ShowQueryCache),
Expand Down Expand Up @@ -58,6 +59,7 @@ impl ParseResult {
Reload(reload) => reload.execute().await,
ShowPools(show_pools) => show_pools.execute().await,
ShowConfig(show_config) => show_config.execute().await,
ShowConfigFile(show_config_file) => show_config_file.execute().await,
ShowServers(show_servers) => show_servers.execute().await,
ShowPeers(show_peers) => show_peers.execute().await,
ShowQueryCache(show_query_cache) => show_query_cache.execute().await,
Expand Down Expand Up @@ -93,6 +95,7 @@ impl ParseResult {
Reload(reload) => reload.name(),
ShowPools(show_pools) => show_pools.name(),
ShowConfig(show_config) => show_config.name(),
ShowConfigFile(show_config_file) => show_config_file.name(),
ShowServers(show_servers) => show_servers.name(),
ShowPeers(show_peers) => show_peers.name(),
ShowQueryCache(show_query_cache) => show_query_cache.name(),
Expand Down Expand Up @@ -137,7 +140,22 @@ impl Parser {
"show" => match iter.next().ok_or(Error::Syntax)?.trim() {
"clients" => ParseResult::ShowClients(ShowClients::parse(&sql)?),
"pools" => ParseResult::ShowPools(ShowPools::parse(&sql)?),
"config" => ParseResult::ShowConfig(ShowConfig::parse(&sql)?),
"config" => {
let next_keyword = iter.clone().find_map(|token| {
let trimmed = token.trim();
if trimmed.is_empty() {
None
} else {
Some(trimmed)
}
});

if next_keyword == Some("file") {
ParseResult::ShowConfigFile(ShowConfigFile::parse(&sql)?)
} else {
ParseResult::ShowConfig(ShowConfig::parse(&sql)?)
}
}
"servers" => ParseResult::ShowServers(ShowServers::parse(&sql)?),
"server" => match iter.next().ok_or(Error::Syntax)?.trim() {
"memory" => ParseResult::ShowServerMemory(ShowServerMemory::parse(&sql)?),
Expand Down Expand Up @@ -229,4 +247,10 @@ mod tests {
let result = Parser::parse("SHOW CLIENT MEMORY;");
assert!(matches!(result, Ok(ParseResult::ShowClientMemory(_))));
}

#[test]
fn parses_show_config_file_command() {
let result = Parser::parse("SHOW CONFIG FILE;");
assert!(matches!(result, Ok(ParseResult::ShowConfigFile(_))));
}
}
55 changes: 55 additions & 0 deletions pgdog/src/admin/show_config_file.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//! SHOW CONFIG FILE command.

use crate::config::config;

use super::prelude::*;

pub struct ShowConfigFile;

#[async_trait]
impl Command for ShowConfigFile {
fn name(&self) -> String {
"SHOW".into()
}

fn parse(_sql: &str) -> Result<Self, Error> {
Ok(Self {})
}

async fn execute(&self) -> Result<Vec<Message>, Error> {
let config = config();
let snapshot = sanitize_for_toml(config.config.clone());
let toml = toml::to_string_pretty(&snapshot)?;

let mut messages = vec![RowDescription::new(&[Field::text("pgdog.toml")]).message()?];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might as well show both of them, either as rows or columns.


let mut row = DataRow::new();
row.add(&toml);
messages.push(row.message()?);

Ok(messages)
}
}

fn sanitize_for_toml(mut config: crate::config::Config) -> crate::config::Config {
let max_i64 = i64::MAX as u64;
let max_i64_usize = i64::MAX as usize;

if config.general.client_idle_timeout > max_i64 {
config.general.client_idle_timeout = max_i64;
}

if config.general.query_timeout > max_i64 {
config.general.query_timeout = max_i64;
}

if config.general.lsn_check_delay > max_i64 {
config.general.lsn_check_delay = max_i64;
}

if config.general.prepared_statements_limit > max_i64_usize {
config.general.prepared_statements_limit = max_i64_usize;
}

config
}
86 changes: 86 additions & 0 deletions pgdog/src/admin/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::net::messages::{DataRow, DataType, FromBytes, Protocol, RowDescriptio

use super::show_client_memory::ShowClientMemory;
use super::show_config::ShowConfig;
use super::show_config_file::ShowConfigFile;
use super::show_lists::ShowLists;
use super::show_mirrors::ShowMirrors;
use super::show_pools::ShowPools;
Expand Down Expand Up @@ -197,6 +198,91 @@ async fn show_config_pretty_prints_general_settings() {
assert_eq!(connect_timeout, "2s");
}

#[tokio::test(flavor = "current_thread")]
async fn show_config_file_dumps_live_state_as_toml() {
let context = TestAdminContext::new();

let mut config = ConfigAndUsers::default();
config.config.general.default_pool_size = 11;
config.config.general.connect_timeout = 7_000;
config.config.general.log_connections = true;
config.config.general.tls_client_required = true;
config.config.databases.push(Database {
name: "app".into(),
host: "127.0.0.1".into(),
database_name: Some("postgres".into()),
user: Some("postgres".into()),
password: Some("hunter2".into()),
shard: 0,
..Default::default()
});

context.set_config(config);

let command = ShowConfigFile;
let messages = command
.execute()
.await
.expect("show config file execution failed");

assert_eq!(messages.len(), 2, "expected row description plus data row");

let row_description = RowDescription::from_bytes(messages[0].payload())
.expect("row description message should parse");
let columns: Vec<&str> = row_description
.fields
.iter()
.map(|field| field.name.as_str())
.collect();
assert_eq!(columns, vec!["pgdog.toml"]);
assert_eq!(row_description.fields[0].data_type(), DataType::Text);

let row = DataRow::from_bytes(messages[1].payload()).expect("data row should parse");
let payload = row.get_text(0).expect("toml payload should be text");

let actual_value: toml::Value = payload
.parse()
.expect("payload should parse back into toml value");

let general = actual_value
.get("general")
.and_then(|value| value.as_table())
.expect("general section should exist and be a table");
assert_eq!(
general
.get("default_pool_size")
.and_then(|v| v.as_integer()),
Some(11)
);
assert_eq!(
general.get("connect_timeout").and_then(|v| v.as_integer()),
Some(7_000)
);
assert_eq!(
general.get("log_connections").and_then(|v| v.as_bool()),
Some(true)
);
assert_eq!(
general.get("tls_client_required").and_then(|v| v.as_bool()),
Some(true)
);

let databases = actual_value
.get("databases")
.and_then(|value| value.as_array())
.expect("databases array should be present");
assert_eq!(databases.len(), 1);

let database = databases[0]
.as_table()
.expect("database entry should be a table");
assert_eq!(database.get("name").and_then(|v| v.as_str()), Some("app"));
assert_eq!(
database.get("password").and_then(|v| v.as_str()),
Some("hunter2")
);
}

#[tokio::test(flavor = "current_thread")]
async fn show_mirrors_reports_counts() {
let context = TestAdminContext::new();
Expand Down
Loading