[New] Allow to override DB config in env
This commit is contained in:
parent
405704968e
commit
8d8bfd0ede
|
@ -16,6 +16,7 @@
|
||||||
package li.strolch.runtime;
|
package li.strolch.runtime;
|
||||||
|
|
||||||
import static li.strolch.utils.helper.StringHelper.DOT;
|
import static li.strolch.utils.helper.StringHelper.DOT;
|
||||||
|
import static li.strolch.utils.helper.StringHelper.UNDERLINE;
|
||||||
|
|
||||||
import li.strolch.agent.api.ObserverHandler;
|
import li.strolch.agent.api.ObserverHandler;
|
||||||
import li.strolch.model.StrolchModelConstants;
|
import li.strolch.model.StrolchModelConstants;
|
||||||
|
@ -46,10 +47,14 @@ public class StrolchConstants extends StrolchModelConstants {
|
||||||
public static final String TYPE_STROLCH_JOB = "StrolchJob";
|
public static final String TYPE_STROLCH_JOB = "StrolchJob";
|
||||||
|
|
||||||
public static String makeRealmKey(String realmName, String key) {
|
public static String makeRealmKey(String realmName, String key) {
|
||||||
|
return makeRealmKey(realmName, key, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String makeRealmKey(String realmName, String key, boolean useEnv) {
|
||||||
String realmKey = key;
|
String realmKey = key;
|
||||||
if (!realmName.equals(DEFAULT_REALM))
|
if (!realmName.equals(DEFAULT_REALM))
|
||||||
realmKey += DOT + realmName;
|
realmKey += (useEnv ? UNDERLINE : DOT) + realmName;
|
||||||
return realmKey;
|
return useEnv ? realmKey.replace(DOT, UNDERLINE).toUpperCase() : realmKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -16,7 +16,9 @@
|
||||||
package li.strolch.runtime.configuration;
|
package li.strolch.runtime.configuration;
|
||||||
|
|
||||||
import static li.strolch.db.DbConstants.*;
|
import static li.strolch.db.DbConstants.*;
|
||||||
|
import static li.strolch.runtime.StrolchConstants.DEFAULT_REALM;
|
||||||
import static li.strolch.runtime.StrolchConstants.makeRealmKey;
|
import static li.strolch.runtime.StrolchConstants.makeRealmKey;
|
||||||
|
import static li.strolch.utils.helper.StringHelper.*;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
|
@ -29,7 +31,6 @@ import java.util.Set;
|
||||||
import li.strolch.agent.api.ComponentContainer;
|
import li.strolch.agent.api.ComponentContainer;
|
||||||
import li.strolch.agent.api.StrolchRealm;
|
import li.strolch.agent.api.StrolchRealm;
|
||||||
import li.strolch.persistence.api.StrolchPersistenceException;
|
import li.strolch.persistence.api.StrolchPersistenceException;
|
||||||
import li.strolch.runtime.StrolchConstants;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -61,36 +62,44 @@ public abstract class DbConnectionBuilder {
|
||||||
if (realm.getMode().isTransient())
|
if (realm.getMode().isTransient())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
String dbIgnoreRealmKey = makeRealmKey(realmName, PROP_DB_IGNORE_REALM);
|
String dbUseEnvKey = makeRealmKey(realmName, PROP_USE_ENV, false);
|
||||||
String dbUrlKey = makeRealmKey(realmName, PROP_DB_URL);
|
boolean dbUseEnv = this.configuration.getBoolean(dbUseEnvKey, false);
|
||||||
String dbUsernameKey = makeRealmKey(realmName, PROP_DB_USERNAME);
|
if (dbUseEnv)
|
||||||
String dbPasswordKey = makeRealmKey(realmName, PROP_DB_PASSWORD);
|
logger.info("Configuration specifies to use environment variables to configure DB access...");
|
||||||
|
|
||||||
boolean dbIgnoreRealm = this.configuration.getBoolean(dbIgnoreRealmKey, Boolean.FALSE);
|
String dbUrlKey = makeRealmKey(realmName, PROP_DB_URL, dbUseEnv);
|
||||||
|
String dbUsernameKey = makeRealmKey(realmName, PROP_DB_USERNAME, dbUseEnv);
|
||||||
|
String dbPasswordKey = makeRealmKey(realmName, PROP_DB_PASSWORD, dbUseEnv);
|
||||||
|
|
||||||
|
String dbIgnoreRealmKey = makeRealmKey(realmName, PROP_DB_IGNORE_REALM, false);
|
||||||
|
boolean dbIgnoreRealm = this.configuration.getBoolean(dbIgnoreRealmKey, false);
|
||||||
if (dbIgnoreRealm) {
|
if (dbIgnoreRealm) {
|
||||||
logger.info("[" + realm + "] Ignoring any DB configuration for Realm " + realmName);
|
logger.info("[" + realm + "] Ignoring any DB configuration for Realm " + realmName);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
String dbUrl = this.configuration.getString(dbUrlKey, null);
|
String dbUrl = getConfigString(dbUrlKey, dbUseEnv);
|
||||||
String username = this.configuration.getString(dbUsernameKey, null);
|
String username = getConfigString(dbUsernameKey, dbUseEnv);
|
||||||
String password = this.configuration.getString(dbPasswordKey, null);
|
String password = getConfigString(dbPasswordKey, dbUseEnv);
|
||||||
|
|
||||||
if (this.configuration.getBoolean(PROP_DB_ALLOW_HOST_OVERRIDE_ENV, false) //
|
if (this.configuration.getBoolean(PROP_DB_ALLOW_HOST_OVERRIDE_ENV, false) //
|
||||||
&& System.getProperties().containsKey(PROP_DB_HOST_OVERRIDE)) {
|
&& System.getProperties().containsKey(PROP_DB_HOST_OVERRIDE)) {
|
||||||
dbUrl = overridePostgresqlHost(realm.getRealm(), dbUrl);
|
dbUrl = overridePostgresqlHost(realm.getRealm(), dbUrl, dbUseEnv);
|
||||||
}
|
}
|
||||||
|
|
||||||
// find any pool configuration values
|
// find any pool configuration values
|
||||||
Set<String> propertyKeys = this.configuration.getPropertyKeys();
|
Map<String, String> properties = dbUseEnv ? System.getenv() : this.configuration.getAsMap();
|
||||||
|
String dbPoolPrefix = dbUseEnv ?
|
||||||
|
PROP_DB_POOL_PREFIX.replace(DOT, UNDERLINE).toUpperCase() :
|
||||||
|
PROP_DB_POOL_PREFIX;
|
||||||
Properties props = new Properties();
|
Properties props = new Properties();
|
||||||
for (String key : propertyKeys) {
|
for (String key : properties.keySet()) {
|
||||||
if (!key.startsWith(PROP_DB_POOL_PREFIX))
|
if (!key.startsWith(dbPoolPrefix))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// TODO we should change how properties for realms are configured
|
// TODO we should change how properties for realms are configured
|
||||||
// since defaultRealm does not have to be on the key, we need this hack:
|
// since defaultRealm does not have to be on the key, we need this hack:
|
||||||
String[] segments = key.split("\\.");
|
String[] segments = key.split(dbUseEnv ? UNDERLINE : "\\.");
|
||||||
String poolKey;
|
String poolKey;
|
||||||
String foundRealm;
|
String foundRealm;
|
||||||
if (segments.length == 4) {
|
if (segments.length == 4) {
|
||||||
|
@ -98,7 +107,7 @@ public abstract class DbConnectionBuilder {
|
||||||
foundRealm = segments[3];
|
foundRealm = segments[3];
|
||||||
} else if (segments.length == 3) {
|
} else if (segments.length == 3) {
|
||||||
// default realm
|
// default realm
|
||||||
foundRealm = StrolchConstants.DEFAULT_REALM;
|
foundRealm = DEFAULT_REALM;
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("Can't detect realm of this property: " + key);
|
throw new IllegalArgumentException("Can't detect realm of this property: " + key);
|
||||||
}
|
}
|
||||||
|
@ -107,39 +116,62 @@ public abstract class DbConnectionBuilder {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
poolKey = segments[2];
|
poolKey = segments[2];
|
||||||
String value = this.configuration.getString(key, null);
|
String value = properties.get(key);
|
||||||
props.setProperty(poolKey, value);
|
props.setProperty(poolKey, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
DataSource ds = build(realmName, dbUrl, username, password, props);
|
DataSource dataSource = build(realmName, dbUrl, username, password, props);
|
||||||
|
dsMap.put(realmName, dataSource);
|
||||||
dsMap.put(realmName, ds);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return dsMap;
|
return dsMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String overridePostgresqlHost(String realm, String dbUrl) {
|
private String getConfigString(String dbKey, boolean useEnv) {
|
||||||
if (!System.getProperties().containsKey(PROP_DB_HOST_OVERRIDE))
|
if (!useEnv)
|
||||||
return dbUrl;
|
return this.configuration.getString(dbKey, null);
|
||||||
|
|
||||||
|
String value = System.getenv(dbKey);
|
||||||
|
if (isEmpty(value))
|
||||||
|
throw new IllegalStateException("Missing environment variable " + dbKey);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String overridePostgresqlHost(String realmName, String dbUrl) {
|
||||||
|
return overridePostgresqlHost(realmName, dbUrl, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String overridePostgresqlHost(String realmName, String dbUrl, boolean useEnv) {
|
||||||
|
String hostOverride;
|
||||||
|
if (useEnv) {
|
||||||
|
if (!System.getenv().containsKey(ENV_DB_HOST_OVERRIDE))
|
||||||
|
return dbUrl;
|
||||||
|
String hostOverrideKey = makeRealmKey(realmName, PROP_DB_HOST_OVERRIDE, true);
|
||||||
|
hostOverride = System.getenv(hostOverrideKey);
|
||||||
|
} else {
|
||||||
|
if (!System.getProperties().containsKey(PROP_DB_HOST_OVERRIDE))
|
||||||
|
return dbUrl;
|
||||||
|
String hostOverrideKey = makeRealmKey(realmName, PROP_DB_HOST_OVERRIDE, false);
|
||||||
|
hostOverride = System.getProperty(hostOverrideKey);
|
||||||
|
}
|
||||||
|
|
||||||
if (!dbUrl.startsWith("jdbc:postgresql://"))
|
if (!dbUrl.startsWith("jdbc:postgresql://"))
|
||||||
throw new IllegalStateException("DB URL is invalid: " + dbUrl);
|
throw new IllegalStateException("DB URL is invalid: " + dbUrl);
|
||||||
|
|
||||||
String tmp = dbUrl.substring("jdbc:postgresql://".length());
|
String tmp = dbUrl.substring("jdbc:postgresql://".length());
|
||||||
String host = tmp.substring(0, tmp.indexOf('/'));
|
String host = tmp.substring(0, tmp.indexOf('/'));
|
||||||
String dbName = tmp.substring(tmp.indexOf('/'));
|
String dbName = tmp.substring(tmp.indexOf('/'));
|
||||||
String hostOverride = System.getProperty(PROP_DB_HOST_OVERRIDE);
|
|
||||||
|
|
||||||
if (host.equals(hostOverride))
|
if (host.equals(hostOverride))
|
||||||
return dbUrl;
|
return dbUrl;
|
||||||
|
|
||||||
logger.warn("[" + realm + "] Replacing db host " + host + " with override " + hostOverride);
|
logger.warn("[" + realmName + "] Replacing db host " + host + " with override " + hostOverride);
|
||||||
dbUrl = "jdbc:postgresql://" + hostOverride + dbName;
|
dbUrl = "jdbc:postgresql://" + hostOverride + dbName;
|
||||||
logger.warn("[" + realm + "] DB URL is now " + dbUrl);
|
logger.warn("[" + realmName + "] DB URL is now " + dbUrl);
|
||||||
return dbUrl;
|
return dbUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract DataSource build(String realm, String url, String username, String password, Properties proops);
|
protected abstract DataSource build(String realm, String url, String username, String password, Properties props);
|
||||||
|
|
||||||
protected void validateConnection(DataSource ds) {
|
protected void validateConnection(DataSource ds) {
|
||||||
try (Connection con = ds.getConnection()) {
|
try (Connection con = ds.getConnection()) {
|
||||||
|
|
|
@ -91,7 +91,7 @@ public abstract class PostgreSqlInitializer extends SystemAction {
|
||||||
|
|
||||||
protected File getDataStoreFile(RuntimeConfiguration runtimeConfiguration,
|
protected File getDataStoreFile(RuntimeConfiguration runtimeConfiguration,
|
||||||
ComponentConfiguration realmConfiguration, String realmName) {
|
ComponentConfiguration realmConfiguration, String realmName) {
|
||||||
String dataStoreKey = makeRealmKey(realmName, PREFIX_DATA_STORE_FILE);
|
String dataStoreKey = makeRealmKey(realmName, PREFIX_DATA_STORE_FILE, false);
|
||||||
return realmConfiguration.getDataFile(dataStoreKey, null, runtimeConfiguration, true);
|
return realmConfiguration.getDataFile(dataStoreKey, null, runtimeConfiguration, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,10 @@
|
||||||
package li.strolch.persistence.xml;
|
package li.strolch.persistence.xml;
|
||||||
|
|
||||||
import static li.strolch.agent.impl.DefaultRealmHandler.PREFIX_DATA_STORE_FILE;
|
import static li.strolch.agent.impl.DefaultRealmHandler.PREFIX_DATA_STORE_FILE;
|
||||||
|
import static li.strolch.db.DbConstants.PROP_DB_IGNORE_REALM;
|
||||||
|
import static li.strolch.db.DbConstants.PROP_USE_ENV;
|
||||||
import static li.strolch.runtime.StrolchConstants.makeRealmKey;
|
import static li.strolch.runtime.StrolchConstants.makeRealmKey;
|
||||||
|
import static li.strolch.utils.helper.StringHelper.isEmpty;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
|
@ -42,6 +45,7 @@ import li.strolch.runtime.configuration.ComponentConfiguration;
|
||||||
import li.strolch.runtime.configuration.RuntimeConfiguration;
|
import li.strolch.runtime.configuration.RuntimeConfiguration;
|
||||||
import li.strolch.runtime.configuration.StrolchConfiguration;
|
import li.strolch.runtime.configuration.StrolchConfiguration;
|
||||||
import li.strolch.runtime.configuration.StrolchConfigurationException;
|
import li.strolch.runtime.configuration.StrolchConfigurationException;
|
||||||
|
import li.strolch.utils.helper.StringHelper;
|
||||||
import li.strolch.xmlpers.api.*;
|
import li.strolch.xmlpers.api.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -79,18 +83,21 @@ public class XmlPersistenceHandler extends StrolchComponent implements Persisten
|
||||||
if (realm.getMode().isTransient())
|
if (realm.getMode().isTransient())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
String dbIgnoreRealmKey = makeRealmKey(realmName, PROP_DB_IGNORE_REALM);
|
String dbUseEnvKey = makeRealmKey(realmName, PROP_USE_ENV, false);
|
||||||
String dbStorePathKey = makeRealmKey(realmName, PROP_DB_STORE_PATH);
|
boolean dbUseEnv = configuration.getBoolean(dbUseEnvKey, false);
|
||||||
String dbVerboseKey = makeRealmKey(realmName, PROP_VERBOSE);
|
|
||||||
|
|
||||||
boolean dbIgnoreRealm = configuration.getBoolean(dbIgnoreRealmKey, Boolean.FALSE);
|
String dbStorePathKey = makeRealmKey(realmName, PROP_DB_STORE_PATH, dbUseEnv);
|
||||||
|
String dbVerboseKey = makeRealmKey(realmName, PROP_VERBOSE, dbUseEnv);
|
||||||
|
|
||||||
|
String dbIgnoreRealmKey = makeRealmKey(realmName, PROP_DB_IGNORE_REALM, false);
|
||||||
|
boolean dbIgnoreRealm = configuration.getBoolean(dbIgnoreRealmKey, false);
|
||||||
if (dbIgnoreRealm) {
|
if (dbIgnoreRealm) {
|
||||||
logger.info("Ignoring any DB configuration for Realm " + realmName);
|
logger.info("Ignoring any DB configuration for Realm " + realmName);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
String dbStorePath = configuration.getString(dbStorePathKey, null);
|
String dbStorePath = getConfigString(configuration, dbStorePathKey, dbUseEnv);
|
||||||
boolean verbose = configuration.getBoolean(dbVerboseKey, Boolean.FALSE);
|
boolean verbose = getConfigBoolean(configuration, dbVerboseKey, dbUseEnv);
|
||||||
|
|
||||||
// validate URL
|
// validate URL
|
||||||
if (dbStorePaths.contains(dbStorePath))
|
if (dbStorePaths.contains(dbStorePath))
|
||||||
|
@ -128,6 +135,26 @@ public class XmlPersistenceHandler extends StrolchComponent implements Persisten
|
||||||
super.initialize(configuration);
|
super.initialize(configuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getConfigString(ComponentConfiguration configuration, String dbKey, boolean useEnv) {
|
||||||
|
if (!useEnv)
|
||||||
|
return configuration.getString(dbKey, null);
|
||||||
|
|
||||||
|
String value = System.getenv(dbKey);
|
||||||
|
if (isEmpty(value))
|
||||||
|
throw new IllegalStateException("Missing environment variable " + dbKey);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Boolean getConfigBoolean(ComponentConfiguration configuration, String dbKey, boolean useEnv) {
|
||||||
|
if (!useEnv)
|
||||||
|
return configuration.getBoolean(dbKey, false);
|
||||||
|
|
||||||
|
String value = System.getenv(dbKey);
|
||||||
|
if (isEmpty(value))
|
||||||
|
throw new IllegalStateException("Missing environment variable " + dbKey);
|
||||||
|
return StringHelper.parseBoolean(value);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start() throws Exception {
|
public void start() throws Exception {
|
||||||
|
|
||||||
|
|
|
@ -35,4 +35,6 @@ public class DbConstants {
|
||||||
public static final String PROP_ALLOW_DATA_INIT_ON_EMPTY_DB = "allowDataInitOnEmptyDb";
|
public static final String PROP_ALLOW_DATA_INIT_ON_EMPTY_DB = "allowDataInitOnEmptyDb";
|
||||||
public static final String PROP_DB_VERSION = "db_version";
|
public static final String PROP_DB_VERSION = "db_version";
|
||||||
public static final String RESOURCE_DB_VERSION = "/{0}_db_version.properties";
|
public static final String RESOURCE_DB_VERSION = "/{0}_db_version.properties";
|
||||||
|
|
||||||
|
public static final String ENV_DB_HOST_OVERRIDE = "DB_HOST_OVERRIDE";
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue