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