Basic Usage & Lifecycle (ConnectionProxy)
This page shows how to use connection proxies in function blocks and how to manage connection lifecycle correctly.
- For concepts and architecture: 30-device-connections.md
- For resolution rules and defaults: 32-method-resolution-priority.md
- For writing capabilities/proxies: 33-writing-capabilities-and-proxies.md
- For implementing plugins: 34-writing-base-plugins.md and 35-platform-plugins-and-defaults.md
Before you start (two common gotchas)
1) Plugin registration is import-time
Plugins register themselves when their modules are imported. If you never import any plugin modules, the registry may be empty and you’ll get PluginNotFoundError even if plugins exist in the SDK.
The simplest way to ensure the built-in plugins are registered is:
# noqa: F401 tells linters to ignore “unused import” warnings. This import has side effects (plugin registration) even though you don’t reference the module directly.
If you write custom plugins, you still need to import your plugin modules somewhere before use (same idea: import-time registration).
2) Device object requirements
To connect successfully, the resolved base plugin typically requires:
device.platform(dict/object withshort_name, or a string platform)device.ipdevice.usernamedevice.password
Missing any of these usually raises ConnectionValidationError during connect.
Recommended usage: context manager
The safest pattern is to use the proxy’s context manager so connections are always cleaned up:
import neops_worker_sdk.connection.plugins # noqa: F401
from neops_worker_sdk.connection.proxy import ConnectionProxy
from neops_worker_sdk.connection.capabilities import DeviceInfoCapability
from neops_worker_sdk.workflow import Device
# First, define your proxy class (see 33-writing-capabilities-and-proxies.md for details)
class DeviceInfoProxy(ConnectionProxy, DeviceInfoCapability):
pass
device = Device(
id=1,
platform={"id": 1, "name": "ios", "short_name": "ios"},
ip="192.168.1.1",
username="admin",
password="secret",
skip_if_identifier_exists=False,
identifier_fields=[],
)
with DeviceInfoProxy.connect(
device,
connection_type="ssh",
connection_library="scrapli",
connect=True, # default
fallback_to_default=False, # default
validate_capabilities=True, # default
) as proxy:
version = proxy.get_version()
What you get:
- automatic cleanup via
proxy.close()infinally - clearer code in long workflows
Manual lifecycle: MyProxy.get_connection() + close()
If you need manual lifecycle control, do this:
proxy = DeviceInfoProxy.get_connection(device, "ssh", "scrapli")
try:
version = proxy.get_version()
finally:
proxy.close()
Warning: Don’t rely on GC / object destruction to close connections. Always call
close()if you usedMyProxy.get_connection()directly.Note: After
close(), the proxy will still delegate method calls to the plugin, but the plugin’sget_raw_connection()will typically returnNone. Most capability methods should then raiseConnectionCreationError(“No connection available…”). Treat a closed proxy as unusable.
Parameters you should know
Both get_connection() and connect() accept these important keyword parameters:
connect: bool = True: ifFalse, creates the connection wrapper without establishing a live connection (advanced/testing use).fallback_to_default: bool = False: opt-in default selection when the library is omitted or resolution is ambiguous.validate_capabilities: bool = True: warn if the resolved plugin doesn’t implement capability methods required by the proxy.
Deferred connect (advanced)
proxy = DeviceInfoProxy.get_connection(device, "ssh", "scrapli", connect=False)
# ... inspect proxy/plugin, do other setup ...
proxy.plugin.initialize_connection(connect=True)
Picking connection type and library
ConnectionProxy.get_connection() takes:
connection_type:"ssh","api","netconf","restconf", …connection_library:"netmiko","scrapli","httpx","ncclient", …
In most real deployments you should specify both to avoid ambiguity:
See 30-device-connections.md for the current conventions and examples.
Defaults are opt-in (fallback_to_default=True)
Plugins can register as defaults:
- platform default: used when you don’t specify connection type/library
- platform + connection_type default: used when you specify type but not library
Defaults are only considered when you pass fallback_to_default=True.
Example: platform + connection_type default
Example: platform default
Note: If the registry still finds multiple candidates and no applicable default exists, you’ll get
AmbiguousPluginError. See 32-method-resolution-priority.md.
Errors you should expect (and handle)
Common exceptions raised during resolution/connection:
ConnectionValidationError: device is missing required fields (ip/username/password/platform)PluginNotFoundError: no plugin exists for the platform/type/library/capability requirementsAmbiguousPluginError: multiple plugins qualify (and no default selection was possible)ConnectionCreationError: dependency missing or the library couldn’t connect
Missing capability methods at call time raise:
NotImplementedForThisPlatform: rich context (proxy, method, interface, platform, plugin, device id)
Example: handling common failures
from neops_worker_sdk.connection.exceptions import (
AmbiguousPluginError,
ConnectionCreationError,
ConnectionValidationError,
NotImplementedForThisPlatform,
PluginNotFoundError,
)
try:
with DeviceInfoProxy.connect(device, "ssh", "scrapli") as proxy:
version = proxy.get_version()
except ConnectionValidationError as exc:
# device data is incomplete (fix device fields; retrying won't help)
raise
except PluginNotFoundError as exc:
# plugin modules not imported (add: import neops_worker_sdk.connection.plugins)
# OR no plugin exists for your platform/type/library combination
raise
except AmbiguousPluginError as exc:
# multiple plugins match (specify library or opt into defaults)
raise
except ConnectionCreationError as exc:
# auth/network/dependency problems; consider retry with backoff
raise
except NotImplementedForThisPlatform as exc:
# capability method missing on the selected plugin (use proxy override or different plugin)
raise
Capability validation warnings (early signal)
By default, proxy creation uses validate_capabilities=True, which warns if the resolved plugin is missing methods for the proxy’s declared capabilities.
This is intentionally a warning (not an error) because the system supports best‑match fallback and custom proxy overrides. See 33-writing-capabilities-and-proxies.md for how to override methods on the proxy.