Skip to content
Snippets Groups Projects
Unverified Commit 1cea82dc authored by Agate's avatar Agate :speech_balloon:
Browse files

Addiional hooks, still not working wih webserver though

parent e0ef3f3a
No related branches found
No related tags found
No related merge requests found
from django import urls
from pluggy import PluginManager, HookimplMarker, HookspecMarker
plugins_manager = PluginManager("funkwhale")
hook = HookimplMarker("funkwhale")
hookspec = HookspecMarker("funkwhale")
class PluginViewMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
from django.conf import settings
response = self.get_response(request)
if response.status_code == 404 and request.path.startswith("/plugins/"):
match = urls.resolve(request.path, urlconf=settings.PLUGINS_URLCONF)
response = match.func(request, *match.args, **match.kwargs)
return response
class ConfigError(ValueError):
pass
class Plugin:
conf = {}
def get_conf(self):
return {"enabled": self.plugin_settings.enabled}
def register_api_view(self, path, name=None):
def register(view):
return urls.path(
"plugins/{}/{}".format(self.name.replace("_", "-"), path),
view,
name="plugins-{}-{}".format(self.name, name),
)
return register
def plugin_settings(self):
"""
Return plugin specific settings from django.conf.settings
"""
import ipdb
ipdb.set_trace()
from django.conf import settings
d = {}
for key in dir(settings):
k = key.lower()
if not k.startswith("plugin_{}_".format(self.name.lower())):
continue
value = getattr(settings, key)
s_key = k.replace("plugin_{}_".format(self.name.lower()), "")
d[s_key] = value
return clean(d, self.conf, self.name)
def clean(d, conf, plugin_name):
cleaned = {}
for key, c in conf.items():
if key in d:
try:
cleaned[key] = c["validator"](d[key])
except (ValueError, TypeError, AttributeError):
raise ConfigError(
"Invalid value {} for setting {} in plugin {}".format(
d[key], key, plugin_name
)
)
else:
cleaned[key] = c["default"]
return cleaned
def reverse(name, **kwargs):
from django.conf import settings
return urls.reverse(name, settings.PLUGINS_URLCONF, **kwargs)
def resolve(name, **kwargs):
from django.conf import settings
return urls.resolve(name, settings.PLUGINS_URLCONF, **kwargs)
# def install_plugin(name_or_path):
# subprocess.check_call([sys.executable, "-m", "pip", "install", package])
# sub
class HookSpec:
@hookspec
def register_apps(self):
"""
Register additional apps in INSTALLED_APPS.
:rvalue: list"""
@hookspec
def middlewares_before(self):
"""
Register additional middlewares at the outer level.
:rvalue: list"""
@hookspec
def middlewares_after(self):
"""
Register additional middlewares at the inner level.
:rvalue: list"""
@hookspec
def urls(self):
"""
Register additional urls.
:rvalue: list"""
plugins_manager.add_hookspecs(HookSpec())
...@@ -7,18 +7,20 @@ import os ...@@ -7,18 +7,20 @@ import os
import sys import sys
from urllib.parse import urlsplit from urllib.parse import urlsplit
import environ
from celery.schedules import crontab from celery.schedules import crontab
from funkwhale_api import __version__ from funkwhale_api import __version__
import environ
logger = logging.getLogger("funkwhale_api.config")
ROOT_DIR = environ.Path(__file__) - 3 # (/a/b/myfile.py - 3 = /) ROOT_DIR = environ.Path(__file__) - 3 # (/a/b/myfile.py - 3 = /)
APPS_DIR = ROOT_DIR.path("funkwhale_api") APPS_DIR = ROOT_DIR.path("funkwhale_api")
sys.path.append(os.path.join(APPS_DIR, "plugins"))
logger = logging.getLogger("funkwhale_api.config")
env = environ.Env() env = environ.Env()
from .. import plugins # noqa
total = plugins.plugins_manager.load_setuptools_entrypoints("funkwhale")
LOGLEVEL = env("LOGLEVEL", default="info").upper() LOGLEVEL = env("LOGLEVEL", default="info").upper()
""" """
Default logging level for the Funkwhale processes""" # pylint: disable=W0105 Default logging level for the Funkwhale processes""" # pylint: disable=W0105
...@@ -252,27 +254,45 @@ PLUGINS = [p for p in env.list("FUNKWHALE_PLUGINS", default=[]) if p] ...@@ -252,27 +254,45 @@ PLUGINS = [p for p in env.list("FUNKWHALE_PLUGINS", default=[]) if p]
""" """
List of Funkwhale plugins to load. List of Funkwhale plugins to load.
""" """
if PLUGINS:
logger.info("Running with the following plugins enabled: %s", ", ".join(PLUGINS))
else:
logger.info("Running with no plugins")
ADDITIONAL_APPS = env.list("ADDITIONAL_APPS", default=[]) ADDITIONAL_APPS = env.list("ADDITIONAL_APPS", default=[])
""" """
List of Django apps to load in addition to Funkwhale plugins and apps. List of Django apps to load in addition to Funkwhale plugins and apps.
""" """
PLUGINS_APPS = tuple()
for p in plugins.plugins_manager.hook.register_apps():
PLUGINS_APPS += (p,)
INSTALLED_APPS = ( INSTALLED_APPS = (
DJANGO_APPS DJANGO_APPS
+ THIRD_PARTY_APPS + THIRD_PARTY_APPS
+ LOCAL_APPS + LOCAL_APPS
+ tuple(["{}.apps.Plugin".format(p) for p in PLUGINS])
+ tuple(ADDITIONAL_APPS) + tuple(ADDITIONAL_APPS)
+ tuple(PLUGINS)
+ tuple(PLUGINS_APPS)
) )
if PLUGINS:
logger.info("Running with the following plugins enabled: %s", ", ".join(PLUGINS))
else:
logger.info("Running with no plugins")
# MIDDLEWARE CONFIGURATION # MIDDLEWARE CONFIGURATION
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
ADDITIONAL_MIDDLEWARES_BEFORE = env.list("ADDITIONAL_MIDDLEWARES_BEFORE", default=[]) ADDITIONAL_MIDDLEWARES_START = env.list("ADDITIONAL_MIDDLEWARES_START", default=[])
MIDDLEWARE = tuple(ADDITIONAL_MIDDLEWARES_BEFORE) + ( for group in plugins.plugins_manager.hook.middlewares_before():
for m in group:
ADDITIONAL_MIDDLEWARES_START.append(m)
ADDITIONAL_MIDDLEWARES_END = env.list("ADDITIONAL_MIDDLEWARES_END", default=[])
for group in plugins.plugins_manager.hook.middlewares_after():
for m in group:
ADDITIONAL_MIDDLEWARES_END.append(m)
MIDDLEWARE = (
tuple(ADDITIONAL_MIDDLEWARES_START)
+ (
"django.middleware.security.SecurityMiddleware", "django.middleware.security.SecurityMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware",
"corsheaders.middleware.CorsMiddleware", "corsheaders.middleware.CorsMiddleware",
...@@ -288,6 +308,9 @@ MIDDLEWARE = tuple(ADDITIONAL_MIDDLEWARES_BEFORE) + ( ...@@ -288,6 +308,9 @@ MIDDLEWARE = tuple(ADDITIONAL_MIDDLEWARES_BEFORE) + (
"funkwhale_api.common.middleware.ThrottleStatusMiddleware", "funkwhale_api.common.middleware.ThrottleStatusMiddleware",
"funkwhale_api.common.plugins.PluginViewMiddleware", "funkwhale_api.common.plugins.PluginViewMiddleware",
) )
+ tuple(ADDITIONAL_MIDDLEWARES_END)
)
# DEBUG # DEBUG
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
...@@ -480,6 +503,7 @@ AWS_ACCESS_KEY_ID = env("AWS_ACCESS_KEY_ID", default=None) ...@@ -480,6 +503,7 @@ AWS_ACCESS_KEY_ID = env("AWS_ACCESS_KEY_ID", default=None)
""" """
Access-key ID for your S3 storage. Access-key ID for your S3 storage.
""" """
SECRET_KEY = env("DJANGO_SECRET_KEY")
if AWS_ACCESS_KEY_ID: if AWS_ACCESS_KEY_ID:
AWS_ACCESS_KEY_ID = AWS_ACCESS_KEY_ID AWS_ACCESS_KEY_ID = AWS_ACCESS_KEY_ID
......
...@@ -17,14 +17,6 @@ DEBUG = env.bool("DJANGO_DEBUG", default=True) ...@@ -17,14 +17,6 @@ DEBUG = env.bool("DJANGO_DEBUG", default=True)
FORCE_HTTPS_URLS = env.bool("FORCE_HTTPS_URLS", default=False) FORCE_HTTPS_URLS = env.bool("FORCE_HTTPS_URLS", default=False)
TEMPLATES[0]["OPTIONS"]["debug"] = DEBUG TEMPLATES[0]["OPTIONS"]["debug"] = DEBUG
# SECRET CONFIGURATION
# ------------------------------------------------------------------------------
# See: https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
# Note: This key only used for development and testing.
SECRET_KEY = env(
"DJANGO_SECRET_KEY", default="mc$&b=5j#6^bv7tld1gyjp2&+^-qrdy=0sw@r5sua*1zp4fmxc"
)
# Mail settings # Mail settings
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
EMAIL_HOST = "localhost" EMAIL_HOST = "localhost"
......
...@@ -16,8 +16,6 @@ from .common import * # noqa ...@@ -16,8 +16,6 @@ from .common import * # noqa
# SECRET CONFIGURATION # SECRET CONFIGURATION
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# See: https://docs.djangoproject.com/en/dev/ref/settings/#secret-key # See: https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
# Raises ImproperlyConfigured exception if DJANGO_SECRET_KEY not in os.environ
SECRET_KEY = env("DJANGO_SECRET_KEY")
# django-secure # django-secure
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
......
...@@ -8,6 +8,8 @@ from django.conf.urls.static import static ...@@ -8,6 +8,8 @@ from django.conf.urls.static import static
from funkwhale_api.common import admin from funkwhale_api.common import admin
from django.views import defaults as default_views from django.views import defaults as default_views
from config import plugins
urlpatterns = [ urlpatterns = [
# Django Admin, use {% url 'admin:index' %} # Django Admin, use {% url 'admin:index' %}
...@@ -24,6 +26,9 @@ urlpatterns = [ ...@@ -24,6 +26,9 @@ urlpatterns = [
# Your stuff: custom urls includes go here # Your stuff: custom urls includes go here
] ]
for group in plugins.plugins_manager.hook.urls():
urlpatterns += group
if settings.DEBUG: if settings.DEBUG:
# This allows the error pages to be debugged during development, just visit # This allows the error pages to be debugged during development, just visit
# these url in browser to see how these error pages look like. # these url in browser to see how these error pages look like.
......
import json
from django import http
from django import urls
from config import plugins
class Plugin(plugins.Plugin):
name = "prometheus_exporter"
@plugins.hook
def register_apps(self):
return "django_prometheus"
@plugins.hook
def middlewares_before(self):
return [
"django_prometheus.middleware.PrometheusBeforeMiddleware",
]
@plugins.hook
def middlewares_after(self):
return [
"django_prometheus.middleware.PrometheusAfterMiddleware",
]
@plugins.hook
def urls(self):
return [urls.url(r"^plugins/prometheus/exporter/?$", prometheus)]
plugins.plugins_manager.register(Plugin())
def prometheus(request):
stats = {"foo": "bar"}
return http.HttpResponse(json.dumps(stats))
[metadata]
name = funkwhale-prometheus
description = "A prometheus metric exporter for your Funkwhale pod"
version = 0.1.dev0
author = Agate Blue
author_email = me@agate.blue
url = https://dev.funkwhale.audio/funkwhale/funkwhale
long_description = file: README.md
license = AGPL3
classifiers =
Development Status :: 3 - Alpha
License :: OSI Approved :: AGPL
Natural Language :: English
Programming Language :: Python :: 3.6
[options]
zip_safe = True
include_package_data = True
packages = find:
install_requires =
django_prometheus
[options.entry_points]
funkwhale-plugin =
prometheus = prometheus_exporter.main
[options.packages.find]
exclude =
tests
[bdist_wheel]
universal = 1
[tool:pytest]
testpaths = tests
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from setuptools import setup
setup()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment