netbox-community / netbox

The premier source of truth powering network automation. Open source under Apache 2. Try NetBox Cloud free: https://netboxlabs.com/free-netbox-cloud/
http://netboxlabs.com/oss/netbox/
Apache License 2.0
16.22k stars 2.59k forks source link

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

Open zunkree opened 1 month ago

zunkree commented 1 month ago

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

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()
client.DcimApi.DcimDevicesCreate(context.Background()).WritableDeviceWithConfigContextRequest(
    netbox.WritableDeviceWithConfigContextRequest{
        DeviceType: 1,
        Role:       2,
        Site:       3,
    },
).Execute()
jqueuniet commented 2 days ago

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{}
}