|
1 | | -from unittest.mock import Mock, patch |
| 1 | +from unittest.mock import patch |
2 | 2 |
|
3 | 3 | import pytest |
4 | 4 | from httpx import AsyncClient |
5 | 5 | from sqlalchemy.ext.asyncio import AsyncSession |
6 | 6 |
|
7 | | -from dstack._internal.core.errors import DstackError |
8 | 7 | from dstack._internal.core.models.backends.base import BackendType |
9 | 8 | from dstack._internal.core.models.users import GlobalRole, ProjectRole |
10 | 9 | from dstack._internal.server.services.projects import add_project_member |
11 | 10 | from dstack._internal.server.testing.common import ( |
12 | | - ComputeMockSpec, |
13 | 11 | clear_events, |
14 | 12 | create_backend, |
15 | 13 | create_gateway, |
@@ -457,7 +455,9 @@ async def test_only_admin_can_delete( |
457 | 455 |
|
458 | 456 | @pytest.mark.asyncio |
459 | 457 | @pytest.mark.parametrize("test_db", ["sqlite", "postgres"], indirect=True) |
460 | | - async def test_delete_gateway(self, test_db, session: AsyncSession, client: AsyncClient): |
| 458 | + async def test_marks_gateways_to_be_deleted( |
| 459 | + self, test_db, session: AsyncSession, client: AsyncClient |
| 460 | + ): |
461 | 461 | user = await create_user(session, global_role=GlobalRole.USER) |
462 | 462 | project = await create_project(session) |
463 | 463 | await add_project_member( |
@@ -487,68 +487,36 @@ async def test_delete_gateway(self, test_db, session: AsyncSession, client: Asyn |
487 | 487 | name="gateway-gcp", |
488 | 488 | gateway_compute_id=gateway_compute_gcp.id, |
489 | 489 | ) |
490 | | - with patch( |
491 | | - "dstack._internal.server.services.gateways.get_project_backend_by_type_or_error" |
492 | | - ) as m: |
493 | | - aws = Mock() |
494 | | - aws.compute.return_value = Mock(spec=ComputeMockSpec) |
495 | | - aws.compute.return_value.terminate_gateway.return_value = None # success |
496 | | - gcp = Mock() |
497 | | - gcp.compute.return_value = Mock(spec=ComputeMockSpec) |
498 | | - gcp.compute.return_value.terminate_gateway.side_effect = DstackError() # fail |
499 | | - |
500 | | - def get_backend(project, backend_type): |
501 | | - return {BackendType.AWS: aws, BackendType.GCP: gcp}[backend_type] |
502 | | - |
503 | | - m.side_effect = get_backend |
| 490 | + response = await client.post( |
| 491 | + f"/api/project/{project.name}/gateways/delete", |
| 492 | + json={"names": [gateway_aws.name, gateway_gcp.name]}, |
| 493 | + headers=get_auth_headers(user.token), |
| 494 | + ) |
| 495 | + assert response.status_code == 200 |
504 | 496 |
|
505 | | - response = await client.post( |
506 | | - f"/api/project/{project.name}/gateways/delete", |
507 | | - json={"names": [gateway_aws.name, gateway_gcp.name]}, |
508 | | - headers=get_auth_headers(user.token), |
509 | | - ) |
510 | | - aws.compute.return_value.terminate_gateway.assert_called_once() |
511 | | - gcp.compute.return_value.terminate_gateway.assert_called_once() |
512 | | - assert response.status_code == 200 |
| 497 | + await session.refresh(gateway_aws) |
| 498 | + await session.refresh(gateway_gcp) |
| 499 | + await session.refresh(gateway_compute_aws) |
| 500 | + await session.refresh(gateway_compute_gcp) |
| 501 | + assert gateway_aws.to_be_deleted is True |
| 502 | + assert gateway_gcp.to_be_deleted is True |
| 503 | + assert gateway_compute_aws.active is True |
| 504 | + assert gateway_compute_aws.deleted is False |
| 505 | + assert gateway_compute_gcp.active is True |
| 506 | + assert gateway_compute_gcp.deleted is False |
513 | 507 |
|
514 | 508 | response = await client.post( |
515 | 509 | f"/api/project/{project.name}/gateways/list", |
516 | 510 | headers=get_auth_headers(user.token), |
517 | 511 | ) |
518 | 512 | assert response.status_code == 200 |
519 | | - assert response.json() == [ |
520 | | - { |
521 | | - "id": str(gateway_gcp.id), |
522 | | - "backend": backend_gcp.type.value, |
523 | | - "created_at": response.json()[0]["created_at"], |
524 | | - "default": False, |
525 | | - "status": "submitted", |
526 | | - "status_message": None, |
527 | | - "instance_id": gateway_compute_gcp.instance_id, |
528 | | - "ip_address": gateway_compute_gcp.ip_address, |
529 | | - "hostname": gateway_compute_gcp.ip_address, |
530 | | - "name": gateway_gcp.name, |
531 | | - "region": gateway_gcp.region, |
532 | | - "wildcard_domain": gateway_gcp.wildcard_domain, |
533 | | - "configuration": { |
534 | | - "type": "gateway", |
535 | | - "name": gateway_gcp.name, |
536 | | - "backend": backend_gcp.type.value, |
537 | | - "region": gateway_gcp.region, |
538 | | - "instance_type": None, |
539 | | - "router": None, |
540 | | - "domain": gateway_gcp.wildcard_domain, |
541 | | - "default": False, |
542 | | - "public_ip": True, |
543 | | - "certificate": {"type": "lets-encrypt"}, |
544 | | - "tags": None, |
545 | | - }, |
546 | | - } |
547 | | - ] |
| 513 | + assert {g["name"] for g in response.json()} == {"gateway-aws", "gateway-gcp"} |
| 514 | + |
548 | 515 | events = await list_events(session) |
549 | | - assert len(events) == 1 |
550 | | - assert events[0].message == "Gateway deleted" |
551 | | - assert events[0].targets[0].entity_name == "gateway-aws" |
| 516 | + assert len(events) == 2 |
| 517 | + assert all(e.message == "Gateway marked for deletion" for e in events) |
| 518 | + assert {e.targets[0].entity_name for e in events} == {"gateway-aws", "gateway-gcp"} |
| 519 | + assert all(e.actor_user_id == user.id for e in events) |
552 | 520 |
|
553 | 521 |
|
554 | 522 | class TestUpdateGateway: |
|
0 commit comments