Преглед изворни кода

9478 link peers to GraphQL (#10574)

* 9468 add link_peer to GraphQL

* 9478 add class_type

* 9478 fix tests

* 9478 fix tests

* 9478 fix tests
Arthur Hanson пре 3 година
родитељ
комит
10bb8fa10a

+ 59 - 0
netbox/dcim/graphql/gfk_mixins.py

@@ -0,0 +1,59 @@
+import graphene
+from circuits.graphql.types import CircuitTerminationType
+from circuits.models import CircuitTermination
+from dcim.graphql.types import (
+    ConsolePortType,
+    ConsoleServerPortType,
+    FrontPortType,
+    InterfaceType,
+    PowerFeedType,
+    PowerOutletType,
+    PowerPortType,
+    RearPortType,
+)
+from dcim.models import (
+    ConsolePort,
+    ConsoleServerPort,
+    FrontPort,
+    Interface,
+    PowerFeed,
+    PowerOutlet,
+    PowerPort,
+    RearPort,
+)
+
+
+class LinkPeerType(graphene.Union):
+    class Meta:
+        types = (
+            CircuitTerminationType,
+            ConsolePortType,
+            ConsoleServerPortType,
+            FrontPortType,
+            InterfaceType,
+            PowerFeedType,
+            PowerOutletType,
+            PowerPortType,
+            RearPortType,
+        )
+
+    @classmethod
+    def resolve_type(cls, instance, info):
+        if type(instance) == CircuitTermination:
+            return CircuitTerminationType
+        if type(instance) == ConsolePortType:
+            return ConsolePortType
+        if type(instance) == ConsoleServerPort:
+            return ConsoleServerPortType
+        if type(instance) == FrontPort:
+            return FrontPortType
+        if type(instance) == Interface:
+            return InterfaceType
+        if type(instance) == PowerFeed:
+            return PowerFeedType
+        if type(instance) == PowerOutlet:
+            return PowerOutletType
+        if type(instance) == PowerPort:
+            return PowerPortType
+        if type(instance) == RearPort:
+            return RearPortType

+ 7 - 0
netbox/dcim/graphql/mixins.py

@@ -1,5 +1,12 @@
+import graphene
+
+
 class CabledObjectMixin:
+    link_peers = graphene.List('dcim.graphql.gfk_mixins.LinkPeerType')
 
     def resolve_cable_end(self, info):
         # Handle empty values
         return self.cable_end or None
+
+    def resolve_link_peers(self, info):
+        return self.link_peers

+ 13 - 5
netbox/netbox/graphql/types.py

@@ -1,10 +1,14 @@
 import graphene
 
 from django.contrib.contenttypes.models import ContentType
+from extras.graphql.mixins import (
+    ChangelogMixin,
+    CustomFieldsMixin,
+    JournalEntriesMixin,
+    TagsMixin,
+)
 from graphene_django import DjangoObjectType
 
-from extras.graphql.mixins import ChangelogMixin, CustomFieldsMixin, JournalEntriesMixin, TagsMixin
-
 __all__ = (
     'BaseObjectType',
     'ObjectType',
@@ -22,9 +26,7 @@ class BaseObjectType(DjangoObjectType):
     Base GraphQL object type for all NetBox objects. Restricts the model queryset to enforce object permissions.
     """
     display = graphene.String()
-
-    def resolve_display(parent, info, **kwargs):
-        return str(parent)
+    class_type = graphene.String()
 
     class Meta:
         abstract = True
@@ -34,6 +36,12 @@ class BaseObjectType(DjangoObjectType):
         # Enforce object permissions on the queryset
         return queryset.restrict(info.context.user, 'view')
 
+    def resolve_display(parent, info, **kwargs):
+        return str(parent)
+
+    def resolve_class_type(parent, info, **kwargs):
+        return parent.__class__.__name__
+
 
 class ObjectType(
     ChangelogMixin,

+ 5 - 1
netbox/utilities/testing/api.py

@@ -1,3 +1,4 @@
+import inspect
 import json
 
 from django.conf import settings
@@ -5,7 +6,7 @@ from django.contrib.auth.models import User
 from django.contrib.contenttypes.models import ContentType
 from django.urls import reverse
 from django.test import override_settings
-from graphene.types import Dynamic as GQLDynamic, List as GQLList
+from graphene.types import Dynamic as GQLDynamic, List as GQLList, Union as GQLUnion
 from rest_framework import status
 from rest_framework.test import APIClient
 
@@ -449,6 +450,9 @@ class APIViewTestCases:
                 if type(field) is GQLDynamic:
                     # Dynamic fields must specify a subselection
                     fields_string += f'{field_name} {{ id }}\n'
+                elif type(field.type) is GQLList and inspect.isclass(field.type.of_type) and issubclass(field.type.of_type, GQLUnion):
+                    # Union types dont' have an id or consistent values
+                    continue
                 elif type(field.type) is GQLList and field_name != 'choices':
                     # TODO: Come up with something more elegant
                     # Temporary hack to support automated testing of reverse generic relations