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

Implement wasmer whoami #3316

Merged
merged 17 commits into from
Nov 21, 2022
Merged
9 changes: 8 additions & 1 deletion 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 Down Expand Up @@ -151,6 +153,10 @@ enum WasmerCLIOptions {
#[clap(name = "binfmt")]
Binfmt(Binfmt),

/// Shows the current logged in user for the current active registry
#[clap(name = "whoami")]
fschutt marked this conversation as resolved.
Show resolved Hide resolved
Whoami(Whoami),

/// Add a WAPM package's bindings to your application.
Add(Add),
}
Expand All @@ -176,6 +182,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:?}");
Michael-F-Bryan marked this conversation as resolved.
Show resolved Hide resolved
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
42 changes: 42 additions & 0 deletions lib/registry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -894,6 +894,48 @@ 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}"))
.context(anyhow::anyhow!("{registry:?}"))?;
fschutt marked this conversation as resolved.
Show resolved Hide resolved

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)
.map_err(|e| anyhow::anyhow!("{e}"))
.context(anyhow::anyhow!("{registry:?}"))?;
fschutt marked this conversation as resolved.
Show resolved Hide resolved

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
47 changes: 47 additions & 0 deletions tests/integration/cli/tests/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,53 @@ fn test_cross_compile_python_windows() -> anyhow::Result<()> {
Ok(())
}

#[test]
fn run_whoami_works() -> anyhow::Result<()> {
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(())
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think this test is a good idea.

It assumes the $WAPM_DEV_TOKEN variable is set and that user's name is ciuser, so the only way for integration tests to pass locally is if you have the ciuser token on your computer, which is a massive no-no (no human developers should have access to CI tokens).

We're also trying to contact wapm.dev, which makes the test slow and flaky (e.g. wapm.dev could be having a bad day and always error out).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah well with network requests, that's kind of a given, otherwise it wouldn't be an integration test. In the worst case the test fails because wapm.dev is down, then we just need to restart the tests on GitHub.

The other part, I think I can require WAPM_DEV_TOKEN if GITHUB_TOKEN is present (true for integration tests in the CI, false for running tests locally).


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