Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wapm.io integration #43

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use humansize::{format_size, BINARY};
use owo_colors::OwoColorize;
use prettytable::{row, Table};
use tokio::runtime::Runtime;
use utils::registry::RegistryPackageSpec;
use utils::structs::Manifest;
use uuid::Uuid;

Expand Down Expand Up @@ -70,6 +71,11 @@ pub enum Command {
History,
/// Liveness check: ping at least one node on the mesh.
Ping,
/// Highly experimental: Pull a package from WAPM.io and store it in Serval Mesh
Pull {
/// The name of the software package, formatted as author/packagename@version
identifer: String,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can eventually make the identifier a type more specific than a string and have clap parse it for us. Some examples here. There is no need to do that in this PR, however.

},
}

static SERVAL_NODE_URL: Mutex<Option<String>> = Mutex::new(None);
Expand Down Expand Up @@ -286,7 +292,19 @@ fn blocking_maybe_discover_service_url(
};

let port = info.get_port();
return Ok(format!("http://{addr}:{port}"));
Ok(format!("http://{addr}:{port}"))
}

fn pull(registry: &str, identifer: String) -> Result<()> {
let package_spec = RegistryPackageSpec::parse(registry, identifer).unwrap();
println!("{:#?}", package_spec);
jkbecker marked this conversation as resolved.
Show resolved Hide resolved
let dl_url = package_spec.registry.baseurl_download.to_string();
println!("{dl_url}");

println!("{}", package_spec.fqtn());

println!("{}", package_spec.fqdn());
jkbecker marked this conversation as resolved.
Show resolved Hide resolved
Ok(())
}

/// Parse command-line arguments and act.
Expand Down Expand Up @@ -320,6 +338,7 @@ fn main() -> Result<()> {
Command::Status { id } => status(id)?,
Command::History => history()?,
Command::Ping => ping()?,
Command::Pull { identifer } => pull("wapm", identifer)?,
jkbecker marked this conversation as resolved.
Show resolved Hide resolved
};

Ok(())
Expand Down
4 changes: 4 additions & 0 deletions utils/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ pub enum ServalError {
/// Translation for errors from ssri.
#[error("ssri::Error: {0}")]
SsriError(#[from] ssri::Error),

/// The Package Registry Manifest could not be constructed.
#[error("failed to parse registry manifest `{0}`")]
PackageRegistryManifestError(String),
}

use axum::http::StatusCode;
Expand Down
1 change: 1 addition & 0 deletions utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ pub mod errors;
pub mod futures;
pub mod mdns;
pub mod networking;
pub mod registry;
pub mod structs;
101 changes: 101 additions & 0 deletions utils/src/registry.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
use std::str::FromStr;
jkbecker marked this conversation as resolved.
Show resolved Hide resolved

use crate::errors::ServalError;

/// Package registry information, used to download executables and construct the Manifest.
#[derive(Debug, PartialEq)]
pub struct Registry {
pub namespace: String,
pub baseurl_summary: &'static str,
pub baseurl_download: &'static str,
}

impl FromStr for Registry {
type Err = ();

fn from_str(input: &str) -> Result<Registry, Self::Err> {
if let "wapm" = input {
Ok(Registry {
namespace: String::from("io.wapm"),
baseurl_summary: "https://wapm.io/{author}/{name}@{version}",
baseurl_download: "https://registry-cdn.wapm.io/contents/{author}/{name}/{version}/target/wasm32-wasi/release/{name}.wasm",
})
} else {
Err(())
}
}
}

/// Specification for a registry package
#[derive(Debug, PartialEq)]
pub struct RegistryPackageSpec {
pub registry: Registry,
pub author: String,
pub package: String,
pub version: String,
}

impl RegistryPackageSpec {

/// Parses a registry package using a registry key and a package identifier
pub fn parse(registry: &str, identifer: String) -> Result<RegistryPackageSpec, ServalError> {
let registry_spec = Registry::from_str(registry).unwrap();
// Split the string by "/". We expect the provided identifier to be one of the following:
// - author/package/version
// - author/package@version
jkbecker marked this conversation as resolved.
Show resolved Hide resolved
let pkg_author_spec: Vec<&str> = identifer.split('/').collect();
match pkg_author_spec.len() {
// we assume the provided format is author/package@version
2 => {
let author = pkg_author_spec[0].to_string();
// The string after the / should contain package@version
let pkg_version_spec: Vec<&str> = pkg_author_spec[1].split('@').collect();
match pkg_version_spec.len() {
// we found a package and version
2 => {
let (name, version) = (
pkg_version_spec[0].to_string(),
pkg_version_spec[1].to_string(),
);
Ok(RegistryPackageSpec {
registry: registry_spec,
author,
package: name,
version,
})
}
_ => Err(ServalError::PackageRegistryManifestError(String::from(
"could not parse version.",
))),
}
}
// we assume the provided format is author/package/version
3 => {
let (author, name, version) = (
pkg_author_spec[0].to_string(),
pkg_author_spec[1].to_string(),
pkg_author_spec[2].to_string(),
);
Ok(RegistryPackageSpec {
registry: registry_spec,
author,
package: name,
version,
})
}
// unclear format, we're erroring out
_ => Err(ServalError::PackageRegistryManifestError(String::from(
"could not parse package identifier.",
))),
}
}

/// The fully-qualified task name of the package, composed of the registry
/// namespace, author, package name and version.
pub fn fqtn(self) -> String {
format!(
"{}.{}.{}@{}",
self.registry.namespace, self.author, self.package, self.version
)
}
}