Initial version
This commit is contained in:
17
nomact/build.rs
Normal file
17
nomact/build.rs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
tonic_prost_build::configure()
|
||||||
|
.build_server(false)
|
||||||
|
.compile_protos(
|
||||||
|
&["../actions-proto-def/proto/runner/v1/services.proto"],
|
||||||
|
&["../actions-proto-def/proto"],
|
||||||
|
)?;
|
||||||
|
|
||||||
|
tonic_prost_build::configure()
|
||||||
|
.build_server(false)
|
||||||
|
.compile_protos(
|
||||||
|
&["../actions-proto-def/proto/ping/v1/services.proto"],
|
||||||
|
&["../actions-proto-def/proto"],
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
115
nomact/src/lib.rs
Normal file
115
nomact/src/lib.rs
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
use std::vec;
|
||||||
|
|
||||||
|
pub mod runner {
|
||||||
|
tonic::include_proto!("runner.v1");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod ping {
|
||||||
|
tonic::include_proto!("ping.v1");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RegisterConfig {
|
||||||
|
pub name: String,
|
||||||
|
pub register_token: String,
|
||||||
|
pub instance: hyper::Uri,
|
||||||
|
pub version: String,
|
||||||
|
pub labels: Vec<String>,
|
||||||
|
pub ephemeral: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct RegisteredRunner {
|
||||||
|
pub uuid: String,
|
||||||
|
pub token: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn instance_to_api_url(instance: hyper::Uri) -> hyper::Uri {
|
||||||
|
let mut parts = instance.into_parts();
|
||||||
|
parts.path_and_query = Some("/api/actions".try_into().unwrap());
|
||||||
|
hyper::Uri::from_parts(parts).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn register(conf: RegisterConfig) -> Result<RegisteredRunner, ()> {
|
||||||
|
use hyper_rustls::ConfigBuilderExt;
|
||||||
|
|
||||||
|
let tls = rustls::ClientConfig::builder()
|
||||||
|
.with_native_roots()
|
||||||
|
.unwrap()
|
||||||
|
.with_no_client_auth();
|
||||||
|
// Prepare the HTTPS connector
|
||||||
|
let https = hyper_rustls::HttpsConnectorBuilder::new()
|
||||||
|
.with_tls_config(tls)
|
||||||
|
.https_or_http()
|
||||||
|
.enable_http1()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Must use hyper directly...
|
||||||
|
let client = hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new())
|
||||||
|
.build(https);
|
||||||
|
|
||||||
|
let svc = tower::ServiceBuilder::new()
|
||||||
|
.layer(tonic_web::GrpcWebClientLayer::new())
|
||||||
|
.service(client);
|
||||||
|
|
||||||
|
let uri = instance_to_api_url(conf.instance);
|
||||||
|
|
||||||
|
let mut client = runner::runner_service_client::RunnerServiceClient::with_origin(svc, uri);
|
||||||
|
|
||||||
|
let request = tonic::Request::new(runner::RegisterRequest {
|
||||||
|
name: conf.name,
|
||||||
|
token: conf.register_token,
|
||||||
|
version: conf.version,
|
||||||
|
labels: conf.labels,
|
||||||
|
ephemeral: conf.ephemeral,
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
|
||||||
|
let response = client.register(request).await.unwrap();
|
||||||
|
|
||||||
|
match response.into_inner().runner {
|
||||||
|
Some(runner) => Ok(RegisteredRunner {
|
||||||
|
uuid: runner.uuid,
|
||||||
|
token: runner.token,
|
||||||
|
}),
|
||||||
|
None => Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn run_task<T>(
|
||||||
|
client: &mut runner::runner_service_client::RunnerServiceClient<T>,
|
||||||
|
task: runner::Task,
|
||||||
|
) where
|
||||||
|
T: tonic::client::GrpcService<tonic::body::Body>,
|
||||||
|
T::Error: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
|
||||||
|
T::ResponseBody: http_body::Body<Data = prost::bytes::Bytes> + std::marker::Send + 'static,
|
||||||
|
<T::ResponseBody as http_body::Body>::Error:
|
||||||
|
Into<Box<dyn std::error::Error + Send + Sync + 'static>> + std::marker::Send,
|
||||||
|
{
|
||||||
|
tracing::debug!(?task, "Run-Task");
|
||||||
|
|
||||||
|
let workflow = core::str::from_utf8(task.workflow_payload()).unwrap();
|
||||||
|
tracing::info!("Raw-Workflow: {}", workflow);
|
||||||
|
|
||||||
|
let task_id = task.id;
|
||||||
|
let task_workflow = core::str::from_utf8(task.workflow_payload()).unwrap();
|
||||||
|
let task_context = task.context.as_ref();
|
||||||
|
let task_secrets = &task.secrets;
|
||||||
|
let task_needs = &task.needs;
|
||||||
|
let task_vars = &task.vars;
|
||||||
|
|
||||||
|
let workflow = serde_yaml::from_slice::<serde_yaml::Value>(task.workflow_payload());
|
||||||
|
tracing::info!("Workflow: {:?}", &workflow);
|
||||||
|
|
||||||
|
let update_req = tonic::Request::new(runner::UpdateTaskRequest {
|
||||||
|
outputs: std::collections::HashMap::new(),
|
||||||
|
state: Some(runner::TaskState {
|
||||||
|
id: task.id,
|
||||||
|
result: runner::Result::Failure.into(),
|
||||||
|
started_at: None,
|
||||||
|
stopped_at: None,
|
||||||
|
steps: vec![],
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
let resp = client.update_task(update_req).await.unwrap();
|
||||||
|
tracing::info!(resp = tracing::field::debug(resp.get_ref()), "Update Task State");
|
||||||
|
}
|
||||||
122
nomact/src/main.rs
Normal file
122
nomact/src/main.rs
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
use hyper_rustls::ConfigBuilderExt;
|
||||||
|
use tracing_subscriber::layer::SubscriberExt;
|
||||||
|
|
||||||
|
use nomact::runner;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let registry = tracing_subscriber::registry().with(tracing_subscriber::fmt::layer());
|
||||||
|
tracing::subscriber::set_global_default(registry).unwrap();
|
||||||
|
|
||||||
|
tracing::info!("Starting...");
|
||||||
|
|
||||||
|
let rt = tokio::runtime::Builder::new_current_thread()
|
||||||
|
.enable_all()
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let register_token = include_str!("../../register_token");
|
||||||
|
let instance_url = include_str!("../../instance_url");
|
||||||
|
let name = "Testing";
|
||||||
|
|
||||||
|
let runner = rt.block_on(async move {
|
||||||
|
let path = "./runner_state.json";
|
||||||
|
match tokio::fs::try_exists(path).await {
|
||||||
|
Ok(true) => {
|
||||||
|
tracing::info!("Using already registered runner");
|
||||||
|
|
||||||
|
let content = tokio::fs::read(path).await.unwrap();
|
||||||
|
serde_json::from_slice::<nomact::RegisteredRunner>(&content).unwrap()
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
tracing::info!("Registering new runner");
|
||||||
|
|
||||||
|
let runner = nomact::register(nomact::RegisterConfig {
|
||||||
|
name: name.into(),
|
||||||
|
register_token: register_token.into(),
|
||||||
|
instance: hyper::Uri::from_static(instance_url),
|
||||||
|
version: "0.0.1".into(),
|
||||||
|
labels: Vec::new(),
|
||||||
|
ephemeral: false,
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
tracing::info!(?runner, "Registered Runner");
|
||||||
|
|
||||||
|
let serialized = serde_json::to_vec(&runner).unwrap();
|
||||||
|
tokio::fs::write(path, serialized).await.unwrap();
|
||||||
|
|
||||||
|
runner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
rt.block_on(async move {
|
||||||
|
let tls = rustls::ClientConfig::builder()
|
||||||
|
.with_native_roots()
|
||||||
|
.unwrap()
|
||||||
|
.with_no_client_auth();
|
||||||
|
// Prepare the HTTPS connector
|
||||||
|
let https = hyper_rustls::HttpsConnectorBuilder::new()
|
||||||
|
.with_tls_config(tls)
|
||||||
|
.https_or_http()
|
||||||
|
.enable_http1()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Must use hyper directly...
|
||||||
|
let client =
|
||||||
|
hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new())
|
||||||
|
.build(https);
|
||||||
|
|
||||||
|
let svc = tower::ServiceBuilder::new()
|
||||||
|
.layer(tonic_web::GrpcWebClientLayer::new())
|
||||||
|
.service(client);
|
||||||
|
|
||||||
|
let mut client = runner::runner_service_client::RunnerServiceClient::with_origin(
|
||||||
|
tonic::service::interceptor::InterceptedService::new(
|
||||||
|
svc,
|
||||||
|
move |mut req: tonic::Request<()>| {
|
||||||
|
req.metadata_mut()
|
||||||
|
.insert("x-runner-uuid", runner.uuid.as_str().try_into().unwrap());
|
||||||
|
req.metadata_mut()
|
||||||
|
.insert("x-runner-token", runner.token.as_str().try_into().unwrap());
|
||||||
|
|
||||||
|
Ok(req)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
nomact::instance_to_api_url(hyper::Uri::from_static(instance_url))
|
||||||
|
);
|
||||||
|
|
||||||
|
let request = tonic::Request::new(runner::DeclareRequest {
|
||||||
|
version: "0.0.2".into(),
|
||||||
|
labels: vec![
|
||||||
|
"ubuntu-latest".into(),
|
||||||
|
"ubuntu-22.04".into(),
|
||||||
|
"ubuntu-20.04".into(),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
let response = client.declare(request).await.unwrap();
|
||||||
|
tracing::info!(runner = tracing::field::debug(response.get_ref().runner.as_ref()), "Declare current runner state");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let mut task_id = 0;
|
||||||
|
loop {
|
||||||
|
tracing::info!("Checking for new Task");
|
||||||
|
|
||||||
|
let request = tonic::Request::new(runner::FetchTaskRequest {
|
||||||
|
tasks_version: task_id,
|
||||||
|
});
|
||||||
|
|
||||||
|
let response = client.fetch_task(request).await.unwrap();
|
||||||
|
|
||||||
|
task_id = response.get_ref().tasks_version;
|
||||||
|
|
||||||
|
if let Some(task) = response.into_inner().task {
|
||||||
|
nomact::run_task(&mut client, task).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
tokio::time::sleep(std::time::Duration::from_secs(30)).await;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user