connectrpc is not grpc

This commit is contained in:
sevki 2024-06-05 20:06:52 +01:00
parent 68b98de797
commit a088110476
6 changed files with 1271 additions and 213 deletions

1153
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -10,11 +10,16 @@ license = "MIT"
build = "build.rs"
[dependencies]
axum = "0.7.5"
axum-connect = "0.3.2"
okstd = { version = "0.1.9", registry = "oksoftware", features = ["macros"] }
prost = "0.12"
prost-types = "0.12"
tokio = { version = "1.38.0", features = ["full"] }
tonic = "0.11.0"
[build-dependencies]
prost-build = "0.12.6"
tonic-build = "0.11"
hyper = { version = "0.14" }
hyper = { version = "0.14" }
axum-connect-build = "0.3.2"

View file

@ -1,3 +1,4 @@
use axum_connect_build::{axum_connect_codegen, AxumConnectGenSettings};
use std::env;
use std::path::PathBuf;
use std::process::Command;
@ -15,7 +16,7 @@ fn main() {
"-L",
"-o",
outfile.to_str().unwrap(),
"https://ok.software/ok/actions-proto-def/archive/main.tar.gz",
"https://ok.software/mirrors/actions-proto-def/archive/main.tar.gz",
])
.status()
.unwrap();
@ -32,29 +33,32 @@ fn main() {
.unwrap();
// Check if protoc is installed
let status = Command::new("protoc").arg("--version").status().unwrap();
if !status.success() {
panic!("protoc is not installed");
let status = Command::new("protoc").arg("--version").status();
match status {
Err(_) => panic!("protoc is not installed"),
_ => {}
}
let protos_dir = out_dir.join("actions-proto-def/proto");
let settings = AxumConnectGenSettings::from_directory_recursive(protos_dir.to_str().unwrap())
.expect("failed to glob protos");
axum_connect_codegen(settings).unwrap();
// // Create longer-lived values for the proto paths
// let ping_proto_path = out_dir.join("actions-proto-def/proto/ping/v1/services.proto");
// let runner_proto_path = out_dir.join("actions-proto-def/proto/runner/v1/services.proto");
// let proto_files = &[
// ping_proto_path.to_str().unwrap(),
// runner_proto_path.to_str().unwrap(),
// ];
// Create longer-lived values for the proto paths
let ping_proto_path = out_dir.join("actions-proto-def/proto/ping/v1/services.proto");
let runner_proto_path = out_dir.join("actions-proto-def/proto/runner/v1/services.proto");
// let includes_path = out_dir.join("actions-proto-def/proto/");
let proto_files = &[
ping_proto_path.to_str().unwrap(),
runner_proto_path.to_str().unwrap(),
];
let includes_path = out_dir.join("actions-proto-def/proto/");
// Compile the proto files
// Compile the proto files using tonic_build
tonic_build::configure()
.out_dir(&out_dir)
.compile(proto_files, &[includes_path])
.unwrap();
// // Compile the proto files
// // Compile the proto files using tonic_build
// tonic_build::configure()
// .out_dir(&out_dir)
// .compile(proto_files, &[includes_path])
// .unwrap();
// // Generate additional services and codecs as needed
// let descriptor_set_path = out_dir.join("descriptor.bin");
@ -62,5 +66,4 @@ fn main() {
// .file_descriptor_set_path(&descriptor_set_path)
// .compile(proto_files, &[includes_path])
// .unwrap();
}
}

View file

@ -9,7 +9,7 @@ repository = "https://ok.software/ok/runner_rs.git"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
actions-proto-rs = { version = "0.1.1", registry = "oksoftware" }
actions-proto-rs = { version = "*", path = ".." }
url = "2.2.2"
argh = "0.1.1"
hyper = { version = "0.14" }
@ -18,11 +18,13 @@ tokio = { version = "1.37.0", features = ["full"] }
tonic = "0.11.0"
tonic-web = "0.11.0"
tower = "0.4.13"
uuid = { version = "1.8.0", features = [
"v4",
"v1",
"v3",
"v5",
"v8",
] }
uuid = { version = "1.8.0", features = ["v4"] }
okstd = { version = "0.1.9", registry = "oksoftware", features = ["macros"] }
axum-connect = "0.3.2"
prost = "0.12.6"
axum = "0.7.5"
serde_json = "1.0.117"
http = "1.1.0"
serde = "1.0.203"
bytes = "1.6.0"
http-body-util = "0.1.1"

View file

@ -1,30 +1,37 @@
use actions_proto_rs::ping_service_client::PingServiceClient;
use actions_proto_rs::runner_service_client::RunnerServiceClient;
use actions_proto_rs::RegisterRequest;
use hyper::Uri;
use hyper::client::HttpConnector;
use hyper::Client;
use hyper_tls::HttpsConnector;
use tonic::codegen::InterceptedService;
use tonic::metadata::AsciiMetadataValue;
use tonic::metadata::MetadataMap;
use tonic::metadata::MetadataValue;
use tonic::service::Interceptor;
use tonic::Extensions;
use tonic::{transport::Channel, Request};
use tonic_web::GrpcWebClientLayer;
use url::Url;
use actions_proto_rs::{FetchTaskRequest, FetchTaskResponse, PingRequest, RegisterRequest, RegisterResponse};
use argh::FromArgs;
use axum::http::{HeaderMap, HeaderValue};
use hyper::{Client, Uri};
use hyper_tls::HttpsConnector;
use okstd::prelude::*;
use serde_json::json;
use bytes::Bytes;
use http_body_util::{BodyExt, Empty};
use hyper::{body::Buf, Request};
use serde::Deserialize;
const UUID_HEADER_KEY: &str = "x-runner-uuid";
const TOKEN_HEADER_KEY: &str = "x-runner-token";
const VERSION_HEADER_KEY: &str = "x-runner-version";
// Structure to hold command-line arguments
#[derive(FromArgs, Debug)]
/// Actions Runner Client
struct Gump {
#[argh(subcommand)]
nested: Commands,
}
#[derive(FromArgs, Debug)]
#[argh(subcommand)]
enum Commands {
Ping(PingCmd),
Register(RegisterCmd),
}
#[derive(FromArgs, Debug)]
/// Ping Command
#[argh(subcommand, name = "ping")]
struct PingCmd {
/// authentication token
#[argh(option, short = 't', long = "token")]
token: String,
@ -39,60 +46,110 @@ struct Gump {
base_url: Option<String>,
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Parse arguments using argh
#[derive(FromArgs, Debug)]
/// Register Command
#[argh(subcommand, name = "register")]
struct RegisterCmd {
/// authentication token
#[argh(option, short = 't', long = "token")]
token: String,
/// runner version
#[argh(option, short = 'v', long = "version")]
version: Option<String>,
/// unique identifier
#[argh(option, short = 'u', long = "uuid")]
uuid: Option<String>,
/// base URL of the API server
#[argh(option, short = 'b', long = "base-url")]
base_url: Option<String>,
}
#[okstd::log(trace)]
#[okstd::main]
async fn main() {
let args: Gump = argh::from_env();
// Parse base URL
let base_url = args.base_url.unwrap_or("https://ok.software/api/actions".to_string());
let version = args.version.unwrap_or(concat!("v", env!("CARGO_PKG_VERSION")).to_string());
let base_url = base_url.parse::<Uri>().unwrap();
let client = hyper::Client::builder().build(HttpsConnector::new());
let svc = tower::ServiceBuilder::new()
.layer(GrpcWebClientLayer::new())
.service(client);
let mut runner_client = RunnerServiceClient::with_origin(
svc.clone(),
base_url.clone(),
);
let mut ping_client = PingServiceClient::with_origin(svc, base_url);
let token = args.token;
let uuid = args.uuid.unwrap_or(uuid::Uuid::new_v4().to_string());
// Log the client creation
println!("Client created with UUID: {}", uuid);
let mut metadata = MetadataMap::new();
metadata.insert(VERSION_HEADER_KEY, version.parse().unwrap());
metadata.insert(UUID_HEADER_KEY, uuid.parse().unwrap());
metadata.insert(TOKEN_HEADER_KEY, token.parse().unwrap());
metadata.insert(VERSION_HEADER_KEY, version.parse().unwrap());
// register meta data needs to be empty
let reg_metadata = metadata.clone();
// ping request
let ping_request = Request::from_parts(
reg_metadata.clone(),
Extensions::default(),
actions_proto_rs::PingRequest {
data: "nixos".to_string(),
},
);
// Log ping request
println!("Ping Request: {:?}", ping_request);
match ping_client.ping(ping_request).await {
Ok(resp) => {
println!("Response: {:?}", resp);
}
Err(e) => {
println!("Error: {:?}", e);
}
match args.nested {
Commands::Ping(cmd) => handle_ping(cmd).await,
Commands::Register(cmd) => handle_register(cmd).await,
}
.expect("command didn't run successfully");
}
async fn handle_ping(cmd: PingCmd) -> Result<(), Box<dyn std::error::Error>> {
let base_url = cmd
.base_url
.unwrap_or("https://ok.software/api/actions".to_string());
let version = cmd
.version
.unwrap_or(concat!("v", env!("CARGO_PKG_VERSION")).to_string());
let base_uri = Uri::builder()
.scheme("https")
.authority("ok.software")
.path_and_query("/api/actions/ping.v1.PingService/Ping")
.build()
.unwrap();
let https = HttpsConnector::new();
let client = Client::builder().build::<_, hyper::Body>(https);
let token = cmd.token;
let uuid = cmd.uuid.unwrap_or(uuid::Uuid::new_v4().to_string());
info!("Ping client created with UUID: {}", uuid);
let mut headers = HeaderMap::new();
headers.insert(VERSION_HEADER_KEY, HeaderValue::from_str(&version).unwrap());
headers.insert(UUID_HEADER_KEY, HeaderValue::from_str(&uuid).unwrap());
headers.insert(TOKEN_HEADER_KEY, HeaderValue::from_str(&token).unwrap());
let ping_request = PingRequest {
data: "nixos".to_string(),
};
let request = hyper::Request::builder()
.method(hyper::Method::POST)
.uri(base_uri)
.header("Content-Type", "application/json")
.header(VERSION_HEADER_KEY, version)
.header(UUID_HEADER_KEY, uuid)
.header(TOKEN_HEADER_KEY, token)
.body(hyper::Body::from(json!(ping_request).to_string()))
.unwrap();
info!("Ping Request: {:?}", request);
let response = client.request(request).await?;
info!("Ping Response: {:?}", response);
Ok(())
}
async fn handle_register(cmd: RegisterCmd) -> Result<(), Box<dyn std::error::Error>> {
let base_url = cmd
.base_url
.unwrap_or("https://ok.software/api/actions".to_string());
let version = cmd
.version
.unwrap_or(concat!("v", env!("CARGO_PKG_VERSION")).to_string());
let base_uri = Uri::builder()
.scheme("https")
.authority("ok.software")
.path_and_query("/api/actions/runner.v1.RunnerService/Register")
.build()
.unwrap();
let https = HttpsConnector::new();
let client = Client::builder().build::<_, hyper::Body>(https);
let token = cmd.token;
let uuid = cmd.uuid.unwrap_or(uuid::Uuid::new_v4().to_string());
info!("Register client created with UUID: {}", uuid);
let mut headers = HeaderMap::new();
headers.insert(VERSION_HEADER_KEY, HeaderValue::from_str(&version).unwrap());
headers.insert(UUID_HEADER_KEY, HeaderValue::from_str(&uuid).unwrap());
headers.insert(TOKEN_HEADER_KEY, HeaderValue::from_str(&token).unwrap());
let labels = vec![
"ubuntu-latest:docker://gitea/runner-images:ubuntu-latest".to_string(),
@ -100,42 +157,31 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
"ubuntu-20.04:docker://gitea/runner-images:ubuntu-20.04".to_string(),
];
// Log metadata
println!("Metadata: {:?}", metadata);
let request = Request::from_parts(
reg_metadata,
Extensions::default(),
RegisterRequest {
name: "nixos".to_string(),
version: version,
token: token.to_string(),
labels: labels.clone(),
agent_labels: labels,
custom_labels: vec![],
},
);
let register_request = RegisterRequest {
name: "nixos".to_string(),
version: version.clone(),
token: token.clone(),
labels: labels.clone(),
agent_labels: labels.clone(),
custom_labels: vec![],
};
// Log request
println!("Request: {:?}", request);
let resp = runner_client.register(request).await;
match resp {
Ok(resp) => {
println!("Response: {:?}", resp);
}
Err(e) => {
println!("Error: {:?}", e);
}
}
let fetch_task_request = Request::from_parts(
metadata,
Extensions::default(),
actions_proto_rs::FetchTaskRequest { tasks_version: 0 },
);
// Log fetch task request
println!("Fetch Task Request: {:?}", fetch_task_request);
let response = runner_client.fetch_task(fetch_task_request).await?;
let request = hyper::Request::builder()
.method(hyper::Method::POST)
.uri(base_uri)
.header("Content-Type", "application/json")
.header(VERSION_HEADER_KEY, version)
.header(UUID_HEADER_KEY, uuid)
.header(TOKEN_HEADER_KEY, token)
.body(hyper::Body::from(json!(register_request).to_string()))
.unwrap();
info!("Register Request: {:?}", request);
let response = client.request(request).await?;
info!("Register Response: {:?}", response);
let body = hyper::body::aggregate(response).await?;
let register_response: RegisterResponse = serde_json::from_reader(body.reader())?;
info!("Register Response: {:?}", register_response);
Ok(())
}

3
rust-toolchain Normal file
View file

@ -0,0 +1,3 @@
[toolchain]
channel = "1.78"
components = [ "rustfmt", "clippy", "llvm-tools-preview", "rust-src" ]