diff --git a/Cargo.lock b/Cargo.lock index de477c2..b05a3ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2762,6 +2762,7 @@ dependencies = [ "console", "env_logger", "indicatif", + "jsonwebtoken", "lambda_runtime", "lazy_static", "libc", diff --git a/resctl-bench/Cargo.toml b/resctl-bench/Cargo.toml index 3876b15..907e8d6 100644 --- a/resctl-bench/Cargo.toml +++ b/resctl-bench/Cargo.toml @@ -24,6 +24,7 @@ aws-sdk-s3 = { version = "0.28.0", optional = true, features = ["rustls", "rt-to aws-sdk-ssm = { version = "0.28.0", optional = true, features = ["rustls", "rt-tokio"], default-features = false } aws_lambda_events = "0.10.0" +jsonwebtoken = "8.3.0" lambda_runtime = { version = "0.8.1", optional = true } md5 = { version = "0.7", optional = true } octocrab = { version = "0.28.0", optional = true, features = ["rustls"], default-features = false } diff --git a/resctl-bench/doc/lambda.md b/resctl-bench/doc/lambda.md index 9a02f11..411099b 100644 --- a/resctl-bench/doc/lambda.md +++ b/resctl-bench/doc/lambda.md @@ -87,6 +87,32 @@ We still need to configure our S3 bucket to allow public read only access, so th } ``` + +We also store the credential parameters required to file a github issue in AWS Systems Manager -> parameter store. +We use github app `iocost-issue-creater` to file a github issue, thus it's credentials information `App Id` and +`Private Key` are stored in parameter store. +``` +{ + /iocost-bot/appid : "xxxx" + /iocost-bot/privatekey : "PEM format key" +} +``` + +AWS lambda flow +=============== +1. User generates the benchmark result on their device. +`$ resctl-bench -r "$RESULT_JSON" --logfile=$LOG_FILE run iocost-tun` +2. User uploads the result to aws lambda function url as: +`resctl-bench -r upload --upload-url ` +e.g +`$resctl-bench --result resctl-bench-result_2022_07_01-00_26_40.json.gz upload --upload-url https://ygvr6jnjckwamfao5xztg6idiu0ukjeb.lambda-url.eu-west-1.on.aws` + +3. Lamda is tiggered automatically in AWS. + - It saves the benchmark result to S3 bucket. + - Then create a issue in iocost-benchmark/iocost-benchmarks project using `iocost-issue-creater` github app. + - Issue contain a link to benchmark result stored in s3 bucket. + + Deploying ========= diff --git a/resctl-bench/src/lambda.rs b/resctl-bench/src/lambda.rs index 7a6f639..9f42a97 100644 --- a/resctl-bench/src/lambda.rs +++ b/resctl-bench/src/lambda.rs @@ -5,6 +5,9 @@ use aws_lambda_events::event::lambda_function_urls::LambdaFunctionUrlRequest; use aws_sdk_s3::error::SdkError; use lambda_runtime::{service_fn, LambdaEvent}; use log::error; +use octocrab::models::InstallationToken; +use octocrab::params::apps::CreateInstallationAccessToken; +use octocrab::Octocrab; use std::io::{Cursor, Read, Write}; use std::os::unix::process::CommandExt; use std::path::Path; @@ -145,10 +148,10 @@ impl LambdaHelper { } pub async fn create_github_issue(&self, title: &str, body: &str) -> Result { - let token = self + let app_id = self .ssm .get_parameter() - .set_name(Some("/iocost-bot/token".to_string())) + .set_name(Some("/iocost-bot/appid".to_string())) .send() .await .expect("Failed to query parameter") @@ -157,8 +160,47 @@ impl LambdaHelper { .value .expect("Parameter value is None"); + let pem = self + .ssm + .get_parameter() + .set_name(Some("/iocost-bot/privatekey".to_string())) + .send() + .await + .expect("Failed to query parameter") + .parameter + .expect("Could not find parameter") + .value + .expect("Parameter value is None"); + + let token = octocrab::auth::create_jwt( + app_id.parse::().unwrap().into(), + &jsonwebtoken::EncodingKey::from_rsa_pem(pem.as_bytes()).unwrap(), + ) + .unwrap(); + + let octocrab = Octocrab::builder().personal_token(token).build()?; + + let installations = octocrab + .apps() + .installations() + .send() + .await + .unwrap() + .take_items(); + + let mut create_access_token = CreateInstallationAccessToken::default(); + create_access_token.repositories = vec!["iocost-benchmarks".to_string()]; + + let access: InstallationToken = octocrab + .post( + installations[0].access_tokens_url.as_ref().unwrap(), + Some(&create_access_token), + ) + .await + .unwrap(); + let issue = octocrab::OctocrabBuilder::new() - .personal_token(token) + .personal_token(access.token) .build()? .issues("iocost-benchmark", "iocost-benchmarks") .create(title)