@@ -230,3 +230,104 @@ def test_new_profile_without_region(
230230 },
231231 'configfile' ,
232232 )
233+
234+
235+ @pytest .mark .parametrize (
236+ 'profile_config,expect_prompt_to_be_called' ,
237+ [
238+ pytest .param ({}, False , id = "Empty profile" ),
239+ pytest .param (
240+ {'login_session' : 'arn:aws:iam::0123456789012:user/Admin' },
241+ False ,
242+ id = "Existing login profile" ,
243+ ),
244+ pytest .param (
245+ {'web_identity_token_file' : '/path' },
246+ True ,
247+ id = "Web Identity Token profile" ,
248+ ),
249+ pytest .param ({'sso_role_name' : 'role' }, True , id = "SSO profile" ),
250+ pytest .param (
251+ {'aws_access_key_id' : 'AKIAIOSFODNN7EXAMPLE' },
252+ True ,
253+ id = "IAM access key profile" ,
254+ ),
255+ pytest .param (
256+ {'role_arn' : 'arn:aws:iam::123456789012:role/MyRole' },
257+ True ,
258+ id = "Assume role profile" ,
259+ ),
260+ pytest .param (
261+ {'credential_process' : '/path/to/credential/process' },
262+ True ,
263+ id = "Credential process profile" ,
264+ ),
265+ ],
266+ )
267+ @mock .patch ('awscli.customizations.login.login.compat_input' , return_value = 'y' )
268+ @mock .patch ('awscli.customizations.login.utils.get_base_sign_in_uri' )
269+ @mock .patch (
270+ 'awscli.customizations.login.utils.SameDeviceLoginTokenFetcher.fetch_token'
271+ )
272+ def test_accept_change_to_existing_profile_if_needed (
273+ mock_token_fetcher ,
274+ mock_base_sign_in_uri ,
275+ mock_input ,
276+ mock_login_command ,
277+ mock_session ,
278+ profile_config ,
279+ expect_prompt_to_be_called ,
280+ ):
281+ mock_base_sign_in_uri .return_value = 'https://foo'
282+ mock_token_fetcher .return_value = (
283+ {
284+ 'accessToken' : 'access_token' ,
285+ 'idToken' : SAMPLE_ID_TOKEN ,
286+ 'expiresIn' : 3600 ,
287+ },
288+ 'arn:aws:iam::0123456789012:user/Admin' ,
289+ )
290+ mock_session .full_config = {'profiles' : {'profile-name' : profile_config }}
291+
292+ mock_login_command ._run_main (DEFAULT_ARGS , DEFAULT_GLOBAL_ARGS )
293+ mock_token_fetcher .assert_called_once ()
294+
295+ assert mock_input .called == expect_prompt_to_be_called
296+
297+
298+ @mock .patch ('awscli.customizations.login.login.compat_input' , return_value = 'n' )
299+ @mock .patch ('awscli.customizations.login.utils.get_base_sign_in_uri' )
300+ @mock .patch (
301+ 'awscli.customizations.login.utils.SameDeviceLoginTokenFetcher.fetch_token'
302+ )
303+ def test_decline_change_to_existing_profile_does_not_update (
304+ mock_token_fetcher ,
305+ mock_base_sign_in_uri ,
306+ mock_input ,
307+ mock_login_command ,
308+ mock_session ,
309+ mock_config_file_writer ,
310+ mock_token_loader ,
311+ ):
312+ mock_base_sign_in_uri .return_value = 'https://foo'
313+ mock_token_fetcher .return_value = (
314+ {
315+ 'accessToken' : 'access_token' ,
316+ 'idToken' : SAMPLE_ID_TOKEN ,
317+ 'expiresIn' : 3600 ,
318+ },
319+ 'arn:aws:iam::0123456789012:user/Admin' ,
320+ )
321+ mock_session .full_config = {
322+ 'profiles' : {
323+ 'profile-name' : {'aws_access_key_id' : 'AKIAIOSFODNN7EXAMPLE' }
324+ }
325+ }
326+
327+ mock_login_command ._run_main (DEFAULT_ARGS , DEFAULT_GLOBAL_ARGS )
328+
329+ # Because we mocked 'n' to compat_input above, we don't expect the command
330+ # to have finished when the user declines the existing credential prompt
331+ mock_input .assert_called_once ()
332+ mock_token_loader .save_token .assert_not_called ()
333+ mock_config_file_writer .update_config .assert_not_called ()
0 commit comments