Skip to content

Commit fc6c81b

Browse files
committed
feat: add json schema generation for CasConfig via schemars
1 parent 07bd27a commit fc6c81b

File tree

8 files changed

+156
-1
lines changed

8 files changed

+156
-1
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@ nixos.bazelrc
2323
rust-project.json
2424
darwin.bazelrc
2525
nativelink.bazelrc
26+
nativelink_config.schema.json

Cargo.lock

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

nativelink-config/Cargo.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,17 @@ humantime = "2.1.0"
99
serde = { version = "1.0.218", default-features = false, features = ["derive"] }
1010
serde_json5 = "0.2.1"
1111
shellexpand = { version = "3.1.0", default-features = false, features = ["base-0"] }
12+
schemars = { version = "0.8.22", features = ["derive"], optional = true }
13+
serde_json = { version = "1.0.139", default-features = false, optional = true }
1214

1315
[dev-dependencies]
1416
pretty_assertions = { version = "1.4.1", features = ["std"] }
1517
serde_json = { version = "1.0.139", default-features = false }
18+
19+
[features]
20+
dev-schema = ["schemars", "serde_json"]
21+
22+
[[bin]]
23+
name = "build-schema"
24+
path = "src/bin/build_schema.rs"
25+
required-features=["dev-schema"]
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//! ```sh
2+
//! cargo run --bin build-schema --features dev-schema --package nativelink-config
3+
//! ```
4+
5+
#[cfg(feature = "dev-schema")]
6+
fn main() {
7+
use std::fs::File;
8+
9+
use nativelink_config::cas_server::CasConfig;
10+
use schemars::schema_for;
11+
use serde_json::to_writer_pretty;
12+
const FILE: &str = "nativelink_config.schema.json";
13+
14+
let schema = schema_for!(CasConfig);
15+
to_writer_pretty(File::create(FILE).expect("to create file"), &schema)
16+
.expect("to export schema");
17+
18+
println!("Wrote schema to {FILE}");
19+
}
20+
21+
#[cfg(not(feature = "dev-schema"))]
22+
fn main() {
23+
eprintln!("Enable with --features dev-schema");
24+
}

nativelink-config/src/cas_server.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
use std::collections::HashMap;
1616

17+
#[cfg(feature = "dev-schema")]
18+
use schemars::JsonSchema;
1719
use serde::Deserialize;
1820

1921
use crate::serde_utils::{
@@ -34,6 +36,7 @@ pub type InstanceName = String;
3436

3537
#[allow(non_camel_case_types)]
3638
#[derive(Deserialize, Debug, Default, Clone, Copy)]
39+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
3740
pub enum HttpCompressionAlgorithm {
3841
/// No compression.
3942
#[default]
@@ -54,6 +57,7 @@ pub enum HttpCompressionAlgorithm {
5457
/// and cloud-clients to use another.
5558
#[derive(Deserialize, Debug, Default)]
5659
#[serde(deny_unknown_fields)]
60+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
5761
pub struct HttpCompressionConfig {
5862
/// The compression algorithm that the server will use when sending
5963
/// responses to clients. Enabling this will likely save a lot of
@@ -77,6 +81,7 @@ pub struct HttpCompressionConfig {
7781

7882
#[derive(Deserialize, Debug)]
7983
#[serde(deny_unknown_fields)]
84+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
8085
pub struct AcStoreConfig {
8186
/// The store name referenced in the `stores` map in the main config.
8287
/// This store name referenced here may be reused multiple times.
@@ -91,6 +96,7 @@ pub struct AcStoreConfig {
9196

9297
#[derive(Deserialize, Debug)]
9398
#[serde(deny_unknown_fields)]
99+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
94100
pub struct CasStoreConfig {
95101
/// The store name referenced in the `stores` map in the main config.
96102
/// This store name referenced here may be reused multiple times.
@@ -100,6 +106,7 @@ pub struct CasStoreConfig {
100106

101107
#[derive(Deserialize, Debug, Default)]
102108
#[serde(deny_unknown_fields)]
109+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
103110
pub struct CapabilitiesRemoteExecutionConfig {
104111
/// Scheduler used to configure the capabilities of remote execution.
105112
#[serde(deserialize_with = "convert_string_with_shellexpand")]
@@ -108,6 +115,7 @@ pub struct CapabilitiesRemoteExecutionConfig {
108115

109116
#[derive(Deserialize, Debug, Default)]
110117
#[serde(deny_unknown_fields)]
118+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
111119
pub struct CapabilitiesConfig {
112120
/// Configuration for remote execution capabilities.
113121
/// If not set the capabilities service will inform the client that remote
@@ -117,6 +125,7 @@ pub struct CapabilitiesConfig {
117125

118126
#[derive(Deserialize, Debug)]
119127
#[serde(deny_unknown_fields)]
128+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
120129
pub struct ExecutionConfig {
121130
/// The store name referenced in the `stores` map in the main config.
122131
/// This store name referenced here may be reused multiple times.
@@ -131,6 +140,7 @@ pub struct ExecutionConfig {
131140

132141
#[derive(Deserialize, Debug, Default)]
133142
#[serde(deny_unknown_fields)]
143+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
134144
pub struct ByteStreamConfig {
135145
/// Name of the store in the "stores" configuration.
136146
pub cas_stores: HashMap<InstanceName, StoreRefName>,
@@ -161,6 +171,7 @@ pub struct ByteStreamConfig {
161171

162172
#[derive(Deserialize, Debug)]
163173
#[serde(deny_unknown_fields)]
174+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
164175
pub struct WorkerApiConfig {
165176
/// The scheduler name referenced in the `schedulers` map in the main config.
166177
#[serde(deserialize_with = "convert_string_with_shellexpand")]
@@ -169,6 +180,7 @@ pub struct WorkerApiConfig {
169180

170181
#[derive(Deserialize, Debug, Default)]
171182
#[serde(deny_unknown_fields)]
183+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
172184
pub struct PrometheusConfig {
173185
/// Path to register prometheus metrics. If path is "/metrics", and your
174186
/// domain is "example.com", you can reach the endpoint with:
@@ -181,6 +193,7 @@ pub struct PrometheusConfig {
181193

182194
#[derive(Deserialize, Debug, Default)]
183195
#[serde(deny_unknown_fields)]
196+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
184197
pub struct AdminConfig {
185198
/// Path to register the admin API. If path is "/admin", and your
186199
/// domain is "example.com", you can reach the endpoint with:
@@ -193,6 +206,7 @@ pub struct AdminConfig {
193206

194207
#[derive(Deserialize, Debug, Default)]
195208
#[serde(deny_unknown_fields)]
209+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
196210
pub struct HealthConfig {
197211
/// Path to register the health status check. If path is "/status", and your
198212
/// domain is "example.com", you can reach the endpoint with:
@@ -204,6 +218,7 @@ pub struct HealthConfig {
204218
}
205219

206220
#[derive(Deserialize, Debug)]
221+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
207222
pub struct BepConfig {
208223
/// The store to publish build events to.
209224
/// The store name referenced in the `stores` map in the main config.
@@ -212,6 +227,7 @@ pub struct BepConfig {
212227
}
213228

214229
#[derive(Deserialize, Clone, Debug, Default)]
230+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
215231
pub struct IdentityHeaderSpec {
216232
/// The name of the header to look for the identity in.
217233
/// Default: "x-identity"
@@ -224,6 +240,7 @@ pub struct IdentityHeaderSpec {
224240
}
225241

226242
#[derive(Deserialize, Clone, Debug)]
243+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
227244
pub struct OriginEventsPublisherSpec {
228245
/// The store to publish nativelink events to.
229246
/// The store name referenced in the `stores` map in the main config.
@@ -232,6 +249,7 @@ pub struct OriginEventsPublisherSpec {
232249
}
233250

234251
#[derive(Deserialize, Clone, Debug)]
252+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
235253
pub struct OriginEventsSpec {
236254
/// The publisher configuration for origin events.
237255
pub publisher: OriginEventsPublisherSpec,
@@ -247,6 +265,7 @@ pub struct OriginEventsSpec {
247265

248266
#[derive(Deserialize, Debug)]
249267
#[serde(deny_unknown_fields)]
268+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
250269
pub struct ServicesConfig {
251270
/// The Content Addressable Storage (CAS) backend config.
252271
/// The key is the `instance_name` used in the protocol and the
@@ -301,6 +320,7 @@ pub struct ServicesConfig {
301320

302321
#[derive(Deserialize, Debug)]
303322
#[serde(deny_unknown_fields)]
323+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
304324
pub struct TlsConfig {
305325
/// Path to the certificate file.
306326
#[serde(deserialize_with = "convert_string_with_shellexpand")]
@@ -329,6 +349,7 @@ pub struct TlsConfig {
329349
/// specified.
330350
#[derive(Deserialize, Debug, Default)]
331351
#[serde(deny_unknown_fields)]
352+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
332353
pub struct HttpServerConfig {
333354
/// Interval to send keep-alive pings via HTTP2.
334355
/// Note: This is in seconds.
@@ -396,13 +417,15 @@ pub struct HttpServerConfig {
396417

397418
#[allow(non_camel_case_types)]
398419
#[derive(Deserialize, Debug)]
420+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
399421
pub enum ListenerConfig {
400422
/// Listener for HTTP/HTTPS/HTTP2 sockets.
401423
http(HttpListener),
402424
}
403425

404426
#[derive(Deserialize, Debug)]
405427
#[serde(deny_unknown_fields)]
428+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
406429
pub struct HttpListener {
407430
/// Address to listen on. Example: `127.0.0.1:8080` or `:8080` to listen
408431
/// to all IPs.
@@ -427,6 +450,7 @@ pub struct HttpListener {
427450

428451
#[derive(Deserialize, Debug)]
429452
#[serde(deny_unknown_fields)]
453+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
430454
pub struct ServerConfig {
431455
/// Name of the server. This is used to help identify the service
432456
/// for telemetry and logs.
@@ -449,6 +473,7 @@ pub struct ServerConfig {
449473

450474
#[allow(non_camel_case_types)]
451475
#[derive(Deserialize, Debug)]
476+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
452477
pub enum WorkerProperty {
453478
/// List of static values.
454479
/// Note: Generally there should only ever be 1 value, but if the platform
@@ -464,6 +489,7 @@ pub enum WorkerProperty {
464489
/// Generic config for an endpoint and associated configs.
465490
#[derive(Deserialize, Debug, Default)]
466491
#[serde(deny_unknown_fields)]
492+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
467493
pub struct EndpointConfig {
468494
/// URI of the endpoint.
469495
#[serde(deserialize_with = "convert_string_with_shellexpand")]
@@ -479,6 +505,7 @@ pub struct EndpointConfig {
479505

480506
#[allow(non_camel_case_types)]
481507
#[derive(Copy, Clone, Deserialize, Debug, Default)]
508+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
482509
pub enum UploadCacheResultsStrategy {
483510
/// Only upload action results with an exit code of 0.
484511
#[default]
@@ -496,6 +523,7 @@ pub enum UploadCacheResultsStrategy {
496523

497524
#[allow(non_camel_case_types)]
498525
#[derive(Clone, Deserialize, Debug)]
526+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
499527
pub enum EnvironmentSource {
500528
/// The name of the platform property in the action to get the value from.
501529
property(String),
@@ -543,6 +571,7 @@ pub enum EnvironmentSource {
543571

544572
#[derive(Deserialize, Debug, Default)]
545573
#[serde(deny_unknown_fields)]
574+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
546575
pub struct UploadActionResultConfig {
547576
/// Underlying AC store that the worker will use to publish execution results
548577
/// into. Objects placed in this store should be reachable from the
@@ -603,6 +632,7 @@ pub struct UploadActionResultConfig {
603632

604633
#[derive(Deserialize, Debug, Default)]
605634
#[serde(deny_unknown_fields)]
635+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
606636
pub struct LocalWorkerConfig {
607637
/// Name of the worker. This is give a more friendly name to a worker for logging
608638
/// and metric publishing. This is also the prefix of the worker id
@@ -695,13 +725,15 @@ pub struct LocalWorkerConfig {
695725

696726
#[allow(non_camel_case_types)]
697727
#[derive(Deserialize, Debug)]
728+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
698729
pub enum WorkerConfig {
699730
/// A worker type that executes jobs locally on this machine.
700731
local(LocalWorkerConfig),
701732
}
702733

703734
#[derive(Deserialize, Debug, Clone, Copy)]
704735
#[serde(deny_unknown_fields)]
736+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
705737
pub struct GlobalConfig {
706738
/// Maximum number of open files that can be opened at one time.
707739
/// This value is not strictly enforced, it is a best effort. Some internal libraries
@@ -747,6 +779,7 @@ pub struct GlobalConfig {
747779

748780
#[derive(Deserialize, Debug)]
749781
#[serde(deny_unknown_fields)]
782+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
750783
pub struct CasConfig {
751784
/// List of stores available to use in this config.
752785
/// The keys can be used in other configs when needing to reference a store.

nativelink-config/src/lib.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@ use std::collections::HashMap;
2222
use std::fmt;
2323
use std::marker::PhantomData;
2424

25+
#[cfg(feature = "dev-schema")]
26+
use schemars::JsonSchema;
2527
use serde::de::{MapAccess, SeqAccess, Visitor};
2628
use serde::{Deserialize, Deserializer};
27-
2829
#[derive(Debug, Clone, Deserialize)]
30+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
2931
pub struct NamedConfig<Spec> {
3032
pub name: String,
3133
#[serde(flatten)]
@@ -41,6 +43,7 @@ pub type StoreConfigs = NamedConfigs<crate::stores::StoreSpec>;
4143
pub type SchedulerConfigs = NamedConfigs<crate::schedulers::SchedulerSpec>;
4244

4345
#[derive(Debug)]
46+
#[cfg_attr(feature = "dev-schema", derive(JsonSchema))]
4447
pub struct NamedConfigs<T>(pub Vec<NamedConfig<T>>);
4548

4649
impl<T> NamedConfigs<T> {

0 commit comments

Comments
 (0)