wake-up-neo.com

spezifische Konfiguration nach Umgebung in Scala

Was ist eine gute Möglichkeit, ein Projekt in Scala einzurichten, das je nach Umgebung eine andere Konfiguration verwendet.

Ich muss speziell unterschiedliche Datenbanken für Entwicklung , Test und Produktion Umgebung haben (ähnlich wie in Rails)

20
Daniel Cukier

Eine andere Strategie, die ich verwende, besteht in der Verwendung von Includes . Ich speichere meine DEV-Einstellungen normalerweise in der Standardapplication.conf-Datei und erstelle dann eine neue conf-Datei für andere Umgebungen und enthalten die Standardumgebung.

Nehmen wir an, mein DEV conf application.conf sieht folgendermaßen aus:

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

    some-other-setting = "cool !"
}

Dann könnte ich für die PROD eine andere Datei namens prod.conf haben:

include "application"

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

Beachten Sie, dass ich only die Einstellungen überschreibe, die sich in der PROD-Umgebung ändern (some-other-setting ist also die gleiche wie in DEV).

Der Konfigurations-Bootstrap-Code testet nichts

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

Um vom DEV zum PROD conf zu wechseln, übergeben Sie einfach eine Systemeigenschaft mit dem Namen der zu ladenden Konfigurationsdatei:

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

In DEV müssen Sie sie nicht übergeben, da application.conf von Standard geladen wird.

Hier verwenden wir den Standardlademechanismus von Typesafe Config , um dies zu erreichen.

Ich habe ein einfaches Projekt erstellt, um diese Technik zu demonstrieren. Fühlen Sie sich frei zu klonen und zu experimentieren.

40
ozeebee

Verwenden Sie typsichere Konfig. Erstellen Sie ein Config-Objekt wie folgt:

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

Dann erstellen Sie die application.conf-Datei im src/main/resources-Ordner:

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

Jetzt können Sie von überall in Ihrer Anwendung auf die Konfiguration zugreifen:

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

Wenn Sie Ihre Umgebung beim Ausführen Ihrer Anwendung eingerichtet haben (z. B. export SCALA_ENV=test), wird der richtige Konfigurationsabschnitt berücksichtigt. Der Standardwert ist Entwicklung

20
Daniel Cukier

Ich war nicht zufrieden damit, dass die Lösung von Daniel Cukiers keine Standardeinstellungen und Überschreibungen zulässt. Daher habe ich sie geändert, um sie vollständig zu nutzen.

Sie müssen lediglich eine ENVIRONMENT-Variable im System einstellen (Standardeinstellung ist "dev", wenn keine gesetzt ist).

(Java-Lösung, kompatibel mit 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;
    }
}

Dies ermöglicht eine einzelne reference.conf in einer Bibliothek, die folgendermaßen aussieht:

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

Verwendungszweck:

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

Hier ist eine Lösung in Scala, die Überschreibungen zulässt und nicht auf eine externe Bibliothek angewiesen ist.

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

}

Wenn PROJECT_ENV auf test eingestellt ist, gibt Config.get("somethingElse")"hi" zurück. Andernfalls wird "whatever" zurückgegeben.

Das Ausführen von PROJECT_ENV=test sbt test wird schnell alt, sodass Sie SBT die Umgebungsvariable setzen können, wenn die Testsuite ausgeführt wird.

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

So können Sie die vorhandene Konfiguration überschreiben.

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

Hier ist ein Link zum vollständigen Blogbeitrag Ich habe zu diesem Thema geschrieben.

0
Powers