-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.rs
122 lines (101 loc) · 4.48 KB
/
main.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use std::path::PathBuf;
use clap::{Arg, Command};
use futures::TryFutureExt;
use openapi::apis::{configuration, configuration::Configuration, Error, ResponseContent};
use openapi::apis::k6_report_ingress_api::UploadJsonReportError;
use reqwest::Body;
use reqwest::multipart::Part;
use tokio::fs::File;
use tokio_util::codec::{BytesCodec, FramedRead};
#[tokio::main]
async fn main() {
let matches = Command::new("k6-dashboard")
.version("0.0.0")
.author("Timon Borter")
.about("A K6 Dashboard with History")
.subcommand_required(true)
.arg_required_else_help(true)
.subcommand(
Command::new("upload")
.about("Upload a JSON report file")
.arg(
Arg::new("FILE")
.required(true)
.index(1)
.help("Sets the input file to use")
)
.arg(
Arg::new("url")
.short('u')
.required(true)
.help("The URL of the backend API")
)
)
.get_matches();
if let Some(upload_matches) = matches.subcommand_matches("upload") {
if let Some(file) = upload_matches.get_one::<String>("FILE") {
let url = upload_matches.get_one::<String>("url").unwrap(); // Safe to use unwrap() since it's a required argument
upload_json_report_with_client(file, url).await;
}
}
}
async fn upload_json_report_with_client(file_path: &str, base_path: &str) {
let config = Configuration::from(
Configuration {
base_path: base_path.to_owned(),
..Configuration::default()
}
);
let path_buf = PathBuf::from(file_path);
upload_json_report(&config, Some(path_buf))
.map_ok(|_| {
println!("Success");
})
.map_err(|e| {
println!("Failed: {:?}", e);
})
.await
.expect("Failed to upload JSON report");
}
// Based on client/src/apis/k6_report_ingress_api.rs, because it does not support Multipart/Form
// requests with files.
/// Accepts a JSON report generated by K6 load testing tool.
pub async fn upload_json_report(configuration: &configuration::Configuration, report_file: Option<std::path::PathBuf>) -> Result<(), Error<UploadJsonReportError>> {
let local_var_configuration = configuration;
let local_var_client = &local_var_configuration.client;
let local_var_uri_str = format!("{}/api/rest/v1/k6/reports", local_var_configuration.base_path);
let mut local_var_req_builder = local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str());
if let Some(ref local_var_user_agent) = local_var_configuration.user_agent {
local_var_req_builder = local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone());
}
let mut local_var_form = reqwest::multipart::Form::new();
if let Some(report_file_path) = report_file {
let report_file_path_clone = report_file_path.clone();
let file = File::open(report_file_path.as_path()).await.expect("Failed to open JSON report file");
let file_body = file_to_body(file);
let file_name = report_file_path_clone.file_name().unwrap().to_str().unwrap().to_owned();
let report_mime_file = Part::stream(file_body)
.file_name(file_name)
.mime_str("application/json")?;
local_var_form = local_var_form.part("reportFile", report_mime_file);
}
local_var_req_builder = local_var_req_builder.multipart(local_var_form);
let local_var_req = local_var_req_builder.build()?;
let local_var_resp = local_var_client.execute(local_var_req).await?;
let local_var_status = local_var_resp.status();
let local_var_content = local_var_resp.text().await?;
if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
Ok(())
} else {
let local_var_entity: Option<UploadJsonReportError> = serde_json::from_str(&local_var_content).ok();
let local_var_error = ResponseContent { status: local_var_status, content: local_var_content, entity: local_var_entity };
Err(Error::ResponseError(local_var_error))
}
}
// See: https://stackoverflow.com/a/65815578
// See: https://docs.rs/tokio/latest/tokio/fs/struct.File.html
fn file_to_body(file: File) -> Body {
let stream = FramedRead::new(file, BytesCodec::new());
let body = Body::wrap_stream(stream);
body
}