web-dev-qa-db-fra.com

configuration spécifique par environnement en Scala

Quel est un bon moyen de mettre en place un projet dans Scala qui utilise une configuration différente selon les environnements.

Je dois spécifiquement avoir différentes bases de données pour développement , test et production environnement (similaire à ce qui est fait dans Rails)

20
Daniel Cukier

Une autre stratégie que j'utilise consiste à utiliser includes . Je stocke généralement mes paramètres DEV dans le fichier defaultapplication.conf, puis je crée un nouveau fichier de configuration pour les autres. environnements et inclure celui par défaut.

Disons que mon confconcode application.conf ressemble à ceci:

myapp {
    server-address = "localhost"
    server-port = 9000

    some-other-setting = "cool !"
}

Ensuite, pour le PROD, je pourrais avoir un autre fichier appelé prod.conf:

include "application"

# override default (DEV) settings
myapp {
    server-address = ${PROD_SERVER_HOSTNAME}
    server-port = ${PROD_SERVER_PORT}
}

Notez que je remplace only les paramètres qui changent dans l’environnement PROD (some-other-setting est donc identique à celui de DEV).

Le code d'amorçage de configuration ne teste rien

...
val conf = ConfigFactory.load()
...

Pour passer du DEV à la conf PROD, il suffit de passer une propriété système avec le nom du fichier de configuration à charger:

Java -Dconfig.resource=prod.conf ...

En DEV, pas besoin de le passer car application.conf sera chargé par default .

Nous utilisons donc ici le mécanisme de chargement par défaut de Typesafe Config pour y parvenir.

J'ai créé un simple projet pour démontrer cette technique. N'hésitez pas à cloner et à expérimenter.

40
ozeebee

Utilisez la configuration typesafe. Créez un objet de configuration comme ceci:

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)
}

Créez ensuite le fichier application.conf dans le dossier 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"
  }
}

Désormais, depuis n'importe où dans votre application, vous pouvez accéder à la configuration:

Config (). GetString ("your_app.databaseUrl")

Si votre environnement est configuré (par exemple, export SCALA_ENV=test) lorsque vous exécutez votre application, il considérera la section de configuration appropriée. Le défaut est le développement

20
Daniel Cukier

Je n'étais pas satisfait de la solution proposée par Daniel Cukiers qui n'autorisait pas les valeurs par défaut ni les substitutions. Je l'ai donc modifiée pour en tirer le meilleur parti.

La seule configuration à faire est de définir une variable ENVIRONMENT sur le système (la valeur par défaut est 'dev' si aucune n'est définie)

(Solution Java compatible avec 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;
    }
}

Cela permet à une seule référence.conf dans une bibliothèque de ressembler à ceci:

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"
    }
}

Usage:

Config conf = MyCompanyConfig.load("module1")
2
DHa

Voici une solution qui se trouve dans Scala, permet des substitutions et ne repose pas sur une bibliothèque externe.

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 défini sur test, Config.get("somethingElse") renverra "hi". Sinon, il retournera "whatever".

L'exécution de PROJECT_ENV=test sbt test vieillira rapidement, vous pouvez donc laisser SBT définir la variable d'environnement lors de l'exécution de la suite de tests.

fork in Test := true
envVars in Test := Map("PROJECT_ENV" -> "test")

Voici comment remplacer la configuration existante.

Config.test = Config.test ++ Map("somethingElse" -> "give me clean air")

Voici un lien vers le blog complet J'ai écrit sur ce sujet.

0
Powers