Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aws
GitHub Repository: aws/aws-cli
Path: blob/develop/tests/functional/codeartifact/test_codeartifact_login.py
2630 views
1
import copy
2
import os
3
import platform
4
import subprocess
5
import time
6
import re
7
8
from botocore.utils import parse_timestamp
9
10
from tests import CLIRunner, AWSRequest, AWSResponse
11
from awscli.testutils import unittest, FileCreator, mock
12
from awscli.compat import urlparse, StringIO, RawConfigParser
13
from awscli.customizations.codeartifact.login import CodeArtifactLogin
14
15
16
class TestCodeArtifactLogin(unittest.TestCase):
17
18
prefix = ['codeartifact', 'login']
19
20
def setUp(self):
21
self.file_creator = FileCreator()
22
self.test_pypi_rc_path = self.file_creator.full_path('pypirc')
23
if not os.path.isdir(os.path.dirname(self.test_pypi_rc_path)):
24
os.makedirs(os.path.dirname(self.test_pypi_rc_path))
25
26
self.domain = 'domain'
27
self.domain_owner = 'domain-owner'
28
self.repository = 'repository'
29
self.endpoint_type = 'ipv4'
30
self.auth_token = 'auth-token'
31
self.namespace = 'namespace'
32
self.nuget_index_url_fmt = '{endpoint}v3/index.json'
33
self.nuget_source_name = self.domain + '/' + self.repository
34
self.duration = 3600
35
self.expiration = time.time() + self.duration
36
self.expiration_as_datetime = parse_timestamp(self.expiration)
37
38
self.pypi_rc_path_patch = mock.patch(
39
'awscli.customizations.codeartifact.login.TwineLogin'
40
'.get_pypi_rc_path'
41
)
42
self.pypi_rc_path_mock = self.pypi_rc_path_patch.start()
43
self.pypi_rc_path_mock.return_value = self.test_pypi_rc_path
44
45
self.test_netrc_path = self.file_creator.full_path('.netrc')
46
self.get_netrc_path_patch = mock.patch(
47
'awscli.customizations.codeartifact.login.SwiftLogin'
48
'.get_netrc_path'
49
)
50
self.get_netrc_mock = self.get_netrc_path_patch.start()
51
self.get_netrc_mock.return_value = self.test_netrc_path
52
53
self.subprocess_patch = mock.patch('subprocess.run')
54
self.subprocess_mock = self.subprocess_patch.start()
55
self.subprocess_check_output_patch = mock.patch(
56
'subprocess.check_output'
57
)
58
self.subprocess_check_out_mock = \
59
self.subprocess_check_output_patch.start()
60
self.cli_runner = CLIRunner()
61
62
def tearDown(self):
63
self.pypi_rc_path_patch.stop()
64
self.subprocess_check_output_patch.stop()
65
self.get_netrc_path_patch.stop()
66
self.subprocess_patch.stop()
67
self.file_creator.remove_all()
68
69
def _setup_cmd(self, tool,
70
include_domain_owner=False,
71
dry_run=False,
72
include_endpoint_type=False,
73
include_duration_seconds=False,
74
include_namespace=False):
75
package_format = CodeArtifactLogin.TOOL_MAP[tool]['package_format']
76
self.endpoint = 'https://{domain}-{domainOwner}.codeartifact.aws.' \
77
'a2z.com/{format}/{repository}/'.format(
78
domain=self.domain,
79
domainOwner=self.domain_owner,
80
format=package_format,
81
repository=self.repository
82
)
83
84
cmdline = copy.copy(self.prefix)
85
cmdline.extend([
86
'--domain', self.domain,
87
'--repository', self.repository,
88
'--tool', tool,
89
])
90
91
if include_domain_owner:
92
cmdline.extend(['--domain-owner', self.domain_owner])
93
94
if include_endpoint_type:
95
cmdline.extend(['--endpoint-type', self.endpoint_type])
96
97
if dry_run:
98
cmdline.append('--dry-run')
99
100
if include_duration_seconds:
101
cmdline.extend(['--duration-seconds', str(self.duration)])
102
103
if include_namespace:
104
cmdline.extend(['--namespace', self.namespace])
105
106
self.cli_runner.add_response(
107
AWSResponse(
108
service_name='codeartifact',
109
operation_name='GetAuthorizationToken',
110
parsed_response={
111
"authorizationToken": self.auth_token,
112
"expiration": self.expiration_as_datetime
113
}
114
)
115
)
116
self.cli_runner.add_response(
117
AWSResponse(
118
service_name='codeartifact',
119
operation_name='GetRepositoryEndpoint',
120
parsed_response={"repositoryEndpoint": self.endpoint}
121
)
122
)
123
124
return cmdline
125
126
def _get_swift_commands(self, scope=None, token=None):
127
commands = []
128
set_registry_command = [
129
'swift', 'package-registry', 'set', self.endpoint
130
]
131
if scope is not None:
132
set_registry_command.extend(['--scope', scope])
133
commands.append(set_registry_command)
134
135
login_registry_command = [
136
'swift', 'package-registry', 'login', f'{self.endpoint}login'
137
]
138
if token is not None:
139
login_registry_command.extend(['--token', token])
140
commands.append(login_registry_command)
141
142
return commands
143
144
def _get_nuget_commands(self):
145
nuget_index_url = self.nuget_index_url_fmt.format(
146
endpoint=self.endpoint
147
)
148
149
commands = []
150
commands.append(
151
[
152
'nuget', 'sources', 'add',
153
'-name', self.nuget_source_name,
154
'-source', nuget_index_url,
155
'-username', 'aws',
156
'-password', self.auth_token
157
]
158
)
159
return commands
160
161
def _get_dotnet_commands(self):
162
nuget_index_url = self.nuget_index_url_fmt.format(
163
endpoint=self.endpoint
164
)
165
166
commands = []
167
commands.append(
168
[
169
'dotnet', 'nuget', 'add', 'source', nuget_index_url,
170
'--name', self.nuget_source_name,
171
'--username', 'aws',
172
'--password', self.auth_token
173
]
174
)
175
return commands
176
177
def _get_npm_commands(self, **kwargs):
178
npm_cmd = 'npm.cmd' \
179
if platform.system().lower() == 'windows' else 'npm'
180
181
repo_uri = urlparse.urlsplit(self.endpoint)
182
always_auth_config = '//{}{}:always-auth'.format(
183
repo_uri.netloc, repo_uri.path
184
)
185
auth_token_config = '//{}{}:_authToken'.format(
186
repo_uri.netloc, repo_uri.path
187
)
188
189
scope = kwargs.get('scope')
190
registry = '{}:registry'.format(scope) if scope else 'registry'
191
192
commands = []
193
commands.append(
194
[npm_cmd, 'config', 'set', registry, self.endpoint]
195
)
196
commands.append(
197
[npm_cmd, 'config', 'set', always_auth_config, 'true']
198
)
199
commands.append(
200
[npm_cmd, 'config', 'set', auth_token_config, self.auth_token]
201
)
202
203
return commands
204
205
def _get_pip_commands(self):
206
pip_index_url_fmt = '{scheme}://aws:{auth_token}@{netloc}{path}simple/'
207
repo_uri = urlparse.urlsplit(self.endpoint)
208
pip_index_url = pip_index_url_fmt.format(
209
scheme=repo_uri.scheme,
210
auth_token=self.auth_token,
211
netloc=repo_uri.netloc,
212
path=repo_uri.path
213
)
214
215
return [['pip', 'config', 'set', 'global.index-url', pip_index_url]]
216
217
def _get_twine_commands(self):
218
default_pypi_rc_fmt = '''\
219
[distutils]
220
index-servers=
221
pypi
222
codeartifact
223
224
[codeartifact]
225
repository: {repository_endpoint}
226
username: aws
227
password: {auth_token}'''
228
default_pypi_rc = default_pypi_rc_fmt.format(
229
repository_endpoint=self.endpoint,
230
auth_token=self.auth_token
231
)
232
233
pypi_rc = RawConfigParser()
234
if os.path.exists(self.test_pypi_rc_path):
235
pypi_rc.read(self.test_pypi_rc_path)
236
index_servers = pypi_rc.get('distutils', 'index-servers')
237
servers = [
238
server.strip()
239
for server in index_servers.split('\n')
240
if server.strip() != ''
241
]
242
243
if 'codeartifact' not in servers:
244
servers.append('codeartifact')
245
pypi_rc.set(
246
'distutils', 'index-servers', '\n' + '\n'.join(servers)
247
)
248
249
if 'codeartifact' not in pypi_rc.sections():
250
pypi_rc.add_section('codeartifact')
251
252
pypi_rc.set('codeartifact', 'repository', self.endpoint)
253
pypi_rc.set('codeartifact', 'username', 'aws')
254
pypi_rc.set('codeartifact', 'password', self.auth_token)
255
else:
256
pypi_rc.read_string(default_pypi_rc)
257
258
pypi_rc_stream = StringIO()
259
pypi_rc.write(pypi_rc_stream)
260
pypi_rc_str = pypi_rc_stream.getvalue()
261
pypi_rc_stream.close()
262
263
return pypi_rc_str
264
265
def _assert_expiration_printed_to_stdout(self, stdout):
266
self.assertEqual(
267
self.expiration_as_datetime.strftime(
268
"%Y-%m-%d %H:%M:%S"), stdout.split("at ")[1][0:19]
269
)
270
271
def _assert_operations_called(
272
self, package_format, result,
273
include_domain_owner=False, include_duration_seconds=False,
274
include_endpoint_type=False
275
):
276
277
get_auth_token_kwargs = {
278
'domain': self.domain
279
}
280
get_repo_endpoint_kwargs = {
281
'domain': self.domain,
282
'repository': self.repository,
283
'format': package_format
284
}
285
286
if include_domain_owner:
287
get_auth_token_kwargs['domainOwner'] = self.domain_owner
288
get_repo_endpoint_kwargs['domainOwner'] = self.domain_owner
289
290
if include_endpoint_type:
291
get_repo_endpoint_kwargs['endpointType'] = self.endpoint_type
292
293
if include_duration_seconds:
294
get_auth_token_kwargs['durationSeconds'] = self.duration
295
296
self.assertEqual(
297
result.aws_requests,
298
[
299
AWSRequest(
300
service_name='codeartifact',
301
operation_name='GetAuthorizationToken',
302
params=get_auth_token_kwargs,
303
),
304
AWSRequest(
305
service_name='codeartifact',
306
operation_name='GetRepositoryEndpoint',
307
params=get_repo_endpoint_kwargs,
308
)
309
]
310
)
311
312
def _assert_subprocess_execution(self, commands):
313
expected_calls = [
314
mock.call(
315
command,
316
capture_output=True,
317
check=True
318
) for command in commands
319
]
320
self.subprocess_mock.assert_has_calls(
321
expected_calls, any_order=True
322
)
323
324
def _assert_subprocess_check_output_execution(self, commands):
325
expected_calls = [
326
mock.call(
327
command,
328
stderr=subprocess.PIPE,
329
) for command in commands
330
]
331
self.subprocess_check_out_mock.assert_has_calls(
332
expected_calls, any_order=True
333
)
334
335
def _assert_dry_run_execution(self, commands, stdout):
336
self.subprocess_mock.assert_not_called()
337
for command in commands:
338
self.assertIn(' '.join(command), stdout)
339
340
def _assert_pypi_rc_has_expected_content(
341
self, pypi_rc_str, server, repo_url=None, username=None, password=None
342
):
343
pypi_rc = RawConfigParser()
344
pypi_rc.read_string(pypi_rc_str)
345
346
self.assertIn('distutils', pypi_rc.sections())
347
self.assertIn('index-servers', pypi_rc.options('distutils'))
348
index_servers = pypi_rc.get('distutils', 'index-servers')
349
index_servers = [
350
index_server.strip()
351
for index_server
352
in index_servers.split('\n')
353
if index_server.strip() != ''
354
]
355
self.assertIn(server, index_servers)
356
357
if repo_url or username or password:
358
self.assertIn(server, pypi_rc.sections())
359
360
if repo_url:
361
self.assertIn('repository', pypi_rc.options(server))
362
self.assertEqual(pypi_rc.get(server, 'repository'), repo_url)
363
364
if username:
365
self.assertIn('username', pypi_rc.options(server))
366
self.assertEqual(pypi_rc.get(server, 'username'), username)
367
368
if password:
369
self.assertIn('password', pypi_rc.options(server))
370
self.assertEqual(pypi_rc.get(server, 'password'), password)
371
372
def _assert_netrc_has_expected_content(self):
373
with open(self.test_netrc_path, 'r') as f:
374
actual_contents = f.read()
375
376
hostname = urlparse.urlparse(self.endpoint).hostname
377
expected_contents = f'machine {hostname} login token password {self.auth_token}\n'
378
self.assertEqual(expected_contents, actual_contents)
379
380
@mock.patch('awscli.customizations.codeartifact.login.is_macos', True)
381
def test_swift_login_without_domain_owner_macos(self):
382
cmdline = self._setup_cmd(tool='swift')
383
result = self.cli_runner.run(cmdline)
384
self.assertEqual(result.rc, 0)
385
self._assert_operations_called(package_format='swift', result=result)
386
self._assert_expiration_printed_to_stdout(result.stdout)
387
self._assert_subprocess_execution(
388
self._get_swift_commands(token=self.auth_token)
389
)
390
self.assertFalse(os.path.exists(self.test_netrc_path))
391
392
@mock.patch('awscli.customizations.codeartifact.login.is_macos', False)
393
def test_swift_login_without_domain_owner_non_macos(self):
394
cmdline = self._setup_cmd(tool='swift')
395
result = self.cli_runner.run(cmdline)
396
self.assertEqual(result.rc, 0)
397
self._assert_operations_called(package_format='swift', result=result)
398
self._assert_expiration_printed_to_stdout(result.stdout)
399
self._assert_subprocess_execution(
400
self._get_swift_commands()
401
)
402
self._assert_netrc_has_expected_content()
403
404
@mock.patch('awscli.customizations.codeartifact.login.is_macos', False)
405
def test_swift_login_without_domain_owner_dry_run(self):
406
cmdline = self._setup_cmd(tool='swift', dry_run=True)
407
result = self.cli_runner.run(cmdline)
408
self.assertEqual(result.rc, 0)
409
self._assert_operations_called(package_format='swift', result=result)
410
self._assert_dry_run_execution(self._get_swift_commands(), result.stdout)
411
self.assertFalse(os.path.exists(self.test_netrc_path))
412
413
@mock.patch('awscli.customizations.codeartifact.login.is_macos', True)
414
def test_swift_login_with_domain_owner_macos(self):
415
cmdline = self._setup_cmd(tool='swift', include_domain_owner=True)
416
result = self.cli_runner.run(cmdline)
417
self.assertEqual(result.rc, 0)
418
self._assert_operations_called(
419
package_format='swift', result=result,
420
include_domain_owner=True, include_duration_seconds=False
421
)
422
self._assert_expiration_printed_to_stdout(result.stdout)
423
self._assert_subprocess_execution(
424
self._get_swift_commands(token=self.auth_token)
425
)
426
427
@mock.patch('awscli.customizations.codeartifact.login.is_macos', False)
428
def test_swift_login_with_domain_owner_non_macos(self):
429
cmdline = self._setup_cmd(tool='swift', include_domain_owner=True)
430
result = self.cli_runner.run(cmdline)
431
self.assertEqual(result.rc, 0)
432
self._assert_operations_called(
433
package_format='swift', result=result,
434
include_domain_owner=True, include_duration_seconds=False
435
)
436
self._assert_expiration_printed_to_stdout(result.stdout)
437
self._assert_subprocess_execution(
438
self._get_swift_commands()
439
)
440
self._assert_netrc_has_expected_content()
441
442
@mock.patch('awscli.customizations.codeartifact.login.is_macos', True)
443
def test_swift_login_with_domain_owner_duration_macos(self):
444
cmdline = self._setup_cmd(tool='swift', include_domain_owner=True,
445
include_duration_seconds=True)
446
result = self.cli_runner.run(cmdline)
447
self.assertEqual(result.rc, 0)
448
self._assert_operations_called(
449
package_format='swift', result=result,
450
include_domain_owner=True, include_duration_seconds=True
451
)
452
self._assert_expiration_printed_to_stdout(result.stdout)
453
self._assert_subprocess_execution(
454
self._get_swift_commands(token=self.auth_token)
455
)
456
457
@mock.patch('awscli.customizations.codeartifact.login.is_macos', False)
458
def test_swift_login_with_domain_owner_duration_non_macos(self):
459
cmdline = self._setup_cmd(tool='swift', include_domain_owner=True,
460
include_duration_seconds=True)
461
result = self.cli_runner.run(cmdline)
462
self.assertEqual(result.rc, 0)
463
self._assert_operations_called(
464
package_format='swift', result=result,
465
include_domain_owner=True, include_duration_seconds=True
466
)
467
self._assert_expiration_printed_to_stdout(result.stdout)
468
self._assert_subprocess_execution(
469
self._get_swift_commands()
470
)
471
self._assert_netrc_has_expected_content()
472
473
@mock.patch('awscli.customizations.codeartifact.login.is_macos', False)
474
def test_swift_login_with_domain_owner_dry_run(self):
475
cmdline = self._setup_cmd(
476
tool='swift', include_domain_owner=True, dry_run=True
477
)
478
result = self.cli_runner.run(cmdline)
479
self.assertEqual(result.rc, 0)
480
self._assert_operations_called(
481
package_format='swift', result=result, include_domain_owner=True
482
)
483
self._assert_dry_run_execution(
484
self._get_swift_commands(), result.stdout
485
)
486
self.assertFalse(os.path.exists(self.test_netrc_path))
487
488
@mock.patch('awscli.customizations.codeartifact.login.is_macos', True)
489
def test_swift_login_with_domain_owner_duration_dry_run(self):
490
cmdline = self._setup_cmd(
491
tool='swift', include_domain_owner=True,
492
include_duration_seconds=True, dry_run=True
493
)
494
result = self.cli_runner.run(cmdline)
495
self.assertEqual(result.rc, 0)
496
self._assert_operations_called(
497
package_format='swift', result=result, include_domain_owner=True,
498
include_duration_seconds=True
499
)
500
self._assert_dry_run_execution(
501
self._get_swift_commands(token=self.auth_token), result.stdout
502
)
503
504
@mock.patch('awscli.customizations.codeartifact.login.is_macos', True)
505
def test_swift_login_with_namespace_macos(self):
506
cmdline = self._setup_cmd(
507
tool='swift', include_namespace=True
508
)
509
result = self.cli_runner.run(cmdline)
510
self.assertEqual(result.rc, 0)
511
self._assert_operations_called(package_format='swift', result=result)
512
self._assert_expiration_printed_to_stdout(result.stdout)
513
self._assert_subprocess_execution(
514
self._get_swift_commands(scope=self.namespace, token=self.auth_token)
515
)
516
517
@mock.patch('awscli.customizations.codeartifact.login.is_macos', False)
518
def test_swift_login_with_namespace_non_macos(self):
519
cmdline = self._setup_cmd(
520
tool='swift', include_namespace=True
521
)
522
result = self.cli_runner.run(cmdline)
523
self.assertEqual(result.rc, 0)
524
self._assert_operations_called(package_format='swift', result=result)
525
self._assert_expiration_printed_to_stdout(result.stdout)
526
self._assert_subprocess_execution(
527
self._get_swift_commands(scope=self.namespace)
528
)
529
self._assert_netrc_has_expected_content()
530
531
@mock.patch('awscli.customizations.codeartifact.login.is_macos', True)
532
def test_swift_login_with_namespace_dry_run(self):
533
cmdline = self._setup_cmd(
534
tool='swift', include_namespace=True, dry_run=True
535
)
536
result = self.cli_runner.run(cmdline)
537
self.assertEqual(result.rc, 0)
538
self._assert_operations_called(package_format='swift', result=result)
539
self._assert_dry_run_execution(
540
self._get_swift_commands(scope=self.namespace),result.stdout)
541
542
@mock.patch('awscli.customizations.codeartifact.login.is_macos', False)
543
def test_swift_login_with_namespace_with_endpoint_type(self):
544
cmdline = self._setup_cmd(
545
tool='swift', include_namespace=True, include_endpoint_type=True
546
)
547
result = self.cli_runner.run(cmdline)
548
self.assertEqual(result.rc, 0)
549
self._assert_operations_called(package_format='swift', result=result, include_endpoint_type=True)
550
self._assert_expiration_printed_to_stdout(result.stdout)
551
self._assert_subprocess_execution(
552
self._get_swift_commands(scope=self.namespace)
553
)
554
self._assert_netrc_has_expected_content()
555
556
@mock.patch('awscli.customizations.codeartifact.login.is_macos', True)
557
def test_swift_login_with_domain_owner_with_endpoint_type(self):
558
cmdline = self._setup_cmd(
559
tool='swift', include_domain_owner=True, include_endpoint_type=True
560
)
561
result = self.cli_runner.run(cmdline)
562
self.assertEqual(result.rc, 0)
563
self._assert_operations_called(package_format='swift', result=result, include_endpoint_type=True,
564
include_domain_owner=True)
565
self._assert_expiration_printed_to_stdout(result.stdout)
566
self._assert_subprocess_execution(
567
self._get_swift_commands(token=self.auth_token)
568
)
569
570
def test_nuget_login_without_domain_owner_without_duration_seconds(self):
571
cmdline = self._setup_cmd(tool='nuget')
572
result = self.cli_runner.run(cmdline)
573
self.assertEqual(result.rc, 0)
574
self._assert_operations_called(package_format='nuget', result=result)
575
self._assert_expiration_printed_to_stdout(result.stdout)
576
self._assert_subprocess_execution(
577
self._get_nuget_commands()
578
)
579
580
def test_nuget_login_with_domain_owner_without_duration_seconds(self):
581
cmdline = self._setup_cmd(tool='nuget', include_domain_owner=True)
582
result = self.cli_runner.run(cmdline)
583
self.assertEqual(result.rc, 0)
584
self._assert_operations_called(
585
package_format='nuget',
586
include_domain_owner=True,
587
result=result
588
)
589
self._assert_expiration_printed_to_stdout(result.stdout)
590
self._assert_subprocess_execution(
591
self._get_nuget_commands()
592
)
593
594
def test_nuget_login_without_domain_owner_with_duration_seconds(self):
595
cmdline = self._setup_cmd(tool='nuget', include_duration_seconds=True)
596
result = self.cli_runner.run(cmdline)
597
self.assertEqual(result.rc, 0)
598
self._assert_operations_called(
599
package_format='nuget',
600
include_duration_seconds=True,
601
result=result
602
)
603
self._assert_expiration_printed_to_stdout(result.stdout)
604
self._assert_subprocess_execution(
605
self._get_nuget_commands()
606
)
607
608
def test_nuget_login_with_domain_owner_duration_sections(self):
609
cmdline = self._setup_cmd(
610
tool='nuget',
611
include_domain_owner=True,
612
include_duration_seconds=True
613
)
614
result = self.cli_runner.run(cmdline)
615
self.assertEqual(result.rc, 0)
616
self._assert_operations_called(
617
package_format='nuget',
618
include_domain_owner=True,
619
include_duration_seconds=True,
620
result=result
621
)
622
self._assert_expiration_printed_to_stdout(result.stdout)
623
self._assert_subprocess_execution(
624
self._get_nuget_commands()
625
)
626
627
def test_nuget_login_with_domain_owner_duration_endpoint_type(self):
628
cmdline = self._setup_cmd(
629
tool='nuget',
630
include_domain_owner=True,
631
include_duration_seconds=True,
632
include_endpoint_type=True
633
)
634
result = self.cli_runner.run(cmdline)
635
self.assertEqual(result.rc, 0)
636
self._assert_operations_called(
637
package_format='nuget',
638
include_domain_owner=True,
639
include_duration_seconds=True,
640
include_endpoint_type=True,
641
result=result
642
)
643
self._assert_expiration_printed_to_stdout(result.stdout)
644
self._assert_subprocess_execution(
645
self._get_nuget_commands()
646
)
647
648
def test_nuget_login_without_domain_owner_dry_run(self):
649
cmdline = self._setup_cmd(tool='nuget', dry_run=True)
650
result = self.cli_runner.run(cmdline)
651
self.assertEqual(result.rc, 0)
652
self._assert_operations_called(package_format='nuget', result=result)
653
self._assert_dry_run_execution(
654
self._get_nuget_commands(),
655
result.stdout
656
)
657
658
def test_nuget_login_with_domain_owner_dry_run(self):
659
cmdline = self._setup_cmd(
660
tool='nuget', include_domain_owner=True, dry_run=True
661
)
662
result = self.cli_runner.run(cmdline)
663
self.assertEqual(result.rc, 0)
664
self._assert_operations_called(
665
package_format='nuget',
666
include_domain_owner=True,
667
result=result
668
)
669
self._assert_dry_run_execution(
670
self._get_nuget_commands(),
671
result.stdout
672
)
673
674
def test_nuget_login_with_duration_seconds_dry_run(self):
675
cmdline = self._setup_cmd(
676
tool='nuget', include_duration_seconds=True, dry_run=True
677
)
678
result = self.cli_runner.run(cmdline)
679
self.assertEqual(result.rc, 0)
680
self._assert_operations_called(
681
package_format='nuget',
682
include_duration_seconds=True,
683
result=result
684
)
685
self._assert_dry_run_execution(
686
self._get_nuget_commands(),
687
result.stdout
688
)
689
690
def test_nuget_login_with_domain_owner_duration_seconds_dry_run(self):
691
cmdline = self._setup_cmd(
692
tool='nuget', include_domain_owner=True,
693
include_duration_seconds=True, dry_run=True
694
)
695
result = self.cli_runner.run(cmdline)
696
self.assertEqual(result.rc, 0)
697
self._assert_operations_called(
698
package_format='nuget',
699
include_domain_owner=True,
700
include_duration_seconds=True,
701
result=result
702
)
703
self._assert_dry_run_execution(
704
self._get_nuget_commands(),
705
result.stdout
706
)
707
708
def test_nuget_login_with_domain_owner_duration_seconds_with_endpoint_type_dryrun(self):
709
cmdline = self._setup_cmd(
710
tool='nuget', include_domain_owner=True,
711
include_duration_seconds=True,
712
dry_run=True, include_endpoint_type=True
713
)
714
result = self.cli_runner.run(cmdline)
715
self.assertEqual(result.rc, 0)
716
self._assert_operations_called(
717
package_format='nuget',
718
include_domain_owner=True,
719
include_duration_seconds=True,
720
include_endpoint_type=True,
721
result=result
722
)
723
self._assert_dry_run_execution(
724
self._get_nuget_commands(),
725
result.stdout
726
)
727
728
@mock.patch('awscli.customizations.codeartifact.login.is_windows', True)
729
def test_dotnet_login_without_domain_owner_without_duration_seconds(self):
730
cmdline = self._setup_cmd(tool='dotnet')
731
result = self.cli_runner.run(cmdline)
732
self.assertEqual(result.rc, 0)
733
self._assert_operations_called(package_format='nuget', result=result)
734
self._assert_expiration_printed_to_stdout(result.stdout)
735
self._assert_subprocess_execution(
736
self._get_dotnet_commands()
737
)
738
739
@mock.patch('awscli.customizations.codeartifact.login.is_windows', True)
740
def test_dotnet_login_without_domain_owner_without_duration_seconds_with_endpoint_type(self):
741
cmdline = self._setup_cmd(tool='dotnet', include_endpoint_type=True)
742
result = self.cli_runner.run(cmdline)
743
self.assertEqual(result.rc, 0)
744
self._assert_operations_called(package_format='nuget', result=result, include_endpoint_type=True)
745
self._assert_expiration_printed_to_stdout(result.stdout)
746
self._assert_subprocess_execution(
747
self._get_dotnet_commands()
748
)
749
750
@mock.patch('awscli.customizations.codeartifact.login.is_windows', True)
751
def test_dotnet_login_with_domain_owner_without_duration_seconds(self):
752
cmdline = self._setup_cmd(tool='dotnet', include_domain_owner=True)
753
result = self.cli_runner.run(cmdline)
754
self.assertEqual(result.rc, 0)
755
self._assert_operations_called(
756
package_format='nuget',
757
include_domain_owner=True,
758
result=result
759
)
760
self._assert_expiration_printed_to_stdout(result.stdout)
761
self._assert_subprocess_execution(
762
self._get_dotnet_commands()
763
)
764
765
@mock.patch('awscli.customizations.codeartifact.login.is_windows', True)
766
def test_dotnet_login_without_domain_owner_with_duration_seconds(self):
767
cmdline = self._setup_cmd(tool='dotnet', include_duration_seconds=True)
768
result = self.cli_runner.run(cmdline)
769
self.assertEqual(result.rc, 0)
770
self._assert_operations_called(
771
package_format='nuget',
772
include_duration_seconds=True,
773
result=result
774
)
775
self._assert_expiration_printed_to_stdout(result.stdout)
776
self._assert_subprocess_execution(
777
self._get_dotnet_commands()
778
)
779
780
@mock.patch('awscli.customizations.codeartifact.login.is_windows', True)
781
def test_dotnet_login_with_domain_owner_duration_sections(self):
782
cmdline = self._setup_cmd(
783
tool='dotnet',
784
include_domain_owner=True,
785
include_duration_seconds=True
786
)
787
result = self.cli_runner.run(cmdline)
788
self.assertEqual(result.rc, 0)
789
self._assert_operations_called(
790
package_format='nuget',
791
include_domain_owner=True,
792
include_duration_seconds=True,
793
result=result
794
)
795
self._assert_expiration_printed_to_stdout(result.stdout)
796
self._assert_subprocess_execution(
797
self._get_dotnet_commands()
798
)
799
800
@mock.patch('awscli.customizations.codeartifact.login.is_windows', True)
801
def test_dotnet_login_without_domain_owner_dry_run(self):
802
cmdline = self._setup_cmd(tool='dotnet', dry_run=True)
803
result = self.cli_runner.run(cmdline)
804
self.assertEqual(result.rc, 0)
805
self._assert_operations_called(package_format='nuget', result=result)
806
self._assert_dry_run_execution(
807
self._get_dotnet_commands(),
808
result.stdout
809
)
810
811
@mock.patch('awscli.customizations.codeartifact.login.is_windows', True)
812
def test_dotnet_login_with_domain_owner_dry_run(self):
813
cmdline = self._setup_cmd(
814
tool='dotnet', include_domain_owner=True, dry_run=True
815
)
816
result = self.cli_runner.run(cmdline)
817
self.assertEqual(result.rc, 0)
818
self._assert_operations_called(
819
package_format='nuget',
820
include_domain_owner=True,
821
result=result
822
)
823
self._assert_dry_run_execution(
824
self._get_dotnet_commands(),
825
result.stdout
826
)
827
828
@mock.patch('awscli.customizations.codeartifact.login.is_windows', True)
829
def test_dotnet_login_with_duration_seconds_dry_run(self):
830
cmdline = self._setup_cmd(
831
tool='dotnet', include_duration_seconds=True, dry_run=True
832
)
833
result = self.cli_runner.run(cmdline)
834
self.assertEqual(result.rc, 0)
835
self._assert_operations_called(
836
package_format='nuget',
837
include_duration_seconds=True,
838
result=result
839
)
840
self._assert_dry_run_execution(
841
self._get_dotnet_commands(),
842
result.stdout
843
)
844
845
@mock.patch('awscli.customizations.codeartifact.login.is_windows', True)
846
def test_dotnet_login_with_domain_owner_duration_seconds_dry_run(self):
847
cmdline = self._setup_cmd(
848
tool='dotnet', include_domain_owner=True,
849
include_duration_seconds=True, dry_run=True
850
)
851
result = self.cli_runner.run(cmdline)
852
self.assertEqual(result.rc, 0)
853
self._assert_operations_called(
854
package_format='nuget',
855
include_domain_owner=True,
856
include_duration_seconds=True,
857
result=result
858
)
859
self._assert_dry_run_execution(
860
self._get_dotnet_commands(),
861
result.stdout
862
)
863
864
_NUGET_SOURCES_LIST_RESPONSE_WITH_EXTRA_NON_LIST_TEXT = b"""\
865
Welcome to dotnet 2.0!
866
867
Registered Sources:
868
1. Source Name 1 [Enabled]
869
https://source1.com/index.json
870
2. ati-nugetserver [Disabled]
871
http://atinugetserver-env.elasticbeanstalk.com/nuget
872
warn : You are running the 'list source' operation with an 'HTTP' source,
873
'ati-nugetserver' [http://atinugetserver-env..elasticbeanstalk.com/nuget]'.
874
Non-HTTPS access will be removed in a future version. Consider migrating
875
to an 'HTTPS' source."""
876
877
@mock.patch('awscli.customizations.codeartifact.login.is_windows', True)
878
def test_dotnet_login_sources_listed_with_extra_non_list_text(self):
879
880
self.subprocess_check_output_patch.return_value = \
881
self._NUGET_SOURCES_LIST_RESPONSE_WITH_EXTRA_NON_LIST_TEXT
882
883
cmdline = self._setup_cmd(tool='dotnet')
884
result = self.cli_runner.run(cmdline)
885
self.assertEqual(result.rc, 0)
886
self._assert_operations_called(package_format='nuget', result=result)
887
commands = [[
888
'dotnet', 'nuget', 'list', 'source', '--format', 'detailed'
889
]]
890
self._assert_subprocess_check_output_execution(commands)
891
892
@mock.patch('awscli.customizations.codeartifact.login.is_windows', True)
893
def test_dotnet_login_sources_listed_with_extra_non_list_text_with_endpoint_type(self):
894
895
self.subprocess_check_output_patch.return_value = \
896
self._NUGET_SOURCES_LIST_RESPONSE_WITH_EXTRA_NON_LIST_TEXT
897
898
cmdline = self._setup_cmd(tool='dotnet', include_endpoint_type=True)
899
result = self.cli_runner.run(cmdline)
900
self.assertEqual(result.rc, 0)
901
self._assert_operations_called(package_format='nuget', result=result, include_endpoint_type=True)
902
commands = [[
903
'dotnet', 'nuget', 'list', 'source', '--format', 'detailed'
904
]]
905
self._assert_subprocess_check_output_execution(commands)
906
907
def test_npm_login_without_domain_owner(self):
908
cmdline = self._setup_cmd(tool='npm')
909
result = self.cli_runner.run(cmdline)
910
self.assertEqual(result.rc, 0)
911
self._assert_operations_called(package_format='npm', result=result)
912
self._assert_expiration_printed_to_stdout(result.stdout)
913
self._assert_subprocess_execution(self._get_npm_commands())
914
915
def test_npm_login_without_domain_owner_dry_run(self):
916
cmdline = self._setup_cmd(tool='npm', dry_run=True)
917
result = self.cli_runner.run(cmdline)
918
self.assertEqual(result.rc, 0)
919
self._assert_operations_called(package_format='npm', result=result)
920
self._assert_dry_run_execution(self._get_npm_commands(), result.stdout)
921
922
def test_npm_login_always_auth_error_ignored(self):
923
"""Test login ignores error for always-auth.
924
925
This test is for NPM version >= 9 where the support of 'always-auth'
926
has been dropped. Running the command to set config gives a non-zero
927
exit code. This is to make sure that login ignores that error and all
928
other commands executes successfully.
929
"""
930
def side_effect(command, capture_output, check):
931
if any('always-auth' in arg for arg in command):
932
raise subprocess.CalledProcessError(
933
returncode=1,
934
cmd=command
935
)
936
937
return mock.DEFAULT
938
939
self.subprocess_mock.side_effect = side_effect
940
cmdline = self._setup_cmd(tool='npm')
941
result = self.cli_runner.run(cmdline)
942
self.assertEqual(result.rc, 0)
943
self._assert_expiration_printed_to_stdout(result.stdout)
944
self._assert_subprocess_execution(self._get_npm_commands())
945
946
def test_npm_login_with_domain_owner(self):
947
cmdline = self._setup_cmd(tool='npm', include_domain_owner=True)
948
result = self.cli_runner.run(cmdline)
949
self.assertEqual(result.rc, 0)
950
self._assert_operations_called(
951
package_format='npm', result=result,
952
include_domain_owner=True, include_duration_seconds=False
953
)
954
self._assert_expiration_printed_to_stdout(result.stdout)
955
self._assert_subprocess_execution(self._get_npm_commands())
956
957
def test_npm_login_with_domain_owner_endpoint_type(self):
958
cmdline = self._setup_cmd(tool='npm', include_domain_owner=True, include_endpoint_type=True)
959
result = self.cli_runner.run(cmdline)
960
self.assertEqual(result.rc, 0)
961
self._assert_operations_called(
962
package_format='npm', result=result,
963
include_domain_owner=True, include_duration_seconds=False,
964
include_endpoint_type=True
965
)
966
self._assert_expiration_printed_to_stdout(result.stdout)
967
self._assert_subprocess_execution(self._get_npm_commands())
968
969
def test_npm_login_with_domain_owner_duration(self):
970
cmdline = self._setup_cmd(tool='npm', include_domain_owner=True,
971
include_duration_seconds=True)
972
result = self.cli_runner.run(cmdline)
973
self.assertEqual(result.rc, 0)
974
self._assert_operations_called(
975
package_format='npm', result=result,
976
include_domain_owner=True, include_duration_seconds=True
977
)
978
self._assert_expiration_printed_to_stdout(result.stdout)
979
self._assert_subprocess_execution(self._get_npm_commands())
980
981
def test_npm_login_with_domain_owner_dry_run(self):
982
cmdline = self._setup_cmd(
983
tool='npm', include_domain_owner=True, dry_run=True
984
)
985
result = self.cli_runner.run(cmdline)
986
self.assertEqual(result.rc, 0)
987
self._assert_operations_called(
988
package_format='npm', result=result, include_domain_owner=True
989
)
990
self._assert_dry_run_execution(self._get_npm_commands(), result.stdout)
991
992
def test_npm_login_with_namespace(self):
993
cmdline = self._setup_cmd(
994
tool='npm', include_namespace=True
995
)
996
result = self.cli_runner.run(cmdline)
997
self.assertEqual(result.rc, 0)
998
self._assert_operations_called(package_format='npm', result=result)
999
self._assert_expiration_printed_to_stdout(result.stdout)
1000
self._assert_subprocess_execution(
1001
self._get_npm_commands(scope='@{}'.format(self.namespace))
1002
)
1003
1004
def test_npm_login_with_namespace_dry_run(self):
1005
cmdline = self._setup_cmd(
1006
tool='npm', include_namespace=True, dry_run=True
1007
)
1008
result = self.cli_runner.run(cmdline)
1009
self.assertEqual(result.rc, 0)
1010
self._assert_operations_called(package_format='npm', result=result)
1011
self._assert_dry_run_execution(
1012
self._get_npm_commands(scope='@{}'.format(self.namespace)),
1013
result.stdout
1014
)
1015
1016
def test_npm_login_with_namespace_endpoint_type_dry_run(self):
1017
cmdline = self._setup_cmd(
1018
tool='npm', include_namespace=True, dry_run=True, include_endpoint_type=True
1019
)
1020
result = self.cli_runner.run(cmdline)
1021
self.assertEqual(result.rc, 0)
1022
self._assert_operations_called(package_format='npm', result=result, include_endpoint_type=True)
1023
self._assert_dry_run_execution(
1024
self._get_npm_commands(scope='@{}'.format(self.namespace)),
1025
result.stdout
1026
)
1027
1028
def test_pip_login_without_domain_owner(self):
1029
cmdline = self._setup_cmd(tool='pip')
1030
result = self.cli_runner.run(cmdline)
1031
self.assertEqual(result.rc, 0)
1032
self._assert_operations_called(package_format='pypi', result=result)
1033
self._assert_expiration_printed_to_stdout(result.stdout)
1034
self._assert_subprocess_execution(self._get_pip_commands())
1035
1036
def test_pip_login_without_domain_owner_dry_run(self):
1037
cmdline = self._setup_cmd(tool='pip', dry_run=True)
1038
result = self.cli_runner.run(cmdline)
1039
self.assertEqual(result.rc, 0)
1040
self._assert_operations_called(package_format='pypi', result=result)
1041
self._assert_dry_run_execution(self._get_pip_commands(), result.stdout)
1042
1043
def test_pip_login_with_domain_owner(self):
1044
cmdline = self._setup_cmd(tool='pip', include_domain_owner=True)
1045
result = self.cli_runner.run(cmdline)
1046
self.assertEqual(result.rc, 0)
1047
self._assert_operations_called(
1048
package_format='pypi', result=result, include_domain_owner=True
1049
)
1050
self._assert_expiration_printed_to_stdout(result.stdout)
1051
self._assert_subprocess_execution(self._get_pip_commands())
1052
1053
def test_pip_login_with_domain_owner_duration(self):
1054
cmdline = self._setup_cmd(tool='pip', include_domain_owner=True,
1055
include_duration_seconds=True)
1056
result = self.cli_runner.run(cmdline)
1057
self.assertEqual(result.rc, 0)
1058
self._assert_operations_called(
1059
package_format='pypi', result=result, include_domain_owner=True,
1060
include_duration_seconds=True
1061
)
1062
self._assert_expiration_printed_to_stdout(result.stdout)
1063
self._assert_subprocess_execution(self._get_pip_commands())
1064
1065
def test_pip_login_with_domain_owner_duration_endpoint_type(self):
1066
cmdline = self._setup_cmd(tool='pip', include_domain_owner=True,
1067
include_duration_seconds=True, include_endpoint_type=True)
1068
result = self.cli_runner.run(cmdline)
1069
self.assertEqual(result.rc, 0)
1070
self._assert_operations_called(
1071
package_format='pypi', result=result, include_domain_owner=True,
1072
include_duration_seconds=True, include_endpoint_type=True
1073
)
1074
self._assert_expiration_printed_to_stdout(result.stdout)
1075
self._assert_subprocess_execution(self._get_pip_commands())
1076
1077
def test_pip_login_with_domain_owner_dry_run(self):
1078
cmdline = self._setup_cmd(
1079
tool='pip', include_domain_owner=True, dry_run=True
1080
)
1081
result = self.cli_runner.run(cmdline)
1082
self.assertEqual(result.rc, 0)
1083
self._assert_operations_called(
1084
package_format='pypi', result=result, include_domain_owner=True
1085
)
1086
self._assert_dry_run_execution(self._get_pip_commands(), result.stdout)
1087
1088
def test_pip_login_with_namespace(self):
1089
cmdline = self._setup_cmd(tool='pip', include_namespace=True)
1090
result = self.cli_runner.run(cmdline)
1091
self.assertEqual(result.rc, 255)
1092
self._assert_operations_called(package_format='pypi', result=result)
1093
self.assertIn(
1094
'Argument --namespace is not supported for pip', result.stderr
1095
)
1096
1097
def test_pip_login_with_namespace_dry_run(self):
1098
cmdline = self._setup_cmd(
1099
tool='pip', include_namespace=True, dry_run=True)
1100
result = self.cli_runner.run(cmdline)
1101
self.assertEqual(result.rc, 255)
1102
self._assert_operations_called(package_format='pypi', result=result)
1103
self.assertIn(
1104
'Argument --namespace is not supported for pip', result.stderr
1105
)
1106
1107
def test_pip_login_command_failed_auth_token_redacted(self):
1108
def side_effect(command, capture_output, check):
1109
raise subprocess.CalledProcessError(
1110
returncode=1,
1111
cmd=command
1112
)
1113
1114
self.subprocess_mock.side_effect = side_effect
1115
cmdline = self._setup_cmd(tool='pip')
1116
result = self.cli_runner.run(cmdline)
1117
self.assertEqual(result.rc, 255)
1118
self.assertIn(
1119
"Command '['pip', 'config', 'set', 'global.index-url',"
1120
" 'https://aws:******@domain-domain-owner.codeartifact.aws.a2z.com/pypi/repository/simple/']'"
1121
" returned non-zero exit status 1.",
1122
result.stderr
1123
)
1124
1125
def test_twine_login_without_domain_owner(self):
1126
cmdline = self._setup_cmd(tool='twine')
1127
result = self.cli_runner.run(cmdline)
1128
self.assertEqual(result.rc, 0)
1129
self._assert_operations_called(package_format='pypi', result=result)
1130
self._assert_expiration_printed_to_stdout(result.stdout)
1131
with open(self.test_pypi_rc_path) as f:
1132
test_pypi_rc_str = f.read()
1133
1134
self._assert_pypi_rc_has_expected_content(
1135
pypi_rc_str=test_pypi_rc_str,
1136
server='codeartifact',
1137
repo_url=self.endpoint,
1138
username='aws',
1139
password=self.auth_token
1140
)
1141
1142
def test_twine_login_without_domain_owner_dry_run(self):
1143
cmdline = self._setup_cmd(tool='twine', dry_run=True)
1144
result = self.cli_runner.run(cmdline)
1145
self.assertEqual(result.rc, 0)
1146
self._assert_operations_called(package_format='pypi', result=result)
1147
self.assertFalse(os.path.exists(self.test_pypi_rc_path))
1148
self._assert_pypi_rc_has_expected_content(
1149
pypi_rc_str=self._get_twine_commands(),
1150
server='codeartifact',
1151
repo_url=self.endpoint,
1152
username='aws',
1153
password=self.auth_token
1154
)
1155
1156
def test_twine_login_without_domain_owner_dry_run_endpoint_type(self):
1157
cmdline = self._setup_cmd(tool='twine', dry_run=True, include_endpoint_type=True)
1158
result = self.cli_runner.run(cmdline)
1159
self.assertEqual(result.rc, 0)
1160
self._assert_operations_called(package_format='pypi', result=result, include_endpoint_type=True)
1161
self.assertFalse(os.path.exists(self.test_pypi_rc_path))
1162
self._assert_pypi_rc_has_expected_content(
1163
pypi_rc_str=self._get_twine_commands(),
1164
server='codeartifact',
1165
repo_url=self.endpoint,
1166
username='aws',
1167
password=self.auth_token
1168
)
1169
1170
def test_twine_login_with_domain_owner(self):
1171
cmdline = self._setup_cmd(tool='twine', include_domain_owner=True)
1172
result = self.cli_runner.run(cmdline)
1173
self.assertEqual(result.rc, 0)
1174
self._assert_operations_called(
1175
package_format='pypi', result=result, include_domain_owner=True
1176
)
1177
self._assert_expiration_printed_to_stdout(result.stdout)
1178
1179
with open(self.test_pypi_rc_path) as f:
1180
test_pypi_rc_str = f.read()
1181
1182
self._assert_pypi_rc_has_expected_content(
1183
pypi_rc_str=test_pypi_rc_str,
1184
server='codeartifact',
1185
repo_url=self.endpoint,
1186
username='aws',
1187
password=self.auth_token
1188
)
1189
1190
def test_twine_login_with_domain_owner_duration(self):
1191
cmdline = self._setup_cmd(tool='twine', include_domain_owner=True,
1192
include_duration_seconds=True)
1193
result = self.cli_runner.run(cmdline)
1194
self.assertEqual(result.rc, 0)
1195
self._assert_operations_called(
1196
package_format='pypi', result=result, include_domain_owner=True,
1197
include_duration_seconds=True
1198
)
1199
self._assert_expiration_printed_to_stdout(result.stdout)
1200
1201
with open(self.test_pypi_rc_path) as f:
1202
test_pypi_rc_str = f.read()
1203
1204
self._assert_pypi_rc_has_expected_content(
1205
pypi_rc_str=test_pypi_rc_str,
1206
server='codeartifact',
1207
repo_url=self.endpoint,
1208
username='aws',
1209
password=self.auth_token
1210
)
1211
1212
def test_twine_login_with_domain_owner_dry_run(self):
1213
cmdline = self._setup_cmd(
1214
tool='twine', include_domain_owner=True, dry_run=True
1215
)
1216
result = self.cli_runner.run(cmdline)
1217
self.assertEqual(result.rc, 0)
1218
self._assert_operations_called(
1219
package_format='pypi', result=result, include_domain_owner=True
1220
)
1221
self.assertFalse(os.path.exists(self.test_pypi_rc_path))
1222
self._assert_pypi_rc_has_expected_content(
1223
pypi_rc_str=self._get_twine_commands(),
1224
server='codeartifact',
1225
repo_url=self.endpoint,
1226
username='aws',
1227
password=self.auth_token
1228
)
1229
1230
def test_twine_login_with_namespace(self):
1231
cmdline = self._setup_cmd(
1232
tool='twine', include_namespace=True
1233
)
1234
result = self.cli_runner.run(cmdline)
1235
self.assertEqual(result.rc, 255)
1236
self._assert_operations_called(package_format='pypi', result=result)
1237
self.assertIn(
1238
'Argument --namespace is not supported for twine', result.stderr
1239
)
1240
1241
def test_twine_login_with_namespace_dry_run(self):
1242
cmdline = self._setup_cmd(
1243
tool='twine', include_namespace=True, dry_run=True
1244
)
1245
result = self.cli_runner.run(cmdline)
1246
self.assertEqual(result.rc, 255)
1247
self._assert_operations_called(package_format='pypi', result=result)
1248
self.assertFalse(os.path.exists(self.test_pypi_rc_path))
1249
self.assertIn(
1250
'Argument --namespace is not supported for twine', result.stderr
1251
)
1252
1253