OpenAPI Specification Does Not Allow Numeric IDs for Related Objects, Contrary to Documentation #10336

Closed
opened 2025-12-29 21:30:12 +01:00 by adam · 6 comments
Owner

Originally created by @zunkree on GitHub (Oct 9, 2024).

Originally assigned to: @mraerino on GitHub.

Deployment Type

Self-hosted

NetBox Version

v4.1.3

Python Version

3.12

Steps to Reproduce

  1. Access the NetBox REST API documentation generated from the OpenAPI specification (e.g., /api/schema/swagger-ui/).

  2. Navigate to the API endpoint for creating a new device (POST /api/dcim/devices/).

  3. Review the schema for the request body in the OpenAPI specification.

  4. Observe that foreign key fields, such as device_role, device_type, site, etc., are defined as requiring nested objects with specific attributes.

  5. Attempt to create a new device by specifying related objects using numeric IDs in the request body:

{
    "device_type": 1,
    "role": 2,
    "site": 3,
}
  1. Note that according to the OpenAPI schema, this request does not conform to the expected input format.

Expected Behavior

According to the NetBox documentation under the "Related Objects" section:

  1. When performing write API actions (POST, PUT, and PATCH), related objects may be specified by either numeric ID (primary key) or by a set of attributes sufficiently unique to return the desired object.

  2. For example, creating a new device by specifying its rack using a numeric ID should be acceptable:

{
    "device_type": 1,
    "role": 2,
    "site": 3,
}

The OpenAPI specification should reflect this flexibility, allowing foreign key fields to accept either a numeric ID or a nested object with unique attributes.

Client code generated from the OpenAPI schema should support specifying related objects using numeric IDs, resulting in concise and manageable code, especially in statically typed languages.

Observed Behavior

  • The OpenAPI specification only allows for specifying related objects as nested objects with specific attributes and does not provide the option to use numeric IDs.

  • Client code generated from the OpenAPI schema enforces the use of verbose nested objects for related fields, leading to cumbersome and less maintainable code.

  • This discrepancy between the documentation and the OpenAPI specification creates confusion and hinders the development of client applications, particularly in statically typed languages like Go.

  • For example, in Go, creating a device requires constructing nested objects for each related field:

client.DcimAPI.DcimDevicesCreate(context.Background()).WritableDeviceWithConfigContextRequest(
	netbox.WritableDeviceWithConfigContextRequest{
		DeviceType: *netbox.NewBriefDeviceTypeRequest(
			*netbox.NewBriefManufacturerRequest(typeMikrotik.Manufacturer.Name, typeMikrotik.Manufacturer.Slug),
			typeMikrotik.Model,
			typeMikrotik.Slug,
		),
		Role: *netbox.NewBriefDeviceRoleRequest(roleRouter.Name, roleRouter.Slug),
		Site: *netbox.NewBriefSiteRequest(site.Name, site.Slug),
	}).Execute()
  • If the OpenAPI specification allowed for numeric IDs, the code would be much simpler:
client.DcimApi.DcimDevicesCreate(context.Background()).WritableDeviceWithConfigContextRequest(
    netbox.WritableDeviceWithConfigContextRequest{
        DeviceType: 1,
        Role:       2,
        Site:       3,
    },
).Execute()
Originally created by @zunkree on GitHub (Oct 9, 2024). Originally assigned to: @mraerino on GitHub. ### Deployment Type Self-hosted ### NetBox Version v4.1.3 ### Python Version 3.12 ### Steps to Reproduce 1. Access the NetBox REST API documentation generated from the OpenAPI specification (e.g., `/api/schema/swagger-ui/`). 2. Navigate to the API endpoint for creating a new device (`POST /api/dcim/devices/`). 3. Review the schema for the request body in the OpenAPI specification. 4. Observe that foreign key fields, such as `device_role`, `device_type`, `site`, etc., are defined as requiring nested objects with specific attributes. 5. Attempt to create a new device by specifying related objects using numeric IDs in the request body: ```json { "device_type": 1, "role": 2, "site": 3, } ``` 6. Note that according to the OpenAPI schema, this request does not conform to the expected input format. ### Expected Behavior According to the NetBox documentation under the "Related Objects" section: 1. When performing write API actions (POST, PUT, and PATCH), related objects may be specified by either numeric ID (primary key) or by a set of attributes sufficiently unique to return the desired object. 2. For example, creating a new device by specifying its rack using a numeric ID should be acceptable: ```json { "device_type": 1, "role": 2, "site": 3, } ``` The OpenAPI specification should reflect this flexibility, allowing foreign key fields to accept either a numeric ID or a nested object with unique attributes. Client code generated from the OpenAPI schema should support specifying related objects using numeric IDs, resulting in concise and manageable code, especially in statically typed languages. ### Observed Behavior - The OpenAPI specification only allows for specifying related objects as nested objects with specific attributes and does not provide the option to use numeric IDs. - Client code generated from the OpenAPI schema enforces the use of verbose nested objects for related fields, leading to cumbersome and less maintainable code. - This discrepancy between the documentation and the OpenAPI specification creates confusion and hinders the development of client applications, particularly in statically typed languages like Go. - For example, in Go, creating a device requires constructing nested objects for each related field: ```go client.DcimAPI.DcimDevicesCreate(context.Background()).WritableDeviceWithConfigContextRequest( netbox.WritableDeviceWithConfigContextRequest{ DeviceType: *netbox.NewBriefDeviceTypeRequest( *netbox.NewBriefManufacturerRequest(typeMikrotik.Manufacturer.Name, typeMikrotik.Manufacturer.Slug), typeMikrotik.Model, typeMikrotik.Slug, ), Role: *netbox.NewBriefDeviceRoleRequest(roleRouter.Name, roleRouter.Slug), Site: *netbox.NewBriefSiteRequest(site.Name, site.Slug), }).Execute() ``` - If the OpenAPI specification allowed for numeric IDs, the code would be much simpler: ```go client.DcimApi.DcimDevicesCreate(context.Background()).WritableDeviceWithConfigContextRequest( netbox.WritableDeviceWithConfigContextRequest{ DeviceType: 1, Role: 2, Site: 3, }, ).Execute() ```
adam added the type: bugstatus: acceptednetboxseverity: low labels 2025-12-29 21:30:12 +01:00
adam closed this issue 2025-12-29 21:30:12 +01:00
Author
Owner

@jqueuniet commented on GitHub (Nov 12, 2024):

Aside from the issue of code complexity, this is an even bigger problem for object references that do not have a unique name, ie IPAddress can have duplicated address properties, but the BriefIPAddressRequest object only provides the address field as reference key.

type BriefIPAddressRequest struct {
	Address string `json:"address"`
	Description *string `json:"description,omitempty"`
	AdditionalProperties map[string]interface{}
}
@jqueuniet commented on GitHub (Nov 12, 2024): Aside from the issue of code complexity, this is an even bigger problem for object references that do not have a unique name, ie `IPAddress` can have duplicated `address` properties, but the `BriefIPAddressRequest` object only provides the `address` field as reference key. ```go type BriefIPAddressRequest struct { Address string `json:"address"` Description *string `json:"description,omitempty"` AdditionalProperties map[string]interface{} } ```
Author
Owner

@hikhvar commented on GitHub (Jan 21, 2025):

We have the same issue here. We have non-unique racknames and locations accross our sides. Currently, we can't migrate to netbox v4.0 as this breaks a lot of our data import code. What is more, why does the spec require both the name and the slug, where as the slug should be unique by design.

@hikhvar commented on GitHub (Jan 21, 2025): We have the same issue here. We have non-unique racknames and locations accross our sides. Currently, we can't migrate to netbox v4.0 as this breaks a lot of our data import code. What is more, why does the spec require both the name and the slug, where as the slug should be unique by design.
Author
Owner

@hikhvar commented on GitHub (Jan 21, 2025):

I digged a bit into the past pull requests. I think this issue was introduced around this issue and the related pull requests https://github.com/netbox-community/netbox/issues/16670

@hikhvar commented on GitHub (Jan 21, 2025): I digged a bit into the past pull requests. I think this issue was introduced around this issue and the related pull requests https://github.com/netbox-community/netbox/issues/16670
Author
Owner

@mraerino commented on GitHub (Jan 21, 2025):

I volunteer to own this issue

@mraerino commented on GitHub (Jan 21, 2025): I volunteer to own this issue
Author
Owner

@mraerino commented on GitHub (Jan 22, 2025):

this is my proposed fix: https://github.com/netbox-community/netbox/pull/18451

@mraerino commented on GitHub (Jan 22, 2025): this is my proposed fix: https://github.com/netbox-community/netbox/pull/18451
Author
Owner

@deliciouslytyped commented on GitHub (Feb 16, 2025):

Is this the same issues as Racks not having a slug field or is that unrelated?

@deliciouslytyped commented on GitHub (Feb 16, 2025): Is this the same issues as Racks not having a slug field or is that unrelated?
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#10336