postgres_service/
lib.rs

1//! Parse Postgres service configuration files
2//!
3//! [Postgres service files](https://www.postgresql.org/docs/current/libpq-pgservice.html)
4//! are configuration files that contain connection parameters
5//!
6//! # Example
7//!
8//! ```rust
9//! # fn _norun() {
10//! postgres_service::load_connect_params("mydb")
11//!    .expect("reading postgres service")
12//!    .user("username") // optionally override the username
13//!    .connect(postgres::NoTls)
14//!    .expect("connecting to postgres");
15//! # }
16//! ```
17
18use ini::Properties;
19
20fn build_from_section(section: &Properties) -> tokio_postgres::config::Config {
21	let mut username: Option<String> = None;
22	let mut password: Option<String> = None;
23
24	let mut builder = tokio_postgres::config::Config::new();
25	let mut options = String::new();
26
27	for (k, v) in section.iter() {
28		match k {
29			"host" => {
30				builder.host(v);
31			}
32			"hostaddr" => {
33				builder.host(v);
34			}
35			"port" => {
36				builder.port(v.parse().unwrap());
37			}
38			"dbname" => {
39				builder.dbname(v);
40			}
41			"user" => username = Some(v.to_owned()),
42			"password" => password = Some(v.to_owned()),
43			_ => options += &format!("{}={} ", k, v),
44		}
45	}
46
47	if !options.is_empty() {
48		builder.options(&options);
49	}
50
51	if let Some(username) = username {
52		builder.user(&username);
53	}
54	if let Some(password) = password {
55		builder.password(&password);
56	}
57
58	builder
59}
60
61/// Load connection parameters for the named Postgresql service
62pub fn load_connect_params(service_name: &str) -> Option<postgres::config::Config> {
63	tokio::load_connect_params(service_name).map(Into::into)
64}
65
66/// For use with tokio-postgres
67pub mod tokio {
68	use crate::build_from_section;
69	use ini::Ini;
70	/// Load connection parameters for the named Postgresql service
71	pub fn load_connect_params(service_name: &str) -> Option<tokio_postgres::config::Config> {
72		if let Ok(home) = std::env::var("HOME") {
73			if let Ok(ini) = Ini::load_from_file(home + "/" + ".pg_service.conf") {
74				if let Some(section) = ini.section(Some(service_name)) {
75					return Some(build_from_section(section));
76				}
77			}
78		}
79
80		let confdir = std::env::var("PGSYSCONFDIR").unwrap_or("/etc/postgresql-common".into());
81
82		if let Ok(ini) = Ini::load_from_file(confdir + "/" + "pg_service.conf") {
83			if let Some(section) = ini.section(Some(service_name)) {
84				return Some(build_from_section(section));
85			}
86		}
87
88		None
89	}
90}