예제 #1
0
 def setup(self):
     self.mock_conn = Mock()
     self.mock_client_config = Mock()
     type(self.mock_client_config).region_name = 'us-east-1'
     type(self.mock_conn)._client_config = self.mock_client_config
     self.cls = TrustedAdvisor({}, {})
     self.cls.conn = self.mock_conn
예제 #2
0
class TestCanRefreshCheck(object):
    def setup(self):
        self.mock_conn = Mock()
        self.mock_client_config = Mock()
        type(self.mock_client_config).region_name = 'us-east-1'
        type(self.mock_conn)._client_config = self.mock_client_config
        self.cls = TrustedAdvisor({}, {})
        self.cls.conn = self.mock_conn

    def test_true(self):
        tmp = self.mock_conn.describe_trusted_advisor_check_refresh_statuses
        chkstat = {
            'checkId': 'abc123',
            'status': 'none',
            'millisUntilNextRefreshable': 0
        }
        tmp.return_value = {'statuses': [chkstat]}
        with patch('%s.logger' % pbm, autospec=True) as mock_logger:
            res = self.cls._can_refresh_check('abc123')
        assert res is True
        assert tmp.mock_calls == [call(checkIds=['abc123'])]
        assert mock_logger.mock_calls == [
            call.debug('TA Check %s refresh status: %s', 'abc123', chkstat)
        ]

    def test_false(self):
        tmp = self.mock_conn.describe_trusted_advisor_check_refresh_statuses
        chkstat = {
            'checkId': 'abc123',
            'status': 'none',
            'millisUntilNextRefreshable': 123456
        }
        tmp.return_value = {'statuses': [chkstat]}
        with patch('%s.logger' % pbm, autospec=True) as mock_logger:
            res = self.cls._can_refresh_check('abc123')
        assert res is False
        assert tmp.mock_calls == [call(checkIds=['abc123'])]
        assert mock_logger.mock_calls == [
            call.debug('TA Check %s refresh status: %s', 'abc123', chkstat),
            call.warning(
                "Trusted Advisor check cannot be refreshed for "
                "another %d milliseconds; skipping refresh and "
                "getting check results now", 123456)
        ]

    def test_exception(self):
        tmp = self.mock_conn.describe_trusted_advisor_check_refresh_statuses
        chkstat = {'checkId': 'abc123', 'status': 'none'}
        tmp.return_value = {'statuses': [chkstat]}
        with patch('%s.logger' % pbm, autospec=True) as mock_logger:
            res = self.cls._can_refresh_check('abc123')
        assert res is True
        assert tmp.mock_calls == [call(checkIds=['abc123'])]
        assert mock_logger.mock_calls == [
            call.debug('TA Check %s refresh status: %s', 'abc123', chkstat),
            call.warning('Could not get refresh status for TA check %s',
                         'abc123',
                         exc_info=True)
        ]
 def test_connect(self):
     cls = TrustedAdvisor()
     mock_conn = Mock(spec_set=SupportConnection, name='mock_conn')
     with patch('awslimitchecker.trustedadvisor.boto.connect_support'
                '', autospec=True) as mock_connect:
         mock_connect.return_value = mock_conn
         cls.connect()
     assert cls.conn == mock_conn
     assert mock_connect.mock_calls == [call()]
예제 #4
0
 def test_connect(self):
     cls = TrustedAdvisor()
     mock_conn = Mock(spec_set=SupportConnection, name='mock_conn')
     with patch('awslimitchecker.trustedadvisor.boto.connect_support'
                '',
                autospec=True) as mock_connect:
         mock_connect.return_value = mock_conn
         cls.connect()
     assert cls.conn == mock_conn
     assert mock_connect.mock_calls == [call()]
 def test_connect_again(self):
     cls = TrustedAdvisor()
     mock_original_conn = Mock(spec_set=SupportConnection)
     cls.conn = mock_original_conn
     mock_conn = Mock(spec_set=SupportConnection)
     with patch('awslimitchecker.trustedadvisor.boto.connect_support'
                '') as mock_connect:
         mock_connect.return_value = mock_conn
         cls.connect()
     assert cls.conn == mock_original_conn
     assert mock_connect.mock_calls == []
예제 #6
0
 def test_connect_again(self):
     cls = TrustedAdvisor()
     mock_original_conn = Mock(spec_set=SupportConnection)
     cls.conn = mock_original_conn
     mock_conn = Mock(spec_set=SupportConnection)
     with patch('awslimitchecker.trustedadvisor.boto.connect_support'
                '') as mock_connect:
         mock_connect.return_value = mock_conn
         cls.connect()
     assert cls.conn == mock_original_conn
     assert mock_connect.mock_calls == []
예제 #7
0
    def setup(self):
        self.mock_conn = Mock(spec_set=SupportConnection)
        type(self.mock_conn).region = RegionInfo(name='us-east-1')
        self.cls = TrustedAdvisor()
        self.cls.conn = self.mock_conn

        self.mock_svc1 = Mock(spec_set=_AwsService)
        self.mock_svc2 = Mock(spec_set=_AwsService)
        self.services = {
            'SvcFoo': self.mock_svc1,
            'SvcBar': self.mock_svc2,
        }
예제 #8
0
    def setup(self):
        self.mock_conn = Mock()
        self.mock_client_config = Mock()
        type(self.mock_client_config).region_name = 'us-east-1'
        type(self.mock_conn)._client_config = self.mock_client_config
        self.cls = TrustedAdvisor()
        self.cls.conn = self.mock_conn

        self.mock_svc1 = Mock(spec_set=_AwsService)
        self.mock_svc2 = Mock(spec_set=_AwsService)
        self.services = {
            'SvcFoo': self.mock_svc1,
            'SvcBar': self.mock_svc2,
        }
    def test_boto_kwargs(self):
        mock_svc = Mock(spec_set=_AwsService)
        mock_svc.get_limits.return_value = {}
        boto_args = dict(region_name='myregion',
                         aws_access_key_id='myaccesskey',
                         aws_secret_access_key='mysecretkey',
                         aws_session_token='mytoken')

        cls = TrustedAdvisor(
            {'foo': mock_svc},
            boto_args,
            ta_refresh_mode=123,
            ta_refresh_timeout=456
        )
        assert cls.conn is None
        cls_boto_args = cls._boto3_connection_kwargs
        assert cls_boto_args.get('region_name') == 'us-east-1'
        assert cls_boto_args.get('aws_access_key_id') == 'myaccesskey'
        assert cls_boto_args.get('aws_secret_access_key') == 'mysecretkey'
        assert cls_boto_args.get('aws_session_token') == 'mytoken'
        assert cls.ta_region == 'myregion'
        assert cls.all_services == {'foo': mock_svc}
        assert cls.limits_updated is False
        assert cls.refresh_mode == 123
        assert cls.refresh_timeout == 456
예제 #10
0
 def test_connect_region(self):
     cls = TrustedAdvisor(account_id='foo', account_role='bar', region='re')
     mock_conn = Mock(spec_set=SupportConnection, name='mock_conn')
     mock_conn_via = Mock(spec_set=SupportConnection, name='mock_conn')
     with patch('awslimitchecker.trustedadvisor.TrustedAdvisor.connect_via'
                '') as mock_connect_via:
         mock_connect_via.return_value = mock_conn_via
         with patch('awslimitchecker.trustedadvisor.boto.connect_support'
                    '', autospec=True) as mock_connect:
             mock_connect.return_value = mock_conn
             cls.connect()
     assert cls.conn == mock_conn_via
     assert mock_connect.mock_calls == []
     assert mock_connect_via.mock_calls == [
         call(connect_to_region)
     ]
예제 #11
0
 def test_connect_region(self):
     cls = TrustedAdvisor(account_id='foo', account_role='bar', region='re')
     mock_conn = Mock(spec_set=SupportConnection, name='mock_conn')
     mock_conn_via = Mock(spec_set=SupportConnection, name='mock_conn')
     with patch('awslimitchecker.trustedadvisor.TrustedAdvisor.connect_via'
                '') as mock_connect_via:
         mock_connect_via.return_value = mock_conn_via
         with patch(
                 'awslimitchecker.trustedadvisor.boto.connect_support'
                 '',
                 autospec=True) as mock_connect:
             mock_connect.return_value = mock_conn
             cls.connect()
     assert cls.conn == mock_conn_via
     assert mock_connect.mock_calls == []
     assert mock_connect_via.mock_calls == [call(connect_to_region)]
예제 #12
0
class TestUpdateLimits(object):

    def setup(self):
        self.mock_conn = Mock()
        self.mock_client_config = Mock()
        type(self.mock_client_config).region_name = 'us-east-1'
        type(self.mock_conn)._client_config = self.mock_client_config
        self.cls = TrustedAdvisor({}, {})
        self.cls.conn = self.mock_conn

        self.mock_svc1 = Mock(spec_set=_AwsService)
        self.mock_svc2 = Mock(spec_set=_AwsService)
        self.services = {
            'SvcFoo': self.mock_svc1,
            'SvcBar': self.mock_svc2,
        }

    def test_simple(self):
        mock_results = Mock()
        with patch('%s.connect' % pb, autospec=True) as mock_connect:
            with patch('%s._poll' % pb, autospec=True) as mock_poll:
                with patch('%s._update_services' % pb,
                           autospec=True) as mock_update_services:
                    mock_poll.return_value = mock_results
                    self.cls.update_limits()
        assert mock_connect.mock_calls == [call(self.cls)]
        assert mock_poll.mock_calls == [call(self.cls)]
        assert mock_update_services.mock_calls == [
            call(self.cls, mock_results)
        ]

    def test_again(self):
        mock_results = Mock()
        self.cls.limits_updated = True
        with patch('%s.connect' % pb, autospec=True) as mock_connect:
            with patch('%s._poll' % pb, autospec=True) as mock_poll:
                with patch('%s._update_services' % pb,
                           autospec=True) as mock_update_services:
                    with patch('%s.logger' % pbm) as mock_logger:
                        mock_poll.return_value = mock_results
                        self.cls.update_limits()
        assert mock_connect.mock_calls == []
        assert mock_poll.mock_calls == []
        assert mock_update_services.mock_calls == []
        assert mock_logger.mock_calls == [
            call.debug('Already polled TA; skipping update')
        ]
예제 #13
0
 def test_init_sts(self):
     cls = TrustedAdvisor(account_id='aid', account_role='role', region='r')
     assert cls.conn is None
     assert cls.account_id == 'aid'
     assert cls.account_role == 'role'
     assert cls.region == 'us-east-1'
     assert cls.ta_region == 'r'
     assert cls.external_id is None
예제 #14
0
 def test_simple(self):
     cls = TrustedAdvisor({}, {})
     assert cls.conn is None
     assert cls._boto3_connection_kwargs == {'region_name': 'us-east-1'}
     assert cls.all_services == {}
     assert cls.limits_updated is False
     assert cls.refresh_mode is None
     assert cls.refresh_timeout is None
예제 #15
0
 def test_init(self):
     cls = TrustedAdvisor()
     assert cls.conn is None
     assert cls.account_id is None
     assert cls.account_role is None
     assert cls.region == 'us-east-1'
     assert cls.ta_region is None
     assert cls.external_id is None
    def setup(self):
        self.mock_conn = Mock(spec_set=SupportConnection)
        type(self.mock_conn).region = RegionInfo(name='us-east-1')
        self.cls = TrustedAdvisor()
        self.cls.conn = self.mock_conn

        self.mock_svc1 = Mock(spec_set=_AwsService)
        self.mock_svc2 = Mock(spec_set=_AwsService)
        self.services = {
            'SvcFoo': self.mock_svc1,
            'SvcBar': self.mock_svc2,
        }
예제 #17
0
 def test_init(self):
     cls = TrustedAdvisor({})
     assert cls.conn is None
     assert cls.account_id is None
     assert cls.account_role is None
     assert cls.region == 'us-east-1'
     assert cls.ta_region is None
     assert cls.external_id is None
     assert cls.mfa_serial_number is None
     assert cls.mfa_token is None
     assert cls.all_services == {}
     assert cls.limits_updated is False
예제 #18
0
 def test_init_sts_external_id(self):
     cls = TrustedAdvisor(account_id='aid',
                          account_role='role',
                          region='r',
                          external_id='myeid')
     assert cls.conn is None
     assert cls.account_id == 'aid'
     assert cls.account_role == 'role'
     assert cls.region == 'us-east-1'
     assert cls.ta_region == 'r'
     assert cls.external_id == 'myeid'
     assert cls.mfa_serial_number is None
     assert cls.mfa_token is None
    def setup(self):
        self.mock_conn = Mock()
        self.mock_client_config = Mock()
        type(self.mock_client_config).region_name = 'us-east-1'
        type(self.mock_conn)._client_config = self.mock_client_config
        self.cls = TrustedAdvisor({})
        self.cls.conn = self.mock_conn

        self.mock_svc1 = Mock(spec_set=_AwsService)
        self.mock_svc2 = Mock(spec_set=_AwsService)
        self.services = {
            'SvcFoo': self.mock_svc1,
            'SvcBar': self.mock_svc2,
        }
예제 #20
0
 def test_init_sts(self):
     mock_svc = Mock(spec_set=_AwsService)
     mock_svc.get_limits.return_value = {}
     cls = TrustedAdvisor({'foo': mock_svc},
                          account_id='aid',
                          account_role='role',
                          region='r')
     assert cls.conn is None
     assert cls.account_id == 'aid'
     assert cls.account_role == 'role'
     assert cls.region == 'us-east-1'
     assert cls.ta_region == 'r'
     assert cls.external_id is None
     assert cls.mfa_serial_number is None
     assert cls.mfa_token is None
     assert cls.all_services == {'foo': mock_svc}
     assert cls.limits_updated is False
class Test_TrustedAdvisor(object):

    def setup(self):
        self.mock_conn = Mock(spec_set=SupportConnection)
        type(self.mock_conn).region = RegionInfo(name='us-east-1')
        self.cls = TrustedAdvisor()
        self.cls.conn = self.mock_conn

        self.mock_svc1 = Mock(spec_set=_AwsService)
        self.mock_svc2 = Mock(spec_set=_AwsService)
        self.services = {
            'SvcFoo': self.mock_svc1,
            'SvcBar': self.mock_svc2,
        }

    def test_init(self):
        cls = TrustedAdvisor()
        assert cls.conn is None

    def test_connect(self):
        cls = TrustedAdvisor()
        mock_conn = Mock(spec_set=SupportConnection, name='mock_conn')
        with patch('awslimitchecker.trustedadvisor.boto.connect_support'
                   '', autospec=True) as mock_connect:
            mock_connect.return_value = mock_conn
            cls.connect()
        assert cls.conn == mock_conn
        assert mock_connect.mock_calls == [call()]

    def test_connect_again(self):
        cls = TrustedAdvisor()
        mock_original_conn = Mock(spec_set=SupportConnection)
        cls.conn = mock_original_conn
        mock_conn = Mock(spec_set=SupportConnection)
        with patch('awslimitchecker.trustedadvisor.boto.connect_support'
                   '') as mock_connect:
            mock_connect.return_value = mock_conn
            cls.connect()
        assert cls.conn == mock_original_conn
        assert mock_connect.mock_calls == []

    def test_update_limits(self):
        mock_results = Mock()
        with patch('%s.connect' % pb, autospec=True) as mock_connect:
            with patch('%s._poll' % pb, autospec=True) as mock_poll:
                with patch('%s._update_services' % pb,
                           autospec=True) as mock_update_services:
                    mock_poll.return_value = mock_results
                    self.cls.update_limits(self.services)
        assert mock_connect.mock_calls == [call(self.cls)]
        assert mock_poll.mock_calls == [call(self.cls)]
        assert mock_update_services.mock_calls == [
            call(self.cls, mock_results, self.services)
        ]

    def test_get_limit_check_id(self):
        api_resp = {
            'checks': [
                {
                    'category': 'performance',
                    'name': 'Service Limits',
                    'id': 'bar',
                    'metadata': [
                        'Region',
                        'Service',
                        'Limit Name',
                        'Limit Amount',
                        'Current Usage',
                        'Status'
                    ],
                },
                {
                    'category': 'fault_tolerance',
                    'name': 'ELB Cross-Zone Load Balancing',
                    'id': 'foo',
                },
            ]
        }
        self.mock_conn.describe_trusted_advisor_checks.return_value = api_resp
        res = self.cls._get_limit_check_id()
        assert res == (
            'bar',
            [
                'Region',
                'Service',
                'Limit Name',
                'Limit Amount',
                'Current Usage',
                'Status'
            ]
        )
        assert self.mock_conn.mock_calls == [
            call.describe_trusted_advisor_checks('en')
        ]

    def test_get_limit_check_id_none(self):
        api_resp = {
            'checks': [
                {
                    'category': 'performance',
                    'name': 'Something Else',
                    'id': 'bar',
                },
                {
                    'category': 'fault_tolerance',
                    'name': 'ELB Cross-Zone Load Balancing',
                    'id': 'foo',
                },
            ]
        }
        self.mock_conn.describe_trusted_advisor_checks.return_value = api_resp
        res = self.cls._get_limit_check_id()
        assert res == (None, None)
        assert self.mock_conn.mock_calls == [
            call.describe_trusted_advisor_checks('en')
        ]

    def test_get_limit_check_id_subscription_required(self):

        def se_api(language):
            status = 400
            reason = 'Bad Request'
            body = {
                'message': 'AWS Premium Support Subscription is required to '
                'use this service.',
                '__type': 'SubscriptionRequiredException'
            }
            raise JSONResponseError(status, reason, body)

        self.mock_conn.describe_trusted_advisor_checks.side_effect = se_api
        assert self.cls.have_ta is True
        with patch('awslimitchecker.trustedadvisor'
                   '.logger', autospec=True) as mock_logger:
            res = self.cls._get_limit_check_id()
        assert self.cls.have_ta is False
        assert res == (None, None)
        assert self.mock_conn.mock_calls == [
            call.describe_trusted_advisor_checks('en')
        ]
        assert mock_logger.mock_calls == [
            call.debug("Querying Trusted Advisor checks"),
            call.warning("Cannot check TrustedAdvisor: %s",
                         "AWS Premium Support "
                         "Subscription is required to use this service.")
        ]

    def test_get_limit_check_id_other_exception(self):

        def se_api(language):
            status = 400
            reason = 'foobar'
            body = {
                'message': 'other message',
                '__type': 'OtherException'
            }
            raise JSONResponseError(status, reason, body)

        self.mock_conn.describe_trusted_advisor_checks.side_effect = se_api
        with pytest.raises(BotoServerError) as excinfo:
            self.cls._get_limit_check_id()
        assert self.mock_conn.mock_calls == [
            call.describe_trusted_advisor_checks('en')
        ]
        assert excinfo.value.status == 400
        assert excinfo.value.reason == 'foobar'
        assert excinfo.value.body['__type'] == 'OtherException'

    def test_poll_id_none(self):
        tmp = self.mock_conn.describe_trusted_advisor_check_result
        with patch('%s._get_limit_check_id' % pb, autospec=True) as mock_id:
            mock_id.return_value = None
            self.cls._poll()
        assert tmp.mock_calls == []

    def test_poll(self):
        tmp = self.mock_conn.describe_trusted_advisor_check_result
        tmp.return_value = {
            'result': {
                'timestamp': '2015-06-15T20:27:42Z',
                'flaggedResources': [
                    {
                        'status': 'ok',
                        'resourceId': 'resid1',
                        'isSuppressed': False,
                        'region': 'us-west-2',
                        'metadata': [
                            'us-west-2',
                            'AutoScaling',
                            'Auto Scaling groups',
                            '20',
                            '2',
                            'Green'
                        ]
                    },
                    {
                        'status': 'ok',
                        'resourceId': 'resid2',
                        'isSuppressed': False,
                        'region': 'us-east-1',
                        'metadata': [
                            'us-east-1',
                            'AutoScaling',
                            'Launch configurations',
                            '20',
                            '18',
                            'Yellow'
                        ]
                    },
                    {
                        'status': 'ok',
                        'resourceId': 'resid3',
                        'isSuppressed': False,
                        'region': 'us-east-1',
                        'metadata': [
                            'us-west-2',
                            'AutoScaling',
                            'Auto Scaling groups',
                            '40',
                            '10',
                            'Green'
                        ]
                    },
                ]
            }
        }
        with patch('%s._get_limit_check_id' % pb, autospec=True) as mock_id:
            mock_id.return_value = (
                'foo',
                [
                    'Region',
                    'Service',
                    'Limit Name',
                    'Limit Amount',
                    'Current Usage',
                    'Status'
                ]
            )
            res = self.cls._poll()
        assert tmp.mock_calls == [call('foo')]
        assert mock_id.mock_calls == [call(self.cls)]
        assert res == {
            'AutoScaling': {
                'Launch configurations': 20,
                'Auto Scaling groups': 40,
            }
        }

    def test_poll_dont_have_ta(self):
        self.cls.have_ta = False
        tmp = self.mock_conn.describe_trusted_advisor_check_result
        with patch('%s._get_limit_check_id' % pb, autospec=True) as mock_id:
            with patch('awslimitchecker.trustedadvisor'
                       '.logger', autospec=True) as mock_logger:
                res = self.cls._poll()
        assert tmp.mock_calls == []
        assert mock_id.mock_calls == [
            call(self.cls)
        ]
        assert mock_logger.mock_calls == [
            call.info('Beginning TrustedAdvisor poll'),
            call.info('TrustedAdvisor.have_ta is False; not polling TA')
        ]
        assert res == {}

    def test_update_services(self):

        def se_set(lname, val):
            if lname == 'blam':
                raise ValueError("foo")

        mock_autoscale = Mock(spec_set=_AwsService)
        mock_ec2 = Mock(spec_set=_AwsService)
        mock_ec2._set_ta_limit.side_effect = se_set
        services = {
            'AutoScaling': mock_autoscale,
            'EC2': mock_ec2,
        }
        ta_results = {
            'AutoScaling': {
                'foo': 20,
                'bar': 40,
            },
            'EC2': {
                'baz': 5,
                'blam': 10,
            },
            'OtherService': {
                'blarg': 1,
            }
        }
        with patch('awslimitchecker.trustedadvisor'
                   '.logger', autospec=True) as mock_logger:
            self.cls._update_services(ta_results, services)
        assert mock_logger.mock_calls == [
            call.debug("Updating TA limits on all services"),
            call.info("TrustedAdvisor returned check results for unknown "
                      "limit '%s' (service %s)", 'blam', 'EC2'),
            call.info("TrustedAdvisor returned check results for unknown "
                      "service '%s'", 'OtherService'),
            call.info("Done updating TA limits on all services"),
        ]
        assert mock_autoscale.mock_calls == [
            call._set_ta_limit('bar', 40),
            call._set_ta_limit('foo', 20),
        ]
        assert mock_ec2.mock_calls == [
            call._set_ta_limit('baz', 5),
            call._set_ta_limit('blam', 10),
        ]
class Test_TrustedAdvisor(object):

    def setup(self):
        self.mock_conn = Mock()
        self.mock_client_config = Mock()
        type(self.mock_client_config).region_name = 'us-east-1'
        type(self.mock_conn)._client_config = self.mock_client_config
        self.cls = TrustedAdvisor({})
        self.cls.conn = self.mock_conn

        self.mock_svc1 = Mock(spec_set=_AwsService)
        self.mock_svc2 = Mock(spec_set=_AwsService)
        self.services = {
            'SvcFoo': self.mock_svc1,
            'SvcBar': self.mock_svc2,
        }

    def test_init(self):
        cls = TrustedAdvisor({})
        assert cls.conn is None
        assert cls.account_id is None
        assert cls.account_role is None
        assert cls.region == 'us-east-1'
        assert cls.ta_region is None
        assert cls.external_id is None
        assert cls.mfa_serial_number is None
        assert cls.mfa_token is None
        assert cls.all_services == {}
        assert cls.limits_updated is False

    def test_init_sts(self):
        mock_svc = Mock(spec_set=_AwsService)
        mock_svc.get_limits.return_value = {}
        cls = TrustedAdvisor(
            {'foo': mock_svc},
            account_id='aid', account_role='role', region='r'
        )
        assert cls.conn is None
        assert cls.account_id == 'aid'
        assert cls.account_role == 'role'
        assert cls.region == 'us-east-1'
        assert cls.ta_region == 'r'
        assert cls.external_id is None
        assert cls.mfa_serial_number is None
        assert cls.mfa_token is None
        assert cls.all_services == {'foo': mock_svc}
        assert cls.limits_updated is False

    def test_init_sts_external_id(self):
        cls = TrustedAdvisor(
            {}, account_id='aid', account_role='role', region='r',
            external_id='myeid'
        )
        assert cls.conn is None
        assert cls.account_id == 'aid'
        assert cls.account_role == 'role'
        assert cls.region == 'us-east-1'
        assert cls.ta_region == 'r'
        assert cls.external_id == 'myeid'
        assert cls.mfa_serial_number is None
        assert cls.mfa_token is None
        assert cls.limits_updated is False

    def test_update_limits(self):
        mock_results = Mock()
        with patch('%s.connect' % pb, autospec=True) as mock_connect:
            with patch('%s._poll' % pb, autospec=True) as mock_poll:
                with patch('%s._update_services' % pb,
                           autospec=True) as mock_update_services:
                    mock_poll.return_value = mock_results
                    self.cls.update_limits()
        assert mock_connect.mock_calls == [call(self.cls)]
        assert mock_poll.mock_calls == [call(self.cls)]
        assert mock_update_services.mock_calls == [
            call(self.cls, mock_results)
        ]

    def test_update_limits_again(self):
        mock_results = Mock()
        self.cls.limits_updated = True
        with patch('%s.connect' % pb, autospec=True) as mock_connect:
            with patch('%s._poll' % pb, autospec=True) as mock_poll:
                with patch('%s._update_services' % pb,
                           autospec=True) as mock_update_services:
                    with patch('%s.logger' % pbm) as mock_logger:
                        mock_poll.return_value = mock_results
                        self.cls.update_limits()
        assert mock_connect.mock_calls == []
        assert mock_poll.mock_calls == []
        assert mock_update_services.mock_calls == []
        assert mock_logger.mock_calls == [
            call.debug('Already polled TA; skipping update')
        ]

    def test_get_limit_check_id(self):
        api_resp = {
            'checks': [
                {
                    'category': 'performance',
                    'name': 'Service Limits',
                    'id': 'bar',
                    'metadata': [
                        'Region',
                        'Service',
                        'Limit Name',
                        'Limit Amount',
                        'Current Usage',
                        'Status'
                    ],
                },
                {
                    'category': 'fault_tolerance',
                    'name': 'ELB Cross-Zone Load Balancing',
                    'id': 'foo',
                },
            ]
        }
        self.mock_conn.describe_trusted_advisor_checks.return_value = api_resp
        res = self.cls._get_limit_check_id()
        assert res == (
            'bar',
            [
                'Region',
                'Service',
                'Limit Name',
                'Limit Amount',
                'Current Usage',
                'Status'
            ]
        )
        assert self.mock_conn.mock_calls == [
            call.describe_trusted_advisor_checks(language='en')
        ]

    def test_get_limit_check_id_none(self):
        api_resp = {
            'checks': [
                {
                    'category': 'performance',
                    'name': 'Something Else',
                    'id': 'bar',
                },
                {
                    'category': 'fault_tolerance',
                    'name': 'ELB Cross-Zone Load Balancing',
                    'id': 'foo',
                },
            ]
        }
        self.mock_conn.describe_trusted_advisor_checks.return_value = api_resp
        res = self.cls._get_limit_check_id()
        assert res == (None, None)
        assert self.mock_conn.mock_calls == [
            call.describe_trusted_advisor_checks(language='en')
        ]

    def test_get_limit_check_id_subscription_required(self):

        def se_api(language=None):
            response = {
                'ResponseMetadata': {
                    'HTTPStatusCode': 400,
                    'RequestId': '3cc9b2a8-c6e5-11e5-bc1d-b13dcea36176'
                },
                'Error': {
                    'Message': 'AWS Premium Support Subscription is required '
                               'to use this service.',
                    'Code': 'SubscriptionRequiredException'
                }
            }
            raise ClientError(response, 'operation')

        assert self.cls.have_ta is True
        self.mock_conn.describe_trusted_advisor_checks.side_effect = se_api
        with patch('awslimitchecker.trustedadvisor'
                   '.logger', autospec=True) as mock_logger:
            res = self.cls._get_limit_check_id()
        assert self.cls.have_ta is False
        assert res == (None, None)
        assert self.mock_conn.mock_calls == [
            call.describe_trusted_advisor_checks(language='en')
        ]
        assert mock_logger.mock_calls == [
            call.debug("Querying Trusted Advisor checks"),
            call.warning("Cannot check TrustedAdvisor: %s",
                         'AWS Premium Support Subscription is required to '
                         'use this service.')
        ]

    def test_get_limit_check_id_other_exception(self):

        def se_api(language=None):
            response = {
                'ResponseMetadata': {
                    'HTTPStatusCode': 400,
                    'RequestId': '3cc9b2a8-c6e5-11e5-bc1d-b13dcea36176'
                },
                'Error': {
                    'Message': 'foo',
                    'Code': 'SomeOtherException'
                }
            }
            raise ClientError(response, 'operation')

        self.mock_conn.describe_trusted_advisor_checks.side_effect = se_api
        with pytest.raises(ClientError) as excinfo:
            self.cls._get_limit_check_id()
        assert self.mock_conn.mock_calls == [
            call.describe_trusted_advisor_checks(language='en')
        ]
        assert excinfo.value.response['ResponseMetadata'][
                   'HTTPStatusCode'] == 400
        assert excinfo.value.response['Error']['Message'] == 'foo'
        assert excinfo.value.response['Error']['Code'] == 'SomeOtherException'

    def test_poll_id_none(self):
        tmp = self.mock_conn.describe_trusted_advisor_check_result
        with patch('%s._get_limit_check_id' % pb, autospec=True) as mock_id:
            mock_id.return_value = None
            res = self.cls._poll()
        assert tmp.mock_calls == []
        assert res is None

    def test_poll(self):
        tmp = self.mock_conn.describe_trusted_advisor_check_result
        poll_return_val = {
            'result': {
                'timestamp': '2015-06-15T20:27:42Z',
                'flaggedResources': [
                    {
                        'status': 'ok',
                        'resourceId': 'resid1',
                        'isSuppressed': False,
                        'region': 'us-west-2',
                        'metadata': [
                            'us-west-2',
                            'AutoScaling',
                            'Auto Scaling groups',
                            '20',
                            '2',
                            'Green'
                        ]
                    },
                    {
                        'status': 'ok',
                        'resourceId': 'resid2',
                        'isSuppressed': False,
                        'region': 'us-east-1',
                        'metadata': [
                            'us-east-1',
                            'AutoScaling',
                            'Launch configurations',
                            '20',
                            '18',
                            'Yellow'
                        ]
                    },
                    {
                        'status': 'ok',
                        'resourceId': 'resid3',
                        'isSuppressed': False,
                        'region': 'us-east-1',
                        'metadata': [
                            'us-west-2',
                            'AutoScaling',
                            'Auto Scaling groups',
                            '40',
                            '10',
                            'Green'
                        ]
                    },
                    {
                        'status': 'ok',
                        'resourceId': 'resid4',
                        'isSuppressed': False,
                        'metadata': [
                            '-',
                            'IAM',
                            'Users',
                            '5000',
                            '152',
                            'Green'
                        ]
                    },
                ]
            }
        }
        tmp.return_value = poll_return_val
        with patch('%s._get_limit_check_id' % pb, autospec=True) as mock_id:
            mock_id.return_value = (
                'foo',
                [
                    'Region',
                    'Service',
                    'Limit Name',
                    'Limit Amount',
                    'Current Usage',
                    'Status'
                ]
            )
            res = self.cls._poll()
        assert self.mock_conn.mock_calls == [
            call.describe_trusted_advisor_check_result(
                checkId='foo', language='en'
            )
        ]
        assert mock_id.mock_calls == [call(self.cls)]
        assert res == {
            'AutoScaling': {
                'Launch configurations': 20,
                'Auto Scaling groups': 40,
            },
            'IAM': {
                'Users': 5000
            }
        }

    def test_poll_region(self):
        tmp = self.mock_conn.describe_trusted_advisor_check_result
        self.cls.ta_region = 'us-west-2'
        poll_return_value = {
            'result': {
                'timestamp': '2015-06-15T20:27:42Z',
                'flaggedResources': [
                    {
                        'status': 'ok',
                        'resourceId': 'resid1',
                        'isSuppressed': False,
                        'region': 'us-west-2',
                        'metadata': [
                            'us-west-2',
                            'AutoScaling',
                            'Auto Scaling groups',
                            '20',
                            '2',
                            'Green'
                        ]
                    },
                    {
                        'status': 'ok',
                        'resourceId': 'resid2',
                        'isSuppressed': False,
                        'region': 'us-east-1',
                        'metadata': [
                            'us-east-1',
                            'AutoScaling',
                            'Launch configurations',
                            '20',
                            '18',
                            'Yellow'
                        ]
                    },
                    {
                        'status': 'ok',
                        'resourceId': 'resid3',
                        'isSuppressed': False,
                        'region': 'us-east-1',
                        'metadata': [
                            'us-west-2',
                            'AutoScaling',
                            'Auto Scaling groups',
                            '40',
                            '10',
                            'Green'
                        ]
                    },
                    {
                        'status': 'ok',
                        'resourceId': 'resid4',
                        'isSuppressed': False,
                        'metadata': [
                            '-',
                            'IAM',
                            'Users',
                            '5000',
                            '152',
                            'Green'
                        ]
                    },
                ]
            }
        }
        tmp.return_value = poll_return_value
        with patch('%s._get_limit_check_id' % pb, autospec=True) as mock_id:
            mock_id.return_value = (
                'foo',
                [
                    'Region',
                    'Service',
                    'Limit Name',
                    'Limit Amount',
                    'Current Usage',
                    'Status'
                ]
            )
            res = self.cls._poll()
        assert self.mock_conn.mock_calls == [
            call.describe_trusted_advisor_check_result(
                checkId='foo', language='en'
            )
        ]
        assert mock_id.mock_calls == [call(self.cls)]
        assert res == {
            'AutoScaling': {
                'Auto Scaling groups': 20,
            },
            'IAM': {
                'Users': 5000
            }
        }

    def test_poll_dont_have_ta(self):
        self.cls.have_ta = False
        tmp = self.mock_conn.describe_trusted_advisor_check_result
        with patch('%s._get_limit_check_id' % pb, autospec=True) as mock_id:
            with patch('awslimitchecker.trustedadvisor'
                       '.logger', autospec=True) as mock_logger:
                res = self.cls._poll()
        assert self.mock_conn.mock_calls == []
        assert tmp.mock_calls == []
        assert mock_id.mock_calls == [
            call(self.cls)
        ]
        assert mock_logger.mock_calls == [
            call.info('Beginning TrustedAdvisor poll'),
            call.info('TrustedAdvisor.have_ta is False; not polling TA')
        ]
        assert res == {}

    def test_update_services(self):
        mock_as_foo = Mock(spec_set=AwsLimit)
        mock_as_bar = Mock(spec_set=AwsLimit)
        mock_ec2_baz = Mock(spec_set=AwsLimit)
        mock_vpc = Mock(spec_set=AwsLimit)
        ta_services = {
            'AutoScaling': {
                'foo': mock_as_foo,
                'bar': mock_as_bar
            },
            'EC2': {
                'baz': mock_ec2_baz
            },
            'VPC': {
                'VPC Elastic IP addresses (EIPs)': mock_vpc
            },
        }
        ta_results = {
            'AutoScaling': {
                'foo': 20,
                'bar': 40,
            },
            'EC2': {
                'baz': 5,
                'blam': 10,
            },
            'OtherService': {
                'blarg': 1,
            },
            'VPC': {
                'VPC Elastic IP addresses (EIPs)': 11,
            }
        }
        with patch('awslimitchecker.trustedadvisor'
                   '.logger', autospec=True) as mock_logger:
            self.cls.ta_services = ta_services
            self.cls._update_services(ta_results)
        assert mock_logger.mock_calls == [
            call.debug("Updating TA limits on all services"),
            call.info("TrustedAdvisor returned check results for unknown "
                      "limit '%s' (service %s)", 'blam', 'EC2'),
            call.info("TrustedAdvisor returned check results for unknown "
                      "service '%s'", 'OtherService'),
            call.info("Done updating TA limits on all services"),
        ]
        assert mock_as_foo.mock_calls == [
            call._set_ta_limit(20)
        ]
        assert mock_as_bar.mock_calls == [
            call._set_ta_limit(40)
        ]
        assert mock_ec2_baz.mock_calls == [
            call._set_ta_limit(5)
        ]
        assert mock_vpc.mock_calls == [
            call._set_ta_limit(11)
        ]

    def test_make_ta_service_dict(self):
        mock_ec2 = Mock(spec_set=_AwsService)
        mock_el1 = Mock(spec_set=AwsLimit)
        type(mock_el1).name = 'el1'
        type(mock_el1).ta_service_name = 'EC2'
        type(mock_el1).ta_limit_name = 'el1'
        mock_el2 = Mock(spec_set=AwsLimit)
        type(mock_el2).name = 'el2'
        type(mock_el2).ta_service_name = 'Foo'
        type(mock_el2).ta_limit_name = 'el2'
        mock_ec2.get_limits.return_value = {
            'mock_el1': mock_el1,
            'mock_el2': mock_el2
        }

        mock_vpc = Mock(spec_set=_AwsService)
        mock_vl1 = Mock(spec_set=AwsLimit)
        type(mock_vl1).name = 'vl1'
        type(mock_vl1).ta_service_name = 'VPC'
        type(mock_vl1).ta_limit_name = 'other name'
        mock_vl2 = Mock(spec_set=AwsLimit)
        type(mock_vl2).name = 'vl2'
        type(mock_vl2).ta_service_name = 'Foo'
        type(mock_vl2).ta_limit_name = 'other limit'
        mock_vpc.get_limits.return_value = {
            'mock_vl1': mock_vl1,
            'mock_vl2': mock_vl2
        }

        svcs = {
            'EC2': mock_ec2,
            'VPC': mock_vpc
        }

        expected = {
            'EC2': {
                'el1': mock_el1
            },
            'VPC': {
                'other name': mock_vl1
            },
            'Foo': {
                'el2': mock_el2,
                'other limit': mock_vl2
            }
        }
        self.cls.all_services = svcs
        assert self.cls._make_ta_service_dict() == expected
예제 #23
0
class TestUpdateServices(object):
    def setup(self):
        self.mock_conn = Mock()
        self.mock_client_config = Mock()
        type(self.mock_client_config).region_name = 'us-east-1'
        type(self.mock_conn)._client_config = self.mock_client_config
        self.cls = TrustedAdvisor({}, {})
        self.cls.conn = self.mock_conn

        self.mock_svc1 = Mock(spec_set=_AwsService)
        self.mock_svc2 = Mock(spec_set=_AwsService)
        self.services = {
            'SvcFoo': self.mock_svc1,
            'SvcBar': self.mock_svc2,
        }

    def test_simple(self):
        mock_as_foo = Mock(spec_set=AwsLimit)
        mock_as_bar = Mock(spec_set=AwsLimit)
        mock_ec2_baz = Mock(spec_set=AwsLimit)
        mock_ec2_blarg = Mock(spec_set=AwsLimit)
        mock_vpc = Mock(spec_set=AwsLimit)
        ta_services = {
            'AutoScaling': {
                'foo': mock_as_foo,
                'bar': mock_as_bar
            },
            'EC2': {
                'baz': mock_ec2_baz,
                'blarg': mock_ec2_blarg
            },
            'VPC': {
                'VPC Elastic IP addresses (EIPs)': mock_vpc
            },
        }
        ta_results = {
            'AutoScaling': {
                'foo': 20,
                'bar': 40,
            },
            'EC2': {
                'baz': 5,
                'blam': 10,
                'blarg': 'Unlimited',
            },
            'OtherService': {
                'blarg': 1,
            },
            'VPC': {
                'VPC Elastic IP addresses (EIPs)': 11,
            }
        }
        with patch('awslimitchecker.trustedadvisor'
                   '.logger', autospec=True) as mock_logger:
            self.cls.ta_services = ta_services
            self.cls._update_services(ta_results)
        assert mock_logger.mock_calls == [
            call.debug("Updating TA limits on all services"),
            call.info(
                "TrustedAdvisor returned check results for unknown "
                "limit '%s' (service %s)", 'blam', 'EC2'),
            call.info(
                "TrustedAdvisor returned check results for unknown "
                "service '%s'", 'OtherService'),
            call.info("Done updating TA limits on all services"),
        ]
        assert mock_as_foo.mock_calls == [call._set_ta_limit(20)]
        assert mock_as_bar.mock_calls == [call._set_ta_limit(40)]
        assert mock_ec2_baz.mock_calls == [call._set_ta_limit(5)]
        assert mock_ec2_blarg.mock_calls == [call._set_ta_unlimited()]
        assert mock_vpc.mock_calls == [call._set_ta_limit(11)]
예제 #24
0
class TestMakeTAServiceDict(object):
    def setup(self):
        self.mock_conn = Mock()
        self.mock_client_config = Mock()
        type(self.mock_client_config).region_name = 'us-east-1'
        type(self.mock_conn)._client_config = self.mock_client_config
        self.cls = TrustedAdvisor({}, {})
        self.cls.conn = self.mock_conn

        self.mock_svc1 = Mock(spec_set=_AwsService)
        self.mock_svc2 = Mock(spec_set=_AwsService)
        self.services = {
            'SvcFoo': self.mock_svc1,
            'SvcBar': self.mock_svc2,
        }

    def test_simple(self):
        mock_ec2 = Mock(spec_set=_AwsService)
        mock_el1 = Mock(spec_set=AwsLimit)
        type(mock_el1).name = 'el1'
        type(mock_el1).ta_service_name = 'EC2'
        type(mock_el1).ta_limit_name = 'el1'
        mock_el2 = Mock(spec_set=AwsLimit)
        type(mock_el2).name = 'el2'
        type(mock_el2).ta_service_name = 'Foo'
        type(mock_el2).ta_limit_name = 'el2'
        mock_ec2.get_limits.return_value = {
            'mock_el1': mock_el1,
            'mock_el2': mock_el2
        }

        mock_vpc = Mock(spec_set=_AwsService)
        mock_vl1 = Mock(spec_set=AwsLimit)
        type(mock_vl1).name = 'vl1'
        type(mock_vl1).ta_service_name = 'VPC'
        type(mock_vl1).ta_limit_name = 'other name'
        mock_vl2 = Mock(spec_set=AwsLimit)
        type(mock_vl2).name = 'vl2'
        type(mock_vl2).ta_service_name = 'Foo'
        type(mock_vl2).ta_limit_name = 'other limit'
        mock_vpc.get_limits.return_value = {
            'mock_vl1': mock_vl1,
            'mock_vl2': mock_vl2
        }

        svcs = {'EC2': mock_ec2, 'VPC': mock_vpc}

        expected = {
            'EC2': {
                'el1': mock_el1
            },
            'VPC': {
                'other name': mock_vl1
            },
            'Foo': {
                'el2': mock_el2,
                'other limit': mock_vl2
            }
        }
        self.cls.all_services = svcs
        assert self.cls._make_ta_service_dict() == expected
예제 #25
0
class TestGetLimitCheckId(object):
    def setup(self):
        self.mock_conn = Mock()
        self.mock_client_config = Mock()
        type(self.mock_client_config).region_name = 'us-east-1'
        type(self.mock_conn)._client_config = self.mock_client_config
        self.cls = TrustedAdvisor({}, {})
        self.cls.conn = self.mock_conn

        self.mock_svc1 = Mock(spec_set=_AwsService)
        self.mock_svc2 = Mock(spec_set=_AwsService)
        self.services = {
            'SvcFoo': self.mock_svc1,
            'SvcBar': self.mock_svc2,
        }

    def test_simple(self):
        api_resp = {
            'checks': [
                {
                    'category':
                    'performance',
                    'name':
                    'Service Limits',
                    'id':
                    'bar',
                    'metadata': [
                        'Region', 'Service', 'Limit Name', 'Limit Amount',
                        'Current Usage', 'Status'
                    ],
                },
                {
                    'category': 'fault_tolerance',
                    'name': 'ELB Cross-Zone Load Balancing',
                    'id': 'foo',
                },
            ]
        }
        self.mock_conn.describe_trusted_advisor_checks.return_value = api_resp
        res = self.cls._get_limit_check_id()
        assert res == ('bar', [
            'Region', 'Service', 'Limit Name', 'Limit Amount', 'Current Usage',
            'Status'
        ])
        assert self.mock_conn.mock_calls == [
            call.describe_trusted_advisor_checks(language='en')
        ]

    def test_none(self):
        api_resp = {
            'checks': [
                {
                    'category': 'performance',
                    'name': 'Something Else',
                    'id': 'bar',
                },
                {
                    'category': 'fault_tolerance',
                    'name': 'ELB Cross-Zone Load Balancing',
                    'id': 'foo',
                },
            ]
        }
        self.mock_conn.describe_trusted_advisor_checks.return_value = api_resp
        res = self.cls._get_limit_check_id()
        assert res == (None, None)
        assert self.mock_conn.mock_calls == [
            call.describe_trusted_advisor_checks(language='en')
        ]

    def test_subscription_required(self):
        def se_api(language=None):
            response = {
                'ResponseMetadata': {
                    'HTTPStatusCode': 400,
                    'RequestId': '3cc9b2a8-c6e5-11e5-bc1d-b13dcea36176'
                },
                'Error': {
                    'Message': 'AWS Premium Support Subscription is required '
                    'to use this service.',
                    'Code': 'SubscriptionRequiredException'
                }
            }
            raise ClientError(response, 'operation')

        assert self.cls.have_ta is True
        self.mock_conn.describe_trusted_advisor_checks.side_effect = se_api
        with patch('awslimitchecker.trustedadvisor'
                   '.logger', autospec=True) as mock_logger:
            res = self.cls._get_limit_check_id()
        assert self.cls.have_ta is False
        assert res == (None, None)
        assert self.mock_conn.mock_calls == [
            call.describe_trusted_advisor_checks(language='en')
        ]
        assert mock_logger.mock_calls == [
            call.debug("Querying Trusted Advisor checks"),
            call.warning(
                "Cannot check TrustedAdvisor: %s",
                'AWS Premium Support Subscription is required to '
                'use this service.')
        ]

    def test_other_exception(self):
        def se_api(language=None):
            response = {
                'ResponseMetadata': {
                    'HTTPStatusCode': 400,
                    'RequestId': '3cc9b2a8-c6e5-11e5-bc1d-b13dcea36176'
                },
                'Error': {
                    'Message': 'foo',
                    'Code': 'SomeOtherException'
                }
            }
            raise ClientError(response, 'operation')

        self.mock_conn.describe_trusted_advisor_checks.side_effect = se_api
        with pytest.raises(ClientError) as excinfo:
            self.cls._get_limit_check_id()
        assert self.mock_conn.mock_calls == [
            call.describe_trusted_advisor_checks(language='en')
        ]
        assert excinfo.value.response['ResponseMetadata'][
            'HTTPStatusCode'] == 400
        assert excinfo.value.response['Error']['Message'] == 'foo'
        assert excinfo.value.response['Error']['Code'] == 'SomeOtherException'
예제 #26
0
class Test_TrustedAdvisor(object):
    def setup(self):
        self.mock_conn = Mock(spec_set=SupportConnection)
        type(self.mock_conn).region = RegionInfo(name='us-east-1')
        self.cls = TrustedAdvisor()
        self.cls.conn = self.mock_conn

        self.mock_svc1 = Mock(spec_set=_AwsService)
        self.mock_svc2 = Mock(spec_set=_AwsService)
        self.services = {
            'SvcFoo': self.mock_svc1,
            'SvcBar': self.mock_svc2,
        }

    def test_init(self):
        cls = TrustedAdvisor()
        assert cls.conn is None
        assert cls.account_id is None
        assert cls.account_role is None
        assert cls.region == 'us-east-1'
        assert cls.ta_region is None
        assert cls.external_id is None

    def test_init_sts(self):
        cls = TrustedAdvisor(account_id='aid', account_role='role', region='r')
        assert cls.conn is None
        assert cls.account_id == 'aid'
        assert cls.account_role == 'role'
        assert cls.region == 'us-east-1'
        assert cls.ta_region == 'r'
        assert cls.external_id is None

    def test_init_sts_external_id(self):
        cls = TrustedAdvisor(account_id='aid',
                             account_role='role',
                             region='r',
                             external_id='myeid')
        assert cls.conn is None
        assert cls.account_id == 'aid'
        assert cls.account_role == 'role'
        assert cls.region == 'us-east-1'
        assert cls.ta_region == 'r'
        assert cls.external_id == 'myeid'

    def test_connect(self):
        cls = TrustedAdvisor()
        mock_conn = Mock(spec_set=SupportConnection, name='mock_conn')
        with patch('awslimitchecker.trustedadvisor.boto.connect_support'
                   '',
                   autospec=True) as mock_connect:
            mock_connect.return_value = mock_conn
            cls.connect()
        assert cls.conn == mock_conn
        assert mock_connect.mock_calls == [call()]

    def test_connect_region(self):
        cls = TrustedAdvisor(account_id='foo', account_role='bar', region='re')
        mock_conn = Mock(spec_set=SupportConnection, name='mock_conn')
        mock_conn_via = Mock(spec_set=SupportConnection, name='mock_conn')
        with patch('awslimitchecker.trustedadvisor.TrustedAdvisor.connect_via'
                   '') as mock_connect_via:
            mock_connect_via.return_value = mock_conn_via
            with patch(
                    'awslimitchecker.trustedadvisor.boto.connect_support'
                    '',
                    autospec=True) as mock_connect:
                mock_connect.return_value = mock_conn
                cls.connect()
        assert cls.conn == mock_conn_via
        assert mock_connect.mock_calls == []
        assert mock_connect_via.mock_calls == [call(connect_to_region)]

    def test_connect_again(self):
        cls = TrustedAdvisor()
        mock_original_conn = Mock(spec_set=SupportConnection)
        cls.conn = mock_original_conn
        mock_conn = Mock(spec_set=SupportConnection)
        with patch('awslimitchecker.trustedadvisor.boto.connect_support'
                   '') as mock_connect:
            mock_connect.return_value = mock_conn
            cls.connect()
        assert cls.conn == mock_original_conn
        assert mock_connect.mock_calls == []

    def test_update_limits(self):
        mock_results = Mock()
        with patch('%s.connect' % pb, autospec=True) as mock_connect:
            with patch('%s._poll' % pb, autospec=True) as mock_poll:
                with patch('%s._update_services' % pb,
                           autospec=True) as mock_update_services:
                    mock_poll.return_value = mock_results
                    self.cls.update_limits(self.services)
        assert mock_connect.mock_calls == [call(self.cls)]
        assert mock_poll.mock_calls == [call(self.cls)]
        assert mock_update_services.mock_calls == [
            call(self.cls, mock_results, self.services)
        ]

    def test_get_limit_check_id(self):
        api_resp = {
            'checks': [
                {
                    'category':
                    'performance',
                    'name':
                    'Service Limits',
                    'id':
                    'bar',
                    'metadata': [
                        'Region', 'Service', 'Limit Name', 'Limit Amount',
                        'Current Usage', 'Status'
                    ],
                },
                {
                    'category': 'fault_tolerance',
                    'name': 'ELB Cross-Zone Load Balancing',
                    'id': 'foo',
                },
            ]
        }
        with patch('%s.boto_query_wrapper' % pbm) as mock_wrapper:
            mock_wrapper.return_value = api_resp
            res = self.cls._get_limit_check_id()
        assert res == ('bar', [
            'Region', 'Service', 'Limit Name', 'Limit Amount', 'Current Usage',
            'Status'
        ])
        assert self.mock_conn.mock_calls == []
        assert mock_wrapper.mock_calls == [
            call(self.mock_conn.describe_trusted_advisor_checks, 'en')
        ]

    def test_get_limit_check_id_none(self):
        api_resp = {
            'checks': [
                {
                    'category': 'performance',
                    'name': 'Something Else',
                    'id': 'bar',
                },
                {
                    'category': 'fault_tolerance',
                    'name': 'ELB Cross-Zone Load Balancing',
                    'id': 'foo',
                },
            ]
        }
        with patch('%s.boto_query_wrapper' % pbm) as mock_wrapper:
            mock_wrapper.return_value = api_resp
            res = self.cls._get_limit_check_id()
        assert res == (None, None)
        assert self.mock_conn.mock_calls == []
        assert mock_wrapper.mock_calls == [
            call(self.mock_conn.describe_trusted_advisor_checks, 'en')
        ]

    def test_get_limit_check_id_subscription_required(self):
        def se_api(foo, language):
            status = 400
            reason = 'Bad Request'
            body = {
                'message': 'AWS Premium Support Subscription is required to '
                'use this service.',
                '__type': 'SubscriptionRequiredException'
            }
            raise JSONResponseError(status, reason, body)

        assert self.cls.have_ta is True
        with patch('awslimitchecker.trustedadvisor'
                   '.logger', autospec=True) as mock_logger:
            with patch('%s.boto_query_wrapper' % pbm) as mock_wrapper:
                mock_wrapper.side_effect = se_api
                res = self.cls._get_limit_check_id()
        assert self.cls.have_ta is False
        assert res == (None, None)
        assert self.mock_conn.mock_calls == []
        assert mock_wrapper.mock_calls == [
            call(self.mock_conn.describe_trusted_advisor_checks, 'en')
        ]
        assert mock_logger.mock_calls == [
            call.debug("Querying Trusted Advisor checks"),
            call.warning(
                "Cannot check TrustedAdvisor: %s", "AWS Premium Support "
                "Subscription is required to use this service.")
        ]

    def test_get_limit_check_id_other_exception(self):
        def se_api(foo, language):
            status = 400
            reason = 'foobar'
            body = {'message': 'other message', '__type': 'OtherException'}
            raise JSONResponseError(status, reason, body)

        with pytest.raises(BotoServerError) as excinfo:
            with patch('%s.boto_query_wrapper' % pbm) as mock_wrapper:
                mock_wrapper.side_effect = se_api
                self.cls._get_limit_check_id()
        assert self.mock_conn.mock_calls == []
        assert mock_wrapper.mock_calls == [
            call(self.mock_conn.describe_trusted_advisor_checks, 'en')
        ]
        assert excinfo.value.status == 400
        assert excinfo.value.reason == 'foobar'
        assert excinfo.value.body['__type'] == 'OtherException'

    def test_poll_id_none(self):
        tmp = self.mock_conn.describe_trusted_advisor_check_result
        with patch('%s._get_limit_check_id' % pb, autospec=True) as mock_id:
            with patch('%s.boto_query_wrapper' % pbm) as mock_wrapper:
                mock_id.return_value = None
                res = self.cls._poll()
        assert tmp.mock_calls == []
        assert mock_wrapper.mock_calls == []
        assert res is None

    def test_poll(self):
        tmp = self.mock_conn.describe_trusted_advisor_check_result
        poll_return_val = {
            'result': {
                'timestamp':
                '2015-06-15T20:27:42Z',
                'flaggedResources': [
                    {
                        'status':
                        'ok',
                        'resourceId':
                        'resid1',
                        'isSuppressed':
                        False,
                        'region':
                        'us-west-2',
                        'metadata': [
                            'us-west-2', 'AutoScaling', 'Auto Scaling groups',
                            '20', '2', 'Green'
                        ]
                    },
                    {
                        'status':
                        'ok',
                        'resourceId':
                        'resid2',
                        'isSuppressed':
                        False,
                        'region':
                        'us-east-1',
                        'metadata': [
                            'us-east-1', 'AutoScaling',
                            'Launch configurations', '20', '18', 'Yellow'
                        ]
                    },
                    {
                        'status':
                        'ok',
                        'resourceId':
                        'resid3',
                        'isSuppressed':
                        False,
                        'region':
                        'us-east-1',
                        'metadata': [
                            'us-west-2', 'AutoScaling', 'Auto Scaling groups',
                            '40', '10', 'Green'
                        ]
                    },
                ]
            }
        }
        with patch('%s._get_limit_check_id' % pb, autospec=True) as mock_id:
            with patch('%s.boto_query_wrapper' % pbm) as mock_wrapper:
                mock_id.return_value = ('foo', [
                    'Region', 'Service', 'Limit Name', 'Limit Amount',
                    'Current Usage', 'Status'
                ])
                mock_wrapper.return_value = poll_return_val
                res = self.cls._poll()
        assert tmp.mock_calls == []
        assert mock_wrapper.mock_calls == [call(tmp, 'foo')]
        assert mock_id.mock_calls == [call(self.cls)]
        assert res == {
            'AutoScaling': {
                'Launch configurations': 20,
                'Auto Scaling groups': 40,
            }
        }

    def test_poll_region(self):
        tmp = self.mock_conn.describe_trusted_advisor_check_result
        self.cls.ta_region = 'us-west-2'
        poll_return_value = {
            'result': {
                'timestamp':
                '2015-06-15T20:27:42Z',
                'flaggedResources': [
                    {
                        'status':
                        'ok',
                        'resourceId':
                        'resid1',
                        'isSuppressed':
                        False,
                        'region':
                        'us-west-2',
                        'metadata': [
                            'us-west-2', 'AutoScaling', 'Auto Scaling groups',
                            '20', '2', 'Green'
                        ]
                    },
                    {
                        'status':
                        'ok',
                        'resourceId':
                        'resid2',
                        'isSuppressed':
                        False,
                        'region':
                        'us-east-1',
                        'metadata': [
                            'us-east-1', 'AutoScaling',
                            'Launch configurations', '20', '18', 'Yellow'
                        ]
                    },
                    {
                        'status':
                        'ok',
                        'resourceId':
                        'resid3',
                        'isSuppressed':
                        False,
                        'region':
                        'us-east-1',
                        'metadata': [
                            'us-west-2', 'AutoScaling', 'Auto Scaling groups',
                            '40', '10', 'Green'
                        ]
                    },
                ]
            }
        }
        with patch('%s._get_limit_check_id' % pb, autospec=True) as mock_id:
            with patch('%s.boto_query_wrapper' % pbm) as mock_wrapper:
                mock_id.return_value = ('foo', [
                    'Region', 'Service', 'Limit Name', 'Limit Amount',
                    'Current Usage', 'Status'
                ])
                mock_wrapper.return_value = poll_return_value
                res = self.cls._poll()
        assert tmp.mock_calls == []
        assert mock_wrapper.mock_calls == [call(tmp, 'foo')]
        assert mock_id.mock_calls == [call(self.cls)]
        assert res == {
            'AutoScaling': {
                'Auto Scaling groups': 20,
            }
        }

    def test_poll_dont_have_ta(self):
        self.cls.have_ta = False
        tmp = self.mock_conn.describe_trusted_advisor_check_result
        with patch('%s._get_limit_check_id' % pb, autospec=True) as mock_id:
            with patch('%s.boto_query_wrapper' % pbm) as mock_wrapper:
                with patch('awslimitchecker.trustedadvisor'
                           '.logger',
                           autospec=True) as mock_logger:
                    res = self.cls._poll()
        assert mock_wrapper.mock_calls == []
        assert tmp.mock_calls == []
        assert mock_id.mock_calls == [call(self.cls)]
        assert mock_logger.mock_calls == [
            call.info('Beginning TrustedAdvisor poll'),
            call.info('TrustedAdvisor.have_ta is False; not polling TA')
        ]
        assert res == {}

    def test_update_services(self):
        def se_set(lname, val):
            if lname == 'blam':
                raise ValueError("foo")

        mock_autoscale = Mock(spec_set=_AwsService)
        mock_ec2 = Mock(spec_set=_AwsService)
        mock_ec2._set_ta_limit.side_effect = se_set
        mock_vpc = Mock(spec_set=_AwsService)
        services = {
            'AutoScaling': mock_autoscale,
            'EC2': mock_ec2,
            'VPC': mock_vpc,
        }
        ta_results = {
            'AutoScaling': {
                'foo': 20,
                'bar': 40,
            },
            'EC2': {
                'baz': 5,
                'blam': 10,
            },
            'OtherService': {
                'blarg': 1,
            },
            'VPC': {
                'VPC Elastic IP addresses (EIPs)': 11,
            }
        }
        with patch('awslimitchecker.trustedadvisor'
                   '.logger', autospec=True) as mock_logger:
            self.cls._update_services(ta_results, services)
        assert mock_logger.mock_calls == [
            call.debug("Updating TA limits on all services"),
            call.info(
                "TrustedAdvisor returned check results for unknown "
                "limit '%s' (service %s)", 'blam', 'EC2'),
            call.info(
                "TrustedAdvisor returned check results for unknown "
                "service '%s'", 'OtherService'),
            call.info("Done updating TA limits on all services"),
        ]
        assert mock_autoscale.mock_calls == [
            call._set_ta_limit('bar', 40),
            call._set_ta_limit('foo', 20),
        ]
        assert mock_ec2.mock_calls == [
            call._set_ta_limit('baz', 5),
            call._set_ta_limit('blam', 10),
            call._set_ta_limit('VPC Elastic IP addresses (EIPs)', 11)
        ]
예제 #27
0
class TestPoll(object):
    def setup(self):
        self.mock_conn = Mock()
        self.mock_client_config = Mock()
        type(self.mock_client_config).region_name = 'us-east-1'
        type(self.mock_conn)._client_config = self.mock_client_config
        self.cls = TrustedAdvisor({}, {})
        self.cls.conn = self.mock_conn

        self.mock_svc1 = Mock(spec_set=_AwsService)
        self.mock_svc2 = Mock(spec_set=_AwsService)
        self.services = {
            'SvcFoo': self.mock_svc1,
            'SvcBar': self.mock_svc2,
        }

    def test_none(self):
        tmp = self.mock_conn.describe_trusted_advisor_check_result
        with patch('%s._get_limit_check_id' % pb, autospec=True) as mock_id:
            mock_id.return_value = None
            res = self.cls._poll()
        assert tmp.mock_calls == []
        assert res is None

    def test_basic(self):
        poll_return_val = {
            'result': {
                'timestamp':
                '2015-06-15T20:27:42Z',
                'flaggedResources': [
                    {
                        'status':
                        'ok',
                        'resourceId':
                        'resid1',
                        'isSuppressed':
                        False,
                        'region':
                        'us-west-2',
                        'metadata': [
                            'us-west-2', 'AutoScaling', 'Auto Scaling groups',
                            '20', '2', 'Green'
                        ]
                    },
                    {
                        'status':
                        'ok',
                        'resourceId':
                        'resid1',
                        'isSuppressed':
                        False,
                        'region':
                        'us-east-1',
                        'metadata': [
                            'us-east-1', 'EC2',
                            'On-Demand instances - t2.micro', 'Unlimited', '2',
                            'Green'
                        ]
                    },
                    {
                        'status':
                        'ok',
                        'resourceId':
                        'resid1',
                        'isSuppressed':
                        False,
                        'region':
                        'us-east-1',
                        'metadata': [
                            'us-east-1', 'EC2',
                            'On-Demand instances - t2.small', 'error', '2',
                            'Green'
                        ]
                    },
                    {
                        'status':
                        'ok',
                        'resourceId':
                        'resid2',
                        'isSuppressed':
                        False,
                        'region':
                        'us-east-1',
                        'metadata': [
                            'us-east-1', 'AutoScaling',
                            'Launch configurations', '20', '18', 'Yellow'
                        ]
                    },
                    {
                        'status':
                        'ok',
                        'resourceId':
                        'resid3',
                        'isSuppressed':
                        False,
                        'region':
                        'us-east-1',
                        'metadata': [
                            'us-west-2', 'AutoScaling', 'Auto Scaling groups',
                            '40', '10', 'Green'
                        ]
                    },
                    {
                        'status': 'ok',
                        'resourceId': 'resid4',
                        'isSuppressed': False,
                        'metadata':
                        ['-', 'IAM', 'Users', '5000', '152', 'Green']
                    },
                ]
            }
        }
        with patch('%s._get_limit_check_id' % pb, autospec=True) as mock_id:
            with patch('%s._get_refreshed_check_result' % pb,
                       autospec=True) as mock_hr:
                mock_hr.return_value = poll_return_val
                mock_id.return_value = ('foo', [
                    'Region', 'Service', 'Limit Name', 'Limit Amount',
                    'Current Usage', 'Status'
                ])
                res = self.cls._poll()
        assert self.mock_conn.mock_calls == []
        assert mock_id.mock_calls == [call(self.cls)]
        assert mock_hr.mock_calls == [call(self.cls, 'foo')]
        assert res == {
            'AutoScaling': {
                'Launch configurations': 20,
                'Auto Scaling groups': 40,
            },
            'EC2': {
                'On-Demand instances - t2.micro': 'Unlimited'
            },
            'IAM': {
                'Users': 5000
            }
        }

    def test_no_timestamp(self):
        poll_return_val = {
            'result': {
                'flaggedResources': [
                    {
                        'status':
                        'ok',
                        'resourceId':
                        'resid1',
                        'isSuppressed':
                        False,
                        'region':
                        'us-west-2',
                        'metadata': [
                            'us-west-2', 'AutoScaling', 'Auto Scaling groups',
                            '20', '2', 'Green'
                        ]
                    },
                    {
                        'status':
                        'ok',
                        'resourceId':
                        'resid1',
                        'isSuppressed':
                        False,
                        'region':
                        'us-east-1',
                        'metadata': [
                            'us-east-1', 'EC2',
                            'On-Demand instances - t2.micro', 'Unlimited', '2',
                            'Green'
                        ]
                    },
                    {
                        'status':
                        'ok',
                        'resourceId':
                        'resid1',
                        'isSuppressed':
                        False,
                        'region':
                        'us-east-1',
                        'metadata': [
                            'us-east-1', 'EC2',
                            'On-Demand instances - t2.small', 'error', '2',
                            'Green'
                        ]
                    },
                    {
                        'status':
                        'ok',
                        'resourceId':
                        'resid2',
                        'isSuppressed':
                        False,
                        'region':
                        'us-east-1',
                        'metadata': [
                            'us-east-1', 'AutoScaling',
                            'Launch configurations', '20', '18', 'Yellow'
                        ]
                    },
                    {
                        'status':
                        'ok',
                        'resourceId':
                        'resid3',
                        'isSuppressed':
                        False,
                        'region':
                        'us-east-1',
                        'metadata': [
                            'us-west-2', 'AutoScaling', 'Auto Scaling groups',
                            '40', '10', 'Green'
                        ]
                    },
                    {
                        'status': 'ok',
                        'resourceId': 'resid4',
                        'isSuppressed': False,
                        'metadata':
                        ['-', 'IAM', 'Users', '5000', '152', 'Green']
                    },
                ]
            }
        }
        with patch('%s._get_limit_check_id' % pb, autospec=True) as mock_id:
            with patch('%s._get_refreshed_check_result' % pb,
                       autospec=True) as mock_hr:
                mock_hr.return_value = poll_return_val
                mock_id.return_value = ('foo', [
                    'Region', 'Service', 'Limit Name', 'Limit Amount',
                    'Current Usage', 'Status'
                ])
                res = self.cls._poll()
        assert self.mock_conn.mock_calls == []
        assert mock_id.mock_calls == [call(self.cls)]
        assert mock_hr.mock_calls == [call(self.cls, 'foo')]
        assert res == {
            'AutoScaling': {
                'Launch configurations': 20,
                'Auto Scaling groups': 40,
            },
            'EC2': {
                'On-Demand instances - t2.micro': 'Unlimited'
            },
            'IAM': {
                'Users': 5000
            }
        }

    def test_region(self):
        self.cls.ta_region = 'us-west-2'
        poll_return_value = {
            'result': {
                'timestamp':
                '2015-06-15T20:27:42Z',
                'flaggedResources': [
                    {
                        'status':
                        'ok',
                        'resourceId':
                        'resid1',
                        'isSuppressed':
                        False,
                        'region':
                        'us-west-2',
                        'metadata': [
                            'us-west-2', 'AutoScaling', 'Auto Scaling groups',
                            '20', '2', 'Green'
                        ]
                    },
                    {
                        'status':
                        'ok',
                        'resourceId':
                        'resid2',
                        'isSuppressed':
                        False,
                        'region':
                        'us-east-1',
                        'metadata': [
                            'us-east-1', 'AutoScaling',
                            'Launch configurations', '20', '18', 'Yellow'
                        ]
                    },
                    {
                        'status':
                        'ok',
                        'resourceId':
                        'resid3',
                        'isSuppressed':
                        False,
                        'region':
                        'us-east-1',
                        'metadata': [
                            'us-west-2', 'AutoScaling', 'Auto Scaling groups',
                            '40', '10', 'Green'
                        ]
                    },
                    {
                        'status': 'ok',
                        'resourceId': 'resid4',
                        'isSuppressed': False,
                        'metadata':
                        ['-', 'IAM', 'Users', '5000', '152', 'Green']
                    },
                ]
            }
        }
        with patch('%s._get_limit_check_id' % pb, autospec=True) as mock_id:
            with patch('%s._get_refreshed_check_result' % pb,
                       autospec=True) as mock_hr:
                mock_hr.return_value = poll_return_value
                mock_id.return_value = ('foo', [
                    'Region', 'Service', 'Limit Name', 'Limit Amount',
                    'Current Usage', 'Status'
                ])
                res = self.cls._poll()
        assert self.mock_conn.mock_calls == []
        assert mock_id.mock_calls == [call(self.cls)]
        assert mock_hr.mock_calls == [call(self.cls, 'foo')]
        assert res == {
            'AutoScaling': {
                'Auto Scaling groups': 20,
            },
            'IAM': {
                'Users': 5000
            }
        }

    def test_dont_have_ta(self):
        self.cls.have_ta = False
        with patch('%s._get_limit_check_id' % pb, autospec=True) as mock_id:
            with patch('%s._get_refreshed_check_result' % pb,
                       autospec=True) as mock_hr:
                with patch('awslimitchecker.trustedadvisor'
                           '.logger',
                           autospec=True) as mock_logger:
                    res = self.cls._poll()
        assert self.mock_conn.mock_calls == []
        assert mock_id.mock_calls == [call(self.cls)]
        assert mock_hr.mock_calls == []
        assert mock_logger.mock_calls == [
            call.info('Beginning TrustedAdvisor poll'),
            call.info('TrustedAdvisor.have_ta is False; not polling TA')
        ]
        assert res == {}
예제 #28
0
class TestGetRefreshedCheckResult(object):
    def setup(self):
        self.mock_conn = Mock()
        self.mock_client_config = Mock()
        type(self.mock_client_config).region_name = 'us-east-1'
        type(self.mock_conn)._client_config = self.mock_client_config
        self.cls = TrustedAdvisor({}, {})
        self.cls.conn = self.mock_conn

        self.mock_svc1 = Mock(spec_set=_AwsService)
        self.mock_svc2 = Mock(spec_set=_AwsService)
        self.services = {
            'SvcFoo': self.mock_svc1,
            'SvcBar': self.mock_svc2,
        }

    def test_mode_none(self):
        self.cls.refresh_mode = None
        with patch('%s._get_check_result' % pb, autospec=True) as mock_gcr:
            with patch('%s._can_refresh_check' % pb,
                       autospec=True) as mock_crc:
                with patch('%s.logger' % pbm, autospec=True) as mock_logger:
                    with patch('%s._poll_for_refresh' % pb,
                               autospec=True) as mock_pfr:
                        mock_gcr.return_value = ({'mock': 'gcr'}, None)
                        res = self.cls._get_refreshed_check_result('abc123')
        assert res == {'mock': 'gcr'}
        assert mock_gcr.mock_calls == [call(self.cls, 'abc123')]
        assert mock_crc.mock_calls == []
        assert mock_pfr.mock_calls == []
        assert mock_logger.mock_calls == [
            call.info("Not refreshing Trusted Advisor check (refresh mode is "
                      "None)")
        ]

    @freeze_time("2016-12-16 10:40:42", tz_offset=0)
    def test_mode_int(self):
        self.cls.refresh_mode = 120  # 2 minutes
        check_dt = datetime(2016,
                            12,
                            16,
                            hour=10,
                            minute=30,
                            second=12,
                            tzinfo=utc)
        with patch('%s._get_check_result' % pb, autospec=True) as mock_gcr:
            with patch('%s._can_refresh_check' % pb,
                       autospec=True) as mock_crc:
                with patch('%s.logger' % pbm, autospec=True) as mock_logger:
                    with patch('%s._poll_for_refresh' % pb,
                               autospec=True) as mock_pfr:
                        mock_gcr.return_value = ({'mock': 'gcr'}, check_dt)
                        mock_pfr.return_value = {'mock': 'pfr'}
                        mock_crc.return_value = True
                        res = self.cls._get_refreshed_check_result('abc123')
        assert res == {'mock': 'pfr'}
        assert mock_gcr.mock_calls == [call(self.cls, 'abc123')]
        assert mock_crc.mock_calls == [call(self.cls, 'abc123')]
        assert mock_pfr.mock_calls == [call(self.cls, 'abc123')]
        assert mock_logger.mock_calls == [
            call.debug('Handling refresh of check: %s', 'abc123'),
            call.debug(
                'ta_refresh_mode older; check last refresh: %s; '
                'threshold=%d seconds', check_dt, 120),
            call.info('Refreshing Trusted Advisor check: %s', 'abc123')
        ]

    @freeze_time("2016-12-16 10:40:42", tz_offset=0)
    def test_mode_int_within_threshold(self):
        self.cls.refresh_mode = 120  # 2 minutes
        check_dt = datetime(2016,
                            12,
                            16,
                            hour=10,
                            minute=40,
                            second=12,
                            tzinfo=utc)
        with patch('%s._get_check_result' % pb, autospec=True) as mock_gcr:
            with patch('%s._can_refresh_check' % pb,
                       autospec=True) as mock_crc:
                with patch('%s.logger' % pbm, autospec=True) as mock_logger:
                    with patch('%s._poll_for_refresh' % pb,
                               autospec=True) as mock_pfr:
                        mock_gcr.return_value = ({'mock': 'gcr'}, check_dt)
                        mock_pfr.return_value = {'mock': 'pfr'}
                        mock_crc.return_value = True
                        res = self.cls._get_refreshed_check_result('abc123')
        assert res == {'mock': 'gcr'}
        assert mock_gcr.mock_calls == [
            call(self.cls, 'abc123'),
            call(self.cls, 'abc123')
        ]
        assert mock_crc.mock_calls == [call(self.cls, 'abc123')]
        assert mock_pfr.mock_calls == []
        assert mock_logger.mock_calls == [
            call.debug('Handling refresh of check: %s', 'abc123'),
            call.debug(
                'ta_refresh_mode older; check last refresh: %s; '
                'threshold=%d seconds', check_dt, 120),
            call.warning(
                'Trusted Advisor check %s last refresh time of %s '
                'is newer than refresh threshold of %d seconds.', 'abc123',
                datetime(2016, 12, 16, 10, 40, 12, tzinfo=utc), 120)
        ]

    @freeze_time("2016-12-16 10:40:42", tz_offset=0)
    def test_mode_trigger(self):
        self.cls.refresh_mode = 'trigger'
        check_dt = datetime(2016,
                            12,
                            16,
                            hour=10,
                            minute=30,
                            second=12,
                            tzinfo=utc)
        with patch('%s._get_check_result' % pb, autospec=True) as mock_gcr:
            with patch('%s._can_refresh_check' % pb,
                       autospec=True) as mock_crc:
                with patch('%s.logger' % pbm, autospec=True) as mock_logger:
                    with patch('%s._poll_for_refresh' % pb,
                               autospec=True) as mock_pfr:
                        mock_gcr.return_value = ({'mock': 'gcr'}, check_dt)
                        mock_pfr.return_value = {'mock': 'pfr'}
                        mock_crc.return_value = True
                        res = self.cls._get_refreshed_check_result('abc123')
        assert res == {'mock': 'gcr'}
        assert mock_gcr.mock_calls == [call(self.cls, 'abc123')]
        assert mock_crc.mock_calls == [call(self.cls, 'abc123')]
        assert mock_pfr.mock_calls == []
        assert mock_logger.mock_calls == [
            call.debug('Handling refresh of check: %s', 'abc123'),
            call.info('Refreshing Trusted Advisor check: %s', 'abc123')
        ]

    @freeze_time("2016-12-16 10:40:42", tz_offset=0)
    def test_cant_refresh(self):
        self.cls.refresh_mode = 120  # 2 minutes
        check_dt = datetime(2016,
                            12,
                            16,
                            hour=10,
                            minute=30,
                            second=12,
                            tzinfo=utc)
        with patch('%s._get_check_result' % pb, autospec=True) as mock_gcr:
            with patch('%s._can_refresh_check' % pb,
                       autospec=True) as mock_crc:
                with patch('%s.logger' % pbm, autospec=True) as mock_logger:
                    with patch('%s._poll_for_refresh' % pb,
                               autospec=True) as mock_pfr:
                        mock_gcr.return_value = ({'mock': 'gcr'}, check_dt)
                        mock_pfr.return_value = {'mock': 'pfr'}
                        mock_crc.return_value = False
                        res = self.cls._get_refreshed_check_result('abc123')
        assert res == {'mock': 'gcr'}
        assert mock_gcr.mock_calls == [call(self.cls, 'abc123')]
        assert mock_crc.mock_calls == [call(self.cls, 'abc123')]
        assert mock_pfr.mock_calls == []
        assert mock_logger.mock_calls == [
            call.debug('Handling refresh of check: %s', 'abc123')
        ]
예제 #29
0
class TestGetCheckResult(object):
    def setup(self):
        self.mock_conn = Mock()
        self.mock_client_config = Mock()
        type(self.mock_client_config).region_name = 'us-east-1'
        type(self.mock_conn)._client_config = self.mock_client_config
        self.cls = TrustedAdvisor({}, {})
        self.cls.conn = self.mock_conn

        self.mock_svc1 = Mock(spec_set=_AwsService)
        self.mock_svc2 = Mock(spec_set=_AwsService)
        self.services = {
            'SvcFoo': self.mock_svc1,
            'SvcBar': self.mock_svc2,
        }

    def test_simple(self):
        tmp = self.mock_conn.describe_trusted_advisor_check_result
        check_result = {
            'result': {
                'timestamp':
                '2015-06-15T20:27:42Z',
                'flaggedResources': [{
                    'status':
                    'ok',
                    'resourceId':
                    'resid1',
                    'isSuppressed':
                    False,
                    'region':
                    'us-west-2',
                    'metadata': [
                        'us-west-2', 'AutoScaling', 'Auto Scaling groups',
                        '20', '2', 'Green'
                    ]
                }]
            }
        }
        tmp.return_value = check_result
        res = self.cls._get_check_result('abc123')
        assert tmp.mock_calls == [call(checkId='abc123', language='en')]
        assert res == (check_result,
                       datetime(2015, 6, 15, 20, 27, 42, tzinfo=utc))

    def test_no_timestamp(self):
        tmp = self.mock_conn.describe_trusted_advisor_check_result
        check_result = {
            'result': {
                'flaggedResources': [{
                    'status':
                    'ok',
                    'resourceId':
                    'resid1',
                    'isSuppressed':
                    False,
                    'region':
                    'us-west-2',
                    'metadata': [
                        'us-west-2', 'AutoScaling', 'Auto Scaling groups',
                        '20', '2', 'Green'
                    ]
                }]
            }
        }
        tmp.return_value = check_result
        res = self.cls._get_check_result('abc123')
        assert tmp.mock_calls == [call(checkId='abc123', language='en')]
        assert res == (check_result, None)
예제 #30
0
class TestPollForRefresh(object):
    def setup(self):
        self.mock_conn = Mock()
        self.mock_client_config = Mock()
        type(self.mock_client_config).region_name = 'us-east-1'
        type(self.mock_conn)._client_config = self.mock_client_config
        self.cls = TrustedAdvisor({}, {})
        self.cls.conn = self.mock_conn

    def test_no_timeout(self):
        self.cls.refresh_timeout = None
        check_dt = datetime(2016,
                            12,
                            16,
                            hour=10,
                            minute=30,
                            second=12,
                            tzinfo=utc)
        now_dt = datetime(2016,
                          12,
                          16,
                          hour=11,
                          minute=30,
                          second=12,
                          tzinfo=utc)
        statuses = [{
            'statuses': [{
                'status': 'none'
            }]
        }, {
            'statuses': [{
                'status': 'enqueued'
            }]
        }, {
            'statuses': [{
                'status': 'processing'
            }]
        }, {
            'statuses': [{
                'status': 'success'
            }]
        }]
        m_s = self.mock_conn.describe_trusted_advisor_check_refresh_statuses
        with patch('%s.logger' % pbm, autospec=True) as mock_logger:
            with patch('%s.sleep' % pbm, autospec=True) as mock_sleep:
                with patch('%s._get_check_result' % pb, autospec=True) as gcr:
                    with patch('%s.datetime_now' % pbm) as mock_dt_now:
                        mock_dt_now.return_value = now_dt
                        m_s.side_effect = statuses
                        gcr.return_value = ({'foo': 'bar'}, check_dt)
                        res = self.cls._poll_for_refresh('abc123')
        assert res == {'foo': 'bar'}
        assert self.mock_conn.mock_calls == [
            call.describe_trusted_advisor_check_refresh_statuses(
                checkIds=['abc123']),
            call.describe_trusted_advisor_check_refresh_statuses(
                checkIds=['abc123']),
            call.describe_trusted_advisor_check_refresh_statuses(
                checkIds=['abc123']),
            call.describe_trusted_advisor_check_refresh_statuses(
                checkIds=['abc123'])
        ]
        assert gcr.mock_calls == [call(self.cls, 'abc123')]
        assert mock_sleep.mock_calls == [call(30), call(30), call(30)]
        assert mock_dt_now.mock_calls == [
            call(), call(), call(), call(),
            call()
        ]
        assert mock_logger.mock_calls == [
            call.warning('Polling for TA check %s refresh...', 'abc123'),
            call.debug('Checking refresh status'),
            call.info('Refresh status: %s; sleeping 30s', 'none'),
            call.debug('Checking refresh status'),
            call.info('Refresh status: %s; sleeping 30s', 'enqueued'),
            call.debug('Checking refresh status'),
            call.info('Refresh status: %s; sleeping 30s', 'processing'),
            call.debug('Checking refresh status'),
            call.info('Refresh status: %s; done polling', 'success'),
            call.info('Done polling for check refresh'),
            call.debug('Check shows last refresh time of: %s', check_dt)
        ]

    def test_timeout(self):
        self.cls.refresh_timeout = 45
        check_dt = datetime(2016,
                            12,
                            16,
                            hour=10,
                            minute=30,
                            second=12,
                            tzinfo=utc)
        now_dts = [
            datetime(2016, 12, 16, hour=11, minute=30, second=0, tzinfo=utc),
            datetime(2016, 12, 16, hour=11, minute=30, second=0, tzinfo=utc),
            datetime(2016, 12, 16, hour=11, minute=30, second=30, tzinfo=utc),
            datetime(2016, 12, 16, hour=11, minute=31, second=0, tzinfo=utc),
        ]
        status = {'statuses': [{'status': 'processing'}]}
        m_s = self.mock_conn.describe_trusted_advisor_check_refresh_statuses
        with patch('%s.logger' % pbm, autospec=True) as mock_logger:
            with patch('%s.sleep' % pbm, autospec=True) as mock_sleep:
                with patch('%s._get_check_result' % pb, autospec=True) as gcr:
                    with patch('%s.datetime_now' % pbm) as mock_dt_now:
                        mock_dt_now.side_effect = now_dts
                        m_s.return_value = status
                        gcr.return_value = ({'foo': 'bar'}, check_dt)
                        res = self.cls._poll_for_refresh('abc123')
        assert res == {'foo': 'bar'}
        assert self.mock_conn.mock_calls == [
            call.describe_trusted_advisor_check_refresh_statuses(
                checkIds=['abc123']),
            call.describe_trusted_advisor_check_refresh_statuses(
                checkIds=['abc123'])
        ]
        assert gcr.mock_calls == [call(self.cls, 'abc123')]
        assert mock_sleep.mock_calls == [call(30), call(30)]
        assert mock_dt_now.mock_calls == [call(), call(), call(), call()]
        assert mock_logger.mock_calls == [
            call.warning('Polling for TA check %s refresh...', 'abc123'),
            call.debug('Checking refresh status'),
            call.info('Refresh status: %s; sleeping 30s', 'processing'),
            call.debug('Checking refresh status'),
            call.info('Refresh status: %s; sleeping 30s', 'processing'),
            call.error('Timed out waiting for TA Check refresh; status=%s',
                       'processing'),
            call.info('Done polling for check refresh'),
            call.debug('Check shows last refresh time of: %s', check_dt)
        ]

    def test_none(self):
        self.cls.refresh_timeout = None
        check_dt = datetime(2016,
                            12,
                            16,
                            hour=10,
                            minute=30,
                            second=12,
                            tzinfo=utc)
        now_dt = datetime(2016,
                          12,
                          16,
                          hour=11,
                          minute=30,
                          second=12,
                          tzinfo=utc)
        statuses = [{
            'statuses': [{
                'status': 'none'
            }]
        }, {
            'statuses': [{
                'status': 'enqueued'
            }]
        }, {
            'statuses': [{
                'status': 'processing'
            }]
        }, {
            'statuses': [{
                'status': 'none'
            }]
        }]
        m_s = self.mock_conn.describe_trusted_advisor_check_refresh_statuses
        with patch('%s.logger' % pbm, autospec=True) as mock_logger:
            with patch('%s.sleep' % pbm, autospec=True) as mock_sleep:
                with patch('%s._get_check_result' % pb, autospec=True) as gcr:
                    with patch('%s.datetime_now' % pbm) as mock_dt_now:
                        mock_dt_now.return_value = now_dt
                        m_s.side_effect = statuses
                        gcr.return_value = ({'foo': 'bar'}, check_dt)
                        res = self.cls._poll_for_refresh('abc123')
        assert res == {'foo': 'bar'}
        assert self.mock_conn.mock_calls == [
            call.describe_trusted_advisor_check_refresh_statuses(
                checkIds=['abc123']),
            call.describe_trusted_advisor_check_refresh_statuses(
                checkIds=['abc123']),
            call.describe_trusted_advisor_check_refresh_statuses(
                checkIds=['abc123']),
            call.describe_trusted_advisor_check_refresh_statuses(
                checkIds=['abc123'])
        ]
        assert gcr.mock_calls == [call(self.cls, 'abc123')]
        assert mock_sleep.mock_calls == [call(30), call(30), call(30)]
        assert mock_dt_now.mock_calls == [
            call(), call(), call(), call(),
            call()
        ]
        assert mock_logger.mock_calls == [
            call.warning('Polling for TA check %s refresh...', 'abc123'),
            call.debug('Checking refresh status'),
            call.info('Refresh status: %s; sleeping 30s', 'none'),
            call.debug('Checking refresh status'),
            call.info('Refresh status: %s; sleeping 30s', 'enqueued'),
            call.debug('Checking refresh status'),
            call.info('Refresh status: %s; sleeping 30s', 'processing'),
            call.debug('Checking refresh status'),
            call.warning(
                'Trusted Advisor check refresh status went '
                'from "%s" to "%s"; refresh is either complete '
                'or timed out on AWS side. Continuing', 'processing', 'none'),
            call.info('Done polling for check refresh'),
            call.debug('Check shows last refresh time of: %s', check_dt)
        ]
예제 #31
0
class Test_TrustedAdvisor(object):
    def setup(self):
        self.mock_conn = Mock()
        self.mock_client_config = Mock()
        type(self.mock_client_config).region_name = 'us-east-1'
        type(self.mock_conn)._client_config = self.mock_client_config
        self.cls = TrustedAdvisor()
        self.cls.conn = self.mock_conn

        self.mock_svc1 = Mock(spec_set=_AwsService)
        self.mock_svc2 = Mock(spec_set=_AwsService)
        self.services = {
            'SvcFoo': self.mock_svc1,
            'SvcBar': self.mock_svc2,
        }

    def test_init(self):
        cls = TrustedAdvisor()
        assert cls.conn is None
        assert cls.account_id is None
        assert cls.account_role is None
        assert cls.region == 'us-east-1'
        assert cls.ta_region is None
        assert cls.external_id is None
        assert cls.mfa_serial_number is None
        assert cls.mfa_token is None

    def test_init_sts(self):
        cls = TrustedAdvisor(account_id='aid', account_role='role', region='r')
        assert cls.conn is None
        assert cls.account_id == 'aid'
        assert cls.account_role == 'role'
        assert cls.region == 'us-east-1'
        assert cls.ta_region == 'r'
        assert cls.external_id is None
        assert cls.mfa_serial_number is None
        assert cls.mfa_token is None

    def test_init_sts_external_id(self):
        cls = TrustedAdvisor(account_id='aid',
                             account_role='role',
                             region='r',
                             external_id='myeid')
        assert cls.conn is None
        assert cls.account_id == 'aid'
        assert cls.account_role == 'role'
        assert cls.region == 'us-east-1'
        assert cls.ta_region == 'r'
        assert cls.external_id == 'myeid'
        assert cls.mfa_serial_number is None
        assert cls.mfa_token is None

    def test_update_limits(self):
        mock_results = Mock()
        with patch('%s.connect' % pb, autospec=True) as mock_connect:
            with patch('%s._poll' % pb, autospec=True) as mock_poll:
                with patch('%s._update_services' % pb,
                           autospec=True) as mock_update_services:
                    mock_poll.return_value = mock_results
                    self.cls.update_limits(self.services)
        assert mock_connect.mock_calls == [call(self.cls)]
        assert mock_poll.mock_calls == [call(self.cls)]
        assert mock_update_services.mock_calls == [
            call(self.cls, mock_results, self.services)
        ]

    def test_get_limit_check_id(self):
        api_resp = {
            'checks': [
                {
                    'category':
                    'performance',
                    'name':
                    'Service Limits',
                    'id':
                    'bar',
                    'metadata': [
                        'Region', 'Service', 'Limit Name', 'Limit Amount',
                        'Current Usage', 'Status'
                    ],
                },
                {
                    'category': 'fault_tolerance',
                    'name': 'ELB Cross-Zone Load Balancing',
                    'id': 'foo',
                },
            ]
        }
        self.mock_conn.describe_trusted_advisor_checks.return_value = api_resp
        res = self.cls._get_limit_check_id()
        assert res == ('bar', [
            'Region', 'Service', 'Limit Name', 'Limit Amount', 'Current Usage',
            'Status'
        ])
        assert self.mock_conn.mock_calls == [
            call.describe_trusted_advisor_checks(language='en')
        ]

    def test_get_limit_check_id_none(self):
        api_resp = {
            'checks': [
                {
                    'category': 'performance',
                    'name': 'Something Else',
                    'id': 'bar',
                },
                {
                    'category': 'fault_tolerance',
                    'name': 'ELB Cross-Zone Load Balancing',
                    'id': 'foo',
                },
            ]
        }
        self.mock_conn.describe_trusted_advisor_checks.return_value = api_resp
        res = self.cls._get_limit_check_id()
        assert res == (None, None)
        assert self.mock_conn.mock_calls == [
            call.describe_trusted_advisor_checks(language='en')
        ]

    def test_get_limit_check_id_subscription_required(self):
        def se_api(language=None):
            response = {
                'ResponseMetadata': {
                    'HTTPStatusCode': 400,
                    'RequestId': '3cc9b2a8-c6e5-11e5-bc1d-b13dcea36176'
                },
                'Error': {
                    'Message': 'AWS Premium Support Subscription is required '
                    'to use this service.',
                    'Code': 'SubscriptionRequiredException'
                }
            }
            raise ClientError(response, 'operation')

        assert self.cls.have_ta is True
        self.mock_conn.describe_trusted_advisor_checks.side_effect = se_api
        with patch('awslimitchecker.trustedadvisor'
                   '.logger', autospec=True) as mock_logger:
            res = self.cls._get_limit_check_id()
        assert self.cls.have_ta is False
        assert res == (None, None)
        assert self.mock_conn.mock_calls == [
            call.describe_trusted_advisor_checks(language='en')
        ]
        assert mock_logger.mock_calls == [
            call.debug("Querying Trusted Advisor checks"),
            call.warning(
                "Cannot check TrustedAdvisor: %s",
                'AWS Premium Support Subscription is required to '
                'use this service.')
        ]

    def test_get_limit_check_id_other_exception(self):
        def se_api(language=None):
            response = {
                'ResponseMetadata': {
                    'HTTPStatusCode': 400,
                    'RequestId': '3cc9b2a8-c6e5-11e5-bc1d-b13dcea36176'
                },
                'Error': {
                    'Message': 'foo',
                    'Code': 'SomeOtherException'
                }
            }
            raise ClientError(response, 'operation')

        self.mock_conn.describe_trusted_advisor_checks.side_effect = se_api
        with pytest.raises(ClientError) as excinfo:
            self.cls._get_limit_check_id()
        assert self.mock_conn.mock_calls == [
            call.describe_trusted_advisor_checks(language='en')
        ]
        assert excinfo.value.response['ResponseMetadata'][
            'HTTPStatusCode'] == 400
        assert excinfo.value.response['Error']['Message'] == 'foo'
        assert excinfo.value.response['Error']['Code'] == 'SomeOtherException'

    def test_poll_id_none(self):
        tmp = self.mock_conn.describe_trusted_advisor_check_result
        with patch('%s._get_limit_check_id' % pb, autospec=True) as mock_id:
            mock_id.return_value = None
            res = self.cls._poll()
        assert tmp.mock_calls == []
        assert res is None

    def test_poll(self):
        tmp = self.mock_conn.describe_trusted_advisor_check_result
        poll_return_val = {
            'result': {
                'timestamp':
                '2015-06-15T20:27:42Z',
                'flaggedResources': [
                    {
                        'status':
                        'ok',
                        'resourceId':
                        'resid1',
                        'isSuppressed':
                        False,
                        'region':
                        'us-west-2',
                        'metadata': [
                            'us-west-2', 'AutoScaling', 'Auto Scaling groups',
                            '20', '2', 'Green'
                        ]
                    },
                    {
                        'status':
                        'ok',
                        'resourceId':
                        'resid2',
                        'isSuppressed':
                        False,
                        'region':
                        'us-east-1',
                        'metadata': [
                            'us-east-1', 'AutoScaling',
                            'Launch configurations', '20', '18', 'Yellow'
                        ]
                    },
                    {
                        'status':
                        'ok',
                        'resourceId':
                        'resid3',
                        'isSuppressed':
                        False,
                        'region':
                        'us-east-1',
                        'metadata': [
                            'us-west-2', 'AutoScaling', 'Auto Scaling groups',
                            '40', '10', 'Green'
                        ]
                    },
                ]
            }
        }
        tmp.return_value = poll_return_val
        with patch('%s._get_limit_check_id' % pb, autospec=True) as mock_id:
            mock_id.return_value = ('foo', [
                'Region', 'Service', 'Limit Name', 'Limit Amount',
                'Current Usage', 'Status'
            ])
            res = self.cls._poll()
        assert self.mock_conn.mock_calls == [
            call.describe_trusted_advisor_check_result(checkId='foo',
                                                       language='en')
        ]
        assert mock_id.mock_calls == [call(self.cls)]
        assert res == {
            'AutoScaling': {
                'Launch configurations': 20,
                'Auto Scaling groups': 40,
            }
        }

    def test_poll_region(self):
        tmp = self.mock_conn.describe_trusted_advisor_check_result
        self.cls.ta_region = 'us-west-2'
        poll_return_value = {
            'result': {
                'timestamp':
                '2015-06-15T20:27:42Z',
                'flaggedResources': [
                    {
                        'status':
                        'ok',
                        'resourceId':
                        'resid1',
                        'isSuppressed':
                        False,
                        'region':
                        'us-west-2',
                        'metadata': [
                            'us-west-2', 'AutoScaling', 'Auto Scaling groups',
                            '20', '2', 'Green'
                        ]
                    },
                    {
                        'status':
                        'ok',
                        'resourceId':
                        'resid2',
                        'isSuppressed':
                        False,
                        'region':
                        'us-east-1',
                        'metadata': [
                            'us-east-1', 'AutoScaling',
                            'Launch configurations', '20', '18', 'Yellow'
                        ]
                    },
                    {
                        'status':
                        'ok',
                        'resourceId':
                        'resid3',
                        'isSuppressed':
                        False,
                        'region':
                        'us-east-1',
                        'metadata': [
                            'us-west-2', 'AutoScaling', 'Auto Scaling groups',
                            '40', '10', 'Green'
                        ]
                    },
                ]
            }
        }
        tmp.return_value = poll_return_value
        with patch('%s._get_limit_check_id' % pb, autospec=True) as mock_id:
            mock_id.return_value = ('foo', [
                'Region', 'Service', 'Limit Name', 'Limit Amount',
                'Current Usage', 'Status'
            ])
            res = self.cls._poll()
        assert self.mock_conn.mock_calls == [
            call.describe_trusted_advisor_check_result(checkId='foo',
                                                       language='en')
        ]
        assert mock_id.mock_calls == [call(self.cls)]
        assert res == {
            'AutoScaling': {
                'Auto Scaling groups': 20,
            }
        }

    def test_poll_dont_have_ta(self):
        self.cls.have_ta = False
        tmp = self.mock_conn.describe_trusted_advisor_check_result
        with patch('%s._get_limit_check_id' % pb, autospec=True) as mock_id:
            with patch('awslimitchecker.trustedadvisor'
                       '.logger',
                       autospec=True) as mock_logger:
                res = self.cls._poll()
        assert self.mock_conn.mock_calls == []
        assert tmp.mock_calls == []
        assert mock_id.mock_calls == [call(self.cls)]
        assert mock_logger.mock_calls == [
            call.info('Beginning TrustedAdvisor poll'),
            call.info('TrustedAdvisor.have_ta is False; not polling TA')
        ]
        assert res == {}

    def test_update_services(self):
        def se_set(lname, val):
            if lname == 'blam':
                raise ValueError("foo")

        mock_autoscale = Mock(spec_set=_AwsService)
        mock_ec2 = Mock(spec_set=_AwsService)
        mock_ec2._set_ta_limit.side_effect = se_set
        mock_vpc = Mock(spec_set=_AwsService)
        services = {
            'AutoScaling': mock_autoscale,
            'EC2': mock_ec2,
            'VPC': mock_vpc,
        }
        ta_results = {
            'AutoScaling': {
                'foo': 20,
                'bar': 40,
            },
            'EC2': {
                'baz': 5,
                'blam': 10,
            },
            'OtherService': {
                'blarg': 1,
            },
            'VPC': {
                'VPC Elastic IP addresses (EIPs)': 11,
            }
        }
        with patch('awslimitchecker.trustedadvisor'
                   '.logger', autospec=True) as mock_logger:
            self.cls._update_services(ta_results, services)
        assert mock_logger.mock_calls == [
            call.debug("Updating TA limits on all services"),
            call.info(
                "TrustedAdvisor returned check results for unknown "
                "limit '%s' (service %s)", 'blam', 'EC2'),
            call.info(
                "TrustedAdvisor returned check results for unknown "
                "service '%s'", 'OtherService'),
            call.info("Done updating TA limits on all services"),
        ]
        assert mock_autoscale.mock_calls == [
            call._set_ta_limit('bar', 40),
            call._set_ta_limit('foo', 20),
        ]
        assert mock_ec2.mock_calls == [
            call._set_ta_limit('baz', 5),
            call._set_ta_limit('blam', 10),
            call._set_ta_limit('VPC Elastic IP addresses (EIPs)', 11)
        ]

    def test_update_services_no_ec2(self):

        mock_autoscale = Mock(spec_set=_AwsService)
        mock_vpc = Mock(spec_set=_AwsService)
        services = {
            'AutoScaling': mock_autoscale,
            'VPC': mock_vpc,
        }
        ta_results = {
            'AutoScaling': {
                'foo': 20,
                'bar': 40,
            },
            'EC2': {
                'baz': 5,
            },
            'VPC': {
                'VPC Elastic IP addresses (EIPs)': 11,
            }
        }
        with patch('awslimitchecker.trustedadvisor'
                   '.logger', autospec=True) as mock_logger:
            self.cls._update_services(ta_results, services)
        assert mock_logger.mock_calls == [
            call.debug("Updating TA limits on all services"),
            call.info(
                "TrustedAdvisor returned check results for unknown "
                "service '%s'", 'EC2'),
            call.info("Done updating TA limits on all services"),
        ]
        assert mock_autoscale.mock_calls == [
            call._set_ta_limit('bar', 40),
            call._set_ta_limit('foo', 20),
        ]
        assert mock_vpc.mock_calls == []