Skip to content

Platform Plugins, Defaults, and Real Examples

This page shows how to:


Example: iOS SSH defaults (Netmiko)

In this repository, iOS ships with a Netmiko SSH plugin registered as both platform and connection-type defaults (default_for_platform=True, default_for_connection_type=True). See neops_worker_sdk/connection/plugins/ios/netmiko_plugin.py.

At call sites you can opt into defaults:

proxy = MyProxy.get_connection(device, "ssh", fallback_to_default=True)

or even:

proxy = MyProxy.get_connection(device, fallback_to_default=True)

See 32-method-resolution-priority.md for exactly when defaults apply (and when they don’t).


Example: iOS SSH + DeviceInfoCapability (Scrapli)

This repo also contains a Scrapli-based plugin that implements DeviceInfoCapability:

  • neops_worker_sdk/connection/plugins/ios/scrapli_plugin.py

It’s a good example of a “real” capability implementation:

  • uses get_raw_connection() to access the underlying Scrapli connection
  • raises ConnectionCreationError if no connection is available
  • logs at info for a user-visible action and warning for parse fallback

Note: get_raw_connection() returns the underlying library object (e.g. Scrapli driver / Netmiko connection / httpx client).

It returns None if the plugin is not connected, the connection was torn down, or the connection is dead.

Capability-driven selection

Consider a proxy that requires DeviceInfoCapability:

from neops_worker_sdk.connection.capabilities import DeviceInfoCapability
from neops_worker_sdk.connection.proxy import ConnectionProxy


class DeviceInfoProxy(ConnectionProxy, DeviceInfoCapability):
    pass

If you call without specifying a library:

proxy = DeviceInfoProxy.get_connection(device, "ssh", fallback_to_default=True)

The resolver considers iOS SSH plugins and filters by capability: only plugins implementing DeviceInfoCapability qualify. This narrows the candidate set and often resolves library ambiguity, but if multiple plugins implement the same capability you may still need to specify the library or opt into defaults.


Writing your own platform plugin

Platform plugins typically:

  • inherit the library base plugin (see 34-writing-base-plugins.md)
  • inherit one or more capability interfaces
  • set platform = "..." and register with @register_connection_plugin(...)

Skeleton:

from neops_worker_sdk.connection.capabilities import DeviceInfoCapability
from neops_worker_sdk.connection.exceptions import ConnectionCreationError
from neops_worker_sdk.connection.registry import register_connection_plugin
from neops_worker_sdk.connection.plugins.base.scrapli_plugin import ScrapliConnectionPluginBase


@register_connection_plugin(default_for_connection_type=True)
class MyPlatformScrapliPlugin(ScrapliConnectionPluginBase, DeviceInfoCapability):
    platform = "my_platform"

    def get_version(self) -> dict[str, str | None]:
        conn = self.get_raw_connection()
        if not conn:
            raise ConnectionCreationError(
                "No connection available; initialize the connection before calling get_version().",
                device_id=str(self.device.id) if self.device.id else None,
            )
        output = conn.send_command("show version")
        return {"vendor": "...", "model": "...", "serial": "...", "software_release": "..."}

Checklist (platform plugin quality)

  • Capabilities: implement the capability interface methods you claim to provide
  • Exceptions: raise ConnectionCreationError / ConnectionValidationError (not ValueError)
  • Logging: use Logger() with appropriate levels (info for “doing a thing”, warning for recoverable fallbacks)
  • Parsing: if parsing fails, return a safe structure with raw_output when helpful
  • Defaults: only register defaults when you’re confident they’re safe for most users