Skip to content

Commit

Permalink
Merge #3316
Browse files Browse the repository at this point in the history
3316: Implement wasmer whoami r=Michael-F-Bryan a=fschutt

Note: has to be rebased on the `wasmer login` branch, otherwise the integration test won't work

Co-authored-by: Felix Schütt <felix@wasmer.io>
Co-authored-by: Felix Schütt <12084016+fschutt@users.noreply.github.com>
  • Loading branch information
3 people authored Nov 21, 2022
2 parents b6613a4 + 9beaf8e commit f503052
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 12 deletions.
19 changes: 8 additions & 11 deletions lib/cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ use crate::commands::CreateExe;
use crate::commands::CreateObj;
#[cfg(feature = "wast")]
use crate::commands::Wast;
use crate::commands::{Add, Cache, Config, Inspect, List, Login, Run, SelfUpdate, Validate};
use crate::commands::{
Add, Cache, Config, Inspect, List, Login, Run, SelfUpdate, Validate, Whoami,
};
use crate::error::PrettyError;
use clap::{CommandFactory, ErrorKind, Parser};
use std::{fmt, str::FromStr};
Expand All @@ -37,28 +39,23 @@ use std::{fmt, str::FromStr};
/// The options for the wasmer Command Line Interface
enum WasmerCLIOptions {
/// List all locally installed packages
#[clap(name = "list")]
List(List),

/// Run a WebAssembly file. Formats accepted: wasm, wat
#[clap(name = "run")]
Run(Run),

/// Login into a wapm.io-like registry
#[clap(name = "login")]
Login(Login),

/// Wasmer cache
#[clap(subcommand, name = "cache")]
#[clap(subcommand)]
Cache(Cache),

/// Validate a WebAssembly binary
#[clap(name = "validate")]
Validate(Validate),

/// Compile a WebAssembly binary
#[cfg(feature = "compiler")]
#[clap(name = "compile")]
Compile(Compile),

/// Compile a WebAssembly binary into a native executable
Expand Down Expand Up @@ -130,27 +127,26 @@ enum WasmerCLIOptions {

/// Get various configuration information needed
/// to compile programs which use Wasmer
#[clap(name = "config")]
Config(Config),

/// Update wasmer to the latest version
#[clap(name = "self-update")]
SelfUpdate(SelfUpdate),

/// Inspect a WebAssembly file
#[clap(name = "inspect")]
Inspect(Inspect),

/// Run spec testsuite
#[cfg(feature = "wast")]
#[clap(name = "wast")]
Wast(Wast),

/// Unregister and/or register wasmer as binfmt interpreter
#[cfg(target_os = "linux")]
#[clap(name = "binfmt")]
Binfmt(Binfmt),

/// Shows the current logged in user for the current active registry
Whoami(Whoami),

/// Add a WAPM package's bindings to your application.
Add(Add),
}
Expand All @@ -176,6 +172,7 @@ impl WasmerCLIOptions {
Self::Wast(wast) => wast.execute(),
#[cfg(target_os = "linux")]
Self::Binfmt(binfmt) => binfmt.execute(),
Self::Whoami(whoami) => whoami.execute(),
Self::Add(install) => install.execute(),
}
}
Expand Down
4 changes: 3 additions & 1 deletion lib/cli/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ mod self_update;
mod validate;
#[cfg(feature = "wast")]
mod wast;
mod whoami;

#[cfg(target_os = "linux")]
pub use binfmt::*;
Expand All @@ -30,7 +31,8 @@ pub use create_obj::*;
#[cfg(feature = "wast")]
pub use wast::*;
pub use {
add::*, cache::*, config::*, inspect::*, list::*, login::*, run::*, self_update::*, validate::*,
add::*, cache::*, config::*, inspect::*, list::*, login::*, run::*, self_update::*,
validate::*, whoami::*,
};

/// The kind of object format to emit.
Expand Down
18 changes: 18 additions & 0 deletions lib/cli/src/commands/whoami.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use clap::Parser;

#[derive(Debug, Parser)]
/// The options for the `wasmer whoami` subcommand
pub struct Whoami {
/// Which registry to check the logged in username for
#[clap(long, name = "registry")]
pub registry: Option<String>,
}

impl Whoami {
/// Execute `wasmer whoami`
pub fn execute(&self) -> Result<(), anyhow::Error> {
let (registry, username) = wasmer_registry::whoami(self.registry.as_deref())?;
println!("logged into registry {registry:?} as user {username:?}");
Ok(())
}
}
8 changes: 8 additions & 0 deletions lib/registry/src/graphql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,14 @@ pub(crate) mod proxy {
)]
pub(crate) struct GetPackageVersionQuery;

#[derive(GraphQLQuery)]
#[graphql(
schema_path = "graphql/schema.graphql",
query_path = "graphql/queries/whoami.graphql",
response_derives = "Debug"
)]
pub(crate) struct WhoAmIQuery;

#[derive(GraphQLQuery)]
#[graphql(
schema_path = "graphql/schema.graphql",
Expand Down
41 changes: 41 additions & 0 deletions lib/registry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -894,6 +894,47 @@ pub fn install_package(
))
}

pub fn whoami(
#[cfg(test)] test_name: &str,
registry: Option<&str>,
) -> Result<(String, String), anyhow::Error> {
use crate::graphql::{who_am_i_query, WhoAmIQuery};
use graphql_client::GraphQLQuery;

#[cfg(test)]
let config = PartialWapmConfig::from_file(test_name);
#[cfg(not(test))]
let config = PartialWapmConfig::from_file();

let config = config
.map_err(|e| anyhow::anyhow!("{e}"))
.with_context(|| format!("{registry:?}"))?;

let registry = match registry {
Some(s) => format_graphql(s),
None => config.registry.get_current_registry(),
};

let login_token = config
.registry
.get_login_token_for_registry(&registry)
.ok_or_else(|| anyhow::anyhow!("not logged into registry {:?}", registry))?;

let q = WhoAmIQuery::build_query(who_am_i_query::Variables {});
let response: who_am_i_query::ResponseData =
crate::graphql::execute_query(&registry, &login_token, &q)
.with_context(|| format!("{registry:?}"))?;

let username = response
.viewer
.as_ref()
.ok_or_else(|| anyhow::anyhow!("not logged into registry {:?}", registry))?
.username
.to_string();

Ok((registry, username))
}

pub fn test_if_registry_present(registry: &str) -> Result<bool, String> {
use crate::graphql::{test_if_registry_present, TestIfRegistryPresent};
use graphql_client::GraphQLQuery;
Expand Down
5 changes: 5 additions & 0 deletions tests/integration/cli/tests/login.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ use wasmer_integration_tests_cli::{get_repo_root_path, get_wasmer_path, ASSET_PA

#[test]
fn login_works() -> anyhow::Result<()> {
// running test locally: should always pass since
// developers don't have access to WAPM_DEV_TOKEN
if std::env::var("GITHUB_TOKEN").is_err() {
return Ok(());
}
let wapm_dev_token = std::env::var("WAPM_DEV_TOKEN").expect("WAPM_DEV_TOKEN env var not set");
let output = Command::new(get_wasmer_path())
.arg("login")
Expand Down
53 changes: 53 additions & 0 deletions tests/integration/cli/tests/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,59 @@ fn test_cross_compile_python_windows() -> anyhow::Result<()> {
Ok(())
}

#[test]
fn run_whoami_works() -> anyhow::Result<()> {
// running test locally: should always pass since
// developers don't have access to WAPM_DEV_TOKEN
if std::env::var("GITHUB_TOKEN").is_err() {
return Ok(());
}

let ciuser_token = std::env::var("WAPM_DEV_TOKEN").expect("no CIUSER / WAPM_DEV_TOKEN token");

let output = Command::new(get_wasmer_path())
.arg("login")
.arg("--registry")
.arg("wapm.dev")
.arg(ciuser_token)
.output()?;

if !output.status.success() {
bail!(
"wasmer login failed with: stdout: {}\n\nstderr: {}",
std::str::from_utf8(&output.stdout)
.expect("stdout is not utf8! need to handle arbitrary bytes"),
std::str::from_utf8(&output.stderr)
.expect("stderr is not utf8! need to handle arbitrary bytes")
);
}

let output = Command::new(get_wasmer_path())
.arg("whoami")
.arg("--registry")
.arg("wapm.dev")
.output()?;

let stdout = std::str::from_utf8(&output.stdout)
.expect("stdout is not utf8! need to handle arbitrary bytes");

if !output.status.success() {
bail!(
"linking failed with: stdout: {}\n\nstderr: {}",
stdout,
std::str::from_utf8(&output.stderr)
.expect("stderr is not utf8! need to handle arbitrary bytes")
);
}

assert_eq!(
stdout,
"logged into registry \"https://registry.wapm.dev/graphql\" as user \"ciuser\"\n"
);

Ok(())
}

#[test]
fn run_wasi_works() -> anyhow::Result<()> {
let output = Command::new(get_wasmer_path())
Expand Down

0 comments on commit f503052

Please sign in to comment.