Webhook Data - Fails to show Parent / Child #2460

Closed
opened 2025-12-29 18:19:02 +01:00 by adam · 8 comments
Owner

Originally created by @luis-n4489 on GitHub (Mar 13, 2019).

Originally assigned to: @lampwins on GitHub.

Environment

  • Python version: v3.6.7
  • NetBox version: v2.5.6

Steps to Reproduce

  1. Create a device test1 with interface eth0
  2. connect test1 interface eth0 to "switch" port in netbox
  3. delete test1 device.

Expected Behavior

  • deletion webhook for children should be invoked before deletion webhook for parents
  • deletion webhook for children should include the parent reference

Observed Behavior

{
  "status": "processed",
  "occurrence_time": "2019-03-09T18:29:27.000000Z",
  "trigger": "netbox.webhook.object_deleted",
  "id": "5c844c5755fdfa02b51f03c0",
  "payload": {
    "timestamp": "2019-03-09 23:29:27.546951",
    "model": "device",
    "data": {
      "last_updated": "2019-03-09T23:29:09.980034Z",
      "site": {
        "url": "/api/dcim/sites/1/",
        "id": 1,
        "name": "Nap",
        "slug": "nap"
      },
      "asset_tag": null,
      "cluster": null,
      "device_type": {
        "display_name": "APC AP8841",
        "url": "/api/dcim/device-types/2/",
        "id": 2,
        "model": "AP8841",
        "slug": "ap8841",
        "manufacturer": {
          "url": "/api/dcim/manufacturers/1/",
          "id": 1,
          "slug": "apc",
          "name": "APC"
        }
      },
      "serial": "12345",
      "id": 20,
      "custom_fields": {
        "Environment": null,
        "SnipeITID": null,
        "Monitor": null,
        "coordinates": null
      },
      "display_name": "test",
      "local_context_data": null,
      "comments": "",
      "platform": null,
      "status": {
        "value": 1,
        "label": "Active"
      },
      "device_role": {
        "url": "/api/dcim/device-roles/4/",
        "id": 4,
        "name": "Access Switch",
        "slug": "access-switch"
      },
      "primary_ip": null,
      "tags": [],
      "vc_priority": null,
      "parent_device": null,
      "primary_ip4": null,
      "primary_ip6": null,
      "tenant": null,
      "virtual_chassis": null,
      "name": "test",
      "created": "2019-03-09",
      "face": {
        "value": 0,
        "label": "Front"
      },
      "vc_position": null,
      "position": null,
      "rack": {
        "url": "/api/dcim/racks/3/",
        "display_name": "test1",
        "id": 3,
        "name": "test1"
      }
    },
    "event": "deleted"
  }
}

{
  "status": "processed",
  "occurrence_time": "2019-03-09T18:29:27.000000Z",
  "trigger": "netbox.webhook.object_deleted",
  "id": "5c844c5755fdfa02b51f03c2",
  "payload": {
    "timestamp": "2019-03-09 23:29:27.608366",
    "model": "interface",
    "data": {
      "connected_endpoint_type": null,
      "connection_status": null,
      "description": "",
      "cable": null,
      "tagged_vlans": [],
      "name": "eth0",
      "lag": null,
      "enabled": true,
      "untagged_vlan": null,
      "mtu": null,
      "mac_address": null,
      "mode": null,
      "connected_endpoint": null,
      "form_factor": {
        "value": 1000,
        "label": "1000BASE-T (1GE)"
      },
      "device": null,
      "count_ipaddresses": 0,
      "id": 28,
      "tags": [],
      "mgmt_only": true
    },
    "event": "deleted"
  }
}

Originally created by @luis-n4489 on GitHub (Mar 13, 2019). Originally assigned to: @lampwins on GitHub. <!-- NOTE: This form is only for reproducible bugs. If you need assistance with NetBox installation, or if you have a general question, DO NOT open an issue. Instead, post to our mailing list: https://groups.google.com/forum/#!forum/netbox-discuss Please describe the environment in which you are running NetBox. Be sure that you are running an unmodified instance of the latest stable release before submitting a bug report. --> ### Environment * Python version: v3.6.7 * NetBox version: v2.5.6 <!-- Describe in detail the exact steps that someone else can take to reproduce this bug using the current stable release of NetBox (or the current beta release where applicable). Begin with the creation of any necessary database objects and call out every operation being performed explicitly. If reporting a bug in the REST API, be sure to reconstruct the raw HTTP request(s) being made: Don't rely on a wrapper like pynetbox. --> ### Steps to Reproduce 1. Create a device test1 with interface eth0 2. connect test1 interface eth0 to "switch" port in netbox 3. delete test1 device. <!-- What did you expect to happen? --> ### Expected Behavior - deletion webhook for children should be invoked *before* deletion webhook for parents - deletion webhook for children should include the parent reference <!-- What happened instead? --> ### Observed Behavior ``` { "status": "processed", "occurrence_time": "2019-03-09T18:29:27.000000Z", "trigger": "netbox.webhook.object_deleted", "id": "5c844c5755fdfa02b51f03c0", "payload": { "timestamp": "2019-03-09 23:29:27.546951", "model": "device", "data": { "last_updated": "2019-03-09T23:29:09.980034Z", "site": { "url": "/api/dcim/sites/1/", "id": 1, "name": "Nap", "slug": "nap" }, "asset_tag": null, "cluster": null, "device_type": { "display_name": "APC AP8841", "url": "/api/dcim/device-types/2/", "id": 2, "model": "AP8841", "slug": "ap8841", "manufacturer": { "url": "/api/dcim/manufacturers/1/", "id": 1, "slug": "apc", "name": "APC" } }, "serial": "12345", "id": 20, "custom_fields": { "Environment": null, "SnipeITID": null, "Monitor": null, "coordinates": null }, "display_name": "test", "local_context_data": null, "comments": "", "platform": null, "status": { "value": 1, "label": "Active" }, "device_role": { "url": "/api/dcim/device-roles/4/", "id": 4, "name": "Access Switch", "slug": "access-switch" }, "primary_ip": null, "tags": [], "vc_priority": null, "parent_device": null, "primary_ip4": null, "primary_ip6": null, "tenant": null, "virtual_chassis": null, "name": "test", "created": "2019-03-09", "face": { "value": 0, "label": "Front" }, "vc_position": null, "position": null, "rack": { "url": "/api/dcim/racks/3/", "display_name": "test1", "id": 3, "name": "test1" } }, "event": "deleted" } } { "status": "processed", "occurrence_time": "2019-03-09T18:29:27.000000Z", "trigger": "netbox.webhook.object_deleted", "id": "5c844c5755fdfa02b51f03c2", "payload": { "timestamp": "2019-03-09 23:29:27.608366", "model": "interface", "data": { "connected_endpoint_type": null, "connection_status": null, "description": "", "cable": null, "tagged_vlans": [], "name": "eth0", "lag": null, "enabled": true, "untagged_vlan": null, "mtu": null, "mac_address": null, "mode": null, "connected_endpoint": null, "form_factor": { "value": 1000, "label": "1000BASE-T (1GE)" }, "device": null, "count_ipaddresses": 0, "id": 28, "tags": [], "mgmt_only": true }, "event": "deleted" } } ```
adam added the type: bug label 2025-12-29 18:19:02 +01:00
adam closed this issue 2025-12-29 18:19:02 +01:00
Author
Owner

@luis-n4489 commented on GitHub (Mar 13, 2019):

Will need to also test to find out if the data from the webhook trigger gives me the "disconnected" port on said switch, and which switch

@luis-n4489 commented on GitHub (Mar 13, 2019): Will need to also test to find out if the data from the webhook trigger gives me the "disconnected" port on said switch, and which switch
Author
Owner

@luis-n4489 commented on GitHub (Mar 13, 2019):

Possible that there is a bug with webhooks sending double data as well

I connected an interface and get 4 payloads sent. 2 x server -> switch, and 2 x switch -> server


{
  "status": "processed",
  "occurrence_time": "2019-03-13T12:26:58.000000Z",
  "trigger": "netbox.webhook.object_updated",
  "id": "5c892f5255fdfa043a6a5609",
  "payload": {
    "timestamp": "2019-03-13 16:26:58.648520",
    "model": "interface",
    "data": {
      "connected_endpoint_type": "dcim.interface",
      "connection_status": {
        "value": true,
        "label": "Connected"
      },
      "description": "",
      "cable": {
        "url": "/api/dcim/cables/13/",
        "id": 13,
        "label": ""
      },
      "tagged_vlans": [],
      "name": "ge-0/0/1",
      "lag": null,
      "enabled": true,
      "untagged_vlan": null,
      "mtu": null,
      "mac_address": null,
      "mode": null,
      "connected_endpoint": {
        "connection_status": {
          "value": true,
          "label": "Connected"
        },
        "name": "eth0",
        "cable": 13,
        "url": "/api/dcim/interfaces/31/",
        "device": {
          "url": "/api/dcim/devices/7/",
          "display_name": "test1",
          "id": 7,
          "name": "test1"
        },
        "id": 31
      },
      "form_factor": {
        "value": 1000,
        "label": "1000BASE-T (1GE)"
      },
      "device": {
        "url": "/api/dcim/devices/22/",
        "display_name": "switch1",
        "id": 22,
        "name": "switch1"
      },
      "count_ipaddresses": 0,
      "id": 30,
      "tags": [],
      "mgmt_only": false
    },
    "event": "updated"
  }
}

And

Back

{
  "status": "processed",
  "occurrence_time": "2019-03-13T12:26:59.000000Z",
  "trigger": "netbox.webhook.object_updated",
  "id": "5c892f5355fdfa043a6a560f",
  "payload": {
    "timestamp": "2019-03-13 16:26:58.942463",
    "model": "interface",
    "data": {
      "connected_endpoint_type": "dcim.interface",
      "connection_status": {
        "value": true,
        "label": "Connected"
      },
      "description": "",
      "cable": {
        "url": "/api/dcim/cables/13/",
        "id": 13,
        "label": ""
      },
      "tagged_vlans": [],
      "name": "ge-0/0/1",
      "lag": null,
      "enabled": true,
      "untagged_vlan": null,
      "mtu": null,
      "mac_address": null,
      "mode": null,
      "connected_endpoint": {
        "connection_status": {
          "value": true,
          "label": "Connected"
        },
        "name": "eth0",
        "cable": 13,
        "url": "/api/dcim/interfaces/31/",
        "device": {
          "url": "/api/dcim/devices/7/",
          "display_name": "test1",
          "id": 7,
          "name": "test1"
        },
        "id": 31
      },
      "form_factor": {
        "value": 1000,
        "label": "1000BASE-T (1GE)"
      },
      "device": {
        "url": "/api/dcim/devices/22/",
        "display_name": "switch1",
        "id": 22,
        "name": "switch1"
      },
      "count_ipaddresses": 0,
      "id": 30,
      "tags": [],
      "mgmt_only": false
    },
    "event": "updated"
  }
}
@luis-n4489 commented on GitHub (Mar 13, 2019): Possible that there is a bug with webhooks sending double data as well I connected an interface and get 4 payloads sent. 2 x server -> switch, and 2 x switch -> server ``` { "status": "processed", "occurrence_time": "2019-03-13T12:26:58.000000Z", "trigger": "netbox.webhook.object_updated", "id": "5c892f5255fdfa043a6a5609", "payload": { "timestamp": "2019-03-13 16:26:58.648520", "model": "interface", "data": { "connected_endpoint_type": "dcim.interface", "connection_status": { "value": true, "label": "Connected" }, "description": "", "cable": { "url": "/api/dcim/cables/13/", "id": 13, "label": "" }, "tagged_vlans": [], "name": "ge-0/0/1", "lag": null, "enabled": true, "untagged_vlan": null, "mtu": null, "mac_address": null, "mode": null, "connected_endpoint": { "connection_status": { "value": true, "label": "Connected" }, "name": "eth0", "cable": 13, "url": "/api/dcim/interfaces/31/", "device": { "url": "/api/dcim/devices/7/", "display_name": "test1", "id": 7, "name": "test1" }, "id": 31 }, "form_factor": { "value": 1000, "label": "1000BASE-T (1GE)" }, "device": { "url": "/api/dcim/devices/22/", "display_name": "switch1", "id": 22, "name": "switch1" }, "count_ipaddresses": 0, "id": 30, "tags": [], "mgmt_only": false }, "event": "updated" } } ``` And ``` Back { "status": "processed", "occurrence_time": "2019-03-13T12:26:59.000000Z", "trigger": "netbox.webhook.object_updated", "id": "5c892f5355fdfa043a6a560f", "payload": { "timestamp": "2019-03-13 16:26:58.942463", "model": "interface", "data": { "connected_endpoint_type": "dcim.interface", "connection_status": { "value": true, "label": "Connected" }, "description": "", "cable": { "url": "/api/dcim/cables/13/", "id": 13, "label": "" }, "tagged_vlans": [], "name": "ge-0/0/1", "lag": null, "enabled": true, "untagged_vlan": null, "mtu": null, "mac_address": null, "mode": null, "connected_endpoint": { "connection_status": { "value": true, "label": "Connected" }, "name": "eth0", "cable": 13, "url": "/api/dcim/interfaces/31/", "device": { "url": "/api/dcim/devices/7/", "display_name": "test1", "id": 7, "name": "test1" }, "id": 31 }, "form_factor": { "value": 1000, "label": "1000BASE-T (1GE)" }, "device": { "url": "/api/dcim/devices/22/", "display_name": "switch1", "id": 22, "name": "switch1" }, "count_ipaddresses": 0, "id": 30, "tags": [], "mgmt_only": false }, "event": "updated" } } ```
Author
Owner

@luis-n4489 commented on GitHub (Mar 21, 2019):

Any update on this?

@luis-n4489 commented on GitHub (Mar 21, 2019): Any update on this?
Author
Owner

@lampwins commented on GitHub (Mar 24, 2019):

This is tricky because of the way in which we use django signals to handle the event routing. Delete events make use of the post_delete signal which is fired after the object is actually deleted from the DB. This is significant because the relation from the child to the parent is a foreign key. After the parent model instance is deleted, that foreign key from the child no longer resolves and thus the serialized representation is null.

Django offers a pre_delete signal, however, it is unattractive because a DB constraint can cause an object to to not actually be deleted after the pre_delete has been called.

deletion webhook for children should be invoked before deletion webhook for parents

We can't do this in the current implementation because webhooks are enqueued at the end of the request after all DB operations are complete. Furthermore, in most cases (including the example provided), the child relations are implemented via a foreign key with a cascade delete. This means the child will always be deleted after the parent, at the DB level.

All that said, we do have the ability to replace the nested serialized related object with the pk of the relation. This is exactly how the changelog representations look. So if the relation is missing, we can fall back to providing the object pk. @chelapa would this suffice?

@lampwins commented on GitHub (Mar 24, 2019): This is tricky because of the way in which we use django signals to handle the event routing. Delete events make use of the `post_delete` signal which is fired _after_ the object is actually deleted from the DB. This is significant because the relation from the child to the parent is a foreign key. After the parent model instance is deleted, that foreign key from the child no longer resolves and thus the serialized representation is null. Django offers a `pre_delete` signal, however, it is unattractive because a DB constraint can cause an object to to not actually be deleted after the `pre_delete` has been called. > deletion webhook for children should be invoked before deletion webhook for parents We can't do this in the current implementation because webhooks are enqueued at the end of the request after all DB operations are complete. Furthermore, in most cases (including the example provided), the child relations are implemented via a foreign key with a cascade delete. This means the child will always be deleted after the parent, at the DB level. All that said, we do have the ability to replace the nested serialized related object with the `pk` of the relation. This is exactly how the changelog representations look. So if the relation is missing, we can fall back to providing the object `pk`. @chelapa would this suffice?
Author
Owner

@luis-n4489 commented on GitHub (Mar 24, 2019):

anything to reference the parent from the child can work, but has to be viewable from webhook.

Sent from my iPhone

On Mar 24, 2019, at 3:04 PM, John Anderson notifications@github.com wrote:

This is tricky because of the way in which we use django signals to handle the event routing. Delete events make use of the post_delete signal which is fired after the object is actually deleted from the DB. This is significant because the relation from the child to the parent is a foreign key. After the parent model instance is deleted, that foreign key from the child no longer resolves and thus the serialized representation is null.

Django offers a pre_delete signal, however, it is unattractive because a DB constraint can cause an object to to not actually be deleted after the pre_delete has been called.

deletion webhook for children should be invoked before deletion webhook for parents
We can't do this in the current implementation because webhooks are enqueued at the end of the request after all DB operations are complete. Furthermore, in most cases (including the example provided), the child relations are implemented via a foreign key with a cascade delete. This means the child will always be deleted after the parent, at the DB level.

All that said, we do have the ability to replace the nested serialized related object with the pk of the relation. This is exactly how the changelog representations look. So if the relation is missing, we can fall back to providing the object pk. @chelapa would this suffice?


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.

@luis-n4489 commented on GitHub (Mar 24, 2019): anything to reference the parent from the child can work, but has to be viewable from webhook. Sent from my iPhone > On Mar 24, 2019, at 3:04 PM, John Anderson <notifications@github.com> wrote: > > This is tricky because of the way in which we use django signals to handle the event routing. Delete events make use of the post_delete signal which is fired after the object is actually deleted from the DB. This is significant because the relation from the child to the parent is a foreign key. After the parent model instance is deleted, that foreign key from the child no longer resolves and thus the serialized representation is null. > > Django offers a pre_delete signal, however, it is unattractive because a DB constraint can cause an object to to not actually be deleted after the pre_delete has been called. > > deletion webhook for children should be invoked before deletion webhook for parents > We can't do this in the current implementation because webhooks are enqueued at the end of the request after all DB operations are complete. Furthermore, in most cases (including the example provided), the child relations are implemented via a foreign key with a cascade delete. This means the child will always be deleted after the parent, at the DB level. > > All that said, we do have the ability to replace the nested serialized related object with the pk of the relation. This is exactly how the changelog representations look. So if the relation is missing, we can fall back to providing the object pk. @chelapa would this suffice? > > — > You are receiving this because you were mentioned. > Reply to this email directly, view it on GitHub, or mute the thread.
Author
Owner

@jeremystretch commented on GitHub (Oct 23, 2019):

Tagging this as potentially addressed by #3632

@jeremystretch commented on GitHub (Oct 23, 2019): Tagging this as potentially addressed by #3632
Author
Owner

@jeremystretch commented on GitHub (Oct 25, 2019):

Marking this as blocked pending testing of the changes to the middleware merged in #3632

@jeremystretch commented on GitHub (Oct 25, 2019): Marking this as blocked pending testing of the changes to the middleware merged in #3632
Author
Owner

@jeremystretch commented on GitHub (Dec 9, 2019):

I believe this was resolved in v2.6.7 by #3632. Please ask to re-open if you experience this on a recent release.

@jeremystretch commented on GitHub (Dec 9, 2019): I _believe_ this was resolved in v2.6.7 by #3632. Please ask to re-open if you experience this on a recent release.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#2460