aboutsummaryrefslogtreecommitdiffstats
path: root/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/TrafficShareUpdaterTest.java
blob: 08af46d8d33ded48faf46011f7e6d4bb3ddee2f3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.maintenance;

import com.yahoo.component.Version;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.zone.ZoneId;
import com.yahoo.vespa.hosted.controller.api.application.v4.model.ClusterMetrics;
import com.yahoo.vespa.hosted.controller.api.identifiers.DeploymentId;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType;
import com.yahoo.vespa.hosted.controller.application.pkg.ApplicationPackage;
import com.yahoo.vespa.hosted.controller.deployment.DeploymentTester;
import com.yahoo.vespa.hosted.controller.integration.NodeRepositoryMock;
import org.junit.Test;

import java.time.Duration;
import java.util.Map;

import static org.junit.Assert.assertEquals;

/**
 * Tests the traffic fraction updater. This also tests its dependency on DeploymentMetricsMaintainer.
 *
 * @author bratseth
 */
public class TrafficShareUpdaterTest {

    @Test
    public void testTrafficUpdater() {
        DeploymentTester tester = new DeploymentTester();
        var application = tester.newDeploymentContext();
        var deploymentMetricsMaintainer = new DeploymentMetricsMaintainer(tester.controller(), Duration.ofDays(1));
        var updater = new TrafficShareUpdater(tester.controller(), Duration.ofDays(1));
        ZoneId prod1 = ZoneId.from("prod", "ap-northeast-1");
        ZoneId prod2 = ZoneId.from("prod", "us-east-3");
        ZoneId prod3 = ZoneId.from("prod", "us-west-1");
        application.runJob(JobType.productionApNortheast1, new ApplicationPackage(new byte[0]), Version.fromString("7.1"));

        // Single zone
        setQpsMetric(50.0, application.application().id().defaultInstance(), prod1, tester);
        deploymentMetricsMaintainer.maintain();
        assertEquals(1.0, updater.maintain(), 0.0000001);
        assertTrafficFraction(1.0, 1.0, application.instanceId(), prod1, tester);

        // Two zones
        application.runJob(JobType.productionUsEast3, new ApplicationPackage(new byte[0]), Version.fromString("7.1"));
        // - one cold
        setQpsMetric(50.0, application.application().id().defaultInstance(), prod1, tester);
        setQpsMetric(0.0, application.application().id().defaultInstance(), prod2, tester);
        deploymentMetricsMaintainer.maintain();
        assertEquals(1.0, updater.maintain(), 0.0000001);
        assertTrafficFraction(1.0, 1.0, application.instanceId(), prod1, tester);
        assertTrafficFraction(0.0, 1.0, application.instanceId(), prod2, tester);
        // - both hot
        setQpsMetric(53.0, application.application().id().defaultInstance(), prod1, tester);
        setQpsMetric(47.0, application.application().id().defaultInstance(), prod2, tester);
        deploymentMetricsMaintainer.maintain();
        assertEquals(1.0, updater.maintain(), 0.0000001);
        assertTrafficFraction(0.53, 1.0, application.instanceId(), prod1, tester);
        assertTrafficFraction(0.47, 1.0, application.instanceId(), prod2, tester);

        // Three zones
        application.runJob(JobType.productionUsWest1, new ApplicationPackage(new byte[0]), Version.fromString("7.1"));
        // - one cold
        setQpsMetric(53.0, application.application().id().defaultInstance(), prod1, tester);
        setQpsMetric(47.0, application.application().id().defaultInstance(), prod2, tester);
        setQpsMetric(0.0, application.application().id().defaultInstance(), prod3, tester);
        deploymentMetricsMaintainer.maintain();
        assertEquals(1.0, updater.maintain(), 0.0000001);
        assertTrafficFraction(0.53, 0.53, application.instanceId(), prod1, tester);
        assertTrafficFraction(0.47, 0.50, application.instanceId(), prod2, tester);
        assertTrafficFraction(0.00, 0.50, application.instanceId(), prod3, tester);
        // - all hot
        setQpsMetric( 50.0, application.application().id().defaultInstance(), prod1, tester);
        setQpsMetric(25.0, application.application().id().defaultInstance(), prod2, tester);
        setQpsMetric(25.0, application.application().id().defaultInstance(), prod3, tester);
        deploymentMetricsMaintainer.maintain();
        assertEquals(1.0, updater.maintain(), 0.0000001);
        assertTrafficFraction(0.50, 0.5, application.instanceId(), prod1, tester);
        assertTrafficFraction(0.25, 0.5, application.instanceId(), prod2, tester);
        assertTrafficFraction(0.25, 0.5, application.instanceId(), prod3, tester);
    }

    private void setQpsMetric(double qps, ApplicationId application, ZoneId zone, DeploymentTester tester) {
        var clusterMetrics = new ClusterMetrics("default", "container", Map.of(ClusterMetrics.QUERIES_PER_SECOND, qps), Map.of());
        tester.controllerTester().serviceRegistry().configServerMock().setMetrics(new DeploymentId(application, zone), clusterMetrics);
    }

    private void assertTrafficFraction(double currentReadShare, double maxReadShare,
                                       ApplicationId application, ZoneId zone, DeploymentTester tester) {
        NodeRepositoryMock mock = (NodeRepositoryMock)tester.controller().serviceRegistry().configServer().nodeRepository();
        assertEquals(currentReadShare, mock.getTrafficFraction(application, zone).getFirst(), 0.00001);
        assertEquals(maxReadShare, mock.getTrafficFraction(application, zone).getSecond(), 0.00001);
    }

}