Clan_lib: add filtering by tag to list API
This commit is contained in:
@@ -3,7 +3,6 @@ import logging
|
|||||||
|
|
||||||
from clan_lib.flake import Flake
|
from clan_lib.flake import Flake
|
||||||
from clan_lib.machines.actions import list_machines
|
from clan_lib.machines.actions import list_machines
|
||||||
from clan_lib.machines.list import query_machines_by_tags
|
|
||||||
|
|
||||||
from clan_cli.completions import add_dynamic_completer, complete_tags
|
from clan_cli.completions import add_dynamic_completer, complete_tags
|
||||||
|
|
||||||
@@ -13,12 +12,8 @@ log = logging.getLogger(__name__)
|
|||||||
def list_command(args: argparse.Namespace) -> None:
|
def list_command(args: argparse.Namespace) -> None:
|
||||||
flake: Flake = args.flake
|
flake: Flake = args.flake
|
||||||
|
|
||||||
if args.tags:
|
for name in list_machines(flake, opts={"filter": {"tags": args.tags}}):
|
||||||
for name in query_machines_by_tags(flake, args.tags):
|
print(name)
|
||||||
print(name)
|
|
||||||
else:
|
|
||||||
for name in list_machines(flake):
|
|
||||||
print(name)
|
|
||||||
|
|
||||||
|
|
||||||
def register_list_parser(parser: argparse.ArgumentParser) -> None:
|
def register_list_parser(parser: argparse.ArgumentParser) -> None:
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import sys
|
|||||||
|
|
||||||
from clan_lib.async_run import AsyncContext, AsyncOpts, AsyncRuntime
|
from clan_lib.async_run import AsyncContext, AsyncOpts, AsyncRuntime
|
||||||
from clan_lib.errors import ClanError
|
from clan_lib.errors import ClanError
|
||||||
from clan_lib.machines.list import list_full_machines
|
from clan_lib.machines.list import list_full_machines, query_machines_by_tags
|
||||||
from clan_lib.machines.machines import Machine
|
from clan_lib.machines.machines import Machine
|
||||||
from clan_lib.machines.suggestions import validate_machine_names
|
from clan_lib.machines.suggestions import validate_machine_names
|
||||||
from clan_lib.machines.update import deploy_machine
|
from clan_lib.machines.update import deploy_machine
|
||||||
@@ -16,7 +16,6 @@ from clan_cli.completions import (
|
|||||||
complete_machines,
|
complete_machines,
|
||||||
complete_tags,
|
complete_tags,
|
||||||
)
|
)
|
||||||
from clan_cli.machines.list import query_machines_by_tags
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
from typing import TypedDict
|
||||||
|
|
||||||
from clan_lib.api import API
|
from clan_lib.api import API
|
||||||
from clan_lib.errors import ClanError
|
from clan_lib.errors import ClanError
|
||||||
@@ -10,15 +11,44 @@ from clan_lib.persist.inventory_store import InventoryStore
|
|||||||
from clan_lib.persist.util import set_value_by_path
|
from clan_lib.persist.util import set_value_by_path
|
||||||
|
|
||||||
|
|
||||||
|
class MachineFilter(TypedDict):
|
||||||
|
tags: list[str]
|
||||||
|
|
||||||
|
|
||||||
|
class ListOptions(TypedDict):
|
||||||
|
filter: MachineFilter
|
||||||
|
|
||||||
|
|
||||||
@API.register
|
@API.register
|
||||||
def list_machines(flake: Flake) -> dict[str, InventoryMachine]:
|
def list_machines(
|
||||||
|
flake: Flake, opts: ListOptions | None = None
|
||||||
|
) -> dict[str, InventoryMachine]:
|
||||||
"""
|
"""
|
||||||
List machines in the inventory for the UI.
|
List machines of a clan
|
||||||
|
|
||||||
|
Usage Example:
|
||||||
|
|
||||||
|
machines = list_machines(flake, {"filter": {"tags": ["foo" "bar"]}})
|
||||||
|
|
||||||
|
lists only machines that include both "foo" AND "bar"
|
||||||
|
|
||||||
"""
|
"""
|
||||||
inventory_store = InventoryStore(flake=flake)
|
inventory_store = InventoryStore(flake=flake)
|
||||||
inventory = inventory_store.read()
|
inventory = inventory_store.read()
|
||||||
|
|
||||||
machines = inventory.get("machines", {})
|
machines = inventory.get("machines", {})
|
||||||
|
|
||||||
|
if opts and opts.get("filter"):
|
||||||
|
filtered_machines = {}
|
||||||
|
filter_tags = opts.get("filter", {}).get("tags", [])
|
||||||
|
|
||||||
|
for machine_name, machine in machines.items():
|
||||||
|
machine_tags = machine.get("tags", [])
|
||||||
|
if all(ft in machine_tags for ft in filter_tags):
|
||||||
|
filtered_machines[machine_name] = machine
|
||||||
|
|
||||||
|
return filtered_machines
|
||||||
|
|
||||||
return machines
|
return machines
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -31,21 +31,21 @@ def list_full_machines(flake: Flake) -> dict[str, Machine]:
|
|||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
# TODO: Add filter to list_machines -> list_machines(flake, filter={tags=...})
|
def query_machines_by_tags(
|
||||||
def query_machines_by_tags(flake: Flake, tags: list[str]) -> dict[str, Machine]:
|
flake: Flake, tags: list[str]
|
||||||
|
) -> dict[str, InventoryMachine]:
|
||||||
"""
|
"""
|
||||||
Query machines by their respective tags, if multiple tags are specified
|
Query machines by their respective tags, if multiple tags are specified
|
||||||
then only machines that have those respective tags specified will be listed.
|
then only machines that have those respective tags specified will be listed.
|
||||||
It is an intersection of the tags and machines.
|
It is an intersection of the tags and machines.
|
||||||
"""
|
"""
|
||||||
machines = list_full_machines(flake)
|
machines = list_machines(flake)
|
||||||
|
|
||||||
filtered_machines = {}
|
filtered_machines = {}
|
||||||
for machine in machines.values():
|
for machine_name, machine in machines.items():
|
||||||
inv_machine = get_machine(machine.flake, machine.name)
|
machine_tags = machine.get("tags", [])
|
||||||
machine_tags = inv_machine.get("tags", [])
|
|
||||||
if all(tag in machine_tags for tag in tags):
|
if all(tag in machine_tags for tag in tags):
|
||||||
filtered_machines[machine.name] = machine
|
filtered_machines[machine_name] = machine
|
||||||
|
|
||||||
return filtered_machines
|
return filtered_machines
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user