hocon - configuración específica por entorno en Scala
configuration environment-variables (4)
Aquí hay una solución que está en Scala, permite anulaciones y no depende de una biblioteca externa.
object Config {
var test: Map[String, String] = {
Map(
"libsvmData" -> new java.io.File("./src/test/resources/sample_libsvm_data.txt").getCanonicalPath,
"somethingElse" -> "hi"
)
}
var production: Map[String, String] = {
Map(
"libsvmData" -> "s3a://my-cool-bucket/fun-data/libsvm.txt",
"somethingElse" -> "whatever"
)
}
var environment = sys.env.getOrElse("PROJECT_ENV", "production")
def get(key: String): String = {
if (environment == "test") {
test(key)
} else {
production(key)
}
}
}
Si PROJECT_ENV
está configurado para test
, Config.get("somethingElse")
devolverá "hi"
. De lo contrario, devolverá "whatever"
.
La ejecución de PROJECT_ENV=test sbt test
envejecerá rápidamente, por lo que puede hacer que SBT establezca la variable de entorno cuando se ejecuta el conjunto de pruebas.
fork in Test := true
envVars in Test := Map("PROJECT_ENV" -> "test")
Aquí es cómo anular la configuración existente.
Config.test = Config.test ++ Map("somethingElse" -> "give me clean air")
Aquí hay un enlace al blog completo que escribí sobre este tema.
¿Cuál es una buena manera de configurar un proyecto en Scala que utiliza una configuración diferente según los entornos?
Necesito tener específicamente diferentes bases de datos para el entorno de desarrollo , prueba y producción (similar a lo que se hace en Rails)
No estaba contento con la forma en que la solución de Daniel Cukiers no permitía los valores predeterminados ni las anulaciones, así que la cambié para hacer un uso completo de ellos.
La única configuración que debe hacer es establecer una variable de MEDIO AMBIENTE en el sistema (el valor predeterminado es ''dev'' si no se establece ninguno)
(Solución Java, compatible con Scala):
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
public class MyCompanyConfig {
public final static Config base = ConfigFactory.load().getConfig("mycompany");
public final static String environment = System.getenv("ENVIRONMENT") == null ? "dev" : System.getenv("ENVIRONMENT");
/**
* Returns a subtree of the base configuration with environment settings applied.
*
* @param setting The subtree to return config for.
* @return A config with base in given setting, with environment modifications applied.
*/
public static Config load(String setting) {
Config config = base.getConfig(setting);
if (config.hasPath(environment)) {
return config.getConfig(environment).withFallback(config);
}
return config;
}
}
Esto permite un simple reference.conf en una biblioteca con este aspecto:
mycompany.module1 {
setting1 : "adefaultvalue"
url : "localhost"
test {
// will be used where ENVIRONMENT="test"
url : "test.mycompany.com"
}
prod {
// will be used where ENVIRONMENT="prod"
setting1 : "changethedefault"
url : "www.mycompany.com"
}
}
Uso:
Config conf = MyCompanyConfig.load("module1")
Utilice la configuración segura. Crea un objeto Config como este:
import com.typesafe.config._
object Config {
val env = if (System.getenv("SCALA_ENV") == null) "development" else System.getenv("SCALA_ENV")
val conf = ConfigFactory.load()
def apply() = conf.getConfig(env)
}
Luego cree el archivo application.conf
en la carpeta src/main/resources
:
development {
your_app {
databaseUrl = "jdbc:mysql://localhost:3306/dev_db"
databaseUser = "xxxx"
databasePassword = "xxxx"
}
}
test {
your_app {
databaseUrl = "jdbc:mysql://localhost:3306/test_db"
databaseUser = "xxxxx"
databasePassword = "xxxx"
}
}
Ahora desde cualquier lugar en su aplicación, puede acceder a la configuración:
Config (). GetString ("your_app.databaseUrl")
Si tiene configurado su entorno (por ejemplo, export SCALA_ENV=test
) cuando ejecute su aplicación, considerará la sección de configuración correcta. El valor predeterminado es el desarrollo.
Otra estrategia que estoy usando consiste en usar includes . Por lo general, almaceno mis configuraciones de DEV en el archivo de application.conf
default application.conf
, luego creo un nuevo archivo de configuración para otros entornos e incluyo el predeterminado.
Digamos que mi DEV conf application.conf
tiene este aspecto:
myapp {
server-address = "localhost"
server-port = 9000
some-other-setting = "cool !"
}
Luego para el PROD, podría tener otro archivo llamado prod.conf
:
include "application"
# override default (DEV) settings
myapp {
server-address = ${PROD_SERVER_HOSTNAME}
server-port = ${PROD_SERVER_PORT}
}
Tenga en cuenta que anulo solo las configuraciones que cambian en el entorno PROD ( some-other-setting
son las mismas que en DEV).
El código de arranque de configuración no prueba nada
...
val conf = ConfigFactory.load()
...
Para cambiar de DEV a PROD conf, simplemente pase una propiedad del sistema con el nombre del archivo de configuración para cargar:
java -Dconfig.resource=prod.conf ...
En DEV, no es necesario que lo pase, ya que se cargará application.conf
de default .
Así que aquí estamos usando el mecanismo de carga predeterminado de Typesafe Config para lograr esto.
He creado un project simple para demostrar esta técnica. Siéntete libre de clonar y experimentar.