diff --git a/README.md b/README.md index 74dcf99..786af8f 100644 --- a/README.md +++ b/README.md @@ -43,3 +43,29 @@ Host mybastion `~/.annet/context.yml` the same because gnetcli read .ssh/config by default. +## Connecting to an externally-running gnetcli_server + +If `gnetcli_server` is already running on a bastion host, set `url` and the +adapter will connect to it instead of spawning a local server binary. `login` +and `password` authenticate to the gnetcli server itself (Basic auth); +`dev_login`/`dev_password` are still the network device credentials. + +```yaml +fetcher: + default: + adapter: gnetcli + params: &gnetcli + url: 192.0.2.10:50051 + login: gnetcli-user + password: gnetcli-secret + dev_login: mylogin + dev_password: mypassword +deployer: + default: + adapter: gnetcli + params: + <<: *gnetcli +``` + +When `url` is unset, the adapter starts a local `gnetcli_server` subprocess +(`server_path` defaults to `gnetcli_server` on `$PATH`). diff --git a/src/gnetcli_adapter/gnetcli_adapter.py b/src/gnetcli_adapter/gnetcli_adapter.py index 836734a..b7bd886 100644 --- a/src/gnetcli_adapter/gnetcli_adapter.py +++ b/src/gnetcli_adapter/gnetcli_adapter.py @@ -153,14 +153,21 @@ class ApiMaker(metaclass=abc.ABCMeta): @asynccontextmanager async def make_api(self) -> AsyncIterator[Gnetcli]: - async with GnetcliStarter(self.conf.server_path, self.conf.server_conf) as gnetcli_url: - yield Gnetcli( - server=gnetcli_url, + def _client(server_url: str) -> Gnetcli: + return Gnetcli( + server=server_url, auth_token=self.conf.make_server_credentials(), insecure_grpc=self.conf.insecure_grpc, user_agent="annet", ) + if self.conf.url: + yield _client(self.conf.url) + return + + async with GnetcliStarter(self.conf.server_path, self.conf.server_conf) as gnetcli_url: + yield _client(gnetcli_url) + class GnetcliFetcher(Fetcher, AdapterWithConfig, AdapterWithName, ApiMaker): def __init__( diff --git a/tests/test_methods.py b/tests/test_methods.py index 9d48db4..3f78d97 100644 --- a/tests/test_methods.py +++ b/tests/test_methods.py @@ -1 +1,18 @@ from __future__ import annotations + +import asyncio +from unittest.mock import patch + +from gnetcli_adapter.gnetcli_adapter import GnetcliFetcher + + +def test_make_api_uses_url_without_starter(): + fetcher = GnetcliFetcher(url="127.0.0.1:50050") + + async def run(): + with patch("gnetcli_adapter.gnetcli_adapter.GnetcliStarter") as starter: + async with fetcher.make_api() as api: + assert api._server == "127.0.0.1:50050" + starter.assert_not_called() + + asyncio.run(run())