From 918b42a28bcc289011410fa80c02f6d71908c541 Mon Sep 17 00:00:00 2001 From: brianheineman Date: Sat, 17 Feb 2024 21:31:16 -0700 Subject: [PATCH 1/3] refactor: update psql to manage setting the PGPASSWORD environment variable when pg_password is set --- Cargo.lock | 19 ++++++++++--------- postgresql_embedded/src/command/psql.rs | 20 +++++++++++++++++++- postgresql_embedded/src/command/traits.rs | 11 ++++++++++- postgresql_embedded/src/postgresql.rs | 7 +++---- 4 files changed, 42 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ad192f4..06b5b8d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -105,9 +105,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "d32a994c2b3ca201d9b263612a374263f05e7adde37c4707f693dcd375076d1f" [[package]] name = "bytes" @@ -369,9 +369,9 @@ checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" [[package]] name = "hermit-abi" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c62115964e08cb8039170eb33c1d0e2388a256930279edca206fff675f82c3" +checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd" [[package]] name = "hex" @@ -826,16 +826,17 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.7" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", + "cfg-if", "getrandom", "libc", "spin", "untrusted", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1006,9 +1007,9 @@ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "syn" -version = "2.0.48" +version = "2.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "915aea9e586f80826ee59f8453c1101f9d1c4b3964cd2460185ee8e299ada496" dependencies = [ "proc-macro2", "quote", diff --git a/postgresql_embedded/src/command/psql.rs b/postgresql_embedded/src/command/psql.rs index 6ccc48e..f440c8f 100644 --- a/postgresql_embedded/src/command/psql.rs +++ b/postgresql_embedded/src/command/psql.rs @@ -41,6 +41,7 @@ pub struct PsqlBuilder { username: Option, no_password: bool, password: bool, + pg_password: Option, } impl PsqlBuilder { @@ -267,6 +268,12 @@ impl PsqlBuilder { self.password = true; self } + + /// database user name + pub fn pg_password>(mut self, pg_password: S) -> Self { + self.pg_password = Some(pg_password.as_ref().to_os_string()); + self + } } impl CommandBuilder for PsqlBuilder { @@ -440,6 +447,16 @@ impl CommandBuilder for PsqlBuilder { args } + + fn get_envs(&self) -> Vec<(OsString, OsString)> { + let mut envs: Vec<(OsString, OsString)> = Vec::new(); + + if let Some(password) = &self.pg_password { + envs.push(("PGPASSWORD".into(), password.into())); + } + + envs + } } #[cfg(test)] @@ -496,10 +513,11 @@ mod tests { .username("postgres") .no_password() .password() + .pg_password("password") .build(); assert_eq!( - r#""psql" "--command" "SELECT * FROM test" "--dbname" "dbname" "--file" "test.sql" "--list" "--variable" "ON_ERROR_STOP=1" "--version" "--no-psqlrc" "--single-transaction" "--help" "options" "--echo-all" "--echo-errors" "--echo-queries" "--echo-hidden" "--log-file" "psql.log" "--no-readline" "--output" "output.txt" "--quiet" "--single-step" "--single-line" "--no-align" "--csv" "--field-separator" "|" "--html" "--pset" "border=1" "--record-separator" "\n" "--tuples-only" "--table-attr" "width=100" "--expanded" "--field-separator-zero" "--record-separator-zero" "--host" "localhost" "--port" "5432" "--username" "postgres" "--no-password" "--password""#, + r#"PGPASSWORD="password" "psql" "--command" "SELECT * FROM test" "--dbname" "dbname" "--file" "test.sql" "--list" "--variable" "ON_ERROR_STOP=1" "--version" "--no-psqlrc" "--single-transaction" "--help" "options" "--echo-all" "--echo-errors" "--echo-queries" "--echo-hidden" "--log-file" "psql.log" "--no-readline" "--output" "output.txt" "--quiet" "--single-step" "--single-line" "--no-align" "--csv" "--field-separator" "|" "--html" "--pset" "border=1" "--record-separator" "\n" "--tuples-only" "--table-attr" "width=100" "--expanded" "--field-separator-zero" "--record-separator-zero" "--host" "localhost" "--port" "5432" "--username" "postgres" "--no-password" "--password""#, command.to_command_string() ); } diff --git a/postgresql_embedded/src/command/traits.rs b/postgresql_embedded/src/command/traits.rs index 5fc8d7b..466a7f1 100644 --- a/postgresql_embedded/src/command/traits.rs +++ b/postgresql_embedded/src/command/traits.rs @@ -23,7 +23,14 @@ pub trait CommandBuilder { } /// Get the arguments for the command - fn get_args(&self) -> Vec; + fn get_args(&self) -> Vec { + vec![] + } + + /// Get the environment variables for the command + fn get_envs(&self) -> Vec<(OsString, OsString)> { + vec![] + } /// Build a standard Command fn build(self) -> std::process::Command @@ -34,6 +41,7 @@ pub trait CommandBuilder { let mut command = std::process::Command::new(program_file); command.args(self.get_args()); + command.envs(self.get_envs()); command } @@ -47,6 +55,7 @@ pub trait CommandBuilder { let mut command = tokio::process::Command::new(program_file); command.args(self.get_args()); + command.envs(self.get_envs()); command } } diff --git a/postgresql_embedded/src/postgresql.rs b/postgresql_embedded/src/postgresql.rs index 78d1919..a8508ed 100644 --- a/postgresql_embedded/src/postgresql.rs +++ b/postgresql_embedded/src/postgresql.rs @@ -338,6 +338,7 @@ impl PostgreSQL { .host(&self.settings.host) .port(self.settings.port) .username(&self.settings.username) + .pg_password(&self.settings.password) .no_psqlrc() .no_align() .tuples_only(); @@ -373,6 +374,7 @@ impl PostgreSQL { .host(&self.settings.host) .port(self.settings.port) .username(&self.settings.username) + .pg_password(&self.settings.password) .no_psqlrc() .no_align() .tuples_only(); @@ -403,6 +405,7 @@ impl PostgreSQL { .host(&self.settings.host) .port(self.settings.port) .username(&self.settings.username) + .pg_password(&self.settings.password) .no_psqlrc() .no_align() .tuples_only(); @@ -428,8 +431,6 @@ impl PostgreSQL { command_builder: B, ) -> Result<(String, String)> { let mut command = command_builder.build(); - // TODO: move this into the command builder - command.env("PGPASSWORD", &self.settings.password); command.execute(self.settings.timeout).await } @@ -440,8 +441,6 @@ impl PostgreSQL { command_builder: B, ) -> Result<(String, String)> { let mut command = command_builder.build_tokio(); - // TODO: move this into the command builder - command.env("PGPASSWORD", &self.settings.password); command.execute(self.settings.timeout).await } } From b5d884498bb7c0da2c10c890de59a749c5a3d3db Mon Sep 17 00:00:00 2001 From: brianheineman Date: Sat, 17 Feb 2024 21:49:17 -0700 Subject: [PATCH 2/3] test: add CommandBuilder test coverage --- postgresql_embedded/src/command/traits.rs | 39 +++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/postgresql_embedded/src/command/traits.rs b/postgresql_embedded/src/command/traits.rs index 466a7f1..227e267 100644 --- a/postgresql_embedded/src/command/traits.rs +++ b/postgresql_embedded/src/command/traits.rs @@ -156,9 +156,32 @@ mod test { use super::*; use test_log::test; + #[test] + fn test_command_builder_defaults() { + struct DefaultCommandBuilder { + program_dir: Option, + } + + impl CommandBuilder for DefaultCommandBuilder { + fn get_program(&self) -> &'static OsStr { + "test".as_ref() + } + + fn get_program_dir(&self) -> &Option { + &self.program_dir + } + } + + let builder = DefaultCommandBuilder { program_dir: None }; + let command = builder.build(); + + assert_eq!(r#""test""#, command.to_command_string()); + } + struct TestCommandBuilder { program_dir: Option, args: Vec, + envs: Vec<(OsString, OsString)>, } impl CommandBuilder for TestCommandBuilder { @@ -173,6 +196,10 @@ mod test { fn get_args(&self) -> Vec { self.args.clone() } + + fn get_envs(&self) -> Vec<(OsString, OsString)> { + self.envs.clone() + } } #[test] @@ -180,11 +207,15 @@ mod test { let builder = TestCommandBuilder { program_dir: None, args: vec!["--help".to_string().into()], + envs: vec![(OsString::from("PASSWORD"), OsString::from("foo"))], }; let command = builder.build(); assert_eq!( - format!(r#""{}" "--help""#, PathBuf::from("test").to_string_lossy()), + format!( + r#"PASSWORD="foo" "{}" "--help""#, + PathBuf::from("test").to_string_lossy() + ), command.to_command_string() ); } @@ -195,11 +226,15 @@ mod test { let builder = TestCommandBuilder { program_dir: None, args: vec!["--help".to_string().into()], + envs: vec![(OsString::from("PASSWORD"), OsString::from("foo"))], }; let command = builder.build_tokio(); assert_eq!( - format!(r#""{}" "--help""#, PathBuf::from("test").to_string_lossy()), + format!( + r#"PASSWORD="foo" "{}" "--help""#, + PathBuf::from("test").to_string_lossy() + ), command.to_command_string() ); } From 0137a2e211e51ed51698b0412c5abd89de296100 Mon Sep 17 00:00:00 2001 From: brianheineman Date: Sat, 17 Feb 2024 22:01:38 -0700 Subject: [PATCH 3/3] docs: update docs for new functions --- postgresql_embedded/src/command/psql.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/postgresql_embedded/src/command/psql.rs b/postgresql_embedded/src/command/psql.rs index f440c8f..0e973a2 100644 --- a/postgresql_embedded/src/command/psql.rs +++ b/postgresql_embedded/src/command/psql.rs @@ -269,7 +269,7 @@ impl PsqlBuilder { self } - /// database user name + /// user password pub fn pg_password>(mut self, pg_password: S) -> Self { self.pg_password = Some(pg_password.as_ref().to_os_string()); self @@ -448,6 +448,7 @@ impl CommandBuilder for PsqlBuilder { args } + /// Get the environment variables for the command fn get_envs(&self) -> Vec<(OsString, OsString)> { let mut envs: Vec<(OsString, OsString)> = Vec::new();