netbox icon indicating copy to clipboard operation
netbox copied to clipboard

Integrate NetBox UI with plugins catalog

Open jeremystretch opened this issue 1 year ago • 7 comments

NetBox version

v3.7.0

Feature type

New functionality

Proposed functionality

Provide an interface for users to compare their installed plugins against the public database, and potentially to discover new plugins

Use case

Providing a single interface where NetBox administrators can compare the installed version of each plugin to the latest available greatly simplifies the task of keeping plugins up-to-date.

Database changes

This can probably be done without introducing any new models, as plugin details live in memory. Some caching may be needed.

External dependencies

TBD, but no new dependencies are expected.

jeremystretch avatar Jan 08 '24 14:01 jeremystretch

Blocked by #14728. We'll also likely need to build out a full API for the plugins database to support this.

jeremystretch avatar Jan 08 '24 14:01 jeremystretch

Could this be done on client side? In our case (and I'm sure it's the same for many others), the Netbox infrastructure does not have access to internet...

AnythingOverIP avatar Jan 08 '24 16:01 AnythingOverIP

For this to work properly (and for plugin authors to know how to make sure the information in the plugin database is correct) it would really be helpful to have some documentation on how the database is created. Additionally, the database needs to be kept in a more current state if it's supposed to be useful.

Example: In the case of NetBox DNS (netbox-plugin-dns), the last version according to the database is 0.18.2, which is almost 9 months old, and the development status is "unknown". The current version is 0.22.1, which was released last week, and the development status is, as far as I'm concerned, "supported" ... on the other hand, the old netbox-dns is still in there, whose status is definitely "abandoned" (the last commit is almost a year old, and there will be no new ones, as the project was forked by me due to the sudden demise of its former maintainers).

peteeckel avatar Feb 06 '24 08:02 peteeckel

Details of the public plugin catalog endpoint URL: https://api.netbox.oss.netboxlabs.com//v1/plugins Allowed methods: GET Allowed query parameters:

  • page: Page number to fetch
  • per_page: Number of entries per page

At the time of this comment, it appears the endpoint expects an authentication token, which I assume will be removed soon.

Here is a sample of the endpoint's output.

{
  "metadata": {
    "duration": 1,
    "pagination": {
      "current_page": 1,
      "first_page": true,
      "last_page": true,
      "page_size": 50,
      "total_items": 2,
      "total_pages": 1
    }
  },
  "data": [
    {
      "id": "77525ee1-838e-4b99-9d0a-ff3d891a9049",
      "status": "active",
      "title_short": "Netbox plugin for BGP related objects documentation.",
      "title_long": "Model & manage BGP related resources like communities, sessions, routing policies, and IP prefix lists",
      "tag_line": "BGP related objects",
      "description_short": "Netbox plugin for BGP related objects documentation.",
      "slug": "netbox-bgp",
      "author": {
        "name": "Nikolay Yuzefovich",
        "org_id": "org-00000000",
        "url": "https://github.com/netbox-community/netbox-bgp"
      },
      "created_at": "2023-10-24T22:24:59.244147Z",
      "updated_at": "2024-04-17T17:55:16.837377Z",
      "license_type": "Apache 2.0",
      "homepage_url": "https://github.com/netbox-community/netbox-bgp",
      "package_name_pypi": "netbox-bgp",
      "config_name": "netbox_bgp",
      "is_certified": false,
      "release_count": 2,
      "release_latest": {
        "date": "2024-02-26T19:46:31.962084Z",
        "version": "0.12.1",
        "netbox_min_version": "3.7.3",
        "netbox_max_version": "3.7.8",
        "has_model": true,
        "is_certified": true,
        "is_feature": false,
        "is_integration": false,
        "is_netboxlabs_supported": true
      },
      "release_recent_history": [
        {
          "date": "2024-02-26T19:46:31.962084Z",
          "version": "0.12.1",
          "netbox_min_version": "3.7.3",
          "netbox_max_version": "3.7.8",
          "has_model": true,
          "is_certified": true,
          "is_feature": false,
          "is_integration": false,
          "is_netboxlabs_supported": true
        },
        {
          "date": "2024-01-18T15:15:03.870601Z",
          "version": "0.12.0",
          "netbox_min_version": "3.7.0",
          "netbox_max_version": "3.7.2",
          "has_model": true,
          "is_certified": false,
          "is_feature": false,
          "is_integration": false,
          "is_netboxlabs_supported": true
        }
      ]
    },
    {
      "id": "4c107c65-59d8-4197-9a26-9eb2a29a742a",
      "status": "active",
      "title_short": "Automatically discover your network with Slurp’it",
      "title_long": "Automatically discover your network with Slurp’it",
      "tag_line": "Automatically discover your network with Slurp’it",
      "description_short": "Automatically discover your network with Slurp’it",
      "slug": "slurpit_netbox",
      "author": {
        "name": "Pieter van Os",
        "org_id": "org-00000000",
        "url": "https://gitlab.com/slurpit.io/slurpit-netbox"
      },
      "created_at": "2024-01-31T15:31:37.247368Z",
      "updated_at": "2024-04-19T14:23:33.598421Z",
      "license_type": "MIT",
      "homepage_url": "https://gitlab.com/slurpit.io/slurpit-netbox",
      "package_name_pypi": "slurpit_netbox",
      "config_name": "slurpit_netbox",
      "is_certified": true,
      "release_count": 1,
      "release_latest": {
        "date": "2024-04-18T12:15:52.308399Z",
        "version": "0.8.117",
        "netbox_min_version": "3.7.5",
        "netbox_max_version": "3.7.8",
        "has_model": true,
        "is_certified": true,
        "is_feature": false,
        "is_integration": true,
        "is_netboxlabs_supported": false
      },
      "release_recent_history": [
        {
          "date": "2024-04-18T12:15:52.308399Z",
          "version": "0.8.117",
          "netbox_min_version": "3.7.5",
          "netbox_max_version": "3.7.8",
          "has_model": true,
          "is_certified": true,
          "is_feature": false,
          "is_integration": true,
          "is_netboxlabs_supported": false
        }
      ]
    }
  ]
}

jeffgdotorg avatar May 14 '24 22:05 jeffgdotorg

~~Roughed-out~~ Proper pydantic-generated json-schema description for this endpoint:

{
  "$defs": {
    "Author": {
      "description": "Author model.",
      "properties": {
        "name": {
          "description": "Name",
          "title": "Name",
          "type": "string"
        },
        "org_id": {
          "description": "Organization ID",
          "title": "Org Id",
          "type": "string"
        },
        "url": {
          "description": "Author URL",
          "format": "uri",
          "minLength": 1,
          "title": "Url",
          "type": "string"
        }
      },
      "required": [
        "name",
        "org_id",
        "url"
      ],
      "title": "Author",
      "type": "object"
    },
    "LicenseType": {
      "description": "License type model.",
      "enum": [
        "No license",
        "MIT",
        "Apache 2.0",
        "BSD-3-Clause",
        "BSD-2-Clause",
        "CDDL-1.0",
        "LGPLv3",
        "GPLv3",
        "MPL-2.0",
        "EPL-2.0"
      ],
      "title": "LicenseType",
      "type": "string"
    },
    "Metadata": {
      "description": "Metadata model.",
      "properties": {
        "duration": {
          "default": 0,
          "description": "Duration",
          "title": "Duration",
          "type": "integer"
        },
        "pagination": {
          "allOf": [
            {
              "$ref": "#/$defs/Pagination"
            }
          ],
          "description": "Pagination object"
        }
      },
      "required": [
        "pagination"
      ],
      "title": "Metadata",
      "type": "object"
    },
    "Pagination": {
      "description": "Pagination model.",
      "properties": {
        "current_page": {
          "default": 1,
          "description": "Current page",
          "title": "Current Page",
          "type": "integer"
        },
        "first_page": {
          "description": "First page",
          "title": "First Page",
          "type": "boolean"
        },
        "last_page": {
          "description": "Last page",
          "title": "Last Page",
          "type": "boolean"
        },
        "page_size": {
          "description": "Page size",
          "title": "Page Size",
          "type": "integer"
        },
        "total_items": {
          "default": 0,
          "description": "Total items",
          "title": "Total Items",
          "type": "integer"
        },
        "total_pages": {
          "default": 0,
          "description": "Total pages",
          "title": "Total Pages",
          "type": "integer"
        }
      },
      "required": [
        "first_page",
        "last_page",
        "page_size"
      ],
      "title": "Pagination",
      "type": "object"
    },
    "Plugin": {
      "description": "Plugin model.",
      "properties": {
        "id": {
          "description": "Plugin ID",
          "format": "uuid4",
          "title": "Id",
          "type": "string"
        },
        "status": {
          "allOf": [
            {
              "$ref": "#/$defs/PluginStatus"
            }
          ],
          "description": "Plugin status"
        },
        "title_short": {
          "description": "Short title",
          "title": "Title Short",
          "type": "string"
        },
        "title_long": {
          "description": "Long title",
          "title": "Title Long",
          "type": "string"
        },
        "tag_line": {
          "description": "Tag line",
          "title": "Tag Line",
          "type": "string"
        },
        "description_short": {
          "description": "Short description",
          "title": "Description Short",
          "type": "string"
        },
        "slug": {
          "description": "Slug",
          "title": "Slug",
          "type": "string"
        },
        "author": {
          "allOf": [
            {
              "$ref": "#/$defs/Author"
            }
          ],
          "description": "Author"
        },
        "created_at": {
          "description": "Created at",
          "format": "date-time",
          "title": "Created At",
          "type": "string"
        },
        "updated_at": {
          "description": "Updated at",
          "format": "date-time",
          "title": "Updated At",
          "type": "string"
        },
        "license_type": {
          "allOf": [
            {
              "$ref": "#/$defs/LicenseType"
            }
          ],
          "description": "License type"
        },
        "homepage_url": {
          "description": "Homepage URL",
          "format": "uri",
          "minLength": 1,
          "title": "Homepage Url",
          "type": "string"
        },
        "package_name_pypi": {
          "description": "Package name (PyPI)",
          "title": "Package Name Pypi",
          "type": "string"
        },
        "config_name": {
          "description": "Configuration name",
          "title": "Config Name",
          "type": "string"
        },
        "is_certified": {
          "description": "Certified",
          "title": "Is Certified",
          "type": "boolean"
        },
        "release_count": {
          "default": 0,
          "description": "Release count",
          "title": "Release Count",
          "type": "integer"
        },
        "release_latest": {
          "allOf": [
            {
              "$ref": "#/$defs/Release"
            }
          ],
          "default": null,
          "description": "Latest release"
        },
        "release_recent_history": {
          "default": [],
          "description": "Recent releases",
          "items": {
            "$ref": "#/$defs/Release"
          },
          "title": "Release Recent History",
          "type": "array"
        }
      },
      "required": [
        "id",
        "status",
        "title_short",
        "title_long",
        "tag_line",
        "description_short",
        "slug",
        "author",
        "created_at",
        "updated_at",
        "license_type",
        "homepage_url",
        "package_name_pypi",
        "config_name",
        "is_certified"
      ],
      "title": "Plugin",
      "type": "object"
    },
    "PluginStatus": {
      "const": "active",
      "description": "Plugin status model.",
      "enum": [
        "active"
      ],
      "title": "PluginStatus",
      "type": "string"
    },
    "Release": {
      "description": "Release model.",
      "properties": {
        "id": {
          "description": "Release ID",
          "format": "uuid4",
          "title": "Id",
          "type": "string"
        },
        "date": {
          "description": "Date",
          "format": "date-time",
          "title": "Date",
          "type": "string"
        },
        "version": {
          "description": "Version",
          "title": "Version",
          "type": "string"
        },
        "netbox_min_version": {
          "description": "NetBox minimum version",
          "title": "Netbox Min Version",
          "type": "string"
        },
        "netbox_max_version": {
          "description": "NetBox maximum version",
          "title": "Netbox Max Version",
          "type": "string"
        },
        "has_model": {
          "description": "Has model",
          "title": "Has Model",
          "type": "boolean"
        },
        "is_certified": {
          "description": "Is certified",
          "title": "Is Certified",
          "type": "boolean"
        },
        "is_feature": {
          "description": "Is feature",
          "title": "Is Feature",
          "type": "boolean"
        },
        "is_integration": {
          "description": "Is integration",
          "title": "Is Integration",
          "type": "boolean"
        },
        "is_netboxlabs_supported": {
          "description": "Is NetBox Labs supported",
          "title": "Is Netboxlabs Supported",
          "type": "boolean"
        }
      },
      "required": [
        "id",
        "date",
        "version",
        "netbox_min_version",
        "netbox_max_version",
        "has_model",
        "is_certified",
        "is_feature",
        "is_integration",
        "is_netboxlabs_supported"
      ],
      "title": "Release",
      "type": "object"
    }
  },
  "description": "List response model.",
  "properties": {
    "metadata": {
      "allOf": [
        {
          "$ref": "#/$defs/Metadata"
        }
      ],
      "description": "Metadata object"
    },
    "data": {
      "description": "Plugins",
      "items": {
        "$ref": "#/$defs/Plugin"
      },
      "title": "Data",
      "type": "array"
    }
  },
  "required": [
    "metadata",
    "data"
  ],
  "title": "PluginListResponse",
  "type": "object"
}

jeffgdotorg avatar May 29 '24 20:05 jeffgdotorg

Prototype of list view: Embedded catalog – card list (1)

(edit: Added a made up locally-installed plugin Contrail Sync not listed in the catalog)

jeffgdotorg avatar Jun 27 '24 15:06 jeffgdotorg

Additional prototypes for per-plugin detail view. I'm having trouble getting clickable prototype sharing to work so I'm just dropping static images here for the time being.

ACLs plugin – certified, not installed Board_ Embedded catalog – ACLs overview Board_ Embedded catalog – ACLs version history Board_ Embedded catalog – ACLs install

Contrail Sync plugin – made up, installed locally, not in catalog Board_ Embedded catalog – Contrail overview

DNS plugin – certified, installed, new version available (pretend version history tab shows this) Board_ Embedded catalog – DNS overview Board_ Embedded catalog – DNS version history Board_ Embedded catalog – DNS upgrade

jeffgdotorg avatar Jun 27 '24 19:06 jeffgdotorg