com.pulumi.Config Maven / Gradle / Ivy
package com.pulumi;
import com.google.common.annotations.VisibleForTesting;
import com.google.gson.Gson;
import com.google.gson.JsonParseException;
import com.pulumi.core.Output;
import com.pulumi.core.TypeShape;
import com.pulumi.core.internal.annotations.InternalUse;
import com.pulumi.deployment.Deployment;
import com.pulumi.deployment.internal.DeploymentImpl;
import com.pulumi.exceptions.RunException;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.io.Reader;
import java.util.List;
import java.util.Optional;
import static java.util.Objects.requireNonNull;
/**
* Config is a bag of related configuration state. Each bag contains any number
* of configuration variables, indexed by simple keys, and each has a name that uniquely
* identifies it; two bags with different names do not share values for variables that
* otherwise share the same key. For example, a bag whose name is {@code pulumi:foo}, with keys
* {@code a}, {@code b}, and {@code c}, is entirely separate from a bag whose name is
* {@code pulumi:bar} with the same simple key names. Each key has a fully qualified names,
* such as {@code pulumi:foo:a}, ..., and {@code pulumi:bar:a}, respectively.
* @see com.pulumi.context.ConfigContext
*/
@ParametersAreNonnullByDefault
public class Config {
private final String name;
private final DeploymentImpl.Config internalConfig;
/**
* @see com.pulumi.Context#config()
* @see com.pulumi.Context#config(String)
*/
@InternalUse
public Config(DeploymentImpl.Config internalConfig, String name) {
this.internalConfig = requireNonNull(internalConfig);
requireNonNull(name);
if (name.endsWith(":config")) {
name = name.replaceAll(":config$", "");
}
this.name = name;
}
/**
* For internal use by providers.
* @see com.pulumi.Context#config()
* @see com.pulumi.Context#config(String)
* @deprecated will be removed in the future, use {@link com.pulumi.Context#config(String)}
*/
// TODO: remove after refactoring the deployment
@InternalUse
@Deprecated
public static Config of(String name) {
return new Config(Deployment.getInstance().getConfig(), name);
}
/**
* The configuration bag's logical name and uniquely identifies it.
* The default is the name of the current project.
*
* @return unique logical configuration bag name
*/
@Nonnull
public String getName() {
return name;
}
/**
* Loads an optional configuration value by its key, or returns empty if it doesn't exist.
*/
public Optional get(String key) {
var fullKey = fullKey(key);
// FIXME: due to https://github.com/pulumi/pulumi/issues/7127
// there is a check for key being a secret missing here
return this.internalConfig.getConfig(fullKey);
}
/**
* Loads an optional configuration value by its key, marking it as a secret,
* or empty if it doesn't exist.
*/
public Output> getSecret(String key) {
return Output.ofSecret(get(key));
}
/**
* Loads an optional configuration value, as a boolean, by its key, or null if it doesn't exist.
* If the configuration value isn't a legal boolean, this function will throw an error.
*/
public Optional getBoolean(String key) {
return get(key).map(Boolean::parseBoolean);
}
/**
* Loads an optional configuration value, as a boolean, by its key, making it as a secret or
* null if it doesn't exist. If the configuration value isn't a legal boolean, this
* function will throw an error.
*/
public Output> getSecretBoolean(String key) {
return Output.ofSecret(getBoolean(key));
}
/**
* Loads an optional configuration value, as a number, by its key, or null if it doesn't exist.
* If the configuration value isn't a legal number, this function will throw an error.
*/
public Optional getInteger(String key) {
return get(key).map(string -> {
try {
return Integer.parseInt(string);
} catch (NumberFormatException ex) {
throw new ConfigTypeException(fullKey(key), string, "Integer", ex);
}
});
}
/**
* Loads an optional configuration value, as a number, by its key, or null if it doesn't exist.
* If the configuration value isn't a legal number, this function will throw an error.
*/
public Optional getDouble(String key) {
return get(key).map(string -> {
try {
return Double.parseDouble(string);
} catch (NumberFormatException ex) {
throw new ConfigTypeException(fullKey(key), string, "Double", ex);
}
});
}
/**
* Loads an optional configuration value, as a number, by its key, marking it as a secret
* or null if it doesn't exist.
* If the configuration value isn't a legal number, this function will throw an error.
*/
public Output> getSecretInteger(String key) {
return Output.ofSecret(getInteger(key));
}
/**
* Loads an optional configuration value as a JSON string and deserializes it
* as an object, by its key, or null if it doesn't exist.
* This works by taking the value associated with {@code key} and passing
* it to {@link Gson#fromJson(Reader, Class)}.
*/
public Optional getObject(String key, Class classOfT) {
var v = get(key);
try {
var gson = new Gson();
return v.map(string -> gson.fromJson(string, classOfT));
} catch (JsonParseException ex) {
throw new ConfigTypeException(fullKey(key), v, classOfT.getTypeName(), ex);
}
}
/**
* Loads an optional configuration value as a JSON string and deserializes it
* as an object, by its key, marking it as a secret or null (empty) if it doesn't exist.
* This works by taking the value associated with {@code key}
* and passing it to {@link Gson#fromJson(Reader, Class)}.
*/
public Output> getSecretObject(String key, Class classOfT) {
return Output.ofSecret(getObject(key, classOfT));
}
/**
* @see #getObject(String, Class)
*/
public Optional getObject(String key, TypeShape shapeOfT) {
var v = get(key);
// TODO should this be using Pulumi deserializers from protobuf Struct instead of GSON?
// JSON can be converted to protobuf struct.
try {
var gson = new Gson();
return v.map(string -> gson.fromJson(string, shapeOfT.toGSON().getType()));
} catch (JsonParseException ex) {
throw new ConfigTypeException(fullKey(key), v, shapeOfT.getTypeName(), ex);
}
}
/**
* @see #getSecretObject(String, Class)
*/
public Output> getSecretObject(String key, TypeShape shapeOfT) {
return Output.ofSecret(getObject(key, shapeOfT));
}
/**
* Loads a configuration value by its given key. If it doesn't exist, an error is thrown.
*/
public String require(String key) {
return get(key).orElseThrow(() -> new ConfigMissingException(fullKey(key)));
}
/**
* Loads a configuration value by its given key, marking it as a secret. If it doesn't exist, an error
* is thrown.
*/
public Output requireSecret(String key) {
return Output.ofSecret(require(key));
}
/**
* Loads a configuration value, as a boolean, by its given key. If it doesn't exist, or the
* configuration value is not a legal boolean, an error is thrown.
*/
public boolean requireBoolean(String key) {
return getBoolean(key).orElseThrow(() -> new ConfigMissingException(fullKey(key)));
}
/**
* Loads a configuration value, as a boolean, by its given key, marking it as a secret.
* If it doesn't exist, or the configuration value is not a legal boolean, an error is thrown.
*/
public Output requireSecretBoolean(String key) {
return Output.ofSecret(requireBoolean(key));
}
/**
* Loads a configuration value, as a number, by its given key. If it doesn't exist, or the
* configuration value is not a legal number, an error is thrown.
*/
public int requireInteger(String key) {
return getInteger(key).orElseThrow(() -> new ConfigMissingException(fullKey(key)));
}
/**
* Loads a configuration value, as a number, by its given key, marking it as a secret.
* If it doesn't exist, or the configuration value is not a legal number, an error is thrown.
*/
public Output requireSecretInteger(String key) {
return Output.ofSecret(requireInteger(key));
}
/**
* Loads a configuration value as a JSON string and deserializes it into an object.
* If it doesn't exist, or the configuration value cannot be converted
* using {@link Gson#fromJson(Reader, Class)}, an error is thrown.
*/
public T requireObject(String key, Class classOfT) {
return getObject(key, classOfT).orElseThrow(() -> new ConfigMissingException(fullKey(key)));
}
/**
* Loads a configuration value as a JSON string and deserializes it into an object,
* marking it as a secret.
* If it doesn't exist, or the configuration value cannot be converted
* using {@link Gson#fromJson(Reader, Class)}, an error is thrown.
*/
public Output requireSecretObject(String key, Class classOfT) {
return Output.ofSecret(requireObject(key, classOfT));
}
/**
* Turns a simple configuration key into a fully resolved one, by prepending the bag's name.
*/
private String fullKey(String key) {
return String.format("%s:%s", this.name, key);
}
/**
* ConfigTypeException is used when a configuration value is of the wrong type.
*/
private static class ConfigTypeException extends RunException {
public ConfigTypeException(String key, @Nullable Object v, String expectedType, @Nullable Exception cause) {
super(String.format("Configuration '%s' value '%s' is not a valid %s", key, v, expectedType), cause);
}
}
/**
* ConfigMissingException is used when a configuration value is completely missing.
*/
@ParametersAreNonnullByDefault
@InternalUse
@VisibleForTesting
public static class ConfigMissingException extends RunException {
public ConfigMissingException(String key) {
super(String.format("Missing required configuration variable '%s'\n", key) +
String.format("\tplease set a value using the command `pulumi config set %s `", key));
}
public ConfigMissingException(String key, List envVars) {
super(String.format("Missing required configuration variable '%s'\n", key) +
String.format("\tplease set a value using the command `pulumi config set %s `", key) +
String.format("\tor provide it via an environment variable %s",
String.join(", ", envVars)));
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy