feat: plugins can extend the GraphQL schema

This commit is contained in:
Jens Vogler 2022-02-02 14:21:45 +01:00
parent c15cfc26f1
commit ceb0d9d78f
2 changed files with 73 additions and 3 deletions

View File

@ -1,7 +1,10 @@
import collections
import inspect
import graphene
from packaging import version
from graphql.type.definition import GraphQLType
from django.apps import AppConfig
from django.core.exceptions import ImproperlyConfigured
from django.template.loader import get_template
@ -15,6 +18,10 @@ from extras.plugins.utils import import_object
# Initialize plugin registry stores
registry['plugin_template_extensions'] = collections.defaultdict(list)
registry['plugin_menu_items'] = {}
registry['graphql_queries'] = []
registry['graphql_mutations'] = []
registry['graphql_subscriptions'] = []
registry['graphql_types'] = []
#
@ -50,6 +57,12 @@ class PluginConfig(AppConfig):
# Django-rq queues dedicated to the plugin
queues = []
# Graphene GraphQL schema extension points
graphql_queries = []
graphql_mutations = []
graphql_subscriptions = []
graphql_types = []
# Default integration paths. Plugin authors can override these to customize the paths to
# integrated components.
template_extensions = 'template_content.template_extensions'
@ -67,6 +80,10 @@ class PluginConfig(AppConfig):
if menu_items is not None:
register_menu_items(self.verbose_name, menu_items)
# Register GraphQL schema extensions
register_graphql_schema(self.graphql_queries, self.graphql_mutations, self.graphql_subscriptions,
self.graphql_types)
@classmethod
def validate(cls, user_config, netbox_version):
@ -242,3 +259,20 @@ def register_menu_items(section_name, class_list):
raise TypeError(f"{button} must be an instance of extras.plugins.PluginMenuButton")
registry['plugin_menu_items'][section_name] = class_list
def register_graphql_schema(queries, mutations, subscriptions, types):
"""
Register extensions to the GraphQL schema
"""
for object_type in [*queries, *mutations, *subscriptions]:
if not issubclass(object_type, graphene.ObjectType):
raise TypeError(f"{object_type} must be a subclass of graphene.types.objecttype.ObjectType")
for graphql_type in types:
if not issubclass(graphql_type, GraphQLType):
raise TypeError(f"f{graphql_type} must be a subclass of graphql.type.definition.GraphQLType")
registry['graphql_queries'].extend(queries)
registry['graphql_subscriptions'].extend(subscriptions)
registry['graphql_types'].extend(types)

View File

@ -3,14 +3,14 @@ import graphene
from circuits.graphql.schema import CircuitsQuery
from dcim.graphql.schema import DCIMQuery
from extras.graphql.schema import ExtrasQuery
from extras.plugins import registry
from ipam.graphql.schema import IPAMQuery
from tenancy.graphql.schema import TenancyQuery
from users.graphql.schema import UsersQuery
from virtualization.graphql.schema import VirtualizationQuery
from wireless.graphql.schema import WirelessQuery
class Query(
query_types = [
CircuitsQuery,
DCIMQuery,
ExtrasQuery,
@ -19,9 +19,45 @@ class Query(
UsersQuery,
VirtualizationQuery,
WirelessQuery,
*registry['graphql_queries'],
]
mutation_types = [
*registry['graphql_mutations'],
]
subscription_types = [
*registry['graphql_subscriptions'],
]
extra_types = [
*registry['graphql_types'],
]
class Query(
*query_types,
graphene.ObjectType
):
pass
schema = graphene.Schema(query=Query, auto_camelcase=False)
class Mutation(
*mutation_types,
graphene.ObjectType
):
pass
class Subscription(
*subscription_types,
graphene.ObjectType
):
pass
schema = graphene.Schema(query=Query,
mutation=Mutation if len(mutation_types) > 0 else None,
subscription=Subscription if len(subscription_types) > 0 else None,
types=extra_types if len(extra_types) > 0 else None,
auto_camelcase=False)