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