Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨Adding new cli option to debug internal status of director-v2 #4963

Merged
merged 3 commits into from
Nov 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from tenacity.stop import stop_after_delay
from tenacity.wait import wait_random_exponential

from ...models.dynamic_services_scheduler import SchedulerData
from ...modules.dynamic_sidecar.scheduler import DynamicSidecarsScheduler
from ...utils.routes import NoContentResponse
from ..dependencies.dynamic_sidecar import get_dynamic_sidecar_scheduler
Expand Down Expand Up @@ -121,6 +122,24 @@ async def _progress_callback(
raise HTTPException(status.HTTP_409_CONFLICT, detail=f"{e}") from e


@router.get(
"/services/{node_uuid}/state",
summary="Returns the internals of the scheduler for the given service",
status_code=status.HTTP_200_OK,
response_model=SchedulerData,
)
async def get_service_state(
node_uuid: NodeID,
dynamic_sidecars_scheduler: Annotated[
DynamicSidecarsScheduler, Depends(get_dynamic_sidecar_scheduler)
],
):
# pylint: disable=protected-access
return dynamic_sidecars_scheduler._scheduler.get_scheduler_data(
node_uuid
) # noqa: SLF001


@router.post(
"/services/{node_uuid}/state:save",
summary="Starts the saving of the state for the service",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from ..core.settings import AppSettings
from ..meta import PROJECT_NAME
from ._close_and_save_service import async_close_and_save_service
from ._core import async_project_save_state, async_project_state
from ._core import async_project_save_state, async_project_state, async_service_state

DEFAULT_NODE_SAVE_ATTEMPTS: Final[int] = 3
DEFAULT_STATE_UPDATE_INTERVAL_S: Final[int] = 5
Expand Down Expand Up @@ -50,6 +50,14 @@ def project_state(
asyncio.run(async_project_state(project_id, blocking, update_interval))


@main.command()
def service_state(node_id: NodeID):
"""
Prints the state of a services as tracked by director-v2
"""
asyncio.run(async_service_state(node_id))


@main.command()
def close_and_save_service(
node_id: NodeID,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,8 @@ async def delete_service_docker_resources(self, node_uuid: str) -> Response:
return await self.client.delete(
self._get_url(f"/services/{node_uuid}/docker-resources")
)

@retry_on_errors
@expect_status(status.HTTP_200_OK)
async def get_service_state(self, node_uuid: str) -> Response:
return await self.client.get(self._get_url(f"/services/{node_uuid}/state"))
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from ..modules.dynamic_sidecar import api_client
from ..modules.projects_networks import requires_dynamic_sidecar
from ..utils.db import get_repository
from ._client import ThinDV2LocalhostClient


@asynccontextmanager
Expand Down Expand Up @@ -273,3 +274,9 @@ async def async_project_state(
await _display(
app, project_id, update_interval=update_interval, blocking=blocking
)


async def async_service_state(node_id: NodeID) -> None:
thin_dv2_localhost_client = ThinDV2LocalhostClient()
result = await thin_dv2_localhost_client.get_service_state(node_id)
typer.echo(f"Service state: {result.text}")
11 changes: 11 additions & 0 deletions services/director-v2/tests/unit/with_dbs/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ async def mock_close_service_routes(
respx_mock.post(
re.compile(f"{regex_base}/state:save"), name="save_service_state"
).respond(status_code=status.HTTP_202_ACCEPTED, json=task_id)
respx_mock.get(
re.compile(f"{regex_base}/state"), name="service_internal_state"
).respond(status_code=status.HTTP_200_OK)
respx_mock.post(
re.compile(f"{regex_base}/outputs:push"), name="push_service_outputs"
).respond(status_code=status.HTTP_202_ACCEPTED, json=task_id)
Expand Down Expand Up @@ -235,3 +238,11 @@ def test_close_and_save_service(
result = cli_runner.invoke(main, ["close-and-save-service", f"{node_id}"])
assert result.exit_code == os.EX_OK, _format_cli_error(result)
print(result.stdout)


def test_service_state(
mock_close_service_routes: None, cli_runner: CliRunner, node_id: NodeID
):
result = cli_runner.invoke(main, ["service-state", f"{node_id}"])
assert result.exit_code == os.EX_OK, _format_cli_error(result)
print(result.stdout)
Loading