Skip to content

Commit

Permalink
library updates and mauth
Browse files Browse the repository at this point in the history
  • Loading branch information
JordiPolo committed Feb 4, 2021
1 parent 02fbb05 commit 3384b74
Show file tree
Hide file tree
Showing 8 changed files with 1,113 additions and 540 deletions.
1,450 changes: 965 additions & 485 deletions Cargo.lock

Large diffs are not rendered by default.

37 changes: 28 additions & 9 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ serde_json = "1.0"
daedalus = { path = "crates/daedalus" }

termcolor = "1.0"
rand = "0.7"
rand = "0.8"
openapiv3 = "0.3"
#openapi_utils = { path = "../../oasproxy/openapi_utils" }
openapi_utils = "0.2"
Expand All @@ -31,22 +31,40 @@ valico = "3"
tracing = { version = "0.1", default-features = false, features = ["log", "std"] }
tracing-subscriber = "0.2"

itertools = "0.9"
comfy-table = "1.0"
itertools = "0.10"
comfy-table = "2.0"
lazy_static = "*"
reqwest = { version = "0.10", default-features = false, features = ["json", "rustls-tls"] }
hyper = "*"
hyper = { version = "0.14", default-features = false, features = ["client", "http1", "stream", "runtime"] }
http = "*"
tokio = { version = "0.2", features = ["full"] }
#mauth-client = { path = "../mauth-client-rust"}
mauth-client = "*"
indicatif = "*"
# clap = "3.0.0-beta.1"
gumdrop = "*"




[dependencies.clap]
#version = "0.9"
# default-features = false
# features = ["rustls"]

git = "https://github.com/clap-rs/clap.git"
rev = "v3.0.0-beta.2"
#rev = "90622b397e3d5bd6bdcecfbf1488b13f5a3f8301"
#rev = "e4c2d09"



clap = "3.0.0-beta.1"
[dependencies.goose]
version = "0.9"
#version = "0.10.7"
default-features = false
features = ["rustls"]
#git = "https://github.com/tag1consulting/goose"

git = "https://github.com/tag1consulting/goose"
rev = "59d7e90"


[profile.dev]
Expand All @@ -55,6 +73,7 @@ debug = 0
[profile.release]
opt-level = 3
lto = true
codegen-units = 1 # better optimizations
#codegen-units = 1 # better optimizations
incremental = false
panic = 'abort'
debug = true
6 changes: 3 additions & 3 deletions crates/daedalus/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ serde_yaml = "0.8"
uuid = { version = ">= 0.6", features = ["v4"] }
chrono = "0.4"
openapiv3 = "0.3"
# #openapi_utils = { path = "../../oasproxy/openapi_utils" }
#openapi_utils = { path = "../../../../oasproxy/openapi_utils" }
openapi_utils = "0.2"
tracing = { version = "0.1", default-features = false, features = ["log", "std"] }
rand = "0.7"
rand = "0.8"
shellexpand = "2.0"
itertools = "0.9"
itertools = "0.10"
lazy_static = "*"
http = "*"
2 changes: 2 additions & 0 deletions crates/daedalus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ impl Generator {
/// Construction out of the configuration
pub fn new(config: &GeneratorConfig) -> Self {
let spec = spec::read(&config.filename).deref_all();
// println!("{:?}", spec);
// panic!("bye");
let mutator = mutation::Mutator::new(&config.conv_filename, config.scenarios_all_codes);
let endpoints = Self::endpoints(spec, &config.matches);
Generator { mutator, endpoints }
Expand Down
36 changes: 19 additions & 17 deletions src/authentication.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
// use mauth_client::*;
use mauth_client::*;

// pub struct Authentication {
// mauth_info: mauth_client::MAuthInfo
// }
pub struct Authentication {
mauth_info: mauth_client::MAuthInfo
}

// impl Authentication {
// pub fn new() -> Self {
// Authentication {
// mauth_info: MAuthInfo::from_default_file().expect("Mauth file missing")
// }
// }
// pub fn authenticate(&self, mut requ: &mut hyper::Request<hyper::Body>) {
// // on empty body we digest "" TODO: Support request bodies
// let (_, body_digest) = MAuthInfo::build_body_with_digest("".to_string());
// self.mauth_info.sign_request_v2(&mut requ, &body_digest);
// self.mauth_info.sign_request_v1(&mut requ, &body_digest);
// }
// }
impl Authentication {
pub fn new() -> Self {
Authentication {
mauth_info: MAuthInfo::from_default_file().expect("Mauth file missing")
}
}
pub fn authenticate(&self, mut requ: &mut hyper::Request<hyper::Body>) {
// on empty body we digest "" TODO: Support request bodies
let (_, body_digest) = MAuthInfo::build_body_with_digest("".to_string());
self.mauth_info.sign_request_v2(&mut requ, &body_digest);
self.mauth_info.sign_request_v1(&mut requ, &body_digest);
}
}

/*
pub struct Authentication {}
impl Authentication {
Expand All @@ -26,3 +27,4 @@ impl Authentication {
}
pub fn authenticate(&self, mut _requ: &mut hyper::Request<hyper::Body>) {}
}
*/
18 changes: 9 additions & 9 deletions src/cli_args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,39 +23,39 @@ impl CLIArgs {
)]
pub struct CLIArgs {
#[clap(
short = "f",
short = 'f',
long = "file",
about = "Input OpenAPI file",
default_value = "doc/contracts/openapi.yaml"
)]
pub filename: String,

#[clap(
short = "u",
short = 'u',
long = "url",
about = "URL where the server is running (it can also be in localhost)",
default_value = "http://localhost:3000"
)]
pub base_url: String,

#[clap(
short = "c",
short = 'c',
long = "conversions",
about = "The location of the conversions file with parameter values for this run.",
default_value = "./conversions.yml"
)]
pub conv_filename: String,

#[clap(
short = "m",
short = 'm',
long = "matches",
about = "Only generate scenarios for paths matching certain expression.",
default_value = "/"
)]
pub matches: String,

#[clap(
short = "a",
short = 'a',
long = "all-codes",
about = "Generate scenarios for all codes. Default is to generate only scenarios with 200 codes."
)]
Expand All @@ -77,7 +77,7 @@ pub enum Command {
)]
Verify {
#[clap(
short = "n",
short = 'n',
long = "allow-missing-rs",
about = "Do not fail the test if the response body do not have a schema defining it. Useful if the API does not document the application error responses."
)]
Expand All @@ -89,22 +89,22 @@ pub enum Command {
#[clap(about = "Runs auto-genenerated scenarios as performance tests.")]
pub struct PerformanceCommand {
#[clap(
short = "t",
short = 't',
long = "threads",
about = "Number of threads(users) running the performance suite. More users more resources used.",
default_value = "16"
)]
pub users: usize,
#[clap(
short = "r",
short = 'r',
long = "requests",
about = "Number of maximum requests per second to run against the whole service.",
default_value = "100"
)]
pub request_per_second: usize,

#[clap(
short = "l",
short = 'l',
long = "length",
about = "Length of test, as readable time (300s, 20m, 3h, 1h30m, etc.) .",
default_value = "90s"
Expand Down
100 changes: 85 additions & 15 deletions src/command_performance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use lazy_static::lazy_static;
use reqwest::header::{HeaderMap, HeaderValue};
use std::sync::RwLock;
use std::{thread, time};
//use std::sync::Arc;

lazy_static! {
static ref PATH_HEADER_LIST: RwLock<Vec<(reqwest::Url, HeaderMap<HeaderValue>)>> =
Expand All @@ -21,9 +22,11 @@ pub fn run<'a>(
command: PerformanceCommand,
) {
let config = config(command);
//let goose_attack = default_attack(command);

let goose_attack = GooseAttack::initialize_with_config(config.clone())
.setup()
.expect("Failed to setup the performance test.");
// .setup()
.expect("Failed to setup the performance test.");

{
// Need to drop the rwlock after this block so we can read it
Expand All @@ -35,10 +38,43 @@ pub fn run<'a>(
}
}

// let mut taskset = taskset!("WebsiteUser");
// for scenario in scenarios {
// let request = service.runnable_request(scenario.request()).http_request();
// //let url = reqwest::Url::parse(&request.uri().to_string()).unwrap();
// let url = Arc::new(request.uri().to_string()); //.clone();
// let headers = request.headers().clone();

// let closure: GooseTaskFunction = Arc::new(move |user| {

// Box::pin(async move {
// let builder = user
// .client
// .lock()
// .await
// .get(&*url.clone())
// .headers(headers.clone());
// user.goose_send(builder, None).await?;
// Ok(())
// })
// });
// let task = GooseTask::new(closure);
// let new_taskset = taskset.register_task(task);
// taskset = new_taskset;
// }
// let goose_stats = goose_attack
// .register_taskset(taskset)
// .execute()
// .expect("Errors while running performance test");



let indicative = thread::spawn(move || {
// sleep the hatching
let hatching = (config.users.unwrap() / config.hatch_rate) * 1000;
// let hatching : u32 = (config.users.unwrap() / (1 + config.hatch_rate.unwrap().parse().unwrap())) * 1000;
let hatching = 1000; // TODO: this is not correct but hacky for now to make it compile
thread::sleep(time::Duration::from_millis(hatching as u64));
//let slot = parse_timespan("10s") * 10; // total time * 1000 ms / 100 slots

let slot = parse_timespan(&config.run_time) * 10; // total time * 1000 ms / 100 slots
let slot = slot as u64;
Expand All @@ -55,7 +91,7 @@ pub fn run<'a>(
thread::sleep(time::Duration::from_millis(slot));
}
bar.finish();
println!("");
println!();
});

let goose_stats = goose_attack
Expand All @@ -81,6 +117,36 @@ async fn call_url(user: &GooseUser) -> GooseTaskResult {
}
Ok(())
}
/*
fn default_attack(command: PerformanceCommand) -> goose::GooseAttack {
let PerformanceCommand {
users,
request_per_second,
time,
} = command;
let hatch_rate = users * 100;
let empty_args: Vec<&str> = vec![];
let configuration: GooseConfiguration = GooseConfiguration::parse_args_default(&empty_args).unwrap();
goose::GooseAttack::initialize_with_config(configuration).unwrap()
.set_default(GooseDefault::HatchRate, hatch_rate)
.set_default(GooseDefault::Users, users)
.set_default(GooseDefault::Host, "http://localhost:3000")
.set_default(GooseDefault::RunTime, parse_timespan(&time))
.set_default(GooseDefault::StatusCodes, false)
.set_default(GooseDefault::NoTaskMetrics, true)
.set_default(GooseDefault::OnlySummary, false)
.set_default(GooseDefault::MetricsFormat, "json")
.set_default(GooseDefault::MetricsFile, "/tmp/minos_metrics")
.set_default(GooseDefault::ThrottleRequests, request_per_second)
.set_default(GooseDefault::StickyFollow, true)
.set_default(GooseDefault::NoHashCheck, true)
//attack
}
*/

use gumdrop::Options;

fn config(command: PerformanceCommand) -> GooseConfiguration {
let PerformanceCommand {
Expand All @@ -89,30 +155,34 @@ fn config(command: PerformanceCommand) -> GooseConfiguration {
time,
} = command;
let hatch_rate = users * 10; // ramp up in 100 ms, hopefully it is possible.

let empty_args: Vec<&str> = vec![];
// ::default() is not working properly I think it is a bug inn structopt
let mut configuration: GooseConfiguration = GooseConfiguration::default();
configuration.hatch_rate = hatch_rate; // Make 32 users per second
let mut configuration: GooseConfiguration = GooseConfiguration::parse_args_default(&empty_args).unwrap(); //default();
configuration.hatch_rate = Some(hatch_rate.to_string()); // Make 32 users per second
configuration.users = Some(users); // How many users accessing simultaneously
configuration.run_time = time.clone(); // End test after time after users all online
configuration.reset_stats = true; // Stats reset after hatching is completed so only count working hard
configuration.status_codes = false; // Add or not stats about status codes
configuration.only_summary = true; // kill both runnig and final stats :(
// No idea what the below does
configuration.running_metrics = Some(0);
configuration.status_codes = true; // Add or not stats about status codes
configuration.report_file = "/tmp/minos.html".to_string();
// Stuff I do not care about but need to be set for config not to blow up
configuration.stats_log_format = "json".to_string();
configuration.metrics_format = "json".to_string();
configuration.requests_file = "/tmp/minos_metrics".to_string();
configuration.log_file = "/tmp/minos_performance".to_string();
configuration.debug_log_format = "json".to_string();
configuration.debug_log_file = "/tmp/minos_performance_debug".to_string();
configuration.report_file = "/tmp/minos.html".to_string();
configuration.debug_format = "json".to_string();
configuration.debug_file = "/tmp/minos_performance_debug".to_string();
configuration.host = "http://localhost:3000".to_string(); // Dummy. Goose needs this. we overwrite urls later
configuration.throttle_requests = Some(request_per_second);
configuration.throttle_requests = request_per_second;
configuration.no_task_metrics = true;

print!(" Concurrent users: ");
print_value(users);
print!("Max requests per second: ");
print_value(request_per_second);
print!(" Duration: ");
print_value(time);
println!("");
println!();

configuration
}
Expand Down
4 changes: 2 additions & 2 deletions src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ impl RunnableRequest {
self.request
}

pub fn trace_id<'a>(&'a self) -> &'a str {
pub fn trace_id(&self) -> &str {
self.request.headers()["X-B3-TraceID"].to_str().unwrap()
}

Expand Down Expand Up @@ -65,7 +65,7 @@ impl Service {
*request.uri_mut() = format!("{}{}", self.base_url, request.uri())
.parse()
.unwrap();
let mut request = request.map(|body| hyper::Body::from(body));
let mut request = request.map(hyper::Body::from);
self.authentication.authenticate(&mut request);
RunnableRequest::new(request)
}
Expand Down

0 comments on commit 3384b74

Please sign in to comment.