##// END OF EJS Templates
redis: fixed new redis url schema requirement for connection string
marcink -
r3867:2bc3e4d7 default
parent child Browse files
Show More
@@ -1,740 +1,746 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 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('rhodecode.lib.rc_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.file_store')
285 285 config.include('rhodecode.apps.login')
286 286 config.include('rhodecode.apps.home')
287 287 config.include('rhodecode.apps.journal')
288 288 config.include('rhodecode.apps.repository')
289 289 config.include('rhodecode.apps.repo_group')
290 290 config.include('rhodecode.apps.user_group')
291 291 config.include('rhodecode.apps.search')
292 292 config.include('rhodecode.apps.user_profile')
293 293 config.include('rhodecode.apps.user_group_profile')
294 294 config.include('rhodecode.apps.my_account')
295 295 config.include('rhodecode.apps.svn_support')
296 296 config.include('rhodecode.apps.ssh_support')
297 297 config.include('rhodecode.apps.gist')
298 298 config.include('rhodecode.apps.debug_style')
299 299 config.include('rhodecode.api')
300 300
301 301 config.add_route('rhodecode_support', 'https://rhodecode.com/help/', static=True)
302 302 config.add_translation_dirs('rhodecode:i18n/')
303 303 settings['default_locale_name'] = settings.get('lang', 'en')
304 304
305 305 # Add subscribers.
306 306 config.add_subscriber(inject_app_settings,
307 307 pyramid.events.ApplicationCreated)
308 308 config.add_subscriber(scan_repositories_if_enabled,
309 309 pyramid.events.ApplicationCreated)
310 310 config.add_subscriber(write_metadata_if_needed,
311 311 pyramid.events.ApplicationCreated)
312 312 config.add_subscriber(write_js_routes_if_enabled,
313 313 pyramid.events.ApplicationCreated)
314 314
315 315 # request custom methods
316 316 config.add_request_method(
317 317 'rhodecode.lib.partial_renderer.get_partial_renderer',
318 318 'get_partial_renderer')
319 319
320 320 # Set the authorization policy.
321 321 authz_policy = ACLAuthorizationPolicy()
322 322 config.set_authorization_policy(authz_policy)
323 323
324 324 # Set the default renderer for HTML templates to mako.
325 325 config.add_mako_renderer('.html')
326 326
327 327 config.add_renderer(
328 328 name='json_ext',
329 329 factory='rhodecode.lib.ext_json_renderer.pyramid_ext_json')
330 330
331 331 # include RhodeCode plugins
332 332 includes = aslist(settings.get('rhodecode.includes', []))
333 333 for inc in includes:
334 334 config.include(inc)
335 335
336 336 # custom not found view, if our pyramid app doesn't know how to handle
337 337 # the request pass it to potential VCS handling ap
338 338 config.add_notfound_view(not_found_view)
339 339 if not settings.get('debugtoolbar.enabled', False):
340 340 # disabled debugtoolbar handle all exceptions via the error_handlers
341 341 config.add_view(error_handler, context=Exception)
342 342
343 343 # all errors including 403/404/50X
344 344 config.add_view(error_handler, context=HTTPError)
345 345
346 346
347 347 def wrap_app_in_wsgi_middlewares(pyramid_app, config):
348 348 """
349 349 Apply outer WSGI middlewares around the application.
350 350 """
351 351 registry = config.registry
352 352 settings = registry.settings
353 353
354 354 # enable https redirects based on HTTP_X_URL_SCHEME set by proxy
355 355 pyramid_app = HttpsFixup(pyramid_app, settings)
356 356
357 357 pyramid_app, _ae_client = wrap_in_appenlight_if_enabled(
358 358 pyramid_app, settings)
359 359 registry.ae_client = _ae_client
360 360
361 361 if settings['gzip_responses']:
362 362 pyramid_app = make_gzip_middleware(
363 363 pyramid_app, settings, compress_level=1)
364 364
365 365 # this should be the outer most middleware in the wsgi stack since
366 366 # middleware like Routes make database calls
367 367 def pyramid_app_with_cleanup(environ, start_response):
368 368 try:
369 369 return pyramid_app(environ, start_response)
370 370 finally:
371 371 # Dispose current database session and rollback uncommitted
372 372 # transactions.
373 373 meta.Session.remove()
374 374
375 375 # In a single threaded mode server, on non sqlite db we should have
376 376 # '0 Current Checked out connections' at the end of a request,
377 377 # if not, then something, somewhere is leaving a connection open
378 378 pool = meta.Base.metadata.bind.engine.pool
379 379 log.debug('sa pool status: %s', pool.status())
380 380 log.debug('Request processing finalized')
381 381
382 382 return pyramid_app_with_cleanup
383 383
384 384
385 385 def sanitize_settings_and_apply_defaults(global_config, settings):
386 386 """
387 387 Applies settings defaults and does all type conversion.
388 388
389 389 We would move all settings parsing and preparation into this place, so that
390 390 we have only one place left which deals with this part. The remaining parts
391 391 of the application would start to rely fully on well prepared settings.
392 392
393 393 This piece would later be split up per topic to avoid a big fat monster
394 394 function.
395 395 """
396 396
397 397 settings.setdefault('rhodecode.edition', 'Community Edition')
398 398
399 399 if 'mako.default_filters' not in settings:
400 400 # set custom default filters if we don't have it defined
401 401 settings['mako.imports'] = 'from rhodecode.lib.base import h_filter'
402 402 settings['mako.default_filters'] = 'h_filter'
403 403
404 404 if 'mako.directories' not in settings:
405 405 mako_directories = settings.setdefault('mako.directories', [
406 406 # Base templates of the original application
407 407 'rhodecode:templates',
408 408 ])
409 409 log.debug(
410 410 "Using the following Mako template directories: %s",
411 411 mako_directories)
412 412
413 # NOTE(marcink): fix redis requirement for schema of connection since 3.X
414 if 'beaker.session.type' in settings and settings['beaker.session.type'] == 'ext:redis':
415 raw_url = settings['beaker.session.url']
416 if not raw_url.startswith(('redis://', 'rediss://', 'unix://')):
417 settings['beaker.session.url'] = 'redis://' + raw_url
418
413 419 # Default includes, possible to change as a user
414 420 pyramid_includes = settings.setdefault('pyramid.includes', [
415 421 'rhodecode.lib.middleware.request_wrapper',
416 422 ])
417 423 log.debug(
418 424 "Using the following pyramid.includes: %s",
419 425 pyramid_includes)
420 426
421 427 # TODO: johbo: Re-think this, usually the call to config.include
422 428 # should allow to pass in a prefix.
423 429 settings.setdefault('rhodecode.api.url', '/_admin/api')
424 430 settings.setdefault('__file__', global_config.get('__file__'))
425 431
426 432 # Sanitize generic settings.
427 433 _list_setting(settings, 'default_encoding', 'UTF-8')
428 434 _bool_setting(settings, 'is_test', 'false')
429 435 _bool_setting(settings, 'gzip_responses', 'false')
430 436
431 437 # Call split out functions that sanitize settings for each topic.
432 438 _sanitize_appenlight_settings(settings)
433 439 _sanitize_vcs_settings(settings)
434 440 _sanitize_cache_settings(settings)
435 441
436 442 # configure instance id
437 443 config_utils.set_instance_id(settings)
438 444
439 445 return settings
440 446
441 447
442 448 def enable_debug():
443 449 """
444 450 Helper to enable debug on running instance
445 451 :return:
446 452 """
447 453 import tempfile
448 454 import textwrap
449 455 import logging.config
450 456
451 457 ini_template = textwrap.dedent("""
452 458 #####################################
453 459 ### DEBUG LOGGING CONFIGURATION ####
454 460 #####################################
455 461 [loggers]
456 462 keys = root, sqlalchemy, beaker, celery, rhodecode, ssh_wrapper
457 463
458 464 [handlers]
459 465 keys = console, console_sql
460 466
461 467 [formatters]
462 468 keys = generic, color_formatter, color_formatter_sql
463 469
464 470 #############
465 471 ## LOGGERS ##
466 472 #############
467 473 [logger_root]
468 474 level = NOTSET
469 475 handlers = console
470 476
471 477 [logger_sqlalchemy]
472 478 level = INFO
473 479 handlers = console_sql
474 480 qualname = sqlalchemy.engine
475 481 propagate = 0
476 482
477 483 [logger_beaker]
478 484 level = DEBUG
479 485 handlers =
480 486 qualname = beaker.container
481 487 propagate = 1
482 488
483 489 [logger_rhodecode]
484 490 level = DEBUG
485 491 handlers =
486 492 qualname = rhodecode
487 493 propagate = 1
488 494
489 495 [logger_ssh_wrapper]
490 496 level = DEBUG
491 497 handlers =
492 498 qualname = ssh_wrapper
493 499 propagate = 1
494 500
495 501 [logger_celery]
496 502 level = DEBUG
497 503 handlers =
498 504 qualname = celery
499 505
500 506
501 507 ##############
502 508 ## HANDLERS ##
503 509 ##############
504 510
505 511 [handler_console]
506 512 class = StreamHandler
507 513 args = (sys.stderr, )
508 514 level = DEBUG
509 515 formatter = color_formatter
510 516
511 517 [handler_console_sql]
512 518 # "level = DEBUG" logs SQL queries and results.
513 519 # "level = INFO" logs SQL queries.
514 520 # "level = WARN" logs neither. (Recommended for production systems.)
515 521 class = StreamHandler
516 522 args = (sys.stderr, )
517 523 level = WARN
518 524 formatter = color_formatter_sql
519 525
520 526 ################
521 527 ## FORMATTERS ##
522 528 ################
523 529
524 530 [formatter_generic]
525 531 class = rhodecode.lib.logging_formatter.ExceptionAwareFormatter
526 532 format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s | %(req_id)s
527 533 datefmt = %Y-%m-%d %H:%M:%S
528 534
529 535 [formatter_color_formatter]
530 536 class = rhodecode.lib.logging_formatter.ColorRequestTrackingFormatter
531 537 format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s | %(req_id)s
532 538 datefmt = %Y-%m-%d %H:%M:%S
533 539
534 540 [formatter_color_formatter_sql]
535 541 class = rhodecode.lib.logging_formatter.ColorFormatterSql
536 542 format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s
537 543 datefmt = %Y-%m-%d %H:%M:%S
538 544 """)
539 545
540 546 with tempfile.NamedTemporaryFile(prefix='rc_debug_logging_', suffix='.ini',
541 547 delete=False) as f:
542 548 log.info('Saved Temporary DEBUG config at %s', f.name)
543 549 f.write(ini_template)
544 550
545 551 logging.config.fileConfig(f.name)
546 552 log.debug('DEBUG MODE ON')
547 553 os.remove(f.name)
548 554
549 555
550 556 def _sanitize_appenlight_settings(settings):
551 557 _bool_setting(settings, 'appenlight', 'false')
552 558
553 559
554 560 def _sanitize_vcs_settings(settings):
555 561 """
556 562 Applies settings defaults and does type conversion for all VCS related
557 563 settings.
558 564 """
559 565 _string_setting(settings, 'vcs.svn.compatible_version', '')
560 566 _string_setting(settings, 'git_rev_filter', '--all')
561 567 _string_setting(settings, 'vcs.hooks.protocol', 'http')
562 568 _string_setting(settings, 'vcs.hooks.host', '127.0.0.1')
563 569 _string_setting(settings, 'vcs.scm_app_implementation', 'http')
564 570 _string_setting(settings, 'vcs.server', '')
565 571 _string_setting(settings, 'vcs.server.log_level', 'debug')
566 572 _string_setting(settings, 'vcs.server.protocol', 'http')
567 573 _bool_setting(settings, 'startup.import_repos', 'false')
568 574 _bool_setting(settings, 'vcs.hooks.direct_calls', 'false')
569 575 _bool_setting(settings, 'vcs.server.enable', 'true')
570 576 _bool_setting(settings, 'vcs.start_server', 'false')
571 577 _list_setting(settings, 'vcs.backends', 'hg, git, svn')
572 578 _int_setting(settings, 'vcs.connection_timeout', 3600)
573 579
574 580 # Support legacy values of vcs.scm_app_implementation. Legacy
575 581 # configurations may use 'rhodecode.lib.middleware.utils.scm_app_http', or
576 582 # disabled since 4.13 'vcsserver.scm_app' which is now mapped to 'http'.
577 583 scm_app_impl = settings['vcs.scm_app_implementation']
578 584 if scm_app_impl in ['rhodecode.lib.middleware.utils.scm_app_http', 'vcsserver.scm_app']:
579 585 settings['vcs.scm_app_implementation'] = 'http'
580 586
581 587
582 588 def _sanitize_cache_settings(settings):
583 589 temp_store = tempfile.gettempdir()
584 590 default_cache_dir = os.path.join(temp_store, 'rc_cache')
585 591
586 592 # save default, cache dir, and use it for all backends later.
587 593 default_cache_dir = _string_setting(
588 594 settings,
589 595 'cache_dir',
590 596 default_cache_dir, lower=False, default_when_empty=True)
591 597
592 598 # ensure we have our dir created
593 599 if not os.path.isdir(default_cache_dir):
594 600 os.makedirs(default_cache_dir, mode=0o755)
595 601
596 602 # exception store cache
597 603 _string_setting(
598 604 settings,
599 605 'exception_tracker.store_path',
600 606 temp_store, lower=False, default_when_empty=True)
601 607
602 608 # cache_perms
603 609 _string_setting(
604 610 settings,
605 611 'rc_cache.cache_perms.backend',
606 612 'dogpile.cache.rc.file_namespace', lower=False)
607 613 _int_setting(
608 614 settings,
609 615 'rc_cache.cache_perms.expiration_time',
610 616 60)
611 617 _string_setting(
612 618 settings,
613 619 'rc_cache.cache_perms.arguments.filename',
614 620 os.path.join(default_cache_dir, 'rc_cache_1'), lower=False)
615 621
616 622 # cache_repo
617 623 _string_setting(
618 624 settings,
619 625 'rc_cache.cache_repo.backend',
620 626 'dogpile.cache.rc.file_namespace', lower=False)
621 627 _int_setting(
622 628 settings,
623 629 'rc_cache.cache_repo.expiration_time',
624 630 60)
625 631 _string_setting(
626 632 settings,
627 633 'rc_cache.cache_repo.arguments.filename',
628 634 os.path.join(default_cache_dir, 'rc_cache_2'), lower=False)
629 635
630 636 # cache_license
631 637 _string_setting(
632 638 settings,
633 639 'rc_cache.cache_license.backend',
634 640 'dogpile.cache.rc.file_namespace', lower=False)
635 641 _int_setting(
636 642 settings,
637 643 'rc_cache.cache_license.expiration_time',
638 644 5*60)
639 645 _string_setting(
640 646 settings,
641 647 'rc_cache.cache_license.arguments.filename',
642 648 os.path.join(default_cache_dir, 'rc_cache_3'), lower=False)
643 649
644 650 # cache_repo_longterm memory, 96H
645 651 _string_setting(
646 652 settings,
647 653 'rc_cache.cache_repo_longterm.backend',
648 654 'dogpile.cache.rc.memory_lru', lower=False)
649 655 _int_setting(
650 656 settings,
651 657 'rc_cache.cache_repo_longterm.expiration_time',
652 658 345600)
653 659 _int_setting(
654 660 settings,
655 661 'rc_cache.cache_repo_longterm.max_size',
656 662 10000)
657 663
658 664 # sql_cache_short
659 665 _string_setting(
660 666 settings,
661 667 'rc_cache.sql_cache_short.backend',
662 668 'dogpile.cache.rc.memory_lru', lower=False)
663 669 _int_setting(
664 670 settings,
665 671 'rc_cache.sql_cache_short.expiration_time',
666 672 30)
667 673 _int_setting(
668 674 settings,
669 675 'rc_cache.sql_cache_short.max_size',
670 676 10000)
671 677
672 678
673 679 def _int_setting(settings, name, default):
674 680 settings[name] = int(settings.get(name, default))
675 681 return settings[name]
676 682
677 683
678 684 def _bool_setting(settings, name, default):
679 685 input_val = settings.get(name, default)
680 686 if isinstance(input_val, unicode):
681 687 input_val = input_val.encode('utf8')
682 688 settings[name] = asbool(input_val)
683 689 return settings[name]
684 690
685 691
686 692 def _list_setting(settings, name, default):
687 693 raw_value = settings.get(name, default)
688 694
689 695 old_separator = ','
690 696 if old_separator in raw_value:
691 697 # If we get a comma separated list, pass it to our own function.
692 698 settings[name] = rhodecode_aslist(raw_value, sep=old_separator)
693 699 else:
694 700 # Otherwise we assume it uses pyramids space/newline separation.
695 701 settings[name] = aslist(raw_value)
696 702 return settings[name]
697 703
698 704
699 705 def _string_setting(settings, name, default, lower=True, default_when_empty=False):
700 706 value = settings.get(name, default)
701 707
702 708 if default_when_empty and not value:
703 709 # use default value when value is empty
704 710 value = default
705 711
706 712 if lower:
707 713 value = value.lower()
708 714 settings[name] = value
709 715 return settings[name]
710 716
711 717
712 718 def _substitute_values(mapping, substitutions):
713 719 result = {}
714 720
715 721 try:
716 722 for key, value in mapping.items():
717 723 # initialize without substitution first
718 724 result[key] = value
719 725
720 726 # Note: Cannot use regular replacements, since they would clash
721 727 # with the implementation of ConfigParser. Using "format" instead.
722 728 try:
723 729 result[key] = value.format(**substitutions)
724 730 except KeyError as e:
725 731 env_var = '{}'.format(e.args[0])
726 732
727 733 msg = 'Failed to substitute: `{key}={{{var}}}` with environment entry. ' \
728 734 'Make sure your environment has {var} set, or remove this ' \
729 735 'variable from config file'.format(key=key, var=env_var)
730 736
731 737 if env_var.startswith('ENV_'):
732 738 raise ValueError(msg)
733 739 else:
734 740 log.warning(msg)
735 741
736 742 except ValueError as e:
737 743 log.warning('Failed to substitute ENV variable: %s', e)
738 744 result = mapping
739 745
740 746 return result
General Comments 0
You need to be logged in to leave comments. Login now