##// END OF EJS Templates
core: deprecated http based callback deamon....
super-admin -
r1315:910dabad default
parent child Browse files
Show More
@@ -71,7 +71,7 b' def VcsException(org_exc=None):'
71 71 return _make_exception_wrapper
72 72
73 73
74 def RepositoryLockedException(org_exc=None):
74 def LockedRepoException(org_exc=None):
75 75 def _make_exception_wrapper(*args):
76 76 return _make_exception('repo_locked', org_exc, *args)
77 77 return _make_exception_wrapper
@@ -41,54 +41,6 b" celery_app = Celery('__vcsserver__')"
41 41 log = logging.getLogger(__name__)
42 42
43 43
44 class HooksHttpClient:
45 proto = 'msgpack.v1'
46 connection = None
47
48 def __init__(self, hooks_uri):
49 self.hooks_uri = hooks_uri
50
51 def __repr__(self):
52 return f'{self.__class__}(hook_uri={self.hooks_uri}, proto={self.proto})'
53
54 def __call__(self, method, extras):
55 connection = http.client.HTTPConnection(self.hooks_uri)
56 # binary msgpack body
57 headers, body = self._serialize(method, extras)
58 log.debug('Doing a new hooks call using HTTPConnection to %s', self.hooks_uri)
59
60 try:
61 try:
62 connection.request('POST', '/', body, headers)
63 except Exception as error:
64 log.error('Hooks calling Connection failed on %s, org error: %s', connection.__dict__, error)
65 raise
66
67 response = connection.getresponse()
68 try:
69 return msgpack.load(response)
70 except Exception:
71 response_data = response.read()
72 log.exception('Failed to decode hook response json data. '
73 'response_code:%s, raw_data:%s',
74 response.status, response_data)
75 raise
76 finally:
77 connection.close()
78
79 @classmethod
80 def _serialize(cls, hook_name, extras):
81 data = {
82 'method': hook_name,
83 'extras': extras
84 }
85 headers = {
86 "rc-hooks-protocol": cls.proto,
87 "Connection": "keep-alive"
88 }
89 return headers, msgpack.packb(data)
90
91
92 44 class HooksCeleryClient:
93 45 TASK_TIMEOUT = 60 # time in seconds
94 46
@@ -160,17 +112,20 b' class SvnMessageWriter(RemoteMessageWrit'
160 112
161 113
162 114 def _maybe_handle_exception(result):
115
116
163 117 exception_class = result.get('exception')
164 118 exception_traceback = result.get('exception_traceback')
165 if not (exception_class and exception_traceback):
119 if not exception_class:
166 120 return
121
167 122 log.debug('Handling hook-call exception: %s', exception_class)
168 123
169 124 if exception_traceback:
170 125 log.error('Got traceback from remote call:%s', exception_traceback)
171 126
172 if exception_class == 'HTTPLockedRC':
173 raise exceptions.RepositoryLockedException()(*result['exception_args'])
127 if exception_class == 'HTTPLockedRepo':
128 raise exceptions.LockedRepoException()(*result['exception_args'])
174 129 elif exception_class == 'ClientNotSupportedError':
175 130 raise exceptions.ClientNotSupportedException()(*result['exception_args'])
176 131 elif exception_class == 'HTTPBranchProtected':
@@ -184,14 +139,11 b' def _maybe_handle_exception(result):'
184 139
185 140
186 141 def _get_hooks_client(extras):
187 hooks_uri = extras.get('hooks_uri')
188 142 task_queue = extras.get('task_queue')
189 143 task_backend = extras.get('task_backend')
190 144 is_shadow_repo = extras.get('is_shadow_repo')
191 145
192 if hooks_uri:
193 return HooksHttpClient(hooks_uri)
194 elif task_queue and task_backend:
146 if task_queue and task_backend:
195 147 return HooksCeleryClient(task_queue, task_backend)
196 148 elif is_shadow_repo:
197 149 return HooksShadowRepoClient()
@@ -15,17 +15,11 b''
15 15 # along with this program; if not, write to the Free Software Foundation,
16 16 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 17
18 import threading
19 import msgpack
20
21 from http.server import BaseHTTPRequestHandler
22 from socketserver import TCPServer
18 import pytest
23 19
24 20 import mercurial.ui
25 21 import mock
26 import pytest
27 22
28 from vcsserver.hooks import HooksHttpClient
29 23 from vcsserver.lib.ext_json import json
30 24 from vcsserver import hooks
31 25
@@ -41,7 +35,6 b' def get_hg_ui(extras=None):'
41 35 'make_lock': '',
42 36 'action': '',
43 37 'ip': '',
44 'hooks_uri': 'fake_hooks_uri',
45 38 }
46 39 required_extras.update(extras)
47 40 hg_ui = mercurial.ui.ui()
@@ -123,15 +116,6 b' def test_git_post_pull_is_disabled():'
123 116
124 117 class TestGetHooksClient:
125 118
126 def test_returns_http_client_when_protocol_matches(self):
127 hooks_uri = 'localhost:8000'
128 result = hooks._get_hooks_client({
129 'hooks_uri': hooks_uri,
130 'hooks_protocol': 'http'
131 })
132 assert isinstance(result, hooks.HooksHttpClient)
133 assert result.hooks_uri == hooks_uri
134
135 119 def test_return_celery_client_when_queue_and_backend_provided(self):
136 120 task_queue = 'redis://task_queue:0'
137 121 task_backend = task_queue
@@ -142,116 +126,10 b' class TestGetHooksClient:'
142 126 assert isinstance(result, hooks.HooksCeleryClient)
143 127
144 128
145 class TestHooksHttpClient:
146 def test_init_sets_hooks_uri(self):
147 uri = 'localhost:3000'
148 client = hooks.HooksHttpClient(uri)
149 assert client.hooks_uri == uri
150
151 def test_serialize_returns_serialized_string(self):
152 client = hooks.HooksHttpClient('localhost:3000')
153 hook_name = 'test'
154 extras = {
155 'first': 1,
156 'second': 'two'
157 }
158 hooks_proto, result = client._serialize(hook_name, extras)
159 expected_result = msgpack.packb({
160 'method': hook_name,
161 'extras': extras,
162 })
163 assert hooks_proto == {'rc-hooks-protocol': 'msgpack.v1', 'Connection': 'keep-alive'}
164 assert result == expected_result
165
166 def test_call_queries_http_server(self, http_mirror):
167 client = hooks.HooksHttpClient(http_mirror.uri)
168 hook_name = 'test'
169 extras = {
170 'first': 1,
171 'second': 'two'
172 }
173 result = client(hook_name, extras)
174 expected_result = msgpack.unpackb(msgpack.packb({
175 'method': hook_name,
176 'extras': extras
177 }), raw=False)
178 assert result == expected_result
179
180
181 @pytest.fixture
182 def http_mirror(request):
183 server = MirrorHttpServer()
184 request.addfinalizer(server.stop)
185 return server
186
187
188 class MirrorHttpHandler(BaseHTTPRequestHandler):
189
190 def do_POST(self):
191 length = int(self.headers['Content-Length'])
192 body = self.rfile.read(length)
193 self.send_response(200)
194 self.end_headers()
195 self.wfile.write(body)
196
197
198 class MirrorHttpServer:
199 ip_address = '127.0.0.1'
200 port = 0
129 class TestHooksCeleryClient:
201 130
202 def __init__(self):
203 self._daemon = TCPServer((self.ip_address, 0), MirrorHttpHandler)
204 _, self.port = self._daemon.server_address
205 self._thread = threading.Thread(target=self._daemon.serve_forever)
206 self._thread.daemon = True
207 self._thread.start()
208
209 def stop(self):
210 self._daemon.shutdown()
211 self._thread.join()
212 self._daemon = None
213 self._thread = None
214
215 @property
216 def uri(self):
217 return '{}:{}'.format(self.ip_address, self.port)
218
219
220 def test_hooks_http_client_init():
221 hooks_uri = 'http://localhost:8000'
222 client = HooksHttpClient(hooks_uri)
223 assert client.hooks_uri == hooks_uri
224
225
226 def test_hooks_http_client_call():
227 hooks_uri = 'http://localhost:8000'
228
229 method = 'test_method'
230 extras = {'key': 'value'}
231
232 with \
233 mock.patch('http.client.HTTPConnection') as mock_connection,\
234 mock.patch('msgpack.load') as mock_load:
235
236 client = HooksHttpClient(hooks_uri)
237
238 mock_load.return_value = {'result': 'success'}
239 response = mock.MagicMock()
240 response.status = 200
241 mock_connection.request.side_effect = None
242 mock_connection.getresponse.return_value = response
243
244 result = client(method, extras)
245
246 mock_connection.assert_called_with(hooks_uri)
247 mock_connection.return_value.request.assert_called_once()
248 assert result == {'result': 'success'}
249
250
251 def test_hooks_http_client_serialize():
252 method = 'test_method'
253 extras = {'key': 'value'}
254 headers, body = HooksHttpClient._serialize(method, extras)
255
256 assert headers == {'rc-hooks-protocol': HooksHttpClient.proto, 'Connection': 'keep-alive'}
257 assert msgpack.unpackb(body) == {'method': method, 'extras': extras}
131 def test_hooks_http_client_init(self):
132 queue = 'redis://redis:6379/0'
133 backend = 'redis://redis:6379/0'
134 client = hooks.HooksCeleryClient(queue, backend)
135 assert client.celery_app.conf.broker_url == queue
General Comments 0
You need to be logged in to leave comments. Login now