diff --git a/aptly-rest/src/lib.rs b/aptly-rest/src/lib.rs index db47d45..b2e1107 100644 --- a/aptly-rest/src/lib.rs +++ b/aptly-rest/src/lib.rs @@ -5,6 +5,7 @@ use api::{ repos::{Repo, RepoApi}, snapshots::{Snapshot, SnapshotApi}, }; +use reqwest::header; use serde::{Deserialize, Serialize}; use thiserror::Error; use url::Url; @@ -19,6 +20,8 @@ pub mod utils; pub enum AptlyRestError { #[error("Http Request failed {0}")] Request(#[from] reqwest::Error), + #[error("Invalid authentication token {0}")] + InvalidAuthToken(#[from] header::InvalidHeaderValue), } #[derive(Debug, Clone)] @@ -35,6 +38,18 @@ impl AptlyRest { } } + pub fn new_with_token(url: Url, token: &str) -> Result { + let mut headers = header::HeaderMap::new(); + headers.insert(header::AUTHORIZATION, format!("Bearer {token}").parse()?); + + Ok(Self { + client: reqwest::ClientBuilder::new() + .default_headers(headers) + .build()?, + url, + }) + } + pub async fn version(&self) -> Result { let mut url = self.url.clone(); url.path_segments_mut().unwrap().extend(&["api", "version"]); diff --git a/aptlyctl/Cargo.toml b/aptlyctl/Cargo.toml index 33174fb..3ec784d 100644 --- a/aptlyctl/Cargo.toml +++ b/aptlyctl/Cargo.toml @@ -8,7 +8,7 @@ edition = "2021" [dependencies] aptly-rest = { path = "../aptly-rest", version = "0.1.0" } aptly-rest-mock = { version = "0.0.1", path = "../aptly-rest-mock" } -clap = { version = "4", features = ["derive"] } +clap = { version = "4", features = ["derive", "env"] } color-eyre = "0.6.2" http = "0.2.9" serde_json = "1.0.83" diff --git a/aptlyctl/src/main.rs b/aptlyctl/src/main.rs index c7badd6..2e14e2c 100644 --- a/aptlyctl/src/main.rs +++ b/aptlyctl/src/main.rs @@ -47,9 +47,12 @@ enum Command { struct Opts { #[clap(subcommand)] command: Command, - /// Url for the aptly rest api endpoint + /// Url for the aptly rest API endpoint #[clap(short, long, default_value = "http://localhost:8080")] url: url::Url, + /// Authentication token for the API + #[clap(short, long, env = "APTLY_AUTH_TOKEN")] + auth_token: Option, } #[tokio::main] @@ -60,7 +63,11 @@ async fn main() -> Result { .init(); color_eyre::install().unwrap(); let opts = Opts::parse(); - let aptly = AptlyRest::new(opts.url); + let aptly = if let Some(token) = opts.auth_token { + AptlyRest::new_with_token(opts.url, &token)? + } else { + AptlyRest::new(opts.url) + }; match opts.command { Command::Repo { command } => command.run(&aptly).await, diff --git a/aptlyctl/src/repo.rs b/aptlyctl/src/repo.rs index 0981648..12b16e4 100644 --- a/aptlyctl/src/repo.rs +++ b/aptlyctl/src/repo.rs @@ -101,12 +101,13 @@ impl RepoCommand { RepoCommand::TestExists(args) => { if let Err(err) = aptly.repo(&args.repo).get().await { - let AptlyRestError::Request(err) = err; - if err.status() == Some(StatusCode::NOT_FOUND) { - return Ok(ExitCode::FAILURE); - } else { - return Err(err.into()); + if let AptlyRestError::Request(err) = &err { + if err.status() == Some(StatusCode::NOT_FOUND) { + return Ok(ExitCode::FAILURE); + } } + + return Err(err.into()); } } diff --git a/aptlyctl/src/snapshot.rs b/aptlyctl/src/snapshot.rs index 3a30d91..e973596 100644 --- a/aptlyctl/src/snapshot.rs +++ b/aptlyctl/src/snapshot.rs @@ -29,12 +29,13 @@ impl SnapshotCommand { match self { SnapshotCommand::TestExists(args) => { if let Err(err) = aptly.snapshot(&args.snapshot).get().await { - let AptlyRestError::Request(err) = err; - if err.status() == Some(StatusCode::NOT_FOUND) { - return Ok(ExitCode::FAILURE); - } else { - return Err(err.into()); + if let AptlyRestError::Request(err) = &err { + if err.status() == Some(StatusCode::NOT_FOUND) { + return Ok(ExitCode::FAILURE); + } } + + return Err(err.into()); } } SnapshotCommand::Drop(args) => { diff --git a/obs2aptly/Cargo.toml b/obs2aptly/Cargo.toml index 03942cd..a7c8f96 100644 --- a/obs2aptly/Cargo.toml +++ b/obs2aptly/Cargo.toml @@ -12,7 +12,7 @@ tokio = { version = "1.19.2", features = ["full"] } tokio-util = { version = "0.7.3", features = ["compat"] } async-walkdir = "0.2.0" -clap = { version = "4", features = ["derive"] } +clap = { version = "4", features = ["derive", "env"] } debian-packaging = "0.15.0" futures = "0.3.21" walker = "1.0.1" diff --git a/obs2aptly/src/lib.rs b/obs2aptly/src/lib.rs index 71f7b79..6558fca 100644 --- a/obs2aptly/src/lib.rs +++ b/obs2aptly/src/lib.rs @@ -860,9 +860,10 @@ impl SyncActions { const DIR: &str = "obs2aptly"; if let Err(err) = self.aptly.files().directory(DIR.to_owned()).delete().await { - let AptlyRestError::Request(inner) = &err; - if inner.status() != Some(http::StatusCode::NOT_FOUND) { - return Err(err.into()); + if let AptlyRestError::Request(inner) = &err { + if inner.status() != Some(http::StatusCode::NOT_FOUND) { + return Err(err.into()); + } } } diff --git a/obs2aptly/src/main.rs b/obs2aptly/src/main.rs index 6b46b85..1676ded 100644 --- a/obs2aptly/src/main.rs +++ b/obs2aptly/src/main.rs @@ -13,6 +13,9 @@ struct Opts { /// Url for the aptly rest api endpoint #[clap(short, long, default_value = "http://localhost:8080")] url: url::Url, + /// Authentication token for the API + #[clap(short, long, env = "APTLY_AUTH_TOKEN")] + auth_token: Option, /// Repo in aptly aptly_repo: String, /// Directory with obs repositories @@ -30,7 +33,11 @@ async fn main() -> Result<()> { .init(); color_eyre::install().unwrap(); let opts = Opts::parse(); - let aptly = AptlyRest::new(opts.url); + let aptly = if let Some(token) = opts.auth_token { + AptlyRest::new_with_token(opts.url, &token)? + } else { + AptlyRest::new(opts.url) + }; let aptly_contents = AptlyContent::new_from_aptly(&aptly, opts.aptly_repo).await?; let obs_content = ObsContent::new_from_path(opts.obs_repo).await?;