|
18 | 18 |
|
19 | 19 | import datetime
|
20 | 20 | import itertools
|
| 21 | +import uuid |
21 | 22 | from collections import defaultdict
|
22 |
| -from typing import Any |
| 23 | +from typing import Any, Optional |
23 | 24 | from uuid import UUID
|
24 | 25 |
|
25 | 26 | import pytest
|
26 | 27 | from dateutil.tz import UTC
|
27 | 28 |
|
28 |
| -from inmanta import const, data |
| 29 | +from inmanta import const, data, util |
29 | 30 | from inmanta.const import ResourceState
|
30 |
| -from inmanta.data.model import ResourceVersionIdStr |
| 31 | +from inmanta.data.model import ResourceIdStr, ResourceVersionIdStr |
31 | 32 | from inmanta.util import parse_timestamp
|
32 | 33 |
|
33 | 34 |
|
@@ -491,3 +492,157 @@ async def test_resource_details(server, client, env_with_resources):
|
491 | 492 | assert result.result["data"]["status"] == "orphaned"
|
492 | 493 | await assert_matching_attributes(result.result["data"], resources[env.id][orphaned][0])
|
493 | 494 | assert result.result["data"]["requires_status"] == {"std::File[internal,path=/tmp/orphaned_req]": "orphaned"}
|
| 495 | + |
| 496 | + |
| 497 | +async def test_move_to_available_state(server, environment, client, clienthelper, agent): |
| 498 | + """ |
| 499 | + Verify that the endpoints, that return the state of a resource, return the correct state |
| 500 | + when a resource moved back to the available state. This state is not written back to the |
| 501 | + resource_persistent_state table and should be determined based on the content of the |
| 502 | + resource table. |
| 503 | + """ |
| 504 | + # Create model version1 |
| 505 | + version1 = await clienthelper.get_version() |
| 506 | + result = await client.put_version( |
| 507 | + tid=environment, |
| 508 | + version=version1, |
| 509 | + resources=[ |
| 510 | + { |
| 511 | + "id": f"std::testing::NullResource[agent1,name=test1],v={version1}", |
| 512 | + "val": "val1", |
| 513 | + "requires": [], |
| 514 | + }, |
| 515 | + { |
| 516 | + "id": f"std::testing::NullResource[agent1,name=test2],v={version1}", |
| 517 | + "val": "val2", |
| 518 | + "requires": [], |
| 519 | + }, |
| 520 | + { |
| 521 | + "id": f"std::testing::NullResource[agent1,name=test3],v={version1}", |
| 522 | + "val": "val3", |
| 523 | + "requires": [], |
| 524 | + }, |
| 525 | + { |
| 526 | + "id": f"std::testing::NullResource[agent1,name=test4],v={version1}", |
| 527 | + "val": "val4", |
| 528 | + "requires": [], |
| 529 | + }, |
| 530 | + { |
| 531 | + "id": f"std::testing::NullResource[agent1,name=test5],v={version1}", |
| 532 | + "val": "val5", |
| 533 | + "requires": [f"std::testing::NullResource[agent1,name=test4],v={version1}"], |
| 534 | + }, |
| 535 | + ], |
| 536 | + resource_state={"std::testing::NullResource[agent1,name=test4]": const.ResourceState.undefined}, |
| 537 | + compiler_version=util.get_compiler_version(), |
| 538 | + ) |
| 539 | + assert result.code == 200, result.result |
| 540 | + |
| 541 | + # Release version |
| 542 | + result = await client.release_version(tid=environment, id=version1) |
| 543 | + assert result.code == 200 |
| 544 | + |
| 545 | + # Move resources |
| 546 | + # * std::testing::NullResource[agent1,name=test1] |
| 547 | + # * std::testing::NullResource[agent1,name=test2] |
| 548 | + # to deployed state |
| 549 | + aclient = agent._client |
| 550 | + for i in range(1, 3): |
| 551 | + action_id = uuid.uuid4() |
| 552 | + result = await aclient.resource_deploy_start( |
| 553 | + tid=environment, |
| 554 | + rvid=f"std::testing::NullResource[agent1,name=test{i}],v={version1}", |
| 555 | + action_id=action_id, |
| 556 | + ) |
| 557 | + assert result.code == 200 |
| 558 | + result = await aclient.resource_deploy_done( |
| 559 | + tid=environment, |
| 560 | + rvid=f"std::testing::NullResource[agent1,name=test{i}],v={version1}", |
| 561 | + action_id=action_id, |
| 562 | + status=const.ResourceState.deployed, |
| 563 | + ) |
| 564 | + assert result.code == 200, result.result |
| 565 | + |
| 566 | + # Create a new version containing: |
| 567 | + # * an updated desired state for resource std::testing::NullResource[agent1,name=test1] |
| 568 | + # * A version of the std::testing::NullResource[agent1,name=test4] that is no longer undefined but available. |
| 569 | + version2 = await clienthelper.get_version() |
| 570 | + result = await client.put_version( |
| 571 | + tid=environment, |
| 572 | + version=version2, |
| 573 | + resources=[ |
| 574 | + { |
| 575 | + "id": f"std::testing::NullResource[agent1,name=test1],v={version2}", |
| 576 | + "val": "val1_updated", |
| 577 | + "requires": [], |
| 578 | + }, |
| 579 | + { |
| 580 | + "id": f"std::testing::NullResource[agent1,name=test2],v={version2}", |
| 581 | + "val": "val2", |
| 582 | + "requires": [], |
| 583 | + }, |
| 584 | + { |
| 585 | + "id": f"std::testing::NullResource[agent1,name=test3],v={version2}", |
| 586 | + "val": "val3", |
| 587 | + "requires": [], |
| 588 | + }, |
| 589 | + { |
| 590 | + "id": f"std::testing::NullResource[agent1,name=test4],v={version2}", |
| 591 | + "val": "val4", |
| 592 | + "requires": [], |
| 593 | + }, |
| 594 | + { |
| 595 | + "id": f"std::testing::NullResource[agent1,name=test5],v={version2}", |
| 596 | + "val": "val5", |
| 597 | + "requires": [f"std::testing::NullResource[agent1,name=test4],v={version2}"], |
| 598 | + }, |
| 599 | + ], |
| 600 | + resource_state={}, |
| 601 | + compiler_version=util.get_compiler_version(), |
| 602 | + ) |
| 603 | + assert result.code == 200, result.result |
| 604 | + |
| 605 | + async def assert_states(expected_states: dict[ResourceIdStr, const.ResourceState]) -> None: |
| 606 | + # Verify behavior of resource_details() endpoint. |
| 607 | + for rid, state in expected_states.items(): |
| 608 | + result = await client.resource_details(tid=environment, rid=rid) |
| 609 | + assert result.code == 200 |
| 610 | + assert ( |
| 611 | + result.result["data"]["status"] == state.value |
| 612 | + ), f"Got state {result.result['data']['status']} for resource {rid}, expected {state.value}" |
| 613 | + |
| 614 | + # Verify behavior of get_current_resource_state() endpoint |
| 615 | + resource_state: Optional[ResourceState] |
| 616 | + for rid, state in expected_states.items(): |
| 617 | + resource_state = await data.Resource.get_current_resource_state(env=uuid.UUID(environment), rid=rid) |
| 618 | + assert resource_state == state |
| 619 | + |
| 620 | + # Verify behavior of resource_list() endpoint |
| 621 | + result = await client.resource_list(tid=environment) |
| 622 | + assert result.code == 200 |
| 623 | + actual_states = {r["resource_id"]: const.ResourceState(r["status"]) for r in result.result["data"]} |
| 624 | + assert expected_states == actual_states |
| 625 | + |
| 626 | + await assert_states( |
| 627 | + { |
| 628 | + ResourceIdStr("std::testing::NullResource[agent1,name=test1]"): const.ResourceState.deployed, |
| 629 | + ResourceIdStr("std::testing::NullResource[agent1,name=test2]"): const.ResourceState.deployed, |
| 630 | + ResourceIdStr("std::testing::NullResource[agent1,name=test3]"): const.ResourceState.available, |
| 631 | + ResourceIdStr("std::testing::NullResource[agent1,name=test4]"): const.ResourceState.undefined, |
| 632 | + ResourceIdStr("std::testing::NullResource[agent1,name=test5]"): const.ResourceState.skipped_for_undefined, |
| 633 | + } |
| 634 | + ) |
| 635 | + |
| 636 | + # Release version2 |
| 637 | + result = await client.release_version(tid=environment, id=version2) |
| 638 | + assert result.code == 200 |
| 639 | + |
| 640 | + await assert_states( |
| 641 | + { |
| 642 | + ResourceIdStr("std::testing::NullResource[agent1,name=test1]"): const.ResourceState.available, |
| 643 | + ResourceIdStr("std::testing::NullResource[agent1,name=test2]"): const.ResourceState.deployed, |
| 644 | + ResourceIdStr("std::testing::NullResource[agent1,name=test3]"): const.ResourceState.available, |
| 645 | + ResourceIdStr("std::testing::NullResource[agent1,name=test4]"): const.ResourceState.available, |
| 646 | + ResourceIdStr("std::testing::NullResource[agent1,name=test5]"): const.ResourceState.available, |
| 647 | + } |
| 648 | + ) |
0 commit comments