Show More
@@ -0,0 +1,42 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | ||
|
3 | # Copyright (C) 2010-2016 RhodeCode GmbH | |
|
4 | # | |
|
5 | # This program is free software: you can redistribute it and/or modify | |
|
6 | # it under the terms of the GNU Affero General Public License, version 3 | |
|
7 | # (only), as published by the Free Software Foundation. | |
|
8 | # | |
|
9 | # This program is distributed in the hope that it will be useful, | |
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
|
12 | # GNU General Public License for more details. | |
|
13 | # | |
|
14 | # You should have received a copy of the GNU Affero General Public License | |
|
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
|
16 | # | |
|
17 | # This program is dual-licensed. If you wish to learn more about the | |
|
18 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
|
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
|
20 | ||
|
21 | import mock | |
|
22 | import pytest | |
|
23 | import rhodecode.lib.vcs.client as client | |
|
24 | ||
|
25 | @pytest.mark.usefixtures('autologin_user', 'app') | |
|
26 | def test_vcs_available_returns_summary_page(app, backend): | |
|
27 | url = '/{repo_name}'.format(repo_name=backend.repo.repo_name) | |
|
28 | response = app.get(url) | |
|
29 | assert response.status_code == 200 | |
|
30 | assert 'Summary' in response.body | |
|
31 | ||
|
32 | ||
|
33 | @pytest.mark.usefixtures('autologin_user', 'app') | |
|
34 | def test_vcs_unavailable_returns_vcs_error_page(app, backend): | |
|
35 | url = '/{repo_name}'.format(repo_name=backend.repo.repo_name) | |
|
36 | ||
|
37 | with mock.patch.object(client, '_get_proxy_method') as p: | |
|
38 | p.side_effect = client.exceptions.PyroVCSCommunicationError() | |
|
39 | response = app.get(url, expect_errors=True) | |
|
40 | ||
|
41 | assert response.status_code == 502 | |
|
42 | assert 'Could not connect to VCS Server' in response.body |
@@ -43,9 +43,10 b' from rhodecode.config import patches' | |||
|
43 | 43 | from rhodecode.config.routing import STATIC_FILE_PREFIX |
|
44 | 44 | from rhodecode.config.environment import ( |
|
45 | 45 | load_environment, load_pyramid_environment) |
|
46 | from rhodecode.lib.exceptions import VCSServerUnavailable | |
|
47 | from rhodecode.lib.vcs.exceptions import VCSCommunicationError | |
|
46 | 48 | from rhodecode.lib.middleware import csrf |
|
47 | 49 | from rhodecode.lib.middleware.appenlight import wrap_in_appenlight_if_enabled |
|
48 | from rhodecode.lib.middleware.disable_vcs import DisableVCSPagesWrapper | |
|
49 | 50 | from rhodecode.lib.middleware.https_fixup import HttpsFixup |
|
50 | 51 | from rhodecode.lib.middleware.vcs import VCSMiddleware |
|
51 | 52 | from rhodecode.lib.plugins.utils import register_rhodecode_plugin |
@@ -188,10 +189,6 b' def make_not_found_view(config):' | |||
|
188 | 189 | |
|
189 | 190 | pylons_app_as_view = wsgiapp(pylons_app) |
|
190 | 191 | |
|
191 | # Protect from VCS Server error related pages when server is not available | |
|
192 | if not vcs_server_enabled: | |
|
193 | pylons_app_as_view = DisableVCSPagesWrapper(pylons_app_as_view) | |
|
194 | ||
|
195 | 192 | def pylons_app_with_error_handler(context, request): |
|
196 | 193 | """ |
|
197 | 194 | Handle exceptions from rc pylons app: |
@@ -216,10 +213,17 b' def make_not_found_view(config):' | |||
|
216 | 213 | return error_handler(response, request) |
|
217 | 214 | except HTTPError as e: # pyramid type exceptions |
|
218 | 215 | return error_handler(e, request) |
|
219 | except Exception: | |
|
216 | except Exception as e: | |
|
217 | log.exception(e) | |
|
218 | ||
|
220 | 219 | if settings.get('debugtoolbar.enabled', False): |
|
221 | 220 | raise |
|
221 | ||
|
222 | if isinstance(e, VCSCommunicationError): | |
|
223 | return error_handler(VCSServerUnavailable(), request) | |
|
224 | ||
|
222 | 225 | return error_handler(HTTPInternalServerError(), request) |
|
226 | ||
|
223 | 227 | return response |
|
224 | 228 | |
|
225 | 229 | return pylons_app_with_error_handler |
@@ -23,6 +23,7 b' Set of custom exceptions used in RhodeCo' | |||
|
23 | 23 | """ |
|
24 | 24 | |
|
25 | 25 | from webob.exc import HTTPClientError |
|
26 | from pyramid.httpexceptions import HTTPBadGateway | |
|
26 | 27 | |
|
27 | 28 | |
|
28 | 29 | class LdapUsernameError(Exception): |
@@ -120,3 +121,14 b' class NotAllowedToCreateUserError(Except' | |||
|
120 | 121 | |
|
121 | 122 | class RepositoryCreationError(Exception): |
|
122 | 123 | pass |
|
124 | ||
|
125 | ||
|
126 | class VCSServerUnavailable(HTTPBadGateway): | |
|
127 | """ HTTP Exception class for VCS Server errors """ | |
|
128 | code = 502 | |
|
129 | title = 'VCS Server Error' | |
|
130 | def __init__(self, message=''): | |
|
131 | self.explanation = 'Could not connect to VCS Server' | |
|
132 | if message: | |
|
133 | self.explanation += ': ' + message | |
|
134 | super(VCSServerUnavailable, self).__init__() |
@@ -305,7 +305,7 b' def _get_proxy_method(proxy, name):' | |||
|
305 | 305 | try: |
|
306 | 306 | return getattr(proxy, name) |
|
307 | 307 | except CommunicationError: |
|
308 | raise CommunicationError( | |
|
308 | raise exceptions.PyroVCSCommunicationError( | |
|
309 | 309 | 'Unable to connect to remote pyro server %s' % proxy) |
|
310 | 310 | |
|
311 | 311 |
@@ -36,6 +36,7 b' import urllib2' | |||
|
36 | 36 | import urlparse |
|
37 | 37 | import uuid |
|
38 | 38 | |
|
39 | import pycurl | |
|
39 | 40 | import msgpack |
|
40 | 41 | import requests |
|
41 | 42 | |
@@ -172,7 +173,11 b' class RemoteObject(object):' | |||
|
172 | 173 | |
|
173 | 174 | |
|
174 | 175 | def _remote_call(url, payload, exceptions_map, session): |
|
175 | response = session.post(url, data=msgpack.packb(payload)) | |
|
176 | try: | |
|
177 | response = session.post(url, data=msgpack.packb(payload)) | |
|
178 | except pycurl.error as e: | |
|
179 | raise exceptions.HttpVCSCommunicationError(e) | |
|
180 | ||
|
176 | 181 | response = msgpack.unpackb(response.content) |
|
177 | 182 | error = response.get('error') |
|
178 | 183 | if error: |
@@ -24,6 +24,19 b' Custom vcs exceptions module.' | |||
|
24 | 24 | |
|
25 | 25 | import functools |
|
26 | 26 | import urllib2 |
|
27 | import pycurl | |
|
28 | from Pyro4.errors import CommunicationError | |
|
29 | ||
|
30 | class VCSCommunicationError(Exception): | |
|
31 | pass | |
|
32 | ||
|
33 | ||
|
34 | class PyroVCSCommunicationError(VCSCommunicationError): | |
|
35 | pass | |
|
36 | ||
|
37 | ||
|
38 | class HttpVCSCommunicationError(VCSCommunicationError): | |
|
39 | pass | |
|
27 | 40 | |
|
28 | 41 | |
|
29 | 42 | class VCSError(Exception): |
@@ -161,7 +174,6 b' def map_vcs_exceptions(func):' | |||
|
161 | 174 | try: |
|
162 | 175 | return func(*args, **kwargs) |
|
163 | 176 | except Exception as e: |
|
164 | ||
|
165 | 177 | # The error middleware adds information if it finds |
|
166 | 178 | # __traceback_info__ in a frame object. This way the remote |
|
167 | 179 | # traceback information is made available in error reports. |
@@ -182,5 +194,4 b' def map_vcs_exceptions(func):' | |||
|
182 | 194 | raise _EXCEPTION_MAP[kind](*e.args) |
|
183 | 195 | else: |
|
184 | 196 | raise |
|
185 | ||
|
186 | 197 | return wrapper |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now