Repository: netbox-community/netbox

Issue:
Add connected_enpoints property to graphql api
### NetBox version

v.3.4.5

### Feature type

Change to existing functionality

### Proposed functionality

The netbox graphql api should expose the same connected_endpoints property as the rest api.
This makes it easier to resolve complete paths via graphql.

A query would look like:

```{
  device(id:xx) {
    id
    name
    interfaces {
      name
      connected_endpoints {
        ... on InterfaceType {
          ip_addresses {
            address
          }
          device {
            name
            device_role {
              slug
            }
          }
        }
      }
    }
  }
}
```

### Use case

This function helps on making graphql information analog to rest-Api information.

### Database changes

_No response_

### External dependencies

_No response_


Discussion:

Resolving patch:
diff --git a/netbox/dcim/graphql/mixins.py b/netbox/dcim/graphql/mixins.py
--- a/netbox/dcim/graphql/mixins.py
+++ b/netbox/dcim/graphql/mixins.py
@@ -10,3 +10,11 @@ def resolve_cable_end(self, info):
 
     def resolve_link_peers(self, info):
         return self.link_peers
+
+
+class PathEndpointMixin:
+    connected_endpoints = graphene.List('dcim.graphql.gfk_mixins.LinkPeerType')
+
+    def resolve_connected_endpoints(self, info):
+        # Handle empty values
+        return self.connected_endpoints or None
diff --git a/netbox/dcim/graphql/types.py b/netbox/dcim/graphql/types.py
--- a/netbox/dcim/graphql/types.py
+++ b/netbox/dcim/graphql/types.py
@@ -7,7 +7,7 @@
 from ipam.graphql.mixins import IPAddressesMixin, VLANGroupsMixin
 from netbox.graphql.scalars import BigInt
 from netbox.graphql.types import BaseObjectType, OrganizationalObjectType, NetBoxObjectType
-from .mixins import CabledObjectMixin
+from .mixins import CabledObjectMixin, PathEndpointMixin
 
 __all__ = (
     'CableType',
@@ -117,7 +117,7 @@ class Meta:
         filterset_class = filtersets.CableTerminationFilterSet
 
 
-class ConsolePortType(ComponentObjectType, CabledObjectMixin):
+class ConsolePortType(ComponentObjectType, CabledObjectMixin, PathEndpointMixin):
 
     class Meta:
         model = models.ConsolePort
@@ -139,7 +139,7 @@ def resolve_type(self, info):
         return self.type or None
 
 
-class ConsoleServerPortType(ComponentObjectType, CabledObjectMixin):
+class ConsoleServerPortType(ComponentObjectType, CabledObjectMixin, PathEndpointMixin):
 
     class Meta:
         model = models.ConsoleServerPort
@@ -241,7 +241,7 @@ class Meta:
         filterset_class = filtersets.FrontPortTemplateFilterSet
 
 
-class InterfaceType(IPAddressesMixin, ComponentObjectType, CabledObjectMixin):
+class InterfaceType(IPAddressesMixin, ComponentObjectType, CabledObjectMixin, PathEndpointMixin):
 
     class Meta:
         model = models.Interface
@@ -354,7 +354,7 @@ class Meta:
         filterset_class = filtersets.PlatformFilterSet
 
 
-class PowerFeedType(NetBoxObjectType, CabledObjectMixin):
+class PowerFeedType(NetBoxObjectType, CabledObjectMixin, PathEndpointMixin):
 
     class Meta:
         model = models.PowerFeed
@@ -362,7 +362,7 @@ class Meta:
         filterset_class = filtersets.PowerFeedFilterSet
 
 
-class PowerOutletType(ComponentObjectType, CabledObjectMixin):
+class PowerOutletType(ComponentObjectType, CabledObjectMixin, PathEndpointMixin):
 
     class Meta:
         model = models.PowerOutlet
@@ -398,7 +398,7 @@ class Meta:
         filterset_class = filtersets.PowerPanelFilterSet
 
 
-class PowerPortType(ComponentObjectType, CabledObjectMixin):
+class PowerPortType(ComponentObjectType, CabledObjectMixin, PathEndpointMixin):
 
     class Meta:
         model = models.PowerPort


Test patch: