|
27 | 27 | FSX_SUPPORTED_ARCHITECTURES_OSES, |
28 | 28 | LOGFILE_LOGGER, |
29 | 29 | architecture_os_validator, |
| 30 | + check_usage_class, |
| 31 | + cluster_type_validator, |
30 | 32 | compute_resource_validator, |
31 | 33 | disable_hyperthreading_architecture_validator, |
32 | 34 | efa_gdr_validator, |
33 | 35 | efa_os_arch_validator, |
34 | 36 | fsx_ignored_parameters_validator, |
35 | 37 | instances_architecture_compatibility_validator, |
36 | 38 | intel_hpc_architecture_validator, |
| 39 | + queue_compute_type_validator, |
37 | 40 | queue_validator, |
38 | 41 | settings_validator, |
39 | 42 | ) |
@@ -2808,3 +2811,96 @@ def test_efa_os_arch_validator(mocker, cluster_dict, architecture, expected_erro |
2808 | 2811 | def test_ebs_volume_throughput_validator(mocker, section_dict, expected_message): |
2809 | 2812 | config_parser_dict = {"cluster default": {"ebs_settings": "default"}, "ebs default": section_dict} |
2810 | 2813 | utils.assert_param_validator(mocker, config_parser_dict, expected_message) |
| 2814 | + |
| 2815 | + |
| 2816 | +@pytest.mark.parametrize( |
| 2817 | + "usage_class, supported_usage_classes, expected_error_message, expected_warning_message", |
| 2818 | + [ |
| 2819 | + ("ondemand", ["ondemand", "spot"], None, None), |
| 2820 | + ("spot", ["ondemand", "spot"], None, None), |
| 2821 | + ("ondemand", ["ondemand"], None, None), |
| 2822 | + ("spot", ["spot"], None, None), |
| 2823 | + ("spot", [], None, "Could not check support for usage class 'spot' with instance type 'instance-type'"), |
| 2824 | + ("ondemand", [], None, "Could not check support for usage class 'ondemand' with instance type 'instance-type'"), |
| 2825 | + ("spot", ["ondemand"], "Usage type 'spot' not supported with instance type 'instance-type'", None), |
| 2826 | + ("ondemand", ["spot"], "Usage type 'ondemand' not supported with instance type 'instance-type'", None), |
| 2827 | + ], |
| 2828 | +) |
| 2829 | +def test_check_usage_class( |
| 2830 | + mocker, usage_class, supported_usage_classes, expected_error_message, expected_warning_message |
| 2831 | +): |
| 2832 | + # This test checks the common logic triggered from cluster_type_validator and queue_compute_type_validator. |
| 2833 | + instance_type_info_mock = mocker.MagicMock() |
| 2834 | + mocker.patch( |
| 2835 | + "pcluster.config.cfn_param_types.InstanceTypeInfo.init_from_instance_type", return_value=instance_type_info_mock |
| 2836 | + ) |
| 2837 | + instance_type_info_mock.supported_usage_classes.return_value = supported_usage_classes |
| 2838 | + |
| 2839 | + errors = [] |
| 2840 | + warnings = [] |
| 2841 | + check_usage_class("instance-type", usage_class, errors, warnings) |
| 2842 | + |
| 2843 | + if expected_error_message: |
| 2844 | + assert_that(errors).contains(expected_error_message) |
| 2845 | + else: |
| 2846 | + assert_that(errors).is_empty() |
| 2847 | + |
| 2848 | + if expected_warning_message: |
| 2849 | + assert_that(warnings).contains(expected_warning_message) |
| 2850 | + else: |
| 2851 | + assert_that(warnings).is_empty() |
| 2852 | + |
| 2853 | + |
| 2854 | +@pytest.mark.parametrize( |
| 2855 | + "scheduler, expected_usage_class_check", [("sge", True), ("torque", True), ("slurm", True), ("awsbatch", False)] |
| 2856 | +) |
| 2857 | +def test_cluster_type_validator(mocker, scheduler, expected_usage_class_check): |
| 2858 | + # Usage class validation logic is tested in `test_check_usage_class`. |
| 2859 | + # This test only makes sure that the logic is triggered from validator. |
| 2860 | + mock = mocker.patch("pcluster.config.validators.check_usage_class", return_value=None) |
| 2861 | + cluster_dict = {"compute_instance_type": "t2.micro", "scheduler": scheduler} |
| 2862 | + config_parser_dict = {"cluster default": cluster_dict} |
| 2863 | + config_parser = configparser.ConfigParser() |
| 2864 | + config_parser.read_dict(config_parser_dict) |
| 2865 | + |
| 2866 | + pcluster_config = utils.init_pcluster_config_from_configparser(config_parser, False, auto_refresh=False) |
| 2867 | + errors, warnings = cluster_type_validator("compute_type", "spot", pcluster_config) |
| 2868 | + if expected_usage_class_check: |
| 2869 | + mock.assert_called_with("t2.micro", "spot", [], []) |
| 2870 | + else: |
| 2871 | + mock.assert_not_called() |
| 2872 | + |
| 2873 | + assert_that(errors).is_equal_to([]) |
| 2874 | + assert_that(warnings).is_equal_to([]) |
| 2875 | + |
| 2876 | + |
| 2877 | +@pytest.mark.parametrize("compute_type", [("ondemand"), ("spot")]) |
| 2878 | +def test_queue_compute_type_validator(mocker, compute_type): |
| 2879 | + # Usage class validation logic is tested in `test_check_usage_class`. |
| 2880 | + # This test only makes sure that the logic is triggered from validator. |
| 2881 | + mock = mocker.patch("pcluster.config.validators.check_usage_class", return_value=None) |
| 2882 | + |
| 2883 | + config_parser_dict = { |
| 2884 | + "cluster default": { |
| 2885 | + "queue_settings": "q1", |
| 2886 | + }, |
| 2887 | + "queue q1": {"compute_resource_settings": "q1cr1, q1cr2", "compute_type": compute_type}, |
| 2888 | + "compute_resource q1cr1": {"instance_type": "q1cr1_instance_type"}, |
| 2889 | + "compute_resource q1cr2": {"instance_type": "q1cr2_instance_type"}, |
| 2890 | + } |
| 2891 | + |
| 2892 | + config_parser = configparser.ConfigParser() |
| 2893 | + config_parser.read_dict(config_parser_dict) |
| 2894 | + |
| 2895 | + pcluster_config = utils.init_pcluster_config_from_configparser(config_parser, False, auto_refresh=False) |
| 2896 | + errors, warnings = queue_compute_type_validator("queue", "q1", pcluster_config) |
| 2897 | + mock.assert_has_calls( |
| 2898 | + [ |
| 2899 | + mocker.call("q1cr1_instance_type", compute_type, [], []), |
| 2900 | + mocker.call("q1cr2_instance_type", compute_type, [], []), |
| 2901 | + ], |
| 2902 | + any_order=True, |
| 2903 | + ) |
| 2904 | + |
| 2905 | + assert_that(errors).is_equal_to([]) |
| 2906 | + assert_that(warnings).is_equal_to([]) |
0 commit comments