aboutsummaryrefslogtreecommitdiffstats
path: root/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ExpeditedChangeApplicationMaintainerTest.java
blob: ab95de5f0bc17c756fef26155bcb9a6a74ce8f73 (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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.provision.maintenance;

import com.yahoo.component.Version;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ApplicationName;
import com.yahoo.config.provision.Capacity;
import com.yahoo.config.provision.ClusterResources;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.InstanceName;
import com.yahoo.config.provision.NodeResources;
import com.yahoo.config.provision.NodeType;
import com.yahoo.config.provision.TenantName;
import com.yahoo.test.ManualClock;
import com.yahoo.vespa.hosted.provision.Node;
import com.yahoo.vespa.hosted.provision.NodeRepository;
import com.yahoo.vespa.hosted.provision.node.Agent;
import com.yahoo.vespa.hosted.provision.provisioning.ProvisioningTester;
import com.yahoo.vespa.hosted.provision.testutils.MockDeployer;
import com.yahoo.vespa.service.duper.InfraApplication;
import org.junit.Test;

import java.time.Duration;
import java.util.List;

import static org.junit.Assert.assertEquals;

/**
 * @author bratseth
 */
public class ExpeditedChangeApplicationMaintainerTest {

    @Test
    public void test_application_maintenance() {
        NodeResources hostResources = new NodeResources(64, 128, 2000, 10);
        Fixture fixture = new Fixture();
        ManualClock clock = fixture.tester.clock();
        NodeRepository nodeRepository = fixture.nodeRepository;

        fixture.tester.makeReadyNodes(15, fixture.nodeResources);
        fixture.tester.makeReadyNodes(2, hostResources);
        fixture.tester.makeReadyNodes(2, fixture.nodeResources, NodeType.proxy);

        // Create applications
        fixture.activate();
        assertEquals("Initial applications are deployed", 3, fixture.deployer.activations);
        ExpeditedChangeApplicationMaintainer maintainer = new ExpeditedChangeApplicationMaintainer(fixture.deployer,
                                                                                                   new TestMetric(),
                                                                                                   nodeRepository,
                                                                                                   Duration.ofMinutes(1));
        
        clock.advance(Duration.ofMinutes(2));
        maintainer.maintain();
        assertEquals("No changes -> no redeployments", 3, fixture.deployer.activations);

        nodeRepository.nodes().fail(nodeRepository.nodes().list().owner(fixture.app1).asList().get(3).hostname(), Agent.system, "Failing to unit test");
        clock.advance(Duration.ofMinutes(2));
        maintainer.maintain();
        assertEquals("System change -> no redeployments", 3, fixture.deployer.activations);

        clock.advance(Duration.ofSeconds(1));
        nodeRepository.nodes().fail(nodeRepository.nodes().list().owner(fixture.app2).asList().get(4).hostname(), Agent.operator, "Manual node failing");
        clock.advance(Duration.ofMinutes(2));
        maintainer.maintain();
        assertEquals("Operator change -> redeployment", 4, fixture.deployer.activations);

        clock.advance(Duration.ofSeconds(1));
        nodeRepository.nodes().fail(nodeRepository.nodes().list().owner(fixture.app3).asList().get(1).hostname(), Agent.operator, "Manual node failing");
        clock.advance(Duration.ofMinutes(2));
        maintainer.maintain();
        assertEquals("Operator change -> redeployment", 5, fixture.deployer.activations);

        clock.advance(Duration.ofSeconds(1));
        fixture.tester.makeReadyNodes(1, fixture.nodeResources, NodeType.proxy);
        clock.advance(Duration.ofMinutes(2));
        maintainer.maintain();
        assertEquals("Ready proxy node -> redeployment", 6, fixture.deployer.activations);

        clock.advance(Duration.ofMinutes(2));
        maintainer.maintain();
        assertEquals("No further operator changes -> no (new) redeployments", 6, fixture.deployer.activations);
    }

    private static class Fixture {

        final ProvisioningTester tester;
        final NodeRepository nodeRepository;
        final MockDeployer deployer;

        final NodeResources nodeResources = new NodeResources(2, 8, 50, 1);
        final InfraApplication proxyApp = ProvisioningTester.infraApplication(NodeType.proxy);
        final ApplicationId app1 = ApplicationId.from(TenantName.from("foo1"), ApplicationName.from("bar"), InstanceName.from("fuz"));
        final ApplicationId app2 = ApplicationId.from(TenantName.from("foo2"), ApplicationName.from("bar"), InstanceName.from("fuz"));
        final ApplicationId app3 = proxyApp.getApplicationId();
        final ClusterSpec clusterApp1 = ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("test")).vespaVersion("6.42").build();
        final ClusterSpec clusterApp2 = ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("test")).vespaVersion("6.42").build();
        final int wantedNodesApp1 = 5;
        final int wantedNodesApp2 = 7;
        final int wantedNodesApp3 = 2;

        Fixture() {
            this.tester = new ProvisioningTester.Builder().build();
            this.nodeRepository = tester.nodeRepository();
            List<MockDeployer.ApplicationContext> apps = List.of(
                    new MockDeployer.ApplicationContext(app1, clusterApp1, Capacity.from(new ClusterResources(wantedNodesApp1, 1, nodeResources))),
                    new MockDeployer.ApplicationContext(app2, clusterApp2, Capacity.from(new ClusterResources(wantedNodesApp2, 1, nodeResources))),
                    new MockDeployer.ApplicationContext(proxyApp, Version.fromString("6.42")));
            this.deployer = new MockDeployer(tester.provisioner(), nodeRepository.clock(), apps);
        }

        void activate() {
            deployer.deployFromLocalActive(app1, false).get().activate();
            deployer.deployFromLocalActive(app2, false).get().activate();
            deployer.deployFromLocalActive(app3, false).get().activate();
            assertEquals(wantedNodesApp1, nodeRepository.nodes().list(Node.State.active).owner(app1).size());
            assertEquals(wantedNodesApp2, nodeRepository.nodes().list(Node.State.active).owner(app2).size());
            assertEquals(wantedNodesApp3, nodeRepository.nodes().list(Node.State.active).owner(app3).size());
        }

    }
    
}