diff --git a/.gitignore b/.gitignore index 0168ef04..6f848019 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,6 @@ .cargo vendor/ publish +# Test generated files +bundled.wasm +locked.wasm diff --git a/crates/client/src/api.rs b/crates/client/src/api.rs index 758d7d74..a9bf6855 100644 --- a/crates/client/src/api.rs +++ b/crates/client/src/api.rs @@ -35,7 +35,6 @@ use warg_transparency::{ }; use crate::registry_url::RegistryUrl; - /// Represents an error that occurred while communicating with the registry. #[derive(Debug, Error)] pub enum ClientError { @@ -102,6 +101,9 @@ pub enum ClientError { /// Invalid upload HTTP method. #[error("server returned an invalid HTTP header `{0}: {1}`")] InvalidHttpHeader(String, String), + /// The provided log was not found with hint header. + #[error("log `{0}` was not found in this registry, but the registry provided the hint header: `{1:?}`")] + LogNotFoundWithHint(LogId, HeaderValue), /// An other error occurred during the requested operation. #[error(transparent)] Other(#[from] anyhow::Error), @@ -153,12 +155,29 @@ async fn into_result) -> RequestBuilder; +} + +impl WithWargHeader for RequestBuilder { + type Client = Client; + fn warg_header(self, registry_header: &Option) -> reqwest::RequestBuilder { + if let Some(reg) = registry_header { + let registry_header = HeaderName::try_from("warg-registry").unwrap(); + self.header(registry_header, reg) + } else { + self + } + } +} + /// Represents a Warg API client for communicating with /// a Warg registry server. pub struct Client { - home_url: RegistryUrl, + url: RegistryUrl, client: reqwest::Client, - namespace_registry: Option, + warg_header: Option, } impl Client { @@ -166,37 +185,31 @@ impl Client { pub fn new(url: impl IntoUrl) -> Result { let url = RegistryUrl::new(url)?; Ok(Self { - home_url: url, + url, client: reqwest::Client::new(), - namespace_registry: None, + warg_header: None, }) } /// Gets the URL of the API client. - pub fn home_url(&self) -> &RegistryUrl { - &self.home_url + pub fn url(&self) -> &RegistryUrl { + &self.url } /// Gets the latest checkpoint from the registry. pub async fn latest_checkpoint( &self, ) -> Result, ClientError> { - let url = self.home_url.join(paths::fetch_checkpoint()); + let url = self.url.join(paths::fetch_checkpoint()); tracing::debug!("getting latest checkpoint at `{url}`"); - if let Some(nm) = self.namespace_registry() { - let registry_header = HeaderName::try_from("warg-registry").unwrap(); - let header_val = HeaderValue::try_from(nm).unwrap(); - into_result::<_, FetchError>( - self.client - .get(url) - .header(registry_header, header_val) - .send() - .await?, - ) - .await - } else { - into_result::<_, FetchError>(reqwest::get(url).await?).await - } + into_result::<_, FetchError>( + self.client + .get(url) + .warg_header(self.get_warg_header()) + .send() + .await?, + ) + .await } /// Gets the latest checkpoints from registries. @@ -206,7 +219,7 @@ impl Client { ) -> Result>> { let mut timestamps = HashMap::new(); for reg in registries.into_iter() { - let url = self.home_url.join(paths::fetch_checkpoint()); + let url = self.url.join(paths::fetch_checkpoint()); let registry_header = HeaderName::try_from("warg-registry").unwrap(); let header_val = HeaderValue::try_from(reg).unwrap(); let res: SerdeEnvelope = into_result::<_, FetchError>( @@ -227,67 +240,43 @@ impl Client { &self, request: SerdeEnvelope, ) -> Result { - let url = self.home_url.join(paths::verify_checkpoint()); + let url = self.url.join(paths::verify_checkpoint()); tracing::debug!("verifying checkpoint at `{url}`"); - let response = self.client.post(url).json(&request).send().await?; + let response = self + .client + .post(url) + .json(&request) + .warg_header(self.get_warg_header()) + .send() + .await?; into_result::<_, MonitorError>(response).await } - /// Add warg header to request - pub fn warg_header( - &self, - namespace_registry: &Option, - req: RequestBuilder, - ) -> RequestBuilder { - if let Some(nm) = namespace_registry { - let registry_header = HeaderName::try_from("warg-registry").unwrap(); - let header_val = HeaderValue::try_from(nm).unwrap(); - req.header(registry_header, header_val) - } else { - req - } - } - /// Fetches package log entries from the registry. pub async fn fetch_logs( &self, request: FetchLogsRequest<'_>, ) -> Result { - let url = self.home_url.join(paths::fetch_logs()); + let url = self.url.join(paths::fetch_logs()); tracing::debug!("fetching logs at `{url}`"); let response = self - .warg_header(self.namespace_registry(), self.client.post(&url)) + .client + .post(&url) .json(&request) + .warg_header(self.get_warg_header()) .send() .await?; - if let Some(hint) = response.headers().get("Warg-Registry-Hint") { - let hint_reg = hint.to_str().unwrap().to_owned(); - let mut terms = hint_reg.split('='); - let namespace = terms.next(); - let registry = terms.next(); - if let (Some(namespace), Some(registry)) = (namespace, registry) { - print!( - "One of the packages you're requesting does not exist in the registry you're using. - However, the package namespace `{namespace}` does exist in the registry at {registry}.\nWould you like to configure your warg cli to use this registry for packages with this namespace in the future? y/N\n", - ); - std::io::Write::flush(&mut std::io::stdout()).expect("flush failed!"); - let mut buf = String::new(); - std::io::stdin().read_line(&mut buf).unwrap(); - let lowered = buf.to_lowercase(); - if lowered == "y" || lowered == "yes" { - return into_result::<_, FetchError>( - self.warg_header(&Some(hint_reg), self.client.post(url)) - .json(&request) - .send() - .await?, - ) - .await; + let header = response.headers().get("Warg-Registry-Hint").cloned(); + into_result::<_, FetchError>(response) + .await + .map_err(|err| match err { + ClientError::Fetch(FetchError::LogNotFound(log_id)) if header.is_some() => { + ClientError::LogNotFoundWithHint(log_id, header.unwrap()) } - } - } - into_result::<_, FetchError>(response).await + _ => err, + }) } /// Fetches package names from the registry. @@ -295,7 +284,7 @@ impl Client { &self, request: FetchPackageNamesRequest<'_>, ) -> Result { - let url = self.home_url.join(paths::fetch_package_names()); + let url = self.url.join(paths::fetch_package_names()); tracing::debug!("fetching package names at `{url}`"); let response = self.client.post(url).json(&request).send().await?; @@ -304,11 +293,17 @@ impl Client { /// Gets ledger sources from the registry. pub async fn ledger_sources(&self) -> Result { - let url = self.home_url.join(paths::ledger_sources()); + let url = self.url.join(paths::ledger_sources()); tracing::debug!("getting ledger sources at `{url}`"); - let response = reqwest::get(url).await?; - into_result::<_, LedgerError>(response).await + into_result::<_, LedgerError>( + self.client + .get(url) + .warg_header(self.get_warg_header()) + .send() + .await?, + ) + .await } /// Publish a new record to a package log. @@ -317,15 +312,17 @@ impl Client { log_id: &LogId, request: PublishRecordRequest<'_>, ) -> Result { - let url = self.home_url.join(&paths::publish_package_record(log_id)); + let url = self.url.join(&paths::publish_package_record(log_id)); tracing::debug!( "appending record to package `{name}` at `{url}`", name = request.package_name ); let response = self - .warg_header(&self.namespace_registry, self.client.post(url)) + .client + .post(url) .json(&request) + .warg_header(self.get_warg_header()) .send() .await?; into_result::<_, PackageError>(response).await @@ -337,23 +334,17 @@ impl Client { log_id: &LogId, record_id: &RecordId, ) -> Result { - let url = self - .home_url - .join(&paths::package_record(log_id, record_id)); + let url = self.url.join(&paths::package_record(log_id, record_id)); tracing::debug!("getting record `{record_id}` for package `{log_id}` at `{url}`"); - let response = if let Some(nm) = self.namespace_registry() { - let registry_header = HeaderName::try_from("warg-registry").unwrap(); - let header_val = HeaderValue::try_from(nm).unwrap(); + into_result::<_, PackageError>( self.client .get(url) - .header(registry_header, header_val) + .warg_header(self.get_warg_header()) .send() - .await? - } else { - reqwest::get(url).await? - }; - into_result::<_, PackageError>(response).await + .await?, + ) + .await } /// Gets a content sources from the registry. @@ -361,11 +352,17 @@ impl Client { &self, digest: &AnyHash, ) -> Result { - let url = self.home_url.join(&paths::content_sources(digest)); + let url = self.url.join(&paths::content_sources(digest)); tracing::debug!("getting content sources for digest `{digest}` at `{url}`"); - let response = reqwest::get(url).await?; - into_result::<_, ContentError>(response).await + into_result::<_, ContentError>( + self.client + .get(url) + .warg_header(self.get_warg_header()) + .send() + .await?, + ) + .await } /// Downloads the content associated with a given record. @@ -386,7 +383,12 @@ impl Client { tracing::debug!("downloading content `{digest}` from `{url}`"); - let response = self.client.get(url).send().await?; + let response = self + .client + .get(url) + .warg_header(self.get_warg_header()) + .send() + .await?; if !response.status().is_success() { tracing::debug!( "failed to download content `{digest}` from `{url}`: {status}", @@ -402,13 +404,13 @@ impl Client { } /// Map namespace - pub fn map_namespace(&mut self, registry: Option) { - self.namespace_registry = registry; + pub fn map_warg_header(&mut self, registry: Option) { + self.warg_header = registry; } /// Get namespace registry - pub fn namespace_registry(&self) -> &Option { - &self.namespace_registry + pub fn get_warg_header(&self) -> &Option { + &self.warg_header } /// Proves the inclusion of the given package log heads in the registry. @@ -418,12 +420,14 @@ impl Client { checkpoint: &Checkpoint, leafs: &[LogLeaf], ) -> Result<(), ClientError> { - let url = self.home_url.join(paths::prove_inclusion()); + let url = self.url.join(paths::prove_inclusion()); tracing::debug!("proving checkpoint inclusion at `{url}`"); let response = into_result::( - self.warg_header(self.namespace_registry(), self.client.post(url)) + self.client + .post(url) .json(&request) + .warg_header(&self.get_warg_header()) .send() .await?, ) @@ -439,10 +443,12 @@ impl Client { from_log_root: Cow<'_, AnyHash>, to_log_root: Cow<'_, AnyHash>, ) -> Result<(), ClientError> { - let url = self.home_url.join(paths::prove_consistency()); + let url = self.url.join(paths::prove_consistency()); let response = into_result::( - self.warg_header(self.namespace_registry(), self.client.post(url)) + self.client + .post(url) .json(&request) + .warg_header(self.get_warg_header()) .send() .await?, ) @@ -494,7 +500,7 @@ impl Client { content: impl Into, ) -> Result<(), ClientError> { // Upload URLs may be relative to the registry URL. - let url = self.home_url.join(url); + let url = self.url.join(url); let method = match method { "POST" => Method::POST, @@ -519,13 +525,11 @@ impl Client { tracing::debug!("uploading content to `{url}`"); let response = self - .warg_header( - self.namespace_registry(), - self.client - .request(method, url) - .headers(headers) - .body(content), - ) + .client + .request(method, url) + .warg_header(self.get_warg_header()) + .headers(headers) + .body(content) .send() .await?; if !response.status().is_success() { diff --git a/crates/client/src/config.rs b/crates/client/src/config.rs index c0438efc..3a44dca6 100644 --- a/crates/client/src/config.rs +++ b/crates/client/src/config.rs @@ -77,7 +77,7 @@ pub struct StoragePaths { pub struct Config { /// The default Warg registry server URL. #[serde(default, skip_serializing_if = "Option::is_none")] - pub default_url: Option, + pub home_url: Option, /// The path to the top-level directory where per-registry information is stored. /// @@ -101,7 +101,7 @@ pub struct Config { /// /// This path is expected to be relative to the configuration file. /// - /// If `None`, the default of `$CACHE_DIR/warg/namespace` is used, where + /// If `None`, the default of `$CACHE_DIR/warg/namespaces` is used, where /// `$CACHE_DIR` is the platform-specific cache directory. #[serde(default, skip_serializing_if = "Option::is_none")] pub namespace_map_path: Option, @@ -165,7 +165,7 @@ impl Config { assert!(parent.is_absolute()); let config = Config { - default_url: self.default_url.clone(), + home_url: self.home_url.clone(), registries_dir: self.registries_dir.as_ref().map(|p| { let p = normalize_path(parent.join(p).as_path()); assert!(p.is_absolute()); @@ -272,7 +272,7 @@ impl Config { url: Option<&str>, ) -> Result { let registry_url = RegistryUrl::new( - url.or(self.default_url.as_deref()) + url.or(self.home_url.as_deref()) .ok_or(ClientError::NoDefaultUrl)?, )?; diff --git a/crates/client/src/depsolve.rs b/crates/client/src/depsolve.rs index cb72c6e5..c1d98e67 100644 --- a/crates/client/src/depsolve.rs +++ b/crates/client/src/depsolve.rs @@ -11,7 +11,7 @@ use wasm_encoder::{ use wasmparser::{Chunk, ComponentImportSectionReader, Parser, Payload}; use super::Client; -use crate::storage::{ContentStorage, PackageInfo, RegistryStorage}; +use crate::storage::{ContentStorage, NamespaceMapStorage, PackageInfo, RegistryStorage}; use crate::version_util::{DependencyImportParser, Import, ImportKind}; /// Import Kinds found in components @@ -32,7 +32,7 @@ impl Default for LockListBuilder { impl LockListBuilder { fn parse_import( - &mut self, + &self, parser: &ComponentImportSectionReader, imports: &mut Vec, ) -> Result<()> { @@ -45,9 +45,9 @@ impl LockListBuilder { } #[async_recursion] - async fn parse_package( + async fn parse_package( &mut self, - client: &Client, + client: &Client, mut bytes: &[u8], ) -> Result<()> { let mut parser = Parser::new(0); @@ -101,7 +101,11 @@ impl LockListBuilder { match import.kind { ImportKind::Locked(_) | ImportKind::Unlocked => { let id = PackageName::new(import.name.clone())?; - if let Some(info) = client.registry().load_package(&id).await? { + if let Some(info) = client + .registry() + .load_package(client.get_warg_header(), &id) + .await? + { let release = info.state.releases().last(); if let Some(r) = release { if let Some(bytes) = self.release_bytes(r, client)? { @@ -111,7 +115,11 @@ impl LockListBuilder { self.lock_list.insert(import); } else { client.download(&id, &VersionReq::STAR).await?; - if let Some(info) = client.registry().load_package(&id).await? { + if let Some(info) = client + .registry() + .load_package(client.get_warg_header(), &id) + .await? + { let release = info.state.releases().last(); if let Some(r) = release { if let Some(bytes) = self.release_bytes(r, client)? { @@ -128,10 +136,10 @@ impl LockListBuilder { Ok(()) } - fn release_bytes( + fn release_bytes( &self, release: &Release, - client: &Client, + client: &Client, ) -> Result>> { let state = &release.state; if let ReleaseState::Released { content } = state { @@ -145,9 +153,9 @@ impl LockListBuilder { /// List of deps for building #[async_recursion] - pub async fn build_list( + pub async fn build_list( &mut self, - client: &Client, + client: &Client, info: &PackageInfo, ) -> Result<()> { let release = info.state.releases().last(); @@ -166,22 +174,24 @@ impl LockListBuilder { } /// Bundles Dependencies -pub struct Bundler<'a, R, C> +pub struct Bundler<'a, R, C, N> where R: RegistryStorage, C: ContentStorage, + N: NamespaceMapStorage, { /// Warg client used for bundling - client: &'a Client, + client: &'a Client, } -impl<'a, R, C> Bundler<'a, R, C> +impl<'a, R, C, N> Bundler<'a, R, C, N> where R: RegistryStorage, C: ContentStorage, + N: NamespaceMapStorage, { /// New Bundler - pub fn new(client: &'a Client) -> Self { + pub fn new(client: &'a Client) -> Self { Self { client } } @@ -200,7 +210,12 @@ where let parsed_imp = dep_parser.parse()?; if !parsed_imp.name.contains('/') { let pkg_id = PackageName::new(parsed_imp.name)?; - if let Some(info) = self.client.registry().load_package(&pkg_id).await? { + if let Some(info) = self + .client + .registry() + .load_package(&self.client.get_warg_header(), &pkg_id) + .await? + { let release = if parsed_imp.req != VersionReq::STAR { info.state .releases() diff --git a/crates/client/src/lib.rs b/crates/client/src/lib.rs index 8158c822..495e5da4 100644 --- a/crates/client/src/lib.rs +++ b/crates/client/src/lib.rs @@ -3,6 +3,7 @@ #![deny(missing_docs)] use crate::storage::PackageInfo; use anyhow::{anyhow, Context, Result}; +use reqwest::header::HeaderValue; use reqwest::{Body, IntoUrl}; use semver::{Version, VersionReq}; use std::cmp::Ordering; @@ -72,8 +73,8 @@ impl Client &RegistryUrl { - self.api.home_url() + pub fn url(&self) -> &RegistryUrl { + self.api.url() } /// Gets the registry storage used by the client. @@ -91,6 +92,25 @@ impl Client Result<()> { + self.namespace_map + .store_namespace(namespace, registry_domain) + .await?; + Ok(()) + } + + // /// Gets the namespace map mutably + // pub fn namespace_map_mut(&mut self) -> &mut N { + // &mut self.namespace_map + // } + + /// Gets the namespace map + pub async fn reset_namespaces(&self) -> Result<()> { + self.namespace_map.reset_namespaces().await?; + Ok(()) + } + /// Reset client storage for the registry. pub async fn reset_registry(&self, all_registries: bool) -> ClientResult<()> { tracing::info!("resetting registry local state"); @@ -109,129 +129,136 @@ impl Client ClientResult<()> { + /// Check operator log for namespace mapping + pub async fn fetch_namespace(&mut self, namespace: &str) -> ClientResult<()> { self.update_checkpoint(&self.api.latest_checkpoint().await?, vec![]) .await?; let operator = self.registry().load_operator(&None).await.unwrap(); if let Some(op) = operator { - for (name, namespace_def) in op.state.namespaces().clone() { - if name == namespace { - match namespace_def.state().clone() { - warg_protocol::operator::NamespaceState::Defined => {} - warg_protocol::operator::NamespaceState::Imported { registry } => { - self.api.map_namespace(Some(registry)); - break; - } + let namespace_state = op.state.namespace_state(namespace); + if let Ok(Some(nm)) = namespace_state { + match nm { + warg_protocol::operator::NamespaceState::Defined => {} + warg_protocol::operator::NamespaceState::Imported { registry } => { + self.api + .map_warg_header(Some(HeaderValue::from_str(registry).unwrap())); } } } } - if self.api.namespace_registry().is_none() { + if self.api.get_warg_header().is_none() { let map = self.namespace_map().load_namespace_map().await?; if let Some(map) = map { let namespace = map.get(namespace); - self.api.map_namespace(namespace.cloned()); + if let Some(nm) = namespace { + self.api + .map_warg_header(Some(HeaderValue::from_str(nm).unwrap())); + } else { + self.api.map_warg_header(None); + } } } Ok(()) } /// Get namespace registry - pub fn namespace_registry(&self) -> &Option { - self.api.namespace_registry() + pub fn get_warg_header(&self) -> &Option { + self.api.get_warg_header() } - + /// Locks component pub async fn lock_component(&self, info: &PackageInfo) -> ClientResult> { - let mut builder = LockListBuilder::default(); - builder.build_list(self, info).await?; - let top = Import { - name: format!("{}:{}", info.name.namespace(), info.name.name()), - req: VersionReq::STAR, - kind: ImportKind::Unlocked, - }; - builder.lock_list.insert(top); - let mut composer = CompositionGraph::new(); - let mut handled = HashMap::::new(); - for package in builder.lock_list { - let name = package.name.clone(); - let version = package.req; - let id = PackageName::new(name)?; - let info = self.registry().load_package(self.namespace_registry(), &id).await?; - if let Some(inf) = info { - let release = if version != VersionReq::STAR { - inf.state - .releases() - .filter(|r| version.matches(&r.version)) - .last() - } else { - inf.state.releases().last() - }; - - if let Some(r) = release { - let state = &r.state; - if let ReleaseState::Released { content } = state { - let locked_package = locked_package(&package.name, r, content); - let path = self.content().content_location(content); - if let Some(p) = path { - let bytes = fs::read(&p).map_err(|_| ClientError::ContentNotFound { - digest: content.clone(), - })?; - - let read_digest = - AnyHash::from_str(&format!("sha256:{}", sha256::digest(bytes))) - .unwrap(); - if content != &read_digest { - return Err(ClientError::IncorrectContent { - digest: read_digest, - expected: content.clone(), - }); - } - let component = - wasm_compose::graph::Component::from_file(&locked_package, p)?; - let component_id = if let Some((id, _)) = - composer.get_component_by_name(&locked_package) - { - id - } else { - composer.add_component(component)? - }; - let instance_id = composer.instantiate(component_id)?; - let added = composer.get_component(component_id); - handled.insert(versioned_package(&package.name, version), instance_id); - let mut args = Vec::new(); - if let Some(added) = added { - for (index, name, _) in added.imports() { - let iid = handled.get(kindless_name(name)); - if let Some(arg) = iid { - args.push((arg, index)); - } - } - } - for arg in args { - composer.connect( - *arg.0, - None::, - instance_id, - arg.1, - )?; - } - } - } - } - } - } - let final_name = &format!("{}:{}", info.name.namespace(), &info.name.name()); - let id = handled.get(final_name); - let options = EncodeOptions { - export: id.copied(), - ..Default::default() - }; - let locked = composer.encode(options)?; - fs::write("./locked.wasm", locked.as_slice()).map_err(|e| ClientError::Other(e.into()))?; - Ok(locked) - } + let mut builder = LockListBuilder::default(); + builder.build_list(self, info).await?; + let top = Import { + name: format!("{}:{}", info.name.namespace(), info.name.name()), + req: VersionReq::STAR, + kind: ImportKind::Unlocked, + }; + builder.lock_list.insert(top); + let mut composer = CompositionGraph::new(); + let mut handled = HashMap::::new(); + for package in builder.lock_list { + let name = package.name.clone(); + let version = package.req; + let id = PackageName::new(name)?; + let info = self + .registry() + .load_package(self.get_warg_header(), &id) + .await?; + if let Some(inf) = info { + let release = if version != VersionReq::STAR { + inf.state + .releases() + .filter(|r| version.matches(&r.version)) + .last() + } else { + inf.state.releases().last() + }; + + if let Some(r) = release { + let state = &r.state; + if let ReleaseState::Released { content } = state { + let locked_package = locked_package(&package.name, r, content); + let path = self.content().content_location(content); + if let Some(p) = path { + let bytes = fs::read(&p).map_err(|_| ClientError::ContentNotFound { + digest: content.clone(), + })?; + + let read_digest = + AnyHash::from_str(&format!("sha256:{}", sha256::digest(bytes))) + .unwrap(); + if content != &read_digest { + return Err(ClientError::IncorrectContent { + digest: read_digest, + expected: content.clone(), + }); + } + let component = + wasm_compose::graph::Component::from_file(&locked_package, p)?; + let component_id = if let Some((id, _)) = + composer.get_component_by_name(&locked_package) + { + id + } else { + composer.add_component(component)? + }; + let instance_id = composer.instantiate(component_id)?; + let added = composer.get_component(component_id); + handled.insert(versioned_package(&package.name, version), instance_id); + let mut args = Vec::new(); + if let Some(added) = added { + for (index, name, _) in added.imports() { + let iid = handled.get(kindless_name(name)); + if let Some(arg) = iid { + args.push((arg, index)); + } + } + } + for arg in args { + composer.connect( + *arg.0, + None::, + instance_id, + arg.1, + )?; + } + } + } + } + } + } + let final_name = &format!("{}:{}", info.name.namespace(), &info.name.name()); + let id = handled.get(final_name); + let options = EncodeOptions { + export: id.copied(), + ..Default::default() + }; + let locked = composer.encode(options)?; + fs::write("./locked.wasm", locked.as_slice()).map_err(|e| ClientError::Other(e.into()))?; + Ok(locked) + } /// Bundles component pub async fn bundle_component(&self, info: &PackageInfo) -> ClientResult> { @@ -255,7 +282,7 @@ impl Client ClientResult { + pub async fn publish(&mut self, signing_key: &signing::PrivateKey) -> ClientResult { let info = self .registry .load_publish() @@ -296,7 +323,7 @@ impl Client Client Client Result { @@ -554,7 +581,7 @@ impl Client Client>(); loop { - let response: FetchLogsResponse = self + let response: FetchLogsResponse = match self .api .fetch_logs(FetchLogsRequest { log_length: checkpoint.log_length, @@ -590,11 +617,59 @@ impl Client res, + Err(api::ClientError::LogNotFoundWithHint(log_id, header)) => { + let hint_reg = header.to_str().unwrap(); + let mut terms = hint_reg.split('='); + let namespace = terms.next(); + let registry = terms.next(); + let resp = if let (Some(namespace), Some(registry)) = (namespace, registry) { + print!( + "One of the packages you're requesting does not exist in the registry you're using. + However, the package namespace `{namespace}` does exist in the registry at {registry}.\nWould you like to configure your warg cli to use this registry for packages with this namespace in the future? y/N\n", + ); + std::io::Write::flush(&mut std::io::stdout()).expect("flush failed!"); + let mut buf = String::new(); + std::io::stdin().read_line(&mut buf).unwrap(); + let lowered = buf.to_lowercase(); + if lowered == "y" || lowered == "yes" { + self.store_namespace(namespace.to_string(), registry.to_string()) + .await?; + Some( + self.api + .fetch_logs(FetchLogsRequest { + log_length: checkpoint.log_length, + operator: operator + .head_fetch_token + .as_ref() + .map(|t| Cow::Borrowed(t.as_str())), + limit: None, + packages: Cow::Borrowed(&last_known), + }) + .await?, + ) + } else { + None + } + } else { + None + }; + if let Some(resp) = resp { + resp + } else { + return Err(ClientError::translate_log_not_found( + api::ClientError::Fetch(FetchError::LogNotFound(log_id)), + |id| packages.get(id).map(|p| p.name.clone()), + )); + } + } + Err(e) => { + return Err(ClientError::translate_log_not_found(e, |id| { packages.get(id).map(|p| p.name.clone()) - }) - })?; + })) + } + }; for record in response.operator { let proto_envelope: PublishedProtoEnvelope = @@ -714,7 +789,7 @@ impl Client Client) { - self.api.map_namespace(namespace.clone()); + pub fn map_warg_header(&mut self, namespace: &Option) { + self.api.map_warg_header(namespace.clone()); } async fn update_checkpoints<'a>( @@ -782,10 +857,10 @@ impl Client>, ) -> Result<(), ClientError> { for (name, ts_checkpoint) in ts_checkpoints { - if self.home_url().safe_label() != name { - self.map_namespace(&Some(name.clone())); + if self.url().safe_label() != name { + self.map_warg_header(&Some(HeaderValue::from_str(&name).unwrap())); } else { - self.map_namespace(&None) + self.map_warg_header(&None) } let mut packages = packages.get_mut(&name.clone()); if let Some(pkgs) = &mut packages { @@ -800,7 +875,7 @@ impl Client Result { match self .registry - .load_package(self.namespace_registry(), name) + .load_package(self.get_warg_header(), name) .await? { Some(info) => { diff --git a/crates/client/src/storage.rs b/crates/client/src/storage.rs index 0c4ebf6c..1b962d7f 100644 --- a/crates/client/src/storage.rs +++ b/crates/client/src/storage.rs @@ -4,6 +4,7 @@ use anyhow::Result; use async_trait::async_trait; use bytes::Bytes; use futures_util::Stream; +use reqwest::header::HeaderValue; use serde::{Deserialize, Serialize}; use std::{collections::HashMap, path::PathBuf, pin::Pin, time::SystemTime}; use warg_crypto::{ @@ -37,13 +38,13 @@ pub trait RegistryStorage: Send + Sync { /// Loads most recent checkpoint async fn load_checkpoint( &self, - namespace_registry: &Option, + namespace_registry: &Option, ) -> Result>>; /// Stores most recent checkpoint async fn store_checkpoint( &self, - namespace_registry: &Option, + namespace_registry: &Option, ts_checkpoint: &SerdeEnvelope, ) -> Result<()>; @@ -52,13 +53,13 @@ pub trait RegistryStorage: Send + Sync { /// Returns `Ok(None)` if the information is not present. async fn load_operator( &self, - namespace_registry: &Option, + namespace_registry: &Option, ) -> Result>; /// Stores the operator information in the storage. async fn store_operator( &self, - namespace_registry: &Option, + namespace_registry: &Option, operator: OperatorInfo, ) -> Result<()>; @@ -73,14 +74,14 @@ pub trait RegistryStorage: Send + Sync { /// Returns `Ok(None)` if the information is not present. async fn load_package( &self, - namespace_registry: &Option, + namespace_registry: &Option, package: &PackageName, ) -> Result>; /// Stores the package information in the storage. async fn store_package( &self, - namespace_registry: &Option, + namespace_registry: &Option, info: &PackageInfo, ) -> Result<()>; @@ -140,6 +141,10 @@ pub trait ContentStorage: Send + Sync { pub trait NamespaceMapStorage: Send + Sync { /// Loads namespace map async fn load_namespace_map(&self) -> Result>>; + /// Reset namespace mappings + async fn reset_namespaces(&self) -> Result<()>; + /// Store namespace mapping + async fn store_namespace(&self, namespace: String, registry_domain: String) -> Result<()>; } /// Represents information about a registry operator. diff --git a/crates/client/src/storage/fs.rs b/crates/client/src/storage/fs.rs index fadf7cf9..5fe010cf 100644 --- a/crates/client/src/storage/fs.rs +++ b/crates/client/src/storage/fs.rs @@ -8,6 +8,7 @@ use anyhow::{anyhow, bail, Context, Result}; use async_trait::async_trait; use bytes::Bytes; use futures_util::{Stream, StreamExt, TryStreamExt}; +use reqwest::header::HeaderValue; use serde::{Deserialize, Serialize}; use std::{ collections::HashMap, @@ -76,20 +77,31 @@ impl FileSystemRegistryStorage { }) } - fn operator_path(&self, namespace_registry: &Option) -> PathBuf { + fn operator_path(&self, namespace_registry: &Option) -> PathBuf { if let Some(nm) = namespace_registry { - return self.registries_dir.join(nm).join("operator.log"); + return self + .registries_dir + .join(nm.to_str().unwrap()) + .join("operator.log"); } self.base_dir.join("operator.log") } - fn package_path(&self, namespace_registry: &Option, name: &PackageName) -> PathBuf { + fn package_path( + &self, + namespace_registry: &Option, + name: &PackageName, + ) -> PathBuf { if let Some(nm) = namespace_registry { - return self.registries_dir.join(nm).join(PACKAGE_LOGS_DIR).join( - LogId::package_log::(name) - .to_string() - .replace(':', "/"), - ); + return self + .registries_dir + .join(nm.to_str().unwrap()) + .join(PACKAGE_LOGS_DIR) + .join( + LogId::package_log::(name) + .to_string() + .replace(':', "/"), + ); } self.base_dir.join(PACKAGE_LOGS_DIR).join( LogId::package_log::(name) @@ -115,22 +127,31 @@ impl RegistryStorage for FileSystemRegistryStorage { async fn load_checkpoint( &self, - namespace_registry: &Option, + namespace_registry: &Option, ) -> Result>> { if let Some(nm) = namespace_registry { - return load(&self.registries_dir.join(nm).join("checkpoint")).await; + return load( + &self + .registries_dir + .join(nm.to_str().unwrap()) + .join("checkpoint"), + ) + .await; } load(&self.base_dir.join("checkpoint")).await } async fn store_checkpoint( &self, - namespace_registry: &Option, + namespace_registry: &Option, ts_checkpoint: &SerdeEnvelope, ) -> Result<()> { if let Some(nm) = namespace_registry { return store( - &self.registries_dir.join(nm).join("checkpoint"), + &self + .registries_dir + .join(nm.to_str().unwrap()) + .join("checkpoint"), ts_checkpoint, ) .await; @@ -215,14 +236,14 @@ impl RegistryStorage for FileSystemRegistryStorage { async fn load_operator( &self, - namespace_registry: &Option, + namespace_registry: &Option, ) -> Result> { Ok(load(&self.operator_path(namespace_registry)).await?) } async fn store_operator( &self, - namespace_registry: &Option, + namespace_registry: &Option, info: OperatorInfo, ) -> Result<()> { store(&self.operator_path(namespace_registry), info).await @@ -230,7 +251,7 @@ impl RegistryStorage for FileSystemRegistryStorage { async fn load_package( &self, - namespace_registry: &Option, + namespace_registry: &Option, package: &PackageName, ) -> Result> { Ok(load(&self.package_path(namespace_registry, package)).await?) @@ -238,7 +259,7 @@ impl RegistryStorage for FileSystemRegistryStorage { async fn store_package( &self, - namespace_registry: &Option, + namespace_registry: &Option, info: &PackageInfo, ) -> Result<()> { store(&self.package_path(namespace_registry, &info.name), info).await @@ -435,6 +456,26 @@ impl NamespaceMapStorage for FileSystemNamespaceMapStorage { let namespace_map = load(namespace_path).await?; Ok(namespace_map) } + + async fn reset_namespaces(&self) -> Result<()> { + remove(&self.base_dir).await?; + Ok(()) + } + + async fn store_namespace(&self, namespace: String, registry_domain: String) -> Result<()> { + let mapping = self.load_namespace_map().await?; + if let Some(mut mapping) = mapping { + mapping.insert(namespace, registry_domain); + let json = serde_json::to_string(&mapping)?; + fs::write(&self.base_dir, json)?; + } else { + let mut mapping = HashMap::new(); + mapping.insert(namespace, registry_domain); + let json = serde_json::to_string(&mapping)?; + fs::write(&self.base_dir, json)?; + } + Ok(()) + } } async fn remove(path: &Path) -> Result<()> { diff --git a/crates/protocol/src/operator/state.rs b/crates/protocol/src/operator/state.rs index 88debc8e..11545d26 100644 --- a/crates/protocol/src/operator/state.rs +++ b/crates/protocol/src/operator/state.rs @@ -4,7 +4,6 @@ use crate::registry::RecordId; use crate::ProtoEnvelope; use indexmap::{IndexMap, IndexSet}; use serde::{Deserialize, Serialize}; -use std::hash::RandomState; use std::time::SystemTime; use thiserror::Error; use warg_crypto::hash::{HashAlgorithm, Sha256}; @@ -73,23 +72,13 @@ pub enum ValidationError { /// The namespace definition. #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "camelCase")] -pub struct NamespaceDefinition { +struct NamespaceDefinition { /// Case sensitive namespace name. namespace: String, /// Namespace state. state: NamespaceState, } -impl NamespaceDefinition { - pub fn namespace(&self) -> &String { - &self.namespace - } - - pub fn state(&self) -> &NamespaceState { - &self.state - } -} - /// The namespace state for defining or importing from other registries. #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "camelCase")] @@ -174,10 +163,6 @@ impl LogState { self.keys.get(key_id) } - pub fn namespaces(&self) -> &IndexMap { - &self.namespaces - } - /// Gets the namespace state. pub fn namespace_state(&self, namespace: &str) -> Result, &str> { if let Some(def) = self.namespaces.get(&namespace.to_ascii_lowercase()) { diff --git a/src/commands/bundle.rs b/src/commands/bundle.rs index 1b7aa5e8..03d0aca8 100644 --- a/src/commands/bundle.rs +++ b/src/commands/bundle.rs @@ -20,13 +20,22 @@ impl BundleCommand { /// Executes the command. pub async fn exec(self) -> Result<()> { let config = self.common.read_config()?; - let client = self.common.create_client(&config)?; + let mut client = self.common.create_client(&config)?; + client.fetch_namespace(self.package.namespace()).await?; println!("registry: {url}", url = client.url()); - if let Some(info) = client.registry().load_package(&self.package).await? { + if let Some(info) = client + .registry() + .load_package(client.get_warg_header(), &self.package) + .await? + { client.bundle_component(&info).await?; } else { client.download(&self.package, &VersionReq::STAR).await?; - if let Some(info) = client.registry().load_package(&self.package).await? { + if let Some(info) = client + .registry() + .load_package(client.get_warg_header(), &self.package) + .await? + { client.bundle_component(&info).await?; } else { bail!("Unable to find package {}", self.package.name()) diff --git a/src/commands/config.rs b/src/commands/config.rs index f7eaa6cf..ba6ed2d1 100644 --- a/src/commands/config.rs +++ b/src/commands/config.rs @@ -1,31 +1,8 @@ use anyhow::{bail, Context, Result}; use clap::Args; -use std::{path::PathBuf, str::FromStr}; +use std::path::PathBuf; use warg_client::{Config, RegistryUrl}; -#[derive(Clone)] -struct Namespace { - namespace: String, - domain: String, -} - -impl FromStr for Namespace { - type Err = anyhow::Error; - - fn from_str(s: &str) -> std::prelude::v1::Result { - let mut split = s.split('='); - let namespace = split.next(); - let domain = split.next(); - if let (Some(namespace), Some(domain)) = (namespace, domain) { - Ok(Namespace { - namespace: namespace.to_owned(), - domain: domain.to_owned(), - }) - } else { - bail!("expected namesape argument to be of form ="); - } - } -} /// Creates a new warg configuration file. #[derive(Args)] pub struct ConfigCommand { @@ -51,10 +28,6 @@ pub struct ConfigCommand { #[clap(value_name = "PATH")] pub path: Option, - /// The namespace and domain to map - #[clap(long, long, value_name = "NAMESPACE")] - namespace: Option, - /// The path to the namespace map #[clap(long, value_name = "NAMESPACE_PATH")] pub namespace_path: Option, @@ -68,14 +41,14 @@ impl ConfigCommand { .map(Ok) .unwrap_or_else(Config::default_config_path)?; - if !self.overwrite && path.is_file() && self.namespace.is_none() { + if !self.overwrite && path.is_file() { bail!( "configuration file `{path}` already exists; use `--overwrite` to overwrite it", path = path.display() ); } - let default_url = self + let home_url = self .registry .map(RegistryUrl::new) .transpose()? @@ -88,7 +61,7 @@ impl ConfigCommand { // the configuration file's directory. let cwd = std::env::current_dir().context("failed to determine current directory")?; let config = Config { - default_url, + home_url, registries_dir: self.registries_dir.map(|p| cwd.join(p)), content_dir: self.content_dir.map(|p| cwd.join(p)), namespace_map_path: self.namespace_path.map(|p| cwd.join(p)), diff --git a/src/commands/dependencies.rs b/src/commands/dependencies.rs index 4dbbb7fb..5dde5349 100644 --- a/src/commands/dependencies.rs +++ b/src/commands/dependencies.rs @@ -30,9 +30,14 @@ impl DependenciesCommand { /// Executes the command. pub async fn exec(self) -> Result<()> { let config = self.common.read_config()?; - let client = self.common.create_client(&config)?; + let mut client = self.common.create_client(&config)?; + client.fetch_namespace(self.package.namespace()).await?; - if let Some(info) = client.registry().load_package(&self.package).await? { + if let Some(info) = client + .registry() + .load_package(client.get_warg_header(), &self.package) + .await? + { Self::print_package_info(&client, &info).await?; } @@ -49,7 +54,10 @@ impl DependenciesCommand { ) -> Result<()> { client.download(id, &version).await?; - let package = client.registry().load_package(id).await?; + let package = client + .registry() + .load_package(client.get_warg_header(), id) + .await?; if let Some(pkg) = package { let latest = pkg.state.releases().last(); if let Some(l) = latest { @@ -85,7 +93,10 @@ impl DependenciesCommand { async fn print_package_info(client: &FileSystemClient, info: &PackageInfo) -> Result<()> { let mut parser = DepsParser::new(); - let root_package = client.registry().load_package(&info.name).await?; + let root_package = client + .registry() + .load_package(client.get_warg_header(), &info.name) + .await?; if let Some(rp) = root_package { let latest = rp.state.releases().last(); if let Some(l) = latest { diff --git a/src/commands/download.rs b/src/commands/download.rs index 005b840b..68a85900 100644 --- a/src/commands/download.rs +++ b/src/commands/download.rs @@ -1,7 +1,6 @@ use super::CommonOptions; use anyhow::{anyhow, Result}; use clap::Args; -use warg_client::storage::NamespaceMapStorage; use warg_protocol::{registry::PackageName, VersionReq}; /// Download a warg registry package. @@ -25,14 +24,6 @@ impl DownloadCommand { let config = self.common.read_config()?; let mut client = self.common.create_client(&config)?; client.fetch_namespace(self.name.namespace()).await?; - if client.namespace_registry().is_none() { - let map = client.namespace_map().load_namespace_map().await?; - if let Some(map) = map { - let namespace = map.get(self.name.namespace()); - client.map_namespace(&namespace.cloned()); - dbg!(&client.namespace_registry()); - } - } println!("downloading package `{name}`...", name = self.name); diff --git a/src/commands/info.rs b/src/commands/info.rs index 41539ef9..597bf872 100644 --- a/src/commands/info.rs +++ b/src/commands/info.rs @@ -30,14 +30,14 @@ impl InfoCommand { let config = self.common.read_config()?; let client = self.common.create_client(&config)?; - println!("registry: {url}", url = client.home_url()); + println!("registry: {url}", url = client.url()); println!("\npackages in client storage:"); if !self.namespaces { match self.package { Some(package) => { if let Some(info) = client .registry() - .load_package(client.namespace_registry(), &package) + .load_package(client.get_warg_header(), &package) .await? { Self::print_package_info(&info); diff --git a/src/commands/lock.rs b/src/commands/lock.rs index 57d6aa7c..4a6c256c 100644 --- a/src/commands/lock.rs +++ b/src/commands/lock.rs @@ -24,13 +24,22 @@ impl LockCommand { /// Executes the command. pub async fn exec(self) -> Result<()> { let config = self.common.read_config()?; - let client = self.common.create_client(&config)?; + let mut client = self.common.create_client(&config)?; + client.fetch_namespace(self.package.namespace()).await?; println!("registry: {url}", url = client.url()); - if let Some(info) = client.registry().load_package(&self.package).await? { + if let Some(info) = client + .registry() + .load_package(client.get_warg_header(), &self.package) + .await? + { Self::lock(client, &info).await?; } else { client.download(&self.package, &VersionReq::STAR).await?; - if let Some(info) = client.registry().load_package(&self.package).await? { + if let Some(info) = client + .registry() + .load_package(client.get_warg_header(), &self.package) + .await? + { Self::lock(client, &info).await?; } } diff --git a/src/commands/publish.rs b/src/commands/publish.rs index ac09af97..5cb18b09 100644 --- a/src/commands/publish.rs +++ b/src/commands/publish.rs @@ -121,10 +121,10 @@ impl PublishInitCommand { let mut client = self.common.create_client(&config)?; client.fetch_namespace(self.name.namespace()).await?; - let signing_key = if let Some(nm) = client.namespace_registry() { - self.common.signing_key(&RegistryUrl::new(nm)?)? + let signing_key = if let Some(nm) = client.get_warg_header() { + self.common.signing_key(&RegistryUrl::new(nm.to_str()?)?)? } else { - self.common.signing_key(client.home_url())? + self.common.signing_key(client.url())? }; match enqueue(&client, &self.name, |_| { std::future::ready(Ok(PublishEntry::Init)) @@ -195,10 +195,10 @@ impl PublishReleaseCommand { let config = self.common.read_config()?; let mut client = self.common.create_client(&config)?; client.fetch_namespace(self.name.namespace()).await?; - let signing_key = if let Some(nm) = client.namespace_registry() { - self.common.signing_key(&RegistryUrl::new(nm)?)? + let signing_key = if let Some(nm) = client.get_warg_header() { + self.common.signing_key(&RegistryUrl::new(nm.to_str()?)?)? } else { - self.common.signing_key(client.home_url())? + self.common.signing_key(client.url())? }; let path = self.path.clone(); @@ -286,10 +286,10 @@ impl PublishYankCommand { let config = self.common.read_config()?; let mut client = self.common.create_client(&config)?; client.fetch_namespace(self.name.namespace()).await?; - let signing_key = if let Some(nm) = client.namespace_registry() { - self.common.signing_key(&RegistryUrl::new(nm)?)? + let signing_key = if let Some(nm) = client.get_warg_header() { + self.common.signing_key(&RegistryUrl::new(nm.to_str()?)?)? } else { - self.common.signing_key(client.home_url())? + self.common.signing_key(client.url())? }; let version = self.version.clone(); @@ -368,10 +368,10 @@ impl PublishGrantCommand { let config = self.common.read_config()?; let mut client = self.common.create_client(&config)?; client.fetch_namespace(self.name.namespace()).await?; - let signing_key = if let Some(nm) = client.namespace_registry() { - self.common.signing_key(&RegistryUrl::new(nm)?)? + let signing_key = if let Some(nm) = client.get_warg_header() { + self.common.signing_key(&RegistryUrl::new(nm.to_str()?)?)? } else { - self.common.signing_key(client.home_url())? + self.common.signing_key(client.url())? }; match enqueue(&client, &self.name, |_| async { @@ -454,10 +454,10 @@ impl PublishRevokeCommand { let config = self.common.read_config()?; let mut client = self.common.create_client(&config)?; client.fetch_namespace(self.name.namespace()).await?; - let signing_key = if let Some(nm) = client.namespace_registry() { - self.common.signing_key(&RegistryUrl::new(nm)?)? + let signing_key = if let Some(nm) = client.get_warg_header() { + self.common.signing_key(&RegistryUrl::new(nm.to_str()?)?)? } else { - self.common.signing_key(client.home_url())? + self.common.signing_key(client.url())? }; match enqueue(&client, &self.name, |_| async { @@ -657,7 +657,7 @@ impl PublishSubmitCommand { name = info.name ); - let signing_key = self.common.signing_key(client.home_url())?; + let signing_key = self.common.signing_key(client.url())?; let record_id = client.publish_with_info(&signing_key, info.clone()).await?; client.registry().store_publish(None).await?; diff --git a/src/commands/reset.rs b/src/commands/reset.rs index e36ffd92..b3fdb4a8 100644 --- a/src/commands/reset.rs +++ b/src/commands/reset.rs @@ -11,6 +11,9 @@ pub struct ResetCommand { /// Whether to reset all registries. #[clap(long)] pub all: bool, + /// Whether to reset namespace mappings + #[clap(long)] + pub namespaces: bool, } impl ResetCommand { @@ -23,13 +26,14 @@ impl ResetCommand { println!("resetting local data for all registries..."); client.reset_registry(true).await?; } else { - println!( - "resetting local data for registry `{}`...", - client.home_url() - ); + println!("resetting local data for registry `{}`...", client.url()); client.reset_registry(false).await?; } + if self.namespaces { + client.reset_namespaces().await?; + } + Ok(()) } } diff --git a/tests/client.rs b/tests/client.rs index fe7f9011..37cef51e 100644 --- a/tests/client.rs +++ b/tests/client.rs @@ -93,7 +93,7 @@ async fn client_incrementally_fetches() -> Result<()> { // Ensure the package log exists and has releases with all with the same digest let package = client .registry() - .load_package(client.namespace_registry(), &name) + .load_package(client.get_warg_header(), &name) .await? .context("package does not exist in client storage")?; diff --git a/tests/depsolve.rs b/tests/depsolve.rs index 0628a2d7..40ed4047 100644 --- a/tests/depsolve.rs +++ b/tests/depsolve.rs @@ -3,8 +3,8 @@ use anyhow::{Context, Result}; use std::time::Duration; use warg_client::{ storage::{ - ContentStorage, FileSystemContentStorage, FileSystemRegistryStorage, PublishEntry, - PublishInfo, RegistryStorage, + ContentStorage, FileSystemContentStorage, FileSystemNamespaceMapStorage, + FileSystemRegistryStorage, PublishEntry, PublishInfo, RegistryStorage, }, Client, }; @@ -89,7 +89,7 @@ async fn depsolve() -> Result<()> { let info = client .registry() - .load_package(&PackageName::new("test:meet")?) + .load_package(client.get_warg_header(), &PackageName::new("test:meet")?) .await? .context("package does not exist in client storage")?; @@ -109,7 +109,11 @@ async fn depsolve() -> Result<()> { } async fn publish_package( - client: &Client, + client: &Client< + FileSystemRegistryStorage, + FileSystemContentStorage, + FileSystemNamespaceMapStorage, + >, signing_key: &PrivateKey, name: &str, path: &str, diff --git a/tests/memory/mod.rs b/tests/memory/mod.rs index bb79580c..5a7368c3 100644 --- a/tests/memory/mod.rs +++ b/tests/memory/mod.rs @@ -16,7 +16,7 @@ async fn it_publishes_a_component() -> Result<()> { test_component_publishing(&config).await?; // There should be two log entries in the registry - let client = api::Client::new(config.default_url.as_ref().unwrap())?; + let client = api::Client::new(config.home_url.as_ref().unwrap())?; let ts_checkpoint = client.latest_checkpoint().await?; assert_eq!( ts_checkpoint.as_ref().checkpoint.log_length, @@ -35,7 +35,7 @@ async fn it_yanks_a_package() -> Result<()> { test_package_yanking(&config).await?; // There should be three entries in the registry - let client = api::Client::new(config.default_url.as_ref().unwrap())?; + let client = api::Client::new(config.home_url.as_ref().unwrap())?; let ts_checkpoint = client.latest_checkpoint().await?; assert_eq!( ts_checkpoint.as_ref().checkpoint.log_length, @@ -52,7 +52,7 @@ async fn it_publishes_a_wit_package() -> Result<()> { test_wit_publishing(&config).await?; // There should be two log entries in the registry - let client = api::Client::new(config.default_url.as_ref().unwrap())?; + let client = api::Client::new(config.home_url.as_ref().unwrap())?; let ts_checkpoint = client.latest_checkpoint().await?; assert_eq!( ts_checkpoint.as_ref().checkpoint.log_length, diff --git a/tests/server.rs b/tests/server.rs index 3c468883..e354b93f 100644 --- a/tests/server.rs +++ b/tests/server.rs @@ -39,7 +39,7 @@ mod memory; mod postgres; async fn test_initial_checkpoint(config: &Config) -> Result<()> { - let client = api::Client::new(config.default_url.as_ref().unwrap())?; + let client = api::Client::new(config.home_url.as_ref().unwrap())?; let ts_checkpoint = client.latest_checkpoint().await?; let checkpoint = &ts_checkpoint.as_ref().checkpoint; @@ -371,7 +371,7 @@ async fn test_invalid_signature(config: &Config) -> Result<()> { // Use a reqwest client directly here as we're going to be sending an invalid signature let name = PackageName::new(PACKAGE_NAME)?; let log_id = LogId::package_log::(&name); - let url = Url::parse(config.default_url.as_ref().unwrap())? + let url = Url::parse(config.home_url.as_ref().unwrap())? .join(&paths::publish_package_record(&log_id)) .unwrap(); @@ -441,7 +441,7 @@ async fn test_custom_content_url(config: &Config) -> Result<()> { client.upsert([&name]).await?; let package = client .registry() - .load_package(client.namespace_registry(), &name) + .load_package(client.get_warg_header(), &name) .await? .expect("expected the package to exist"); package @@ -450,7 +450,7 @@ async fn test_custom_content_url(config: &Config) -> Result<()> { .expect("expected the package version to exist"); // Look up the content URL for the record - let client = api::Client::new(config.default_url.as_ref().unwrap())?; + let client = api::Client::new(config.home_url.as_ref().unwrap())?; let ContentSourcesResponse { content_sources } = client.content_sources(&digest).await?; assert_eq!(content_sources.len(), 1); let sources = content_sources @@ -476,7 +476,7 @@ async fn test_fetch_package_names(config: &Config) -> Result<()> { let name_1 = PackageName::new("test:component")?; let log_id_1 = LogId::package_log::(&name_1); - let url = Url::parse(config.default_url.as_ref().unwrap())? + let url = Url::parse(config.home_url.as_ref().unwrap())? .join(paths::fetch_package_names()) .unwrap(); @@ -511,12 +511,12 @@ async fn test_fetch_package_names(config: &Config) -> Result<()> { } async fn test_get_ledger(config: &Config) -> Result<()> { - let client = api::Client::new(config.default_url.as_ref().unwrap())?; + let client = api::Client::new(config.home_url.as_ref().unwrap())?; let ts_checkpoint = client.latest_checkpoint().await?; let checkpoint = &ts_checkpoint.as_ref().checkpoint; - let url = Url::parse(config.default_url.as_ref().unwrap())? + let url = Url::parse(config.home_url.as_ref().unwrap())? .join(paths::ledger_sources()) .unwrap(); @@ -565,7 +565,7 @@ async fn test_get_ledger(config: &Config) -> Result<()> { "unexpected ledger source last registry index: {last_registry_index}", ); - let url = Url::parse(config.default_url.as_ref().unwrap())? + let url = Url::parse(config.home_url.as_ref().unwrap())? .join(url) .unwrap(); diff --git a/tests/support/mod.rs b/tests/support/mod.rs index fe5a952d..1d54f2be 100644 --- a/tests/support/mod.rs +++ b/tests/support/mod.rs @@ -160,7 +160,7 @@ pub async fn spawn_server( }; let config = warg_client::Config { - default_url: Some(format!("http://{addr}")), + home_url: Some(format!("http://{addr}")), registries_dir: Some(root.join("registries")), content_dir: Some(root.join("content")), namespace_map_path: Some(root.join("namespaces")),