// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.model.content; import com.yahoo.config.model.deploy.DeployState; import com.yahoo.config.model.deploy.TestProperties; import com.yahoo.vespa.config.content.FleetcontrollerConfig; import com.yahoo.vespa.model.test.utils.ApplicationPackageUtils; import com.yahoo.vespa.model.test.utils.VespaModelCreatorWithMockPkg; import org.junit.jupiter.api.Test; import static com.yahoo.config.model.test.TestUtil.joinLines; import static org.junit.jupiter.api.Assertions.assertEquals; public class FleetControllerClusterTest { private FleetcontrollerConfig parse(String xml, TestProperties props) { var deployStateBuilder = new DeployState.Builder().properties(props); var mockPkg = new VespaModelCreatorWithMockPkg(null, xml, ApplicationPackageUtils.generateSchemas("type1")); var model = mockPkg.create(deployStateBuilder); var builder = new FleetcontrollerConfig.Builder(); model.getConfig(builder, "admin/cluster-controllers/0/components/clustercontroller-storage-configurer"); return builder.build(); } private FleetcontrollerConfig parse(String xml) { return parse(xml, new TestProperties()); } @Test void testParameters() { var config = parse(""" 2 13 27 4 72 0.7 0.3 """, new TestProperties()); assertEquals(13 * 1000, config.init_progress_time()); assertEquals(27 * 1000, config.storage_transition_time()); assertEquals(4, config.max_premature_crashes()); assertEquals(72 * 1000, config.stable_state_time_period()); assertEquals(0.7, config.min_distributor_up_ratio(), 0.01); assertEquals(0.3, config.min_storage_up_ratio(), 0.01); assertEquals(7, config.ideal_distribution_bits()); } @Test void testDurationParameters() { var config = parse( "\n" + "\n" + " " + "\n" + "2\n" + " \n" + " \n" + " 13ms\n" + " \n" + " \n" + ""); assertEquals(13, config.init_progress_time()); } @Test void min_node_ratio_per_group_tuning_config_is_propagated() { var config = parse("" + "" + "" + "" + "2" + " \n" + " 0.75\n" + " \n" + ""); assertEquals(0.75, config.min_node_ratio_per_group(), 0.01); } @Test void min_node_ratio_per_group_is_implicitly_zero_when_omitted() { var config = getConfigForBasicCluster(); assertEquals(0.0, config.min_node_ratio_per_group(), 0.01); } @Test void default_cluster_feed_block_limits_are_set() { assertLimits(0.75, 0.8, getConfigForBasicCluster()); } @Test void resource_limits_can_be_set_in_tuning() { assertLimits(0.6, 0.7, getConfigForResourceLimitsTuning(0.6, 0.7)); assertLimits(0.6, 0.8, getConfigForResourceLimitsTuning(0.6, null)); assertLimits(0.75, 0.7, getConfigForResourceLimitsTuning(null, 0.7)); } private static final double DELTA = 0.00001; private void assertLimits(double expDisk, double expMemory, FleetcontrollerConfig config) { var limits = config.cluster_feed_block_limit(); assertEquals(3, limits.size()); assertEquals(expDisk, limits.get("disk"), DELTA); assertEquals(expMemory, limits.get("memory"), DELTA); assertEquals(0.9, limits.get("attribute-address-space"), DELTA); } private FleetcontrollerConfig getConfigForResourceLimitsTuning(Double diskLimit, Double memoryLimit) { return parse(joinLines("" + "" + "" + "" + "2" + "", " ", (diskLimit != null ? (" " + diskLimit + "") : ""), (memoryLimit != null ? (" " + memoryLimit + "") : ""), " ", "" + "")); } @Test void feature_flag_controls_min_node_ratio_per_group() { verifyFeatureFlagControlsMinNodeRatioPerGroup(0.0, new TestProperties()); verifyFeatureFlagControlsMinNodeRatioPerGroup(0.3, new TestProperties().setMinNodeRatioPerGroup(0.3)); } private void verifyFeatureFlagControlsMinNodeRatioPerGroup(double expRatio, TestProperties props) { var config = getConfigForBasicCluster(props); assertEquals(expRatio, config.min_node_ratio_per_group(), DELTA); } private FleetcontrollerConfig getConfigForBasicCluster(TestProperties props) { return parse("" + "" + "" + "" + "2" + "", props); } private FleetcontrollerConfig getConfigForBasicCluster() { return getConfigForBasicCluster(new TestProperties()); } }