Skip to content

Commit 48946d6

Browse files
authored
Merge pull request #2236 from oasisprotocol/kostko/feature/rofl-scheduler-api-logs
rofl-scheduler: Add API endpoint and route to get logs
2 parents eef00b8 + 32f0c68 commit 48946d6

File tree

21 files changed

+2633
-1246
lines changed

21 files changed

+2633
-1246
lines changed

Cargo.lock

Lines changed: 770 additions & 348 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

contract-sdk/specs/access/oas173/Cargo.lock

Lines changed: 163 additions & 155 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

contract-sdk/specs/token/oas20/Cargo.lock

Lines changed: 163 additions & 155 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/runtime-sdk/rofl-oracle-tdx/Cargo.lock

Lines changed: 220 additions & 201 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/runtime-sdk/rofl-oracle/Cargo.lock

Lines changed: 154 additions & 147 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rofl-scheduler/Cargo.toml

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,38 @@ oasis-runtime-sdk-rofl-market = { path = "../runtime-sdk/modules/rofl-market" }
1212
# Third party.
1313
anyhow = "1.0.86"
1414
async_zip = { version = "0.0.17", features = ["deflate", "tokio"] }
15-
backoff = "0.4"
15+
axum = "0.8.4"
16+
axum-extra = { version = "0.10.1", features = ["typed-header"] }
17+
axum-server = { version = "0.7.2", features = ["tls-rustls"] }
18+
backoff = { version = "0.4", features = ["tokio"] }
1619
base64 = "0.22.1"
1720
bytes = "1.10.1"
21+
chrono = "0.4.41"
1822
cmd_lib = "1.9.5"
1923
hex = "0.4.3"
24+
# TODO: Use 0.8.0 once released.
25+
instant-acme = { git = "https://github.com/djc/instant-acme", rev = "5e59869f54e66b7dff8c2c0ea63599fbcc3595af" }
26+
jsonwebtoken = "9"
2027
nix = { version = "0.29.0", features = ["signal"] }
2128
oci-client = "0.14.0"
2229
qcow2-rs = "0.1.6"
2330
rand = "0.8.4"
31+
rcgen = "0.13.2"
2432
rustc-hex = "2.0.1"
33+
rustls = "0.23.27"
2534
serde = { version = "1.0", features = ["derive"] }
2635
serde_json = "1.0"
2736
sha2 = "0.10.8"
28-
tokio = { version = "1.38", features = ["rt", "rt-multi-thread", "sync", "time", "macros"] }
37+
siwe = "0.6.1"
38+
thiserror = "2"
39+
tokio = { version = "1.38", features = [
40+
"rt",
41+
"rt-multi-thread",
42+
"sync",
43+
"time",
44+
"macros",
45+
] }
2946
tokio-util = { version = "0.7.14", features = ["compat"] }
47+
tower = "0.5.2"
48+
tower-http = { version = "0.6.6", features = ["cors"] }
49+
x509-parser = "0.17.0"

rofl-scheduler/rofl.yaml

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: rofl-scheduler
2-
version: 0.1.2
2+
version: 0.2.0
33
repository: https://github.com/oasisprotocol/oasis-sdk
44
tee: tdx
55
kind: raw
@@ -11,9 +11,9 @@ resources:
1111
size: 64
1212
artifacts:
1313
builder: ghcr.io/oasisprotocol/rofl-dev:v0.1.0@sha256:1d2b77c25811f70219f366153265702417e0e4a08067a68cce4d132e253d7607
14-
firmware: https://github.com/oasisprotocol/oasis-boot/releases/download/v0.4.2/ovmf.tdx.fd#db47100a7d6a0c1f6983be224137c3f8d7cb09b63bb1c7a5ee7829d8e994a42f
15-
kernel: https://github.com/oasisprotocol/oasis-boot/releases/download/v0.4.2/stage1.bin#02903bd0ddfe1e3552e95767f1be17e801690d73d90bb1e800aa4879ba46c4d7
16-
stage2: https://github.com/oasisprotocol/oasis-boot/releases/download/v0.4.2/stage2-basic.tar.bz2#72c84d2566959799fdd98fae08c143a8572a5a09ee426be376f9a8bbd1675f2b
14+
firmware: https://github.com/oasisprotocol/oasis-boot/releases/download/v0.5.0/ovmf.tdx.fd#db47100a7d6a0c1f6983be224137c3f8d7cb09b63bb1c7a5ee7829d8e994a42f
15+
kernel: https://github.com/oasisprotocol/oasis-boot/releases/download/v0.5.0/stage1.bin#23877530413a661e9187aad2eccfc9660fc4f1a864a1fbad2f6c7d43512071ca
16+
stage2: https://github.com/oasisprotocol/oasis-boot/releases/download/v0.5.0/stage2-basic.tar.bz2#72c84d2566959799fdd98fae08c143a8572a5a09ee426be376f9a8bbd1675f2b
1717
deployments:
1818
mainnet:
1919
app_id: rofl1qr95suussttd2g9ehu3zcpgx8ewtwgayyuzsl0x2
@@ -35,7 +35,11 @@ deployments:
3535
- id: OW90gvblTearxfeELGeLmV9/95UmSzmH/qCkqzuplFYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
3636
version: 0.1.1
3737
- id: lkRxF1Ps6zqhEypa3o8VghPtUHE5PMv4v1dPN54kuZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
38+
version: 0.1.2
3839
- id: qegcmpWD7YHForsxaqdAWcou+Njporf2A4tmgNQ2XuIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
40+
version: 0.1.2
41+
- id: uprcd2wbFvXZ7US3vminHlONmOsbaU20Ll/XFn22U4kAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
42+
- id: d8+W9SL9GLSjlox5EahAzQdb/ruz4Qb2al4l9+gsDfUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
3943
endorsements:
4044
- any: {}
4145
fees: endorsing_node
@@ -55,12 +59,6 @@ deployments:
5559
min_tcb_evaluation_data_number: 18
5660
tdx: {}
5761
enclaves:
58-
- id: 2OKs276ykwRIRetgtYGQJMOyfI5FyZ861qMvZGgHVikAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
59-
version: 0.1.0-pre
60-
description: Pre-release version of the scheduler
61-
- id: gjsdGO/HZda3cpvIVp7se/EAUHf80TCKb60IEJ+ba4EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
62-
version: 0.1.0-pre
63-
description: Pre-release version of the scheduler
6462
- id: PE2TSgy9aMfAmxGIDgMpbjr9ejk2evb2wdzaBEkA4TMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
6563
version: 0.1.0
6664
- id: +3Sv/xqzc171KyieVot07v8H7lCGpSqIuaDelVmTE8IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
@@ -70,7 +68,11 @@ deployments:
7068
- id: akLPdeqNVejSkZ807J4KA8kilCv8noHqZ5KOO5RvCJIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
7169
version: 0.1.1
7270
- id: +ZT1Qg8ZVUPS77VTZDFXwqgOnz/TPcWBTX4her22GL4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
71+
version: 0.1.2
7372
- id: FvdH6lM8tThmGJNLYf/rC/qzU3VuplyCP5JkZ7RVejUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
73+
version: 0.1.2
74+
- id: 5pgjooS9Su7Ic+qAFhlBLXgVDrwmKUErrSKEOfIXWHYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
75+
- id: JronXGA4H36ZRJsNQn0qRpWlinNIb7wvk/MhZqKF1S4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
7476
endorsements:
7577
- any: {}
7678
fees: endorsing_node

rofl-scheduler/src/config.rs

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,30 @@
1-
use std::collections::{BTreeMap, BTreeSet};
1+
use std::{
2+
collections::{BTreeMap, BTreeSet},
3+
sync::Arc,
4+
};
25

36
use anyhow::{anyhow, Result};
47
use base64::prelude::*;
58

69
use oasis_runtime_sdk::{
710
cbor,
8-
core::common::crypto::{hash::Hash, signature::PublicKey},
9-
modules::rofl::app::prelude::*,
11+
core::{
12+
common::crypto::{hash::Hash, signature::PublicKey},
13+
Protocol,
14+
},
1015
types::address::Address,
1116
};
1217
use oasis_runtime_sdk_rofl_market as market;
1318

14-
use crate::SchedulerApp;
15-
1619
/// Local configuration key that contains the ROFL scheduler configuration.
1720
const ROFL_SCHEDULER_CONFIG_KEY: &str = "rofl_scheduler";
1821

1922
/// Raw local configuration as serialized.
2023
#[derive(Clone, Debug, Default, cbor::Decode)]
21-
struct RawLocalConfig {
24+
pub struct RawLocalConfig {
2225
/// Address of the provider.
2326
pub provider_address: String,
24-
/// Offers that the scheduler should accept.
27+
/// Offers that the scheduler should accept. If no offers are configured, all are accepted.
2528
///
2629
/// Each offer identifier is the value of the `net.oasis.scheduler.offer` metadata key.
2730
pub offers: BTreeSet<String>,
@@ -44,6 +47,24 @@ struct RawLocalConfig {
4447
pub deploy_pull_timeout: Option<u64>,
4548
/// A list of node addresses to transfer the instances from.
4649
pub transfer_instances_from: Vec<String>,
50+
/// Domain used to serve the scheduler API endpoint. If not set, the endpoint is disabled.
51+
pub api_domain: Option<String>,
52+
/// Lifetime of issued JWT tokens for API access (in seconds).
53+
pub api_token_lifetime: Option<u64>,
54+
}
55+
56+
impl RawLocalConfig {
57+
/// Create a new raw local config by parsing the CBOR provided by the host.
58+
pub fn new(host: Arc<Protocol>) -> Result<Self> {
59+
let cfg = host
60+
.get_host_info()
61+
.local_config
62+
.remove(ROFL_SCHEDULER_CONFIG_KEY)
63+
.map(cbor::from_value)
64+
.transpose()?
65+
.unwrap_or_default();
66+
Ok(cfg)
67+
}
4768
}
4869

4970
/// Resources.
@@ -109,18 +130,21 @@ pub struct LocalConfig {
109130
pub deploy_pull_timeout: u64,
110131
/// A list of node addresses to transfer the instances from.
111132
pub transfer_instances_from: BTreeSet<PublicKey>,
133+
/// Domain used to serve the scheduler API endpoint. If not set, the endpoint is disabled.
134+
pub api_domain: Option<String>,
135+
/// Lifetime of issued JWT tokens for API access (in seconds).
136+
pub api_token_lifetime: u64,
112137
}
113138

114139
impl LocalConfig {
115-
/// Read local configuration.
116-
pub fn from_env(env: Environment<SchedulerApp>) -> Result<Self> {
117-
let cfg: RawLocalConfig = env
118-
.untrusted_local_config()
119-
.remove(ROFL_SCHEDULER_CONFIG_KEY)
120-
.map(cbor::from_value)
121-
.transpose()?
122-
.unwrap_or_default();
140+
/// Read local configuration from host.
141+
pub fn from_host(host: Arc<Protocol>) -> Result<Self> {
142+
let cfg = RawLocalConfig::new(host)?;
143+
Self::from_raw(cfg)
144+
}
123145

146+
/// Read given raw local configuration.
147+
pub fn from_raw(cfg: RawLocalConfig) -> Result<Self> {
124148
let provider_address = Address::from_bech32(&cfg.provider_address)
125149
.map_err(|_| anyhow!("bad provider address"))?;
126150
let allowed_artifacts = cfg
@@ -167,6 +191,11 @@ impl LocalConfig {
167191
claim_payment_interval_secs: cfg.claim_payment_interval.unwrap_or(24) * 3600,
168192
deploy_pull_timeout: cfg.deploy_pull_timeout.unwrap_or(60),
169193
transfer_instances_from,
194+
api_domain: cfg.api_domain,
195+
api_token_lifetime: cfg
196+
.api_token_lifetime
197+
.unwrap_or(6 * 3600) // Default to 6 hours.
198+
.clamp(60, 7 * 24 * 3600),
170199
})
171200
}
172201

rofl-scheduler/src/main.rs

Lines changed: 67 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,98 @@
11
//! The rofl-scheduler is a ROFL app that acts as the instruction interpreter for the on-chain
22
//! control plane implemented by the roflmarket module.
3+
#![feature(once_cell_try)]
4+
5+
use std::collections::BTreeMap;
6+
37
use oasis_runtime_sdk::{
4-
core::common::{logger::get_logger, process},
8+
core::{
9+
common::{logger::get_logger, process},
10+
Protocol,
11+
},
512
modules::rofl::app::prelude::*,
613
};
714

815
mod client;
916
mod config;
1017
mod manager;
1118
mod manifest;
19+
mod serverd;
1220
mod types;
1321

14-
struct SchedulerApp;
22+
struct SchedulerApp {
23+
cfg: Option<Arc<config::LocalConfig>>,
24+
}
25+
26+
impl SchedulerApp {
27+
fn new() -> Self {
28+
Self { cfg: None }
29+
}
30+
}
31+
32+
/// Name of the metadata key used to store the endpoint URL.
33+
const METADATA_KEY_ENDPOINT_URL: &str = "net.oasis.scheduler.api";
1534

1635
#[async_trait]
1736
impl App for SchedulerApp {
1837
const VERSION: Version = sdk::version_from_cargo!();
1938

20-
async fn run(self: Arc<Self>, env: Environment<Self>) {
39+
fn init(&mut self, host: Arc<Protocol>) {
2140
let logger = get_logger("scheduler");
2241

23-
// Read local coniguration.
24-
let cfg = match config::LocalConfig::from_env(env.clone()) {
25-
Ok(cfg) => cfg,
42+
let cfg = match config::LocalConfig::from_host(host) {
43+
Ok(cfg) => Arc::new(cfg),
2644
Err(err) => {
2745
slog::error!(logger, "failed to load configuration"; "err" => ?err);
2846
process::abort();
2947
}
3048
};
3149

32-
let manager = manager::Manager::new(env, cfg);
50+
self.cfg = Some(cfg);
51+
}
52+
53+
async fn get_metadata(
54+
self: Arc<Self>,
55+
_env: Environment<Self>,
56+
) -> Result<BTreeMap<String, String>> {
57+
let cfg = self.cfg.as_ref().unwrap();
58+
let mut meta = serverd::tls::Identity::global()?.metadata();
59+
if let Some(api_domain) = &cfg.api_domain {
60+
meta.insert(
61+
METADATA_KEY_ENDPOINT_URL.to_string(),
62+
format!("https://{}", api_domain),
63+
);
64+
}
65+
66+
Ok(meta)
67+
}
68+
69+
async fn run(self: Arc<Self>, env: Environment<Self>) {
70+
let logger = get_logger("scheduler");
71+
72+
// Create the manager.
73+
let cfg = self.cfg.as_ref().unwrap();
74+
let manager = manager::Manager::new(env.clone(), cfg.clone());
75+
76+
// Start API server when enabled.
77+
if let Some(domain) = &cfg.api_domain {
78+
if let Err(err) = serverd::serve(serverd::Config {
79+
address: "0.0.0.0:443",
80+
domain,
81+
env,
82+
manager: manager.clone(),
83+
config: cfg.clone(),
84+
})
85+
.await
86+
{
87+
slog::error!(logger, "failed to start API server"; "err" => ?err);
88+
}
89+
}
90+
91+
// Start the manager.
3392
manager.run().await
3493
}
3594
}
3695

3796
fn main() {
38-
SchedulerApp.start();
97+
SchedulerApp::new().start();
3998
}

0 commit comments

Comments
 (0)