diff --git a/src/blueapi/cli/cli.py b/src/blueapi/cli/cli.py index bd2154f0a..e513c4bb4 100644 --- a/src/blueapi/cli/cli.py +++ b/src/blueapi/cli/cli.py @@ -81,6 +81,19 @@ def is_str_dict(val: Any) -> TypeGuard[TaskParameters]: invoke_without_command=True, context_settings={"auto_envvar_prefix": "BLUEAPI"} ) @click.version_option(version=__version__, prog_name="blueapi") +@click.option( + "-h", + "--host", + type=str, + help=textwrap.dedent( + """ + Hostname for the blueapi instance to use + + Value should be the full URL including scheme (and port if non-default), + eg `--host http://localhost:8000` + """ + ), +) @click.option( "-c", "--config", type=Path, help="Path to configuration YAML file", multiple=True ) @@ -100,7 +113,10 @@ def is_str_dict(val: Any) -> TypeGuard[TaskParameters]: ) @click.pass_context def main( - ctx: click.Context, config: tuple[Path, ...], log_level: str | None = None + ctx: click.Context, + config: tuple[Path, ...], + host: str | None = None, + log_level: str | None = None, ) -> None: # if no command is supplied, run with the options passed @@ -112,7 +128,8 @@ def main( config_loader.use_values_from_yaml(*config) except FileNotFoundError as fnfe: raise ClickException(f"Config file not found: {fnfe.filename}") from fnfe - + if host: + config_loader.use_values({"api": {"url": host}}) if log_level: config_loader.use_values({"logging": {"level": log_level}}) diff --git a/tests/unit_tests/cli/test_cli.py b/tests/unit_tests/cli/test_cli.py index 687b3a03f..49e8b3e61 100644 --- a/tests/unit_tests/cli/test_cli.py +++ b/tests/unit_tests/cli/test_cli.py @@ -1430,3 +1430,45 @@ def test_log_level_override(flag: str, level: str, runner: CliRunner): runner.invoke(main, [flag]) mock_log.getLogger().setLevel.assert_called_once_with(level) mock_log.StreamHandler().setLevel.assert_called_once_with(level) + + +@responses.activate +def test_host_option(runner: CliRunner): + response = responses.add( + responses.GET, + "http://override.example.com:5678/plans", + json={"plans": []}, + status=200, + ) + + res = runner.invoke( + main, + ["--host", "http://override.example.com:5678", "controller", "plans"], + ) + assert response.call_count == 1 + assert res.exit_code == 0 + + +@responses.activate +def test_host_overrides_config(runner: CliRunner): + config_path = "tests/unit_tests/example_yaml/rest_config.yaml" + response = responses.add( + responses.GET, + "http://override.example.com:5678/plans", + json={"plans": []}, + status=200, + ) + + res = runner.invoke( + main, + [ + "--host", + "http://override.example.com:5678", + "--config", + config_path, + "controller", + "plans", + ], + ) + assert response.call_count == 1 + assert res.exit_code == 0