diff --git a/src/aleph_client/commands/instance/network.py b/src/aleph_client/commands/instance/network.py index 595450fb..2117a1fc 100644 --- a/src/aleph_client/commands/instance/network.py +++ b/src/aleph_client/commands/instance/network.py @@ -41,7 +41,7 @@ async def fetch_crn_info(node_url: str) -> dict | None: """ url = "" try: - base_url: str = sanitize_url(node_url.rstrip("/")) + base_url: str = sanitize_url(node_url) timeout = aiohttp.ClientTimeout(total=settings.HTTP_REQUEST_TIMEOUT) async with aiohttp.ClientSession(timeout=timeout) as session: info: dict diff --git a/src/aleph_client/commands/node.py b/src/aleph_client/commands/node.py index 7f0c3a9b..b8284bbe 100644 --- a/src/aleph_client/commands/node.py +++ b/src/aleph_client/commands/node.py @@ -124,17 +124,26 @@ def _filter_node( logger.debug(e) for node in core_info: try: - sanitized_url = node["address"] or sanitize_url(node["address"]) - if ( - (not active or (node["status"] == "linked" and node["score"] > 0)) - and (not address or node["owner"] == address) - and (not payg_receiver or node["stream_reward"] == payg_receiver) - and (not crn_url or (sanitized_url == node_url)) - and (not crn_hash or node["hash"] == crn_hash) - and (not ccn_hash or node["parent"] == ccn_hash) - ): - node["address"] = sanitized_url - result.append(node) + if "total_staked" in node: # CCN + if ( + (not active or (node["status"] == "active" and node["score"] > 0)) + and (not address or node["owner"] == address) + and (not ccn_hash or node["hash"] == ccn_hash) + ): + result.append(node) + elif "parent" in node: # CRN + sanitized_url = "address" in node and sanitize_url(node["address"]) + if sanitized_url: + node["address"] = sanitized_url + if ( + (not active or (node["status"] == "linked" and node["score"] > 0)) + and (not address or node["owner"] == address) + and (not payg_receiver or node["stream_reward"] == payg_receiver) + and (not crn_url or node["address"] == node_url) + and (not crn_hash or node["hash"] == crn_hash) + and (not ccn_hash or node["parent"] == ccn_hash) + ): + result.append(node) except Exception as e: logger.debug(e) return result @@ -148,12 +157,14 @@ def _show_core(node_info): table.add_column("Linked", style="#029AFF", justify="left") table.add_column("Creation Time", style="#029AFF", justify="center") table.add_column("Status", style="green", justify="right") + table.add_column("Item Hash", style="green", justify="center") for node in node_info: # Prevent escaping with name node_name = node["name"] node_name = _escape_and_normalize(node_name) node_name = _remove_ansi_escape(node_name) + node_hash = node["hash"] # Format Value creation_time = datetime.datetime.fromtimestamp(node["time"]).strftime("%Y-%m-%d %H:%M:%S") @@ -167,6 +178,7 @@ def _show_core(node_info): str(len(node["resource_nodes"])), creation_time, status, + node_hash, ) console = Console() @@ -212,13 +224,14 @@ async def core( json: bool = typer.Option(default=False, help="Print as json instead of rich table"), active: bool = typer.Option(default=False, help="Only show active nodes"), address: Optional[str] = typer.Option(default=None, help="Owner address to filter by"), + ccn_hash: Optional[str] = typer.Option(default=None, help="CCN hash to filter by"), debug: bool = False, ): """Get all core node (CCN) on aleph""" setup_logging(debug) core_info: NodeInfo = await _fetch_nodes() - core_info.core_node = _filter_node(core_info=core_info.core_node, active=active, address=address) + core_info.core_node = _filter_node(core_info=core_info.core_node, active=active, address=address, ccn_hash=ccn_hash) if not json: _show_core(node_info=core_info.core_node) diff --git a/src/aleph_client/utils.py b/src/aleph_client/utils.py index b8398490..4c61b6d7 100644 --- a/src/aleph_client/utils.py +++ b/src/aleph_client/utils.py @@ -172,4 +172,4 @@ def sanitize_url(url: str) -> str: f"({', '.join(FORBIDDEN_HOSTS)})" ) raise aiohttp.InvalidURL("Invalid URL host") - return url + return url.strip("/") diff --git a/tests/unit/mocks.py b/tests/unit/mocks.py index 7d132dc6..3da4c8a8 100644 --- a/tests/unit/mocks.py +++ b/tests/unit/mocks.py @@ -18,8 +18,8 @@ FAKE_VM_HASH = "ab12" * 16 FAKE_PROGRAM_HASH = "cd34" * 16 FAKE_PROGRAM_HASH_2 = "ef56" * 16 -FAKE_CRN_HASH = "2cdb78cf561c6f0f839edb817395d3b5ece20d89125c5afba658f9170d6932c8" -FAKE_CRN_URL = "https://dchq.staging.aleph.sh" +FAKE_CRN_HASH = "cb764fe80f76cd5ec395952263fcbf0f5d2cc0dfe1ed98c90e13734b3fb2df3e" +FAKE_CRN_URL = "https://coco-1.crn.aleph.sh" FAKE_FLOW_HASH = "0xfake_flow_hash" diff --git a/tests/unit/test_node.py b/tests/unit/test_node.py new file mode 100644 index 00000000..bae0aaf6 --- /dev/null +++ b/tests/unit/test_node.py @@ -0,0 +1,34 @@ +from __future__ import annotations + +import pytest + +from aleph_client.commands.node import compute, core + + +@pytest.mark.asyncio +async def test_node_core(capsys): + await core( + json=False, + active=True, + address=None, + ccn_hash=None, + debug=False, + ) + captured = capsys.readouterr() + assert "Core Channel Node Information" in captured.out + + +@pytest.mark.asyncio +async def test_node_compute(capsys): + await compute( + json=False, + active=True, + address=None, + payg_receiver=None, + crn_url=None, + crn_hash=None, + ccn_hash=None, + debug=False, + ) + captured = capsys.readouterr() + assert "Compute Node Information" in captured.out