Repository: nautobot/nautobot

Issue:
Add custom link feature to dcim.interfaces
### As ...

Nelly - Network Engineer

### I want ...

... to be able to add custom links to dcim.interfaces (on the specific interface page and not the "all interfaces" overview page)

### So that ...

... I'm able to add a link to an external application (e.g. external IPAM) which allows the user to click to get additional information about the end device that is connected to the interface x of device y

### I know this is done when...

... I'm able to add custom links for dcim.interfaces content types (not the overview page but the individual interface page)

### Optional - Feature groups this request pertains to.

- [ ] Automation
- [ ] Circuits
- [X] DCIM
- [ ] IPAM
- [ ] Misc (including Data Sources)
- [ ] Organization
- [ ] Plugins (and other Extensibility)
- [ ] Security (Secrets, etc)
- [ ] Image Management
- [ ] UI/UX
- [ ] Documentation
- [ ] Other (not directly a platform feature)

### Database Changes

This feature already exists for a some of the content types like devices, cables, locations, ipam, etc.

I don't know what changes must be made to extend this feature for dcim.interfaces

### External Dependencies

_No response_


Discussion:

Resolving patch:
diff --git a/nautobot/dcim/models/device_components.py b/nautobot/dcim/models/device_components.py
--- a/nautobot/dcim/models/device_components.py
+++ b/nautobot/dcim/models/device_components.py
@@ -205,6 +205,7 @@ def connected_endpoint(self):
 
 @extras_features(
     "cable_terminations",
+    "custom_links",
     "custom_validators",
     "export_templates",
     "graphql",
@@ -236,7 +237,7 @@ def parent(self):
 #
 
 
-@extras_features("cable_terminations", "custom_validators", "graphql", "webhooks")
+@extras_features("custom_links", "cable_terminations", "custom_validators", "graphql", "webhooks")
 class ConsoleServerPort(CableTermination, PathEndpoint, ComponentModel):
     """
     A physical port within a Device (typically a designated console server) which provides access to ConsolePorts.
@@ -265,6 +266,7 @@ def parent(self):
 
 @extras_features(
     "cable_terminations",
+    "custom_links",
     "custom_validators",
     "export_templates",
     "graphql",
@@ -380,7 +382,7 @@ def get_power_draw(self):
 #
 
 
-@extras_features("cable_terminations", "custom_validators", "graphql", "webhooks")
+@extras_features("cable_terminations", "custom_links", "custom_validators", "graphql", "webhooks")
 class PowerOutlet(CableTermination, PathEndpoint, ComponentModel):
     """
     A physical power outlet (output) within a Device which provides power to a PowerPort.
@@ -490,6 +492,7 @@ def save(self, *args, **kwargs):
 
 @extras_features(
     "cable_terminations",
+    "custom_links",
     "custom_validators",
     "export_templates",
     "graphql",
@@ -892,7 +895,7 @@ def __str__(self):
 #
 
 
-@extras_features("cable_terminations", "custom_validators", "graphql", "webhooks")
+@extras_features("cable_terminations", "custom_links", "custom_validators", "graphql", "webhooks")
 class FrontPort(CableTermination, ComponentModel):
     """
     A pass-through port on the front of a Device.
@@ -936,7 +939,7 @@ def clean(self):
             )
 
 
-@extras_features("cable_terminations", "custom_validators", "graphql", "webhooks")
+@extras_features("cable_terminations", "custom_links", "custom_validators", "graphql", "webhooks")
 class RearPort(CableTermination, ComponentModel):
     """
     A pass-through port on the rear of a Device.
@@ -978,7 +981,7 @@ def parent(self):
 #
 
 
-@extras_features("custom_validators", "graphql", "webhooks")
+@extras_features("custom_links", "custom_validators", "graphql", "webhooks")
 class DeviceBay(ComponentModel):
     """
     An empty space within a Device which can house a child device
@@ -1028,6 +1031,7 @@ def parent(self):
 
 
 @extras_features(
+    "custom_links",
     "custom_validators",
     "export_templates",
     "graphql",


Test patch: