LCOV - code coverage report
Current view: top level - libs/postgres_ffi/wal_craft/src/bin - wal_craft.rs (source / functions) Coverage Total Hit
Test: 1b0a6a0c05cee5a7de360813c8034804e105ce1c.info Lines: 47.9 % 121 58
Test Date: 2025-03-12 00:01:28 Functions: 40.0 % 5 2

            Line data    Source code
       1              : use std::path::PathBuf;
       2              : use std::str::FromStr;
       3              : 
       4              : use anyhow::*;
       5              : use clap::{Arg, ArgMatches, Command, value_parser};
       6              : use postgres::Client;
       7              : use wal_craft::*;
       8              : 
       9            0 : fn main() -> Result<()> {
      10            0 :     env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("wal_craft=info"))
      11            0 :         .init();
      12            0 :     let arg_matches = cli().get_matches();
      13            0 : 
      14            0 :     let wal_craft = |arg_matches: &ArgMatches, client: &mut Client| {
      15            0 :         let intermediate_lsns = match arg_matches
      16            0 :             .get_one::<String>("type")
      17            0 :             .map(|s| s.as_str())
      18            0 :             .context("'type' is required")?
      19              :         {
      20            0 :             Simple::NAME => Simple::craft(client)?,
      21            0 :             LastWalRecordXlogSwitch::NAME => LastWalRecordXlogSwitch::craft(client)?,
      22            0 :             LastWalRecordXlogSwitchEndsOnPageBoundary::NAME => {
      23            0 :                 LastWalRecordXlogSwitchEndsOnPageBoundary::craft(client)?
      24              :             }
      25            0 :             WalRecordCrossingSegmentFollowedBySmallOne::NAME => {
      26            0 :                 WalRecordCrossingSegmentFollowedBySmallOne::craft(client)?
      27              :             }
      28            0 :             LastWalRecordCrossingSegment::NAME => LastWalRecordCrossingSegment::craft(client)?,
      29            0 :             a => panic!("Unknown --type argument: {a}"),
      30              :         };
      31            0 :         let end_of_wal_lsn = client.pg_current_wal_insert_lsn()?;
      32            0 :         for lsn in intermediate_lsns {
      33            0 :             println!("intermediate_lsn = {lsn}");
      34            0 :         }
      35            0 :         println!("end_of_wal = {end_of_wal_lsn}");
      36            0 :         Ok(())
      37            0 :     };
      38              : 
      39            0 :     match arg_matches.subcommand() {
      40            0 :         None => panic!("No subcommand provided"),
      41            0 :         Some(("print-postgres-config", _)) => {
      42            0 :             for cfg in REQUIRED_POSTGRES_CONFIG.iter() {
      43            0 :                 println!("{cfg}");
      44            0 :             }
      45            0 :             Ok(())
      46              :         }
      47              : 
      48            0 :         Some(("with-initdb", arg_matches)) => {
      49            0 :             let cfg = Conf {
      50            0 :                 pg_version: *arg_matches
      51            0 :                     .get_one::<u32>("pg-version")
      52            0 :                     .context("'pg-version' is required")?,
      53            0 :                 pg_distrib_dir: arg_matches
      54            0 :                     .get_one::<PathBuf>("pg-distrib-dir")
      55            0 :                     .context("'pg-distrib-dir' is required")?
      56            0 :                     .to_owned(),
      57            0 :                 datadir: arg_matches
      58            0 :                     .get_one::<PathBuf>("datadir")
      59            0 :                     .context("'datadir' is required")?
      60            0 :                     .to_owned(),
      61            0 :             };
      62            0 :             cfg.initdb()?;
      63            0 :             let srv = cfg.start_server()?;
      64            0 :             wal_craft(arg_matches, &mut srv.connect_with_timeout()?)?;
      65            0 :             srv.kill();
      66            0 :             Ok(())
      67              :         }
      68            0 :         Some(("in-existing", arg_matches)) => wal_craft(
      69            0 :             arg_matches,
      70            0 :             &mut postgres::Config::from_str(
      71            0 :                 arg_matches
      72            0 :                     .get_one::<String>("connection")
      73            0 :                     .context("'connection' is required")?,
      74              :             )
      75            0 :             .context(
      76            0 :                 "'connection' argument value could not be parsed as a postgres connection string",
      77            0 :             )?
      78            0 :             .connect(postgres::NoTls)?,
      79              :         ),
      80            0 :         Some(_) => panic!("Unknown subcommand"),
      81              :     }
      82            0 : }
      83              : 
      84            1 : fn cli() -> Command {
      85            1 :     let type_arg = &Arg::new("type")
      86            1 :         .help("Type of WAL to craft")
      87            1 :         .value_parser([
      88            1 :             Simple::NAME,
      89            1 :             LastWalRecordXlogSwitch::NAME,
      90            1 :             LastWalRecordXlogSwitchEndsOnPageBoundary::NAME,
      91            1 :             WalRecordCrossingSegmentFollowedBySmallOne::NAME,
      92            1 :             LastWalRecordCrossingSegment::NAME,
      93            1 :         ])
      94            1 :         .required(true);
      95            1 : 
      96            1 :     Command::new("Postgres WAL crafter")
      97            1 :         .about("Crafts Postgres databases with specific WAL properties")
      98            1 :         .subcommand(
      99            1 :             Command::new("print-postgres-config")
     100            1 :                 .about("Print the configuration required for PostgreSQL server before running this script")
     101            1 :         )
     102            1 :         .subcommand(
     103            1 :             Command::new("with-initdb")
     104            1 :                 .about("Craft WAL in a new data directory first initialized with initdb")
     105            1 :                 .arg(type_arg)
     106            1 :                 .arg(
     107            1 :                     Arg::new("datadir")
     108            1 :                         .help("Data directory for the Postgres server")
     109            1 :                         .value_parser(value_parser!(PathBuf))
     110            1 :                         .required(true)
     111            1 :                 )
     112            1 :                 .arg(
     113            1 :                     Arg::new("pg-distrib-dir")
     114            1 :                         .long("pg-distrib-dir")
     115            1 :                         .value_parser(value_parser!(PathBuf))
     116            1 :                         .help("Directory with Postgres distributions (bin and lib directories, e.g. pg_install containing subpath `v14/bin/postgresql`)")
     117            1 :                         .default_value("/usr/local")
     118            1 :                 )
     119            1 :                 .arg(
     120            1 :                     Arg::new("pg-version")
     121            1 :                     .long("pg-version")
     122            1 :                     .help("Postgres version to use for the initial tenant")
     123            1 :                     .value_parser(value_parser!(u32))
     124            1 :                     .required(true)
     125            1 : 
     126            1 :                 )
     127            1 :         )
     128            1 :         .subcommand(
     129            1 :             Command::new("in-existing")
     130            1 :                 .about("Craft WAL at an existing recently created Postgres database. Note that server may append new WAL entries on shutdown.")
     131            1 :                 .arg(type_arg)
     132            1 :                 .arg(
     133            1 :                     Arg::new("connection")
     134            1 :                         .help("Connection string to the Postgres database to populate")
     135            1 :                         .required(true)
     136            1 :                 )
     137            1 :         )
     138            1 : }
     139              : 
     140              : #[test]
     141            1 : fn verify_cli() {
     142            1 :     cli().debug_assert();
     143            1 : }
        

Generated by: LCOV version 2.1-beta