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