##// END OF EJS Templates
metrics: remove bootstrap timing, as its not usefull at all....
super-admin -
r4813:5072ed70 default
parent child Browse files
Show More
@@ -1,800 +1,794 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2020 RhodeCode GmbH
3 # Copyright (C) 2010-2020 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
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
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
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/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import os
21 import os
22 import sys
22 import sys
23 import logging
23 import logging
24 import collections
24 import collections
25 import tempfile
25 import tempfile
26 import time
26 import time
27
27
28 from paste.gzipper import make_gzip_middleware
28 from paste.gzipper import make_gzip_middleware
29 import pyramid.events
29 import pyramid.events
30 from pyramid.wsgi import wsgiapp
30 from pyramid.wsgi import wsgiapp
31 from pyramid.authorization import ACLAuthorizationPolicy
31 from pyramid.authorization import ACLAuthorizationPolicy
32 from pyramid.config import Configurator
32 from pyramid.config import Configurator
33 from pyramid.settings import asbool, aslist
33 from pyramid.settings import asbool, aslist
34 from pyramid.httpexceptions import (
34 from pyramid.httpexceptions import (
35 HTTPException, HTTPError, HTTPInternalServerError, HTTPFound, HTTPNotFound)
35 HTTPException, HTTPError, HTTPInternalServerError, HTTPFound, HTTPNotFound)
36 from pyramid.renderers import render_to_response
36 from pyramid.renderers import render_to_response
37
37
38 from rhodecode.model import meta
38 from rhodecode.model import meta
39 from rhodecode.config import patches
39 from rhodecode.config import patches
40 from rhodecode.config import utils as config_utils
40 from rhodecode.config import utils as config_utils
41 from rhodecode.config.environment import load_pyramid_environment
41 from rhodecode.config.environment import load_pyramid_environment
42
42
43 import rhodecode.events
43 import rhodecode.events
44 from rhodecode.lib.middleware.vcs import VCSMiddleware
44 from rhodecode.lib.middleware.vcs import VCSMiddleware
45 from rhodecode.lib.request import Request
45 from rhodecode.lib.request import Request
46 from rhodecode.lib.vcs import VCSCommunicationError
46 from rhodecode.lib.vcs import VCSCommunicationError
47 from rhodecode.lib.exceptions import VCSServerUnavailable
47 from rhodecode.lib.exceptions import VCSServerUnavailable
48 from rhodecode.lib.middleware.appenlight import wrap_in_appenlight_if_enabled
48 from rhodecode.lib.middleware.appenlight import wrap_in_appenlight_if_enabled
49 from rhodecode.lib.middleware.https_fixup import HttpsFixup
49 from rhodecode.lib.middleware.https_fixup import HttpsFixup
50 from rhodecode.lib.plugins.utils import register_rhodecode_plugin
50 from rhodecode.lib.plugins.utils import register_rhodecode_plugin
51 from rhodecode.lib.utils2 import aslist as rhodecode_aslist, AttributeDict
51 from rhodecode.lib.utils2 import aslist as rhodecode_aslist, AttributeDict
52 from rhodecode.lib.exc_tracking import store_exception
52 from rhodecode.lib.exc_tracking import store_exception
53 from rhodecode.subscribers import (
53 from rhodecode.subscribers import (
54 scan_repositories_if_enabled, write_js_routes_if_enabled,
54 scan_repositories_if_enabled, write_js_routes_if_enabled,
55 write_metadata_if_needed, write_usage_data)
55 write_metadata_if_needed, write_usage_data)
56 from rhodecode.lib.statsd_client import StatsdClient
56 from rhodecode.lib.statsd_client import StatsdClient
57
57
58 log = logging.getLogger(__name__)
58 log = logging.getLogger(__name__)
59
59
60
60
61 def is_http_error(response):
61 def is_http_error(response):
62 # error which should have traceback
62 # error which should have traceback
63 return response.status_code > 499
63 return response.status_code > 499
64
64
65
65
66 def should_load_all():
66 def should_load_all():
67 """
67 """
68 Returns if all application components should be loaded. In some cases it's
68 Returns if all application components should be loaded. In some cases it's
69 desired to skip apps loading for faster shell script execution
69 desired to skip apps loading for faster shell script execution
70 """
70 """
71 ssh_cmd = os.environ.get('RC_CMD_SSH_WRAPPER')
71 ssh_cmd = os.environ.get('RC_CMD_SSH_WRAPPER')
72 if ssh_cmd:
72 if ssh_cmd:
73 return False
73 return False
74
74
75 return True
75 return True
76
76
77
77
78 def make_pyramid_app(global_config, **settings):
78 def make_pyramid_app(global_config, **settings):
79 """
79 """
80 Constructs the WSGI application based on Pyramid.
80 Constructs the WSGI application based on Pyramid.
81
81
82 Specials:
82 Specials:
83
83
84 * The application can also be integrated like a plugin via the call to
84 * The application can also be integrated like a plugin via the call to
85 `includeme`. This is accompanied with the other utility functions which
85 `includeme`. This is accompanied with the other utility functions which
86 are called. Changing this should be done with great care to not break
86 are called. Changing this should be done with great care to not break
87 cases when these fragments are assembled from another place.
87 cases when these fragments are assembled from another place.
88
88
89 """
89 """
90
90
91 # Allows to use format style "{ENV_NAME}" placeholders in the configuration. It
91 # Allows to use format style "{ENV_NAME}" placeholders in the configuration. It
92 # will be replaced by the value of the environment variable "NAME" in this case.
92 # will be replaced by the value of the environment variable "NAME" in this case.
93 start_time = time.time()
93 start_time = time.time()
94 log.info('Pyramid app config starting')
94 log.info('Pyramid app config starting')
95
95
96 # init and bootstrap StatsdClient
96 # init and bootstrap StatsdClient
97 StatsdClient.setup(settings)
97 StatsdClient.setup(settings)
98
98
99 debug = asbool(global_config.get('debug'))
99 debug = asbool(global_config.get('debug'))
100 if debug:
100 if debug:
101 enable_debug()
101 enable_debug()
102
102
103 environ = {'ENV_{}'.format(key): value for key, value in os.environ.items()}
103 environ = {'ENV_{}'.format(key): value for key, value in os.environ.items()}
104
104
105 global_config = _substitute_values(global_config, environ)
105 global_config = _substitute_values(global_config, environ)
106 settings = _substitute_values(settings, environ)
106 settings = _substitute_values(settings, environ)
107
107
108 sanitize_settings_and_apply_defaults(global_config, settings)
108 sanitize_settings_and_apply_defaults(global_config, settings)
109
109
110 config = Configurator(settings=settings)
110 config = Configurator(settings=settings)
111 # Init our statsd at very start
111 # Init our statsd at very start
112 config.registry.statsd = StatsdClient.statsd
112 config.registry.statsd = StatsdClient.statsd
113
113
114 # Apply compatibility patches
114 # Apply compatibility patches
115 patches.inspect_getargspec()
115 patches.inspect_getargspec()
116
116
117 load_pyramid_environment(global_config, settings)
117 load_pyramid_environment(global_config, settings)
118
118
119 # Static file view comes first
119 # Static file view comes first
120 includeme_first(config)
120 includeme_first(config)
121
121
122 includeme(config)
122 includeme(config)
123
123
124 pyramid_app = config.make_wsgi_app()
124 pyramid_app = config.make_wsgi_app()
125 pyramid_app = wrap_app_in_wsgi_middlewares(pyramid_app, config)
125 pyramid_app = wrap_app_in_wsgi_middlewares(pyramid_app, config)
126 pyramid_app.config = config
126 pyramid_app.config = config
127
127
128 config.configure_celery(global_config['__file__'])
128 config.configure_celery(global_config['__file__'])
129
129
130 # creating the app uses a connection - return it after we are done
130 # creating the app uses a connection - return it after we are done
131 meta.Session.remove()
131 meta.Session.remove()
132 statsd = StatsdClient.statsd
133
132
134 total_time = time.time() - start_time
133 total_time = time.time() - start_time
135 log.info('Pyramid app `%s` created and configured in %.2fs',
134 log.info('Pyramid app `%s` created and configured in %.2fs',
136 pyramid_app.func_name, total_time)
135 pyramid_app.func_name, total_time)
137 if statsd:
138 elapsed_time_ms = round(1000.0 * total_time) # use ms only rounded time
139 statsd.timing('rhodecode_app_bootstrap_timing', elapsed_time_ms, tags=[
140 "pyramid_app:{}".format(pyramid_app.func_name)
141 ], use_decimals=False)
142 return pyramid_app
136 return pyramid_app
143
137
144
138
145 def not_found_view(request):
139 def not_found_view(request):
146 """
140 """
147 This creates the view which should be registered as not-found-view to
141 This creates the view which should be registered as not-found-view to
148 pyramid.
142 pyramid.
149 """
143 """
150
144
151 if not getattr(request, 'vcs_call', None):
145 if not getattr(request, 'vcs_call', None):
152 # handle like regular case with our error_handler
146 # handle like regular case with our error_handler
153 return error_handler(HTTPNotFound(), request)
147 return error_handler(HTTPNotFound(), request)
154
148
155 # handle not found view as a vcs call
149 # handle not found view as a vcs call
156 settings = request.registry.settings
150 settings = request.registry.settings
157 ae_client = getattr(request, 'ae_client', None)
151 ae_client = getattr(request, 'ae_client', None)
158 vcs_app = VCSMiddleware(
152 vcs_app = VCSMiddleware(
159 HTTPNotFound(), request.registry, settings,
153 HTTPNotFound(), request.registry, settings,
160 appenlight_client=ae_client)
154 appenlight_client=ae_client)
161
155
162 return wsgiapp(vcs_app)(None, request)
156 return wsgiapp(vcs_app)(None, request)
163
157
164
158
165 def error_handler(exception, request):
159 def error_handler(exception, request):
166 import rhodecode
160 import rhodecode
167 from rhodecode.lib import helpers
161 from rhodecode.lib import helpers
168 from rhodecode.lib.utils2 import str2bool
162 from rhodecode.lib.utils2 import str2bool
169
163
170 rhodecode_title = rhodecode.CONFIG.get('rhodecode_title') or 'RhodeCode'
164 rhodecode_title = rhodecode.CONFIG.get('rhodecode_title') or 'RhodeCode'
171
165
172 base_response = HTTPInternalServerError()
166 base_response = HTTPInternalServerError()
173 # prefer original exception for the response since it may have headers set
167 # prefer original exception for the response since it may have headers set
174 if isinstance(exception, HTTPException):
168 if isinstance(exception, HTTPException):
175 base_response = exception
169 base_response = exception
176 elif isinstance(exception, VCSCommunicationError):
170 elif isinstance(exception, VCSCommunicationError):
177 base_response = VCSServerUnavailable()
171 base_response = VCSServerUnavailable()
178
172
179 if is_http_error(base_response):
173 if is_http_error(base_response):
180 log.exception(
174 log.exception(
181 'error occurred handling this request for path: %s', request.path)
175 'error occurred handling this request for path: %s', request.path)
182
176
183 error_explanation = base_response.explanation or str(base_response)
177 error_explanation = base_response.explanation or str(base_response)
184 if base_response.status_code == 404:
178 if base_response.status_code == 404:
185 error_explanation += " Optionally you don't have permission to access this page."
179 error_explanation += " Optionally you don't have permission to access this page."
186 c = AttributeDict()
180 c = AttributeDict()
187 c.error_message = base_response.status
181 c.error_message = base_response.status
188 c.error_explanation = error_explanation
182 c.error_explanation = error_explanation
189 c.visual = AttributeDict()
183 c.visual = AttributeDict()
190
184
191 c.visual.rhodecode_support_url = (
185 c.visual.rhodecode_support_url = (
192 request.registry.settings.get('rhodecode_support_url') or
186 request.registry.settings.get('rhodecode_support_url') or
193 request.route_url('rhodecode_support')
187 request.route_url('rhodecode_support')
194 )
188 )
195 c.redirect_time = 0
189 c.redirect_time = 0
196 c.rhodecode_name = rhodecode_title
190 c.rhodecode_name = rhodecode_title
197 if not c.rhodecode_name:
191 if not c.rhodecode_name:
198 c.rhodecode_name = 'Rhodecode'
192 c.rhodecode_name = 'Rhodecode'
199
193
200 c.causes = []
194 c.causes = []
201 if is_http_error(base_response):
195 if is_http_error(base_response):
202 c.causes.append('Server is overloaded.')
196 c.causes.append('Server is overloaded.')
203 c.causes.append('Server database connection is lost.')
197 c.causes.append('Server database connection is lost.')
204 c.causes.append('Server expected unhandled error.')
198 c.causes.append('Server expected unhandled error.')
205
199
206 if hasattr(base_response, 'causes'):
200 if hasattr(base_response, 'causes'):
207 c.causes = base_response.causes
201 c.causes = base_response.causes
208
202
209 c.messages = helpers.flash.pop_messages(request=request)
203 c.messages = helpers.flash.pop_messages(request=request)
210
204
211 exc_info = sys.exc_info()
205 exc_info = sys.exc_info()
212 c.exception_id = id(exc_info)
206 c.exception_id = id(exc_info)
213 c.show_exception_id = isinstance(base_response, VCSServerUnavailable) \
207 c.show_exception_id = isinstance(base_response, VCSServerUnavailable) \
214 or base_response.status_code > 499
208 or base_response.status_code > 499
215 c.exception_id_url = request.route_url(
209 c.exception_id_url = request.route_url(
216 'admin_settings_exception_tracker_show', exception_id=c.exception_id)
210 'admin_settings_exception_tracker_show', exception_id=c.exception_id)
217
211
218 if c.show_exception_id:
212 if c.show_exception_id:
219 store_exception(c.exception_id, exc_info)
213 store_exception(c.exception_id, exc_info)
220 c.exception_debug = str2bool(rhodecode.CONFIG.get('debug'))
214 c.exception_debug = str2bool(rhodecode.CONFIG.get('debug'))
221 c.exception_config_ini = rhodecode.CONFIG.get('__file__')
215 c.exception_config_ini = rhodecode.CONFIG.get('__file__')
222
216
223 response = render_to_response(
217 response = render_to_response(
224 '/errors/error_document.mako', {'c': c, 'h': helpers}, request=request,
218 '/errors/error_document.mako', {'c': c, 'h': helpers}, request=request,
225 response=base_response)
219 response=base_response)
226
220
227 statsd = request.registry.statsd
221 statsd = request.registry.statsd
228 if statsd and base_response.status_code > 499:
222 if statsd and base_response.status_code > 499:
229 exc_type = "{}.{}".format(exception.__class__.__module__, exception.__class__.__name__)
223 exc_type = "{}.{}".format(exception.__class__.__module__, exception.__class__.__name__)
230 statsd.incr('rhodecode_exception_total',
224 statsd.incr('rhodecode_exception_total',
231 tags=["exc_source:web",
225 tags=["exc_source:web",
232 "http_code:{}".format(base_response.status_code),
226 "http_code:{}".format(base_response.status_code),
233 "type:{}".format(exc_type)])
227 "type:{}".format(exc_type)])
234
228
235 return response
229 return response
236
230
237
231
238 def includeme_first(config):
232 def includeme_first(config):
239 # redirect automatic browser favicon.ico requests to correct place
233 # redirect automatic browser favicon.ico requests to correct place
240 def favicon_redirect(context, request):
234 def favicon_redirect(context, request):
241 return HTTPFound(
235 return HTTPFound(
242 request.static_path('rhodecode:public/images/favicon.ico'))
236 request.static_path('rhodecode:public/images/favicon.ico'))
243
237
244 config.add_view(favicon_redirect, route_name='favicon')
238 config.add_view(favicon_redirect, route_name='favicon')
245 config.add_route('favicon', '/favicon.ico')
239 config.add_route('favicon', '/favicon.ico')
246
240
247 def robots_redirect(context, request):
241 def robots_redirect(context, request):
248 return HTTPFound(
242 return HTTPFound(
249 request.static_path('rhodecode:public/robots.txt'))
243 request.static_path('rhodecode:public/robots.txt'))
250
244
251 config.add_view(robots_redirect, route_name='robots')
245 config.add_view(robots_redirect, route_name='robots')
252 config.add_route('robots', '/robots.txt')
246 config.add_route('robots', '/robots.txt')
253
247
254 config.add_static_view(
248 config.add_static_view(
255 '_static/deform', 'deform:static')
249 '_static/deform', 'deform:static')
256 config.add_static_view(
250 config.add_static_view(
257 '_static/rhodecode', path='rhodecode:public', cache_max_age=3600 * 24)
251 '_static/rhodecode', path='rhodecode:public', cache_max_age=3600 * 24)
258
252
259
253
260 def includeme(config, auth_resources=None):
254 def includeme(config, auth_resources=None):
261 from rhodecode.lib.celerylib.loader import configure_celery
255 from rhodecode.lib.celerylib.loader import configure_celery
262 log.debug('Initializing main includeme from %s', os.path.basename(__file__))
256 log.debug('Initializing main includeme from %s', os.path.basename(__file__))
263 settings = config.registry.settings
257 settings = config.registry.settings
264 config.set_request_factory(Request)
258 config.set_request_factory(Request)
265
259
266 # plugin information
260 # plugin information
267 config.registry.rhodecode_plugins = collections.OrderedDict()
261 config.registry.rhodecode_plugins = collections.OrderedDict()
268
262
269 config.add_directive(
263 config.add_directive(
270 'register_rhodecode_plugin', register_rhodecode_plugin)
264 'register_rhodecode_plugin', register_rhodecode_plugin)
271
265
272 config.add_directive('configure_celery', configure_celery)
266 config.add_directive('configure_celery', configure_celery)
273
267
274 if asbool(settings.get('appenlight', 'false')):
268 if asbool(settings.get('appenlight', 'false')):
275 config.include('appenlight_client.ext.pyramid_tween')
269 config.include('appenlight_client.ext.pyramid_tween')
276
270
277 load_all = should_load_all()
271 load_all = should_load_all()
278
272
279 # Includes which are required. The application would fail without them.
273 # Includes which are required. The application would fail without them.
280 config.include('pyramid_mako')
274 config.include('pyramid_mako')
281 config.include('rhodecode.lib.rc_beaker')
275 config.include('rhodecode.lib.rc_beaker')
282 config.include('rhodecode.lib.rc_cache')
276 config.include('rhodecode.lib.rc_cache')
283 config.include('rhodecode.apps._base.navigation')
277 config.include('rhodecode.apps._base.navigation')
284 config.include('rhodecode.apps._base.subscribers')
278 config.include('rhodecode.apps._base.subscribers')
285 config.include('rhodecode.tweens')
279 config.include('rhodecode.tweens')
286 config.include('rhodecode.authentication')
280 config.include('rhodecode.authentication')
287
281
288 if load_all:
282 if load_all:
289 ce_auth_resources = [
283 ce_auth_resources = [
290 'rhodecode.authentication.plugins.auth_crowd',
284 'rhodecode.authentication.plugins.auth_crowd',
291 'rhodecode.authentication.plugins.auth_headers',
285 'rhodecode.authentication.plugins.auth_headers',
292 'rhodecode.authentication.plugins.auth_jasig_cas',
286 'rhodecode.authentication.plugins.auth_jasig_cas',
293 'rhodecode.authentication.plugins.auth_ldap',
287 'rhodecode.authentication.plugins.auth_ldap',
294 'rhodecode.authentication.plugins.auth_pam',
288 'rhodecode.authentication.plugins.auth_pam',
295 'rhodecode.authentication.plugins.auth_rhodecode',
289 'rhodecode.authentication.plugins.auth_rhodecode',
296 'rhodecode.authentication.plugins.auth_token',
290 'rhodecode.authentication.plugins.auth_token',
297 ]
291 ]
298
292
299 # load CE authentication plugins
293 # load CE authentication plugins
300
294
301 if auth_resources:
295 if auth_resources:
302 ce_auth_resources.extend(auth_resources)
296 ce_auth_resources.extend(auth_resources)
303
297
304 for resource in ce_auth_resources:
298 for resource in ce_auth_resources:
305 config.include(resource)
299 config.include(resource)
306
300
307 # Auto discover authentication plugins and include their configuration.
301 # Auto discover authentication plugins and include their configuration.
308 if asbool(settings.get('auth_plugin.import_legacy_plugins', 'true')):
302 if asbool(settings.get('auth_plugin.import_legacy_plugins', 'true')):
309 from rhodecode.authentication import discover_legacy_plugins
303 from rhodecode.authentication import discover_legacy_plugins
310 discover_legacy_plugins(config)
304 discover_legacy_plugins(config)
311
305
312 # apps
306 # apps
313 if load_all:
307 if load_all:
314 config.include('rhodecode.api')
308 config.include('rhodecode.api')
315 config.include('rhodecode.apps._base')
309 config.include('rhodecode.apps._base')
316 config.include('rhodecode.apps.hovercards')
310 config.include('rhodecode.apps.hovercards')
317 config.include('rhodecode.apps.ops')
311 config.include('rhodecode.apps.ops')
318 config.include('rhodecode.apps.channelstream')
312 config.include('rhodecode.apps.channelstream')
319 config.include('rhodecode.apps.file_store')
313 config.include('rhodecode.apps.file_store')
320 config.include('rhodecode.apps.admin')
314 config.include('rhodecode.apps.admin')
321 config.include('rhodecode.apps.login')
315 config.include('rhodecode.apps.login')
322 config.include('rhodecode.apps.home')
316 config.include('rhodecode.apps.home')
323 config.include('rhodecode.apps.journal')
317 config.include('rhodecode.apps.journal')
324
318
325 config.include('rhodecode.apps.repository')
319 config.include('rhodecode.apps.repository')
326 config.include('rhodecode.apps.repo_group')
320 config.include('rhodecode.apps.repo_group')
327 config.include('rhodecode.apps.user_group')
321 config.include('rhodecode.apps.user_group')
328 config.include('rhodecode.apps.search')
322 config.include('rhodecode.apps.search')
329 config.include('rhodecode.apps.user_profile')
323 config.include('rhodecode.apps.user_profile')
330 config.include('rhodecode.apps.user_group_profile')
324 config.include('rhodecode.apps.user_group_profile')
331 config.include('rhodecode.apps.my_account')
325 config.include('rhodecode.apps.my_account')
332 config.include('rhodecode.apps.gist')
326 config.include('rhodecode.apps.gist')
333
327
334 config.include('rhodecode.apps.svn_support')
328 config.include('rhodecode.apps.svn_support')
335 config.include('rhodecode.apps.ssh_support')
329 config.include('rhodecode.apps.ssh_support')
336 config.include('rhodecode.apps.debug_style')
330 config.include('rhodecode.apps.debug_style')
337
331
338 if load_all:
332 if load_all:
339 config.include('rhodecode.integrations')
333 config.include('rhodecode.integrations')
340
334
341 config.add_route('rhodecode_support', 'https://rhodecode.com/help/', static=True)
335 config.add_route('rhodecode_support', 'https://rhodecode.com/help/', static=True)
342 config.add_translation_dirs('rhodecode:i18n/')
336 config.add_translation_dirs('rhodecode:i18n/')
343 settings['default_locale_name'] = settings.get('lang', 'en')
337 settings['default_locale_name'] = settings.get('lang', 'en')
344
338
345 # Add subscribers.
339 # Add subscribers.
346 if load_all:
340 if load_all:
347 config.add_subscriber(scan_repositories_if_enabled,
341 config.add_subscriber(scan_repositories_if_enabled,
348 pyramid.events.ApplicationCreated)
342 pyramid.events.ApplicationCreated)
349 config.add_subscriber(write_metadata_if_needed,
343 config.add_subscriber(write_metadata_if_needed,
350 pyramid.events.ApplicationCreated)
344 pyramid.events.ApplicationCreated)
351 config.add_subscriber(write_usage_data,
345 config.add_subscriber(write_usage_data,
352 pyramid.events.ApplicationCreated)
346 pyramid.events.ApplicationCreated)
353 config.add_subscriber(write_js_routes_if_enabled,
347 config.add_subscriber(write_js_routes_if_enabled,
354 pyramid.events.ApplicationCreated)
348 pyramid.events.ApplicationCreated)
355
349
356 # request custom methods
350 # request custom methods
357 config.add_request_method(
351 config.add_request_method(
358 'rhodecode.lib.partial_renderer.get_partial_renderer',
352 'rhodecode.lib.partial_renderer.get_partial_renderer',
359 'get_partial_renderer')
353 'get_partial_renderer')
360
354
361 config.add_request_method(
355 config.add_request_method(
362 'rhodecode.lib.request_counter.get_request_counter',
356 'rhodecode.lib.request_counter.get_request_counter',
363 'request_count')
357 'request_count')
364
358
365 # Set the authorization policy.
359 # Set the authorization policy.
366 authz_policy = ACLAuthorizationPolicy()
360 authz_policy = ACLAuthorizationPolicy()
367 config.set_authorization_policy(authz_policy)
361 config.set_authorization_policy(authz_policy)
368
362
369 # Set the default renderer for HTML templates to mako.
363 # Set the default renderer for HTML templates to mako.
370 config.add_mako_renderer('.html')
364 config.add_mako_renderer('.html')
371
365
372 config.add_renderer(
366 config.add_renderer(
373 name='json_ext',
367 name='json_ext',
374 factory='rhodecode.lib.ext_json_renderer.pyramid_ext_json')
368 factory='rhodecode.lib.ext_json_renderer.pyramid_ext_json')
375
369
376 config.add_renderer(
370 config.add_renderer(
377 name='string_html',
371 name='string_html',
378 factory='rhodecode.lib.string_renderer.html')
372 factory='rhodecode.lib.string_renderer.html')
379
373
380 # include RhodeCode plugins
374 # include RhodeCode plugins
381 includes = aslist(settings.get('rhodecode.includes', []))
375 includes = aslist(settings.get('rhodecode.includes', []))
382 for inc in includes:
376 for inc in includes:
383 config.include(inc)
377 config.include(inc)
384
378
385 # custom not found view, if our pyramid app doesn't know how to handle
379 # custom not found view, if our pyramid app doesn't know how to handle
386 # the request pass it to potential VCS handling ap
380 # the request pass it to potential VCS handling ap
387 config.add_notfound_view(not_found_view)
381 config.add_notfound_view(not_found_view)
388 if not settings.get('debugtoolbar.enabled', False):
382 if not settings.get('debugtoolbar.enabled', False):
389 # disabled debugtoolbar handle all exceptions via the error_handlers
383 # disabled debugtoolbar handle all exceptions via the error_handlers
390 config.add_view(error_handler, context=Exception)
384 config.add_view(error_handler, context=Exception)
391
385
392 # all errors including 403/404/50X
386 # all errors including 403/404/50X
393 config.add_view(error_handler, context=HTTPError)
387 config.add_view(error_handler, context=HTTPError)
394
388
395
389
396 def wrap_app_in_wsgi_middlewares(pyramid_app, config):
390 def wrap_app_in_wsgi_middlewares(pyramid_app, config):
397 """
391 """
398 Apply outer WSGI middlewares around the application.
392 Apply outer WSGI middlewares around the application.
399 """
393 """
400 registry = config.registry
394 registry = config.registry
401 settings = registry.settings
395 settings = registry.settings
402
396
403 # enable https redirects based on HTTP_X_URL_SCHEME set by proxy
397 # enable https redirects based on HTTP_X_URL_SCHEME set by proxy
404 pyramid_app = HttpsFixup(pyramid_app, settings)
398 pyramid_app = HttpsFixup(pyramid_app, settings)
405
399
406 pyramid_app, _ae_client = wrap_in_appenlight_if_enabled(
400 pyramid_app, _ae_client = wrap_in_appenlight_if_enabled(
407 pyramid_app, settings)
401 pyramid_app, settings)
408 registry.ae_client = _ae_client
402 registry.ae_client = _ae_client
409
403
410 if settings['gzip_responses']:
404 if settings['gzip_responses']:
411 pyramid_app = make_gzip_middleware(
405 pyramid_app = make_gzip_middleware(
412 pyramid_app, settings, compress_level=1)
406 pyramid_app, settings, compress_level=1)
413
407
414 # this should be the outer most middleware in the wsgi stack since
408 # this should be the outer most middleware in the wsgi stack since
415 # middleware like Routes make database calls
409 # middleware like Routes make database calls
416 def pyramid_app_with_cleanup(environ, start_response):
410 def pyramid_app_with_cleanup(environ, start_response):
417 try:
411 try:
418 return pyramid_app(environ, start_response)
412 return pyramid_app(environ, start_response)
419 finally:
413 finally:
420 # Dispose current database session and rollback uncommitted
414 # Dispose current database session and rollback uncommitted
421 # transactions.
415 # transactions.
422 meta.Session.remove()
416 meta.Session.remove()
423
417
424 # In a single threaded mode server, on non sqlite db we should have
418 # In a single threaded mode server, on non sqlite db we should have
425 # '0 Current Checked out connections' at the end of a request,
419 # '0 Current Checked out connections' at the end of a request,
426 # if not, then something, somewhere is leaving a connection open
420 # if not, then something, somewhere is leaving a connection open
427 pool = meta.Base.metadata.bind.engine.pool
421 pool = meta.Base.metadata.bind.engine.pool
428 log.debug('sa pool status: %s', pool.status())
422 log.debug('sa pool status: %s', pool.status())
429 log.debug('Request processing finalized')
423 log.debug('Request processing finalized')
430
424
431 return pyramid_app_with_cleanup
425 return pyramid_app_with_cleanup
432
426
433
427
434 def sanitize_settings_and_apply_defaults(global_config, settings):
428 def sanitize_settings_and_apply_defaults(global_config, settings):
435 """
429 """
436 Applies settings defaults and does all type conversion.
430 Applies settings defaults and does all type conversion.
437
431
438 We would move all settings parsing and preparation into this place, so that
432 We would move all settings parsing and preparation into this place, so that
439 we have only one place left which deals with this part. The remaining parts
433 we have only one place left which deals with this part. The remaining parts
440 of the application would start to rely fully on well prepared settings.
434 of the application would start to rely fully on well prepared settings.
441
435
442 This piece would later be split up per topic to avoid a big fat monster
436 This piece would later be split up per topic to avoid a big fat monster
443 function.
437 function.
444 """
438 """
445
439
446 settings.setdefault('rhodecode.edition', 'Community Edition')
440 settings.setdefault('rhodecode.edition', 'Community Edition')
447 settings.setdefault('rhodecode.edition_id', 'CE')
441 settings.setdefault('rhodecode.edition_id', 'CE')
448
442
449 if 'mako.default_filters' not in settings:
443 if 'mako.default_filters' not in settings:
450 # set custom default filters if we don't have it defined
444 # set custom default filters if we don't have it defined
451 settings['mako.imports'] = 'from rhodecode.lib.base import h_filter'
445 settings['mako.imports'] = 'from rhodecode.lib.base import h_filter'
452 settings['mako.default_filters'] = 'h_filter'
446 settings['mako.default_filters'] = 'h_filter'
453
447
454 if 'mako.directories' not in settings:
448 if 'mako.directories' not in settings:
455 mako_directories = settings.setdefault('mako.directories', [
449 mako_directories = settings.setdefault('mako.directories', [
456 # Base templates of the original application
450 # Base templates of the original application
457 'rhodecode:templates',
451 'rhodecode:templates',
458 ])
452 ])
459 log.debug(
453 log.debug(
460 "Using the following Mako template directories: %s",
454 "Using the following Mako template directories: %s",
461 mako_directories)
455 mako_directories)
462
456
463 # NOTE(marcink): fix redis requirement for schema of connection since 3.X
457 # NOTE(marcink): fix redis requirement for schema of connection since 3.X
464 if 'beaker.session.type' in settings and settings['beaker.session.type'] == 'ext:redis':
458 if 'beaker.session.type' in settings and settings['beaker.session.type'] == 'ext:redis':
465 raw_url = settings['beaker.session.url']
459 raw_url = settings['beaker.session.url']
466 if not raw_url.startswith(('redis://', 'rediss://', 'unix://')):
460 if not raw_url.startswith(('redis://', 'rediss://', 'unix://')):
467 settings['beaker.session.url'] = 'redis://' + raw_url
461 settings['beaker.session.url'] = 'redis://' + raw_url
468
462
469 # Default includes, possible to change as a user
463 # Default includes, possible to change as a user
470 pyramid_includes = settings.setdefault('pyramid.includes', [])
464 pyramid_includes = settings.setdefault('pyramid.includes', [])
471 log.debug(
465 log.debug(
472 "Using the following pyramid.includes: %s",
466 "Using the following pyramid.includes: %s",
473 pyramid_includes)
467 pyramid_includes)
474
468
475 # TODO: johbo: Re-think this, usually the call to config.include
469 # TODO: johbo: Re-think this, usually the call to config.include
476 # should allow to pass in a prefix.
470 # should allow to pass in a prefix.
477 settings.setdefault('rhodecode.api.url', '/_admin/api')
471 settings.setdefault('rhodecode.api.url', '/_admin/api')
478 settings.setdefault('__file__', global_config.get('__file__'))
472 settings.setdefault('__file__', global_config.get('__file__'))
479
473
480 # Sanitize generic settings.
474 # Sanitize generic settings.
481 _list_setting(settings, 'default_encoding', 'UTF-8')
475 _list_setting(settings, 'default_encoding', 'UTF-8')
482 _bool_setting(settings, 'is_test', 'false')
476 _bool_setting(settings, 'is_test', 'false')
483 _bool_setting(settings, 'gzip_responses', 'false')
477 _bool_setting(settings, 'gzip_responses', 'false')
484
478
485 # Call split out functions that sanitize settings for each topic.
479 # Call split out functions that sanitize settings for each topic.
486 _sanitize_appenlight_settings(settings)
480 _sanitize_appenlight_settings(settings)
487 _sanitize_vcs_settings(settings)
481 _sanitize_vcs_settings(settings)
488 _sanitize_cache_settings(settings)
482 _sanitize_cache_settings(settings)
489
483
490 # configure instance id
484 # configure instance id
491 config_utils.set_instance_id(settings)
485 config_utils.set_instance_id(settings)
492
486
493 return settings
487 return settings
494
488
495
489
496 def enable_debug():
490 def enable_debug():
497 """
491 """
498 Helper to enable debug on running instance
492 Helper to enable debug on running instance
499 :return:
493 :return:
500 """
494 """
501 import tempfile
495 import tempfile
502 import textwrap
496 import textwrap
503 import logging.config
497 import logging.config
504
498
505 ini_template = textwrap.dedent("""
499 ini_template = textwrap.dedent("""
506 #####################################
500 #####################################
507 ### DEBUG LOGGING CONFIGURATION ####
501 ### DEBUG LOGGING CONFIGURATION ####
508 #####################################
502 #####################################
509 [loggers]
503 [loggers]
510 keys = root, sqlalchemy, beaker, celery, rhodecode, ssh_wrapper
504 keys = root, sqlalchemy, beaker, celery, rhodecode, ssh_wrapper
511
505
512 [handlers]
506 [handlers]
513 keys = console, console_sql
507 keys = console, console_sql
514
508
515 [formatters]
509 [formatters]
516 keys = generic, color_formatter, color_formatter_sql
510 keys = generic, color_formatter, color_formatter_sql
517
511
518 #############
512 #############
519 ## LOGGERS ##
513 ## LOGGERS ##
520 #############
514 #############
521 [logger_root]
515 [logger_root]
522 level = NOTSET
516 level = NOTSET
523 handlers = console
517 handlers = console
524
518
525 [logger_sqlalchemy]
519 [logger_sqlalchemy]
526 level = INFO
520 level = INFO
527 handlers = console_sql
521 handlers = console_sql
528 qualname = sqlalchemy.engine
522 qualname = sqlalchemy.engine
529 propagate = 0
523 propagate = 0
530
524
531 [logger_beaker]
525 [logger_beaker]
532 level = DEBUG
526 level = DEBUG
533 handlers =
527 handlers =
534 qualname = beaker.container
528 qualname = beaker.container
535 propagate = 1
529 propagate = 1
536
530
537 [logger_rhodecode]
531 [logger_rhodecode]
538 level = DEBUG
532 level = DEBUG
539 handlers =
533 handlers =
540 qualname = rhodecode
534 qualname = rhodecode
541 propagate = 1
535 propagate = 1
542
536
543 [logger_ssh_wrapper]
537 [logger_ssh_wrapper]
544 level = DEBUG
538 level = DEBUG
545 handlers =
539 handlers =
546 qualname = ssh_wrapper
540 qualname = ssh_wrapper
547 propagate = 1
541 propagate = 1
548
542
549 [logger_celery]
543 [logger_celery]
550 level = DEBUG
544 level = DEBUG
551 handlers =
545 handlers =
552 qualname = celery
546 qualname = celery
553
547
554
548
555 ##############
549 ##############
556 ## HANDLERS ##
550 ## HANDLERS ##
557 ##############
551 ##############
558
552
559 [handler_console]
553 [handler_console]
560 class = StreamHandler
554 class = StreamHandler
561 args = (sys.stderr, )
555 args = (sys.stderr, )
562 level = DEBUG
556 level = DEBUG
563 formatter = color_formatter
557 formatter = color_formatter
564
558
565 [handler_console_sql]
559 [handler_console_sql]
566 # "level = DEBUG" logs SQL queries and results.
560 # "level = DEBUG" logs SQL queries and results.
567 # "level = INFO" logs SQL queries.
561 # "level = INFO" logs SQL queries.
568 # "level = WARN" logs neither. (Recommended for production systems.)
562 # "level = WARN" logs neither. (Recommended for production systems.)
569 class = StreamHandler
563 class = StreamHandler
570 args = (sys.stderr, )
564 args = (sys.stderr, )
571 level = WARN
565 level = WARN
572 formatter = color_formatter_sql
566 formatter = color_formatter_sql
573
567
574 ################
568 ################
575 ## FORMATTERS ##
569 ## FORMATTERS ##
576 ################
570 ################
577
571
578 [formatter_generic]
572 [formatter_generic]
579 class = rhodecode.lib.logging_formatter.ExceptionAwareFormatter
573 class = rhodecode.lib.logging_formatter.ExceptionAwareFormatter
580 format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s | %(req_id)s
574 format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s | %(req_id)s
581 datefmt = %Y-%m-%d %H:%M:%S
575 datefmt = %Y-%m-%d %H:%M:%S
582
576
583 [formatter_color_formatter]
577 [formatter_color_formatter]
584 class = rhodecode.lib.logging_formatter.ColorRequestTrackingFormatter
578 class = rhodecode.lib.logging_formatter.ColorRequestTrackingFormatter
585 format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s | %(req_id)s
579 format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s | %(req_id)s
586 datefmt = %Y-%m-%d %H:%M:%S
580 datefmt = %Y-%m-%d %H:%M:%S
587
581
588 [formatter_color_formatter_sql]
582 [formatter_color_formatter_sql]
589 class = rhodecode.lib.logging_formatter.ColorFormatterSql
583 class = rhodecode.lib.logging_formatter.ColorFormatterSql
590 format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s
584 format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s
591 datefmt = %Y-%m-%d %H:%M:%S
585 datefmt = %Y-%m-%d %H:%M:%S
592 """)
586 """)
593
587
594 with tempfile.NamedTemporaryFile(prefix='rc_debug_logging_', suffix='.ini',
588 with tempfile.NamedTemporaryFile(prefix='rc_debug_logging_', suffix='.ini',
595 delete=False) as f:
589 delete=False) as f:
596 log.info('Saved Temporary DEBUG config at %s', f.name)
590 log.info('Saved Temporary DEBUG config at %s', f.name)
597 f.write(ini_template)
591 f.write(ini_template)
598
592
599 logging.config.fileConfig(f.name)
593 logging.config.fileConfig(f.name)
600 log.debug('DEBUG MODE ON')
594 log.debug('DEBUG MODE ON')
601 os.remove(f.name)
595 os.remove(f.name)
602
596
603
597
604 def _sanitize_appenlight_settings(settings):
598 def _sanitize_appenlight_settings(settings):
605 _bool_setting(settings, 'appenlight', 'false')
599 _bool_setting(settings, 'appenlight', 'false')
606
600
607
601
608 def _sanitize_vcs_settings(settings):
602 def _sanitize_vcs_settings(settings):
609 """
603 """
610 Applies settings defaults and does type conversion for all VCS related
604 Applies settings defaults and does type conversion for all VCS related
611 settings.
605 settings.
612 """
606 """
613 _string_setting(settings, 'vcs.svn.compatible_version', '')
607 _string_setting(settings, 'vcs.svn.compatible_version', '')
614 _string_setting(settings, 'vcs.hooks.protocol', 'http')
608 _string_setting(settings, 'vcs.hooks.protocol', 'http')
615 _string_setting(settings, 'vcs.hooks.host', '127.0.0.1')
609 _string_setting(settings, 'vcs.hooks.host', '127.0.0.1')
616 _string_setting(settings, 'vcs.scm_app_implementation', 'http')
610 _string_setting(settings, 'vcs.scm_app_implementation', 'http')
617 _string_setting(settings, 'vcs.server', '')
611 _string_setting(settings, 'vcs.server', '')
618 _string_setting(settings, 'vcs.server.protocol', 'http')
612 _string_setting(settings, 'vcs.server.protocol', 'http')
619 _bool_setting(settings, 'startup.import_repos', 'false')
613 _bool_setting(settings, 'startup.import_repos', 'false')
620 _bool_setting(settings, 'vcs.hooks.direct_calls', 'false')
614 _bool_setting(settings, 'vcs.hooks.direct_calls', 'false')
621 _bool_setting(settings, 'vcs.server.enable', 'true')
615 _bool_setting(settings, 'vcs.server.enable', 'true')
622 _bool_setting(settings, 'vcs.start_server', 'false')
616 _bool_setting(settings, 'vcs.start_server', 'false')
623 _list_setting(settings, 'vcs.backends', 'hg, git, svn')
617 _list_setting(settings, 'vcs.backends', 'hg, git, svn')
624 _int_setting(settings, 'vcs.connection_timeout', 3600)
618 _int_setting(settings, 'vcs.connection_timeout', 3600)
625
619
626 # Support legacy values of vcs.scm_app_implementation. Legacy
620 # Support legacy values of vcs.scm_app_implementation. Legacy
627 # configurations may use 'rhodecode.lib.middleware.utils.scm_app_http', or
621 # configurations may use 'rhodecode.lib.middleware.utils.scm_app_http', or
628 # disabled since 4.13 'vcsserver.scm_app' which is now mapped to 'http'.
622 # disabled since 4.13 'vcsserver.scm_app' which is now mapped to 'http'.
629 scm_app_impl = settings['vcs.scm_app_implementation']
623 scm_app_impl = settings['vcs.scm_app_implementation']
630 if scm_app_impl in ['rhodecode.lib.middleware.utils.scm_app_http', 'vcsserver.scm_app']:
624 if scm_app_impl in ['rhodecode.lib.middleware.utils.scm_app_http', 'vcsserver.scm_app']:
631 settings['vcs.scm_app_implementation'] = 'http'
625 settings['vcs.scm_app_implementation'] = 'http'
632
626
633
627
634 def _sanitize_cache_settings(settings):
628 def _sanitize_cache_settings(settings):
635 temp_store = tempfile.gettempdir()
629 temp_store = tempfile.gettempdir()
636 default_cache_dir = os.path.join(temp_store, 'rc_cache')
630 default_cache_dir = os.path.join(temp_store, 'rc_cache')
637
631
638 # save default, cache dir, and use it for all backends later.
632 # save default, cache dir, and use it for all backends later.
639 default_cache_dir = _string_setting(
633 default_cache_dir = _string_setting(
640 settings,
634 settings,
641 'cache_dir',
635 'cache_dir',
642 default_cache_dir, lower=False, default_when_empty=True)
636 default_cache_dir, lower=False, default_when_empty=True)
643
637
644 # ensure we have our dir created
638 # ensure we have our dir created
645 if not os.path.isdir(default_cache_dir):
639 if not os.path.isdir(default_cache_dir):
646 os.makedirs(default_cache_dir, mode=0o755)
640 os.makedirs(default_cache_dir, mode=0o755)
647
641
648 # exception store cache
642 # exception store cache
649 _string_setting(
643 _string_setting(
650 settings,
644 settings,
651 'exception_tracker.store_path',
645 'exception_tracker.store_path',
652 temp_store, lower=False, default_when_empty=True)
646 temp_store, lower=False, default_when_empty=True)
653 _bool_setting(
647 _bool_setting(
654 settings,
648 settings,
655 'exception_tracker.send_email',
649 'exception_tracker.send_email',
656 'false')
650 'false')
657 _string_setting(
651 _string_setting(
658 settings,
652 settings,
659 'exception_tracker.email_prefix',
653 'exception_tracker.email_prefix',
660 '[RHODECODE ERROR]', lower=False, default_when_empty=True)
654 '[RHODECODE ERROR]', lower=False, default_when_empty=True)
661
655
662 # cache_perms
656 # cache_perms
663 _string_setting(
657 _string_setting(
664 settings,
658 settings,
665 'rc_cache.cache_perms.backend',
659 'rc_cache.cache_perms.backend',
666 'dogpile.cache.rc.file_namespace', lower=False)
660 'dogpile.cache.rc.file_namespace', lower=False)
667 _int_setting(
661 _int_setting(
668 settings,
662 settings,
669 'rc_cache.cache_perms.expiration_time',
663 'rc_cache.cache_perms.expiration_time',
670 60)
664 60)
671 _string_setting(
665 _string_setting(
672 settings,
666 settings,
673 'rc_cache.cache_perms.arguments.filename',
667 'rc_cache.cache_perms.arguments.filename',
674 os.path.join(default_cache_dir, 'rc_cache_1'), lower=False)
668 os.path.join(default_cache_dir, 'rc_cache_1'), lower=False)
675
669
676 # cache_repo
670 # cache_repo
677 _string_setting(
671 _string_setting(
678 settings,
672 settings,
679 'rc_cache.cache_repo.backend',
673 'rc_cache.cache_repo.backend',
680 'dogpile.cache.rc.file_namespace', lower=False)
674 'dogpile.cache.rc.file_namespace', lower=False)
681 _int_setting(
675 _int_setting(
682 settings,
676 settings,
683 'rc_cache.cache_repo.expiration_time',
677 'rc_cache.cache_repo.expiration_time',
684 60)
678 60)
685 _string_setting(
679 _string_setting(
686 settings,
680 settings,
687 'rc_cache.cache_repo.arguments.filename',
681 'rc_cache.cache_repo.arguments.filename',
688 os.path.join(default_cache_dir, 'rc_cache_2'), lower=False)
682 os.path.join(default_cache_dir, 'rc_cache_2'), lower=False)
689
683
690 # cache_license
684 # cache_license
691 _string_setting(
685 _string_setting(
692 settings,
686 settings,
693 'rc_cache.cache_license.backend',
687 'rc_cache.cache_license.backend',
694 'dogpile.cache.rc.file_namespace', lower=False)
688 'dogpile.cache.rc.file_namespace', lower=False)
695 _int_setting(
689 _int_setting(
696 settings,
690 settings,
697 'rc_cache.cache_license.expiration_time',
691 'rc_cache.cache_license.expiration_time',
698 5*60)
692 5*60)
699 _string_setting(
693 _string_setting(
700 settings,
694 settings,
701 'rc_cache.cache_license.arguments.filename',
695 'rc_cache.cache_license.arguments.filename',
702 os.path.join(default_cache_dir, 'rc_cache_3'), lower=False)
696 os.path.join(default_cache_dir, 'rc_cache_3'), lower=False)
703
697
704 # cache_repo_longterm memory, 96H
698 # cache_repo_longterm memory, 96H
705 _string_setting(
699 _string_setting(
706 settings,
700 settings,
707 'rc_cache.cache_repo_longterm.backend',
701 'rc_cache.cache_repo_longterm.backend',
708 'dogpile.cache.rc.memory_lru', lower=False)
702 'dogpile.cache.rc.memory_lru', lower=False)
709 _int_setting(
703 _int_setting(
710 settings,
704 settings,
711 'rc_cache.cache_repo_longterm.expiration_time',
705 'rc_cache.cache_repo_longterm.expiration_time',
712 345600)
706 345600)
713 _int_setting(
707 _int_setting(
714 settings,
708 settings,
715 'rc_cache.cache_repo_longterm.max_size',
709 'rc_cache.cache_repo_longterm.max_size',
716 10000)
710 10000)
717
711
718 # sql_cache_short
712 # sql_cache_short
719 _string_setting(
713 _string_setting(
720 settings,
714 settings,
721 'rc_cache.sql_cache_short.backend',
715 'rc_cache.sql_cache_short.backend',
722 'dogpile.cache.rc.memory_lru', lower=False)
716 'dogpile.cache.rc.memory_lru', lower=False)
723 _int_setting(
717 _int_setting(
724 settings,
718 settings,
725 'rc_cache.sql_cache_short.expiration_time',
719 'rc_cache.sql_cache_short.expiration_time',
726 30)
720 30)
727 _int_setting(
721 _int_setting(
728 settings,
722 settings,
729 'rc_cache.sql_cache_short.max_size',
723 'rc_cache.sql_cache_short.max_size',
730 10000)
724 10000)
731
725
732
726
733 def _int_setting(settings, name, default):
727 def _int_setting(settings, name, default):
734 settings[name] = int(settings.get(name, default))
728 settings[name] = int(settings.get(name, default))
735 return settings[name]
729 return settings[name]
736
730
737
731
738 def _bool_setting(settings, name, default):
732 def _bool_setting(settings, name, default):
739 input_val = settings.get(name, default)
733 input_val = settings.get(name, default)
740 if isinstance(input_val, unicode):
734 if isinstance(input_val, unicode):
741 input_val = input_val.encode('utf8')
735 input_val = input_val.encode('utf8')
742 settings[name] = asbool(input_val)
736 settings[name] = asbool(input_val)
743 return settings[name]
737 return settings[name]
744
738
745
739
746 def _list_setting(settings, name, default):
740 def _list_setting(settings, name, default):
747 raw_value = settings.get(name, default)
741 raw_value = settings.get(name, default)
748
742
749 old_separator = ','
743 old_separator = ','
750 if old_separator in raw_value:
744 if old_separator in raw_value:
751 # If we get a comma separated list, pass it to our own function.
745 # If we get a comma separated list, pass it to our own function.
752 settings[name] = rhodecode_aslist(raw_value, sep=old_separator)
746 settings[name] = rhodecode_aslist(raw_value, sep=old_separator)
753 else:
747 else:
754 # Otherwise we assume it uses pyramids space/newline separation.
748 # Otherwise we assume it uses pyramids space/newline separation.
755 settings[name] = aslist(raw_value)
749 settings[name] = aslist(raw_value)
756 return settings[name]
750 return settings[name]
757
751
758
752
759 def _string_setting(settings, name, default, lower=True, default_when_empty=False):
753 def _string_setting(settings, name, default, lower=True, default_when_empty=False):
760 value = settings.get(name, default)
754 value = settings.get(name, default)
761
755
762 if default_when_empty and not value:
756 if default_when_empty and not value:
763 # use default value when value is empty
757 # use default value when value is empty
764 value = default
758 value = default
765
759
766 if lower:
760 if lower:
767 value = value.lower()
761 value = value.lower()
768 settings[name] = value
762 settings[name] = value
769 return settings[name]
763 return settings[name]
770
764
771
765
772 def _substitute_values(mapping, substitutions):
766 def _substitute_values(mapping, substitutions):
773 result = {}
767 result = {}
774
768
775 try:
769 try:
776 for key, value in mapping.items():
770 for key, value in mapping.items():
777 # initialize without substitution first
771 # initialize without substitution first
778 result[key] = value
772 result[key] = value
779
773
780 # Note: Cannot use regular replacements, since they would clash
774 # Note: Cannot use regular replacements, since they would clash
781 # with the implementation of ConfigParser. Using "format" instead.
775 # with the implementation of ConfigParser. Using "format" instead.
782 try:
776 try:
783 result[key] = value.format(**substitutions)
777 result[key] = value.format(**substitutions)
784 except KeyError as e:
778 except KeyError as e:
785 env_var = '{}'.format(e.args[0])
779 env_var = '{}'.format(e.args[0])
786
780
787 msg = 'Failed to substitute: `{key}={{{var}}}` with environment entry. ' \
781 msg = 'Failed to substitute: `{key}={{{var}}}` with environment entry. ' \
788 'Make sure your environment has {var} set, or remove this ' \
782 'Make sure your environment has {var} set, or remove this ' \
789 'variable from config file'.format(key=key, var=env_var)
783 'variable from config file'.format(key=key, var=env_var)
790
784
791 if env_var.startswith('ENV_'):
785 if env_var.startswith('ENV_'):
792 raise ValueError(msg)
786 raise ValueError(msg)
793 else:
787 else:
794 log.warning(msg)
788 log.warning(msg)
795
789
796 except ValueError as e:
790 except ValueError as e:
797 log.warning('Failed to substitute ENV variable: %s', e)
791 log.warning('Failed to substitute ENV variable: %s', e)
798 result = mapping
792 result = mapping
799
793
800 return result
794 return result
General Comments 0
You need to be logged in to leave comments. Login now