class TestStreamingOutput(BaseAWSCommandParamsTest): def setUp(self): super(TestStreamingOutput, self).setUp() self.files = FileCreator() def tearDown(self): super(TestStreamingOutput, self).tearDown() self.files.remove_all() def test_get_media_streaming_output(self): cmdline = ( 'kinesis-video-media get-media --stream-name test-stream ' '--start-selector StartSelectorType=EARLIEST %s' ) self.parsed_response = { 'ContentType': 'video/webm', 'Payload': six.BytesIO(b'testbody') } outpath = self.files.full_path('outfile') params = { 'StartSelector': {'StartSelectorType': 'EARLIEST'}, 'StreamName': 'test-stream' } self.assert_params_for_cmd(cmdline % outpath, params) with open(outpath, 'rb') as outfile: self.assertEqual(outfile.read(), b'testbody')
class BaseSSOTest(BaseAWSCommandParamsTest): def setUp(self): super(BaseSSOTest, self).setUp() self.files = FileCreator() self.start_url = 'https://mysigin.com' self.sso_region = 'us-west-2' self.account = '012345678912' self.role_name = 'SSORole' self.config_file = self.files.full_path('config') self.environ['AWS_CONFIG_FILE'] = self.config_file self.set_config_file_content() self.access_token = 'foo.token.string' def tearDown(self): super(BaseSSOTest, self).tearDown() self.files.remove_all() def set_config_file_content(self, content=None): if content is None: content = ('[default]\n' 'sso_start_url=%s\n' 'sso_region=%s\n' 'sso_role_name=%s\n' 'sso_account_id=%s\n' % (self.start_url, self.sso_region, self.role_name, self.account)) self.files.create_file(self.config_file, content) # We need to recreate the driver (which includes its session) in order # for the config changes to be pulled in by the session. self.driver = create_clidriver()
class TestStreamingOutput(BaseAWSCommandParamsTest): def setUp(self): super(TestStreamingOutput, self).setUp() self.files = FileCreator() def tearDown(self): super(TestStreamingOutput, self).tearDown() self.files.remove_all() def test_get_media_streaming_output(self): cmdline = ('kinesis-video-media get-media --stream-name test-stream ' '--start-selector StartSelectorType=EARLIEST %s') self.parsed_response = { 'ContentType': 'video/webm', 'Payload': six.BytesIO(b'testbody') } outpath = self.files.full_path('outfile') params = { 'StartSelector': { 'StartSelectorType': 'EARLIEST' }, 'StreamName': 'test-stream' } self.assert_params_for_cmd(cmdline % outpath, params) with open(outpath, 'rb') as outfile: self.assertEqual(outfile.read(), b'testbody')
class TestZipDirectory(unittest.TestCase): def setUp(self): self.file_creator = FileCreator() self.zip_file = self.file_creator.create_file('build.zip', '') self._dir_root = 'mybuild' def tearDown(self): self.file_creator.remove_all() @property def dir_root(self): return self.file_creator.full_path(self._dir_root) def add_to_directory(self, filename): self.file_creator.create_file( os.path.join(self._dir_root, filename), 'Some contents') def assert_contents_of_zip_file(self, filenames): zip_file_object = zipfile.ZipFile( self.zip_file, 'r', zipfile.ZIP_DEFLATED) with contextlib.closing(zip_file_object) as zf: ref_zipfiles = [] zipfile_contents = zf.namelist() for ref_zipfile in zipfile_contents: if os.sep == '\\': # Internally namelist() represent directories with # forward slashes so we need to account for that if # the separator is a backslash depending on the operating # system. ref_zipfile = ref_zipfile.replace('/', '\\') ref_zipfiles.append(ref_zipfile) self.assertEqual(sorted(ref_zipfiles), filenames) def test_single_file(self): self.add_to_directory('foo') zip_directory(self.zip_file, self.dir_root) self.assert_contents_of_zip_file(['foo']) def test_multiple_files(self): self.add_to_directory('foo') self.add_to_directory('bar') zip_directory(self.zip_file, self.dir_root) self.assert_contents_of_zip_file(['bar', 'foo']) def test_nested_file(self): filename = os.path.join('mydir', 'foo') self.add_to_directory(filename) zip_directory(self.zip_file, self.dir_root) self.assert_contents_of_zip_file([filename])
class TestZipDirectory(unittest.TestCase): def setUp(self): self.file_creator = FileCreator() self.zip_file = self.file_creator.create_file('build.zip', '') self._dir_root = 'mybuild' def tearDown(self): self.file_creator.remove_all() @property def dir_root(self): return self.file_creator.full_path(self._dir_root) def add_to_directory(self, filename): self.file_creator.create_file( os.path.join(self._dir_root, filename), 'Some contents') def assert_contents_of_zip_file(self, filenames): zip_file_object = zipfile.ZipFile( self.zip_file, 'r', zipfile.ZIP_DEFLATED) with contextlib.closing(zip_file_object) as zf: ref_zipfiles = [] zipfile_contents = zf.namelist() for ref_zipfile in zipfile_contents: if os.sep == '\\': # Internally namelist() represent directories with # forward slashes so we need to account for that if # the separator is a backslash depending on the operating # system. ref_zipfile = ref_zipfile.replace('/', '\\') ref_zipfiles.append(ref_zipfile) self.assertEqual(sorted(ref_zipfiles), filenames) def test_single_file(self): self.add_to_directory('foo') zip_directory(self.zip_file, self.dir_root) self.assert_contents_of_zip_file(['foo']) def test_multiple_files(self): self.add_to_directory('foo') self.add_to_directory('bar') zip_directory(self.zip_file, self.dir_root) self.assert_contents_of_zip_file(['bar', 'foo']) def test_nested_file(self): filename = os.path.join('mydir', 'foo') self.add_to_directory(filename) zip_directory(self.zip_file, self.dir_root) self.assert_contents_of_zip_file([filename])
class TestTwineLogin(unittest.TestCase): DEFAULT_PYPI_RC_FMT = TwineLogin.DEFAULT_PYPI_RC_FMT def setUp(self): self.file_creator = FileCreator() self.domain = 'domain' self.domain_owner = 'domain-owner' self.package_format = 'pip' self.repository = 'repository' self.auth_token = 'auth-token' self.expiration = (datetime.now(tzlocal()) + relativedelta(years=1) + relativedelta(months=9)).replace(microsecond=0) self.endpoint = 'https://{domain}-{domainOwner}.codeartifact.aws.' \ 'a2z.com/{format}/{repository}/'.format( domain=self.domain, domainOwner=self.domain_owner, format=self.package_format, repository=self.repository ) self.default_pypi_rc = self.DEFAULT_PYPI_RC_FMT.format( repository_endpoint=self.endpoint, auth_token=self.auth_token) self.subprocess_utils = mock.Mock() self.test_pypi_rc_path = self.file_creator.full_path('pypirc') if not os.path.isdir(os.path.dirname(self.test_pypi_rc_path)): os.makedirs(os.path.dirname(self.test_pypi_rc_path)) self.test_subject = TwineLogin(self.auth_token, self.expiration, self.endpoint, self.subprocess_utils, self.test_pypi_rc_path) def tearDown(self): self.file_creator.remove_all() def _assert_pypi_rc_has_expected_content(self, pypi_rc_str, server, repo_url=None, username=None, password=None): pypi_rc = RawConfigParser() pypi_rc.readfp(StringIO(pypi_rc_str)) self.assertIn('distutils', pypi_rc.sections()) self.assertIn('index-servers', pypi_rc.options('distutils')) index_servers = pypi_rc.get('distutils', 'index-servers') index_servers = [ index_server.strip() for index_server in index_servers.split('\n') if index_server.strip() != '' ] self.assertIn(server, index_servers) if repo_url or username or password: self.assertIn(server, pypi_rc.sections()) if repo_url: self.assertIn('repository', pypi_rc.options(server)) self.assertEqual(pypi_rc.get(server, 'repository'), repo_url) if username: self.assertIn('username', pypi_rc.options(server)) self.assertEqual(pypi_rc.get(server, 'username'), username) if password: self.assertIn('password', pypi_rc.options(server)) self.assertEqual(pypi_rc.get(server, 'password'), password) def test_get_pypi_rc_path(self): self.assertEqual(TwineLogin.get_pypi_rc_path(), os.path.join(os.path.expanduser("~"), ".pypirc")) def test_login_pypi_rc_not_found_defaults_set(self): self.test_subject.login() with open(self.test_pypi_rc_path) as f: test_pypi_rc_str = f.read() self._assert_pypi_rc_has_expected_content(pypi_rc_str=test_pypi_rc_str, server='codeartifact', repo_url=self.endpoint, username='******', password=self.auth_token) def test_login_dry_run(self): self.test_subject.login(dry_run=True) self.subprocess_utils.check_call.assert_not_called() self.assertFalse(os.path.exists(self.test_pypi_rc_path)) def test_login_existing_pypi_rc_not_clobbered(self): existing_pypi_rc = '''\ [distutils] index-servers= pypi test [pypi] repository: http://www.python.org/pypi/ username: monty password: JgCXIr5xGG [test] repository: http://example.com/test/ username: testusername password: testpassword ''' with open(self.test_pypi_rc_path, 'w+') as f: f.write(existing_pypi_rc) self.test_subject.login() with open(self.test_pypi_rc_path) as f: test_pypi_rc_str = f.read() self._assert_pypi_rc_has_expected_content(pypi_rc_str=test_pypi_rc_str, server='codeartifact', repo_url=self.endpoint, username='******', password=self.auth_token) self._assert_pypi_rc_has_expected_content( pypi_rc_str=test_pypi_rc_str, server='pypi', repo_url='http://www.python.org/pypi/', username='******', password='******') self._assert_pypi_rc_has_expected_content( pypi_rc_str=test_pypi_rc_str, server='test', repo_url='http://example.com/test/', username='******', password='******') def test_login_existing_pypi_rc_with_codeartifact_not_clobbered(self): existing_pypi_rc = '''\ [distutils] index-servers= pypi codeartifact [pypi] repository: http://www.python.org/pypi/ username: monty password: JgCXIr5xGG [codeartifact] repository: https://test-testOwner.codeartifact.aws.a2z.com/pypi/testRepo/ username: aws password: expired_token ''' with open(self.test_pypi_rc_path, 'w+') as f: f.write(existing_pypi_rc) self.test_subject.login() with open(self.test_pypi_rc_path) as f: test_pypi_rc_str = f.read() self._assert_pypi_rc_has_expected_content(pypi_rc_str=test_pypi_rc_str, server='codeartifact', repo_url=self.endpoint, username='******', password=self.auth_token) self._assert_pypi_rc_has_expected_content( pypi_rc_str=test_pypi_rc_str, server='pypi', repo_url='http://www.python.org/pypi/', username='******', password='******') def test_login_existing_invalid_pypi_rc_error(self): # This is an invalid pypirc as the list of servers are expected under # an 'index-servers' option instead of 'servers'. existing_pypi_rc = '''\ [distutils] servers= pypi [pypi] repository: http://www.python.org/pypi/ username: monty password: JgCXIr5xGG ''' with open(self.test_pypi_rc_path, 'w+') as f: f.write(existing_pypi_rc) with open(self.test_pypi_rc_path) as f: original_content = f.read() with self.assertRaises(Exception): self.test_subject.login() # We should just leave the pypirc untouched when it's invalid. with open(self.test_pypi_rc_path) as f: self.assertEqual(f.read(), original_content)
class TestOutFileQueryArguments(BaseAWSCommandParamsTest): def setUp(self): self.files = FileCreator() super(TestOutFileQueryArguments, self).setUp() def tearDown(self): self.files.remove_all() super(TestOutFileQueryArguments, self).tearDown() def test_saves_cert_to_file_for_create_certificate_from_csr(self): self.parsed_response = { 'certificatePem': 'cert...', 'ResponseMetadata': { 'HTTPStatusCode': 200, 'RequestId': 'request-id' } } outfile = self.files.full_path('cert.pem') cmdline = 'iot create-certificate-from-csr' cmdline += ' --certificate-signing-request "abc"' cmdline += ' --certificate-pem-outfile ' + outfile self.run_cmd(cmdline, 0) self.assertTrue(os.path.exists(outfile)) with open(outfile) as fp: self.assertEquals('cert...', fp.read()) def test_saves_files_for_create_keys_and_cert(self): self.parsed_response = { 'certificatePem': 'cert...', 'keyPair': { 'PublicKey': 'public', 'PrivateKey': 'private' }, 'ResponseMetadata': { 'HTTPStatusCode': 200, 'RequestId': 'request-id' } } out_cert = self.files.full_path('cert.pem') out_pub = self.files.full_path('key_rsa.pub') out_priv = self.files.full_path('key_rsa') cmdline = 'iot create-keys-and-certificate' cmdline += ' --certificate-pem-outfile ' + out_cert cmdline += ' --public-key-outfile ' + out_pub cmdline += ' --private-key-outfile ' + out_priv self.run_cmd(cmdline, 0) self.assertTrue(os.path.exists(out_cert)) self.assertTrue(os.path.exists(out_pub)) self.assertTrue(os.path.exists(out_priv)) with open(out_cert) as fp: self.assertEquals('cert...', fp.read()) with open(out_pub) as fp: self.assertEquals('public', fp.read()) with open(out_priv) as fp: self.assertEquals('private', fp.read()) def test_bad_response(self): outfile = self.files.full_path('cert.pem') self.parsed_response = { 'Error': {'Code': 'v1', 'Message': 'v2', 'Type': 'v3'}, 'ResponseMetadata': { 'HTTPStatusCode': 403, 'RequestId': 'request-id' } } self.http_response.status_code = 403 cmdline = 'iot create-certificate-from-csr' cmdline += ' --certificate-signing-request "abc"' cmdline += ' --certificate-pem-outfile ' + outfile # The error message should be in the stderr. self.assert_params_for_cmd( cmdline, stderr_contains=self.parsed_response['Error']['Message'], expected_rc=255) def test_ensures_file_is_writable_before_sending(self): outfile = os.sep.join(['', 'does', 'not', 'exist_', 'file.txt']) self.parsed_response = {} cmdline = 'iot create-certificate-from-csr' cmdline += ' --certificate-signing-request "abc"' cmdline += ' --certificate-pem-outfile ' + outfile self.assert_params_for_cmd( cmdline, stderr_contains='Unable to write to file: ', expected_rc=255)
class TestConfigureCommand(BaseAWSCommandParamsTest): def setUp(self): super().setUp() self.files = FileCreator() self.config_filename = self.files.full_path("configure") self.environ["AWS_CONFIG_FILE"] = self.config_filename self.environ["AWS_SHARED_CREDENTIALS_FILE"] = "asdf-does-not-exist" def tearDown(self): super().tearDown() self.files.remove_all() def set_config_file_contents(self, contents): self.files.create_file(self.config_filename, contents) # Reset the session to pick up the new config file. self.driver = create_clidriver() def get_config_file_contents(self): with open(self.config_filename, "r") as f: return f.read() def test_list_command(self): self.set_config_file_contents( "\n" "[default]\n" "aws_access_key_id=12345\n" "aws_secret_access_key=12345\n" "region=us-west-2\n" ) self.environ.pop("AWS_DEFAULT_REGION", None) self.environ.pop("AWS_ACCESS_KEY_ID", None) self.environ.pop("AWS_SECRET_ACCESS_KEY", None) stdout, _, _ = self.run_cmd("configure list") self.assertRegex(stdout, r"access_key.+config-file") self.assertRegex(stdout, r"secret_key.+config-file") self.assertRegex(stdout, r"region\s+us-west-2\s+config-file") def test_get_command(self): self.driver = create_clidriver() self.set_config_file_contents( "\n" "[default]\n" "aws_access_key_id=access_key\n" "aws_secret_access_key=secret_key\n" "region=us-west-2\n" ) stdout, _, _ = self.run_cmd("configure get aws_access_key_id") self.assertEqual(stdout.strip(), "access_key") def test_get_command_with_profile_set(self): self.set_config_file_contents( "\n" "[default]\n" "aws_access_key_id=default_access_key\n" "\n" "[profile testing]\n" "aws_access_key_id=testing_access_key\n" ) stdout, _, _ = self.run_cmd( "configure get aws_access_key_id --profile testing", ) self.assertEqual(stdout.strip(), "testing_access_key") def test_get_with_fq_name(self): # test get configs with fully qualified name. self.set_config_file_contents( "\n" "[default]\n" "aws_access_key_id=default_access_key\n" "\n" "[profile testing]\n" "aws_access_key_id=testing_access_key\n" ) stdout, _, _ = self.run_cmd( "configure get default.aws_access_key_id --profile testing", ) self.assertEqual(stdout.strip(), "default_access_key") def test_get_with_fq_profile_name(self): self.set_config_file_contents( "\n" "[default]\n" "aws_access_key_id=default_access_key\n" "\n" "[profile testing]\n" "aws_access_key_id=testing_access_key\n" ) stdout, _, _ = self.run_cmd( "configure get profile.testing.aws_access_key_id " "--profile default", ) self.assertEqual(stdout.strip(), "testing_access_key") def test_get_fq_with_quoted_profile_name(self): self.set_config_file_contents( "\n" "[default]\n" "aws_access_key_id=default_access_key\n" "\n" '[profile "testing"]\n' "aws_access_key_id=testing_access_key\n" ) stdout, _, _ = self.run_cmd( "configure get profile.testing.aws_access_key_id " "--profile default", ) self.assertEqual(stdout.strip(), "testing_access_key") def test_get_fq_for_non_profile_configs(self): self.set_config_file_contents( "\n" "[default]\n" "aws_access_key_id=default_access_key\n" "\n" "[profile testing]\n" "aws_access_key_id=testing_access_key\n" "[preview]\n" "emr=true" ) stdout, _, _ = self.run_cmd( "configure get preview.emr --profile default", ) self.assertEqual(stdout.strip(), "true") def test_set_with_config_file_no_exist(self): self.run_cmd("configure set region us-west-1") self.assertEqual( "[default]\n" "region = us-west-1\n", self.get_config_file_contents() ) def test_set_with_a_url(self): self.run_cmd( "configure set endpoint http://www.example.com", ) self.assertEqual( "[default]\n" "endpoint = http://www.example.com\n", self.get_config_file_contents(), ) def test_set_with_empty_config_file(self): with open(self.config_filename, "w"): pass self.run_cmd("configure set region us-west-1") self.assertEqual( "[default]\n" "region = us-west-1\n", self.get_config_file_contents() ) def test_set_with_updating_value(self): self.set_config_file_contents( "[default]\n" "region = us-west-2\n" ) self.run_cmd("configure set region us-west-1") self.assertEqual( "[default]\n" "region = us-west-1\n", self.get_config_file_contents() ) def test_set_with_profile_spaces(self): self.run_cmd( [ "configure", "set", "region", "us-west-1", "--profile", "test with spaces", ] ) self.assertEqual( "[profile 'test with spaces']\n" "region = us-west-1\n", self.get_config_file_contents(), ) def test_set_with_profile_unknown_nested_key(self): self.run_cmd( [ "configure", "set", "un.known", "us-west-1", "--profile", "space test", ] ) self.assertEqual( "[profile 'space test']\n" "un =\n" " known = us-west-1\n", self.get_config_file_contents(), ) def test_set_with_profile_spaces_scoped(self): self.run_cmd( [ "configure", "set", "profile.test with spaces.region", "us-west-1", ] ) self.assertEqual( "[profile 'test with spaces']\n" "region = us-west-1\n", self.get_config_file_contents(), ) def test_set_with_profile(self): self.run_cmd( "configure set region us-west-1 --profile testing", ) self.assertEqual( "[profile testing]\n" "region = us-west-1\n", self.get_config_file_contents(), ) def test_set_with_fq_single_dot(self): self.run_cmd("configure set preview.cloudsearch true") self.assertEqual( "[preview]\n" "cloudsearch = true\n", self.get_config_file_contents() ) def test_set_with_fq_double_dot(self): self.run_cmd( "configure set profile.testing.region us-west-2", ) self.assertEqual( "[profile testing]\n" "region = us-west-2\n", self.get_config_file_contents(), ) def test_set_with_commented_out_field(self): self.set_config_file_contents( "#[preview]\n" ";cloudsearch = true\n" ) self.run_cmd("configure set preview.cloudsearch true") self.assertEqual( "#[preview]\n" ";cloudsearch = true\n" "[preview]\n" "cloudsearch = true\n", self.get_config_file_contents(), ) def test_set_with_triple_nesting(self): self.run_cmd( "configure set default.s3.signature_version s3v4", ) self.assertEqual( "[default]\n" "s3 =\n" " signature_version = s3v4\n", self.get_config_file_contents(), ) def test_set_with_existing_config(self): self.set_config_file_contents( "[default]\n" "region = us-west-2\n" "ec2 =\n" " signature_version = v4\n" ) self.run_cmd( "configure set default.s3.signature_version s3v4", ) self.assertEqual( "[default]\n" "region = us-west-2\n" "ec2 =\n" " signature_version = v4\n" "s3 =\n" " signature_version = s3v4\n", self.get_config_file_contents(), ) def test_set_with_new_profile(self): self.set_config_file_contents( "[default]\n" "s3 =\n" " signature_version = s3v4\n" ) self.run_cmd( "configure set profile.dev.s3.signature_version s3v4", ) self.assertEqual( "[default]\n" "s3 =\n" " signature_version = s3v4\n" "[profile dev]\n" "s3 =\n" " signature_version = s3v4\n", self.get_config_file_contents(), ) def test_override_existing_value(self): self.set_config_file_contents( "[default]\n" "s3 =\n" " signature_version = v4\n" ) self.run_cmd( "configure set default.s3.signature_version NEWVALUE", ) self.assertEqual( "[default]\n" "s3 =\n" " signature_version = NEWVALUE\n", self.get_config_file_contents(), ) def test_get_nested_attribute(self): self.set_config_file_contents( "[default]\n" "s3 =\n" " signature_version = v4\n" ) stdout, _, _ = self.run_cmd( "configure get default.s3.signature_version" ) self.assertEqual(stdout.strip(), "v4") stdout, _, _ = self.run_cmd( "configure get default.bad.doesnotexist", expected_rc=1 ) self.assertEqual(stdout, "") def test_can_handle_empty_section(self): self.set_config_file_contents("[default]\n") self.run_cmd( "configure set preview.cloudfront true", ) self.run_cmd( "configure set region us-west-2", ) self.assertEqual( "[default]\n" "region = us-west-2\n" "[preview]\n" "cloudfront = true\n", self.get_config_file_contents(), )
class TestOutFileQueryArguments(BaseAWSCommandParamsTest): def setUp(self): self.files = FileCreator() super(TestOutFileQueryArguments, self).setUp() def tearDown(self): self.files.remove_all() super(TestOutFileQueryArguments, self).tearDown() def test_saves_cert_to_file_for_create_certificate_from_csr(self): self.parsed_response = { 'certificatePem': 'cert...', 'ResponseMetadata': { 'HTTPStatusCode': 200, 'RequestId': 'request-id' } } outfile = self.files.full_path('cert.pem') cmdline = 'iot create-certificate-from-csr' cmdline += ' --certificate-signing-request "abc"' cmdline += ' --certificate-pem-outfile ' + outfile self.run_cmd(cmdline, 0) self.assertTrue(os.path.exists(outfile)) with open(outfile) as fp: self.assertEqual('cert...', fp.read()) def test_saves_files_for_create_keys_and_cert(self): self.parsed_response = { 'certificatePem': 'cert...', 'keyPair': { 'PublicKey': 'public', 'PrivateKey': 'private' }, 'ResponseMetadata': { 'HTTPStatusCode': 200, 'RequestId': 'request-id' } } out_cert = self.files.full_path('cert.pem') out_pub = self.files.full_path('key_rsa.pub') out_priv = self.files.full_path('key_rsa') cmdline = 'iot create-keys-and-certificate' cmdline += ' --certificate-pem-outfile ' + out_cert cmdline += ' --public-key-outfile ' + out_pub cmdline += ' --private-key-outfile ' + out_priv self.run_cmd(cmdline, 0) self.assertTrue(os.path.exists(out_cert)) self.assertTrue(os.path.exists(out_pub)) self.assertTrue(os.path.exists(out_priv)) with open(out_cert) as fp: self.assertEqual('cert...', fp.read()) with open(out_pub) as fp: self.assertEqual('public', fp.read()) with open(out_priv) as fp: self.assertEqual('private', fp.read()) def test_bad_response(self): outfile = self.files.full_path('cert.pem') self.parsed_response = { 'Error': { 'Code': 'v1', 'Message': 'v2', 'Type': 'v3' }, 'ResponseMetadata': { 'HTTPStatusCode': 403, 'RequestId': 'request-id' } } self.http_response.status_code = 403 cmdline = 'iot create-certificate-from-csr' cmdline += ' --certificate-signing-request "abc"' cmdline += ' --certificate-pem-outfile ' + outfile # The error message should be in the stderr. self.assert_params_for_cmd( cmdline, stderr_contains=self.parsed_response['Error']['Message'], expected_rc=255) def test_ensures_file_is_writable_before_sending(self): outfile = os.sep.join(['', 'does', 'not', 'exist_', 'file.txt']) self.parsed_response = {} cmdline = 'iot create-certificate-from-csr' cmdline += ' --certificate-signing-request "abc"' cmdline += ' --certificate-pem-outfile ' + outfile self.assert_params_for_cmd(cmdline, stderr_contains='Unable to write to file: ', expected_rc=255)
class TestCodeArtifactLogin(unittest.TestCase): prefix = ['codeartifact', 'login'] def setUp(self): self.file_creator = FileCreator() self.test_pypi_rc_path = self.file_creator.full_path('pypirc') if not os.path.isdir(os.path.dirname(self.test_pypi_rc_path)): os.makedirs(os.path.dirname(self.test_pypi_rc_path)) self.domain = 'domain' self.domain_owner = 'domain-owner' self.repository = 'repository' self.auth_token = 'auth-token' self.namespace = 'namespace' self.nuget_index_url_fmt = '{endpoint}v3/index.json' self.nuget_source_name = self.domain + '/' + self.repository self.duration = 3600 self.expiration = time.time() + self.duration self.expiration_as_datetime = parse_timestamp(self.expiration) self.pypi_rc_path_patch = mock.patch( 'awscli.customizations.codeartifact.login.TwineLogin' '.get_pypi_rc_path') self.pypi_rc_path_mock = self.pypi_rc_path_patch.start() self.pypi_rc_path_mock.return_value = self.test_pypi_rc_path self.subprocess_patch = mock.patch('subprocess.check_call') self.subprocess_mock = self.subprocess_patch.start() self.subprocess_check_output_patch = mock.patch( 'subprocess.check_output') self.subprocess_check_out_mock = \ self.subprocess_check_output_patch.start() self.cli_runner = CLIRunner() def tearDown(self): self.pypi_rc_path_patch.stop() self.subprocess_patch.stop() self.file_creator.remove_all() def _setup_cmd(self, tool, include_domain_owner=False, dry_run=False, include_duration_seconds=False, include_namespace=False): package_format = CodeArtifactLogin.TOOL_MAP[tool]['package_format'] self.endpoint = 'https://{domain}-{domainOwner}.codeartifact.aws.' \ 'a2z.com/{format}/{repository}/'.format( domain=self.domain, domainOwner=self.domain_owner, format=package_format, repository=self.repository ) cmdline = copy.copy(self.prefix) cmdline.extend([ '--domain', self.domain, '--repository', self.repository, '--tool', tool, ]) if include_domain_owner: cmdline.extend(['--domain-owner', self.domain_owner]) if dry_run: cmdline.append('--dry-run') if include_duration_seconds: cmdline.extend(['--duration-seconds', str(self.duration)]) if include_namespace: cmdline.extend(['--namespace', self.namespace]) self.cli_runner.add_response( AWSResponse(service_name='codeartifact', operation_name='GetAuthorizationToken', parsed_response={ "authorizationToken": self.auth_token, "expiration": self.expiration_as_datetime })) self.cli_runner.add_response( AWSResponse(service_name='codeartifact', operation_name='GetRepositoryEndpoint', parsed_response={"repositoryEndpoint": self.endpoint})) return cmdline def _get_nuget_commands(self): nuget_index_url = self.nuget_index_url_fmt.format( endpoint=self.endpoint) commands = [] commands.append([ 'nuget', 'sources', 'add', '-name', self.nuget_source_name, '-source', nuget_index_url, '-username', 'aws', '-password', self.auth_token ]) return commands def _get_dotnet_commands(self): nuget_index_url = self.nuget_index_url_fmt.format( endpoint=self.endpoint) commands = [] commands.append([ 'dotnet', 'nuget', 'add', 'source', nuget_index_url, '--name', self.nuget_source_name, '--username', 'aws', '--password', self.auth_token ]) return commands def _get_npm_commands(self, **kwargs): npm_cmd = 'npm.cmd' \ if platform.system().lower() == 'windows' else 'npm' repo_uri = urlparse.urlsplit(self.endpoint) always_auth_config = '//{}{}:always-auth'.format( repo_uri.netloc, repo_uri.path) auth_token_config = '//{}{}:_authToken'.format(repo_uri.netloc, repo_uri.path) scope = kwargs.get('scope') registry = '{}:registry'.format(scope) if scope else 'registry' commands = [] commands.append([npm_cmd, 'config', 'set', registry, self.endpoint]) commands.append([npm_cmd, 'config', 'set', always_auth_config, 'true']) commands.append( [npm_cmd, 'config', 'set', auth_token_config, self.auth_token]) return commands def _get_pip_commands(self): pip_index_url_fmt = '{scheme}://aws:{auth_token}@{netloc}{path}simple/' repo_uri = urlparse.urlsplit(self.endpoint) pip_index_url = pip_index_url_fmt.format(scheme=repo_uri.scheme, auth_token=self.auth_token, netloc=repo_uri.netloc, path=repo_uri.path) return [['pip', 'config', 'set', 'global.index-url', pip_index_url]] def _get_twine_commands(self): default_pypi_rc_fmt = '''\ [distutils] index-servers= pypi codeartifact [codeartifact] repository: {repository_endpoint} username: aws password: {auth_token}''' default_pypi_rc = default_pypi_rc_fmt.format( repository_endpoint=self.endpoint, auth_token=self.auth_token) pypi_rc = RawConfigParser() if os.path.exists(self.test_pypi_rc_path): pypi_rc.read(self.test_pypi_rc_path) index_servers = pypi_rc.get('distutils', 'index-servers') servers = [ server.strip() for server in index_servers.split('\n') if server.strip() != '' ] if 'codeartifact' not in servers: servers.append('codeartifact') pypi_rc.set('distutils', 'index-servers', '\n' + '\n'.join(servers)) if 'codeartifact' not in pypi_rc.sections(): pypi_rc.add_section('codeartifact') pypi_rc.set('codeartifact', 'repository', self.endpoint) pypi_rc.set('codeartifact', 'username', 'aws') pypi_rc.set('codeartifact', 'password', self.auth_token) else: pypi_rc.readfp(StringIO(default_pypi_rc)) pypi_rc_stream = StringIO() pypi_rc.write(pypi_rc_stream) pypi_rc_str = pypi_rc_stream.getvalue() pypi_rc_stream.close() return pypi_rc_str def _assert_expiration_printed_to_stdout(self, stdout): self.assertEqual( self.expiration_as_datetime.strftime("%Y-%m-%d %H:%M:%S"), stdout.split("at ")[1][0:19]) def _assert_operations_called(self, package_format, result, include_domain_owner=False, include_duration_seconds=False): get_auth_token_kwargs = {'domain': self.domain} get_repo_endpoint_kwargs = { 'domain': self.domain, 'repository': self.repository, 'format': package_format } if include_domain_owner: get_auth_token_kwargs['domainOwner'] = self.domain_owner get_repo_endpoint_kwargs['domainOwner'] = self.domain_owner if include_duration_seconds: get_auth_token_kwargs['durationSeconds'] = self.duration self.assertEqual(result.aws_requests, [ AWSRequest( service_name='codeartifact', operation_name='GetAuthorizationToken', params=get_auth_token_kwargs, ), AWSRequest( service_name='codeartifact', operation_name='GetRepositoryEndpoint', params=get_repo_endpoint_kwargs, ) ]) def _assert_subprocess_execution(self, commands): expected_calls = [ mock.call( command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) for command in commands ] self.subprocess_mock.assert_has_calls(expected_calls, any_order=True) def _assert_subprocess_check_output_execution(self, commands): expected_calls = [ mock.call( command, stderr=subprocess.PIPE, ) for command in commands ] self.subprocess_check_out_mock.assert_has_calls(expected_calls, any_order=True) def _assert_dry_run_execution(self, commands, stdout): self.subprocess_mock.assert_not_called() for command in commands: self.assertIn(' '.join(command), stdout) def _assert_pypi_rc_has_expected_content(self, pypi_rc_str, server, repo_url=None, username=None, password=None): pypi_rc = RawConfigParser() pypi_rc.readfp(StringIO(pypi_rc_str)) self.assertIn('distutils', pypi_rc.sections()) self.assertIn('index-servers', pypi_rc.options('distutils')) index_servers = pypi_rc.get('distutils', 'index-servers') index_servers = [ index_server.strip() for index_server in index_servers.split('\n') if index_server.strip() != '' ] self.assertIn(server, index_servers) if repo_url or username or password: self.assertIn(server, pypi_rc.sections()) if repo_url: self.assertIn('repository', pypi_rc.options(server)) self.assertEqual(pypi_rc.get(server, 'repository'), repo_url) if username: self.assertIn('username', pypi_rc.options(server)) self.assertEqual(pypi_rc.get(server, 'username'), username) if password: self.assertIn('password', pypi_rc.options(server)) self.assertEqual(pypi_rc.get(server, 'password'), password) def test_nuget_login_without_domain_owner_without_duration_seconds(self): cmdline = self._setup_cmd(tool='nuget') result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='nuget', result=result) self._assert_expiration_printed_to_stdout(result.stdout) self._assert_subprocess_check_output_execution( self._get_nuget_commands()) def test_nuget_login_with_domain_owner_without_duration_seconds(self): cmdline = self._setup_cmd(tool='nuget', include_domain_owner=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='nuget', include_domain_owner=True, result=result) self._assert_expiration_printed_to_stdout(result.stdout) self._assert_subprocess_check_output_execution( self._get_nuget_commands()) def test_nuget_login_without_domain_owner_with_duration_seconds(self): cmdline = self._setup_cmd(tool='nuget', include_duration_seconds=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='nuget', include_duration_seconds=True, result=result) self._assert_expiration_printed_to_stdout(result.stdout) self._assert_subprocess_check_output_execution( self._get_nuget_commands()) def test_nuget_login_with_domain_owner_duration_sections(self): cmdline = self._setup_cmd(tool='nuget', include_domain_owner=True, include_duration_seconds=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='nuget', include_domain_owner=True, include_duration_seconds=True, result=result) self._assert_expiration_printed_to_stdout(result.stdout) self._assert_subprocess_check_output_execution( self._get_nuget_commands()) def test_nuget_login_without_domain_owner_dry_run(self): cmdline = self._setup_cmd(tool='nuget', dry_run=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='nuget', result=result) self._assert_dry_run_execution(self._get_nuget_commands(), result.stdout) def test_nuget_login_with_domain_owner_dry_run(self): cmdline = self._setup_cmd(tool='nuget', include_domain_owner=True, dry_run=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='nuget', include_domain_owner=True, result=result) self._assert_dry_run_execution(self._get_nuget_commands(), result.stdout) def test_nuget_login_with_duration_seconds_dry_run(self): cmdline = self._setup_cmd(tool='nuget', include_duration_seconds=True, dry_run=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='nuget', include_duration_seconds=True, result=result) self._assert_dry_run_execution(self._get_nuget_commands(), result.stdout) def test_nuget_login_with_domain_owner_duration_seconds_dry_run(self): cmdline = self._setup_cmd(tool='nuget', include_domain_owner=True, include_duration_seconds=True, dry_run=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='nuget', include_domain_owner=True, include_duration_seconds=True, result=result) self._assert_dry_run_execution(self._get_nuget_commands(), result.stdout) @mock.patch('awscli.customizations.codeartifact.login.is_windows', True) def test_dotnet_login_without_domain_owner_without_duration_seconds(self): cmdline = self._setup_cmd(tool='dotnet') result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='nuget', result=result) self._assert_expiration_printed_to_stdout(result.stdout) self._assert_subprocess_check_output_execution( self._get_dotnet_commands()) @mock.patch('awscli.customizations.codeartifact.login.is_windows', True) def test_dotnet_login_with_domain_owner_without_duration_seconds(self): cmdline = self._setup_cmd(tool='dotnet', include_domain_owner=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='nuget', include_domain_owner=True, result=result) self._assert_expiration_printed_to_stdout(result.stdout) self._assert_subprocess_check_output_execution( self._get_dotnet_commands()) @mock.patch('awscli.customizations.codeartifact.login.is_windows', True) def test_dotnet_login_without_domain_owner_with_duration_seconds(self): cmdline = self._setup_cmd(tool='dotnet', include_duration_seconds=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='nuget', include_duration_seconds=True, result=result) self._assert_expiration_printed_to_stdout(result.stdout) self._assert_subprocess_check_output_execution( self._get_dotnet_commands()) @mock.patch('awscli.customizations.codeartifact.login.is_windows', True) def test_dotnet_login_with_domain_owner_duration_sections(self): cmdline = self._setup_cmd(tool='dotnet', include_domain_owner=True, include_duration_seconds=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='nuget', include_domain_owner=True, include_duration_seconds=True, result=result) self._assert_expiration_printed_to_stdout(result.stdout) self._assert_subprocess_check_output_execution( self._get_dotnet_commands()) @mock.patch('awscli.customizations.codeartifact.login.is_windows', True) def test_dotnet_login_without_domain_owner_dry_run(self): cmdline = self._setup_cmd(tool='dotnet', dry_run=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='nuget', result=result) self._assert_dry_run_execution(self._get_dotnet_commands(), result.stdout) @mock.patch('awscli.customizations.codeartifact.login.is_windows', True) def test_dotnet_login_with_domain_owner_dry_run(self): cmdline = self._setup_cmd(tool='dotnet', include_domain_owner=True, dry_run=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='nuget', include_domain_owner=True, result=result) self._assert_dry_run_execution(self._get_dotnet_commands(), result.stdout) @mock.patch('awscli.customizations.codeartifact.login.is_windows', True) def test_dotnet_login_with_duration_seconds_dry_run(self): cmdline = self._setup_cmd(tool='dotnet', include_duration_seconds=True, dry_run=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='nuget', include_duration_seconds=True, result=result) self._assert_dry_run_execution(self._get_dotnet_commands(), result.stdout) @mock.patch('awscli.customizations.codeartifact.login.is_windows', True) def test_dotnet_login_with_domain_owner_duration_seconds_dry_run(self): cmdline = self._setup_cmd(tool='dotnet', include_domain_owner=True, include_duration_seconds=True, dry_run=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='nuget', include_domain_owner=True, include_duration_seconds=True, result=result) self._assert_dry_run_execution(self._get_dotnet_commands(), result.stdout) def test_npm_login_without_domain_owner(self): cmdline = self._setup_cmd(tool='npm') result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='npm', result=result) self._assert_expiration_printed_to_stdout(result.stdout) self._assert_subprocess_execution(self._get_npm_commands()) def test_npm_login_without_domain_owner_dry_run(self): cmdline = self._setup_cmd(tool='npm', dry_run=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='npm', result=result) self._assert_dry_run_execution(self._get_npm_commands(), result.stdout) def test_npm_login_with_domain_owner(self): cmdline = self._setup_cmd(tool='npm', include_domain_owner=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='npm', result=result, include_domain_owner=True, include_duration_seconds=False) self._assert_expiration_printed_to_stdout(result.stdout) self._assert_subprocess_execution(self._get_npm_commands()) def test_npm_login_with_domain_owner_duration(self): cmdline = self._setup_cmd(tool='npm', include_domain_owner=True, include_duration_seconds=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='npm', result=result, include_domain_owner=True, include_duration_seconds=True) self._assert_expiration_printed_to_stdout(result.stdout) self._assert_subprocess_execution(self._get_npm_commands()) def test_npm_login_with_domain_owner_dry_run(self): cmdline = self._setup_cmd(tool='npm', include_domain_owner=True, dry_run=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='npm', result=result, include_domain_owner=True) self._assert_dry_run_execution(self._get_npm_commands(), result.stdout) def test_npm_login_with_namespace(self): cmdline = self._setup_cmd(tool='npm', include_namespace=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='npm', result=result) self._assert_expiration_printed_to_stdout(result.stdout) self._assert_subprocess_execution( self._get_npm_commands(scope='@{}'.format(self.namespace))) def test_npm_login_with_namespace_dry_run(self): cmdline = self._setup_cmd(tool='npm', include_namespace=True, dry_run=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='npm', result=result) self._assert_dry_run_execution( self._get_npm_commands(scope='@{}'.format(self.namespace)), result.stdout) def test_pip_login_without_domain_owner(self): cmdline = self._setup_cmd(tool='pip') result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='pypi', result=result) self._assert_expiration_printed_to_stdout(result.stdout) self._assert_subprocess_execution(self._get_pip_commands()) def test_pip_login_without_domain_owner_dry_run(self): cmdline = self._setup_cmd(tool='pip', dry_run=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='pypi', result=result) self._assert_dry_run_execution(self._get_pip_commands(), result.stdout) def test_pip_login_with_domain_owner(self): cmdline = self._setup_cmd(tool='pip', include_domain_owner=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='pypi', result=result, include_domain_owner=True) self._assert_expiration_printed_to_stdout(result.stdout) self._assert_subprocess_execution(self._get_pip_commands()) def test_pip_login_with_domain_owner_duration(self): cmdline = self._setup_cmd(tool='pip', include_domain_owner=True, include_duration_seconds=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='pypi', result=result, include_domain_owner=True, include_duration_seconds=True) self._assert_expiration_printed_to_stdout(result.stdout) self._assert_subprocess_execution(self._get_pip_commands()) def test_pip_login_with_domain_owner_dry_run(self): cmdline = self._setup_cmd(tool='pip', include_domain_owner=True, dry_run=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='pypi', result=result, include_domain_owner=True) self._assert_dry_run_execution(self._get_pip_commands(), result.stdout) def test_pip_login_with_namespace(self): cmdline = self._setup_cmd(tool='pip', include_namespace=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 255) self._assert_operations_called(package_format='pypi', result=result) self.assertIn('Argument --namespace is not supported for pip', result.stderr) def test_pip_login_with_namespace_dry_run(self): cmdline = self._setup_cmd(tool='pip', include_namespace=True, dry_run=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 255) self._assert_operations_called(package_format='pypi', result=result) self.assertIn('Argument --namespace is not supported for pip', result.stderr) def test_twine_login_without_domain_owner(self): cmdline = self._setup_cmd(tool='twine') result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='pypi', result=result) self._assert_expiration_printed_to_stdout(result.stdout) with open(self.test_pypi_rc_path) as f: test_pypi_rc_str = f.read() self._assert_pypi_rc_has_expected_content(pypi_rc_str=test_pypi_rc_str, server='codeartifact', repo_url=self.endpoint, username='******', password=self.auth_token) def test_twine_login_without_domain_owner_dry_run(self): cmdline = self._setup_cmd(tool='twine', dry_run=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='pypi', result=result) self.assertFalse(os.path.exists(self.test_pypi_rc_path)) self._assert_pypi_rc_has_expected_content( pypi_rc_str=self._get_twine_commands(), server='codeartifact', repo_url=self.endpoint, username='******', password=self.auth_token) def test_twine_login_with_domain_owner(self): cmdline = self._setup_cmd(tool='twine', include_domain_owner=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='pypi', result=result, include_domain_owner=True) self._assert_expiration_printed_to_stdout(result.stdout) with open(self.test_pypi_rc_path) as f: test_pypi_rc_str = f.read() self._assert_pypi_rc_has_expected_content(pypi_rc_str=test_pypi_rc_str, server='codeartifact', repo_url=self.endpoint, username='******', password=self.auth_token) def test_twine_login_with_domain_owner_duration(self): cmdline = self._setup_cmd(tool='twine', include_domain_owner=True, include_duration_seconds=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='pypi', result=result, include_domain_owner=True, include_duration_seconds=True) self._assert_expiration_printed_to_stdout(result.stdout) with open(self.test_pypi_rc_path) as f: test_pypi_rc_str = f.read() self._assert_pypi_rc_has_expected_content(pypi_rc_str=test_pypi_rc_str, server='codeartifact', repo_url=self.endpoint, username='******', password=self.auth_token) def test_twine_login_with_domain_owner_dry_run(self): cmdline = self._setup_cmd(tool='twine', include_domain_owner=True, dry_run=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 0) self._assert_operations_called(package_format='pypi', result=result, include_domain_owner=True) self.assertFalse(os.path.exists(self.test_pypi_rc_path)) self._assert_pypi_rc_has_expected_content( pypi_rc_str=self._get_twine_commands(), server='codeartifact', repo_url=self.endpoint, username='******', password=self.auth_token) def test_twine_login_with_namespace(self): cmdline = self._setup_cmd(tool='twine', include_namespace=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 255) self._assert_operations_called(package_format='pypi', result=result) self.assertIn('Argument --namespace is not supported for twine', result.stderr) def test_twine_login_with_namespace_dry_run(self): cmdline = self._setup_cmd(tool='twine', include_namespace=True, dry_run=True) result = self.cli_runner.run(cmdline) self.assertEqual(result.rc, 255) self._assert_operations_called(package_format='pypi', result=result) self.assertFalse(os.path.exists(self.test_pypi_rc_path)) self.assertIn('Argument --namespace is not supported for twine', result.stderr)
class TestCodeArtifactLogin(BaseAWSCommandParamsTest): prefix = 'codeartifact login' def setUp(self): super(TestCodeArtifactLogin, self).setUp() self.file_creator = FileCreator() self.test_pypi_rc_path = self.file_creator.full_path('pypirc') if not os.path.isdir(os.path.dirname(self.test_pypi_rc_path)): os.makedirs(os.path.dirname(self.test_pypi_rc_path)) self.domain = 'domain' self.domain_owner = 'domain-owner' self.repository = 'repository' self.auth_token = 'auth-token' self.duration = 3600 self.expiration = time.time() + self.duration self.expiration_as_datetime = parse_timestamp(self.expiration) self.pypi_rc_path_patch = mock.patch( 'awscli.customizations.codeartifact.login.TwineLogin' '.get_pypi_rc_path') self.pypi_rc_path_mock = self.pypi_rc_path_patch.start() self.pypi_rc_path_mock.return_value = self.test_pypi_rc_path self.subprocess_patch = mock.patch('subprocess.check_call') self.subprocess_mock = self.subprocess_patch.start() def tearDown(self): super(TestCodeArtifactLogin, self).tearDown() self.pypi_rc_path_patch.stop() self.subprocess_patch.stop() self.file_creator.remove_all() def _setup_cmd(self, tool, include_domain_owner=False, dry_run=False, include_duration_seconds=False): package_format = CodeArtifactLogin.TOOL_MAP[tool]['package_format'] self.endpoint = 'https://{domain}-{domainOwner}.codeartifact.aws.' \ 'a2z.com/{format}/{repository}/'.format( domain=self.domain, domainOwner=self.domain_owner, format=package_format, repository=self.repository ) cmdline = self.prefix cmdline += ' --domain %s' % self.domain cmdline += ' --repository %s' % self.repository cmdline += ' --tool %s' % tool if include_domain_owner: cmdline += ' --domain-owner %s' % self.domain_owner if dry_run: cmdline += ' --dry-run' if include_duration_seconds: cmdline += ' --duration-seconds %s' % self.duration # Responses from calls to services. self.parsed_responses = [ { "authorizationToken": self.auth_token, "expiration": self.expiration }, # GetAuthorizationToken { "repositoryEndpoint": self.endpoint }, # GetRepositoryEndpoint ] return cmdline def _get_npm_commands(self): npm_cmd = 'npm.cmd' \ if platform.system().lower() == 'windows' else 'npm' repo_uri = urlparse.urlsplit(self.endpoint) always_auth_config = '//{}{}:always-auth'.format( repo_uri.netloc, repo_uri.path) auth_token_config = '//{}{}:_authToken'.format(repo_uri.netloc, repo_uri.path) commands = [] commands.append([npm_cmd, 'config', 'set', 'registry', self.endpoint]) commands.append([npm_cmd, 'config', 'set', always_auth_config, 'true']) commands.append( [npm_cmd, 'config', 'set', auth_token_config, self.auth_token]) return commands def _get_pip_commands(self): pip_index_url_fmt = '{scheme}://aws:{auth_token}@{netloc}{path}simple/' repo_uri = urlparse.urlsplit(self.endpoint) pip_index_url = pip_index_url_fmt.format(scheme=repo_uri.scheme, auth_token=self.auth_token, netloc=repo_uri.netloc, path=repo_uri.path) return [['pip', 'config', 'set', 'global.index-url', pip_index_url]] def _get_twine_commands(self): default_pypi_rc_fmt = '''\ [distutils] index-servers= pypi codeartifact [codeartifact] repository: {repository_endpoint} username: aws password: {auth_token}''' default_pypi_rc = default_pypi_rc_fmt.format( repository_endpoint=self.endpoint, auth_token=self.auth_token) pypi_rc = RawConfigParser() if os.path.exists(self.test_pypi_rc_path): pypi_rc.read(self.test_pypi_rc_path) index_servers = pypi_rc.get('distutils', 'index-servers') servers = [ server.strip() for server in index_servers.split('\n') if server.strip() != '' ] if 'codeartifact' not in servers: servers.append('codeartifact') pypi_rc.set('distutils', 'index-servers', '\n' + '\n'.join(servers)) if 'codeartifact' not in pypi_rc.sections(): pypi_rc.add_section('codeartifact') pypi_rc.set('codeartifact', 'repository', self.endpoint) pypi_rc.set('codeartifact', 'username', 'aws') pypi_rc.set('codeartifact', 'password', self.auth_token) else: pypi_rc.readfp(StringIO(default_pypi_rc)) pypi_rc_stream = StringIO() pypi_rc.write(pypi_rc_stream) pypi_rc_str = pypi_rc_stream.getvalue() pypi_rc_stream.close() return pypi_rc_str def _assert_expiration_printed_to_stdout(self, stdout): self.assertEqual( self.expiration_as_datetime.strftime("%Y-%m-%d %H:%M:%S"), stdout.split("at ")[1][0:19]) def _assert_operations_called(self, package_format, include_domain_owner=False, include_duration_seconds=False): self.assertEqual(len(self.operations_called), 2) get_auth_token_kwargs = {'domain': self.domain} get_repo_endpoint_kwargs = { 'domain': self.domain, 'repository': self.repository, 'format': package_format } if include_domain_owner: get_auth_token_kwargs['domainOwner'] = self.domain_owner get_repo_endpoint_kwargs['domainOwner'] = self.domain_owner if include_duration_seconds: get_auth_token_kwargs['durationSeconds'] = self.duration self.assertEqual(self.operations_called[0][0].name, 'GetAuthorizationToken') self.assertEqual(self.operations_called[0][1], get_auth_token_kwargs) self.assertEqual(self.operations_called[1][0].name, 'GetRepositoryEndpoint') self.assertEqual(self.operations_called[1][1], get_repo_endpoint_kwargs) def _assert_subprocess_execution(self, commands): expected_calls = [ mock.call( command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) for command in commands ] self.subprocess_mock.assert_has_calls(expected_calls, any_order=True) def _assert_dry_run_execution(self, commands, stdout): self.subprocess_mock.assert_not_called() for command in commands: self.assertIn(' '.join(command), stdout) def _assert_pypi_rc_has_expected_content(self, pypi_rc_str, server, repo_url=None, username=None, password=None): pypi_rc = RawConfigParser() pypi_rc.readfp(StringIO(pypi_rc_str)) self.assertIn('distutils', pypi_rc.sections()) self.assertIn('index-servers', pypi_rc.options('distutils')) index_servers = pypi_rc.get('distutils', 'index-servers') index_servers = [ index_server.strip() for index_server in index_servers.split('\n') if index_server.strip() != '' ] self.assertIn(server, index_servers) if repo_url or username or password: self.assertIn(server, pypi_rc.sections()) if repo_url: self.assertIn('repository', pypi_rc.options(server)) self.assertEqual(pypi_rc.get(server, 'repository'), repo_url) if username: self.assertIn('username', pypi_rc.options(server)) self.assertEqual(pypi_rc.get(server, 'username'), username) if password: self.assertIn('password', pypi_rc.options(server)) self.assertEqual(pypi_rc.get(server, 'password'), password) def test_npm_login_without_domain_owner(self): cmdline = self._setup_cmd(tool='npm') stdout, stderr, rc = self.run_cmd(cmdline, expected_rc=0) self._assert_operations_called(package_format='npm') self._assert_expiration_printed_to_stdout(stdout) self._assert_subprocess_execution(self._get_npm_commands()) def test_npm_login_without_domain_owner_dry_run(self): cmdline = self._setup_cmd(tool='npm', dry_run=True) stdout, stderr, rc = self.run_cmd(cmdline, expected_rc=0) self._assert_operations_called(package_format='npm') self._assert_dry_run_execution(self._get_npm_commands(), stdout) def test_npm_login_with_domain_owner(self): cmdline = self._setup_cmd(tool='npm', include_domain_owner=True) stdout, stderr, rc = self.run_cmd(cmdline, expected_rc=0) self._assert_operations_called(package_format='npm', include_domain_owner=True, include_duration_seconds=False) self._assert_expiration_printed_to_stdout(stdout) self._assert_subprocess_execution(self._get_npm_commands()) def test_npm_login_with_domain_owner_duration(self): cmdline = self._setup_cmd(tool='npm', include_domain_owner=True, include_duration_seconds=True) stdout, stderr, rc = self.run_cmd(cmdline, expected_rc=0) self._assert_operations_called(package_format='npm', include_domain_owner=True, include_duration_seconds=True) self._assert_expiration_printed_to_stdout(stdout) self._assert_subprocess_execution(self._get_npm_commands()) def test_npm_login_with_domain_owner_dry_run(self): cmdline = self._setup_cmd(tool='npm', include_domain_owner=True, dry_run=True) stdout, stderr, rc = self.run_cmd(cmdline, expected_rc=0) self._assert_operations_called(package_format='npm', include_domain_owner=True) self._assert_dry_run_execution(self._get_npm_commands(), stdout) def test_pip_login_without_domain_owner(self): cmdline = self._setup_cmd(tool='pip') stdout, stderr, rc = self.run_cmd(cmdline, expected_rc=0) self._assert_operations_called(package_format='pypi') self._assert_expiration_printed_to_stdout(stdout) self._assert_subprocess_execution(self._get_pip_commands()) def test_pip_login_without_domain_owner_dry_run(self): cmdline = self._setup_cmd(tool='pip', dry_run=True) stdout, stderr, rc = self.run_cmd(cmdline, expected_rc=0) self._assert_operations_called(package_format='pypi') self._assert_dry_run_execution(self._get_pip_commands(), stdout) def test_pip_login_with_domain_owner(self): cmdline = self._setup_cmd(tool='pip', include_domain_owner=True) stdout, stderr, rc = self.run_cmd(cmdline, expected_rc=0) self._assert_operations_called(package_format='pypi', include_domain_owner=True) self._assert_expiration_printed_to_stdout(stdout) self._assert_subprocess_execution(self._get_pip_commands()) def test_pip_login_with_domain_owner_duration(self): cmdline = self._setup_cmd(tool='pip', include_domain_owner=True, include_duration_seconds=True) stdout, stderr, rc = self.run_cmd(cmdline, expected_rc=0) self._assert_operations_called(package_format='pypi', include_domain_owner=True, include_duration_seconds=True) self._assert_expiration_printed_to_stdout(stdout) self._assert_subprocess_execution(self._get_pip_commands()) def test_pip_login_with_domain_owner_dry_run(self): cmdline = self._setup_cmd(tool='pip', include_domain_owner=True, dry_run=True) stdout, stderr, rc = self.run_cmd(cmdline, expected_rc=0) self._assert_operations_called(package_format='pypi', include_domain_owner=True) self._assert_dry_run_execution(self._get_pip_commands(), stdout) def test_twine_login_without_domain_owner(self): cmdline = self._setup_cmd(tool='twine') stdout, stderr, rc = self.run_cmd(cmdline, expected_rc=0) self._assert_operations_called(package_format='pypi') self._assert_expiration_printed_to_stdout(stdout) with open(self.test_pypi_rc_path) as f: test_pypi_rc_str = f.read() self._assert_pypi_rc_has_expected_content(pypi_rc_str=test_pypi_rc_str, server='codeartifact', repo_url=self.endpoint, username='******', password=self.auth_token) def test_twine_login_without_domain_owner_dry_run(self): cmdline = self._setup_cmd(tool='twine', dry_run=True) stdout, stderr, rc = self.run_cmd(cmdline, expected_rc=0) self._assert_operations_called(package_format='pypi') self.assertFalse(os.path.exists(self.test_pypi_rc_path)) self._assert_pypi_rc_has_expected_content( pypi_rc_str=self._get_twine_commands(), server='codeartifact', repo_url=self.endpoint, username='******', password=self.auth_token) def test_twine_login_with_domain_owner(self): cmdline = self._setup_cmd(tool='twine', include_domain_owner=True) stdout, stderr, rc = self.run_cmd(cmdline, expected_rc=0) self._assert_operations_called(package_format='pypi', include_domain_owner=True) self._assert_expiration_printed_to_stdout(stdout) with open(self.test_pypi_rc_path) as f: test_pypi_rc_str = f.read() self._assert_pypi_rc_has_expected_content(pypi_rc_str=test_pypi_rc_str, server='codeartifact', repo_url=self.endpoint, username='******', password=self.auth_token) def test_twine_login_with_domain_owner_duration(self): cmdline = self._setup_cmd(tool='twine', include_domain_owner=True, include_duration_seconds=True) stdout, stderr, rc = self.run_cmd(cmdline, expected_rc=0) self._assert_operations_called(package_format='pypi', include_domain_owner=True, include_duration_seconds=True) self._assert_expiration_printed_to_stdout(stdout) with open(self.test_pypi_rc_path) as f: test_pypi_rc_str = f.read() self._assert_pypi_rc_has_expected_content(pypi_rc_str=test_pypi_rc_str, server='codeartifact', repo_url=self.endpoint, username='******', password=self.auth_token) def test_twine_login_with_domain_owner_dry_run(self): cmdline = self._setup_cmd(tool='twine', include_domain_owner=True, dry_run=True) stdout, stderr, rc = self.run_cmd(cmdline, expected_rc=0) self._assert_operations_called(package_format='pypi', include_domain_owner=True) self.assertFalse(os.path.exists(self.test_pypi_rc_path)) self._assert_pypi_rc_has_expected_content( pypi_rc_str=self._get_twine_commands(), server='codeartifact', repo_url=self.endpoint, username='******', password=self.auth_token)