aboutsummaryrefslogtreecommitdiffstats
path: root/config-model/src/main/java/com/yahoo/config/model/ConfigModelContext.java
blob: 18dfffeecddfb3c64b629ebfb141884279cde156 (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
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.config.model;

import com.yahoo.config.application.api.ApplicationPackage;
import com.yahoo.config.application.api.Bcp.Group;
import com.yahoo.config.application.api.DeployLogger;
import com.yahoo.config.application.api.DeploymentSpec;
import com.yahoo.config.model.api.ModelContext;
import com.yahoo.config.model.deploy.DeployState;
import com.yahoo.config.model.producer.AnyConfigProducer;
import com.yahoo.config.model.producer.TreeConfigProducer;
import com.yahoo.config.provision.CloudAccount;
import com.yahoo.config.provision.ClusterInfo;
import com.yahoo.config.provision.ClusterInfo.Builder;
import com.yahoo.config.provision.zone.ZoneId;
import com.yahoo.vespa.model.VespaModel;

import java.time.Duration;
import java.util.Comparator;
import java.util.Optional;
import java.util.stream.Stream;

/**
 * This class contains a context that is passed to a model builder, and can be used to retrieve the application package,
 * logger etc.
 *
 * @author Ulf Lilleengen
 */
public final class ConfigModelContext {

    private final TreeConfigProducer<AnyConfigProducer> parent;
    private final String producerId;
    private final DeployState deployState;
    private final VespaModel vespaModel;
    private final ConfigModelRepoAdder configModelRepoAdder;
    private final ApplicationType applicationType;

    private ConfigModelContext(ApplicationType applicationType,
                               DeployState deployState,
                               VespaModel vespaModel,
                               ConfigModelRepoAdder configModelRepoAdder,
                               TreeConfigProducer<AnyConfigProducer> parent,
                               String producerId) {
        this.applicationType = applicationType;
        this.deployState = deployState;
        this.vespaModel = vespaModel;
        this.configModelRepoAdder = configModelRepoAdder;
        this.parent = parent;
        this.producerId = producerId;
    }

    public ApplicationPackage getApplicationPackage() { return deployState.getApplicationPackage(); }
    public String getProducerId() { return producerId; }
    public TreeConfigProducer<AnyConfigProducer> getParentProducer() { return parent; }
    public DeployLogger getDeployLogger() { return deployState.getDeployLogger(); }
    public DeployState getDeployState() { return deployState; }
    public ApplicationType getApplicationType() { return applicationType; }
    public VespaModel vespaModel() { return vespaModel; }
    public ModelContext.Properties properties() { return deployState.getProperties(); }
    public ModelContext.FeatureFlags featureFlags() { return deployState.featureFlags(); }

    /** Returns write access to the config model repo, or null (only) if this is improperly initialized during testing */
    public ConfigModelRepoAdder getConfigModelRepoAdder() { return configModelRepoAdder; }

    /** Create a new context with a different parent */
    public ConfigModelContext withParent(TreeConfigProducer<AnyConfigProducer> newParent) {
        return ConfigModelContext.create(deployState, vespaModel, configModelRepoAdder, newParent, producerId);
    }

    /** Create a new context with a different config model producer id */
    public ConfigModelContext withId(String producerId) {
        return ConfigModelContext.create(deployState, vespaModel, configModelRepoAdder, parent, producerId);
    }

    public ConfigModelContext with(VespaModel vespaModel) {
        return ConfigModelContext.create(deployState, vespaModel, configModelRepoAdder, parent, producerId);
    }

    /** Returns a cluster info builder pre-populated with info known in this context. */
    public ClusterInfo.Builder clusterInfo() {
        DeploymentSpec spec = getApplicationPackage().getDeploymentSpec();
        ClusterInfo.Builder builder = new ClusterInfo.Builder();
        spec.hostTTL(properties().applicationId().instance(), deployState.zone().environment(), deployState.zone().region())
            .filter(ttl -> ! ttl.isZero())
            .filter(__ -> deployState.getProperties().cloudAccount().map(account -> ! account.isUnspecified()).orElse(false))
            .ifPresent(builder::hostTTL);
        spec.instance(properties().applicationId().instance())
            .flatMap(instance -> instance.bcp().groups().stream()
                                         .filter(group -> group.memberRegions().contains(properties().zone().region()))
                                         .map(Group::deadline)
                                         .min(Comparator.naturalOrder()))
            .ifPresent(builder::bcpDeadline);
        return builder;
    }

    /**
     * Create an application context from a parent producer and an id.
     *
     * @param deployState the global deploy state for this model
     * @param parent the parent to be used for the config model
     * @param producerId the id to be used for the config model
     * @return a model context that can be passed to a model
     */
    public static ConfigModelContext create(DeployState deployState,
                                            VespaModel vespaModel,
                                            ConfigModelRepoAdder configModelRepoAdder,
                                            TreeConfigProducer<AnyConfigProducer> parent,
                                            String producerId) {
        return new ConfigModelContext(ApplicationType.DEFAULT, deployState, vespaModel, configModelRepoAdder, parent, producerId);
    }

    /**
     * Create an application context from an application type, a parent producer and an id.
     *
     * @param applicationType the application type
     * @param deployState the global deploy state for this model
     * @param parent the parent to be used for the config model
     * @param producerId the id to be used for the config model
     * @return a model context that can be passed to a model
     */
    public static ConfigModelContext create(ApplicationType applicationType,
                                            DeployState deployState,
                                            VespaModel vespaModel,
                                            ConfigModelRepoAdder configModelRepoAdder,
                                            TreeConfigProducer<AnyConfigProducer> parent,
                                            String producerId) {
        return new ConfigModelContext(applicationType, deployState, vespaModel, configModelRepoAdder, parent, producerId);
    }

    public enum ApplicationType {
        DEFAULT("default"),
        HOSTED_INFRASTRUCTURE("hosted-infrastructure");

        private final String type;

        ApplicationType(String type) {
            this.type = type;
        }

        public static ApplicationType fromString(String value) {
            return Stream.of(ApplicationType.values())
                    .filter(applicationType -> applicationType.type.equals(value))
                    .findFirst()
                    .orElse(DEFAULT);

        }

    }
}