##// END OF EJS Templates
elasticsearch: inform about multiple ES nodes
ergo -
r6:4ee08856
parent child Browse files
Show More
@@ -1,285 +1,286 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2016 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 # App Enlight Enterprise Edition, including its added features, Support
19 19 # services, and proprietary license terms, please see
20 20 # https://rhodecode.com/licenses/
21 21
22 22 import datetime
23 23 import logging
24 24 import pyelasticsearch
25 25 import redis
26 26 import os
27 27 from pkg_resources import iter_entry_points
28 28
29 29 import appenlight.lib.jinja2_filters as jinja2_filters
30 30 import appenlight.lib.encryption as encryption
31 31
32 32 from authomatic.providers import oauth2, oauth1
33 33 from authomatic import Authomatic
34 34 from pyramid.config import Configurator, PHASE3_CONFIG
35 35 from pyramid.authentication import AuthTktAuthenticationPolicy
36 36 from pyramid.authorization import ACLAuthorizationPolicy
37 37 from pyramid_mailer.mailer import Mailer
38 38 from pyramid.renderers import JSON
39 39 from pyramid_redis_sessions import session_factory_from_settings
40 40 from pyramid.settings import asbool, aslist
41 41 from pyramid.security import AllPermissionsList
42 42 from pyramid_authstack import AuthenticationStackPolicy
43 43 from redlock import Redlock
44 44 from sqlalchemy import engine_from_config
45 45
46 46 from appenlight.celery import configure_celery
47 47 from appenlight.lib import cache_regions
48 48 from appenlight.lib.ext_json import json
49 49 from appenlight.security import groupfinder, AuthTokenAuthenticationPolicy
50 50
51 51 json_renderer = JSON(serializer=json.dumps, indent=4)
52 52
53 53 log = logging.getLogger(__name__)
54 54
55 55
56 56 def datetime_adapter(obj, request):
57 57 return obj.isoformat()
58 58
59 59
60 60 def all_permissions_adapter(obj, request):
61 61 return '__all_permissions__'
62 62
63 63
64 64 json_renderer.add_adapter(datetime.datetime, datetime_adapter)
65 65 json_renderer.add_adapter(AllPermissionsList, all_permissions_adapter)
66 66
67 67
68 68 def main(global_config, **settings):
69 69 """ This function returns a Pyramid WSGI application.
70 70 """
71 71 auth_tkt_policy = AuthTktAuthenticationPolicy(
72 72 settings['authtkt.secret'],
73 73 hashalg='sha512',
74 74 callback=groupfinder,
75 75 max_age=2592000,
76 76 secure=asbool(settings.get('authtkt.secure', 'false')))
77 77 auth_token_policy = AuthTokenAuthenticationPolicy(
78 78 callback=groupfinder
79 79 )
80 80 authorization_policy = ACLAuthorizationPolicy()
81 81 authentication_policy = AuthenticationStackPolicy()
82 82 authentication_policy.add_policy('auth_tkt', auth_tkt_policy)
83 83 authentication_policy.add_policy('auth_token', auth_token_policy)
84 84 # set crypto key
85 85 encryption.ENCRYPTION_SECRET = settings.get('encryption_secret')
86 86 # import this later so encyption key can be monkeypatched
87 87 from appenlight.models import DBSession, register_datastores
88 88 # update config with cometd info
89 89 settings['cometd_servers'] = {'server': settings['cometd.server'],
90 90 'secret': settings['cometd.secret']}
91 91
92 92 # Create the Pyramid Configurator.
93 93 settings['_mail_url'] = settings['mailing.app_url']
94 94 config = Configurator(settings=settings,
95 95 authentication_policy=authentication_policy,
96 96 authorization_policy=authorization_policy,
97 97 root_factory='appenlight.security.RootFactory',
98 98 default_permission='view')
99 99 config.set_default_csrf_options(require_csrf=True, header='X-XSRF-TOKEN')
100 100 config.add_view_deriver('appenlight.predicates.csrf_view',
101 101 name='csrf_view')
102 102
103
104 103 # later, when config is available
105 104 dogpile_config = {'url': settings['redis.url'],
106 105 "redis_expiration_time": 86400,
107 106 "redis_distributed_lock": True}
108 107 cache_regions.regions = cache_regions.CacheRegions(dogpile_config)
109 108 config.registry.cache_regions = cache_regions.regions
110 109 engine = engine_from_config(settings, 'sqlalchemy.',
111 110 json_serializer=json.dumps)
112 111 DBSession.configure(bind=engine)
113 112
114 113 # json rederer that serializes datetime
115 114 config.add_renderer('json', json_renderer)
116 115 config.set_request_property('appenlight.lib.request.es_conn', 'es_conn')
117 116 config.set_request_property('appenlight.lib.request.get_user', 'user',
118 117 reify=True)
119 118 config.set_request_property('appenlight.lib.request.get_csrf_token',
120 119 'csrf_token', reify=True)
121 120 config.set_request_property('appenlight.lib.request.safe_json_body',
122 121 'safe_json_body', reify=True)
123 122 config.set_request_property('appenlight.lib.request.unsafe_json_body',
124 123 'unsafe_json_body', reify=True)
125 124 config.add_request_method('appenlight.lib.request.add_flash_to_headers',
126 125 'add_flash_to_headers')
127 126
128 127 config.include('pyramid_redis_sessions')
129 128 config.include('pyramid_tm')
130 129 config.include('pyramid_jinja2')
131 130 config.include('appenlight_client.ext.pyramid_tween')
132 131 config.include('ziggurat_foundations.ext.pyramid.sign_in')
133 config.registry.es_conn = pyelasticsearch.ElasticSearch(
134 aslist(settings['elasticsearch.nodes']))
135 config.registry.redis_conn = redis.StrictRedis.from_url(
136 settings['redis.url'])
132 es_server_list = aslist(settings['elasticsearch.nodes'])
133 redis_url = settings['redis.url']
134 log.info('Elasticsearch server list: {}'.format(es_server_list))
135 log.info('Redis server: {}'.format(redis_url))
136 config.registry.es_conn = pyelasticsearch.ElasticSearch(es_server_list)
137 config.registry.redis_conn = redis.StrictRedis.from_url(redis_url)
137 138
138 139 config.registry.redis_lockmgr = Redlock([settings['redis.redlock.url'], ],
139 140 retry_count=0, retry_delay=0)
140 141 # mailer
141 142 config.registry.mailer = Mailer.from_settings(settings)
142 143
143 144 # Configure sessions
144 145 session_factory = session_factory_from_settings(settings)
145 146 config.set_session_factory(session_factory)
146 147
147 148 # Configure renderers and event subscribers
148 149 config.add_jinja2_extension('jinja2.ext.loopcontrols')
149 150 config.add_jinja2_search_path('appenlight:templates')
150 151 # event subscribers
151 152 config.add_subscriber("appenlight.subscribers.application_created",
152 153 "pyramid.events.ApplicationCreated")
153 154 config.add_subscriber("appenlight.subscribers.add_renderer_globals",
154 155 "pyramid.events.BeforeRender")
155 156 config.add_subscriber('appenlight.subscribers.new_request',
156 157 'pyramid.events.NewRequest')
157 158 config.add_view_predicate('context_type_class',
158 159 'appenlight.predicates.contextTypeClass')
159 160
160 161 register_datastores(es_conn=config.registry.es_conn,
161 162 redis_conn=config.registry.redis_conn,
162 163 redis_lockmgr=config.registry.redis_lockmgr)
163 164
164 165 # base stuff and scan
165 166
166 167 # need to ensure webassets exists otherwise config.override_asset()
167 168 # throws exception
168 169 if not os.path.exists(settings['webassets.dir']):
169 170 os.mkdir(settings['webassets.dir'])
170 171 config.add_static_view(path='appenlight:webassets',
171 172 name='static', cache_max_age=3600)
172 173 config.override_asset(to_override='appenlight:webassets/',
173 174 override_with=settings['webassets.dir'])
174 175
175 176 config.include('appenlight.views')
176 177 config.include('appenlight.views.admin')
177 178 config.scan(ignore=['appenlight.migrations',
178 179 'appenlight.scripts',
179 180 'appenlight.tests'])
180 181
181 182 # authomatic social auth
182 183 authomatic_conf = {
183 184 # callback http://yourapp.com/social_auth/twitter
184 185 'twitter': {
185 186 'class_': oauth1.Twitter,
186 187 'consumer_key': settings.get('authomatic.pr.twitter.key', 'X'),
187 188 'consumer_secret': settings.get('authomatic.pr.twitter.secret',
188 189 'X'),
189 190 },
190 191 # callback http://yourapp.com/social_auth/facebook
191 192 'facebook': {
192 193 'class_': oauth2.Facebook,
193 194 'consumer_key': settings.get('authomatic.pr.facebook.app_id', 'X'),
194 195 'consumer_secret': settings.get('authomatic.pr.facebook.secret',
195 196 'X'),
196 197 'scope': ['email'],
197 198 },
198 199 # callback http://yourapp.com/social_auth/google
199 200 'google': {
200 201 'class_': oauth2.Google,
201 202 'consumer_key': settings.get('authomatic.pr.google.key', 'X'),
202 203 'consumer_secret': settings.get(
203 204 'authomatic.pr.google.secret', 'X'),
204 205 'scope': ['profile', 'email'],
205 206 },
206 207 'github': {
207 208 'class_': oauth2.GitHub,
208 209 'consumer_key': settings.get('authomatic.pr.github.key', 'X'),
209 210 'consumer_secret': settings.get(
210 211 'authomatic.pr.github.secret', 'X'),
211 212 'scope': ['repo', 'public_repo', 'user:email'],
212 213 'access_headers': {'User-Agent': 'AppEnlight'},
213 214 },
214 215 'bitbucket': {
215 216 'class_': oauth1.Bitbucket,
216 217 'consumer_key': settings.get('authomatic.pr.bitbucket.key', 'X'),
217 218 'consumer_secret': settings.get(
218 219 'authomatic.pr.bitbucket.secret', 'X')
219 220 }
220 221 }
221 222 config.registry.authomatic = Authomatic(
222 223 config=authomatic_conf, secret=settings['authomatic.secret'])
223 224
224 225 # resource type information
225 226 config.registry.resource_types = ['resource', 'application']
226 227
227 228 # plugin information
228 229 config.registry.appenlight_plugins = {}
229 230
230 231 def register_appenlight_plugin(config, plugin_name, plugin_config):
231 232 def register():
232 233 log.warning('Registering plugin: {}'.format(plugin_name))
233 234 if plugin_name not in config.registry.appenlight_plugins:
234 235 config.registry.appenlight_plugins[plugin_name] = {
235 236 'javascript': None,
236 237 'static': None,
237 238 'css': None,
238 239 'top_nav': None,
239 240 'celery_tasks': None,
240 241 'celery_beats': None,
241 242 'fulltext_indexer': None,
242 243 'sqlalchemy_migrations': None,
243 244 'default_values_setter': None,
244 245 'resource_types': [],
245 246 'url_gen': None
246 247 }
247 248 config.registry.appenlight_plugins[plugin_name].update(
248 249 plugin_config)
249 250 # inform AE what kind of resource types we have available
250 251 # so we can avoid failing when a plugin is removed but data
251 252 # is still present in the db
252 253 if plugin_config.get('resource_types'):
253 254 config.registry.resource_types.extend(
254 255 plugin_config['resource_types'])
255 256
256 257 config.action('appenlight_plugin={}'.format(plugin_name), register)
257 258
258 259 config.add_directive('register_appenlight_plugin',
259 260 register_appenlight_plugin)
260 261
261 262 for entry_point in iter_entry_points(group='appenlight.plugins'):
262 263 plugin = entry_point.load()
263 264 plugin.includeme(config)
264 265
265 266 # include other appenlight plugins explictly if needed
266 267 includes = aslist(settings.get('appenlight.includes', []))
267 268 for inc in includes:
268 269 config.include(inc)
269 270
270 271 # run this after everything registers in configurator
271 272
272 273 def pre_commit():
273 274 jinja_env = config.get_jinja2_environment()
274 275 jinja_env.filters['tojson'] = json.dumps
275 276 jinja_env.filters['toJSONUnsafe'] = jinja2_filters.toJSONUnsafe
276 277
277 278 config.action(None, pre_commit, order=PHASE3_CONFIG + 999)
278 279
279 280 def wrap_config_celery():
280 281 configure_celery(config.registry)
281 282
282 283 config.action(None, wrap_config_celery, order=PHASE3_CONFIG + 999)
283 284
284 285 app = config.make_wsgi_app()
285 286 return app
General Comments 0
You need to be logged in to leave comments. Login now