Skip to content
Snippets Groups Projects
Commit 613b9699 authored by ale's avatar ale
Browse files

Add instrumentation (number of subscribers)

Also use flask.jsonify() instead of our custom function.
parent b2939f0e
No related branches found
No related tags found
No related merge requests found
...@@ -6,7 +6,8 @@ import ssl ...@@ -6,7 +6,8 @@ import ssl
import subprocess import subprocess
import sys import sys
from functools import wraps from functools import wraps
from flask import Flask, request, abort, make_response, g from flask import Flask, request, abort, make_response, jsonify, g
from flask_caching import Cache
from .sso_api import sso_api_auth_required, init_sso from .sso_api import sso_api_auth_required, init_sso
from .tls_auth import tls_auth, init_tls_auth, PeerCertWSGIRequestHandler from .tls_auth import tls_auth, init_tls_auth, PeerCertWSGIRequestHandler
...@@ -14,6 +15,7 @@ from .tls_auth import tls_auth, init_tls_auth, PeerCertWSGIRequestHandler ...@@ -14,6 +15,7 @@ from .tls_auth import tls_auth, init_tls_auth, PeerCertWSGIRequestHandler
sys.path.insert(0, '/var/lib/mailman/bin') sys.path.insert(0, '/var/lib/mailman/bin')
import paths import paths
from Mailman import MailList from Mailman import MailList
from Mailman import Utils
app = Flask(__name__) app = Flask(__name__)
...@@ -21,6 +23,8 @@ app.config['TLS_AUTH_ACLS'] = [ ...@@ -21,6 +23,8 @@ app.config['TLS_AUTH_ACLS'] = [
('/', 'client'), ('/', 'client'),
] ]
cache = Cache(config={'CACHE_TYPE': 'SimpleCache'})
# Set up environment for Mailman processes: if we don't explicitly # Set up environment for Mailman processes: if we don't explicitly
# control LANG, we're going to get locale setup errors. # control LANG, we're going to get locale setup errors.
mm_env = dict(os.environ) mm_env = dict(os.environ)
...@@ -31,17 +35,6 @@ def _run(cmd): ...@@ -31,17 +35,6 @@ def _run(cmd):
subprocess.check_call(cmd, env=mm_env) subprocess.check_call(cmd, env=mm_env)
def to_json(fn):
"""Encode response as JSON."""
@wraps(fn)
def _json_wrapper(*args, **kwargs):
result = fn(*args, **kwargs)
resp = make_response(json.dumps(result))
resp.headers['Content-Type'] = 'application/json'
return resp
return _json_wrapper
def _random_password(): def _random_password():
return os.urandom(12).encode('base64').rstrip('=\n') return os.urandom(12).encode('base64').rstrip('=\n')
...@@ -61,7 +54,6 @@ def _maybe_unicode(s): ...@@ -61,7 +54,6 @@ def _maybe_unicode(s):
@app.route('/api/create_list', methods=('POST',)) @app.route('/api/create_list', methods=('POST',))
@tls_auth @tls_auth
@to_json
def create_list(): def create_list():
list_addr = request.json['list'] list_addr = request.json['list']
admin_addr = request.json['admin'] admin_addr = request.json['admin']
...@@ -88,12 +80,11 @@ def create_list(): ...@@ -88,12 +80,11 @@ def create_list():
]) ])
app.logger.info('created new list %s', list_addr) app.logger.info('created new list %s', list_addr)
return {} return jsonify({})
@app.route('/api/get_list_attrs', methods=('POST',)) @app.route('/api/get_list_attrs', methods=('POST',))
@tls_auth @tls_auth
@to_json
def get_list_attrs(): def get_list_attrs():
lists = request.json['lists'] lists = request.json['lists']
out = [] out = []
...@@ -106,13 +97,12 @@ def get_list_attrs(): ...@@ -106,13 +97,12 @@ def get_list_attrs():
'owners': list(set(m.owner[:])), 'owners': list(set(m.owner[:])),
} }
out.append(attrs) out.append(attrs)
return out return jsonify(out)
@app.route('/api/pwreset', methods=('POST',)) @app.route('/api/pwreset', methods=('POST',))
@tls_auth @tls_auth
@sso_api_auth_required @sso_api_auth_required
@to_json
def pwreset(): def pwreset():
list_addr = request.json['list'] list_addr = request.json['list']
list_name = list_addr.split('@')[0] list_name = list_addr.split('@')[0]
...@@ -125,12 +115,11 @@ def pwreset(): ...@@ -125,12 +115,11 @@ def pwreset():
'/var/lib/mailman/bin/change_pw', '-l', '/var/lib/mailman/bin/change_pw', '-l',
list_name, list_name,
]) ])
return {} return jsonify({})
@app.route('/api/regenerate_archives', methods=('POST',)) @app.route('/api/regenerate_archives', methods=('POST',))
@tls_auth @tls_auth
@to_json
def regenerate_archives(): def regenerate_archives():
list_addr = request.json['list'] list_addr = request.json['list']
list_name = list_addr.split('@')[0] list_name = list_addr.split('@')[0]
...@@ -139,7 +128,29 @@ def regenerate_archives(): ...@@ -139,7 +128,29 @@ def regenerate_archives():
'/var/lib/mailman/bin/arch', '--wipe', '--quiet', '/var/lib/mailman/bin/arch', '--wipe', '--quiet',
list_name, list_name,
]) ])
return {} return jsonify({})
### Instrumentation.
@app.route('/metrics')
@cache.cached(timeout=900)
def metrics():
def _dump_metrics():
list_names = Utils.list_names()
for list_name in list_names:
try:
mlist = MailList.MailList(list_name, lock=False)
except Errors.MMUnknownListError:
# The list could have been deleted by another process.
continue
num_rmembers = len(mlist.getRegularMemberKeys())
num_dmembers = len(mlist.getDigestMemberKeys())
yield 'mailman_subscribers{list="%s"} %d\n' % (
list_name.lower(), num_rmembers + num_dmembers)
return app.response_class(_dump_metrics(), mimetype='text/plain')
### SSL server with the right parameters. ### SSL server with the right parameters.
...@@ -171,6 +182,7 @@ def main(): ...@@ -171,6 +182,7 @@ def main():
parser.error('Too many arguments') parser.error('Too many arguments')
app.config.from_pyfile(opts.config) app.config.from_pyfile(opts.config)
cache.init_app(app)
init_sso(app) init_sso(app)
init_tls_auth(app) init_tls_auth(app)
serve_ssl(app, host=opts.addr, port=opts.port) serve_ssl(app, host=opts.addr, port=opts.port)
......
git+https://git.autistici.org/ai/sso.git#egg=sso&subdirectory=src/python git+https://git.autistici.org/ai/sso.git#egg=sso&subdirectory=src/python
Flask Flask
Flask-Caching
...@@ -11,6 +11,7 @@ setup( ...@@ -11,6 +11,7 @@ setup(
author_email="info@autistici.org", author_email="info@autistici.org",
url="https://git.autistici.org/ai3/python-mailman-api", url="https://git.autistici.org/ai3/python-mailman-api",
install_requires=["Flask", install_requires=["Flask",
"Flask-Caching",
"sso"], "sso"],
packages=find_packages(), packages=find_packages(),
entry_points={ entry_points={
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment