1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
//!
//! Fetch postgresql binaries
//!
//! Download and unpack postgresql binaries
//!
use archiver_rs::{
    Archive, Compressed,
};
use futures::future::BoxFuture;
use futures::{TryFutureExt};
use std::borrow::Borrow;
use std::path::{PathBuf, Path};

use crate::pg_errors::PgEmbedError;
use reqwest::Response;
use tokio::io::AsyncWriteExt;
use bytes::Bytes;
use crate::pg_enums::{OperationSystem, Architecture};


/// Postgresql version struct (simple version wrapper)
pub struct PostgresVersion(
    pub &'static str,
);

/// Latest postgres version 13
pub const PG_V13: PostgresVersion =
    PostgresVersion("13.2.0");
/// Latest postgres version 12
pub const PG_V12: PostgresVersion =
    PostgresVersion("12.6.0");
/// Latest pstgres version 11
pub const PG_V11: PostgresVersion =
    PostgresVersion("11.11.0");
/// Latest postgres version 10
pub const PG_V10: PostgresVersion =
    PostgresVersion("10.16.0");
/// Latest postgres version 9
pub const PG_V9: PostgresVersion =
    PostgresVersion("9.6.21");

/// Settings that determine the postgres binary to be fetched
pub struct PgFetchSettings {
    /// The repository host
    pub host: String,
    /// The operation system
    pub operating_system:
    OperationSystem,
    /// The cpu architecture
    pub architecture: Architecture,
    /// The postgresql version
    pub version: PostgresVersion,
}

impl Default for PgFetchSettings {
    fn default() -> Self {
        PgFetchSettings {
            host: "https://repo1.maven.org".to_string(),
            operating_system: OperationSystem::default(),
            architecture: Architecture::default(),
            version: PG_V13,
        }
    }
}

impl PgFetchSettings {
    /// The platform string (*needed to determine the download path*)
    pub fn platform(&self) -> String {
        let os = self
            .operating_system
            .to_string();
        let arch =
            if self.operating_system == OperationSystem::AlpineLinux {
                format!("{}-{}", self.architecture.to_string(), "alpine")
            } else { self.architecture.to_string() };
        format!("{}-{}", os, arch)
    }

    ///
    /// Fetch postgres binaries
    ///
    /// Returns the data of the downloaded binary in an `Ok([u8])` on success, otherwise returns an error.
    ///
    pub async fn fetch_postgres(&self) -> Result<Box<Bytes>, PgEmbedError>
    {
        let platform = &self.platform();
        let version = self.version.0;
        let download_url = format!(
            "{}/maven2/io/zonky/test/postgres/embedded-postgres-binaries-{}/{}/embedded-postgres-binaries-{}-{}.jar",
            &self.host,
            &platform,
            version,
            &platform,
            version);
        let mut response: Response =
            reqwest::get(download_url).map_err(|e|
                { PgEmbedError::DownloadFailure(e) })
                .await?;

        let content: Bytes = response.bytes().map_err(|e| PgEmbedError::ConversionFailure(e))
            .await?;

        Ok(Box::new(content))
    }
}