@@ -2,9 +2,10 @@ use std::{path::Path, vec};
2
2
3
3
use cb_common:: {
4
4
config:: {
5
- CommitBoostConfig , CB_CONFIG_ENV , CB_CONFIG_NAME , JWTS_ENV , METRICS_SERVER_ENV ,
6
- MODULE_ID_ENV , MODULE_JWT_ENV , SIGNER_DIR_KEYS , SIGNER_DIR_KEYS_ENV , SIGNER_DIR_SECRETS ,
7
- SIGNER_DIR_SECRETS_ENV , SIGNER_KEYS , SIGNER_KEYS_ENV , SIGNER_SERVER_ENV ,
5
+ CommitBoostConfig , ModuleKind , BUILDER_SERVER_ENV , CB_CONFIG_ENV , CB_CONFIG_NAME , JWTS_ENV ,
6
+ METRICS_SERVER_ENV , MODULE_ID_ENV , MODULE_JWT_ENV , SIGNER_DIR_KEYS , SIGNER_DIR_KEYS_ENV ,
7
+ SIGNER_DIR_SECRETS , SIGNER_DIR_SECRETS_ENV , SIGNER_KEYS , SIGNER_KEYS_ENV ,
8
+ SIGNER_SERVER_ENV ,
8
9
} ,
9
10
loader:: SignerLoader ,
10
11
utils:: random_jwt,
@@ -51,17 +52,101 @@ pub fn handle_docker_init(config_path: String, output_dir: String) -> Result<()>
51
52
let signer_port = 20000 ;
52
53
let signer_server = format ! ( "cb_signer:{signer_port}" ) ;
53
54
55
+ let builder_events_port = 30000 ;
56
+ let mut builder_events_modules = Vec :: new ( ) ;
57
+
54
58
// setup pbs service
55
59
targets. push ( PrometheusTargetConfig {
56
60
targets : vec ! [ format!( "cb_pbs:{metrics_port}" ) ] ,
57
61
labels : PrometheusLabelsConfig { job : "pbs" . to_owned ( ) } ,
58
62
} ) ;
59
63
60
- let pbs_envs = IndexMap :: from ( [
64
+ let mut pbs_envs = IndexMap :: from ( [
61
65
get_env_same ( CB_CONFIG_ENV ) ,
62
66
get_env_val ( METRICS_SERVER_ENV , & metrics_port. to_string ( ) ) ,
63
67
] ) ;
64
68
69
+ let mut needs_signer_module = cb_config. pbs . with_signer ;
70
+
71
+ // setup modules
72
+ if let Some ( modules_config) = cb_config. modules {
73
+ for module in modules_config {
74
+ // TODO: support modules volumes and network
75
+ let module_cid = format ! ( "cb_{}" , module. id. to_lowercase( ) ) ;
76
+
77
+ targets. push ( PrometheusTargetConfig {
78
+ targets : vec ! [ format!( "{module_cid}:{metrics_port}" ) ] ,
79
+ labels : PrometheusLabelsConfig { job : module_cid. clone ( ) } ,
80
+ } ) ;
81
+
82
+ let module_service = match module. kind {
83
+ // a commit module needs a JWT and access to the signer network
84
+ ModuleKind :: Commit => {
85
+ needs_signer_module = true ;
86
+
87
+ let jwt = random_jwt ( ) ;
88
+ let jwt_name = format ! ( "CB_JWT_{}" , module. id. to_uppercase( ) ) ;
89
+
90
+ // module ids are assumed unique, so envs dont override each other
91
+ let module_envs = IndexMap :: from ( [
92
+ get_env_val ( MODULE_ID_ENV , & module. id ) ,
93
+ get_env_same ( CB_CONFIG_ENV ) ,
94
+ get_env_interp ( MODULE_JWT_ENV , & jwt_name) ,
95
+ get_env_val ( METRICS_SERVER_ENV , & metrics_port. to_string ( ) ) ,
96
+ get_env_val ( SIGNER_SERVER_ENV , & signer_server) ,
97
+ ] ) ;
98
+
99
+ envs. insert ( jwt_name. clone ( ) , jwt. clone ( ) ) ;
100
+ jwts. insert ( module. id . clone ( ) , jwt) ;
101
+
102
+ Service {
103
+ container_name : Some ( module_cid. clone ( ) ) ,
104
+ image : Some ( module. docker_image ) ,
105
+ // TODO: allow service to open ports here
106
+ networks : Networks :: Simple ( vec ! [
107
+ METRICS_NETWORK . to_owned( ) ,
108
+ SIGNER_NETWORK . to_owned( ) ,
109
+ ] ) ,
110
+ volumes : vec ! [ config_volume. clone( ) ] ,
111
+ environment : Environment :: KvPair ( module_envs) ,
112
+ depends_on : DependsOnOptions :: Simple ( vec ! [ "cb_signer" . to_owned( ) ] ) ,
113
+ ..Service :: default ( )
114
+ }
115
+ }
116
+ // an event module just needs a port to listen on
117
+ ModuleKind :: Events => {
118
+ // module ids are assumed unique, so envs dont override each other
119
+ let module_envs = IndexMap :: from ( [
120
+ get_env_val ( MODULE_ID_ENV , & module. id ) ,
121
+ get_env_same ( CB_CONFIG_ENV ) ,
122
+ get_env_val ( METRICS_SERVER_ENV , & metrics_port. to_string ( ) ) ,
123
+ get_env_val ( BUILDER_SERVER_ENV , & builder_events_port. to_string ( ) ) ,
124
+ ] ) ;
125
+
126
+ builder_events_modules. push ( format ! ( "{module_cid}:{builder_events_port}" ) ) ;
127
+
128
+ Service {
129
+ container_name : Some ( module_cid. clone ( ) ) ,
130
+ image : Some ( module. docker_image ) ,
131
+ networks : Networks :: Simple ( vec ! [ METRICS_NETWORK . to_owned( ) ] ) ,
132
+ volumes : vec ! [ config_volume. clone( ) ] ,
133
+ environment : Environment :: KvPair ( module_envs) ,
134
+ depends_on : DependsOnOptions :: Simple ( vec ! [ "cb_pbs" . to_owned( ) ] ) ,
135
+ ..Service :: default ( )
136
+ }
137
+ }
138
+ } ;
139
+
140
+ services. insert ( module_cid, Some ( module_service) ) ;
141
+ }
142
+ } ;
143
+
144
+ if !builder_events_modules. is_empty ( ) {
145
+ let env = builder_events_modules. join ( "," ) ;
146
+ let ( k, v) = get_env_val ( BUILDER_SERVER_ENV , & env) ;
147
+ pbs_envs. insert ( k, v) ;
148
+ }
149
+
65
150
let pbs_service = Service {
66
151
container_name : Some ( "cb_pbs" . to_owned ( ) ) ,
67
152
image : Some ( cb_config. pbs . docker_image ) ,
@@ -77,102 +162,68 @@ pub fn handle_docker_init(config_path: String, output_dir: String) -> Result<()>
77
162
78
163
services. insert ( "cb_pbs" . to_owned ( ) , Some ( pbs_service) ) ;
79
164
80
- // setup modules
81
- if let Some ( modules_config) = cb_config. modules {
82
- for module in modules_config {
83
- // TODO: support modules volumes and network
84
- let module_cid = format ! ( "cb_{}" , module. id. to_lowercase( ) ) ;
165
+ // TODO: validate if we have signer modules but not signer config
166
+
167
+ // setup signer service
168
+
169
+ if let Some ( signer_config) = cb_config. signer {
170
+ if needs_signer_module {
171
+ let mut volumes = vec ! [ config_volume. clone( ) ] ;
85
172
86
173
targets. push ( PrometheusTargetConfig {
87
- targets : vec ! [ format!( "{module_cid} :{metrics_port}" ) ] ,
88
- labels : PrometheusLabelsConfig { job : module_cid . clone ( ) } ,
174
+ targets : vec ! [ format!( "cb_signer :{metrics_port}" ) ] ,
175
+ labels : PrometheusLabelsConfig { job : "signer" . into ( ) } ,
89
176
} ) ;
90
177
91
- let jwt = random_jwt ( ) ;
92
- let jwt_name = format ! ( "CB_JWT_{}" , module. id. to_uppercase( ) ) ;
93
-
94
- // module ids are assumed unique, so envs dont override each other
95
- let module_envs = IndexMap :: from ( [
96
- get_env_val ( MODULE_ID_ENV , & module. id ) ,
178
+ let mut signer_envs = IndexMap :: from ( [
97
179
get_env_same ( CB_CONFIG_ENV ) ,
98
- get_env_interp ( MODULE_JWT_ENV , & jwt_name ) ,
180
+ get_env_same ( JWTS_ENV ) ,
99
181
get_env_val ( METRICS_SERVER_ENV , & metrics_port. to_string ( ) ) ,
100
- get_env_val ( SIGNER_SERVER_ENV , & signer_server ) ,
182
+ get_env_val ( SIGNER_SERVER_ENV , & signer_port . to_string ( ) ) ,
101
183
] ) ;
102
184
103
- envs. insert ( jwt_name. clone ( ) , jwt. clone ( ) ) ;
104
- jwts. insert ( module. id . clone ( ) , jwt) ;
185
+ // TODO: generalize this, different loaders may not need volumes but eg ports
186
+ match signer_config. loader {
187
+ SignerLoader :: File { key_path } => {
188
+ volumes. push ( Volumes :: Simple ( format ! ( "./{}:{}:ro" , key_path, SIGNER_KEYS ) ) ) ;
189
+ let ( k, v) = get_env_val ( SIGNER_KEYS_ENV , SIGNER_KEYS ) ;
190
+ signer_envs. insert ( k, v) ;
191
+ }
192
+ SignerLoader :: ValidatorsDir { keys_path, secrets_path } => {
193
+ volumes. push ( Volumes :: Simple ( format ! ( "{}:{}:ro" , keys_path, SIGNER_DIR_KEYS ) ) ) ;
194
+ let ( k, v) = get_env_val ( SIGNER_DIR_KEYS_ENV , SIGNER_DIR_KEYS ) ;
195
+ signer_envs. insert ( k, v) ;
196
+
197
+ volumes. push ( Volumes :: Simple ( format ! (
198
+ "{}:{}:ro" ,
199
+ secrets_path, SIGNER_DIR_SECRETS
200
+ ) ) ) ;
201
+ let ( k, v) = get_env_val ( SIGNER_DIR_SECRETS_ENV , SIGNER_DIR_SECRETS ) ;
202
+ signer_envs. insert ( k, v) ;
203
+ }
204
+ } ;
205
+
206
+ // write jwts to env
207
+ let jwts_json = serde_json:: to_string ( & jwts) . unwrap ( ) . clone ( ) ;
208
+ envs. insert ( JWTS_ENV . into ( ) , format ! ( "{jwts_json:?}" ) ) ;
105
209
106
- let module_service = Service {
107
- container_name : Some ( module_cid. clone ( ) ) ,
108
- image : Some ( module. docker_image ) ,
109
- // TODO: allow service to open ports here
210
+ let signer_service = Service {
211
+ container_name : Some ( "cb_signer" . to_owned ( ) ) ,
212
+ image : Some ( signer_config. docker_image ) ,
110
213
networks : Networks :: Simple ( vec ! [
111
214
METRICS_NETWORK . to_owned( ) ,
112
215
SIGNER_NETWORK . to_owned( ) ,
113
216
] ) ,
114
- volumes : vec ! [ config_volume. clone( ) ] ,
115
- environment : Environment :: KvPair ( module_envs) ,
116
- depends_on : DependsOnOptions :: Simple ( vec ! [ "cb_signer" . to_owned( ) ] ) ,
217
+ volumes,
218
+ environment : Environment :: KvPair ( signer_envs) ,
117
219
..Service :: default ( )
118
220
} ;
119
221
120
- services. insert ( module_cid , Some ( module_service ) ) ;
222
+ services. insert ( "cb_signer" . to_owned ( ) , Some ( signer_service ) ) ;
121
223
}
122
- } ;
123
-
124
- // TODO: validate if we have signer modules but not signer config
125
-
126
- // setup signer service
127
- if let Some ( signer_config) = cb_config. signer {
128
- let mut volumes = vec ! [ config_volume. clone( ) ] ;
129
-
130
- targets. push ( PrometheusTargetConfig {
131
- targets : vec ! [ format!( "cb_signer:{metrics_port}" ) ] ,
132
- labels : PrometheusLabelsConfig { job : "signer" . into ( ) } ,
133
- } ) ;
134
-
135
- let mut signer_envs = IndexMap :: from ( [
136
- get_env_same ( CB_CONFIG_ENV ) ,
137
- get_env_same ( JWTS_ENV ) ,
138
- get_env_val ( METRICS_SERVER_ENV , & metrics_port. to_string ( ) ) ,
139
- get_env_val ( SIGNER_SERVER_ENV , & signer_port. to_string ( ) ) ,
140
- ] ) ;
141
-
142
- // TODO: generalize this, different loaders may not need volumes but eg ports
143
- match signer_config. loader {
144
- SignerLoader :: File { key_path } => {
145
- volumes. push ( Volumes :: Simple ( format ! ( "./{}:{}:ro" , key_path, SIGNER_KEYS ) ) ) ;
146
- let ( k, v) = get_env_val ( SIGNER_KEYS_ENV , SIGNER_KEYS ) ;
147
- signer_envs. insert ( k, v) ;
148
- }
149
- SignerLoader :: ValidatorsDir { keys_path, secrets_path } => {
150
- volumes. push ( Volumes :: Simple ( format ! ( "{}:{}:ro" , keys_path, SIGNER_DIR_KEYS ) ) ) ;
151
- let ( k, v) = get_env_val ( SIGNER_DIR_KEYS_ENV , SIGNER_DIR_KEYS ) ;
152
- signer_envs. insert ( k, v) ;
153
-
154
- volumes
155
- . push ( Volumes :: Simple ( format ! ( "{}:{}:ro" , secrets_path, SIGNER_DIR_SECRETS ) ) ) ;
156
- let ( k, v) = get_env_val ( SIGNER_DIR_SECRETS_ENV , SIGNER_DIR_SECRETS ) ;
157
- signer_envs. insert ( k, v) ;
158
- }
159
- } ;
160
-
161
- // write jwts to env
162
- let jwts_json = serde_json:: to_string ( & jwts) ?. clone ( ) ;
163
- envs. insert ( JWTS_ENV . into ( ) , format ! ( "{jwts_json:?}" ) ) ;
164
-
165
- let signer_service = Service {
166
- container_name : Some ( "cb_signer" . to_owned ( ) ) ,
167
- image : Some ( signer_config. docker_image ) ,
168
- networks : Networks :: Simple ( vec ! [ METRICS_NETWORK . to_owned( ) , SIGNER_NETWORK . to_owned( ) ] ) ,
169
- volumes,
170
- environment : Environment :: KvPair ( signer_envs) ,
171
- ..Service :: default ( )
172
- } ;
173
-
174
- services. insert ( "cb_signer" . to_owned ( ) , Some ( signer_service) ) ;
175
- } ;
224
+ } else if needs_signer_module {
225
+ panic ! ( "Signer module required but no signer config provided" ) ;
226
+ }
176
227
177
228
// setup metrics services
178
229
// TODO: make this metrics optional?
@@ -274,6 +325,7 @@ fn get_env_interp(k: &str, v: &str) -> (String, Option<SingleValue>) {
274
325
get_env_val ( k, & format ! ( "${{{v}}}" ) )
275
326
}
276
327
328
+ // FOO=bar
277
329
fn get_env_val ( k : & str , v : & str ) -> ( String , Option < SingleValue > ) {
278
330
( k. into ( ) , Some ( SingleValue :: String ( v. into ( ) ) ) )
279
331
}
0 commit comments