Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/.custom_wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ linters
localhost
l ookups
lookups
loopback
lspci
lxc
lxd
Expand Down
46 changes: 23 additions & 23 deletions docs/coverage.md

Large diffs are not rendered by default.

71 changes: 5 additions & 66 deletions docs/explanation/interfaces/concepts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,44 +43,16 @@ Currently, |ws_markup| and |sdk_markup| support the following:
- :ref:`GPU interface <exp_gpu_interface>` (auto-connected)
- :ref:`Mount interface <exp_mount_interface>` (auto-connected)
- :ref:`SSH interface <exp_ssh_interface>` (manually connected)
- :ref:`Tunnel interface <exp_tunnel_interface>` (conditionally auto-connected)


.. _exp_plugs_slots:

Plugs and slots
---------------

To make use of these interfaces,
SDKs and :ref:`workshops <exp_workshop_definition_connections>` define *slots*.
For example, a :ref:`mount interface <exp_mount_interface>` slot
creates a source directory to be mounted inside the workshop via a plug.

Further, SDKs and :ref:`workshops <exp_workshop_definition_connections>` define *plugs*
to connect to a slot of a certain interface type.
For example, a :ref:`mount interface <exp_mount_interface>` plug
mounts the slot to a target directory inside the workshop.

You can think of the plug as the recipient of the resources exposed by the slot;
note that a slot can handle connections with multiple plugs.

Connections can be established:

- Automatically:
By running :command:`workshop launch`, :command:`workshop refresh`,
or :command:`workshop start`.

- Manually:
By running :command:`workshop connect` after the workshop has started,
or by listing connections in the
:ref:`workshop definition <exp_workshop_definition_connections>`
and running :command:`workshop refresh`.


All connections are subject to validation.
Also, automatic connections require plugs and slots to have matching details
and aren't allowed for some interfaces, such as :samp:`ssh-agent`.
Finally, the order of automatic connections is not guaranteed,
so you should not rely on it.
Interfaces become useful when SDKs declare *plugs* to consume them
and *slots* to provide them.
See :ref:`exp_plugs_slots` for the full mechanics,
including the wiring you can express in the workshop definition.


.. _exp_interfaces_validation:
Expand Down Expand Up @@ -147,39 +119,6 @@ when a workshop is launched, refreshed, or restored,
see :ref:`exp_workshop_connection_lifecycle`.


.. _exp_plug_bindings:

Plug bindings
-------------

SDKs usually access host resources via :ref:`interface plugs <exp_plugs_slots>`.
When multiple SDKs try to use the same resource in conflicting ways,
the workshop won't launch and shows an error.

To fix this issue, you can bind one plug to another of the same interface type.
This makes both plugs point to the same resource without conflicts.
Any action performed on one plug (like mounting or remounting)
thus automatically applies to *all* bound plugs.

When you run :command:`workshop connections`,
a bound plug will have :samp:`bind` listed under :samp:`Notes`,
along with the line number of the target plug:

.. @artefact workshop connections

.. code-block:: console

$ workshop connections digits

INTERFACE PLUG SLOT NOTES
mount digits/torchaudio:hub digits/system:mount bind.1
mount digits/torchvision:hub digits/system:mount bind.1


Here, both plugs are listed as :samp:`bind.1`,
pointing to :samp:`torchaudio:hub` in the *first* line.


.. _exp_interfaces_cli_operations:

Related CLI operations
Expand Down
1 change: 1 addition & 0 deletions docs/explanation/interfaces/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ to connect SDKs to host resources and to each other:
:maxdepth: 1

concepts
plugs-and-slots


Hardware interfaces
Expand Down
292 changes: 292 additions & 0 deletions docs/explanation/interfaces/plugs-and-slots.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,292 @@
.. _exp_plugs_slots:

.. meta::
:description: Plugs and slots are the mechanism through which SDKs in a
workshop expose and consume capabilities, forming the
capability topology that connects providers to consumers.

Plugs and slots
===============

.. @artefact interface plug
.. @artefact interface slot
.. @artefact interface connection

A workshop is a graph of capabilities.
Each SDK can act as a provider, a consumer, or both,
and the wiring between them
is what lets a workshop deliver a coherent environment
out of independently published parts.

In |ws_markup|, that wiring uses two named endpoints:
*plugs* and *slots*.
Both reference an :ref:`interface <exp_interface_concepts>` type;
slots provide a capability of that type,
and plugs consume one.
The workshop connects matching pairs at launch
and lets you adjust the topology
in the :ref:`workshop definition <exp_workshop_definition_connections>`
when the defaults are not what you want.


Slots provide capabilities
--------------------------

A slot exposes a capability that other SDKs can consume;
a single slot can serve connections from multiple plugs at once.
What a slot exposes depends on its interface:

- A :ref:`mount interface <exp_mount_interface>` slot
exposes a directory.

- A :ref:`tunnel interface <exp_tunnel_interface>` slot
exposes a network endpoint.

- A :ref:`GPU interface <exp_gpu_interface>` slot
exposes a GPU device.

- A :ref:`camera interface <exp_camera_interface>`,
:ref:`custom device interface <exp_custom_device_interface>`,
:ref:`desktop interface <exp_desktop_interface>`,
or :ref:`SSH interface <exp_ssh_interface>` slot
exposes the corresponding host facility.


Some capabilities are inherently host-rooted,
like a camera device or a host-side directory.
Only the :ref:`system SDK <exp_system_sdk>`
can expose host-rooted slots,
which is why every workshop has one installed by default.
Regular SDKs can still publish slots
that expose directories or endpoints from inside the workshop;
a mount slot in a regular SDK,
for example,
points at a path within the SDK or the :samp:`workshop` user's home,
not the host filesystem.


Plugs consume capabilities
--------------------------

A plug is the consumer end.
It is named within the SDK that declares it,
references an interface type,
and carries any attributes the consumer needs to apply
once a slot is connected.
For instance, with a mount plug,
the central attribute is the target path inside the workshop
where the slot's directory should appear.

A plug stays declared even if no slot is connected to it,
which means an SDK can ship optional plugs
that only activate when a corresponding provider is also installed.


.. _exp_interface_auto_connection:

Auto-connection
---------------

When a workshop launches or refreshes,
|ws_markup| tries to connect each plug
to a slot of the same interface type.
The attempt succeeds when the interface policy
permits the plug to connect to a candidate slot.
The policy is what gates auto-connection,
not the number of candidate slots in the workshop.

Auto-connection behavior varies by interface:

- The mount interface auto-connects to slots provided by the system SDK.
Regular-SDK mount slots are not auto-connected by default;
wire them by listing the pair in the workshop's
:ref:`top-level connections <exp_workshop_definition_connections>`.

- The GPU interface auto-connects.

- The tunnel interface auto-connects only from host to workshop,
between a plug and a slot of the same name,
and only when the plug's endpoint
is a loopback address or a Unix domain socket.
See :ref:`exp_tunnel_connection` for the full policy.

- The camera, custom device, desktop, and SSH interfaces
do not auto-connect.
They have to be connected manually with :command:`workshop connect`.


When more than one slot is policy-eligible for the same plug,
|ws_markup| attempts a connection for each of them
in an order it does not guarantee.
The right way to express a specific topology
is to write it down in the workshop definition's :samp:`connections:` list
instead of leaving it to auto-connection.


Wiring mechanisms
-----------------

The :ref:`workshop definition <exp_workshop_definition>`
gives you two distinct YAML mechanisms for shaping the topology:

- An inline :ref:`plug binding <exp_plug_bindings>`,
written as :samp:`bind:` inside a plug entry,
delegates one plug to another plug.
Both plugs then point at the same target,
which is how same-interface conflicts are resolved.

- A top-level :samp:`connections:` list,
written at workshop scope,
pairs a specific plug with a specific slot.
Use it to override the default auto-connect target,
for example to wire a mount plug to a regular SDK's slot
rather than the system SDK's.
The pair still has to satisfy the interface's auto-connection policy,
so interfaces that block auto-connection outright
(such as :samp:`ssh-agent`)
cannot be wired this way
and must be connected with :command:`workshop connect`.


The two mechanisms are mutually exclusive for a given plug:
if it's bound to another plug,
it cannot also appear in a top-level :samp:`connections:` entry.

|ws_markup| also exposes the runtime-only
:command:`workshop connect` and :command:`workshop disconnect` commands,
which change the wiring of a running workshop.


.. _exp_plug_bindings:

Inline plug bindings
~~~~~~~~~~~~~~~~~~~~

A plug binding lets one plug stand in for another:

.. code-block:: yaml
:caption: workshop.yaml

sdks:
- name: consumer-sdk
plugs:
tools:
bind: provider-sdk:tools


Both plugs then point to the same resource,
and any action performed on one,
such as connecting or remounting,
applies to all bound plugs.

Bindings are the right tool when two plugs of the same interface
would otherwise conflict over the same target,
typically because two SDKs each declare a plug
with overlapping attributes.

A bound plug only carries the binding;
it cannot also define plug attributes of its own.
The attributes come from the plug it is bound to.

When you run :command:`workshop connections`,
both the bound plug and its target
carry a :samp:`bind.<N>` note in the :samp:`NOTES` column,
where :samp:`<N>` is the row number of the target plug
in the same output.


Top-level connections
~~~~~~~~~~~~~~~~~~~~~

The top-level :samp:`connections:` list
pairs a plug with a slot directly:

.. code-block:: yaml
:caption: workshop.yaml

connections:
- plug: consumer-sdk:tools
slot: provider-sdk:bin


Each entry uses the :samp:`<SDK-NAME>:<NAME>` form
on both sides.
Once the workshop is launched or refreshed,
that pairing is the one |ws_markup| applies,
regardless of what other slots could have matched.

This is the mechanism to use
when the workshop has more than one provider for an interface
and you want to be specific about which one a consumer reads from.


Example: two SDKs sharing a mount
---------------------------------

Consider a workshop that installs two SDKs:

- :samp:`provider-sdk` ships a mount slot named :samp:`bin`
that exposes a directory inside its own filesystem.

- :samp:`consumer-sdk` declares a mount plug named :samp:`tools`
whose target is a path under its workshop user's home.


Auto-connection alone does not wire :samp:`consumer-sdk:tools`
to :samp:`provider-sdk:bin`:
the mount interface auto-connects to system SDK slots by default,
so :samp:`consumer-sdk:tools` lands on :samp:`system:mount`
and :samp:`provider-sdk:bin` stays listed but unconnected.
You name the pairing explicitly
with a top-level :samp:`connections:` entry:

.. code-block:: yaml
:caption: workshop.yaml

sdks:
- name: provider-sdk
- name: consumer-sdk

connections:
- plug: consumer-sdk:tools
slot: provider-sdk:bin


After :command:`workshop launch` or :command:`workshop refresh`,
:command:`workshop connections` shows the chosen pairing
and you can verify that :samp:`consumer-sdk` reads from :samp:`provider-sdk`
rather than the system SDK's default mount slot.


See also
--------

Explanation:

- :ref:`exp_camera_interface`
- :ref:`exp_custom_device_interface`
- :ref:`exp_desktop_interface`
- :ref:`exp_gpu_interface`
- :ref:`exp_interface_concepts`
- :ref:`exp_mount_interface`
- :ref:`exp_sdks`
- :ref:`exp_ssh_interface`
- :ref:`exp_tunnel_interface`
- :ref:`exp_workshop`


How-to guides:

- :ref:`how_declare_plugs_slots`
- :ref:`how_design_interface_layout`
- :ref:`how_resolve_plug_conflicts`


Reference:

- :ref:`ref_sdk_internals`
- :ref:`ref_sdk_plugs_slots`
- :ref:`ref_workshop_connect`
- :ref:`ref_workshop_connections`
- :ref:`ref_workshop_definition`
- :ref:`ref_workshop_disconnect`
Loading
Loading