From eddd1d373a160ca4880a48c2d8aea174952639d2 Mon Sep 17 00:00:00 2001 From: Victor Moene Date: Mon, 14 Sep 2026 10:43:01 +0200 Subject: [PATCH] Made cf-remote info print all hub hosts or all hosts cf-remote info without arguments prints now all the saved hubs. Added a --all option to print all hosts. Ticket: CFE-3870 Signed-off-by: Victor Moene --- cf_remote/args.py | 7 ++++- cf_remote/commands.py | 34 ++++++++++++++++------ cf_remote/main.py | 2 +- tests/test_info.py | 68 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 100 insertions(+), 11 deletions(-) create mode 100644 tests/test_info.py diff --git a/cf_remote/args.py b/cf_remote/args.py index da480eb..fee70a3 100644 --- a/cf_remote/args.py +++ b/cf_remote/args.py @@ -7,7 +7,12 @@ def add_info_args(sp: argparse.ArgumentParser) -> None: sp.add_argument( - "--hosts", "-H", help="Which hosts to get info for", type=str, required=True + "--hosts", "-H", help="Which hosts to get info for", type=str, required=False + ) + sp.add_argument( + "--all", + help="Show info about all hosts", + action="store_true", ) diff --git a/cf_remote/commands.py b/cf_remote/commands.py index 53ecbc7..c56f659 100644 --- a/cf_remote/commands.py +++ b/cf_remote/commands.py @@ -53,8 +53,19 @@ from cf_remote import cloud_data -def info(hosts, users=None): - assert hosts +def info(hosts, users=None, all=False): + if all: + hosts = _get_all_hosts() + elif not hosts: + hosts = _get_hubs() + + if not hosts: + if all: + print("No hosts") + else: + print("No hub hosts") + return 0 + log.debug("hosts='{}'".format(hosts)) errors = 0 for host in hosts: @@ -948,21 +959,26 @@ def deploy_tarball(hubs, tarball): return errors -def _get_hubs(): +def _get_all_hosts(role=None): if not os.path.exists(CLOUD_STATE_FPATH): return None groups = read_json(CLOUD_STATE_FPATH) if not groups: return None - hubs = [] - for name, group in groups.items(): + hosts = [] + for group in groups.values(): for name, vm in group.items(): if name == "meta": continue - if vm["role"] == "hub": - identifier = "{}@{}".format(vm["user"], vm["public_ips"][0]) - hubs.append(identifier) - return hubs + if role is not None and vm["role"] != role: + continue + identifier = "{}@{}".format(vm["user"], vm["public_ips"][0]) + hosts.append(identifier) + return hosts + + +def _get_hubs(): + return _get_all_hosts(role="hub") def deploy(hubs, masterfiles): diff --git a/cf_remote/main.py b/cf_remote/main.py index 403f92a..2713173 100644 --- a/cf_remote/main.py +++ b/cf_remote/main.py @@ -44,7 +44,7 @@ def get_args(): def run_command_with_args(command, args) -> int: if command == "info": - return commands.info(args.hosts, None) + return commands.info(args.hosts, users=None, all=args.all) elif command == "install": if args.trust_keys: trust_keys = args.trust_keys.split(",") diff --git a/tests/test_info.py b/tests/test_info.py new file mode 100644 index 0000000..af8cd8f --- /dev/null +++ b/tests/test_info.py @@ -0,0 +1,68 @@ +import pytest + +from cf_remote import commands +from cf_remote.remote import print_info + +HUB_1 = "admin@34.243.147.219" +HUB_2 = "admin@34.243.147.220" +CLIENT_1 = "admin@34.243.147.221" + +DATA_BY_HOST = { + HUB_1: {"ssh": HUB_1, "role": "hub", "agent_version": None}, + HUB_2: {"ssh": HUB_2, "role": "hub", "agent_version": None}, + CLIENT_1: {"ssh": CLIENT_1, "role": "client", "agent_version": None}, +} + +# Literal JSON string to guarantee the insertion order for python 3.5 +CLOUD_STATE_JSON = """ +{ + "@mygroup": { + "meta": {"provider": "aws", "region": "eu-west-1"}, + "mygroup-1": {"user": "admin", "role": "hub", "public_ips": ["34.243.147.219"]}, + "mygroup-2": {"user": "admin", "role": "hub", "public_ips": ["34.243.147.220"]}, + "mygroup-3": {"user": "admin", "role": "client", "public_ips": ["34.243.147.221"]} + } +} +""" + + +@pytest.fixture +def cloud_state(tmp_path, monkeypatch): + state_path = tmp_path / "cloud_state.json" + state_path.write_text(CLOUD_STATE_JSON) + monkeypatch.setattr(commands, "CLOUD_STATE_FPATH", str(state_path)) + return state_path + + +@pytest.fixture(autouse=True) +def fake_get_info(monkeypatch): + monkeypatch.setattr( + commands, "get_info", lambda host, users=None: DATA_BY_HOST[host] + ) + + +def render(hosts, capsys): + """Render the exact output cf-remote would print for these hosts.""" + for host in hosts: + print_info(DATA_BY_HOST[host]) + return capsys.readouterr().out + + +def test_info_without_hosts_shows_all_hubs(cloud_state, capsys): + expected = render([HUB_1, HUB_2], capsys) + + errors = commands.info(None) + actual = capsys.readouterr().out + + assert errors == 0 + assert actual == expected + + +def test_info_with_all_shows_every_host(cloud_state, capsys): + expected = render([HUB_1, HUB_2, CLIENT_1], capsys) + + errors = commands.info(None, all=True) + actual = capsys.readouterr().out + + assert errors == 0 + assert actual == expected