summaryrefslogtreecommitdiffstats
path: root/config-provisioning/src/main/java/com/yahoo/config/provision/Zone.java
blob: 6b1e1406c8fba9b8ba43f8f1bbe73d6bad72c70c (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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.config.provision;

import com.google.common.base.Strings;
import com.google.inject.Inject;
import com.yahoo.cloud.config.ConfigserverConfig;

import java.util.Objects;
import java.util.Optional;

/**
 * The zone (environment + region) of this runtime, and some other information.
 * An injected instance of this will return the correct current environment and region.
 * Components can use this to obtain information about which zone they are running in.
 *
 * @author bratseth
 */
public class Zone {

    private final CloudName cloudName;
    private final SystemName systemName;
    private final Environment environment;
    private final RegionName region;
    private final FlavorDefaults flavorDefaults;
    private final Optional<NodeFlavors> nodeFlavors;

    @Inject
    public Zone(ConfigserverConfig configserverConfig, NodeFlavors nodeFlavors) {
        this(CloudName.from(configserverConfig.cloud()),
             SystemName.from(configserverConfig.system()),
             Environment.from(configserverConfig.environment()),
             RegionName.from(configserverConfig.region()),
             new FlavorDefaults(configserverConfig),
             nodeFlavors);
    }

    /** Create from environment and region. Use for testing.  */
    public Zone(Environment environment, RegionName region) {
        this(SystemName.defaultSystem(), environment, region);
    }

    /** Create from system, environment and region. Use for testing. */
    public Zone(SystemName systemName, Environment environment, RegionName region) {
        this(CloudName.defaultName(), systemName, environment, region, new FlavorDefaults("default"), null);
    }

    /** Create from cloud, system, environment and region. Use for testing. */
    public Zone(CloudName cloudName, SystemName systemName, Environment environment, RegionName region) {
        this(cloudName, systemName, environment, region, new FlavorDefaults("default"), null);
    }

    private Zone(CloudName cloudName,
                 SystemName systemName,
                 Environment environment,
                 RegionName region,
                 FlavorDefaults flavorDefaults,
                 NodeFlavors nodeFlavors) {
        this.cloudName = cloudName;
        this.systemName = systemName;
        this.environment = environment;
        this.region = region;
        this.flavorDefaults = flavorDefaults;
        this.nodeFlavors = Optional.ofNullable(nodeFlavors);
    }

    /** Returns the current cloud */
    public CloudName cloud() { return cloudName; }

    /** Returns the current system */
    public SystemName system() { return systemName; }

    /** Returns the current environment */
    public Environment environment() {
        return environment;
    }

    /** Returns the current region */
    public RegionName region() {
        return region;
    }

    /** Returns the default hardware flavor to assign in this zone */
    public String defaultFlavor(ClusterSpec.Type clusterType) { return flavorDefaults.flavor(clusterType); }

    /** Returns all available node flavors for the zone, or empty if not set for this Zone. */
    public Optional<NodeFlavors> nodeFlavors() { return nodeFlavors; }

    /** Do not use */
    public static Zone defaultZone() {
        return new Zone(CloudName.defaultName(), SystemName.defaultSystem(), Environment.defaultEnvironment(), RegionName.defaultName());
    }

    @Override
    public String toString() {
        return "zone " + environment + "." + region;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Zone)) return false;
        Zone zone = (Zone) o;
        return environment == zone.environment &&
               Objects.equals(region, zone.region);
    }

    @Override
    public int hashCode() {
        return Objects.hash(environment, region);
    }

    private static class FlavorDefaults {

        /** The default default flavor */
        private final String defaultFlavor;

        /** The default flavor for each cluster type, or empty to use defaultFlavor */
        private final Optional<String> adminFlavor;
        private final Optional<String> containerFlavor;
        private final Optional<String> contentFlavor;

        /** Creates this with a default flavor and all cluster type flavors empty */
        public FlavorDefaults(String defaultFlavor) {
            this(defaultFlavor, Optional.empty(), Optional.empty(), Optional.empty());
        }

        /** Creates this with a default flavor and all cluster type flavors empty */
        public FlavorDefaults(String defaultFlavor,
                              Optional<String> adminFlavor, Optional<String> containerFlavor, Optional<String> contentFlavor) {
            this.defaultFlavor = defaultFlavor;
            this.adminFlavor = adminFlavor;
            this.containerFlavor = containerFlavor;
            this.contentFlavor = contentFlavor;
        }

        public FlavorDefaults(ConfigserverConfig config) {
            this(config.defaultFlavor(),
                 emptyIfDefault(config.defaultAdminFlavor()),
                 emptyIfDefault(config.defaultContainerFlavor()),
                 emptyIfDefault(config.defaultContentFlavor()));
        }

        /** Map "default" to empty - this config cannot have missing values due to the need for supporting non-hosted */
        private static Optional<String> emptyIfDefault(String value) {
            if (Strings.isNullOrEmpty(value)) return Optional.empty();
            if (value.equals("default")) return Optional.empty();
            return Optional.of(value);
        }

        /**
         * Returns the flavor default for a given cluster type.
         * This may be "default" - which is an invalid value - but never null.
         */
        public String flavor(ClusterSpec.Type clusterType) {
            switch (clusterType) {
                case admin: return adminFlavor.orElse(defaultFlavor);
                case container: return containerFlavor.orElse(defaultFlavor);
                case content: return contentFlavor.orElse(defaultFlavor);
                default: return defaultFlavor; // future cluster types
            }
        }

    }

}