Ejemplo n.º 1
0
    def test_authenticate_tenant_propagates_auth_errors(self):
        """
        authenticate_tenant propagates errors from authenticate_user.
        """
        self.impersonate_user.side_effect = lambda *a, **k: fail(
            UpstreamError(Failure(APIError(401, '4')), 'identity', 'o'))
        self.authenticate_user.side_effect = lambda *a, **kw: fail(
            UpstreamError(Failure(APIError(500, '500')), 'identity', 'o'))

        f = self.failureResultOf(self.ia.authenticate_tenant(111111),
                                 UpstreamError)
        self.assertEqual(f.value.reason.value.code, 500)
Ejemplo n.º 2
0
 def test_failure(self):
     """
     Returns FAILURE if rcv3.bulk_delete raises BulkErrors
     """
     terminals = (rcv3.BulkErrors([rcv3.LBInactive("l1")]),
                  APIError(code=403, body="You're out of luck."),
                  APIError(code=422, body="Oh look another 422."))
     eff = self.step.as_effect()
     for exc in terminals:
         seq = [(("bd", self.pairs), lambda i: raise_(exc))]
         self.assertEqual(
             perform_sequence(seq, eff),
             (StepResult.FAILURE, [
                 ErrorReason.Exception((type(exc), exc, ANY))])
         )
Ejemplo n.º 3
0
 def test_other_errors(self):
     """
     Any error other than `BulkErrors` results in RETRY
     """
     non_terminals = (ValueError("internal"),
                      APIError(code=500, body="why?"),
                      APIError(code=503, body="bad service"))
     eff = self.step.as_effect()
     for exc in non_terminals:
         seq = [(("bd", self.pairs), lambda i: raise_(exc))]
         self.assertEqual(
             perform_sequence(seq, eff),
             (StepResult.RETRY, [
                 ErrorReason.Exception((type(exc), exc, ANY))])
         )
Ejemplo n.º 4
0
    def test_diagnose_unwraps_first_error_if_apierr_or_connection_error(self):
        """
        :func:`diagnose` unwraps :class:`FirstError`, no matter how deeply
        nested, and wraps the underlying :class:`ConnectionRefusedError` and
        :class:`APIError` in an :class:`UpstreamError`
        """
        def _wrap(exception):
            return lambda: fail(
                FirstError(
                    Failure(FirstError(Failure(exception), 0)),
                    0))

        f = self.failureResultOf(
            diagnose("system", "operation")(_wrap(APIError(200, {})))(),
            UpstreamError)
        self.assertTrue(f.value.reason.check(APIError))
        self.assertEqual(f.value.system, "system")
        self.assertEqual(f.value.operation, "operation")

        f = self.failureResultOf(
            diagnose("system", "operation")(
                _wrap(ConnectionRefusedError('meh')))(),
            UpstreamError)
        self.assertTrue(f.value.reason.check(ConnectionRefusedError))
        self.assertEqual(f.value.system, "system")
        self.assertEqual(f.value.operation, "operation")
Ejemplo n.º 5
0
 def test_authenticate_tenant_retries_getting_endpoints_for_the_impersonation_token(
         self):
     """
     authenticate_tenant fetches all the endpoints for the impersonation and
     retries with new authentication token if it gets 401
     """
     self.endpoints_for_token.side_effect = [
         fail(UpstreamError(Failure(APIError(401, '')), 'identity', 'o')),
         succeed({'endpoints': [{
             'name': 'anEndpoint',
             'type': 'anType'
         }]})
     ]
     self.successResultOf(self.ia.authenticate_tenant(111111, log=self.log))
     self.endpoints_for_token.assert_has_calls([
         mock.call(self.admin_url,
                   None,
                   'impersonation_token',
                   log=self.log),
         mock.call(self.admin_url,
                   'auth-token',
                   'impersonation_token',
                   log=self.log)
     ])
     self.authenticate_user.assert_called_once_with(self.url,
                                                    self.user,
                                                    self.password,
                                                    log=self.log)
     self.log.msg.assert_called_once_with(
         'Getting new identity admin token')
Ejemplo n.º 6
0
    def test_set_metadata_item(self):
        """
        :obj:`SetMetadataItemOnServer.as_effect` produces a request for
        setting a metadata item on a particular server.  It succeeds if
        successful, but does not fail for any errors.
        """
        server_id = u'abc123'
        meta = SetMetadataItemOnServer(server_id=server_id, key='metadata_key',
                                       value='teapot')
        eff = meta.as_effect()
        seq = [
            (eff.intent, lambda i: (StubResponse(202, {}), {})),
            (Log(ANY, ANY), lambda _: None)
        ]
        self.assertEqual(
            perform_sequence(seq, eff),
            (StepResult.SUCCESS, []))

        exceptions = (NoSuchServerError("msg", server_id=server_id),
                      ServerMetadataOverLimitError("msg", server_id=server_id),
                      NovaRateLimitError("msg"),
                      APIError(code=500, body="", headers={}))
        for exception in exceptions:
            self.assertRaises(
                type(exception),
                perform_sequence,
                [(eff.intent, lambda i: raise_(exception))],
                eff)
Ejemplo n.º 7
0
    def test_remove_nodes_from_clb_terminal_failures(self):
        """
        :obj:`AddNodesToCLB` fails if there are any 4xx errors, then
        the error is propagated up and the result is a failure.
        """
        terminals = (APIError(code=403, body="You're out of luck."),
                     APIError(code=422, body="Oh look another 422."))
        eff = RemoveNodesFromCLB(lb_id='12345',
                                 node_ids=pset(['1', '2'])).as_effect()

        for exc in terminals:
            seq = SequenceDispatcher([(eff.intent, lambda i: raise_(exc))])
            with seq.consume():
                self.assertEquals(
                    sync_perform(seq, eff),
                    (StepResult.FAILURE, [ErrorReason.Exception(
                        matches(ContainsAll([type(exc), exc])))]))
Ejemplo n.º 8
0
    def test_authenticate_tenant_propagates_endpoint_list_errors(self):
        """
        authenticate_tenant propagates errors from endpoints_for_token
        """
        self.endpoints_for_token.return_value = fail(APIError(500, '500'))

        failure = self.failureResultOf(self.ia.authenticate_tenant(111111))
        self.assertTrue(failure.check(APIError))
Ejemplo n.º 9
0
    def test_authenticate_tenant_propagates_impersonation_errors(self):
        """
        authenticate_tenant propagates errors from impersonate_user
        """
        self.impersonate_user.return_value = fail(APIError(500, '500'))

        failure = self.failureResultOf(self.ia.authenticate_tenant(111111))
        self.assertTrue(failure.check(APIError))
Ejemplo n.º 10
0
    def test_add_event_only_retries_5_times_on_non_4xx_api_errors(self):
        """
        Attempting to add an event is only retried up to a maximum of 5 times,
        and only if it's not an 4XX APIError.
        """
        responses = [
            lambda _: raise_(Exception("oh noes!")),
            lambda _: raise_(ResponseFailed(Failure(Exception(":(")))),
            lambda _: raise_(APIError(code=100, body="<some xml>")),
            lambda _: raise_(APIError(code=202, body="<some xml>")),
            lambda _: raise_(APIError(code=301, body="<some xml>")),
            lambda _: raise_(APIError(code=501, body="<some xml>")),
        ]
        with self.assertRaises(APIError) as cm:
            self._perform_add_event(responses)

        self.assertEqual(cm.exception.code, 501)
Ejemplo n.º 11
0
    def test_auth_failure_propagated_to_caller(self):
        """
        authenticate_tenant propagates auth failures to the caller.
        """
        self.resps[1] = APIError(500, '500')

        d = self.ca.authenticate_tenant(1)
        self.failureResultOf(d, APIError)
Ejemplo n.º 12
0
    def test_auth_failure_propagated_to_caller(self):
        """
        authenticate_tenant propagates auth failures to the caller.
        """
        self.auth_function.side_effect = lambda _: fail(APIError(500, '500'))

        d = self.ca.authenticate_tenant(1)
        failure = self.failureResultOf(d)
        self.assertTrue(failure.check(APIError))
Ejemplo n.º 13
0
 def test_raise_error_on_code_does_not_match_code(self):
     """
     ``raise_error_on_code`` expects an APIError, and raises a particular
     error given a specific code.  Otherwise, it just wraps it in a
     :class:`RequestError`
     """
     failure = Failure(APIError(404, '', {}))
     self.assertRaises(RequestError, raise_error_on_code,
                       failure, 500, DummyException(), 'url')
Ejemplo n.º 14
0
    def test_authenticate_tenant_propagates_endpoint_list_errors(self):
        """
        authenticate_tenant propagates errors from endpoints_for_token
        """
        self.endpoints_for_token.side_effect = lambda *a, **kw: fail(
            UpstreamError(Failure(APIError(500, '500')), 'identity', 'o'))

        f = self.failureResultOf(self.ia.authenticate_tenant(111111),
                                 UpstreamError)
        self.assertEqual(f.value.reason.value.code, 500)
Ejemplo n.º 15
0
    def test_authenticate_tenant_propagates_user_list_errors(self):
        """
        authenticate_tenant propagates errors from user_for_tenant
        """
        self.authenticate_user.side_effect = lambda *a, **kw: fail(
            UpstreamError(Failure(APIError(500, '500')), 'identity', 'o'))

        f = self.failureResultOf(self.st.authenticate_tenant('111111'),
                                 UpstreamError)
        self.assertEqual(f.value.reason.value.code, 500)
Ejemplo n.º 16
0
 def test_500_error(self):
     """
     Any error other than 401 is propogated
     """
     d = retry_on_unauth(
         lambda: fail(UpstreamError(Failure(APIError(500, 'a')), 'identity', 'o')),
         self.auth)
     f = self.failureResultOf(d, UpstreamError)
     f.value.reason.trap(APIError)
     self.assertEqual(f.value.reason.value.code, 500)
Ejemplo n.º 17
0
 def test_auth_error_propogates(self):
     """
     `auth()` errors are propogated
     """
     auth = mock.Mock(spec=[], return_value=fail(ValueError('a')))
     func = mock.Mock(side_effect=[
         fail(UpstreamError(Failure(APIError(401, '401')), 'identity', 'o')),
         succeed('r')])
     d = retry_on_unauth(func, auth)
     self.failureResultOf(d, ValueError)
     auth.assert_called_once_with()
Ejemplo n.º 18
0
 def test_apierror_identity(self):
     """
     Wraps APIError from identity and parses error body accordingly
     """
     body = json.dumps({"identityFault": {"message": "ba"}})
     apie = APIError(410, body, {})
     err = UpstreamError(Failure(apie), 'identity', 'stuff', 'xkcd.com')
     self.assertEqual(str(err), 'identity error: 410 - ba (stuff)')
     self.assertEqual(err.details, {
         'system': 'identity', 'operation': 'stuff', 'url': 'xkcd.com',
         'message': 'ba', 'code': 410, 'body': body, 'headers': {}})
Ejemplo n.º 19
0
 def test_auth_error(self):
     """
     Calls auth() followed by func() again if initial func() returns 401
     """
     auth = mock.Mock(spec=[], return_value=succeed('a'))
     func = mock.Mock(side_effect=[
         fail(UpstreamError(Failure(APIError(401, '401')), 'identity', 'o')),
         succeed('r')])
     d = retry_on_unauth(func, auth)
     self.assertEqual(self.successResultOf(d), 'r')
     auth.assert_called_once_with()
Ejemplo n.º 20
0
 def test_apierror_nova(self):
     """
     Wraps APIError from nova and parses error body accordingly
     """
     body = json.dumps({"computeFault": {"message": "b"}})
     apie = APIError(404, body, {})
     err = UpstreamError(Failure(apie), 'nova', 'add', 'xkcd.com')
     self.assertEqual(str(err), 'nova error: 404 - b (add)')
     self.assertEqual(err.details, {
         'system': 'nova', 'operation': 'add', 'url': 'xkcd.com',
         'message': 'b', 'code': 404, 'body': body, 'headers': {}})
Ejemplo n.º 21
0
 def test_apierror_clb(self):
     """
     Wraps APIError from clb and parses error body accordingly
     """
     body = json.dumps({"message": "b"})
     apie = APIError(403, body, {'h1': 2})
     err = UpstreamError(Failure(apie), 'clb', 'remove', 'xkcd.com')
     self.assertEqual(str(err), 'clb error: 403 - b (remove)')
     self.assertEqual(err.details, {
         'system': 'clb', 'operation': 'remove', 'url': 'xkcd.com',
         'message': 'b', 'code': 403, 'body': body, 'headers': {'h1': 2}})
Ejemplo n.º 22
0
    def test_api_error(self):
        """
        An APIError will be instantiated with an HTTP Code and an HTTP response
        body and will expose these in public attributes and have a reasonable
        string representation.
        """
        e = APIError(404, "Not Found.")

        self.assertEqual(e.code, 404)
        self.assertEqual(e.body, "Not Found.")
        self.assertEqual(str(e), "API Error code=404, body='Not Found.'")
Ejemplo n.º 23
0
 def test_delete_and_verify_del_fails(self):
     """
     :func:`delete_and_verify` fails if delete server fails
     """
     eff = delete_and_verify('sid')
     self.assertRaises(
         APIError,
         resolve_effect,
         eff,
         service_request_error_response(APIError(500, '')),
         is_error=True)
Ejemplo n.º 24
0
 def test_change_clb_node_nonterminal_errors(self):
     """Some errors during :obj:`ChangeCLBNode` make convergence retry."""
     eff = self._change_node_eff()
     nonterminal = (APIError(code=500, body="", headers={}),
                    CLBNotActiveError(lb_id=u'abc123'),
                    CLBRateLimitError(lb_id=u'abc123'))
     for exception in nonterminal:
         self.assertEqual(
             perform_sequence([(eff.intent, lambda i: raise_(exception))],
                              eff),
             (StepResult.RETRY, ANY))
Ejemplo n.º 25
0
 def test_change_clb_node_terminal_errors(self):
     """Some errors during :obj:`ChangeCLBNode` make convergence fail."""
     eff = self._change_node_eff()
     terminal = (NoSuchCLBNodeError(lb_id=u'abc123', node_id=u'node1'),
                 CLBNotFoundError(lb_id=u'abc123'),
                 APIError(code=400, body="", headers={}))
     for exception in terminal:
         self.assertEqual(
             perform_sequence([(eff.intent, lambda i: raise_(exception))],
                              eff),
             (StepResult.FAILURE, [ANY]))
Ejemplo n.º 26
0
 def test_delete_and_verify_verify_404(self):
     """
     :func:`delete_and_verify` gets server details after successful delete
     and succeeds if get server details returns 404
     """
     eff = delete_and_verify('sid')
     eff = resolve_effect(
         eff, service_request_error_response(APIError(204, {})),
         is_error=True)
     r = resolve_effect(eff, (StubResponse(404, {}), {"itemNotFound": {}}))
     self.assertIsNone(r)
Ejemplo n.º 27
0
 def test_retries_times_out(self):
     """
     `RetryingAuthenticator` retries internal authenticator and times out if it
     keeps failing for certain period of time
     """
     self.mock_auth.authenticate_tenant.side_effect = lambda *a, **kw: fail(
         APIError(500, '2'))
     d = self.authenticator.authenticate_tenant(23)
     self.assertNoResult(d)
     self.clock.pump([4] * 4)
     f = self.failureResultOf(d, APIError)
     self.assertEqual(f.value.code, 500)
Ejemplo n.º 28
0
 def test_create_server_terminal_failures(self):
     """
     :obj:`CreateServer.as_effect`, when it results in
     :class:`CreateServerConfigurationError` or
     :class:`CreateServerOverQuoteError` or a :class:`APIError` with
     a 400 failure code, returns with :obj:`StepResult.FAILURE`
     """
     errs = (
         CreateServerConfigurationError(
             "Bad networks format: network uuid is not in proper format "
             "(2b55377-890e-4fc9-9ece-ad5a414a788e)"),
         CreateServerConfigurationError("This was just a bad request"),
         CreateServerOverQuoteError(
             "Quota exceeded for ram: Requested 1024, but already used "
             "131072 of 131072 ram"),
         APIError(code=400, body="Unparsable user error", headers={}),
         APIError(code=418, body="I am a teapot but this is still a 4xx",
                  headers={})
     )
     self._assert_create_server_with_errs_has_status(
         errs, StepResult.FAILURE)
Ejemplo n.º 29
0
    def test_add_nodes_to_clb_terminal_failures(self):
        """
        :obj:`AddNodesToCLB` fails if the CLB is not found or deleted, or
        if there is any other 4xx error, then
        the error is propagated up and the result is a failure.
        """
        terminals = (CLBNotFoundError(lb_id=u"12345"),
                     CLBDeletedError(lb_id=u"12345"),
                     NoSuchCLBError(lb_id=u"12345"),
                     CLBNodeLimitError(lb_id=u"12345", node_limit=25),
                     APIError(code=403, body="You're out of luck."),
                     APIError(code=422, body="Oh look another 422."))
        eff = self._add_one_node_to_clb()

        for exc in terminals:
            seq = SequenceDispatcher([(eff.intent, lambda i: raise_(exc))])
            with seq.consume():
                self.assertEquals(
                    sync_perform(seq, eff),
                    (StepResult.FAILURE, [ErrorReason.Exception(
                        matches(ContainsAll([type(exc), exc])))]))
Ejemplo n.º 30
0
 def test_create_server_retryable_failures(self):
     """
     :obj:`CreateServer.as_effect`, when it results in a
     :class:`NovaComputeFaultError` or :class:`NovaRateLimitError` or
     :class:`APIError` that is not a 4xx, returns with a
     :obj:`StepResult.RETRY`
     """
     errs = (
         NovaComputeFaultError("oops"),
         NovaRateLimitError("OverLimit Retry..."),
         APIError(code=501, body=":(", headers={}),
         TypeError("You did something wrong")
     )
     self._assert_create_server_with_errs_has_status(errs, StepResult.RETRY)