netbox-community / go-netbox

The official Go API client for Netbox IPAM and DCIM service.
Other
197 stars 150 forks source link

netbox-comounity/devicetype-library structure varies from that of go-netbox? #168

Closed jacobsalmela closed 8 months ago

jacobsalmela commented 8 months ago

If I try to use go-netbox to import any of the devicetypes defined here, it cannot unmarshal them

For example, on a dell switch, manufacturer: Dell is a string, but in go-netbox, the manufacturer is a NestedManufacturer, not a simple string.

yaml: unmarshal errors:
  line 2: cannot unmarshal !!str `Dell` into netbox.NestedManufacturer
exit status 1

Which is correct? Or am I doing something incorrectly?

Here is some sample code where I see the issue:

package main

import (
    "bytes"
    "fmt"
    "os"

    "github.com/netbox-community/go-netbox/v3"
    "gopkg.in/yaml.v3"
)

type MyType struct {
    netbox.DeviceType `yaml:",inline"`
    Custom            MyCustomThing `yaml:"my-custom-thing"`
}

type MyCustomThing string

func main() {
    // load yaml file
    f, err := os.ReadFile("../devicetype-library/device-types/Dell/PowerSwitch-S4048-ON.yaml")
    if err != nil {
        fmt.Printf("%+v\n", err)
        os.Exit(1)
    }
    r := bytes.NewReader(f)
    decoder := yaml.NewDecoder(r)
    mytype := MyType{}
    err = decoder.Decode(&mytype)
    if err != nil {
        fmt.Printf("%+v\n", err)
        os.Exit(1)
    }
    fmt.Printf("%+v\n", mytype.Manufacturer)
}
jqueuniet commented 8 months ago

This client only aims for compatibility with the Netbox API, defined by the Netbox OpenAPI specification. The device type library uses its own data structures defined by its own schemas (see https://github.com/netbox-community/devicetype-library/blob/master/schema/devicetype.json ). You will likely have to create your own unmarshalling logic, maybe using the provided schema, if you plan on using the device type library with Go.

For reference, here is a device type as returned by the Netbox API, where you can see manufacturers as nested objects instead of strings.

{
    "airflow": null,
    "comments": "",
    "created": "2023-10-26T13:28:11.259335Z",
    "custom_fields": {},
    "description": "",
    "device_count": 0,
    "display": "S5232F-ON",
    "front_image": "https://netbox/media/devicetype-images/S5232F-ON.png",
    "id": 41,
    "is_full_depth": true,
    "last_updated": "2023-10-26T13:28:11.259384Z",
    "manufacturer": {
        "display": "Dell",
        "id": 2,
        "name": "Dell",
        "slug": "dell",
        "url": "https://netbox/api/dcim/manufacturers/2/"
    },
    "model": "S5232F-ON",
    "part_number": "",
    "rear_image": null,
    "slug": "s5232f-on",
    "subdevice_role": null,
    "tags": [],
    "u_height": 1.0,
    "url": "https://netbox/api/dcim/device-types/41/",
    "weight": null,
    "weight_unit": null
}
jacobsalmela commented 8 months ago

Why do the two differ? It seems like the API and the device-types should align for easy importing.

https://github.com/netbox-community/Device-Type-Library-Import reads those yaml files and imports them into netbox. I haven't looked closely but maybe it also is doing its own translation?

Thank you for the response @jqueuniet. I'm relatively new to netbox and we are using it for a large project so I appreciate learning as much as I can on this subject.

jqueuniet commented 8 months ago

The Netbox API advances at its own pace, is not formally versioned and can break from one minor release to the other. Using a separate format for data storage is likely to be more stable in the long run. Handling a translation layer in code allows to adapt to various Netbox versions and avoids changing all data files at each Netbox minor release.

jacobsalmela commented 8 months ago

Thank you. For now, I will work on my own translation/unmarshaller.