environment variables for triggers
This commit is contained in:
parent
c71e996c38
commit
c966587821
1 changed files with 30 additions and 11 deletions
|
@ -21,7 +21,6 @@ import os
|
||||||
import glob
|
import glob
|
||||||
import json
|
import json
|
||||||
import datetime
|
import datetime
|
||||||
import subprocess
|
|
||||||
|
|
||||||
import tornado.httpserver
|
import tornado.httpserver
|
||||||
import tornado.ioloop
|
import tornado.ioloop
|
||||||
|
@ -33,6 +32,7 @@ from tornado import gen, escape, process
|
||||||
import utils
|
import utils
|
||||||
import backend
|
import backend
|
||||||
|
|
||||||
|
ENCODING = 'utf8'
|
||||||
PROCESS_TIMEOUT = 60
|
PROCESS_TIMEOUT = 60
|
||||||
|
|
||||||
|
|
||||||
|
@ -104,6 +104,18 @@ class CollectionHandler(BaseHandler):
|
||||||
arguments = property(lambda self: dict([(k, v[0])
|
arguments = property(lambda self: dict([(k, v[0])
|
||||||
for k, v in self.request.arguments.iteritems()]))
|
for k, v in self.request.arguments.iteritems()]))
|
||||||
|
|
||||||
|
def _dict2env(self, data):
|
||||||
|
"""Convert a dictionary into a form suitable to be passed as environment variables."""
|
||||||
|
ret = {}
|
||||||
|
for key, value in data.iteritems():
|
||||||
|
if isinstance(value, (list, tuple, dict)):
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
ret[key.upper()] = unicode(value).encode(ENCODING)
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
return ret
|
||||||
|
|
||||||
@gen.coroutine
|
@gen.coroutine
|
||||||
def get(self, id_=None, resource=None, resource_id=None, **kwargs):
|
def get(self, id_=None, resource=None, resource_id=None, **kwargs):
|
||||||
if resource:
|
if resource:
|
||||||
|
@ -164,7 +176,7 @@ class CollectionHandler(BaseHandler):
|
||||||
self.ioloop.remove_timeout(self.timeout)
|
self.ioloop.remove_timeout(self.timeout)
|
||||||
|
|
||||||
@gen.coroutine
|
@gen.coroutine
|
||||||
def run_subprocess(self, cmd, stdin_data=None):
|
def run_subprocess(self, cmd, stdin_data=None, env=None):
|
||||||
"""Execute the given action.
|
"""Execute the given action.
|
||||||
|
|
||||||
:param cmd: the command to be run with its command line arguments
|
:param cmd: the command to be run with its command line arguments
|
||||||
|
@ -172,10 +184,12 @@ class CollectionHandler(BaseHandler):
|
||||||
|
|
||||||
:param stdin_data: data to be sent over stdin
|
:param stdin_data: data to be sent over stdin
|
||||||
:type stdin_data: str
|
:type stdin_data: str
|
||||||
|
:param env: environment of the process
|
||||||
|
:type env: dict
|
||||||
"""
|
"""
|
||||||
self.ioloop = tornado.ioloop.IOLoop.instance()
|
self.ioloop = tornado.ioloop.IOLoop.instance()
|
||||||
p = process.Subprocess(cmd, close_fds=True, stdin=process.Subprocess.STREAM,
|
p = process.Subprocess(cmd, close_fds=True, stdin=process.Subprocess.STREAM,
|
||||||
stdout=process.Subprocess.STREAM, stderr=process.Subprocess.STREAM)
|
stdout=process.Subprocess.STREAM, stderr=process.Subprocess.STREAM, env=env)
|
||||||
p.set_exit_callback(lambda returncode: self.on_exit(returncode, cmd, p))
|
p.set_exit_callback(lambda returncode: self.on_exit(returncode, cmd, p))
|
||||||
self.timeout = self.ioloop.add_timeout(datetime.timedelta(seconds=PROCESS_TIMEOUT),
|
self.timeout = self.ioloop.add_timeout(datetime.timedelta(seconds=PROCESS_TIMEOUT),
|
||||||
lambda: self.on_timeout(p))
|
lambda: self.on_timeout(p))
|
||||||
|
@ -183,17 +197,19 @@ class CollectionHandler(BaseHandler):
|
||||||
p.stdin.close()
|
p.stdin.close()
|
||||||
out, err = yield [gen.Task(p.stdout.read_until_close),
|
out, err = yield [gen.Task(p.stdout.read_until_close),
|
||||||
gen.Task(p.stderr.read_until_close)]
|
gen.Task(p.stderr.read_until_close)]
|
||||||
|
print 'out', out
|
||||||
raise gen.Return((out, err))
|
raise gen.Return((out, err))
|
||||||
|
|
||||||
@gen.coroutine
|
@gen.coroutine
|
||||||
def run_triggers(self, action, stdin_data=None):
|
def run_triggers(self, action, stdin_data=None, env=None):
|
||||||
"""Asynchronously execute triggers for the given action.
|
"""Asynchronously execute triggers for the given action.
|
||||||
|
|
||||||
:param action: action name; scripts in directory ./data/triggers/{action}.d will be run
|
:param action: action name; scripts in directory ./data/triggers/{action}.d will be run
|
||||||
:type action: str
|
:type action: str
|
||||||
|
|
||||||
:param stdin_data: a python dictionary that will be serialized in JSON and sent to the process over stdin
|
:param stdin_data: a python dictionary that will be serialized in JSON and sent to the process over stdin
|
||||||
:type stdin_data: dict
|
:type stdin_data: dict
|
||||||
|
:param env: environment of the process
|
||||||
|
:type stdin_data: dict
|
||||||
"""
|
"""
|
||||||
stdin_data = stdin_data or {}
|
stdin_data = stdin_data or {}
|
||||||
try:
|
try:
|
||||||
|
@ -203,7 +219,7 @@ class CollectionHandler(BaseHandler):
|
||||||
for script in glob.glob(os.path.join(self.data_dir, 'triggers', '%s.d' % action, '*')):
|
for script in glob.glob(os.path.join(self.data_dir, 'triggers', '%s.d' % action, '*')):
|
||||||
if not (os.path.isfile(script) and os.access(script, os.X_OK)):
|
if not (os.path.isfile(script) and os.access(script, os.X_OK)):
|
||||||
continue
|
continue
|
||||||
out, err = yield gen.Task(self.run_subprocess, [script], stdin_data)
|
out, err = yield gen.Task(self.run_subprocess, [script], stdin_data, env)
|
||||||
|
|
||||||
|
|
||||||
class PersonsHandler(CollectionHandler):
|
class PersonsHandler(CollectionHandler):
|
||||||
|
@ -289,14 +305,17 @@ class EventsHandler(CollectionHandler):
|
||||||
merged, doc = self.db.update('events', query,
|
merged, doc = self.db.update('events', query,
|
||||||
data, updateList='persons', create=False)
|
data, updateList='persons', create=False)
|
||||||
new_person_data = self._get_person_data(person_id, doc.get('persons') or [])
|
new_person_data = self._get_person_data(person_id, doc.get('persons') or [])
|
||||||
#if old_person_data and old_person_data.get('attended') != new_person_data.get('attended') \
|
env = self._dict2env(new_person_data)
|
||||||
# and new_person_data.get('attended'):
|
env.update({'PERSON_ID': person_id, 'EVENT_ID': id_, 'EVENT_TITLE': doc.get('title', '')})
|
||||||
self.run_triggers('update_person_in_event', {
|
stdin_data = {'old': old_person_data,
|
||||||
'old': old_person_data,
|
|
||||||
'new': new_person_data,
|
'new': new_person_data,
|
||||||
'event': doc,
|
'event': doc,
|
||||||
'merged': merged
|
'merged': merged
|
||||||
})
|
}
|
||||||
|
self.run_triggers('update_person_in_event', stdin_data=stdin_data, env=env)
|
||||||
|
if old_person_data and old_person_data.get('attended') != new_person_data.get('attended') \
|
||||||
|
and new_person_data.get('attended'):
|
||||||
|
self.run_triggers('attends', stdin_data=stdin_data, env=env)
|
||||||
return {'event': doc}
|
return {'event': doc}
|
||||||
|
|
||||||
def handle_delete_persons(self, id_, person_id):
|
def handle_delete_persons(self, id_, person_id):
|
||||||
|
|
Loading…
Reference in a new issue