Skip to content

Commit

Permalink
Allow node search with tags (#64)
Browse files Browse the repository at this point in the history
  • Loading branch information
jschlyter authored Jan 13, 2025
1 parent 7441503 commit 71b6a62
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 3 deletions.
14 changes: 11 additions & 3 deletions nodeman/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from fastapi import APIRouter, Depends, Header, HTTPException, Request, Response, status
from jwcrypto.jwk import JWK
from jwcrypto.jws import JWS, InvalidJWSSignature
from mongoengine import Q
from opentelemetry import metrics, trace
from pydantic_core import ValidationError

Expand Down Expand Up @@ -205,11 +206,18 @@ def get_node_information(name: str, username: Annotated[str, Depends(get_current
status.HTTP_200_OK: {"model": NodeCollection},
},
tags=["backend"],
response_model_exclude_none=False,
)
def get_all_nodes(username: Annotated[str, Depends(get_current_username)]) -> NodeCollection:
def get_all_nodes(username: Annotated[str, Depends(get_current_username)], tags: str | None = None) -> NodeCollection:
"""Get all nodes"""
logging.info("%s queried for all nodes", username, extra={"username": username})
return NodeCollection(nodes=[NodeInformation.from_db_model(node) for node in TapirNode.objects(deleted=None)])
query = Q(deleted=None)
if tags:
query_tags = sorted(set(tags.split(",")))
logging.info("%s queried for nodes with tags %s", username, query_tags, extra={"username": username})
query &= Q(tags__all=sorted(set(query_tags)))
else:
logging.info("%s queried for all nodes", username, extra={"username": username})
return NodeCollection(nodes=[NodeInformation.from_db_model(node) for node in TapirNode.objects(query)])


@router.get(
Expand Down
30 changes: 30 additions & 0 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from nodeman.x509 import RSA_EXPONENT, CertificateAuthorityClient, generate_ca_certificate, generate_x509_csr

ADMIN_TEST_NODE_COUNT = 100
ADMIN_TEST_NODE_COUNT_TAGS = 10
BACKEND_CREDENTIALS = ("username", "password")

PrivateKey = ec.EllipticCurvePrivateKey | rsa.RSAPublicKey | Ed25519PrivateKey | Ed448PrivateKey
Expand Down Expand Up @@ -407,6 +408,35 @@ def test_admin() -> None:
assert response.status_code == status.HTTP_204_NO_CONTENT


def test_admin_tags() -> None:
client = get_test_client()
client.auth = BACKEND_CREDENTIALS

server = ""

for node_number in range(ADMIN_TEST_NODE_COUNT_TAGS):
tags = ["odd"] if node_number % 2 else ["even"]
if node_number == 0:
tags.append("zero")
response = client.post(urljoin(server, "/api/v1/node"), json={"tags": tags})
assert response.status_code == status.HTTP_201_CREATED

# half of the nodes should have tag even
response = client.get(urljoin(server, "/api/v1/nodes"), params={"tags": "even"})
assert response.status_code == status.HTTP_200_OK
assert len(response.json()["nodes"]) == ADMIN_TEST_NODE_COUNT_TAGS // 2

# exactly one node should have tags even & zero
response = client.get(urljoin(server, "/api/v1/nodes"), params={"tags": "even,zero"})
assert response.status_code == status.HTTP_200_OK
assert len(response.json()["nodes"]) == 1

# no nodes should have both tags even & odd
response = client.get(urljoin(server, "/api/v1/nodes"), params={"tags": "even,odd"})
assert response.status_code == status.HTTP_200_OK
assert len(response.json()["nodes"]) == 0


def test_backend_authentication() -> None:
client = get_test_client()
server = ""
Expand Down

0 comments on commit 71b6a62

Please sign in to comment.