11use std:: path:: PathBuf ;
22
3+ use apollo_node_config:: node_config:: SequencerNodeConfig ;
34use jrsonnet_evaluator:: trace:: PathResolver ;
45use jrsonnet_evaluator:: { FileImportResolver , State } ;
56use serde_json:: Value ;
@@ -8,14 +9,24 @@ use strum::IntoEnumIterator;
89use crate :: service:: { GetComponentConfigs , NodeService , NodeType } ;
910
1011const JSONNET_DIR : & str = "crates/apollo_deployments/jsonnet" ;
12+ const TESTING_CHAIN_PARAMS_PATH : & str = "testing/chain_params.libsonnet" ;
13+ const TESTING_NODE_PARAMS_PATH : & str = "testing/node_params.libsonnet" ;
1114
12- /// Evaluates `services/<layout>.jsonnet` (the per-layout infra renderer) and returns its JSON.
13- fn eval_layout_infra ( layout : & str ) -> Value {
15+ /// Evaluates a jsonnet `snippet` against a fresh evaluator (stdlib installed, imports resolved
16+ /// relative to the jsonnet dir) and converts the result to a serde `Value`. `context` labels the
17+ /// evaluation in panic messages.
18+ fn eval_jsonnet ( context : & str , snippet : String ) -> Value {
1419 let state = jsonnet_state ( ) ;
1520 let _guard = state. enter ( ) ;
16- let entry = format ! ( "services/{layout}.jsonnet" ) ;
17- let val = state. import ( entry. as_str ( ) ) . expect ( "failed to evaluate the layout infra renderer" ) ;
18- serde_json:: to_value ( & val) . expect ( "infra config is not serializable" )
21+ let val = state
22+ . evaluate_snippet ( context. to_owned ( ) , snippet)
23+ . expect ( "Failed to evaluate jsonnet snippet." ) ;
24+ serde_json:: to_value ( & val) . expect ( "Failed to serialize jsonnet result to Value." )
25+ }
26+
27+ /// Evaluates `services/<layout>.jsonnet` (the per-layout infra renderer) and returns its JSON.
28+ fn eval_layout_infra ( layout : & str ) -> Value {
29+ eval_jsonnet ( "layout infra" , format ! ( "import 'services/{layout}.jsonnet'" ) )
1930}
2031
2132/// A jrsonnet evaluator with the stdlib installed and file imports resolved relative to the jsonnet
5768 }
5869}
5970
71+ /// Evaluates `build(layout, { chain_params, node_params })` and returns its JSON: a map from service
72+ /// name to that service's fully-assembled config. The testing params supply only the mandatory
73+ /// chain_params + node_params buckets; `replacers` is omitted, so every replacer falls back to its
74+ /// applicative-config default.
75+ fn eval_build ( layout : & str ) -> Value {
76+ let layout_literal = serde_json:: to_string ( layout) . unwrap ( ) ;
77+ eval_jsonnet (
78+ "build" ,
79+ format ! (
80+ "(import 'lib/build.libsonnet').build({layout_literal}, {{ chain_params: import \
81+ '{TESTING_CHAIN_PARAMS_PATH}', node_params: import '{TESTING_NODE_PARAMS_PATH}' }})"
82+ ) ,
83+ )
84+ }
85+
86+ /// Asserts that `build(layout, params)` produces, for every service of layout `S`, an object that
87+ /// deserializes into `SequencerNodeConfig`.
88+ pub ( crate ) fn assert_build_deserializes < S > ( )
89+ where
90+ S : GetComponentConfigs + IntoEnumIterator + Into < NodeService > ,
91+ {
92+ let some_service: NodeService =
93+ S :: iter ( ) . next ( ) . expect ( "a layout has at least one service" ) . into ( ) ;
94+ let layout = NodeType :: from ( & some_service) . to_string ( ) ;
95+ let built = eval_build ( & layout) ;
96+ let services = built. as_object ( ) . unwrap ( ) ;
97+
98+ // Sanity check: the build result should have at least one service.
99+ assert ! ( !services. is_empty( ) , "build({layout}) produced no services" ) ;
100+
101+ for ( service_name, config) in services {
102+ serde_json:: from_value :: < SequencerNodeConfig > ( config. clone ( ) ) . unwrap_or_else ( |error| {
103+ panic ! (
104+ "service {service_name} of layout {layout} does not deserialize into \
105+ SequencerNodeConfig: {error}"
106+ )
107+ } ) ;
108+ }
109+ }
110+
60111/// Clones a `components` map with `url` and `port` removed from each component object — the two
61112/// fields the Rust config leaves as deploy-time placeholders, so they can't be compared against the
62113/// jsonnet's baked-in real values.
0 commit comments