This test verifies that allowing or denying an action will only result in a success or failure on specific operations but not other operations in an accept call. This is a regression test for MESOS-9474 and MESOS-9480.
| 2675 | // success or failure on specific operations but not other operations in an |
| 2676 | // accept call. This is a regression test for MESOS-9474 and MESOS-9480. |
| 2677 | TEST_P(MasterOperationAuthorizationTest, Accept) |
| 2678 | { |
| 2679 | Clock::pause(); |
| 2680 | |
| 2681 | const auto controllableApprover = |
| 2682 | std::make_shared<ControllableObjectApprover>(true); |
| 2683 | |
| 2684 | MockAuthorizer authorizer; |
| 2685 | |
| 2686 | const authorization::Action allowedAction = GetParam(); |
| 2687 | EXPECT_CALL(authorizer, getApprover(_, _)) |
| 2688 | .WillRepeatedly(Invoke([controllableApprover, allowedAction]( |
| 2689 | const Option<authorization::Subject>&, |
| 2690 | const authorization::Action& action) { |
| 2691 | return action == allowedAction ? getAcceptingObjectApprover() |
| 2692 | : controllableApprover; |
| 2693 | })); |
| 2694 | |
| 2695 | Try<Owned<cluster::Master>> master = StartMaster(&authorizer); |
| 2696 | ASSERT_SOME(master); |
| 2697 | |
| 2698 | // First, we create a list of operations to exercise all authorization |
| 2699 | // actions, and compute the total resources needed by these operations and set |
| 2700 | // up their expected terminal states. |
| 2701 | // |
| 2702 | // NOTE: We create some `RUN_TASK` operations in the beginning and some in the |
| 2703 | // end for two reasons: 1. These operations doesn't have operation IDs so |
| 2704 | // needs to be handled differently. 2. By adding some operations for the |
| 2705 | // `RUN_TASK` action in the end, we can verify that their results are not |
| 2706 | // affected by preceding authorizations. |
| 2707 | vector<v1::Offer::Operation> operations; |
| 2708 | v1::Resources totalResources; |
| 2709 | hashmap<v1::TaskID, v1::TaskState> expectedTaskStates; |
| 2710 | hashmap<v1::OperationID, v1::OperationState> expectedOperationStates; |
| 2711 | |
| 2712 | // NOTE: Because we create operations before getting an offer, we synthesize |
| 2713 | // the framework ID and agent ID here and check them later. |
| 2714 | v1::FrameworkID frameworkId; |
| 2715 | frameworkId.set_value(master.get()->getMasterInfo().id() + "-0000"); |
| 2716 | v1::AgentID agentId; |
| 2717 | agentId.set_value(master.get()->getMasterInfo().id() + "-S0"); |
| 2718 | |
| 2719 | auto addRunTaskOperations = [&] { |
| 2720 | foreach ( |
| 2721 | v1::Offer::Operation& operation, |
| 2722 | createOperations(frameworkId, agentId, authorization::RUN_TASK)) { |
| 2723 | if (operation.type() == v1::Offer::Operation::LAUNCH) { |
| 2724 | foreach (const v1::TaskInfo& task, operation.launch().task_infos()) { |
| 2725 | totalResources += task.resources(); |
| 2726 | totalResources += task.executor().resources(); |
| 2727 | |
| 2728 | expectedTaskStates.put( |
| 2729 | task.task_id(), |
| 2730 | authorization::RUN_TASK == GetParam() |
| 2731 | ? v1::TASK_FINISHED : v1::TASK_ERROR); |
| 2732 | } |
| 2733 | } else if (operation.type() == v1::Offer::Operation::LAUNCH_GROUP) { |
| 2734 | totalResources += operation.launch_group().executor().resources(); |
nothing calls this directly
no test coverage detected