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

Problem /about/usage/system was not tested #609

Merged
merged 9 commits into from
May 3, 2024
Merged
Show file tree
Hide file tree
Changes from 7 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
7 changes: 7 additions & 0 deletions .github/workflows/test-on-droplets-matrix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,13 @@ jobs:
-d '{"persistent_vms": [], "instances": ["${{ matrix.check_vm.item_hash }}"]}' \
"http://${DROPLET_IPV4}:4020/control/allocations"

- name: Fetch system usage endpoint
run: |
export DROPLET_IPV4="$(doctl compute droplet get aleph-vm-ci-${{ matrix.os_config.alias }}-${{ matrix.check_vm.alias }} --output json | ./.github/scripts/extract_droplet_ipv4.py)"
curl -X GET -H "Content-Type: application/json" \
"http://${DROPLET_IPV4}:4020/about/usage/system"


nesitor marked this conversation as resolved.
Show resolved Hide resolved
- name: Export aleph logs
if: always()
run: |
Expand Down
5 changes: 3 additions & 2 deletions src/aleph/vm/orchestrator/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ def get_machine_properties() -> MachineProperties:
cpu_info = cpuinfo.get_cpu_info() # Slow
return MachineProperties(
cpu=CpuProperties(
architecture=cpu_info["raw_arch_string"],
vendor=cpu_info["vendor_id"],
architecture=cpu_info.get("raw_arch_string", cpu_info.get("arch_string_raw")),
vendor=cpu_info.get("vendor_id", cpu_info.get("vendor_id_raw")),
nesitor marked this conversation as resolved.
Show resolved Hide resolved
),
)

Expand Down Expand Up @@ -118,6 +118,7 @@ async def about_system_usage(_: web.Request):
),
properties=get_machine_properties(),
)

return web.json_response(text=usage.json(exclude_none=True))


Expand Down
112 changes: 57 additions & 55 deletions src/aleph/vm/orchestrator/supervisor.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,62 +74,63 @@
return web.HTTPNotFound()


app = web.Application(middlewares=[server_version_middleware])
cors = setup(
app,
defaults={
"*": ResourceOptions(
allow_credentials=True,
expose_headers="*",
allow_headers="*",
)
},
)
def setup_webapp():
app = web.Application(middlewares=[server_version_middleware])
cors = setup(
app,
defaults={
"*": ResourceOptions(
allow_credentials=True,
expose_headers="*",
allow_headers="*",
)
},
)

# Routes that need CORS enabled
cors_routes = [
# /about APIs return information about the VM Orchestrator
web.get("/about/login", about_login),
web.get("/about/executions/list", list_executions),
web.get("/about/executions/details", about_executions),
web.get("/about/executions/records", about_execution_records),
web.get("/about/usage/system", about_system_usage),
web.get("/about/config", about_config),
# /control APIs are used to control the VMs and access their logs
web.post("/control/allocation/notify", notify_allocation),
web.get("/control/machine/{ref}/logs", stream_logs),
web.post("/control/machine/{ref}/expire", operate_expire),
web.post("/control/machine/{ref}/stop", operate_stop),
web.post("/control/machine/{ref}/erase", operate_erase),
web.post("/control/machine/{ref}/reboot", operate_reboot),
# /status APIs are used to check that the VM Orchestrator is running properly
web.get("/status/check/fastapi", status_check_fastapi),
web.get("/status/check/fastapi/legacy", status_check_fastapi_legacy),
web.get("/status/check/host", status_check_host),
web.get("/status/check/version", status_check_version),
web.get("/status/check/ipv6", status_check_ipv6),
web.get("/status/config", status_public_config),
]
routes = app.add_routes(cors_routes)
for route in routes:
cors.add(route)


# Routes that don't need CORS enabled
other_routes = [
# /control APIs are used to control the VMs and access their logs
web.post("/control/allocations", update_allocations),
# Raise an HTTP Error 404 if attempting to access an unknown URL within these paths.
web.get("/about/{suffix:.*}", http_not_found),
web.get("/control/{suffix:.*}", http_not_found),
web.get("/status/{suffix:.*}", http_not_found),
# /static is used to serve static files
web.static("/static", Path(__file__).parent / "views/static"),
# /vm is used to launch VMs on-demand
web.route("*", "/vm/{ref}{suffix:.*}", run_code_from_path),
web.route("*", "/{suffix:.*}", run_code_from_hostname),
]
app.add_routes(other_routes)
# Routes that need CORS enabled
cors_routes = [
# /about APIs return information about the VM Orchestrator
web.get("/about/login", about_login),
web.get("/about/executions/list", list_executions),
web.get("/about/executions/details", about_executions),
web.get("/about/executions/records", about_execution_records),
web.get("/about/usage/system", about_system_usage),
web.get("/about/config", about_config),
# /control APIs are used to control the VMs and access their logs
web.post("/control/allocation/notify", notify_allocation),
web.get("/control/machine/{ref}/logs", stream_logs),
web.post("/control/machine/{ref}/expire", operate_expire),
web.post("/control/machine/{ref}/stop", operate_stop),
web.post("/control/machine/{ref}/erase", operate_erase),
web.post("/control/machine/{ref}/reboot", operate_reboot),
# /status APIs are used to check that the VM Orchestrator is running properly
web.get("/status/check/fastapi", status_check_fastapi),
web.get("/status/check/fastapi/legacy", status_check_fastapi_legacy),
web.get("/status/check/host", status_check_host),
web.get("/status/check/version", status_check_version),
web.get("/status/check/ipv6", status_check_ipv6),
web.get("/status/config", status_public_config),
]
routes = app.add_routes(cors_routes)
for route in routes:
cors.add(route)

# Routes that don't need CORS enabled
other_routes = [
# /control APIs are used to control the VMs and access their logs
web.post("/control/allocations", update_allocations),
# Raise an HTTP Error 404 if attempting to access an unknown URL within these paths.
web.get("/about/{suffix:.*}", http_not_found),
web.get("/control/{suffix:.*}", http_not_found),
web.get("/status/{suffix:.*}", http_not_found),
# /static is used to serve static files
web.static("/static", Path(__file__).parent / "views/static"),
# /vm is used to launch VMs on-demand
web.route("*", "/vm/{ref}{suffix:.*}", run_code_from_path),
web.route("*", "/{suffix:.*}", run_code_from_hostname),
]
app.add_routes(other_routes)
return app


async def stop_all_vms(app: web.Application):
Expand All @@ -153,6 +154,7 @@

# Require a random token to access /about APIs
secret_token = token_urlsafe(nbytes=32)
app = setup_webapp()

Check warning on line 157 in src/aleph/vm/orchestrator/supervisor.py

View check run for this annotation

Codecov / codecov/patch

src/aleph/vm/orchestrator/supervisor.py#L157

Added line #L157 was not covered by tests
# Store app singletons. Note that app["pubsub"] will also be created.
app["secret_token"] = secret_token
app["vm_pool"] = pool
Expand Down
16 changes: 15 additions & 1 deletion tests/supervisor/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
from aiohttp import web

from aleph.vm.conf import settings
from aleph.vm.orchestrator.supervisor import app
from aleph.vm.orchestrator.supervisor import setup_webapp


@pytest.mark.asyncio
async def test_allocation_fails_on_invalid_item_hash(aiohttp_client):
"""Test that the allocation endpoint fails when an invalid item_hash is provided."""
app = setup_webapp()
client = await aiohttp_client(app)
settings.ALLOCATION_TOKEN_HASH = "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08" # = "test"
response: web.Response = await client.post(
Expand All @@ -24,3 +25,16 @@ async def test_allocation_fails_on_invalid_item_hash(aiohttp_client):
"type": "value_error.unknownhash",
},
]


@pytest.mark.asyncio
async def test_system_usage(aiohttp_client):
"""Test that the usage system endpoints responds. No auth needed"""
app = setup_webapp()
client = await aiohttp_client(app)
response: web.Response = await client.get("/about/usage/system")
assert response.status == 200
# check if it is valid json
resp = await response.json()
assert "cpu" in resp
assert resp["cpu"]["count"] > 0
nesitor marked this conversation as resolved.
Show resolved Hide resolved
Loading