Path: blob/develop/tests/functional/codeartifact/test_codeartifact_login.py
2630 views
import copy1import os2import platform3import subprocess4import time5import re67from botocore.utils import parse_timestamp89from tests import CLIRunner, AWSRequest, AWSResponse10from awscli.testutils import unittest, FileCreator, mock11from awscli.compat import urlparse, StringIO, RawConfigParser12from awscli.customizations.codeartifact.login import CodeArtifactLogin131415class TestCodeArtifactLogin(unittest.TestCase):1617prefix = ['codeartifact', 'login']1819def setUp(self):20self.file_creator = FileCreator()21self.test_pypi_rc_path = self.file_creator.full_path('pypirc')22if not os.path.isdir(os.path.dirname(self.test_pypi_rc_path)):23os.makedirs(os.path.dirname(self.test_pypi_rc_path))2425self.domain = 'domain'26self.domain_owner = 'domain-owner'27self.repository = 'repository'28self.endpoint_type = 'ipv4'29self.auth_token = 'auth-token'30self.namespace = 'namespace'31self.nuget_index_url_fmt = '{endpoint}v3/index.json'32self.nuget_source_name = self.domain + '/' + self.repository33self.duration = 360034self.expiration = time.time() + self.duration35self.expiration_as_datetime = parse_timestamp(self.expiration)3637self.pypi_rc_path_patch = mock.patch(38'awscli.customizations.codeartifact.login.TwineLogin'39'.get_pypi_rc_path'40)41self.pypi_rc_path_mock = self.pypi_rc_path_patch.start()42self.pypi_rc_path_mock.return_value = self.test_pypi_rc_path4344self.test_netrc_path = self.file_creator.full_path('.netrc')45self.get_netrc_path_patch = mock.patch(46'awscli.customizations.codeartifact.login.SwiftLogin'47'.get_netrc_path'48)49self.get_netrc_mock = self.get_netrc_path_patch.start()50self.get_netrc_mock.return_value = self.test_netrc_path5152self.subprocess_patch = mock.patch('subprocess.run')53self.subprocess_mock = self.subprocess_patch.start()54self.subprocess_check_output_patch = mock.patch(55'subprocess.check_output'56)57self.subprocess_check_out_mock = \58self.subprocess_check_output_patch.start()59self.cli_runner = CLIRunner()6061def tearDown(self):62self.pypi_rc_path_patch.stop()63self.subprocess_check_output_patch.stop()64self.get_netrc_path_patch.stop()65self.subprocess_patch.stop()66self.file_creator.remove_all()6768def _setup_cmd(self, tool,69include_domain_owner=False,70dry_run=False,71include_endpoint_type=False,72include_duration_seconds=False,73include_namespace=False):74package_format = CodeArtifactLogin.TOOL_MAP[tool]['package_format']75self.endpoint = 'https://{domain}-{domainOwner}.codeartifact.aws.' \76'a2z.com/{format}/{repository}/'.format(77domain=self.domain,78domainOwner=self.domain_owner,79format=package_format,80repository=self.repository81)8283cmdline = copy.copy(self.prefix)84cmdline.extend([85'--domain', self.domain,86'--repository', self.repository,87'--tool', tool,88])8990if include_domain_owner:91cmdline.extend(['--domain-owner', self.domain_owner])9293if include_endpoint_type:94cmdline.extend(['--endpoint-type', self.endpoint_type])9596if dry_run:97cmdline.append('--dry-run')9899if include_duration_seconds:100cmdline.extend(['--duration-seconds', str(self.duration)])101102if include_namespace:103cmdline.extend(['--namespace', self.namespace])104105self.cli_runner.add_response(106AWSResponse(107service_name='codeartifact',108operation_name='GetAuthorizationToken',109parsed_response={110"authorizationToken": self.auth_token,111"expiration": self.expiration_as_datetime112}113)114)115self.cli_runner.add_response(116AWSResponse(117service_name='codeartifact',118operation_name='GetRepositoryEndpoint',119parsed_response={"repositoryEndpoint": self.endpoint}120)121)122123return cmdline124125def _get_swift_commands(self, scope=None, token=None):126commands = []127set_registry_command = [128'swift', 'package-registry', 'set', self.endpoint129]130if scope is not None:131set_registry_command.extend(['--scope', scope])132commands.append(set_registry_command)133134login_registry_command = [135'swift', 'package-registry', 'login', f'{self.endpoint}login'136]137if token is not None:138login_registry_command.extend(['--token', token])139commands.append(login_registry_command)140141return commands142143def _get_nuget_commands(self):144nuget_index_url = self.nuget_index_url_fmt.format(145endpoint=self.endpoint146)147148commands = []149commands.append(150[151'nuget', 'sources', 'add',152'-name', self.nuget_source_name,153'-source', nuget_index_url,154'-username', 'aws',155'-password', self.auth_token156]157)158return commands159160def _get_dotnet_commands(self):161nuget_index_url = self.nuget_index_url_fmt.format(162endpoint=self.endpoint163)164165commands = []166commands.append(167[168'dotnet', 'nuget', 'add', 'source', nuget_index_url,169'--name', self.nuget_source_name,170'--username', 'aws',171'--password', self.auth_token172]173)174return commands175176def _get_npm_commands(self, **kwargs):177npm_cmd = 'npm.cmd' \178if platform.system().lower() == 'windows' else 'npm'179180repo_uri = urlparse.urlsplit(self.endpoint)181always_auth_config = '//{}{}:always-auth'.format(182repo_uri.netloc, repo_uri.path183)184auth_token_config = '//{}{}:_authToken'.format(185repo_uri.netloc, repo_uri.path186)187188scope = kwargs.get('scope')189registry = '{}:registry'.format(scope) if scope else 'registry'190191commands = []192commands.append(193[npm_cmd, 'config', 'set', registry, self.endpoint]194)195commands.append(196[npm_cmd, 'config', 'set', always_auth_config, 'true']197)198commands.append(199[npm_cmd, 'config', 'set', auth_token_config, self.auth_token]200)201202return commands203204def _get_pip_commands(self):205pip_index_url_fmt = '{scheme}://aws:{auth_token}@{netloc}{path}simple/'206repo_uri = urlparse.urlsplit(self.endpoint)207pip_index_url = pip_index_url_fmt.format(208scheme=repo_uri.scheme,209auth_token=self.auth_token,210netloc=repo_uri.netloc,211path=repo_uri.path212)213214return [['pip', 'config', 'set', 'global.index-url', pip_index_url]]215216def _get_twine_commands(self):217default_pypi_rc_fmt = '''\218[distutils]219index-servers=220pypi221codeartifact222223[codeartifact]224repository: {repository_endpoint}225username: aws226password: {auth_token}'''227default_pypi_rc = default_pypi_rc_fmt.format(228repository_endpoint=self.endpoint,229auth_token=self.auth_token230)231232pypi_rc = RawConfigParser()233if os.path.exists(self.test_pypi_rc_path):234pypi_rc.read(self.test_pypi_rc_path)235index_servers = pypi_rc.get('distutils', 'index-servers')236servers = [237server.strip()238for server in index_servers.split('\n')239if server.strip() != ''240]241242if 'codeartifact' not in servers:243servers.append('codeartifact')244pypi_rc.set(245'distutils', 'index-servers', '\n' + '\n'.join(servers)246)247248if 'codeartifact' not in pypi_rc.sections():249pypi_rc.add_section('codeartifact')250251pypi_rc.set('codeartifact', 'repository', self.endpoint)252pypi_rc.set('codeartifact', 'username', 'aws')253pypi_rc.set('codeartifact', 'password', self.auth_token)254else:255pypi_rc.read_string(default_pypi_rc)256257pypi_rc_stream = StringIO()258pypi_rc.write(pypi_rc_stream)259pypi_rc_str = pypi_rc_stream.getvalue()260pypi_rc_stream.close()261262return pypi_rc_str263264def _assert_expiration_printed_to_stdout(self, stdout):265self.assertEqual(266self.expiration_as_datetime.strftime(267"%Y-%m-%d %H:%M:%S"), stdout.split("at ")[1][0:19]268)269270def _assert_operations_called(271self, package_format, result,272include_domain_owner=False, include_duration_seconds=False,273include_endpoint_type=False274):275276get_auth_token_kwargs = {277'domain': self.domain278}279get_repo_endpoint_kwargs = {280'domain': self.domain,281'repository': self.repository,282'format': package_format283}284285if include_domain_owner:286get_auth_token_kwargs['domainOwner'] = self.domain_owner287get_repo_endpoint_kwargs['domainOwner'] = self.domain_owner288289if include_endpoint_type:290get_repo_endpoint_kwargs['endpointType'] = self.endpoint_type291292if include_duration_seconds:293get_auth_token_kwargs['durationSeconds'] = self.duration294295self.assertEqual(296result.aws_requests,297[298AWSRequest(299service_name='codeartifact',300operation_name='GetAuthorizationToken',301params=get_auth_token_kwargs,302),303AWSRequest(304service_name='codeartifact',305operation_name='GetRepositoryEndpoint',306params=get_repo_endpoint_kwargs,307)308]309)310311def _assert_subprocess_execution(self, commands):312expected_calls = [313mock.call(314command,315capture_output=True,316check=True317) for command in commands318]319self.subprocess_mock.assert_has_calls(320expected_calls, any_order=True321)322323def _assert_subprocess_check_output_execution(self, commands):324expected_calls = [325mock.call(326command,327stderr=subprocess.PIPE,328) for command in commands329]330self.subprocess_check_out_mock.assert_has_calls(331expected_calls, any_order=True332)333334def _assert_dry_run_execution(self, commands, stdout):335self.subprocess_mock.assert_not_called()336for command in commands:337self.assertIn(' '.join(command), stdout)338339def _assert_pypi_rc_has_expected_content(340self, pypi_rc_str, server, repo_url=None, username=None, password=None341):342pypi_rc = RawConfigParser()343pypi_rc.read_string(pypi_rc_str)344345self.assertIn('distutils', pypi_rc.sections())346self.assertIn('index-servers', pypi_rc.options('distutils'))347index_servers = pypi_rc.get('distutils', 'index-servers')348index_servers = [349index_server.strip()350for index_server351in index_servers.split('\n')352if index_server.strip() != ''353]354self.assertIn(server, index_servers)355356if repo_url or username or password:357self.assertIn(server, pypi_rc.sections())358359if repo_url:360self.assertIn('repository', pypi_rc.options(server))361self.assertEqual(pypi_rc.get(server, 'repository'), repo_url)362363if username:364self.assertIn('username', pypi_rc.options(server))365self.assertEqual(pypi_rc.get(server, 'username'), username)366367if password:368self.assertIn('password', pypi_rc.options(server))369self.assertEqual(pypi_rc.get(server, 'password'), password)370371def _assert_netrc_has_expected_content(self):372with open(self.test_netrc_path, 'r') as f:373actual_contents = f.read()374375hostname = urlparse.urlparse(self.endpoint).hostname376expected_contents = f'machine {hostname} login token password {self.auth_token}\n'377self.assertEqual(expected_contents, actual_contents)378379@mock.patch('awscli.customizations.codeartifact.login.is_macos', True)380def test_swift_login_without_domain_owner_macos(self):381cmdline = self._setup_cmd(tool='swift')382result = self.cli_runner.run(cmdline)383self.assertEqual(result.rc, 0)384self._assert_operations_called(package_format='swift', result=result)385self._assert_expiration_printed_to_stdout(result.stdout)386self._assert_subprocess_execution(387self._get_swift_commands(token=self.auth_token)388)389self.assertFalse(os.path.exists(self.test_netrc_path))390391@mock.patch('awscli.customizations.codeartifact.login.is_macos', False)392def test_swift_login_without_domain_owner_non_macos(self):393cmdline = self._setup_cmd(tool='swift')394result = self.cli_runner.run(cmdline)395self.assertEqual(result.rc, 0)396self._assert_operations_called(package_format='swift', result=result)397self._assert_expiration_printed_to_stdout(result.stdout)398self._assert_subprocess_execution(399self._get_swift_commands()400)401self._assert_netrc_has_expected_content()402403@mock.patch('awscli.customizations.codeartifact.login.is_macos', False)404def test_swift_login_without_domain_owner_dry_run(self):405cmdline = self._setup_cmd(tool='swift', dry_run=True)406result = self.cli_runner.run(cmdline)407self.assertEqual(result.rc, 0)408self._assert_operations_called(package_format='swift', result=result)409self._assert_dry_run_execution(self._get_swift_commands(), result.stdout)410self.assertFalse(os.path.exists(self.test_netrc_path))411412@mock.patch('awscli.customizations.codeartifact.login.is_macos', True)413def test_swift_login_with_domain_owner_macos(self):414cmdline = self._setup_cmd(tool='swift', include_domain_owner=True)415result = self.cli_runner.run(cmdline)416self.assertEqual(result.rc, 0)417self._assert_operations_called(418package_format='swift', result=result,419include_domain_owner=True, include_duration_seconds=False420)421self._assert_expiration_printed_to_stdout(result.stdout)422self._assert_subprocess_execution(423self._get_swift_commands(token=self.auth_token)424)425426@mock.patch('awscli.customizations.codeartifact.login.is_macos', False)427def test_swift_login_with_domain_owner_non_macos(self):428cmdline = self._setup_cmd(tool='swift', include_domain_owner=True)429result = self.cli_runner.run(cmdline)430self.assertEqual(result.rc, 0)431self._assert_operations_called(432package_format='swift', result=result,433include_domain_owner=True, include_duration_seconds=False434)435self._assert_expiration_printed_to_stdout(result.stdout)436self._assert_subprocess_execution(437self._get_swift_commands()438)439self._assert_netrc_has_expected_content()440441@mock.patch('awscli.customizations.codeartifact.login.is_macos', True)442def test_swift_login_with_domain_owner_duration_macos(self):443cmdline = self._setup_cmd(tool='swift', include_domain_owner=True,444include_duration_seconds=True)445result = self.cli_runner.run(cmdline)446self.assertEqual(result.rc, 0)447self._assert_operations_called(448package_format='swift', result=result,449include_domain_owner=True, include_duration_seconds=True450)451self._assert_expiration_printed_to_stdout(result.stdout)452self._assert_subprocess_execution(453self._get_swift_commands(token=self.auth_token)454)455456@mock.patch('awscli.customizations.codeartifact.login.is_macos', False)457def test_swift_login_with_domain_owner_duration_non_macos(self):458cmdline = self._setup_cmd(tool='swift', include_domain_owner=True,459include_duration_seconds=True)460result = self.cli_runner.run(cmdline)461self.assertEqual(result.rc, 0)462self._assert_operations_called(463package_format='swift', result=result,464include_domain_owner=True, include_duration_seconds=True465)466self._assert_expiration_printed_to_stdout(result.stdout)467self._assert_subprocess_execution(468self._get_swift_commands()469)470self._assert_netrc_has_expected_content()471472@mock.patch('awscli.customizations.codeartifact.login.is_macos', False)473def test_swift_login_with_domain_owner_dry_run(self):474cmdline = self._setup_cmd(475tool='swift', include_domain_owner=True, dry_run=True476)477result = self.cli_runner.run(cmdline)478self.assertEqual(result.rc, 0)479self._assert_operations_called(480package_format='swift', result=result, include_domain_owner=True481)482self._assert_dry_run_execution(483self._get_swift_commands(), result.stdout484)485self.assertFalse(os.path.exists(self.test_netrc_path))486487@mock.patch('awscli.customizations.codeartifact.login.is_macos', True)488def test_swift_login_with_domain_owner_duration_dry_run(self):489cmdline = self._setup_cmd(490tool='swift', include_domain_owner=True,491include_duration_seconds=True, dry_run=True492)493result = self.cli_runner.run(cmdline)494self.assertEqual(result.rc, 0)495self._assert_operations_called(496package_format='swift', result=result, include_domain_owner=True,497include_duration_seconds=True498)499self._assert_dry_run_execution(500self._get_swift_commands(token=self.auth_token), result.stdout501)502503@mock.patch('awscli.customizations.codeartifact.login.is_macos', True)504def test_swift_login_with_namespace_macos(self):505cmdline = self._setup_cmd(506tool='swift', include_namespace=True507)508result = self.cli_runner.run(cmdline)509self.assertEqual(result.rc, 0)510self._assert_operations_called(package_format='swift', result=result)511self._assert_expiration_printed_to_stdout(result.stdout)512self._assert_subprocess_execution(513self._get_swift_commands(scope=self.namespace, token=self.auth_token)514)515516@mock.patch('awscli.customizations.codeartifact.login.is_macos', False)517def test_swift_login_with_namespace_non_macos(self):518cmdline = self._setup_cmd(519tool='swift', include_namespace=True520)521result = self.cli_runner.run(cmdline)522self.assertEqual(result.rc, 0)523self._assert_operations_called(package_format='swift', result=result)524self._assert_expiration_printed_to_stdout(result.stdout)525self._assert_subprocess_execution(526self._get_swift_commands(scope=self.namespace)527)528self._assert_netrc_has_expected_content()529530@mock.patch('awscli.customizations.codeartifact.login.is_macos', True)531def test_swift_login_with_namespace_dry_run(self):532cmdline = self._setup_cmd(533tool='swift', include_namespace=True, dry_run=True534)535result = self.cli_runner.run(cmdline)536self.assertEqual(result.rc, 0)537self._assert_operations_called(package_format='swift', result=result)538self._assert_dry_run_execution(539self._get_swift_commands(scope=self.namespace),result.stdout)540541@mock.patch('awscli.customizations.codeartifact.login.is_macos', False)542def test_swift_login_with_namespace_with_endpoint_type(self):543cmdline = self._setup_cmd(544tool='swift', include_namespace=True, include_endpoint_type=True545)546result = self.cli_runner.run(cmdline)547self.assertEqual(result.rc, 0)548self._assert_operations_called(package_format='swift', result=result, include_endpoint_type=True)549self._assert_expiration_printed_to_stdout(result.stdout)550self._assert_subprocess_execution(551self._get_swift_commands(scope=self.namespace)552)553self._assert_netrc_has_expected_content()554555@mock.patch('awscli.customizations.codeartifact.login.is_macos', True)556def test_swift_login_with_domain_owner_with_endpoint_type(self):557cmdline = self._setup_cmd(558tool='swift', include_domain_owner=True, include_endpoint_type=True559)560result = self.cli_runner.run(cmdline)561self.assertEqual(result.rc, 0)562self._assert_operations_called(package_format='swift', result=result, include_endpoint_type=True,563include_domain_owner=True)564self._assert_expiration_printed_to_stdout(result.stdout)565self._assert_subprocess_execution(566self._get_swift_commands(token=self.auth_token)567)568569def test_nuget_login_without_domain_owner_without_duration_seconds(self):570cmdline = self._setup_cmd(tool='nuget')571result = self.cli_runner.run(cmdline)572self.assertEqual(result.rc, 0)573self._assert_operations_called(package_format='nuget', result=result)574self._assert_expiration_printed_to_stdout(result.stdout)575self._assert_subprocess_execution(576self._get_nuget_commands()577)578579def test_nuget_login_with_domain_owner_without_duration_seconds(self):580cmdline = self._setup_cmd(tool='nuget', include_domain_owner=True)581result = self.cli_runner.run(cmdline)582self.assertEqual(result.rc, 0)583self._assert_operations_called(584package_format='nuget',585include_domain_owner=True,586result=result587)588self._assert_expiration_printed_to_stdout(result.stdout)589self._assert_subprocess_execution(590self._get_nuget_commands()591)592593def test_nuget_login_without_domain_owner_with_duration_seconds(self):594cmdline = self._setup_cmd(tool='nuget', include_duration_seconds=True)595result = self.cli_runner.run(cmdline)596self.assertEqual(result.rc, 0)597self._assert_operations_called(598package_format='nuget',599include_duration_seconds=True,600result=result601)602self._assert_expiration_printed_to_stdout(result.stdout)603self._assert_subprocess_execution(604self._get_nuget_commands()605)606607def test_nuget_login_with_domain_owner_duration_sections(self):608cmdline = self._setup_cmd(609tool='nuget',610include_domain_owner=True,611include_duration_seconds=True612)613result = self.cli_runner.run(cmdline)614self.assertEqual(result.rc, 0)615self._assert_operations_called(616package_format='nuget',617include_domain_owner=True,618include_duration_seconds=True,619result=result620)621self._assert_expiration_printed_to_stdout(result.stdout)622self._assert_subprocess_execution(623self._get_nuget_commands()624)625626def test_nuget_login_with_domain_owner_duration_endpoint_type(self):627cmdline = self._setup_cmd(628tool='nuget',629include_domain_owner=True,630include_duration_seconds=True,631include_endpoint_type=True632)633result = self.cli_runner.run(cmdline)634self.assertEqual(result.rc, 0)635self._assert_operations_called(636package_format='nuget',637include_domain_owner=True,638include_duration_seconds=True,639include_endpoint_type=True,640result=result641)642self._assert_expiration_printed_to_stdout(result.stdout)643self._assert_subprocess_execution(644self._get_nuget_commands()645)646647def test_nuget_login_without_domain_owner_dry_run(self):648cmdline = self._setup_cmd(tool='nuget', dry_run=True)649result = self.cli_runner.run(cmdline)650self.assertEqual(result.rc, 0)651self._assert_operations_called(package_format='nuget', result=result)652self._assert_dry_run_execution(653self._get_nuget_commands(),654result.stdout655)656657def test_nuget_login_with_domain_owner_dry_run(self):658cmdline = self._setup_cmd(659tool='nuget', include_domain_owner=True, dry_run=True660)661result = self.cli_runner.run(cmdline)662self.assertEqual(result.rc, 0)663self._assert_operations_called(664package_format='nuget',665include_domain_owner=True,666result=result667)668self._assert_dry_run_execution(669self._get_nuget_commands(),670result.stdout671)672673def test_nuget_login_with_duration_seconds_dry_run(self):674cmdline = self._setup_cmd(675tool='nuget', include_duration_seconds=True, dry_run=True676)677result = self.cli_runner.run(cmdline)678self.assertEqual(result.rc, 0)679self._assert_operations_called(680package_format='nuget',681include_duration_seconds=True,682result=result683)684self._assert_dry_run_execution(685self._get_nuget_commands(),686result.stdout687)688689def test_nuget_login_with_domain_owner_duration_seconds_dry_run(self):690cmdline = self._setup_cmd(691tool='nuget', include_domain_owner=True,692include_duration_seconds=True, dry_run=True693)694result = self.cli_runner.run(cmdline)695self.assertEqual(result.rc, 0)696self._assert_operations_called(697package_format='nuget',698include_domain_owner=True,699include_duration_seconds=True,700result=result701)702self._assert_dry_run_execution(703self._get_nuget_commands(),704result.stdout705)706707def test_nuget_login_with_domain_owner_duration_seconds_with_endpoint_type_dryrun(self):708cmdline = self._setup_cmd(709tool='nuget', include_domain_owner=True,710include_duration_seconds=True,711dry_run=True, include_endpoint_type=True712)713result = self.cli_runner.run(cmdline)714self.assertEqual(result.rc, 0)715self._assert_operations_called(716package_format='nuget',717include_domain_owner=True,718include_duration_seconds=True,719include_endpoint_type=True,720result=result721)722self._assert_dry_run_execution(723self._get_nuget_commands(),724result.stdout725)726727@mock.patch('awscli.customizations.codeartifact.login.is_windows', True)728def test_dotnet_login_without_domain_owner_without_duration_seconds(self):729cmdline = self._setup_cmd(tool='dotnet')730result = self.cli_runner.run(cmdline)731self.assertEqual(result.rc, 0)732self._assert_operations_called(package_format='nuget', result=result)733self._assert_expiration_printed_to_stdout(result.stdout)734self._assert_subprocess_execution(735self._get_dotnet_commands()736)737738@mock.patch('awscli.customizations.codeartifact.login.is_windows', True)739def test_dotnet_login_without_domain_owner_without_duration_seconds_with_endpoint_type(self):740cmdline = self._setup_cmd(tool='dotnet', include_endpoint_type=True)741result = self.cli_runner.run(cmdline)742self.assertEqual(result.rc, 0)743self._assert_operations_called(package_format='nuget', result=result, include_endpoint_type=True)744self._assert_expiration_printed_to_stdout(result.stdout)745self._assert_subprocess_execution(746self._get_dotnet_commands()747)748749@mock.patch('awscli.customizations.codeartifact.login.is_windows', True)750def test_dotnet_login_with_domain_owner_without_duration_seconds(self):751cmdline = self._setup_cmd(tool='dotnet', include_domain_owner=True)752result = self.cli_runner.run(cmdline)753self.assertEqual(result.rc, 0)754self._assert_operations_called(755package_format='nuget',756include_domain_owner=True,757result=result758)759self._assert_expiration_printed_to_stdout(result.stdout)760self._assert_subprocess_execution(761self._get_dotnet_commands()762)763764@mock.patch('awscli.customizations.codeartifact.login.is_windows', True)765def test_dotnet_login_without_domain_owner_with_duration_seconds(self):766cmdline = self._setup_cmd(tool='dotnet', include_duration_seconds=True)767result = self.cli_runner.run(cmdline)768self.assertEqual(result.rc, 0)769self._assert_operations_called(770package_format='nuget',771include_duration_seconds=True,772result=result773)774self._assert_expiration_printed_to_stdout(result.stdout)775self._assert_subprocess_execution(776self._get_dotnet_commands()777)778779@mock.patch('awscli.customizations.codeartifact.login.is_windows', True)780def test_dotnet_login_with_domain_owner_duration_sections(self):781cmdline = self._setup_cmd(782tool='dotnet',783include_domain_owner=True,784include_duration_seconds=True785)786result = self.cli_runner.run(cmdline)787self.assertEqual(result.rc, 0)788self._assert_operations_called(789package_format='nuget',790include_domain_owner=True,791include_duration_seconds=True,792result=result793)794self._assert_expiration_printed_to_stdout(result.stdout)795self._assert_subprocess_execution(796self._get_dotnet_commands()797)798799@mock.patch('awscli.customizations.codeartifact.login.is_windows', True)800def test_dotnet_login_without_domain_owner_dry_run(self):801cmdline = self._setup_cmd(tool='dotnet', dry_run=True)802result = self.cli_runner.run(cmdline)803self.assertEqual(result.rc, 0)804self._assert_operations_called(package_format='nuget', result=result)805self._assert_dry_run_execution(806self._get_dotnet_commands(),807result.stdout808)809810@mock.patch('awscli.customizations.codeartifact.login.is_windows', True)811def test_dotnet_login_with_domain_owner_dry_run(self):812cmdline = self._setup_cmd(813tool='dotnet', include_domain_owner=True, dry_run=True814)815result = self.cli_runner.run(cmdline)816self.assertEqual(result.rc, 0)817self._assert_operations_called(818package_format='nuget',819include_domain_owner=True,820result=result821)822self._assert_dry_run_execution(823self._get_dotnet_commands(),824result.stdout825)826827@mock.patch('awscli.customizations.codeartifact.login.is_windows', True)828def test_dotnet_login_with_duration_seconds_dry_run(self):829cmdline = self._setup_cmd(830tool='dotnet', include_duration_seconds=True, dry_run=True831)832result = self.cli_runner.run(cmdline)833self.assertEqual(result.rc, 0)834self._assert_operations_called(835package_format='nuget',836include_duration_seconds=True,837result=result838)839self._assert_dry_run_execution(840self._get_dotnet_commands(),841result.stdout842)843844@mock.patch('awscli.customizations.codeartifact.login.is_windows', True)845def test_dotnet_login_with_domain_owner_duration_seconds_dry_run(self):846cmdline = self._setup_cmd(847tool='dotnet', include_domain_owner=True,848include_duration_seconds=True, dry_run=True849)850result = self.cli_runner.run(cmdline)851self.assertEqual(result.rc, 0)852self._assert_operations_called(853package_format='nuget',854include_domain_owner=True,855include_duration_seconds=True,856result=result857)858self._assert_dry_run_execution(859self._get_dotnet_commands(),860result.stdout861)862863_NUGET_SOURCES_LIST_RESPONSE_WITH_EXTRA_NON_LIST_TEXT = b"""\864Welcome to dotnet 2.0!865866Registered Sources:8671. Source Name 1 [Enabled]868https://source1.com/index.json8692. ati-nugetserver [Disabled]870http://atinugetserver-env.elasticbeanstalk.com/nuget871warn : You are running the 'list source' operation with an 'HTTP' source,872'ati-nugetserver' [http://atinugetserver-env..elasticbeanstalk.com/nuget]'.873Non-HTTPS access will be removed in a future version. Consider migrating874to an 'HTTPS' source."""875876@mock.patch('awscli.customizations.codeartifact.login.is_windows', True)877def test_dotnet_login_sources_listed_with_extra_non_list_text(self):878879self.subprocess_check_output_patch.return_value = \880self._NUGET_SOURCES_LIST_RESPONSE_WITH_EXTRA_NON_LIST_TEXT881882cmdline = self._setup_cmd(tool='dotnet')883result = self.cli_runner.run(cmdline)884self.assertEqual(result.rc, 0)885self._assert_operations_called(package_format='nuget', result=result)886commands = [[887'dotnet', 'nuget', 'list', 'source', '--format', 'detailed'888]]889self._assert_subprocess_check_output_execution(commands)890891@mock.patch('awscli.customizations.codeartifact.login.is_windows', True)892def test_dotnet_login_sources_listed_with_extra_non_list_text_with_endpoint_type(self):893894self.subprocess_check_output_patch.return_value = \895self._NUGET_SOURCES_LIST_RESPONSE_WITH_EXTRA_NON_LIST_TEXT896897cmdline = self._setup_cmd(tool='dotnet', include_endpoint_type=True)898result = self.cli_runner.run(cmdline)899self.assertEqual(result.rc, 0)900self._assert_operations_called(package_format='nuget', result=result, include_endpoint_type=True)901commands = [[902'dotnet', 'nuget', 'list', 'source', '--format', 'detailed'903]]904self._assert_subprocess_check_output_execution(commands)905906def test_npm_login_without_domain_owner(self):907cmdline = self._setup_cmd(tool='npm')908result = self.cli_runner.run(cmdline)909self.assertEqual(result.rc, 0)910self._assert_operations_called(package_format='npm', result=result)911self._assert_expiration_printed_to_stdout(result.stdout)912self._assert_subprocess_execution(self._get_npm_commands())913914def test_npm_login_without_domain_owner_dry_run(self):915cmdline = self._setup_cmd(tool='npm', dry_run=True)916result = self.cli_runner.run(cmdline)917self.assertEqual(result.rc, 0)918self._assert_operations_called(package_format='npm', result=result)919self._assert_dry_run_execution(self._get_npm_commands(), result.stdout)920921def test_npm_login_always_auth_error_ignored(self):922"""Test login ignores error for always-auth.923924This test is for NPM version >= 9 where the support of 'always-auth'925has been dropped. Running the command to set config gives a non-zero926exit code. This is to make sure that login ignores that error and all927other commands executes successfully.928"""929def side_effect(command, capture_output, check):930if any('always-auth' in arg for arg in command):931raise subprocess.CalledProcessError(932returncode=1,933cmd=command934)935936return mock.DEFAULT937938self.subprocess_mock.side_effect = side_effect939cmdline = self._setup_cmd(tool='npm')940result = self.cli_runner.run(cmdline)941self.assertEqual(result.rc, 0)942self._assert_expiration_printed_to_stdout(result.stdout)943self._assert_subprocess_execution(self._get_npm_commands())944945def test_npm_login_with_domain_owner(self):946cmdline = self._setup_cmd(tool='npm', include_domain_owner=True)947result = self.cli_runner.run(cmdline)948self.assertEqual(result.rc, 0)949self._assert_operations_called(950package_format='npm', result=result,951include_domain_owner=True, include_duration_seconds=False952)953self._assert_expiration_printed_to_stdout(result.stdout)954self._assert_subprocess_execution(self._get_npm_commands())955956def test_npm_login_with_domain_owner_endpoint_type(self):957cmdline = self._setup_cmd(tool='npm', include_domain_owner=True, include_endpoint_type=True)958result = self.cli_runner.run(cmdline)959self.assertEqual(result.rc, 0)960self._assert_operations_called(961package_format='npm', result=result,962include_domain_owner=True, include_duration_seconds=False,963include_endpoint_type=True964)965self._assert_expiration_printed_to_stdout(result.stdout)966self._assert_subprocess_execution(self._get_npm_commands())967968def test_npm_login_with_domain_owner_duration(self):969cmdline = self._setup_cmd(tool='npm', include_domain_owner=True,970include_duration_seconds=True)971result = self.cli_runner.run(cmdline)972self.assertEqual(result.rc, 0)973self._assert_operations_called(974package_format='npm', result=result,975include_domain_owner=True, include_duration_seconds=True976)977self._assert_expiration_printed_to_stdout(result.stdout)978self._assert_subprocess_execution(self._get_npm_commands())979980def test_npm_login_with_domain_owner_dry_run(self):981cmdline = self._setup_cmd(982tool='npm', include_domain_owner=True, dry_run=True983)984result = self.cli_runner.run(cmdline)985self.assertEqual(result.rc, 0)986self._assert_operations_called(987package_format='npm', result=result, include_domain_owner=True988)989self._assert_dry_run_execution(self._get_npm_commands(), result.stdout)990991def test_npm_login_with_namespace(self):992cmdline = self._setup_cmd(993tool='npm', include_namespace=True994)995result = self.cli_runner.run(cmdline)996self.assertEqual(result.rc, 0)997self._assert_operations_called(package_format='npm', result=result)998self._assert_expiration_printed_to_stdout(result.stdout)999self._assert_subprocess_execution(1000self._get_npm_commands(scope='@{}'.format(self.namespace))1001)10021003def test_npm_login_with_namespace_dry_run(self):1004cmdline = self._setup_cmd(1005tool='npm', include_namespace=True, dry_run=True1006)1007result = self.cli_runner.run(cmdline)1008self.assertEqual(result.rc, 0)1009self._assert_operations_called(package_format='npm', result=result)1010self._assert_dry_run_execution(1011self._get_npm_commands(scope='@{}'.format(self.namespace)),1012result.stdout1013)10141015def test_npm_login_with_namespace_endpoint_type_dry_run(self):1016cmdline = self._setup_cmd(1017tool='npm', include_namespace=True, dry_run=True, include_endpoint_type=True1018)1019result = self.cli_runner.run(cmdline)1020self.assertEqual(result.rc, 0)1021self._assert_operations_called(package_format='npm', result=result, include_endpoint_type=True)1022self._assert_dry_run_execution(1023self._get_npm_commands(scope='@{}'.format(self.namespace)),1024result.stdout1025)10261027def test_pip_login_without_domain_owner(self):1028cmdline = self._setup_cmd(tool='pip')1029result = self.cli_runner.run(cmdline)1030self.assertEqual(result.rc, 0)1031self._assert_operations_called(package_format='pypi', result=result)1032self._assert_expiration_printed_to_stdout(result.stdout)1033self._assert_subprocess_execution(self._get_pip_commands())10341035def test_pip_login_without_domain_owner_dry_run(self):1036cmdline = self._setup_cmd(tool='pip', dry_run=True)1037result = self.cli_runner.run(cmdline)1038self.assertEqual(result.rc, 0)1039self._assert_operations_called(package_format='pypi', result=result)1040self._assert_dry_run_execution(self._get_pip_commands(), result.stdout)10411042def test_pip_login_with_domain_owner(self):1043cmdline = self._setup_cmd(tool='pip', include_domain_owner=True)1044result = self.cli_runner.run(cmdline)1045self.assertEqual(result.rc, 0)1046self._assert_operations_called(1047package_format='pypi', result=result, include_domain_owner=True1048)1049self._assert_expiration_printed_to_stdout(result.stdout)1050self._assert_subprocess_execution(self._get_pip_commands())10511052def test_pip_login_with_domain_owner_duration(self):1053cmdline = self._setup_cmd(tool='pip', include_domain_owner=True,1054include_duration_seconds=True)1055result = self.cli_runner.run(cmdline)1056self.assertEqual(result.rc, 0)1057self._assert_operations_called(1058package_format='pypi', result=result, include_domain_owner=True,1059include_duration_seconds=True1060)1061self._assert_expiration_printed_to_stdout(result.stdout)1062self._assert_subprocess_execution(self._get_pip_commands())10631064def test_pip_login_with_domain_owner_duration_endpoint_type(self):1065cmdline = self._setup_cmd(tool='pip', include_domain_owner=True,1066include_duration_seconds=True, include_endpoint_type=True)1067result = self.cli_runner.run(cmdline)1068self.assertEqual(result.rc, 0)1069self._assert_operations_called(1070package_format='pypi', result=result, include_domain_owner=True,1071include_duration_seconds=True, include_endpoint_type=True1072)1073self._assert_expiration_printed_to_stdout(result.stdout)1074self._assert_subprocess_execution(self._get_pip_commands())10751076def test_pip_login_with_domain_owner_dry_run(self):1077cmdline = self._setup_cmd(1078tool='pip', include_domain_owner=True, dry_run=True1079)1080result = self.cli_runner.run(cmdline)1081self.assertEqual(result.rc, 0)1082self._assert_operations_called(1083package_format='pypi', result=result, include_domain_owner=True1084)1085self._assert_dry_run_execution(self._get_pip_commands(), result.stdout)10861087def test_pip_login_with_namespace(self):1088cmdline = self._setup_cmd(tool='pip', include_namespace=True)1089result = self.cli_runner.run(cmdline)1090self.assertEqual(result.rc, 255)1091self._assert_operations_called(package_format='pypi', result=result)1092self.assertIn(1093'Argument --namespace is not supported for pip', result.stderr1094)10951096def test_pip_login_with_namespace_dry_run(self):1097cmdline = self._setup_cmd(1098tool='pip', include_namespace=True, dry_run=True)1099result = self.cli_runner.run(cmdline)1100self.assertEqual(result.rc, 255)1101self._assert_operations_called(package_format='pypi', result=result)1102self.assertIn(1103'Argument --namespace is not supported for pip', result.stderr1104)11051106def test_pip_login_command_failed_auth_token_redacted(self):1107def side_effect(command, capture_output, check):1108raise subprocess.CalledProcessError(1109returncode=1,1110cmd=command1111)11121113self.subprocess_mock.side_effect = side_effect1114cmdline = self._setup_cmd(tool='pip')1115result = self.cli_runner.run(cmdline)1116self.assertEqual(result.rc, 255)1117self.assertIn(1118"Command '['pip', 'config', 'set', 'global.index-url',"1119" 'https://aws:******@domain-domain-owner.codeartifact.aws.a2z.com/pypi/repository/simple/']'"1120" returned non-zero exit status 1.",1121result.stderr1122)11231124def test_twine_login_without_domain_owner(self):1125cmdline = self._setup_cmd(tool='twine')1126result = self.cli_runner.run(cmdline)1127self.assertEqual(result.rc, 0)1128self._assert_operations_called(package_format='pypi', result=result)1129self._assert_expiration_printed_to_stdout(result.stdout)1130with open(self.test_pypi_rc_path) as f:1131test_pypi_rc_str = f.read()11321133self._assert_pypi_rc_has_expected_content(1134pypi_rc_str=test_pypi_rc_str,1135server='codeartifact',1136repo_url=self.endpoint,1137username='aws',1138password=self.auth_token1139)11401141def test_twine_login_without_domain_owner_dry_run(self):1142cmdline = self._setup_cmd(tool='twine', dry_run=True)1143result = self.cli_runner.run(cmdline)1144self.assertEqual(result.rc, 0)1145self._assert_operations_called(package_format='pypi', result=result)1146self.assertFalse(os.path.exists(self.test_pypi_rc_path))1147self._assert_pypi_rc_has_expected_content(1148pypi_rc_str=self._get_twine_commands(),1149server='codeartifact',1150repo_url=self.endpoint,1151username='aws',1152password=self.auth_token1153)11541155def test_twine_login_without_domain_owner_dry_run_endpoint_type(self):1156cmdline = self._setup_cmd(tool='twine', dry_run=True, include_endpoint_type=True)1157result = self.cli_runner.run(cmdline)1158self.assertEqual(result.rc, 0)1159self._assert_operations_called(package_format='pypi', result=result, include_endpoint_type=True)1160self.assertFalse(os.path.exists(self.test_pypi_rc_path))1161self._assert_pypi_rc_has_expected_content(1162pypi_rc_str=self._get_twine_commands(),1163server='codeartifact',1164repo_url=self.endpoint,1165username='aws',1166password=self.auth_token1167)11681169def test_twine_login_with_domain_owner(self):1170cmdline = self._setup_cmd(tool='twine', include_domain_owner=True)1171result = self.cli_runner.run(cmdline)1172self.assertEqual(result.rc, 0)1173self._assert_operations_called(1174package_format='pypi', result=result, include_domain_owner=True1175)1176self._assert_expiration_printed_to_stdout(result.stdout)11771178with open(self.test_pypi_rc_path) as f:1179test_pypi_rc_str = f.read()11801181self._assert_pypi_rc_has_expected_content(1182pypi_rc_str=test_pypi_rc_str,1183server='codeartifact',1184repo_url=self.endpoint,1185username='aws',1186password=self.auth_token1187)11881189def test_twine_login_with_domain_owner_duration(self):1190cmdline = self._setup_cmd(tool='twine', include_domain_owner=True,1191include_duration_seconds=True)1192result = self.cli_runner.run(cmdline)1193self.assertEqual(result.rc, 0)1194self._assert_operations_called(1195package_format='pypi', result=result, include_domain_owner=True,1196include_duration_seconds=True1197)1198self._assert_expiration_printed_to_stdout(result.stdout)11991200with open(self.test_pypi_rc_path) as f:1201test_pypi_rc_str = f.read()12021203self._assert_pypi_rc_has_expected_content(1204pypi_rc_str=test_pypi_rc_str,1205server='codeartifact',1206repo_url=self.endpoint,1207username='aws',1208password=self.auth_token1209)12101211def test_twine_login_with_domain_owner_dry_run(self):1212cmdline = self._setup_cmd(1213tool='twine', include_domain_owner=True, dry_run=True1214)1215result = self.cli_runner.run(cmdline)1216self.assertEqual(result.rc, 0)1217self._assert_operations_called(1218package_format='pypi', result=result, include_domain_owner=True1219)1220self.assertFalse(os.path.exists(self.test_pypi_rc_path))1221self._assert_pypi_rc_has_expected_content(1222pypi_rc_str=self._get_twine_commands(),1223server='codeartifact',1224repo_url=self.endpoint,1225username='aws',1226password=self.auth_token1227)12281229def test_twine_login_with_namespace(self):1230cmdline = self._setup_cmd(1231tool='twine', include_namespace=True1232)1233result = self.cli_runner.run(cmdline)1234self.assertEqual(result.rc, 255)1235self._assert_operations_called(package_format='pypi', result=result)1236self.assertIn(1237'Argument --namespace is not supported for twine', result.stderr1238)12391240def test_twine_login_with_namespace_dry_run(self):1241cmdline = self._setup_cmd(1242tool='twine', include_namespace=True, dry_run=True1243)1244result = self.cli_runner.run(cmdline)1245self.assertEqual(result.rc, 255)1246self._assert_operations_called(package_format='pypi', result=result)1247self.assertFalse(os.path.exists(self.test_pypi_rc_path))1248self.assertIn(1249'Argument --namespace is not supported for twine', result.stderr1250)125112521253