@@ -25,7 +25,8 @@ use std::io::{self, IsTerminal};
2525
2626use clap:: { CommandFactory , Parser } ;
2727use clap_complete:: generate;
28- use eyre:: OptionExt ;
28+ use dialoguer:: FuzzySelect ;
29+ use eyre:: eyre;
2930use tracing:: { warn, Level } ;
3031
3132use openstack_sdk:: {
@@ -81,16 +82,30 @@ pub async fn entry_point() -> Result<(), OpenStackCliError> {
8182 . init ( ) ;
8283
8384 let cfg = openstack_sdk:: config:: ConfigFile :: new ( ) . unwrap ( ) ;
85+ // Identify target cloud to connect to
86+ let cloud_name = match cli. global_opts . os_cloud {
87+ Some ( ref cloud) => cloud. clone ( ) ,
88+ None => {
89+ if std:: io:: stdin ( ) . is_terminal ( ) {
90+ // Cloud was not selected and we are in the potentially interactive mode (terminal)
91+ let mut profiles = cfg. get_available_clouds ( ) ;
92+ profiles. sort ( ) ;
93+ let selected_cloud_idx = FuzzySelect :: new ( )
94+ . with_prompt ( "Please select cloud you want to connect to (use `--os-cloud` next time for efficiency)?" )
95+ . items ( & profiles)
96+ . interact ( ) ?;
97+ profiles[ selected_cloud_idx] . clone ( )
98+ } else {
99+ return Err (
100+ eyre ! ( "`--os-cloud` or `OS_CLOUD` environment variable must be given" ) . into ( ) ,
101+ ) ;
102+ }
103+ }
104+ } ;
105+ // Get the connection details
84106 let profile = cfg
85- . get_cloud_config (
86- cli. global_opts
87- . os_cloud
88- . clone ( )
89- . ok_or_eyre ( "`--os-cloud` or `OS_CLOUD` environment variable must be given" ) ?,
90- ) ?
91- . ok_or ( OpenStackCliError :: ConnectionNotFound (
92- cli. global_opts . os_cloud . clone ( ) . unwrap ( ) ,
93- ) ) ?;
107+ . get_cloud_config ( & cloud_name) ?
108+ . ok_or ( OpenStackCliError :: ConnectionNotFound ( cloud_name) ) ?;
94109 let mut renew_auth: bool = false ;
95110
96111 // Login command need to be analyzed before authorization
@@ -104,10 +119,12 @@ pub async fn entry_point() -> Result<(), OpenStackCliError> {
104119
105120 let mut session;
106121 if std:: io:: stdin ( ) . is_terminal ( ) {
122+ // Interactive session (may ask for password/MFA/SSO)
107123 session = AsyncOpenStack :: new_interactive ( & profile, renew_auth)
108124 . await
109125 . map_err ( |err| OpenStackCliError :: Auth { source : err } ) ?;
110126 } else {
127+ // Non-interactive session if i.e. scripted with chaining
111128 session = AsyncOpenStack :: new ( & profile)
112129 . await
113130 . map_err ( |err| OpenStackCliError :: Auth { source : err } ) ?;
0 commit comments