1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Initial work on GraphQL

This commit is contained in:
jeremystretch
2022-01-27 14:18:25 -05:00
parent df95115e2e
commit 03ea257711
8 changed files with 124 additions and 31 deletions

View File

@@ -14,9 +14,10 @@ from extras.plugins.utils import import_object
# Initialize plugin registry
registry['plugins'] = {
'template_extensions': collections.defaultdict(list),
'graphql_schemas': [],
'menu_items': {},
'preferences': {},
'template_extensions': collections.defaultdict(list),
}
@@ -55,13 +56,15 @@ class PluginConfig(AppConfig):
# Default integration paths. Plugin authors can override these to customize the paths to
# integrated components.
template_extensions = 'template_content.template_extensions'
graphql_schema = 'graphql.schema'
menu_items = 'navigation.menu_items'
template_extensions = 'template_content.template_extensions'
user_preferences = 'preferences.preferences'
def ready(self):
plugin_name = self.name.rsplit('.', 1)[1]
# Register template content
# Register template content (if defined)
template_extensions = import_object(f"{self.__module__}.{self.template_extensions}")
if template_extensions is not None:
register_template_extensions(template_extensions)
@@ -71,10 +74,14 @@ class PluginConfig(AppConfig):
if menu_items is not None:
register_menu_items(self.verbose_name, menu_items)
# Register user preferences
# Register GraphQL schema (if defined)
graphql_schema = import_object(f"{self.__module__}.{self.graphql_schema}")
if graphql_schema is not None:
register_graphql_schema(graphql_schema)
# Register user preferences (if defined)
user_preferences = import_object(f"{self.__module__}.{self.user_preferences}")
if user_preferences is not None:
plugin_name = self.name.rsplit('.', 1)[1]
register_user_preferences(plugin_name, user_preferences)
@classmethod
@@ -180,7 +187,7 @@ def register_template_extensions(class_list):
# Validation
for template_extension in class_list:
if not inspect.isclass(template_extension):
raise TypeError(f"PluginTemplateExtension class {template_extension} was passes as an instance!")
raise TypeError(f"PluginTemplateExtension class {template_extension} was passed as an instance!")
if not issubclass(template_extension, PluginTemplateExtension):
raise TypeError(f"{template_extension} is not a subclass of extras.plugins.PluginTemplateExtension!")
if template_extension.model is None:
@@ -254,6 +261,17 @@ def register_menu_items(section_name, class_list):
registry['plugins']['menu_items'][section_name] = class_list
#
# GraphQL schemas
#
def register_graphql_schema(graphql_schema):
"""
Register a GraphQL schema class for inclusion in NetBox's GraphQL API.
"""
registry['plugins']['graphql_schemas'].append(graphql_schema)
#
# User preferences
#

View File

@@ -0,0 +1,21 @@
import graphene
from graphene_django import DjangoObjectType
from netbox.graphql.fields import ObjectField, ObjectListField
from . import models
class DummyModelType(DjangoObjectType):
class Meta:
model = models.DummyModel
fields = '__all__'
class DummyQuery(graphene.ObjectType):
dummymodel = ObjectField(DummyModelType)
dummymodel_list = ObjectListField(DummyModelType)
schema = DummyQuery

View File

@@ -7,6 +7,7 @@ from django.urls import reverse
from extras.registry import registry
from extras.tests.dummy_plugin import config as dummy_config
from netbox.graphql.schema import Query
@skipIf('extras.tests.dummy_plugin' not in settings.PLUGINS, "dummy_plugin not in settings.PLUGINS")
@@ -143,3 +144,12 @@ class PluginTest(TestCase):
user_config = {'bar': 456}
DummyConfigWithDefaultSettings.validate(user_config, settings.VERSION)
self.assertEqual(user_config['bar'], 456)
def test_graphql(self):
"""
Validate the registration and operation of plugin-provided GraphQL schemas.
"""
from extras.tests.dummy_plugin.graphql import DummyQuery
self.assertIn(DummyQuery, registry['plugins']['graphql_schemas'])
self.assertTrue(issubclass(Query, DummyQuery))