@@ -32,7 +32,9 @@ struct Cli {
3232 #[ arg( long, global = true , value_name = "DIR" ) ]
3333 prefix : Option < String > ,
3434
35- /// auth token for a remote VMM.
35+ /// auth token for a VMM with `[auth]` enabled (sent as `Authorization:
36+ /// Bearer`). Falls back to `DSTACK_VMM_TOKEN`, then the token written by
37+ /// `dstackup install`.
3638 #[ arg( long, global = true ) ]
3739 token : Option < String > ,
3840
@@ -105,20 +107,31 @@ enum Command {
105107#[ tokio:: main]
106108async fn main ( ) -> Result < ( ) > {
107109 let cli = Cli :: parse ( ) ;
108- // remote-auth wiring lands with the TLS+token transport.
109- let _ = & cli. token ;
110110 let defaults = LocalDefaults :: read ( cli. prefix . as_deref ( ) ) ;
111111 let use_local_defaults = cli. host . is_none ( ) ;
112112 let host = cli
113113 . host
114114 . clone ( )
115115 . or_else ( || defaults. as_ref ( ) . and_then ( |d| d. client_url . clone ( ) ) )
116116 . unwrap_or_else ( || DEFAULT_HOST . to_string ( ) ) ;
117+ // auth token: --token, then DSTACK_VMM_TOKEN, then the token file written
118+ // by `dstackup install` (local defaults only).
119+ let token = cli
120+ . token
121+ . clone ( )
122+ . or_else ( || std:: env:: var ( "DSTACK_VMM_TOKEN" ) . ok ( ) )
123+ . filter ( |t| !t. trim ( ) . is_empty ( ) )
124+ . or_else ( || {
125+ use_local_defaults
126+ . then ( || defaults. as_ref ( ) . and_then ( LocalDefaults :: token) )
127+ . flatten ( )
128+ } ) ;
129+ let token = token. as_deref ( ) ;
117130 let json = cli. json ;
118131
119132 match cli. command {
120- Command :: Apps => cmd_apps ( & host, json) . await ,
121- Command :: Logs { id, lines } => cmd_logs ( & host, & id, lines) . await ,
133+ Command :: Apps => cmd_apps ( & host, token , json) . await ,
134+ Command :: Logs { id, lines } => cmd_logs ( & host, token , & id, lines) . await ,
122135 Command :: Deploy {
123136 compose,
124137 compose_file,
@@ -149,6 +162,7 @@ async fn main() -> Result<()> {
149162 } ;
150163 cmd_deploy (
151164 & host,
165+ token,
152166 & compose,
153167 & name,
154168 image. as_deref ( ) ,
@@ -178,6 +192,7 @@ fn resolve_compose_arg(positional: Option<String>, flagged: Option<String>) -> R
178192
179193struct LocalDefaults {
180194 client_url : Option < String > ,
195+ client_token_path : Option < String > ,
181196 image : Option < String > ,
182197 allowlist_path : Option < String > ,
183198}
@@ -197,6 +212,11 @@ impl LocalDefaults {
197212 . and_then ( |x| x. as_str ( ) )
198213 . filter ( |s| !s. is_empty ( ) )
199214 . map ( str:: to_string) ,
215+ client_token_path : v
216+ . get ( "client_token_path" )
217+ . and_then ( |x| x. as_str ( ) )
218+ . filter ( |s| !s. is_empty ( ) )
219+ . map ( str:: to_string) ,
200220 image : v
201221 . get ( "image" )
202222 . and_then ( |x| x. as_str ( ) )
@@ -213,6 +233,14 @@ impl LocalDefaults {
213233 fn allowlist_path ( & self ) -> Option < String > {
214234 self . allowlist_path . clone ( )
215235 }
236+
237+ /// read the VMM API token from the file recorded by `dstackup install`.
238+ fn token ( & self ) -> Option < String > {
239+ let path = self . client_token_path . as_ref ( ) ?;
240+ let token = std:: fs:: read_to_string ( path) . ok ( ) ?;
241+ let token = token. trim ( ) ;
242+ ( !token. is_empty ( ) ) . then ( || token. to_string ( ) )
243+ }
216244}
217245
218246#[ cfg( test) ]
@@ -307,6 +335,7 @@ mod tests {
307335#[ allow( clippy:: too_many_arguments) ]
308336async fn cmd_deploy (
309337 host : & str ,
338+ token : Option < & str > ,
310339 compose_path : & str ,
311340 name : & str ,
312341 image : Option < & str > ,
@@ -339,7 +368,7 @@ async fn cmd_deploy(
339368 ..Default :: default ( )
340369 } ;
341370
342- let vmm = Vmm :: connect ( host) ?;
371+ let vmm = Vmm :: connect_with_token ( host, token ) ?;
343372 let hash = vmm. get_compose_hash ( & cfg) . await ?;
344373 let app_id = short ( & hash, 40 ) ;
345374 cfg. app_id = Some ( app_id. clone ( ) ) ;
@@ -429,8 +458,8 @@ fn stub(name: &str) -> Result<()> {
429458 )
430459}
431460
432- async fn cmd_apps ( host : & str , json : bool ) -> Result < ( ) > {
433- let vmm = Vmm :: connect ( host) ?;
461+ async fn cmd_apps ( host : & str , token : Option < & str > , json : bool ) -> Result < ( ) > {
462+ let vmm = Vmm :: connect_with_token ( host, token ) ?;
434463 let resp = vmm. status ( ) . await ?;
435464 if json {
436465 let arr: Vec < _ > = resp
@@ -470,8 +499,8 @@ async fn cmd_apps(host: &str, json: bool) -> Result<()> {
470499 Ok ( ( ) )
471500}
472501
473- async fn cmd_logs ( host : & str , id : & str , lines : u32 ) -> Result < ( ) > {
474- let vmm = Vmm :: connect ( host) ?;
502+ async fn cmd_logs ( host : & str , token : Option < & str > , id : & str , lines : u32 ) -> Result < ( ) > {
503+ let vmm = Vmm :: connect_with_token ( host, token ) ?;
475504 let logs = vmm. logs ( id, lines) . await ?;
476505 print ! ( "{logs}" ) ;
477506 Ok ( ( ) )
0 commit comments