# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"). You
# may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# or in the "license" file accompanying this file. This file is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
import os
import shutil
import sys

import mock
import unittest

from ebcli.lib import aws, elasticbeanstalk

from ..test_helper import EnvVarSubstitutor

if sys.platform.startswith('win32'):
    HOME = [
        environ
        for environ in os.environ
        if os.environ[environ] == os.path.expanduser('~')
    ][0]
else:
    HOME = 'HOME'

NOT_FOUND_ERROR_TEMPLATE = '{missing_object} does not exist. '
'It is possible that implementation of related logic and'
'not just the method name has changed in a recent version '
'of `botocore`.'

try:
    from botocore.endpoint import Endpoint
    Endpoint._get_response
except (ModuleNotFoundError, AttributeError):
    raise NotImplementedError(
        NOT_FOUND_ERROR_TEMPLATE.format(missing_object='botocore.endpoint.Endpoint._get_response')
    )

try:
    from botocore.httpsession import URLLib3Session
    URLLib3Session.send
except (ModuleNotFoundError, AttributeError):
    raise NotImplementedError(
        NOT_FOUND_ERROR_TEMPLATE.format(missing_object='botocore.httpsession.URLLib3Session.send')
    )


class CredentialsEnvVarSubstituter(object):
    def __init__(self, access_id, secret_key):
        self.access_id = access_id
        self.secret_key = secret_key

    def __call__(self, func):
        with EnvVarSubstitutor('AWS_ACCESS_KEY_ID', self.access_id):
            with EnvVarSubstitutor('AWS_SECRET_ACCESS_KEY', self.secret_key):
                func()


@unittest.skipIf(
    not not os.environ.get('JENKINS_HOME') and sys.platform.startswith('win32'),
    reason='There are issues being able to find the `~` directory '
           'when run by the Jenkins service on Windows'
)
class TestProfileSelection(unittest.TestCase):
    """
    Class hosts integration tests that interact with botocore to ensure
    the right instance profile will be used. Order is defined in the following
    link:

        https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/eb-cli3-configuration.html#eb-cli3-credentials
    """
    def assertCorrectProfileWasUsed(self, _get_response_mock, access_id='access_id'):
        self.assertIn(
            'AWS4-HMAC-SHA256 Credential={}'.format(access_id),
            self._request_header_authorization(_get_response_mock)
        )

    def run(self, result=None):
        aws._flush()
        aws._profile_env_var = 'AWS_EB_PROFILE'
        aws._region_name = 'us-west-2'
        self.root_dir = os.getcwd()
        if os.path.exists('testDir'):
            shutil.rmtree('testDir', ignore_errors=True)
        os.mkdir('testDir')
        os.chdir('testDir')
        try:
            with EnvVarSubstitutor(HOME, os.getcwd()):
                super(TestProfileSelection, self).run(result=result)
        finally:
            aws._flush()
            os.chdir(self.root_dir)
            shutil.rmtree('testDir', ignore_errors=True)

    def _generic_response(self):
        http_object = mock.MagicMock(status_code=200)
        response_object_mock = {
            'PlatformSummaryList': [],
            'ResponseMetadata': {
                'HTTPStatusCode': 200
            }
        }
        return (http_object, response_object_mock), None

    def _generate_profile_with_prefix(
            self,
            credentials_dir=None,
            credentials_file_name='credentials',
            profile='default',
            access_id='access_id',
            secret_key='secret_key'
    ):
        self._generate_profile(
            add_profile_prefix=True,
            credentials_dir=credentials_dir,
            credentials_file_name=credentials_file_name,
            profile=profile,
            access_id=access_id,
            secret_key=secret_key,
        )

    def _generate_profile(
            self,
            add_profile_prefix=False,
            credentials_dir=None,
            credentials_file_name='credentials',
            profile='default',
            access_id='access_id',
            secret_key='secret_key'
    ):
        credentials_dir = credentials_dir or os.path.join(os.environ[HOME], '.aws')
        os.mkdir(credentials_dir)
        credentials_file = os.path.join(credentials_dir, credentials_file_name)
        with open(credentials_file, 'w') as file:
            file.write(
                """[{profile_prefix}{profile}]
aws_access_key_id = {access_id}
aws_secret_access_key = {secret_key}
""".format(
                    profile_prefix='profile ' if add_profile_prefix else '',
                    profile=profile,
                    access_id=access_id,
                    secret_key=secret_key,
                )
            )

    def _request_header_authorization(self, _get_response_mock):
        aws_prepared_request = _get_response_mock.call_args[0][0]
        request_headers = aws_prepared_request.headers
        return str(request_headers['Authorization'])

    @mock.patch('botocore.endpoint.Endpoint._get_response')
    def test_environment_variables_used(
            self,
            _get_response_mock
    ):
        """
            - `--profile` is not passed and is not set in config.yml
            - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` are found
        """
        _get_response_mock.return_value = self._generic_response()

        @CredentialsEnvVarSubstituter('access_id', 'secret_key')
        def invoke_api():
            elasticbeanstalk.list_platform_versions()

        self.assertCorrectProfileWasUsed(_get_response_mock)

    @mock.patch('botocore.httpsession.URLLib3Session.send')
    def test_environment_variables_not_found(
            self,
            send_mock
    ):
        """
            - `--profile` is not passed and is not set in config.yml
            - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` are not found
            - attempt is made to communicate with IAM to assume role
        """
        @CredentialsEnvVarSubstituter(None, None)
        def invoke_api():
            try:
                elasticbeanstalk.list_platform_versions()
            except Exception:
                pass

        iam_role_verification_request = send_mock.call_args[0][0]
        self.assertIn(
            'latest/meta-data/iam/security-credentials/',
            iam_role_verification_request.url
        )

    def test_aws_eb_profile_environment_variable_found_but_profile_does_not_exist(self):
        """
            - `--profile` is not passed and is not set in config.yml
            - environment variable `AWS_EB_PROFILE` found, but profile does not exist
            - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` found but not used
        """
        with EnvVarSubstitutor('AWS_EB_PROFILE', 'some_profile'):
            with self.assertRaises(aws.InvalidProfileError) as context_manager:
                @CredentialsEnvVarSubstituter('access_id', 'secret_key')
                def invoke_api():
                    elasticbeanstalk.list_platform_versions()

            self.assertEqual(
                'The config profile (some_profile) could not be found',
                str(context_manager.exception)
            )

    @mock.patch('botocore.endpoint.Endpoint._get_response')
    def test_aws_eb_profile_environment_variable_found__profile_exists_in_credentials_file(
            self,
            _get_response_mock
    ):
        """
            - `--profile` is not passed and is not set in config.yml
            - environment variable `AWS_EB_PROFILE` found, profile exists in credentials file
            - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` found but not used
        """
        self._generate_profile(profile='some_profile')
        with EnvVarSubstitutor('AWS_EB_PROFILE', 'some_profile'):
            _get_response_mock.return_value = self._generic_response()

            @CredentialsEnvVarSubstituter('access_id', 'secret_key')
            def invoke_api():
                elasticbeanstalk.list_platform_versions()

            self.assertCorrectProfileWasUsed(_get_response_mock)

    @mock.patch('botocore.endpoint.Endpoint._get_response')
    def test_aws_eb_profile_environment_variable_found__profile_exists_in_config_file(
            self,
            _get_response_mock
    ):
        """
            - `--profile` is not passed and is not set in config.yml
            - environment variable `AWS_EB_PROFILE` found, profile exists in config file
            - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` found but not used
        """
        self._generate_profile_with_prefix(profile='some_profile', credentials_file_name='config')
        with EnvVarSubstitutor('AWS_EB_PROFILE', 'some_profile'):
            _get_response_mock.return_value = self._generic_response()

            @CredentialsEnvVarSubstituter('access_id', 'secret_key')
            def invoke_api():
                elasticbeanstalk.list_platform_versions()

            self.assertCorrectProfileWasUsed(_get_response_mock)

    @mock.patch('botocore.endpoint.Endpoint._get_response')
    def test_default_profile_is_found_in_credentials_file(
            self,
            _get_response_mock
    ):
        """
            - `--profile` is not passed and is not set in config.yml
            - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` are not found
            - `default` profile is assumed and found in `$HOME/.aws/credentials` file
        """
        self._generate_profile()
        _get_response_mock.return_value = self._generic_response()

        @CredentialsEnvVarSubstituter(None, None)
        def invoke_api():
            elasticbeanstalk.list_platform_versions()

        self.assertCorrectProfileWasUsed(_get_response_mock)

    @mock.patch('botocore.endpoint.Endpoint._get_response')
    def test_default_profile_is_found_in_config_file__profile_prefix_is_not_added(
            self,
            _get_response_mock
    ):
        """
            - `--profile` is not passed and is not set in config.yml
            - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` are not found
            - `default` profile is assumed and found in `$HOME/.aws/config` file; profile is identified as `[default]`
        """
        self._generate_profile(credentials_file_name='config')
        _get_response_mock.return_value = self._generic_response()

        @CredentialsEnvVarSubstituter(None, None)
        def invoke_api():
            elasticbeanstalk.list_platform_versions()

        self.assertCorrectProfileWasUsed(_get_response_mock)

    @mock.patch('botocore.endpoint.Endpoint._get_response')
    def test_default_profile_is_found_in_config_file__profile_prefix_is_added(
            self,
            _get_response_mock
    ):
        """
            - `--profile` is not passed and is not set in config.yml
            - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` are not found
            - `default` profile is found in `$HOME/.aws/config` file; profile is identified as `[profile default]`
        """
        self._generate_profile_with_prefix(credentials_file_name='config')
        _get_response_mock.return_value = self._generic_response()

        @CredentialsEnvVarSubstituter(None, None)
        def invoke_api():
            elasticbeanstalk.list_platform_versions()

        self.assertCorrectProfileWasUsed(_get_response_mock)

    def test_profile_is_explicitly_passed_but_is_invalid(self):
        """
            - `--profile` is not passed and is not set in config.yml
            - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` are found
            - `some_profile` profile is not found in `$HOME/.aws/credentials`
        """
        aws._profile = 'some_profile'

        with self.assertRaises(aws.InvalidProfileError) as context_manager:
            @CredentialsEnvVarSubstituter('access_id', 'secret_key')
            def invoke_api():
                elasticbeanstalk.list_platform_versions()

        self.assertEqual(
            'The config profile (some_profile) could not be found',
            str(context_manager.exception)
        )

    @mock.patch('botocore.endpoint.Endpoint._get_response')
    def test_profile_is_found_in_credentials_file(
            self,
            _get_response_mock
    ):
        """
            - `--profile` is not passed and is not set in config.yml
            - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` are found
            - `some_profile` profile is found in `$HOME/.aws/credentials`
        """
        aws._profile = 'some_profile'
        self._generate_profile(profile='some_profile')
        _get_response_mock.return_value = self._generic_response()

        @CredentialsEnvVarSubstituter('some_other_access_id', 'secret_key')
        def invoke_api():
            elasticbeanstalk.list_platform_versions()

        self.assertCorrectProfileWasUsed(_get_response_mock)

    @mock.patch('botocore.endpoint.Endpoint._get_response')
    def test_profile_is_found_in_config_file(
            self,
            _get_response_mock
    ):
        """
            - `--profile` is not passed and is not set in config.yml
            - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` are found
            - `some_profile` profile is found in `$HOME/.aws/config`
        """
        aws._profile = 'some_profile'
        self._generate_profile_with_prefix(credentials_file_name='config', profile='some_profile')

        _get_response_mock.return_value = self._generic_response()

        @CredentialsEnvVarSubstituter('access_id', 'secret_key')
        def invoke_api():
            elasticbeanstalk.list_platform_versions()

        self.assertCorrectProfileWasUsed(_get_response_mock)

    def test_profile_is_found_in_config_file_but_profile_prefix_is_absent(self):
        """
            - `--profile` is not passed and is not set in config.yml
            - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` are found
            - `some_profile` profile is found in `$HOME/.aws/config` but profile prefix is absent
        """
        aws._profile = 'some_profile'
        self._generate_profile(credentials_file_name='config', profile='some_profile')

        with self.assertRaises(aws.InvalidProfileError) as context_manager:
            @CredentialsEnvVarSubstituter('access_id', 'secret_key')
            def invoke_api():
                elasticbeanstalk.list_platform_versions()

        self.assertEqual(
            'The config profile (some_profile) could not be found',
            str(context_manager.exception)
        )

# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"). You
# may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# or in the "license" file accompanying this file. This file is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
import os
import shutil
import sys

import mock
import unittest

from ebcli.lib import aws, elasticbeanstalk

from ..test_helper import EnvVarSubstitutor

if sys.platform.startswith('win32'):
    HOME = [
        environ
        for environ in os.environ
        if os.environ[environ] == os.path.expanduser('~')
    ][0]
else:
    HOME = 'HOME'

NOT_FOUND_ERROR_TEMPLATE = '{missing_object} does not exist. '
'It is possible that implementation of related logic and'
'not just the method name has changed in a recent version '
'of `botocore`.'

try:
    from botocore.endpoint import Endpoint
    Endpoint._get_response
except (ModuleNotFoundError, AttributeError):
    raise NotImplementedError(
        NOT_FOUND_ERROR_TEMPLATE.format(missing_object='botocore.endpoint.Endpoint._get_response')
    )

try:
    from botocore.httpsession import URLLib3Session
    URLLib3Session.send
except (ModuleNotFoundError, AttributeError):
    raise NotImplementedError(
        NOT_FOUND_ERROR_TEMPLATE.format(missing_object='botocore.httpsession.URLLib3Session.send')
    )


class CredentialsEnvVarSubstituter(object):
    def __init__(self, access_id, secret_key):
        self.access_id = access_id
        self.secret_key = secret_key

    def __call__(self, func):
        with EnvVarSubstitutor('AWS_ACCESS_KEY_ID', self.access_id):
            with EnvVarSubstitutor('AWS_SECRET_ACCESS_KEY', self.secret_key):
                func()


@unittest.skipIf(
    not not os.environ.get('JENKINS_HOME') and sys.platform.startswith('win32'),
    reason='There are issues being able to find the `~` directory '
           'when run by the Jenkins service on Windows'
)
class TestProfileSelection(unittest.TestCase):
    """
    Class hosts integration tests that interact with botocore to ensure
    the right instance profile will be used. Order is defined in the following
    link:

        https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/eb-cli3-configuration.html#eb-cli3-credentials
    """
    def assertCorrectProfileWasUsed(self, _get_response_mock, access_id='access_id'):
        self.assertIn(
            'AWS4-HMAC-SHA256 Credential={}'.format(access_id),
            self._request_header_authorization(_get_response_mock)
        )

    def run(self, result=None):
        aws._flush()
        aws._profile_env_var = 'AWS_EB_PROFILE'
        aws._region_name = 'us-west-2'
        self.root_dir = os.getcwd()
        if os.path.exists('testDir'):
            shutil.rmtree('testDir', ignore_errors=True)
        os.mkdir('testDir')
        os.chdir('testDir')
        try:
            with EnvVarSubstitutor(HOME, os.getcwd()):
                super(TestProfileSelection, self).run(result=result)
        finally:
            aws._flush()
            os.chdir(self.root_dir)
            shutil.rmtree('testDir', ignore_errors=True)

    def _generic_response(self):
        http_object = mock.MagicMock(status_code=200)
        response_object_mock = {
            'PlatformSummaryList': [],
            'ResponseMetadata': {
                'HTTPStatusCode': 200
            }
        }
        return (http_object, response_object_mock), None

    def _generate_profile_with_prefix(
            self,
            credentials_dir=None,
            credentials_file_name='credentials',
            profile='default',
            access_id='access_id',
            secret_key='secret_key'
    ):
        self._generate_profile(
            add_profile_prefix=True,
            credentials_dir=credentials_dir,
            credentials_file_name=credentials_file_name,
            profile=profile,
            access_id=access_id,
            secret_key=secret_key,
        )

    def _generate_profile(
            self,
            add_profile_prefix=False,
            credentials_dir=None,
            credentials_file_name='credentials',
            profile='default',
            access_id='access_id',
            secret_key='secret_key'
    ):
        credentials_dir = credentials_dir or os.path.join(os.environ[HOME], '.aws')
        os.mkdir(credentials_dir)
        credentials_file = os.path.join(credentials_dir, credentials_file_name)
        with open(credentials_file, 'w') as file:
            file.write(
                """[{profile_prefix}{profile}]
aws_access_key_id = {access_id}
aws_secret_access_key = {secret_key}
""".format(
                    profile_prefix='profile ' if add_profile_prefix else '',
                    profile=profile,
                    access_id=access_id,
                    secret_key=secret_key,
                )
            )

    def _request_header_authorization(self, _get_response_mock):
        aws_prepared_request = _get_response_mock.call_args[0][0]
        request_headers = aws_prepared_request.headers
        return str(request_headers['Authorization'])

    @mock.patch('botocore.endpoint.Endpoint._get_response')
    def test_environment_variables_used(
            self,
            _get_response_mock
    ):
        """
            - `--profile` is not passed and is not set in config.yml
            - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` are found
        """
        _get_response_mock.return_value = self._generic_response()

        @CredentialsEnvVarSubstituter('access_id', 'secret_key')
        def invoke_api():
            elasticbeanstalk.list_platform_versions()

        self.assertCorrectProfileWasUsed(_get_response_mock)

    @mock.patch('botocore.httpsession.URLLib3Session.send')
    def test_environment_variables_not_found(
            self,
            send_mock
    ):
        """
            - `--profile` is not passed and is not set in config.yml
            - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` are not found
            - attempt is made to communicate with IAM to assume role
        """
        @CredentialsEnvVarSubstituter(None, None)
        def invoke_api():
            try:
                elasticbeanstalk.list_platform_versions()
            except Exception:
                pass

        iam_role_verification_request = send_mock.call_args[0][0]
        self.assertIn(
            'latest/meta-data/iam/security-credentials/',
            iam_role_verification_request.url
        )

    def test_aws_eb_profile_environment_variable_found_but_profile_does_not_exist(self):
        """
            - `--profile` is not passed and is not set in config.yml
            - environment variable `AWS_EB_PROFILE` found, but profile does not exist
            - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` found but not used
        """
        with EnvVarSubstitutor('AWS_EB_PROFILE', 'some_profile'):
            with self.assertRaises(aws.InvalidProfileError) as context_manager:
                @CredentialsEnvVarSubstituter('access_id', 'secret_key')
                def invoke_api():
                    elasticbeanstalk.list_platform_versions()

            self.assertEqual(
                'The config profile (some_profile) could not be found',
                str(context_manager.exception)
            )

    @mock.patch('botocore.endpoint.Endpoint._get_response')
    def test_aws_eb_profile_environment_variable_found__profile_exists_in_credentials_file(
            self,
            _get_response_mock
    ):
        """
            - `--profile` is not passed and is not set in config.yml
            - environment variable `AWS_EB_PROFILE` found, profile exists in credentials file
            - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` found but not used
        """
        self._generate_profile(profile='some_profile')
        with EnvVarSubstitutor('AWS_EB_PROFILE', 'some_profile'):
            _get_response_mock.return_value = self._generic_response()

            @CredentialsEnvVarSubstituter('access_id', 'secret_key')
            def invoke_api():
                elasticbeanstalk.list_platform_versions()

            self.assertCorrectProfileWasUsed(_get_response_mock)

    @mock.patch('botocore.endpoint.Endpoint._get_response')
    def test_aws_eb_profile_environment_variable_found__profile_exists_in_config_file(
            self,
            _get_response_mock
    ):
        """
            - `--profile` is not passed and is not set in config.yml
            - environment variable `AWS_EB_PROFILE` found, profile exists in config file
            - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` found but not used
        """
        self._generate_profile_with_prefix(profile='some_profile', credentials_file_name='config')
        with EnvVarSubstitutor('AWS_EB_PROFILE', 'some_profile'):
            _get_response_mock.return_value = self._generic_response()

            @CredentialsEnvVarSubstituter('access_id', 'secret_key')
            def invoke_api():
                elasticbeanstalk.list_platform_versions()

            self.assertCorrectProfileWasUsed(_get_response_mock)

    @mock.patch('botocore.endpoint.Endpoint._get_response')
    def test_default_profile_is_found_in_credentials_file(
            self,
            _get_response_mock
    ):
        """
            - `--profile` is not passed and is not set in config.yml
            - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` are not found
            - `default` profile is assumed and found in `$HOME/.aws/credentials` file
        """
        self._generate_profile()
        _get_response_mock.return_value = self._generic_response()

        @CredentialsEnvVarSubstituter(None, None)
        def invoke_api():
            elasticbeanstalk.list_platform_versions()

        self.assertCorrectProfileWasUsed(_get_response_mock)

    @mock.patch('botocore.endpoint.Endpoint._get_response')
    def test_default_profile_is_found_in_config_file__profile_prefix_is_not_added(
            self,
            _get_response_mock
    ):
        """
            - `--profile` is not passed and is not set in config.yml
            - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` are not found
            - `default` profile is assumed and found in `$HOME/.aws/config` file; profile is identified as `[default]`
        """
        self._generate_profile(credentials_file_name='config')
        _get_response_mock.return_value = self._generic_response()

        @CredentialsEnvVarSubstituter(None, None)
        def invoke_api():
            elasticbeanstalk.list_platform_versions()

        self.assertCorrectProfileWasUsed(_get_response_mock)

    @mock.patch('botocore.endpoint.Endpoint._get_response')
    def test_default_profile_is_found_in_config_file__profile_prefix_is_added(
            self,
            _get_response_mock
    ):
        """
            - `--profile` is not passed and is not set in config.yml
            - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` are not found
            - `default` profile is found in `$HOME/.aws/config` file; profile is identified as `[profile default]`
        """
        self._generate_profile_with_prefix(credentials_file_name='config')
        _get_response_mock.return_value = self._generic_response()

        @CredentialsEnvVarSubstituter(None, None)
        def invoke_api():
            elasticbeanstalk.list_platform_versions()

        self.assertCorrectProfileWasUsed(_get_response_mock)

    def test_profile_is_explicitly_passed_but_is_invalid(self):
        """
            - `--profile` is not passed and is not set in config.yml
            - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` are found
            - `some_profile` profile is not found in `$HOME/.aws/credentials`
        """
        aws._profile = 'some_profile'

        with self.assertRaises(aws.InvalidProfileError) as context_manager:
            @CredentialsEnvVarSubstituter('access_id', 'secret_key')
            def invoke_api():
                elasticbeanstalk.list_platform_versions()

        self.assertEqual(
            'The config profile (some_profile) could not be found',
            str(context_manager.exception)
        )

    @mock.patch('botocore.endpoint.Endpoint._get_response')
    def test_profile_is_found_in_credentials_file(
            self,
            _get_response_mock
    ):
        """
            - `--profile` is not passed and is not set in config.yml
            - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` are found
            - `some_profile` profile is found in `$HOME/.aws/credentials`
        """
        aws._profile = 'some_profile'
        self._generate_profile(profile='some_profile')
        _get_response_mock.return_value = self._generic_response()

        @CredentialsEnvVarSubstituter('some_other_access_id', 'secret_key')
        def invoke_api():
            elasticbeanstalk.list_platform_versions()

        self.assertCorrectProfileWasUsed(_get_response_mock)

    @mock.patch('botocore.endpoint.Endpoint._get_response')
    def test_profile_is_found_in_config_file(
            self,
            _get_response_mock
    ):
        """
            - `--profile` is not passed and is not set in config.yml
            - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` are found
            - `some_profile` profile is found in `$HOME/.aws/config`
        """
        aws._profile = 'some_profile'
        self._generate_profile_with_prefix(credentials_file_name='config', profile='some_profile')

        _get_response_mock.return_value = self._generic_response()

        @CredentialsEnvVarSubstituter('access_id', 'secret_key')
        def invoke_api():
            elasticbeanstalk.list_platform_versions()

        self.assertCorrectProfileWasUsed(_get_response_mock)

    def test_profile_is_found_in_config_file_but_profile_prefix_is_absent(self):
        """
            - `--profile` is not passed and is not set in config.yml
            - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` are found
            - `some_profile` profile is found in `$HOME/.aws/config` but profile prefix is absent
        """
        aws._profile = 'some_profile'
        self._generate_profile(credentials_file_name='config', profile='some_profile')

        with self.assertRaises(aws.InvalidProfileError) as context_manager:
            @CredentialsEnvVarSubstituter('access_id', 'secret_key')
            def invoke_api():
                elasticbeanstalk.list_platform_versions()

        self.assertEqual(
            'The config profile (some_profile) could not be found',
            str(context_manager.exception)
        )

# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"). You # may not use this file except in compliance with the License. A copy of # the License is located at # # http://aws.amazon.com/apache2.0/ # # or in the "license" file accompanying this file. This file is # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. Class hosts integration tests that interact with botocore to ensure     the right instance profile will be used. Order is defined in the following     link:          https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/eb-cli3-configuration.html#eb-cli3-credentials [{profile_prefix}{profile}] aws_access_key_id = {access_id} aws_secret_access_key = {secret_key} - `--profile` is not passed and is not set in config.yml             - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` are found - `--profile` is not passed and is not set in config.yml             - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` are not found             - attempt is made to communicate with IAM to assume role - `--profile` is not passed and is not set in config.yml             - environment variable `AWS_EB_PROFILE` found, but profile does not exist             - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` found but not used - `--profile` is not passed and is not set in config.yml             - environment variable `AWS_EB_PROFILE` found, profile exists in credentials file             - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` found but not used - `--profile` is not passed and is not set in config.yml             - environment variable `AWS_EB_PROFILE` found, profile exists in config file             - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` found but not used - `--profile` is not passed and is not set in config.yml             - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` are not found             - `default` profile is assumed and found in `$HOME/.aws/credentials` file - `--profile` is not passed and is not set in config.yml             - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` are not found             - `default` profile is assumed and found in `$HOME/.aws/config` file; profile is identified as `[default]` - `--profile` is not passed and is not set in config.yml             - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` are not found             - `default` profile is found in `$HOME/.aws/config` file; profile is identified as `[profile default]` - `--profile` is not passed and is not set in config.yml             - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` are found             - `some_profile` profile is not found in `$HOME/.aws/credentials` - `--profile` is not passed and is not set in config.yml             - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` are found             - `some_profile` profile is found in `$HOME/.aws/credentials` - `--profile` is not passed and is not set in config.yml             - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` are found             - `some_profile` profile is found in `$HOME/.aws/config` - `--profile` is not passed and is not set in config.yml             - environment variables `AWS_SECRET_ACCESS_KEY` and `AWS_ACCESS_KEY_ID` are found             - `some_profile` profile is found in `$HOME/.aws/config` but profile prefix is absent