@@ -5,7 +5,6 @@ use proxy::http;
5
5
use proxy:: metrics;
6
6
7
7
use anyhow:: bail;
8
- use clap:: { self , Arg } ;
9
8
use proxy:: config:: { self , ProxyConfig } ;
10
9
use std:: pin:: pin;
11
10
use std:: { borrow:: Cow , net:: SocketAddr } ;
@@ -18,6 +17,70 @@ use utils::{project_git_version, sentry_init::init_sentry};
18
17
19
18
project_git_version ! ( GIT_VERSION ) ;
20
19
20
+ use clap:: { Parser , ValueEnum } ;
21
+
22
+ #[ derive( Clone , Debug , ValueEnum ) ]
23
+ enum AuthBackend {
24
+ Console ,
25
+ Postgres ,
26
+ Link ,
27
+ }
28
+
29
+ /// Neon proxy/router
30
+ #[ derive( Parser ) ]
31
+ #[ command( version = GIT_VERSION , about) ]
32
+ struct ProxyCliArgs {
33
+ /// listen for incoming client connections on ip:port
34
+ #[ clap( short, long, default_value = "127.0.0.1:4432" ) ]
35
+ proxy : String ,
36
+ #[ clap( value_enum, long, default_value_t = AuthBackend :: Link ) ]
37
+ auth_backend : AuthBackend ,
38
+ /// listen for management callback connection on ip:port
39
+ #[ clap( short, long, default_value = "127.0.0.1:7000" ) ]
40
+ mgmt : String ,
41
+ /// listen for incoming http connections (metrics, etc) on ip:port
42
+ #[ clap( long, default_value = "127.0.0.1:7001" ) ]
43
+ http : String ,
44
+ /// listen for incoming wss connections on ip:port
45
+ #[ clap( long) ]
46
+ wss : Option < String > ,
47
+ /// redirect unauthenticated users to the given uri in case of link auth
48
+ #[ clap( short, long, default_value = "http://localhost:3000/psql_session/" ) ]
49
+ uri : String ,
50
+ /// cloud API endpoint for authenticating users
51
+ #[ clap(
52
+ short,
53
+ long,
54
+ default_value = "http://localhost:3000/authenticate_proxy_request/"
55
+ ) ]
56
+ auth_endpoint : String ,
57
+ /// path to TLS key for client postgres connections
58
+ ///
59
+ /// tls-key and tls-cert are for backwards compatibility, we can put all certs in one dir
60
+ #[ clap( short = 'k' , long, alias = "ssl-key" ) ]
61
+ tls_key : Option < String > ,
62
+ /// path to TLS cert for client postgres connections
63
+ ///
64
+ /// tls-key and tls-cert are for backwards compatibility, we can put all certs in one dir
65
+ #[ clap( short = 'c' , long, alias = "ssl-cert" ) ]
66
+ tls_cert : Option < String > ,
67
+ /// path to directory with TLS certificates for client postgres connections
68
+ #[ clap( long) ]
69
+ certs_dir : Option < String > ,
70
+ /// http endpoint to receive periodic metric updates
71
+ #[ clap( long) ]
72
+ metric_collection_endpoint : Option < String > ,
73
+ /// how often metrics should be sent to a collection endpoint
74
+ #[ clap( long) ]
75
+ metric_collection_interval : Option < String > ,
76
+ /// cache for `wake_compute` api method (use `size=0` to disable)
77
+ #[ clap( long, default_value = config:: CacheOptions :: DEFAULT_OPTIONS_NODE_INFO ) ]
78
+ wake_compute_cache : String ,
79
+ /// Allow self-signed certificates for compute nodes (for testing)
80
+ #[ clap( long, default_value_t = false , value_parser = clap:: builder:: BoolishValueParser :: new( ) , action = clap:: ArgAction :: Set ) ]
81
+ allow_self_signed_compute : bool ,
82
+ }
83
+
21
84
#[ tokio:: main]
22
85
async fn main ( ) -> anyhow:: Result < ( ) > {
23
86
let _logging_guard = proxy:: logging:: init ( ) . await ?;
@@ -27,21 +90,21 @@ async fn main() -> anyhow::Result<()> {
27
90
info ! ( "Version: {GIT_VERSION}" ) ;
28
91
:: metrics:: set_build_info_metric ( GIT_VERSION ) ;
29
92
30
- let args = cli ( ) . get_matches ( ) ;
93
+ let args = ProxyCliArgs :: parse ( ) ;
31
94
let config = build_config ( & args) ?;
32
95
33
96
info ! ( "Authentication backend: {}" , config. auth_backend) ;
34
97
35
98
// Check that we can bind to address before further initialization
36
- let http_address: SocketAddr = args. get_one :: < String > ( " http" ) . unwrap ( ) . parse ( ) ?;
99
+ let http_address: SocketAddr = args. http . parse ( ) ?;
37
100
info ! ( "Starting http on {http_address}" ) ;
38
101
let http_listener = TcpListener :: bind ( http_address) . await ?. into_std ( ) ?;
39
102
40
- let mgmt_address: SocketAddr = args. get_one :: < String > ( " mgmt" ) . unwrap ( ) . parse ( ) ?;
103
+ let mgmt_address: SocketAddr = args. mgmt . parse ( ) ?;
41
104
info ! ( "Starting mgmt on {mgmt_address}" ) ;
42
105
let mgmt_listener = TcpListener :: bind ( mgmt_address) . await ?;
43
106
44
- let proxy_address: SocketAddr = args. get_one :: < String > ( " proxy" ) . unwrap ( ) . parse ( ) ?;
107
+ let proxy_address: SocketAddr = args. proxy . parse ( ) ?;
45
108
info ! ( "Starting proxy on {proxy_address}" ) ;
46
109
let proxy_listener = TcpListener :: bind ( proxy_address) . await ?;
47
110
let cancellation_token = CancellationToken :: new ( ) ;
@@ -55,7 +118,7 @@ async fn main() -> anyhow::Result<()> {
55
118
cancellation_token. clone ( ) ,
56
119
) ) ;
57
120
58
- if let Some ( wss_address) = args. get_one :: < String > ( " wss" ) {
121
+ if let Some ( wss_address) = args. wss {
59
122
let wss_address: SocketAddr = wss_address. parse ( ) ?;
60
123
info ! ( "Starting wss on {wss_address}" ) ;
61
124
let wss_listener = TcpListener :: bind ( wss_address) . await ?;
@@ -102,31 +165,24 @@ async fn main() -> anyhow::Result<()> {
102
165
}
103
166
104
167
/// ProxyConfig is created at proxy startup, and lives forever.
105
- fn build_config ( args : & clap:: ArgMatches ) -> anyhow:: Result < & ' static ProxyConfig > {
106
- let tls_config = match (
107
- args. get_one :: < String > ( "tls-key" ) ,
108
- args. get_one :: < String > ( "tls-cert" ) ,
109
- ) {
168
+ fn build_config ( args : & ProxyCliArgs ) -> anyhow:: Result < & ' static ProxyConfig > {
169
+ let tls_config = match ( & args. tls_key , & args. tls_cert ) {
110
170
( Some ( key_path) , Some ( cert_path) ) => Some ( config:: configure_tls (
111
171
key_path,
112
172
cert_path,
113
- args. get_one :: < String > ( "certs-dir" ) ,
173
+ args. certs_dir . as_ref ( ) ,
114
174
) ?) ,
115
175
( None , None ) => None ,
116
176
_ => bail ! ( "either both or neither tls-key and tls-cert must be specified" ) ,
117
177
} ;
118
178
119
- let allow_self_signed_compute: bool = args
120
- . get_one :: < String > ( "allow-self-signed-compute" )
121
- . unwrap ( )
122
- . parse ( ) ?;
123
- if allow_self_signed_compute {
179
+ if args. allow_self_signed_compute {
124
180
warn ! ( "allowing self-signed compute certificates" ) ;
125
181
}
126
182
127
183
let metric_collection = match (
128
- args. get_one :: < String > ( "metric-collection-endpoint" ) ,
129
- args. get_one :: < String > ( "metric-collection-interval" ) ,
184
+ & args. metric_collection_endpoint ,
185
+ & args. metric_collection_interval ,
130
186
) {
131
187
( Some ( endpoint) , Some ( interval) ) => Some ( config:: MetricCollectionConfig {
132
188
endpoint : endpoint. parse ( ) ?,
@@ -139,145 +195,38 @@ fn build_config(args: &clap::ArgMatches) -> anyhow::Result<&'static ProxyConfig>
139
195
) ,
140
196
} ;
141
197
142
- let auth_backend = match args. get_one :: < String > ( "auth-backend" ) . unwrap ( ) . as_str ( ) {
143
- "console" => {
144
- let config:: CacheOptions { size, ttl } = args
145
- . get_one :: < String > ( "wake-compute-cache" )
146
- . unwrap ( )
147
- . parse ( ) ?;
198
+ let auth_backend = match & args. auth_backend {
199
+ AuthBackend :: Console => {
200
+ let config:: CacheOptions { size, ttl } = args. wake_compute_cache . parse ( ) ?;
148
201
149
202
info ! ( "Using NodeInfoCache (wake_compute) with size={size} ttl={ttl:?}" ) ;
150
203
let caches = Box :: leak ( Box :: new ( console:: caches:: ApiCaches {
151
204
node_info : console:: caches:: NodeInfoCache :: new ( "node_info_cache" , size, ttl) ,
152
205
} ) ) ;
153
206
154
- let url = args. get_one :: < String > ( "auth-endpoint" ) . unwrap ( ) . parse ( ) ?;
207
+ let url = args. auth_endpoint . parse ( ) ?;
155
208
let endpoint = http:: Endpoint :: new ( url, http:: new_client ( ) ) ;
156
209
157
210
let api = console:: provider:: neon:: Api :: new ( endpoint, caches) ;
158
211
auth:: BackendType :: Console ( Cow :: Owned ( api) , ( ) )
159
212
}
160
- "postgres" => {
161
- let url = args. get_one :: < String > ( "auth-endpoint" ) . unwrap ( ) . parse ( ) ?;
213
+ AuthBackend :: Postgres => {
214
+ let url = args. auth_endpoint . parse ( ) ?;
162
215
let api = console:: provider:: mock:: Api :: new ( url) ;
163
216
auth:: BackendType :: Postgres ( Cow :: Owned ( api) , ( ) )
164
217
}
165
- "link" => {
166
- let url = args. get_one :: < String > ( " uri" ) . unwrap ( ) . parse ( ) ?;
218
+ AuthBackend :: Link => {
219
+ let url = args. uri . parse ( ) ?;
167
220
auth:: BackendType :: Link ( Cow :: Owned ( url) )
168
221
}
169
- other => bail ! ( "unsupported auth backend: {other}" ) ,
170
222
} ;
171
223
172
224
let config = Box :: leak ( Box :: new ( ProxyConfig {
173
225
tls_config,
174
226
auth_backend,
175
227
metric_collection,
176
- allow_self_signed_compute,
228
+ allow_self_signed_compute : args . allow_self_signed_compute ,
177
229
} ) ) ;
178
230
179
231
Ok ( config)
180
232
}
181
-
182
- fn cli ( ) -> clap:: Command {
183
- clap:: Command :: new ( "Neon proxy/router" )
184
- . disable_help_flag ( true )
185
- . version ( GIT_VERSION )
186
- . arg (
187
- Arg :: new ( "proxy" )
188
- . short ( 'p' )
189
- . long ( "proxy" )
190
- . help ( "listen for incoming client connections on ip:port" )
191
- . default_value ( "127.0.0.1:4432" ) ,
192
- )
193
- . arg (
194
- Arg :: new ( "auth-backend" )
195
- . long ( "auth-backend" )
196
- . value_parser ( [ "console" , "postgres" , "link" ] )
197
- . default_value ( "link" ) ,
198
- )
199
- . arg (
200
- Arg :: new ( "mgmt" )
201
- . short ( 'm' )
202
- . long ( "mgmt" )
203
- . help ( "listen for management callback connection on ip:port" )
204
- . default_value ( "127.0.0.1:7000" ) ,
205
- )
206
- . arg (
207
- Arg :: new ( "http" )
208
- . long ( "http" )
209
- . help ( "listen for incoming http connections (metrics, etc) on ip:port" )
210
- . default_value ( "127.0.0.1:7001" ) ,
211
- )
212
- . arg (
213
- Arg :: new ( "wss" )
214
- . long ( "wss" )
215
- . help ( "listen for incoming wss connections on ip:port" ) ,
216
- )
217
- . arg (
218
- Arg :: new ( "uri" )
219
- . short ( 'u' )
220
- . long ( "uri" )
221
- . help ( "redirect unauthenticated users to the given uri in case of link auth" )
222
- . default_value ( "http://localhost:3000/psql_session/" ) ,
223
- )
224
- . arg (
225
- Arg :: new ( "auth-endpoint" )
226
- . short ( 'a' )
227
- . long ( "auth-endpoint" )
228
- . help ( "cloud API endpoint for authenticating users" )
229
- . default_value ( "http://localhost:3000/authenticate_proxy_request/" ) ,
230
- )
231
- . arg (
232
- Arg :: new ( "tls-key" )
233
- . short ( 'k' )
234
- . long ( "tls-key" )
235
- . alias ( "ssl-key" ) // backwards compatibility
236
- . help ( "path to TLS key for client postgres connections" ) ,
237
- )
238
- . arg (
239
- Arg :: new ( "tls-cert" )
240
- . short ( 'c' )
241
- . long ( "tls-cert" )
242
- . alias ( "ssl-cert" ) // backwards compatibility
243
- . help ( "path to TLS cert for client postgres connections" ) ,
244
- )
245
- // tls-key and tls-cert are for backwards compatibility, we can put all certs in one dir
246
- . arg (
247
- Arg :: new ( "certs-dir" )
248
- . long ( "certs-dir" )
249
- . help ( "path to directory with TLS certificates for client postgres connections" ) ,
250
- )
251
- . arg (
252
- Arg :: new ( "metric-collection-endpoint" )
253
- . long ( "metric-collection-endpoint" )
254
- . help ( "http endpoint to receive periodic metric updates" ) ,
255
- )
256
- . arg (
257
- Arg :: new ( "metric-collection-interval" )
258
- . long ( "metric-collection-interval" )
259
- . help ( "how often metrics should be sent to a collection endpoint" ) ,
260
- )
261
- . arg (
262
- Arg :: new ( "wake-compute-cache" )
263
- . long ( "wake-compute-cache" )
264
- . help ( "cache for `wake_compute` api method (use `size=0` to disable)" )
265
- . default_value ( config:: CacheOptions :: DEFAULT_OPTIONS_NODE_INFO ) ,
266
- )
267
- . arg (
268
- Arg :: new ( "allow-self-signed-compute" )
269
- . long ( "allow-self-signed-compute" )
270
- . help ( "Allow self-signed certificates for compute nodes (for testing)" )
271
- . default_value ( "false" ) ,
272
- )
273
- }
274
-
275
- #[ cfg( test) ]
276
- mod tests {
277
- use super :: * ;
278
-
279
- #[ test]
280
- fn verify_cli ( ) {
281
- cli ( ) . debug_assert ( ) ;
282
- }
283
- }
0 commit comments