Skip to content

Commit 31156eb

Browse files
Fix unclear configure import error (#9617)
* Improved error messaging for command to clarify file:// prefix requirement * Update documentation for the csv file format * Raise ValueError instead * Comment batch
1 parent e7fbb28 commit 31156eb

File tree

3 files changed

+43
-1
lines changed

3 files changed

+43
-1
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"type": "enhancement",
3+
"category": "configure",
4+
"description": "Improved error messaging for `aws configure import --csv` command to clarify file"
5+
}

awscli/customizations/configure/importer.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,11 @@ class ConfigureImportCommand(BasicCommand):
3737
'name': 'csv',
3838
'required': True,
3939
'help_text': (
40-
'The credentials in CSV format generated by the AWS web console.'
40+
'The credentials in CSV format generated by the AWS web console. '
4141
'The CSV file must contain the "User name", "Access key ID", and '
4242
'"Secret access key" headers.'
43+
'If passing a CSV file path instead of a CSV-formatted string, '
44+
'the "file://" prefix is required.'
4345
),
4446
'cli_type_name': 'string',
4547
},
@@ -86,6 +88,7 @@ def _get_config_path(self):
8688
return os.path.expanduser(config_file)
8789

8890
def _import_csv(self, contents):
91+
self._check_possible_filepath(contents)
8992
config_path = self._get_config_path()
9093
credentials = self._csv_parser.parse_credentials(contents)
9194
for credential in credentials:
@@ -97,6 +100,15 @@ def _import_csv(self, contents):
97100
import_msg = 'Successfully imported %s profile(s)\n' % len(credentials)
98101
uni_print(import_msg, out_file=self._out_stream)
99102

103+
def _check_possible_filepath(self, csv_data):
104+
if ('\n' not in csv_data and
105+
os.path.exists(csv_data) and
106+
not csv_data.startswith('file://')):
107+
raise ValueError(
108+
"You may be passing a file to import without the 'file://' prefix. "
109+
"To import a CSV file, use --csv file://path/to/file.csv"
110+
)
111+
100112
def _run_main(self, parsed_args, parsed_globals):
101113
self._csv_parser.strict = not parsed_args.skip_invalid
102114
self._profile_prefix = parsed_args.profile_prefix

tests/unit/customizations/configure/test_importer.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,31 @@ def test_import_downloaded_bad_headers(self):
9393
with self.assertRaises(CredentialParserError):
9494
self.import_command(args=['--csv', content], parsed_globals=None)
9595

96+
def test_raises_error_when_plain_file_path_passed(self):
97+
with open('temp_creds.csv', 'w') as f:
98+
f.write('User name,Access key ID,Secret access key\nuser,AKID,SAK')
99+
try:
100+
with self.assertRaises(ValueError) as cm:
101+
self.import_command(args=['--csv', 'temp_creds.csv'], parsed_globals=None)
102+
self.assertIn("without the 'file://' prefix", str(cm.exception))
103+
finally:
104+
os.remove('temp_creds.csv')
105+
106+
def test_inline_csv_succeeds(self):
107+
csv_string = 'User name,Access key ID,Secret access key\nuser,AKID,SAK'
108+
self.import_command(args=['--csv', csv_string], parsed_globals=None)
109+
self.assertIn('Successfully imported 1 profile', self.stdout.getvalue())
110+
111+
def test_csv_content_from_file_succeeds(self):
112+
with open('temp_creds.csv', 'w') as f:
113+
f.write('User name,Access key ID,Secret access key\nuser,AKID,SAK')
114+
try:
115+
with open('temp_creds.csv', 'r') as f:
116+
contents = f.read()
117+
self.import_command(args=['--csv', contents], parsed_globals=None)
118+
self.assertIn('Successfully imported 1 profile', self.stdout.getvalue())
119+
finally:
120+
os.remove('temp_creds.csv')
96121

97122
class TestCSVCredentialParser(unittest.TestCase):
98123
def setUp(self):

0 commit comments

Comments
 (0)