Skip to content

Commit

Permalink
iss #24: universal config: postprocessors, config parsers
Browse files Browse the repository at this point in the history
  • Loading branch information
maizy committed Jan 10, 2017
1 parent bc3532a commit 95debaa
Show file tree
Hide file tree
Showing 22 changed files with 432 additions and 110 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ object OptionParser {
.action { (value, opts) => opts.copy(influxDbReadonlyPassword = Some(value)) },

opt[String]("influxdb-tags")
.validate{ value => AgentTags.tryParseFromString(value).right.map(v => Unit) }
.validate{ value => AgentTags.tryParseFromString(value).right.map(v => ()) }
.valueName { "<position=outdoor,altitude=200,some=val\\,ue>" }
.action { (value, opts) => opts.copy(influxDbTags = AgentTags.apply(value)) }
.text { "Any additional InfluxDB record tags for filtering data"}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package ru.maizy.ambient7.webapp

/**
* Copyright (c) Nikita Kovaliov, maizy.ru, 2016
* See LICENSE.txt for details.
*/

import ru.maizy.ambient7.core.config.{ MainDbConfigReader, UniversalConfigReader }

object WebAppConfigReader
extends UniversalConfigReader
with MainDbConfigReader
{
override def appName: String = "java -jar ambient7-webapp.jar"

override def fillReader(): Unit = {
fillConfigOptions(requireUniversalConfig = true)
fillDbOptions()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ package ru.maizy.ambient7.webapp
*/
object WebAppLauncher extends App {

val config = WebAppConfigParser
config.fillParser()
val eitherAppConfig = config.parse(args.toSeq)
val config = WebAppConfigReader
config.fillReader()
val eitherAppConfig = config.readAppConfig(args.toIndexedSeq)
println(eitherAppConfig)

// TODO: launch jetty app
// TODO: launch jetty app (merge with JettyLauncher)
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ trait TestsBootstrap extends ScalikeJdbcInit with AppConfigInit with LazyLogging
def loadTestConfig(): Unit = {
logger.info("load test config")
loadAppConfig()
()
}

def overwriteAppConfig(config: AppConfig): Unit = {
Expand All @@ -35,6 +36,7 @@ trait TestsBootstrap extends ScalikeJdbcInit with AppConfigInit with LazyLogging
val flyway = new Flyway()
flyway.setDataSource(ConnectionPool.get().dataSource)
flyway.migrate()
()
}

def destroyWebApp(): Unit = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,5 +183,6 @@ class Co2ReportServletSpec extends BaseServletAndDbTest with JsonAsserts {
(item \\ "unknown_level") shouldBe JInt(expected.unknown)
(item \\ "from" \\ "local_iso8601") shouldBe JString(expectedFrom.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME))
(item \\ "from" \\ "zone") shouldBe JString(expectedFrom.getZone.getId)
()
}
}
3 changes: 2 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ val scalacOpts = Seq(
"-Ywarn-nullary-override",
"-Ywarn-nullary-unit",
"-Ywarn-numeric-widen",
"-Ywarn-unused"
"-Ywarn-unused",
"-Ywarn-value-discard"
)
lazy val commonSettings = Seq(
organization := "ru.maizy",
Expand Down
22 changes: 22 additions & 0 deletions config/application.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// sample production config
db {
url = "jdbc:h2:file:/var/ambient7/analysis;AUTO_SERVER=TRUE"
user = "ambient7"
password = ""
}

co2-devices = [
{
id = "main"
agent-name = "main"
agent-tags = ""
model = "mt8057"
}

{
id = "additional"
agent-name = "additional"
agent-tags = "place=livingroom,altitude=200"
model = "mt8057"
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ package ru.maizy.ambient7.core.config
* See LICENSE.txt for details.
*/

import java.nio.file.Path

case class Ambient7Options(
mainConfigPath: Option[String] = None,
mainInfluxDd: Option[InfluxDbOptions] = None,
universalConfigPath: Option[Path] = None,
influxDb: Option[InfluxDbOptions] = None,
mainDb: Option[DbOptions] = None
)
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@ package ru.maizy.ambient7.core.config
* See LICENSE.txt for details.
*/

import java.nio.file.{ FileSystems, Path }

case object Defaults {
val INFLUXDB_BASEURL = "http://localhost:8086/"
val INFLUXDB_AGENT_NAME = "main"
val DB_USER = "ambient7"
val DB_PASSWORD = "ambient7"
val DB_PASSWORD = ""
val DB_URL = "jdbc:h2:file:/var/ambient7/analysis;AUTO_SERVER=TRUE"
val UNIVERSAL_CONFIG_PATH: Path = FileSystems.getDefault.getPath("/etc", "ambient7", "application.conf")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package ru.maizy.ambient7.core.config

/**
* Copyright (c) Nikita Kovaliov, maizy.ru, 2016
* See LICENSE.txt for details.
*/
trait InfluxDbConfigReader extends UniversalConfigReader {

private def influxDbOpts(opts: Ambient7Options)(fill: InfluxDbOptions => InfluxDbOptions): Ambient7Options = {
opts.copy(influxDb = Some(fill(opts.influxDb.getOrElse(InfluxDbOptions()))))
}

private def appendInfluxDbOptsCheck(check: InfluxDbOptions => Either[IndexedSeq[String], Unit]): Unit =
appendCheck { appOpts =>
appOpts.influxDb match {
case Some(influxDbOptions) => check(influxDbOptions)
case _ => Left(IndexedSeq("InfluxDB opts not defined"))
}
}

// private def appendInfluxDbOptsPostprocessor(postprocessor: InfluxDbOptions => ParseResult): Unit =
// appendPostprocessor { appOpts =>
// appOpts.influxDb match {
// case Some(influxDbOptions) => postprocessor(influxDbOptions)
// case _ => Right(appOpts)
// }
// }

def fillInfluxDbOptions(): Unit = {

cliParser.opt[String]("influxdb-baseurl")
.valueName { s"<${Defaults.INFLUXDB_BASEURL}>" }
.action { (value, opts) => influxDbOpts(opts)(_.copy(baseUrl = value)) }


cliParser.opt[String]("influxdb-database")
.action { (value, opts) => influxDbOpts(opts)(_.copy(database = Some(value))) }
.required()

appendInfluxDbOptsCheck({
opts => Either.cond(opts.database.isDefined, (), IndexedSeq("influxdb-database is required"))
})


cliParser.opt[String]("influxdb-user")
.action { (value, opts) => influxDbOpts(opts)(_.copy(user = Some(value))) }

appendInfluxDbOptsCheck({
opts => Either.cond(opts.user.isDefined, (), IndexedSeq("influxdb-user is required"))
})


cliParser.opt[String]("influxdb-password")
.action { (value, opts) => influxDbOpts(opts)(_.copy(password = Some(value))) }

appendInfluxDbOptsCheck({
opts => Either.cond(opts.password.isDefined, (), IndexedSeq("influxdb-password is required"))
})


cliParser.opt[String]("influxdb-readonly-baseurl")
.action { (value, opts) => influxDbOpts(opts)(_.copy(readonlyBaseUrl = Some(value))) }
.text("By default --influxdb-baseurl")


cliParser.opt[String]("influxdb-readonly-user")
.action { (value, opts) => influxDbOpts(opts)(_.copy(readonlyUser = Some(value))) }
.text("By default --influxdb-user")

appendInfluxDbOptsCheck({
opts => Either.cond(opts.readonlyUser.isDefined, (), IndexedSeq("influxdb-readonly-user is required"))
})


cliParser.opt[String]("influxdb-readonly-password")
.action { (value, opts) => influxDbOpts(opts)(_.copy(readonlyPassword = Some(value))) }
.text("By default --influxdb-password")

appendInfluxDbOptsCheck({
opts => Either.cond(opts.readonlyPassword.isDefined, (), IndexedSeq("influxdb-readonly-password is required"))
})

// TODO: uni config rules

// TODO: config postprocessors

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ package ru.maizy.ambient7.core.config
*/

case class InfluxDbOptions(
baseUrl: String = Defaults.INFLUXDB_BASEURL,
database: Option[String] = None,

baseUrl: String = Defaults.INFLUXDB_BASEURL,
user: Option[String] = None,
password: Option[String] = None,
agentName: String = Defaults.INFLUXDB_AGENT_NAME,
tags: String = ""

readonlyBaseUrl: Option[String] = None,
readonlyUser: Option[String] = None,
readonlyPassword: Option[String] = None
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,42 @@ package ru.maizy.ambient7.core.config
* Copyright (c) Nikita Kovaliov, maizy.ru, 2016
* See LICENSE.txt for details.
*/
trait MainDbConfigParser extends UniversalConfigParser {
trait MainDbConfigReader extends UniversalConfigReader {

private def mainDbOpts(opts: Ambient7Options)(fill: DbOptions => DbOptions): Ambient7Options = {
opts.copy(mainDb = Some(fill(opts.mainDb.getOrElse(DbOptions()))))
}

private def appendDbOptsCheck(check: DbOptions => Either[String, Unit]): Unit = {
appendCheck {
case Some(appOpts) => appOpts.mainDb match {
private def appendDbOptsCheck(check: DbOptions => CheckResult): Unit =
appendCheck { appOpts =>
appOpts.mainDb match {
case Some(dbOpts) => check(dbOpts)
case _ => Left("DB opts not defined")
}
case _ => Left("App opts not defined")
case _ => Left(IndexedSeq("DB opts not defined"))
}
}
}

def fillDbOptions(): Unit = {

parser.opt[String]("db-url")
// TODO: uni config rules

cliParser.opt[String]("db-url")
.abbr("d")
.valueName(s"<${Defaults.DB_URL}>")
.action { (value, opts) => mainDbOpts(opts)(_.copy(url = Some(value))) }
.text(s"URL for connecting to h2 database")

parser.opt[String]("db-user")
appendDbOptsCheck{ dbOpts => Either.cond(dbOpts.url.isDefined, (), IndexedSeq("db-url is required")) }


cliParser.opt[String]("db-user")
.action { (value, opts) => mainDbOpts(opts)(_.copy(user = value)) }
.text("database user")

parser.opt[String]("db-password")

cliParser.opt[String]("db-password")
.action { (value, opts) => mainDbOpts(opts)(_.copy(password = value)) }
.text("database password")

// TODO: uni config rules

appendDbOptsCheck{ dbOpts => Either.cond(dbOpts.url.isDefined, Unit, "db-url is required") }
()
}
}

This file was deleted.

Loading

0 comments on commit 95debaa

Please sign in to comment.