# Introduction

Jumpstarter is an open source framework that brings enterprise-grade testing
capabilities to everyone. While established industries like automotive and
manufacturing have long used {term}`HiL` testing, these tools have typically been
expensive proprietary systems. Jumpstarter democratizes this technology through
a free, cloud native approach that works with both physical hardware and virtual
devices.

At its core, Jumpstarter uses a client/server architecture where a single client
can control multiple devices under test. Its modular design supports both local
development (devices connected directly to your machine) and {term}`distributed mode`
testing environments (devices accessed remotely through a central {term}`controller`). All
communication happens over {term}`gRPC`, providing a consistent interface regardless of
deployment model. Every interface is programmatic - there is no GUI-only
workflow that a script or agent cannot replicate. A human developer running
`jmp shell`, a [pytest](https://docs.pytest.org/en/stable/) script, a CI
pipeline, and an
[AI agent](../getting-started/guides/integration-patterns/agentic.md)
all use the exact same APIs, authentication, and access controls.

Built on Python, Jumpstarter integrates easily with existing development
workflows and runs almost anywhere. It works with common testing tools like
`pytest`, shell scripts, Makefiles, and typical CI/CD systems. Beyond testing, it
can function as a virtual KVM (Keyboard, Video, Mouse) switch, enabling remote
access to physical devices for development.

## Core Components

Jumpstarter architecture is based on the following key components:

- {term}`DUT` - Hardware or virtual {term}`device` being tested
- [Drivers](drivers.md) - Interfaces for {term}`DUT` communication
- [Adapters](adapters.md) - Convert {term}`driver` connections into various formats
- [Exporters](exporters.md) - Expose {term}`device` interfaces over network via {term}`gRPC`
- [Hooks](hooks.md) - Lifecycle scripts that run at {term}`lease` boundaries
- [Clients](clients.md) - Libraries and CLI tools for {term}`device` interaction
- [Service](service.md) - Kubernetes {term}`controller` for resource management

Component interactions include:

- **{term}`DUT` and {term}`Driver`s** - {term}`Driver`s provide standardized
  interfaces to {term}`DUT`'s hardware connections
- **{term}`Driver`s and {term}`Adapter`s** - {term}`Adapter`s transform
  {term}`driver` connections for specialized use cases
- **{term}`Driver`s/{term}`Adapter`s and {term}`Exporter`s** -
  {term}`Exporter`s manage {term}`driver`s/{term}`adapter`s and expose them
  via {term}`gRPC`
- **{term}`Hook`s and {term}`Exporter`s** - {term}`Hook`s execute shell
  scripts at {term}`lease` boundaries, running before {term}`driver`s are
  available and after the {term}`session` ends
- **{term}`Exporter`s and {term}`Client`s** - {term}`Client`s connect to
  {term}`exporter`s to control {term}`device`s
- **{term}`Client`s/{term}`Exporter`s and {term}`Service`** -
  {term}`Service` manages access control and resource allocation in
  {term}`distributed mode`

Together, these components form a comprehensive testing framework that bridges
the gap between development and deployment environments.

```{mermaid}
flowchart TB
    subgraph "Kubernetes Cluster"
        Controller["Controller\nInventory / Lease / Access Control"]
        Router["Router\nNAT Traversal"]
        CRDs["CRDs\nExporter, Client, Lease"]
        Controller --- CRDs
        Controller <--> Router
    end

    subgraph "Exporter Host"
        Exporter["Exporter"]
        subgraph "Drivers"
            GPIO["GPIO"]
            HDMI["HDMI"]
            Serial["Serial"]
            Storage["Storage"]
        end
        Exporter --- GPIO
        Exporter --- HDMI
        Exporter --- Serial
        Exporter --- Storage
    end

    DUT["Device Under Test"]
    GPIO --> DUT
    HDMI --> DUT
    Serial --> DUT
    Storage --> DUT

    Client["Client\n(CLI / Python API)"]

    Client -- "Distributed\n(gRPC via Router)" --> Router
    Router <--> Exporter
    Client -. "Direct\n(gRPC via TCP)" .-> Exporter
    Client -. "Local\n(gRPC via Socket)" .-> Exporter
```

## Operation Modes

Building on these components, Jumpstarter implements three operation modes that
provide flexibility for different scenarios: {term}`local mode`,
{term}`direct mode`, and {term}`distributed mode`.

### Local Mode

In {term}`local mode`, clients communicate directly with {term}`exporter`s running on the same
machine or through direct network connections.

```{mermaid}
flowchart TB
    subgraph "Developer Machine"
        Client["Client\n(Python Library/CLI)"]
        Exporter["Exporter\n(Local Service)"]
    end

    subgraph "Target Devices"
        DUT["Physical/Virtual\nDevice Under Test"]
        Power["Power Interface"]
        Serial["Serial Interface"]
        Storage["Storage Interface"]
    end

    Client <--> |"gRPC via Socket"| Exporter
    Exporter --> Power
    Exporter --> Serial
    Exporter --> Storage
    Power --> DUT
    Serial --> DUT
    Storage --> DUT
```

This mode is ideal for individual developers working directly with accessible
hardware or virtual devices. When no client configuration or environment
variables are present, Jumpstarter runs in {term}`local mode` and communicates with a
built-in {term}`exporter` service via a local socket connection, requiring no Kubernetes
or other infrastructure. Developers can work with devices on their desk, develop
drivers, create automation scripts, and test with QEMU or other virtualization
tools.

```console
$ jmp shell --exporter my-exporter
$ pytest test_device.py
```

The example above shows typical {term}`local mode` usage: first connecting to an
{term}`exporter` (which manages the {term}`device` interfaces) using the `jmp shell` command,
and then running tests against the device with `pytest`. The `--exporter` flag
specifies which exporter configuration to use, allowing you to easily switch
between different hardware or virtual {term}`device` setups.

### Direct Mode

{term}`Direct mode` connects a client to an {term}`exporter` over TCP without a
{term}`controller` or Kubernetes cluster. This is useful when hardware is on one
machine and the client is on another, but you don't need multi-user
{term}`lease` management.

```{mermaid}
flowchart LR
    subgraph "Client Machine"
        Client["Client\n(Python Library/CLI)"]
    end

    subgraph "Exporter Machine"
        Exporter["Exporter\n(Remote Service)"]
        Power["Power"]
        Serial["Serial"]
        Storage["Storage"]
    end

    DUT["Device Under Test"]

    Client <--> |"gRPC via TCP"| Exporter
    Exporter --> Power
    Exporter --> Serial
    Exporter --> Storage
    Power --> DUT
    Serial --> DUT
    Storage --> DUT
```

```console
$ jmp shell --exporter example-direct
```

Only one client should connect at a time. For shared, multi-user environments
use {term}`distributed mode` instead.

### Distributed Mode

{term}`Distributed mode` enables multiple teams to securely share hardware resources
across a network. It uses a Kubernetes-based {term}`controller` to coordinate access to
{term}`exporter`s, managing {term}`lease`s that grant exclusive access to {term}`DUT` resources, while
JWT token-based authentication secures all connections between clients and
{term}`exporter`s.

```{mermaid}
flowchart TB
    subgraph "Kubernetes Cluster"
        Controller["Controller\nResource Management"]
        Router["Router\nMessage Routing"]
        Auth["Authentication\nJWT Tokens"]
    end

    subgraph "Test Runners"
        Client1["Client 1\n(CI Pipeline)"]
        Client2["Client 2\n(Developer)"]
    end

    subgraph "Lab Resources"
        Exporter1["Exporter 1\n(Physical Hardware)"]
        Exporter2["Exporter 2\n(Virtual Devices)"]
        subgraph "Devices"
            DUT1["Physical Device 1"]
            DUT2["Physical Device 2"]
            DUT3["Virtual Device"]
        end
    end

    Client1 <--> |"JWT Authentication"| Auth
    Client2 <--> |"JWT Authentication"| Auth
    Exporter1 <--> |"JWT Authentication"| Auth
    Exporter2 <--> |"JWT Authentication"| Auth
    Auth <--> Controller

    Client1 <--> |"gRPC (Authorized)"| Controller
    Client2 <--> |"gRPC (Authorized)"| Controller
    Controller <--> Router
    Router <--> |"gRPC"| Exporter1
    Router <--> |"gRPC"| Exporter2
    Exporter1 --> DUT1
    Exporter1 --> DUT2
    Exporter2 --> DUT3
```

{term}`Distributed mode` is ideal for environments where teams need to share hardware
resources, especially in CI/CD pipelines requiring scheduled device testing. It
excels in geographically distributed test environments where devices are spread
across multiple locations, and in any scenario requiring centralized management
of testing resources. All these scenarios require a robust security model to
manage access rights and prevent resource conflicts.

To address these security needs, the {term}`distributed mode` implements a comprehensive
authentication system that secures access through:

- **Client Registration** - Clients register in the Kubernetes cluster with
   unique identities
- **Token Issuance** - {term}`Controller` or an OIDC server issues JWT tokens to authenticated clients and
   {term}`exporter`s
- **Secure Communication** - All {term}`gRPC` communication between components uses
   token authentication
- **Access Control** - {term}`Controller` enforces permissions based on token identity:
   - Which {term}`exporter`s a client can {term}`lease`
   - What actions a client can perform
   - Which driver packages can be loaded

This security model enables dynamic registration of clients and {term}`exporter`s,
allowing fine-grained access control in multi-user environments. For example, CI
pipelines can be granted access only to specific {term}`exporter`s based on their
credentials, ensuring proper resource isolation in shared testing environments.

The following example shows how to run tests in {term}`distributed mode`:

```console
$ jmp config client use my-client
$ jmp create lease --selector vendor=acme,model=widget-v2
$ pytest test_device.py
```

The example above demonstrates the {term}`distributed mode` workflow: first configuring
the client with connection information for the central {term}`controller`, then
requesting a {term}`lease` on an {term}`exporter` that matches specific criteria (using
{term}`label selector`s), and finally running tests against the acquired {term}`DUT`. The {term}`lease` system
ensures exclusive access to the requested resources for the duration of testing,
preventing conflicts with other users or pipelines in the shared environment.

```{toctree}
:maxdepth: 1
:hidden:
drivers.md
adapters.md
exporters.md
hooks.md
clients.md
service.md
```
