diff --git a/packages/jumpstarter-cli-driver/README.md b/packages/jumpstarter-cli-driver/README.md new file mode 100644 index 000000000..7fdd7b4bc --- /dev/null +++ b/packages/jumpstarter-cli-driver/README.md @@ -0,0 +1 @@ +# Jumpstarter Driver CLI diff --git a/packages/jumpstarter-cli-driver/jumpstarter_cli_driver/__init__.py b/packages/jumpstarter-cli-driver/jumpstarter_cli_driver/__init__.py new file mode 100644 index 000000000..4eaa8f8b4 --- /dev/null +++ b/packages/jumpstarter-cli-driver/jumpstarter_cli_driver/__init__.py @@ -0,0 +1,24 @@ +import logging +from typing import Optional + +import asyncclick as click +from jumpstarter_cli_common import AliasedGroup, opt_log_level, version + +from .driver import list_drivers + + +@click.group(cls=AliasedGroup) +@opt_log_level +def driver(log_level: Optional[str]): + """Jumpstarter driver CLI tool""" + if log_level: + logging.basicConfig(level=log_level.upper()) + else: + logging.basicConfig(level=logging.INFO) + + +driver.add_command(list_drivers) +driver.add_command(version) + +if __name__ == "__main__": + driver() diff --git a/packages/jumpstarter-cli-driver/jumpstarter_cli_driver/driver.py b/packages/jumpstarter-cli-driver/jumpstarter_cli_driver/driver.py new file mode 100644 index 000000000..984316597 --- /dev/null +++ b/packages/jumpstarter-cli-driver/jumpstarter_cli_driver/driver.py @@ -0,0 +1,13 @@ +from importlib.metadata import entry_points + +import asyncclick as click +from jumpstarter_cli_common import make_table + + +@click.command("list") +async def list_drivers(): + drivers = list(entry_points(group="jumpstarter.drivers")) + if not drivers: + click.echo("No drivers found.") + else: + click.echo(make_table(["NAME", "TYPE"], [{"NAME": e.name, "TYPE": e.value.replace(":", ".")} for e in drivers])) diff --git a/packages/jumpstarter-cli-driver/jumpstarter_cli_driver/driver_test.py b/packages/jumpstarter-cli-driver/jumpstarter_cli_driver/driver_test.py new file mode 100644 index 000000000..ad1d4b1b5 --- /dev/null +++ b/packages/jumpstarter-cli-driver/jumpstarter_cli_driver/driver_test.py @@ -0,0 +1,20 @@ +import pytest +from asyncclick.testing import CliRunner + +from . import driver + + +@pytest.mark.anyio +async def test_list_drivers(): + runner = CliRunner() + + result = await runner.invoke( + driver, + ["list"], + ) + assert result.exit_code == 0 + + +@pytest.fixture +def anyio_backend(): + return "asyncio" diff --git a/packages/jumpstarter-cli-driver/pyproject.toml b/packages/jumpstarter-cli-driver/pyproject.toml new file mode 100644 index 000000000..5c656e9be --- /dev/null +++ b/packages/jumpstarter-cli-driver/pyproject.toml @@ -0,0 +1,42 @@ +[project] +name = "jumpstarter-cli-driver" +dynamic = ["version", "urls"] +description = "" +authors = [ + { name = "Nick Cao", email = "ncao@redhat.com" }, + { name = "Miguel Angel Ajo Pelayo", email = "majopela@redhat.com" }, + { name = "Kirk Brauer", email = "kbrauer@hatci.com" }, +] +readme = "README.md" +license = { text = "Apache-2.0" } +requires-python = ">=3.11" +dependencies = [ + "jumpstarter-cli-common", + "asyncclick>=8.1.7.2", +] + +[dependency-groups] +dev = [ + "pytest>=8.3.2", + "pytest-anyio>=0.0.0", + "pytest-asyncio>=0.0.0", + "pytest-cov>=5.0.0", +] + +[project.scripts] +jmp-driver = "jumpstarter_cli_driver:driver" + +[tool.hatch.build.targets.wheel] +packages = ["jumpstarter_cli_driver"] + +[tool.hatch.metadata.hooks.vcs.urls] +Homepage = "https://jumpstarter.dev" +source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip" + +[tool.hatch.version] +source = "vcs" +raw-options = { 'root' = '../../'} + +[build-system] +requires = ["hatchling", "hatch-vcs"] +build-backend = "hatchling.build" diff --git a/packages/jumpstarter-cli/jumpstarter_cli/__init__.py b/packages/jumpstarter-cli/jumpstarter_cli/__init__.py index a32f07830..36973683c 100644 --- a/packages/jumpstarter-cli/jumpstarter_cli/__init__.py +++ b/packages/jumpstarter-cli/jumpstarter_cli/__init__.py @@ -2,6 +2,7 @@ from jumpstarter_cli_admin import admin from jumpstarter_cli_client import client from jumpstarter_cli_common import AliasedGroup, version +from jumpstarter_cli_driver import driver from jumpstarter_cli_exporter import exporter @@ -11,6 +12,7 @@ def jmp(): jmp.add_command(client) +jmp.add_command(driver) jmp.add_command(exporter) jmp.add_command(admin) jmp.add_command(version) diff --git a/packages/jumpstarter-cli/pyproject.toml b/packages/jumpstarter-cli/pyproject.toml index 97b3a63b5..690e0ad31 100644 --- a/packages/jumpstarter-cli/pyproject.toml +++ b/packages/jumpstarter-cli/pyproject.toml @@ -13,6 +13,7 @@ requires-python = ">=3.11" dependencies = [ "jumpstarter-cli-admin", "jumpstarter-cli-client", + "jumpstarter-cli-driver", "jumpstarter-cli-exporter", ] diff --git a/packages/jumpstarter-driver-can/pyproject.toml b/packages/jumpstarter-driver-can/pyproject.toml index a429a2aa9..06486db5b 100644 --- a/packages/jumpstarter-driver-can/pyproject.toml +++ b/packages/jumpstarter-driver-can/pyproject.toml @@ -16,6 +16,11 @@ dependencies = [ "can-isotp>=2.0.6", ] +[project.entry-points."jumpstarter.drivers"] +Can = "jumpstarter_driver_can.driver:Can" +IsoTpPython = "jumpstarter_driver_can.driver:IsoTpPython" +IsoTpSocket = "jumpstarter_driver_can.driver:IsoTpSocket" + [dependency-groups] dev = [ "pytest>=8.3.2", diff --git a/packages/jumpstarter-driver-composite/pyproject.toml b/packages/jumpstarter-driver-composite/pyproject.toml index e5e2015ef..170915bc2 100644 --- a/packages/jumpstarter-driver-composite/pyproject.toml +++ b/packages/jumpstarter-driver-composite/pyproject.toml @@ -14,6 +14,9 @@ dependencies = [ "asyncclick>=8.1.7.2" ] +[project.entry-points."jumpstarter.drivers"] +Composite = "jumpstarter_driver_composite.driver:Composite" + [dependency-groups] dev = [ "pytest>=8.3.2", diff --git a/packages/jumpstarter-driver-dutlink/pyproject.toml b/packages/jumpstarter-driver-dutlink/pyproject.toml index 7878a2267..deddad15d 100644 --- a/packages/jumpstarter-driver-dutlink/pyproject.toml +++ b/packages/jumpstarter-driver-dutlink/pyproject.toml @@ -22,6 +22,12 @@ dependencies = [ "asyncclick>=8.1.7.2" ] +[project.entry-points."jumpstarter.drivers"] +Dutlink = "jumpstarter_driver_dutlink.driver:Dutlink" +DutlinkSerial = "jumpstarter_driver_dutlink.driver:DutlinkSerial" +DutlinkStorageMux = "jumpstarter_driver_dutlink.driver:DutlinkStorageMux" +DutlinkPower = "jumpstarter_driver_dutlink.driver:DutlinkPower" + [dependency-groups] dev = [ "pytest>=8.3.2", diff --git a/packages/jumpstarter-driver-network/pyproject.toml b/packages/jumpstarter-driver-network/pyproject.toml index 1e01f85aa..83a01880e 100644 --- a/packages/jumpstarter-driver-network/pyproject.toml +++ b/packages/jumpstarter-driver-network/pyproject.toml @@ -16,6 +16,18 @@ dependencies = [ "wsproto>=1.2.0" ] +[project.entry-points."jumpstarter.drivers"] +TcpNetwork = "jumpstarter_driver_network.driver:TcpNetwork" +UdpNetwork = "jumpstarter_driver_network.driver:UdpNetwork" +UnixNetwork = "jumpstarter_driver_network.driver:UnixNetwork" +EchoNetwork = "jumpstarter_driver_network.driver:EchoNetwork" + +[project.entry-points."jumpstarter.adapters"] +TcpPortforward = "jumpstarter_driver_network.adapters:TcpPortforwardAdapter" +UnixPortforward = "jumpstarter_driver_network.adapters:UnixPortforwardAdapter" +Pexpect = "jumpstarter_driver_network.adapters:PexpectAdapter" +Novnc = "jumpstarter_driver_network.adapters:NovncAdapter" + [dependency-groups] dev = [ "pytest>=8.3.2", diff --git a/packages/jumpstarter-driver-opendal/pyproject.toml b/packages/jumpstarter-driver-opendal/pyproject.toml index 2f89c3934..cc69a98cd 100644 --- a/packages/jumpstarter-driver-opendal/pyproject.toml +++ b/packages/jumpstarter-driver-opendal/pyproject.toml @@ -15,6 +15,9 @@ dependencies = [ "asyncclick>=8.1.7.2" ] +[project.entry-points."jumpstarter.adapters"] +Opendal = "jumpstarter_driver_opendal.adapters:OpendalAdapter" + [dependency-groups] dev = [ "pytest>=8.3.2", diff --git a/packages/jumpstarter-driver-power/pyproject.toml b/packages/jumpstarter-driver-power/pyproject.toml index 19e7378a0..eff871b55 100644 --- a/packages/jumpstarter-driver-power/pyproject.toml +++ b/packages/jumpstarter-driver-power/pyproject.toml @@ -15,6 +15,9 @@ dependencies = [ "asyncclick>=8.1.7.2" ] +[project.entry-points."jumpstarter.drivers"] +MockPower = "jumpstarter_driver_power.driver:MockPower" + [dependency-groups] dev = [ "pytest>=8.3.2", diff --git a/packages/jumpstarter-driver-raspberrypi/pyproject.toml b/packages/jumpstarter-driver-raspberrypi/pyproject.toml index 2d2665fbb..7919943f0 100644 --- a/packages/jumpstarter-driver-raspberrypi/pyproject.toml +++ b/packages/jumpstarter-driver-raspberrypi/pyproject.toml @@ -15,6 +15,10 @@ dependencies = [ "gpiozero>=2.0.1", ] +[project.entry-points."jumpstarter.drivers"] +DigitalInput = "jumpstarter_driver_raspberrypi.driver:DigitalInput" +DigitalOutput = "jumpstarter_driver_raspberrypi.driver:DigitalOutput" + [dependency-groups] dev = [ "pytest>=8.3.2", diff --git a/packages/jumpstarter-driver-sdwire/pyproject.toml b/packages/jumpstarter-driver-sdwire/pyproject.toml index d373c0053..ad1cf2633 100644 --- a/packages/jumpstarter-driver-sdwire/pyproject.toml +++ b/packages/jumpstarter-driver-sdwire/pyproject.toml @@ -15,6 +15,9 @@ dependencies = [ "pyudev>=0.24.3", ] +[project.entry-points."jumpstarter.drivers"] +SDWire = "jumpstarter_driver_sdwire.driver:SDWire" + [dependency-groups] dev = [ "pytest>=8.3.2", diff --git a/pyproject.toml b/pyproject.toml index db5adcabf..e784a9ba2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,6 +7,7 @@ jumpstarter-cli = { workspace = true } jumpstarter-cli-admin = { workspace = true } jumpstarter-cli-client = { workspace = true } jumpstarter-cli-common = { workspace = true } +jumpstarter-cli-driver = { workspace = true } jumpstarter-cli-exporter = { workspace = true } jumpstarter-driver-can = { workspace = true } jumpstarter-driver-composite = { workspace = true } diff --git a/uv.lock b/uv.lock index f7670eea4..6a3db1f77 100644 --- a/uv.lock +++ b/uv.lock @@ -8,6 +8,7 @@ members = [ "jumpstarter-cli-admin", "jumpstarter-cli-client", "jumpstarter-cli-common", + "jumpstarter-cli-driver", "jumpstarter-cli-exporter", "jumpstarter-driver-can", "jumpstarter-driver-composite", @@ -787,6 +788,7 @@ source = { editable = "packages/jumpstarter-cli" } dependencies = [ { name = "jumpstarter-cli-admin" }, { name = "jumpstarter-cli-client" }, + { name = "jumpstarter-cli-driver" }, { name = "jumpstarter-cli-exporter" }, ] @@ -802,6 +804,7 @@ dev = [ requires-dist = [ { name = "jumpstarter-cli-admin", editable = "packages/jumpstarter-cli-admin" }, { name = "jumpstarter-cli-client", editable = "packages/jumpstarter-cli-client" }, + { name = "jumpstarter-cli-driver", editable = "packages/jumpstarter-cli-driver" }, { name = "jumpstarter-cli-exporter", editable = "packages/jumpstarter-cli-exporter" }, ] @@ -899,6 +902,36 @@ dev = [ { name = "pytest-cov", specifier = ">=5.0.0" }, ] +[[package]] +name = "jumpstarter-cli-driver" +source = { editable = "packages/jumpstarter-cli-driver" } +dependencies = [ + { name = "asyncclick" }, + { name = "jumpstarter-cli-common" }, +] + +[package.dev-dependencies] +dev = [ + { name = "pytest" }, + { name = "pytest-anyio" }, + { name = "pytest-asyncio" }, + { name = "pytest-cov" }, +] + +[package.metadata] +requires-dist = [ + { name = "asyncclick", specifier = ">=8.1.7.2" }, + { name = "jumpstarter-cli-common", editable = "packages/jumpstarter-cli-common" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "pytest", specifier = ">=8.3.2" }, + { name = "pytest-anyio", specifier = ">=0.0.0" }, + { name = "pytest-asyncio", specifier = ">=0.0.0" }, + { name = "pytest-cov", specifier = ">=5.0.0" }, +] + [[package]] name = "jumpstarter-cli-exporter" source = { editable = "packages/jumpstarter-cli-exporter" }