mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-17 04:58:16 -06:00
feat: plugins can extend the GraphQL schema
This commit is contained in:
parent
c15cfc26f1
commit
ceb0d9d78f
@ -1,7 +1,10 @@
|
|||||||
import collections
|
import collections
|
||||||
import inspect
|
import inspect
|
||||||
|
import graphene
|
||||||
from packaging import version
|
from packaging import version
|
||||||
|
|
||||||
|
from graphql.type.definition import GraphQLType
|
||||||
|
|
||||||
from django.apps import AppConfig
|
from django.apps import AppConfig
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.template.loader import get_template
|
from django.template.loader import get_template
|
||||||
@ -15,6 +18,10 @@ from extras.plugins.utils import import_object
|
|||||||
# Initialize plugin registry stores
|
# Initialize plugin registry stores
|
||||||
registry['plugin_template_extensions'] = collections.defaultdict(list)
|
registry['plugin_template_extensions'] = collections.defaultdict(list)
|
||||||
registry['plugin_menu_items'] = {}
|
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
|
# Django-rq queues dedicated to the plugin
|
||||||
queues = []
|
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
|
# Default integration paths. Plugin authors can override these to customize the paths to
|
||||||
# integrated components.
|
# integrated components.
|
||||||
template_extensions = 'template_content.template_extensions'
|
template_extensions = 'template_content.template_extensions'
|
||||||
@ -67,6 +80,10 @@ class PluginConfig(AppConfig):
|
|||||||
if menu_items is not None:
|
if menu_items is not None:
|
||||||
register_menu_items(self.verbose_name, menu_items)
|
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
|
@classmethod
|
||||||
def validate(cls, user_config, netbox_version):
|
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")
|
raise TypeError(f"{button} must be an instance of extras.plugins.PluginMenuButton")
|
||||||
|
|
||||||
registry['plugin_menu_items'][section_name] = class_list
|
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)
|
||||||
|
@ -3,14 +3,14 @@ import graphene
|
|||||||
from circuits.graphql.schema import CircuitsQuery
|
from circuits.graphql.schema import CircuitsQuery
|
||||||
from dcim.graphql.schema import DCIMQuery
|
from dcim.graphql.schema import DCIMQuery
|
||||||
from extras.graphql.schema import ExtrasQuery
|
from extras.graphql.schema import ExtrasQuery
|
||||||
|
from extras.plugins import registry
|
||||||
from ipam.graphql.schema import IPAMQuery
|
from ipam.graphql.schema import IPAMQuery
|
||||||
from tenancy.graphql.schema import TenancyQuery
|
from tenancy.graphql.schema import TenancyQuery
|
||||||
from users.graphql.schema import UsersQuery
|
from users.graphql.schema import UsersQuery
|
||||||
from virtualization.graphql.schema import VirtualizationQuery
|
from virtualization.graphql.schema import VirtualizationQuery
|
||||||
from wireless.graphql.schema import WirelessQuery
|
from wireless.graphql.schema import WirelessQuery
|
||||||
|
|
||||||
|
query_types = [
|
||||||
class Query(
|
|
||||||
CircuitsQuery,
|
CircuitsQuery,
|
||||||
DCIMQuery,
|
DCIMQuery,
|
||||||
ExtrasQuery,
|
ExtrasQuery,
|
||||||
@ -19,9 +19,45 @@ class Query(
|
|||||||
UsersQuery,
|
UsersQuery,
|
||||||
VirtualizationQuery,
|
VirtualizationQuery,
|
||||||
WirelessQuery,
|
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
|
graphene.ObjectType
|
||||||
):
|
):
|
||||||
pass
|
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)
|
||||||
|
Loading…
Reference in New Issue
Block a user