summaryrefslogtreecommitdiffstats
path: root/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/Change.java
blob: 13d66c8d08374809f583c1b2b81686e6d89aa180 (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
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.application;

import com.yahoo.component.Version;
import com.yahoo.config.application.api.DeploymentSpec;

import java.time.Instant;
import java.util.Objects;
import java.util.Optional;

/**
 * The changes to an application we currently wish to complete deploying.
 * A goal of the system is to deploy platform and application versions separately.
 * However, this goal must some times be traded against others, so a change can
 * consist of both an application and platform version change.
 *
 * This is immutable.
 *
 * @author bratseth
 */
public final class Change {

    private static final Change empty = new Change(Optional.empty(), Optional.empty());

    /** The platform version we are upgrading to, or empty if none */
    private final Optional<Version> platform;

    /** The application version we are changing to, or empty if none */
    private final Optional<ApplicationVersion> application;

    private Change(Optional<Version> platform, Optional<ApplicationVersion> application) {
        Objects.requireNonNull(platform, "platform cannot be null");
        Objects.requireNonNull(application, "application cannot be null");
        this.platform = platform;
        this.application = application;
    }

    /** Returns true if this change is blocked by the given spec at the given instant */
    public boolean blockedBy(DeploymentSpec deploymentSpec, Instant instant) {
        if (platform.isPresent() && ! deploymentSpec.canUpgradeAt(instant)) return true;
        if (application.isPresent() && ! deploymentSpec.canChangeRevisionAt(instant)) return true;
        return false;
    }

    /** Returns whether a change shoudl currently be deployed */
    public boolean isPresent() {
        return platform.isPresent() || application.isPresent();
    }

    /** Returns the platform version change which should currently be deployed, if any */
    public Optional<Version> platform() { return platform; }

    /** Returns the application version change which should currently be deployed, if any */
    public Optional<ApplicationVersion> application() { return application; }

    /** Returns an instance representing no change */
    public static Change empty() { return empty; }

    /** Returns a version of this change which replaces or adds this application change */
    public Change with(ApplicationVersion applicationVersion) {
        return new Change(platform, Optional.of(applicationVersion));
    }

    @Override
    public int hashCode() { return Objects.hash(platform, application); }

    @Override
    public boolean equals(Object other) {
        if (other == this) return true;
        if ( ! (other instanceof Change)) return false;
        Change o = (Change)other;
        if ( ! o.platform.equals(this.platform)) return false;
        if ( ! o.application.equals(this.application)) return false;
        return true;
    }

    @Override
    public String toString() {
        String platformString = platform.map(v -> "upgrade to " + v).orElse(null);
        String applicationString = application.map(v -> "application change to " + v).orElse(null);
        if (platformString != null && applicationString != null)
            return platformString + " and " + applicationString;
        if (platformString != null)
            return platformString;
        if (applicationString != null)
            return applicationString;
        return "no change";
    }

    public static Change of(ApplicationVersion applicationVersion) {
        return new Change(Optional.empty(), Optional.of(applicationVersion));
    }

    public static Change of(Version platformChange) {
        return new Change(Optional.of(platformChange), Optional.empty());
    }

}