PageRenderTime 41ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/unit/customizations/configure/test_configure.py

https://gitlab.com/smoke.torez/aws-cli
Python | 237 lines | 179 code | 24 blank | 34 comment | 0 complexity | 7501a126afa0ba95d408f3dac27bf28b MD5 | raw file
  1. # Copyright 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License"). You
  4. # may not use this file except in compliance with the License. A copy of
  5. # the License is located at
  6. #
  7. # http://aws.amazon.com/apache2.0/
  8. #
  9. # or in the "license" file accompanying this file. This file is
  10. # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
  11. # ANY KIND, either express or implied. See the License for the specific
  12. # language governing permissions and limitations under the License.
  13. import os
  14. import mock
  15. from awscli.customizations.configure import configure, ConfigValue, NOT_SET
  16. from awscli.testutils import unittest
  17. from . import FakeSession
  18. class TestConfigureCommand(unittest.TestCase):
  19. def setUp(self):
  20. self.writer = mock.Mock()
  21. self.global_args = mock.Mock()
  22. self.global_args.profile = None
  23. self.precanned = PrecannedPrompter(value='new_value')
  24. self.session = FakeSession({'config_file': 'myconfigfile'})
  25. self.configure = configure.ConfigureCommand(self.session,
  26. prompter=self.precanned,
  27. config_writer=self.writer)
  28. def assert_credentials_file_updated_with(self, new_values):
  29. called_args = self.writer.update_config.call_args_list
  30. credentials_file_call = called_args[0]
  31. expected_creds_file = os.path.expanduser('~/fake_credentials_filename')
  32. self.assertEqual(credentials_file_call,
  33. mock.call(new_values, expected_creds_file))
  34. def test_configure_command_sends_values_to_writer(self):
  35. self.configure(args=[], parsed_globals=self.global_args)
  36. # Credentials are always written to the shared credentials file.
  37. self.assert_credentials_file_updated_with(
  38. {'aws_access_key_id': 'new_value',
  39. 'aws_secret_access_key': 'new_value'})
  40. # Non-credentials config is written to the config file.
  41. self.writer.update_config.assert_called_with(
  42. {'region': 'new_value',
  43. 'output': 'new_value'}, 'myconfigfile')
  44. def test_same_values_are_not_changed(self):
  45. # If the user enters the same value as the current value, we don't need
  46. # to write anything to the config.
  47. self.configure = configure.ConfigureCommand(self.session,
  48. prompter=EchoPrompter(),
  49. config_writer=self.writer)
  50. self.configure(args=[], parsed_globals=self.global_args)
  51. self.assertFalse(self.writer.update_config.called)
  52. def test_none_values_are_not_changed(self):
  53. # If a user hits enter, this will result in a None value which means
  54. # don't change the existing values. In this case, we don't need
  55. # to write anything out to the config.
  56. user_presses_enter = None
  57. precanned = PrecannedPrompter(value=user_presses_enter)
  58. self.configure = configure.ConfigureCommand(self.session,
  59. prompter=precanned,
  60. config_writer=self.writer)
  61. self.configure(args=[], parsed_globals=self.global_args)
  62. self.assertFalse(self.writer.update_config.called)
  63. def test_create_configure_cmd_session_only(self):
  64. self.configure = configure.ConfigureCommand(self.session)
  65. self.assertIsInstance(self.configure, configure.ConfigureCommand)
  66. def test_some_values_changed(self):
  67. # Test the case where the user only wants to change a single_value.
  68. responses = {
  69. "AWS Access Key ID": None,
  70. "AWS Secert Access Key": None,
  71. "Default region name": None,
  72. "Default output format": "NEW OUTPUT FORMAT",
  73. }
  74. prompter = KeyValuePrompter(responses)
  75. self.configure = configure.ConfigureCommand(self.session, prompter=prompter,
  76. config_writer=self.writer)
  77. self.configure(args=[], parsed_globals=self.global_args)
  78. # We only need to write out the default output format.
  79. self.writer.update_config.assert_called_with(
  80. {'output': 'NEW OUTPUT FORMAT'}, 'myconfigfile')
  81. def test_section_name_can_be_changed_for_profiles(self):
  82. # If the user specifies "--profile myname" we need to write
  83. # this out to the [profile myname] section.
  84. self.global_args.profile = 'myname'
  85. self.configure(args=[], parsed_globals=self.global_args)
  86. # Note the __section__ key name.
  87. self.assert_credentials_file_updated_with(
  88. {'aws_access_key_id': 'new_value',
  89. 'aws_secret_access_key': 'new_value',
  90. '__section__': 'myname'})
  91. self.writer.update_config.assert_called_with(
  92. {'__section__': 'profile myname',
  93. 'region': 'new_value',
  94. 'output': 'new_value'}, 'myconfigfile')
  95. def test_session_says_profile_does_not_exist(self):
  96. # Whenever you try to get a config value from botocore,
  97. # it will raise an exception complaining about ProfileNotFound.
  98. # We should handle this case, and write out a new profile section
  99. # in the config file.
  100. session = FakeSession({'config_file': 'myconfigfile'},
  101. profile_does_not_exist=True)
  102. self.configure = configure.ConfigureCommand(session,
  103. prompter=self.precanned,
  104. config_writer=self.writer)
  105. self.global_args.profile = 'profile-does-not-exist'
  106. self.configure(args=[], parsed_globals=self.global_args)
  107. self.assert_credentials_file_updated_with(
  108. {'aws_access_key_id': 'new_value',
  109. 'aws_secret_access_key': 'new_value',
  110. '__section__': 'profile-does-not-exist'})
  111. self.writer.update_config.assert_called_with(
  112. {'__section__': 'profile profile-does-not-exist',
  113. 'region': 'new_value',
  114. 'output': 'new_value'}, 'myconfigfile')
  115. class TestInteractivePrompter(unittest.TestCase):
  116. def setUp(self):
  117. self.patch = mock.patch(
  118. 'awscli.customizations.configure.configure.raw_input')
  119. self.mock_raw_input = self.patch.start()
  120. def tearDown(self):
  121. self.patch.stop()
  122. def test_access_key_is_masked(self):
  123. self.mock_raw_input.return_value = 'foo'
  124. prompter = configure.InteractivePrompter()
  125. response = prompter.get_value(
  126. current_value='myaccesskey', config_name='aws_access_key_id',
  127. prompt_text='Access key')
  128. # First we should return the value from raw_input.
  129. self.assertEqual(response, 'foo')
  130. # We should also not display the entire access key.
  131. prompt_text = self.mock_raw_input.call_args[0][0]
  132. self.assertNotIn('myaccesskey', prompt_text)
  133. self.assertRegexpMatches(prompt_text, r'\[\*\*\*\*.*\]')
  134. def test_access_key_not_masked_when_none(self):
  135. self.mock_raw_input.return_value = 'foo'
  136. prompter = configure.InteractivePrompter()
  137. response = prompter.get_value(
  138. current_value=None, config_name='aws_access_key_id',
  139. prompt_text='Access key')
  140. # First we should return the value from raw_input.
  141. self.assertEqual(response, 'foo')
  142. prompt_text = self.mock_raw_input.call_args[0][0]
  143. self.assertIn('[None]', prompt_text)
  144. def test_secret_key_is_masked(self):
  145. prompter = configure.InteractivePrompter()
  146. prompter.get_value(
  147. current_value='mysupersecretkey',
  148. config_name='aws_secret_access_key',
  149. prompt_text='Secret Key')
  150. # We should also not display the entire secret key.
  151. prompt_text = self.mock_raw_input.call_args[0][0]
  152. self.assertNotIn('mysupersecretkey', prompt_text)
  153. self.assertRegexpMatches(prompt_text, r'\[\*\*\*\*.*\]')
  154. def test_non_secret_keys_are_not_masked(self):
  155. prompter = configure.InteractivePrompter()
  156. prompter.get_value(
  157. current_value='mycurrentvalue', config_name='not_a_secret_key',
  158. prompt_text='Enter value')
  159. # We should also not display the entire secret key.
  160. prompt_text = self.mock_raw_input.call_args[0][0]
  161. self.assertIn('mycurrentvalue', prompt_text)
  162. self.assertRegexpMatches(prompt_text, r'\[mycurrentvalue\]')
  163. def test_user_hits_enter_returns_none(self):
  164. # If a user hits enter, then raw_input returns the empty string.
  165. self.mock_raw_input.return_value = ''
  166. prompter = configure.InteractivePrompter()
  167. response = prompter.get_value(
  168. current_value=None, config_name='aws_access_key_id',
  169. prompt_text='Access key')
  170. # We convert the empty string to None to indicate that there
  171. # was no input.
  172. self.assertIsNone(response)
  173. class TestConfigValueMasking(unittest.TestCase):
  174. def test_config_value_is_masked(self):
  175. config_value = ConfigValue(
  176. 'fake_access_key', 'config_file', 'aws_access_key_id')
  177. self.assertEqual(config_value.value, 'fake_access_key')
  178. config_value.mask_value()
  179. self.assertEqual(config_value.value, '****************_key')
  180. def test_dont_mask_unset_value(self):
  181. no_config = ConfigValue(NOT_SET, None, None)
  182. self.assertEqual(no_config.value, NOT_SET)
  183. no_config.mask_value()
  184. self.assertEqual(no_config.value, NOT_SET)
  185. class PrecannedPrompter(object):
  186. def __init__(self, value):
  187. self._value = value
  188. def get_value(self, current_value, logical_name, prompt_text=''):
  189. return self._value
  190. class EchoPrompter(object):
  191. def get_value(self, current_value, logical_name, prompt_text=''):
  192. return current_value
  193. class KeyValuePrompter(object):
  194. def __init__(self, mapping):
  195. self.mapping = mapping
  196. def get_value(self, current_value, config_name, prompt_text=''):
  197. return self.mapping.get(prompt_text)