org.flywaydb.core.Flyway Scala Examples

The following examples show how to use org.flywaydb.core.Flyway. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example.
Example 1
Source File: FlywayMigration.scala    From seahorse   with Apache License 2.0 5 votes vote down vote up
package ai.deepsense.seahorse.datasource.db

import org.flywaydb.core.Flyway

import ai.deepsense.seahorse.datasource.DatasourceManagerConfig

object FlywayMigration {

  private val db = DatasourceManagerConfig.database

  def run(): Unit = {
    val flyway = new Flyway
    flyway.setLocations("db.migration.datasourcemanager")
    flyway.setSchemas(db.schema)
    flyway.setDataSource(DatasourceManagerConfig.config.getString("databaseSlick.db.url"), "", "")
    flyway.migrate()
  }
} 
Example 2
Source File: FlywayModule.scala    From scala-server-toolkit   with MIT License 5 votes vote down vote up
package com.avast.sst.flyway

import cats.effect.Sync
import javax.sql.DataSource
import org.flywaydb.core.Flyway

import scala.jdk.CollectionConverters._

object FlywayModule {

  
  def make[F[_]: Sync](dataSource: DataSource, config: FlywayConfig): F[Flyway] = {
    Sync[F].delay {
      val builder = Flyway.configure
        .dataSource(dataSource)
        .baselineOnMigrate(config.baselineOnMigrate)
        .cleanDisabled(config.cleanDisabled)
        .cleanOnValidationError(config.cleanOnValidationError)
        .connectRetries(config.connectRetries)
        .encoding(config.encoding)
        .group(config.group)
        .ignoreFutureMigrations(config.ignoreFutureMigrations)
        .ignoreIgnoredMigrations(config.ignoreIgnoredMigrations)
        .ignoreMissingMigrations(config.ignoreMissingMigrations)
        .ignorePendingMigrations(config.ignorePendingMigrations)
        .mixed(config.mixed)
        .outOfOrder(config.outOfOrder)
        .validateOnMigrate(config.validateOnMigrate)
        .placeholderReplacement(config.placeholderReplacement)
        .placeholders(config.placeholders.asJava)

      config.baselineVersion.foreach(builder.baselineVersion)
      config.targetVersion.foreach(builder.target)
      config.baselineDescription.foreach(builder.baselineDescription)
      config.installedBy.foreach(builder.installedBy)
      if (config.locations.nonEmpty) builder.locations(config.locations: _*)

      builder.load()
    }
  }

} 
Example 3
Source File: SqlDatabase.scala    From scala-clippy   with Apache License 2.0 5 votes vote down vote up
package util

import java.net.URI

import com.typesafe.config.ConfigValueFactory._
import com.typesafe.config.{Config, ConfigFactory}
import com.typesafe.scalalogging.StrictLogging
import org.flywaydb.core.Flyway
import slick.driver.JdbcProfile
import slick.jdbc.JdbcBackend._

case class SqlDatabase(
    db: slick.jdbc.JdbcBackend#Database,
    driver: JdbcProfile,
    connectionString: JdbcConnectionString
) {
  def updateSchema() {
    val flyway = new Flyway()
    flyway.setDataSource(connectionString.url, connectionString.username, connectionString.password)
    flyway.migrate()
  }

  def close() {
    db.close()
  }
}

case class JdbcConnectionString(url: String, username: String = "", password: String = "")

object SqlDatabase extends StrictLogging {

  def create(config: DatabaseConfig): SqlDatabase = {
    val envDatabaseUrl = System.getenv("DATABASE_URL")

    if (config.dbPostgresServerName.length > 0)
      createPostgresFromConfig(config)
    else if (envDatabaseUrl != null)
      createPostgresFromEnv(envDatabaseUrl)
    else
      createEmbedded(config)
  }

  def createEmbedded(connectionString: String): SqlDatabase = {
    val db = Database.forURL(connectionString)
    SqlDatabase(db, slick.driver.H2Driver, JdbcConnectionString(connectionString))
  }

  private def createPostgresFromEnv(envDatabaseUrl: String) = {
    import DatabaseConfig._
    
    val dbUri    = new URI(envDatabaseUrl)
    val username = dbUri.getUserInfo.split(":")(0)
    val password = dbUri.getUserInfo.split(":")(1)
    val intermediaryConfig = new DatabaseConfig {
      override def rootConfig: Config =
        ConfigFactory
          .empty()
          .withValue(PostgresDSClass, fromAnyRef("org.postgresql.ds.PGSimpleDataSource"))
          .withValue(PostgresServerNameKey, fromAnyRef(dbUri.getHost))
          .withValue(PostgresPortKey, fromAnyRef(dbUri.getPort))
          .withValue(PostgresDbNameKey, fromAnyRef(dbUri.getPath.tail))
          .withValue(PostgresUsernameKey, fromAnyRef(username))
          .withValue(PostgresPasswordKey, fromAnyRef(password))
          .withFallback(ConfigFactory.load())
    }
    createPostgresFromConfig(intermediaryConfig)
  }

  private def postgresUrl(host: String, port: String, dbName: String) =
    s"jdbc:postgresql://$host:$port/$dbName"

  private def postgresConnectionString(config: DatabaseConfig) = {
    val host     = config.dbPostgresServerName
    val port     = config.dbPostgresPort
    val dbName   = config.dbPostgresDbName
    val username = config.dbPostgresUsername
    val password = config.dbPostgresPassword
    JdbcConnectionString(postgresUrl(host, port, dbName), username, password)
  }

  private def createPostgresFromConfig(config: DatabaseConfig) = {
    val db = Database.forConfig("db.postgres", config.rootConfig)
    SqlDatabase(db, slick.driver.PostgresDriver, postgresConnectionString(config))
  }

  private def createEmbedded(config: DatabaseConfig): SqlDatabase = {
    val db = Database.forConfig("db.h2")
    SqlDatabase(db, slick.driver.H2Driver, JdbcConnectionString(embeddedConnectionStringFromConfig(config)))
  }

  private def embeddedConnectionStringFromConfig(config: DatabaseConfig): String = {
    val url      = config.dbH2Url
    val fullPath = url.split(":")(3)
    logger.info(s"Using an embedded database, with data files located at: $fullPath")
    url
  }
} 
Example 4
Source File: FlatSpecWithSql.scala    From akka-http-rest-api   with MIT License 5 votes vote down vote up
package utils

import org.flywaydb.core.Flyway
import org.scalatest.concurrent.ScalaFutures
import org.scalatest.{BeforeAndAfterAll, BeforeAndAfterEach, FlatSpec}
import slick.driver.H2Driver.api._

trait FlatSpecWithSql extends FlatSpec with BeforeAndAfterAll with BeforeAndAfterEach with ScalaFutures {

  private val connectionString = "jdbc:h2:mem:rest_api_test" + this.getClass.getSimpleName + ";DB_CLOSE_DELAY=-1"
  implicit val db = Database.forURL(connectionString)

  override protected def beforeAll() {
    super.beforeAll()
    createAll()
  }

  private def createAll() {
    val flyway = new Flyway()
    flyway.setDataSource(connectionString, "", "")
    flyway.migrate()
  }

  override protected def afterAll() {
    super.afterAll()
    dropAll()
    db.close()
  }

  private def dropAll() {
    db.run(sqlu"DROP ALL OBJECTS").futureValue
  }

  override protected def afterEach() {
    try {
      clearData()
    }
    catch {
      case e: Exception => e.printStackTrace()
    }

    super.afterEach()
  }

  private def clearData() {
    dropAll()
    createAll()
  }
} 
Example 5
Source File: FlywayDatabaseMigratorTest.scala    From pfhais   with Creative Commons Attribution Share Alike 4.0 International 5 votes vote down vote up
package com.wegtam.books.pfhais.tapir.db

import cats.effect._
import com.wegtam.books.pfhais.BaseSpec
import com.wegtam.books.pfhais.tapir.config._
import eu.timepit.refined.auto._
import org.flywaydb.core.Flyway
import org.flywaydb.core.api.FlywayException

final class FlywayDatabaseMigratorTest extends BaseSpec {

  override def beforeEach(): Unit = {
    dbConfig.foreach { cfg =>
      val flyway: Flyway = Flyway.configure().dataSource(cfg.url, cfg.user, cfg.pass).load()
      val _ = flyway.migrate()
      flyway.clean()
    }
  }

  override def afterEach(): Unit = {
    dbConfig.foreach { cfg =>
      val flyway: Flyway = Flyway.configure().dataSource(cfg.url, cfg.user, cfg.pass).load()
      flyway.clean()
    }
  }

  "FlywayDatabaseMigrator#migrate" when {
    "the database is configured and available" when {
      "the database is not up to date" must {
        "return the number of applied migrations" in {
          dbConfig.map { cfg =>
            val migrator: DatabaseMigrator[IO] = new FlywayDatabaseMigrator
            val program = migrator.migrate(cfg.url, cfg.user, cfg.pass)
            program.unsafeRunSync must be > 0
          }
        }
      }

      "the database is up to date" must {
        "return zero" in {
          dbConfig.map { cfg =>
            val migrator: DatabaseMigrator[IO] = new FlywayDatabaseMigrator
            val program = migrator.migrate(cfg.url, cfg.user, cfg.pass)
            val _ = program.unsafeRunSync
            program.unsafeRunSync must be(0)
          }
        }
      }
    }

    "the database is not available" must {
      "throw an exception" in {
        val cfg = DatabaseConfig(
          driver = "This is no driver name!",
          url = "jdbc://some.host/whatever",
          user = "no-user",
          pass = "no-password"
        )
        val migrator: DatabaseMigrator[IO] = new FlywayDatabaseMigrator
        val program = migrator.migrate(cfg.url, cfg.user, cfg.pass)
        an[FlywayException] must be thrownBy program.unsafeRunSync
      }
    }
  }

} 
Example 6
Source File: Impure.scala    From pfhais   with Creative Commons Attribution Share Alike 4.0 International 5 votes vote down vote up
package com.wegtam.books.pfhais.impure

import akka.actor._
import akka.http.scaladsl._
import akka.http.scaladsl.server.Directives._
import akka.stream._
import com.wegtam.books.pfhais.impure.api._
import com.wegtam.books.pfhais.impure.db._
import eu.timepit.refined.auto._
import org.flywaydb.core.Flyway
import slick.basic._
import slick.jdbc._

import scala.io.StdIn
import scala.concurrent.ExecutionContext

object Impure {

  
  @SuppressWarnings(Array("org.wartremover.warts.Any"))
  def main(args: Array[String]): Unit = {
    implicit val system: ActorSystem    = ActorSystem()
    implicit val mat: ActorMaterializer = ActorMaterializer()
    implicit val ec: ExecutionContext   = system.dispatcher

    val url = "jdbc:postgresql://" +
      system.settings.config.getString("database.db.properties.serverName") +
      ":" + system.settings.config.getString("database.db.properties.portNumber") +
      "/" + system.settings.config.getString("database.db.properties.databaseName")
    val user           = system.settings.config.getString("database.db.properties.user")
    val pass           = system.settings.config.getString("database.db.properties.password")
    val flyway: Flyway = Flyway.configure().dataSource(url, user, pass).load()
    val _              = flyway.migrate()

    val dbConfig: DatabaseConfig[JdbcProfile] =
      DatabaseConfig.forConfig("database", system.settings.config)
    val repo = new Repository(dbConfig)

    val productRoutes  = new ProductRoutes(repo)
    val productsRoutes = new ProductsRoutes(repo)
    val routes         = productRoutes.routes ~ productsRoutes.routes

    val host       = system.settings.config.getString("api.host")
    val port       = system.settings.config.getInt("api.port")
    val srv        = Http().bindAndHandle(routes, host, port)
    val pressEnter = StdIn.readLine()
    srv.flatMap(_.unbind()).onComplete(_ => system.terminate())
  }

} 
Example 7
Source File: FlywayDatabaseMigratorTest.scala    From pfhais   with Creative Commons Attribution Share Alike 4.0 International 5 votes vote down vote up
package com.wegtam.books.pfhais.pure.db

import cats.effect._
import com.wegtam.books.pfhais.BaseSpec
import com.wegtam.books.pfhais.pure.config._
import eu.timepit.refined.auto._
import org.flywaydb.core.Flyway
import org.flywaydb.core.api.FlywayException

final class FlywayDatabaseMigratorTest extends BaseSpec {

  override def beforeEach(): Unit = {
    dbConfig.foreach { cfg =>
      val flyway: Flyway = Flyway.configure().dataSource(cfg.url, cfg.user, cfg.pass).load()
      val _ = flyway.migrate()
      flyway.clean()
    }
  }

  override def afterEach(): Unit = {
    dbConfig.foreach { cfg =>
      val flyway: Flyway = Flyway.configure().dataSource(cfg.url, cfg.user, cfg.pass).load()
      flyway.clean()
    }
  }

  "FlywayDatabaseMigrator#migrate" when {
    "the database is configured and available" when {
      "the database is not up to date" must {
        "return the number of applied migrations" in {
          dbConfig.map { cfg =>
            val migrator: DatabaseMigrator[IO] = new FlywayDatabaseMigrator
            val program = migrator.migrate(cfg.url, cfg.user, cfg.pass)
            program.unsafeRunSync must be > 0
          }
        }
      }

      "the database is up to date" must {
        "return zero" in {
          dbConfig.map { cfg =>
            val migrator: DatabaseMigrator[IO] = new FlywayDatabaseMigrator
            val program = migrator.migrate(cfg.url, cfg.user, cfg.pass)
            val _ = program.unsafeRunSync
            program.unsafeRunSync must be(0)
          }
        }
      }
    }

    "the database is not available" must {
      "throw an exception" in {
        val cfg = DatabaseConfig(
          driver = "This is no driver name!",
          url = "jdbc://some.host/whatever",
          user = "no-user",
          pass = "no-password"
        )
        val migrator: DatabaseMigrator[IO] = new FlywayDatabaseMigrator
        val program = migrator.migrate(cfg.url, cfg.user, cfg.pass)
        an[FlywayException] must be thrownBy program.unsafeRunSync
      }
    }
  }

} 
Example 8
Source File: TestDBManager.scala    From core   with Apache License 2.0 5 votes vote down vote up
package com.smartbackpackerapp.common.sql

import cats.effect.IO
import doobie.h2.H2Transactor
import doobie.util.transactor.Transactor
import org.flywaydb.core.Flyway

object TestDBManager {

  private def testDbUrl(dbName: String): String =
    s"jdbc:h2:mem:test_sb_$dbName;MODE=PostgreSQL;DB_CLOSE_DELAY=-1"

  private val testDbUser = "sa"
  private val testDbPass = ""

  def xa(dbName: String): IO[Transactor[IO]] =
    H2Transactor.newH2Transactor[IO](testDbUrl(dbName), testDbUser, testDbPass)

  def createTables(dbName: String): IO[Unit] =
    IO {
      val flyway = new Flyway
      flyway.setDataSource(testDbUrl(dbName), testDbUser, testDbPass)
      flyway.migrate()
    }

} 
Example 9
Source File: SchemaInstaller.scala    From modelmatrix   with Apache License 2.0 5 votes vote down vote up
package com.collective.modelmatrix.db

import org.flywaydb.core.Flyway

trait SchemaInstaller {
  val dbConfig: DatabaseConfig

  def installOrMigrate(): Boolean = {
    val flyway = new Flyway
    flyway.setBaselineOnMigrate(true)
    flyway.setBaselineVersionAsString("000")
    flyway.setTable("mmc_schema_version")
    flyway.setDataSource(dbConfig.dbUrl, null, null)
    flyway.setSqlMigrationPrefix("mmc")
    flyway.setLocations(dbConfig.migrationPath)
    val appliedMigrations = flyway.migrate()

    Console.println(s"Schema successfully installed. Applied migrations: $appliedMigrations")
    return true
  }
} 
Example 10
Source File: DatabaseConfig.scala    From scala-pet-store   with Apache License 2.0 5 votes vote down vote up
package io.github.pauljamescleary.petstore.config

import cats.syntax.functor._
import cats.effect.{Async, Blocker, ContextShift, Resource, Sync}
import doobie.hikari.HikariTransactor
import org.flywaydb.core.Flyway

import scala.concurrent.ExecutionContext

case class DatabaseConnectionsConfig(poolSize: Int)
case class DatabaseConfig(
    url: String,
    driver: String,
    user: String,
    password: String,
    connections: DatabaseConnectionsConfig,
)

object DatabaseConfig {
  def dbTransactor[F[_]: Async: ContextShift](
      dbc: DatabaseConfig,
      connEc: ExecutionContext,
      blocker: Blocker,
  ): Resource[F, HikariTransactor[F]] =
    HikariTransactor
      .newHikariTransactor[F](dbc.driver, dbc.url, dbc.user, dbc.password, connEc, blocker)

  
  def initializeDb[F[_]](cfg: DatabaseConfig)(implicit S: Sync[F]): F[Unit] =
    S.delay {
        val fw: Flyway = {
          Flyway
            .configure()
            .dataSource(cfg.url, cfg.user, cfg.password)
            .load()
        }
        fw.migrate()
      }
      .as(())
} 
Example 11
Source File: Migrate.scala    From nelson   with Apache License 2.0 5 votes vote down vote up
package nelson
package storage

import cats.effect.IO
import org.flywaydb.core.Flyway
import journal.Logger

object Migrate {

  val log = Logger[Migrate.type]

  def migrate(cfg: DatabaseConfig): IO[Unit] =
    IO {
      val flyway = new Flyway
      flyway.setDataSource(
        cfg.connection,
        cfg.username.getOrElse(""),
        cfg.password.getOrElse(""))

      try {
        log.info("Conducting database schema migrations if needed.")
        val completed = flyway.migrate()
        log.info(s"Completed $completed succsessful migrations.")
      } catch {
        case e: Throwable => {
          // attempt a repair (useful for local debugging)
          log.error(s"Failed to migrate database. ${e.getMessage}")
          log.info("Repairing database before retrying migration")
          flyway.repair()
          val completed = flyway.migrate()
          log.info(s"After repair, completed $completed succsessful migrations.")
        }
      }
    }
} 
Example 12
Source File: FlywayUtils.scala    From gospeak   with Apache License 2.0 5 votes vote down vote up
package gospeak.infra.services.storage.sql.utils

import com.zaxxer.hikari.{HikariConfig, HikariDataSource}
import gospeak.core.services.storage.DbConf
import org.flywaydb.core.Flyway

object FlywayUtils {
  def build(conf: DbConf): Flyway = {
    val config = new HikariConfig()
    conf match {
      case c: DbConf.H2 =>
        config.setDriverClassName("org.h2.Driver")
        config.setJdbcUrl(c.url)
      case c: DbConf.PostgreSQL =>
        config.setDriverClassName("org.postgresql.Driver")
        config.setJdbcUrl(c.url)
        config.setUsername(c.user)
        config.setPassword(c.pass.decode)
    }
    Flyway.configure()
      .dataSource(new HikariDataSource(config))
      .locations("classpath:sql")
      .load()
  }
} 
Example 13
Source File: MySqlConnector.scala    From vinyldns   with Apache License 2.0 5 votes vote down vote up
package vinyldns.mysql

import cats.effect.IO
import com.zaxxer.hikari.{HikariConfig, HikariDataSource}
import org.flywaydb.core.Flyway
import org.slf4j.LoggerFactory

import scala.collection.JavaConverters._

object MySqlConnector {

  private val logger = LoggerFactory.getLogger("MySqlConnector")

  def runDBMigrations(config: MySqlConnectionConfig): IO[Unit] = {
    val migrationConnectionSettings = MySqlDataSourceSettings(
      "flywayConnectionPool",
      config.driver,
      config.migrationUrl,
      config.user,
      config.password,
      minimumIdle = Some(3)
    )

    getDataSource(migrationConnectionSettings).map { migrationDataSource =>
      logger.info("Running migrations to ready the databases")

      val migration = new Flyway()
      migration.setDataSource(migrationDataSource)
      // flyway changed the default schema table name in v5.0.0
      // this allows to revert to an old naming convention if needed
      config.migrationSchemaTable.foreach { tableName =>
        migration.setTable(tableName)
      }

      val placeholders = Map("dbName" -> config.name)
      migration.setPlaceholders(placeholders.asJava)
      migration.setSchemas(config.name)

      // Runs flyway migrations
      migration.migrate()
      logger.info("migrations complete")
    }
  }

  def getDataSource(settings: MySqlDataSourceSettings): IO[HikariDataSource] = IO {

    logger.error(s"Initializing data source with settings: $settings")

    val dsConfig = new HikariConfig()

    dsConfig.setPoolName(settings.poolName)
    dsConfig.setDriverClassName(settings.driver)
    dsConfig.setJdbcUrl(settings.url)
    dsConfig.setUsername(settings.user)
    dsConfig.setPassword(settings.password)

    settings.connectionTimeoutMillis.foreach(dsConfig.setConnectionTimeout)
    settings.idleTimeout.foreach(dsConfig.setIdleTimeout)
    settings.maximumPoolSize.foreach(dsConfig.setMaximumPoolSize)
    settings.maxLifetime.foreach(dsConfig.setMaxLifetime)
    settings.minimumIdle.foreach(dsConfig.setMinimumIdle)
    dsConfig.setRegisterMbeans(settings.registerMbeans)

    settings.mySqlProperties.foreach {
      case (k, v) => dsConfig.addDataSourceProperty(k, v)
    }

    new HikariDataSource(dsConfig)
  }
} 
Example 14
Source File: FlywayMigration.scala    From seahorse   with Apache License 2.0 5 votes vote down vote up
package ai.deepsense.sessionmanager

import com.typesafe.config.ConfigFactory
import org.flywaydb.core.Flyway

object FlywayMigration {

  private val config = ConfigFactory.load

  def run(): Unit = {
    val flyway = new Flyway
    flyway.setBaselineOnMigrate(true)
    flyway.setLocations("db.migration.sessionmanager")
    flyway.setDataSource(config.getString("db.url"), "", "")
    flyway.migrate()
  }
} 
Example 15
Source File: FlywayMigration.scala    From seahorse   with Apache License 2.0 5 votes vote down vote up
package ai.deepsense.seahorse.scheduling.db

import org.flywaydb.core.Flyway

import ai.deepsense.seahorse.scheduling.SchedulingManagerConfig

object FlywayMigration {

  private val db = SchedulingManagerConfig.database

  def run(): Unit = {
    val flyway = new Flyway
    flyway.setLocations("db.migration.schedulingmanager")
    flyway.setSchemas(db.schema, db.quartzSchema)
    flyway.setDataSource(SchedulingManagerConfig.config.getString("databaseSlick.db.url"), "", "")
    flyway.migrate()
  }
} 
Example 16
Source File: ImmutableMigrationsSpec.scala    From daml   with Apache License 2.0 5 votes vote down vote up
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

package com.daml.ledger.on.sql

import java.io.{BufferedReader, FileNotFoundException}
import java.math.BigInteger
import java.nio.charset.Charset
import java.security.MessageDigest
import java.util

import com.daml.ledger.on.sql.ImmutableMigrationsSpec._
import org.flywaydb.core.Flyway
import org.flywaydb.core.api.configuration.FluentConfiguration
import org.flywaydb.core.internal.resource.LoadableResource
import org.flywaydb.core.internal.scanner.{LocationScannerCache, ResourceNameCache, Scanner}
import org.scalatest.Matchers._
import org.scalatest.WordSpec

import scala.collection.JavaConverters._

class ImmutableMigrationsSpec extends WordSpec {
  "migration files" should {
    "never change, according to their accompanying digest file" in {
      val configuration = Flyway
        .configure()
        .locations(s"classpath:/$migrationsResourcePath")
      val resourceScanner = flywayScanner(configuration)
      val resources = resourceScanner.getResources("", ".sql").asScala.toSeq
      resources.size should be >= 3

      resources.foreach { resource =>
        val migrationFile = resource.getRelativePath
        val digestFile = migrationFile + ".sha256"
        val expectedDigest = readExpectedDigest(migrationFile, digestFile, resourceScanner)
        val currentDigest = computeCurrentDigest(resource, configuration.getEncoding)
        assert(
          currentDigest == expectedDigest,
          s"""The contents of the migration file "$migrationFile" have changed! Migrations are immutable; you must not change their contents or their digest.""",
        )
      }
    }
  }
}

object ImmutableMigrationsSpec {
  private val migrationsResourcePath = "com/daml/ledger/on/sql/migrations"
  private val hashMigrationsScriptPath = "ledger/ledger-on-sql/hash-migrations.sh"

  private def flywayScanner(configuration: FluentConfiguration) =
    new Scanner(
      classOf[Object],
      util.Arrays.asList(configuration.getLocations: _*),
      getClass.getClassLoader,
      configuration.getEncoding,
      new ResourceNameCache,
      new LocationScannerCache,
    )

  private def readExpectedDigest(
      sourceFile: String,
      digestFile: String,
      resourceScanner: Scanner[_],
  ): String = {
    val resource = Option(resourceScanner.getResource(digestFile))
      .getOrElse(throw new FileNotFoundException(
        s"""\"$digestFile\" is missing. If you are introducing a new Flyway migration step, you need to create an SHA-256 digest file by running $hashMigrationsScriptPath."""))
    new BufferedReader(resource.read()).readLine()
  }

  private def computeCurrentDigest(resource: LoadableResource, encoding: Charset): String = {
    val sha256 = MessageDigest.getInstance("SHA-256")
    new BufferedReader(resource.read())
      .lines()
      .forEach(line => sha256.update((line + "\n").getBytes(encoding)))
    val digest = sha256.digest()
    String.format(s"%0${digest.length * 2}x", new BigInteger(1, digest))
  }
} 
Example 17
Source File: FlywayMigration.scala    From seahorse   with Apache License 2.0 5 votes vote down vote up
package ai.deepsense.workflowmanager

import com.typesafe.config.ConfigFactory
import org.flywaydb.core.Flyway

object FlywayMigration {

  private val config = ConfigFactory.load

  def run(): Unit = {
    val flyway = new Flyway
    flyway.setBaselineOnMigrate(true)
    flyway.setLocations("db.migration.workflowmanager")
    flyway.setDataSource(config.getString("db.url"), "", "")
    flyway.migrate()
  }
} 
Example 18
Source File: FlywayDeployment.scala    From flyway-awslambda   with MIT License 5 votes vote down vote up
package crossroad0201.aws.flywaylambda.deploy

import java.nio.file.Path
import java.util.{ Properties => JProperties }

import org.flywaydb.core.Flyway

case class FlywayDeployment(
  sourceBucket: String,
  sourcePrefix:String,
  url: String,
  user: String,
  password: String,
  location: String,
  sqlFiles: Seq[Path],
  options: Seq[FlywayOption]
)
object FlywayDeployment {
  def apply(sourceBucket: String, sourcePrefix:String, conf: JProperties, location: String, sqlFiles: Seq[Path]): FlywayDeployment = {
    FlywayDeployment(
      sourceBucket,
      sourcePrefix,
      conf.getProperty("flyway.url"),
      conf.getProperty("flyway.user"),
      conf.getProperty("flyway.password"),
      location,
      sqlFiles,
      FlywayOption.buildOptions(conf)
    )
  }
}

sealed trait FlywayOption {
  def apply(flyway: Flyway): Flyway
}
object FlywayOption {
  def buildOptions(conf: JProperties): Seq[FlywayOption] = {
    import scala.collection.JavaConverters._
    conf.asScala.flatMap {
      case ("flyway.outOfOrder", enabled) => Some(OutOfOrder(enabled.toBoolean))
      case ("flyway.cleanOnValidationError", enabled) => Some(CleanOnValidationError(enabled.toBoolean))
      case ("flyway.schemas", schemas) => Some(Schemas(schemas.split(",").map(_.trim)))
      case _ => None
    }.toSeq
  }
}
case class OutOfOrder(enabled: Boolean) extends FlywayOption {
  override def apply(flyway: Flyway) = {
    flyway.setOutOfOrder(enabled)
    flyway
  }
}

case class CleanOnValidationError(enabled: Boolean) extends FlywayOption {
  override def apply(flyway: Flyway) = {
    flyway.setCleanOnValidationError(enabled)
    flyway
  }
}

case class Schemas(schemas: Array[String]) extends FlywayOption {
  override def apply(flyway: Flyway) = {
    flyway.setSchemas(schemas: _*)
    flyway
  }
} 
Example 19
Source File: FlywayMigrator.scala    From flyway-awslambda   with MIT License 5 votes vote down vote up
package crossroad0201.aws.flywaylambda.migration

import crossroad0201.aws.flywaylambda.deploy.FlywayDeployment
import org.flywaydb.core.Flyway

import scala.util.{Failure, Success, Try}

trait FlywayMigrator {

  def migrate(deployment: FlywayDeployment) = {
    val flyway = new Flyway

    val appliedCount = Try {
      flyway.setDataSource(
        deployment.url,
        deployment.user,
        deployment.password
      )
      flyway.setLocations(deployment.location)

      deployment.options.map(_.apply(flyway))

      flyway.migrate
    }

    val migrationInfos = Try {
      flyway.info.all
    }

    (appliedCount, migrationInfos) match {
      case (Success(c), Success(is)) => MigrationResult.success(deployment.url, c, is.map(MigrationInfo(_)))
      case (Success(c), Failure(e)) => MigrationResult.failure(deployment.url, e, Seq())
      case (Failure(e), Success(is)) => MigrationResult.failure(deployment.url, e, is.map(MigrationInfo(_)))
      case (Failure(e1), Failure(e2)) => MigrationResult.failure(deployment.url, e1, Seq())
    }
  }

} 
Example 20
Source File: Commands.scala    From franklin   with Apache License 2.0 5 votes vote down vote up
package com.azavea.franklin.api.commands

import cats.effect.{ContextShift, ExitCode, IO}
import cats.implicits._
import com.azavea.franklin.crawler.StacImport
import com.monovore.decline._
import doobie.Transactor
import doobie.free.connection.{rollback, setAutoCommit, unit}
import doobie.util.transactor.Strategy
import org.flywaydb.core.Flyway

object Commands {

  final case class RunMigrations(databaseConfig: DatabaseConfig)

  final case class RunServer(apiConfig: ApiConfig, dbConfig: DatabaseConfig)

  final case class RunImport(
      catalogRoot: String,
      config: DatabaseConfig,
      dryRun: Boolean
  )

  private def runImportOpts(implicit cs: ContextShift[IO]): Opts[RunImport] =
    Opts.subcommand("import", "Import a STAC catalog") {
      (
        Options.catalogRoot,
        Options.databaseConfig,
        Options.dryRun
      ).mapN(RunImport)
    }

  private def runMigrationsOpts(implicit cs: ContextShift[IO]): Opts[RunMigrations] =
    Opts.subcommand("migrate", "Runs migrations against database") {
      Options.databaseConfig map RunMigrations
    }

  private def runServerOpts(implicit cs: ContextShift[IO]): Opts[RunServer] =
    Opts.subcommand("serve", "Runs web service") {
      (Options.apiConfig, Options.databaseConfig) mapN RunServer
    }

  def runMigrations(dbConfig: DatabaseConfig): IO[ExitCode] = IO {
    Flyway
      .configure()
      .dataSource(
        s"${dbConfig.jdbcUrl}",
        dbConfig.dbUser,
        dbConfig.dbPass
      )
      .locations("classpath:migrations/")
      .load()
      .migrate()
    ExitCode.Success
  }

  def runImport(
      stacCatalog: String,
      config: DatabaseConfig,
      dryRun: Boolean
  )(
      implicit contextShift: ContextShift[IO]
  ): IO[Unit] = {
    val xa =
      Transactor.strategy.set(
        Transactor.fromDriverManager[IO](
          config.driver,
          config.jdbcUrl,
          config.dbUser,
          config.dbPass
        ),
        if (dryRun) {
          Strategy.default.copy(before = setAutoCommit(false), after = rollback, always = unit)
        } else { Strategy.default }
      )

    new StacImport(stacCatalog).runIO(xa)
  }

  def applicationCommand(implicit cs: ContextShift[IO]): Command[Product] =
    Command("", "Your Friendly Neighborhood OGC API - Features and STAC Web Service") {
      runServerOpts orElse runMigrationsOpts orElse runImportOpts
    }

} 
Example 21
Source File: FlywayMigrate.scala    From docspell   with GNU General Public License v3.0 5 votes vote down vote up
package docspell.store.migrate

import cats.effect.Sync

import docspell.store.JdbcConfig

import org.flywaydb.core.Flyway
import org.log4s._

object FlywayMigrate {
  private[this] val logger = getLogger

  def run[F[_]: Sync](jdbc: JdbcConfig): F[Int] =
    Sync[F].delay {
      logger.info("Running db migrations...")
      val locations = jdbc.dbmsName match {
        case Some(dbtype) =>
          val name = if (dbtype == "h2") "postgresql" else dbtype
          List(s"classpath:db/migration/${name}")
        case None =>
          logger.warn(
            s"Cannot read database name from jdbc url: ${jdbc.url}. Go with PostgreSQL"
          )
          List("classpath:db/postgresql")
      }

      logger.info(s"Using migration locations: $locations")
      val fw = Flyway
        .configure()
        .cleanDisabled(true)
        .dataSource(jdbc.url.asString, jdbc.user, jdbc.password)
        .locations(locations: _*)
        .load()

      fw.repair()
      fw.migrate()
    }
} 
Example 22
Source File: TestDBSettings.scala    From scuruto   with MIT License 5 votes vote down vote up
package model

import org.flywaydb.core.Flyway
import org.scalatest.{ BeforeAndAfterEach, Suite }
import scalikejdbc.ConnectionPool
import skinny._
import skinny.exception.DBSettingsException

trait TestDBSettings extends BeforeAndAfterEach with DBSettings { this: Suite =>

  override protected def beforeEach(): Unit = {
    clean()
    dbmigration.DBMigration.migrate()
  }

  private def clean(env: String = SkinnyEnv.Test, poolName: String = ConnectionPool.DEFAULT_NAME.name): Unit = {
    val skinnyEnv = SkinnyEnv.get()
    try {
      System.setProperty(SkinnyEnv.PropertyKey, env)
      DBSettings.initialize()
      try {
        val pool = ConnectionPool.get(Symbol(poolName))
        val flyway = new Flyway
        flyway.setDataSource(pool.dataSource)
        flyway.clean()
      } catch {
        case e: IllegalStateException =>
          throw new DBSettingsException(s"ConnectionPool named $poolName is not found.")
      }
    } finally {
      skinnyEnv.foreach { env => System.setProperty(SkinnyEnv.PropertyKey, env) }
      DBSettings.initialize()
    }
  }

} 
Example 23
Source File: DbManagement.scala    From bitcoin-s   with MIT License 5 votes vote down vote up
package org.bitcoins.db

import org.bitcoins.core.util.{BitcoinSLogger, FutureUtil}
import org.flywaydb.core.Flyway
import org.flywaydb.core.api.FlywayException

import scala.concurrent.{ExecutionContext, Future}

trait DbManagement extends BitcoinSLogger {
  _: JdbcProfileComponent[AppConfig] =>
  import profile.api._

  import scala.language.implicitConversions

  
  def migrate(): Int = {
    val module = appConfig.moduleName
    val config =
      Flyway
        .configure()
        .locations(s"classpath:${driverName}/${module}/migration/")
    val flyway = config.dataSource(jdbcUrl, username, password).load

    try {
      flyway.migrate()
    } catch {
      case err: FlywayException =>
        logger.warn(
          s"Failed to apply first round of migrations, attempting baseline and re-apply",
          err)
        //maybe we have an existing database, so attempt to baseline the existing
        //database and then apply migrations again
        flyway.baseline()
        flyway.migrate()
    }
  }
} 
Example 24
Source File: MigrationsSpec.scala    From testcontainers-specs2   with MIT License 5 votes vote down vote up
package io.chrisdavenport.testcontainersspecs2

import cats.effect._
import org.flywaydb.core.Flyway
import org.specs2.mutable.Specification

class MigrationsSpec
    extends Specification
    with ForAllTestContainer
    with UsesPostgreSQLMultipleDatabases {

  "Migrations should run Correctly" in {
    IO {
      Flyway
        .configure()
        .dataSource(jdbcUrl, dbUserName, dbPassword)
        .load()
        .migrate
    }.attempt
      .map(_.isRight)
      .unsafeRunSync() must_=== true
  }

} 
Example 25
Source File: QueriesSpec.scala    From testcontainers-specs2   with MIT License 5 votes vote down vote up
package io.chrisdavenport.testcontainersspecs2

import java.util.UUID

import cats.effect._
import doobie._
import doobie.implicits._
import doobie.postgres.implicits._
import doobie.specs2._
import org.flywaydb.core.Flyway
import org.specs2.mutable.Specification

import scala.concurrent.ExecutionContext

class QueriesSpec[F[_]]
    extends Specification
    with IOChecker
    with ForAllTestContainer
    with UsesPostgreSQLMultipleDatabases {

  implicit val CS: ContextShift[IO] = IO.contextShift(ExecutionContext.global)

  override lazy val transactor: Transactor[IO] = Transactor.fromDriverManager[IO](
    driverName,
    jdbcUrl,
    dbUserName,
    dbPassword
  )

  sequential

  // afterStart / beforeStop available for actions at the begininning
  // and end of a particular container session.
  // In this case we make sure migrations have run before we check the sql statements.
  override def afterStart(): Unit = {
    Flyway
      .configure()
      .dataSource(jdbcUrl, dbUserName, dbPassword)
      .load()
      .migrate
    ()
  }

  private case class Person(person_id: UUID, firstName: String, lastName: String)

  check(sql"SELECT 1".query[Int])
  check(sql"SELECT person_id, first_name, last_name FROM persons".query[Person])

} 
Example 26
Source File: DB.scala    From Learn-Scala-Programming   with MIT License 5 votes vote down vote up
package ch14

import cats.effect.IO
import doobie.hikari.HikariTransactor
import org.flywaydb.core.Flyway

object DB {
  def transactor(config: DBConfig): IO[HikariTransactor[IO]] = {
    HikariTransactor.newHikariTransactor[IO](config.driver,
                                             config.url,
                                             config.user,
                                             config.password)
  }

  def initialize(transactor: HikariTransactor[IO]): IO[Unit] = {
    transactor.configure { dataSource =>
      IO {
        val flyWay = new Flyway()
        flyWay.setLocations("classpath:db_migrations")
        flyWay.setDataSource(dataSource)
        flyWay.migrate()
      }
    }
  }
} 
Example 27
Source File: DatabaseInitializer.scala    From reliable-http-client   with Apache License 2.0 5 votes vote down vote up
package rhttpc.transport.amqpjdbc.slick.helpers

import java.io.PrintWriter
import java.sql.Connection
import java.util.logging.Logger
import javax.sql.DataSource

import com.typesafe.config.Config
import org.flywaydb.core.Flyway
import slick.jdbc.JdbcBackend

import scala.concurrent.ExecutionContext

class DatabaseInitializer(db: JdbcBackend.Database) {
  def initDatabase()(implicit executionContext: ExecutionContext) = {
    migrateIfNeeded(db)
    db
  }

  private def migrateIfNeeded(db: JdbcBackend.Database) = {
    Flyway.configure
      .dataSource(new DatabaseDataSource(db))
      .baselineOnMigrate(true)
      .load
      .migrate
  }
}

object DatabaseInitializer {
  def apply(config: Config) = {
    val db = JdbcBackend.Database.forConfig("db", config)
    new DatabaseInitializer(db)
  }
}

class DatabaseDataSource(db: JdbcBackend.Database) extends DataSource {
  private val conn = db.createSession().conn

  override def getConnection: Connection = conn
  override def getConnection(username: String, password: String): Connection = conn
  override def unwrap[T](iface: Class[T]): T = conn.unwrap(iface)
  override def isWrapperFor(iface: Class[_]): Boolean = conn.isWrapperFor(iface)

  override def setLogWriter(out: PrintWriter): Unit = ???
  override def getLoginTimeout: Int = ???
  override def setLoginTimeout(seconds: Int): Unit = ???
  override def getParentLogger: Logger = ???
  override def getLogWriter: PrintWriter = ???
} 
Example 28
Source File: FlywayMigrator.scala    From zorechka-bot   with MIT License 5 votes vote down vote up
package com.wix.zorechka.repos

import com.zaxxer.hikari.HikariDataSource
import doobie.hikari.HikariTransactor
import org.flywaydb.core.Flyway
import zio.console.{Console, putStrLn}
import zio.{Task, ZIO}

trait FlywayMigrator {
  val flywayMigrator: FlywayMigrator.Service
}

object FlywayMigrator {

  trait Service {
    def migrate(dbTransactor: HikariTransactor[Task]): ZIO[Console, Throwable, Unit]
  }

  trait Live extends FlywayMigrator {

    val flywayMigrator: Service = new Service {
      override def migrate(dbTransactor: HikariTransactor[Task]): ZIO[Console, Throwable, Unit] = for {
        _ <- putStrLn("Starting Flyway migration")
        _ <- dbTransactor.configure(dataSource => loadFlyWayAndMigrate(dataSource))
        _ <- putStrLn("Finished Flyway migration")
      } yield ()
    }

    private def loadFlyWayAndMigrate(dataSource: HikariDataSource) = ZIO.effect {
      Flyway.configure()
        .dataSource(dataSource)
        .load()
        .migrate()
    }
  }

  def migrate(dbTransactor: HikariTransactor[Task]): ZIO[FlywayMigrator with Console, Throwable, Unit] =
    ZIO.accessM[FlywayMigrator with Console](_.flywayMigrator.migrate(dbTransactor))
} 
Example 29
Source File: Migration.scala    From iotchain   with MIT License 5 votes vote down vote up
package jbok.app.service.store

import cats.effect.Sync
import cats.implicits._
import jbok.core.config.DatabaseConfig
import org.flywaydb.core.Flyway

object Migration {
  private val flyway = new Flyway()
  flyway.setLocations("db/mysql", "db/sqlite")

  def migrate[F[_]: Sync](config: DatabaseConfig): F[Unit] =
    Sync[F].delay {
      config.driver match {
        case "org.sqlite.JDBC" => flyway.setLocations("db/sqlite")
        case _                 => flyway.setLocations("db/mysql")
      }
      flyway.setDataSource(config.url, config.user, config.password)
      flyway.migrate()
    }.void
} 
Example 30
Source File: FlywayMigrations.scala    From daml   with Apache License 2.0 5 votes vote down vote up
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

package com.daml.platform.store

import com.daml.logging.{ContextualizedLogger, LoggingContext}
import com.daml.platform.configuration.ServerRole
import com.daml.platform.store.FlywayMigrations._
import com.daml.platform.store.dao.HikariConnection
import com.daml.resources.ResourceOwner
import com.zaxxer.hikari.HikariDataSource
import org.flywaydb.core.Flyway
import org.flywaydb.core.api.MigrationVersion
import org.flywaydb.core.api.configuration.FluentConfiguration

import scala.concurrent.duration.DurationInt
import scala.concurrent.{ExecutionContext, Future}

class FlywayMigrations(jdbcUrl: String)(implicit logCtx: LoggingContext) {
  private val logger = ContextualizedLogger.get(this.getClass)

  private val dbType = DbType.jdbcType(jdbcUrl)

  def validate()(implicit executionContext: ExecutionContext): Future[Unit] =
    dataSource.use { ds =>
      Future {
        val flyway = configurationBase(dbType).dataSource(ds).load()
        logger.info("Running Flyway validation...")
        flyway.validate()
        logger.info("Flyway schema validation finished successfully.")
      }
    }

  def migrate(allowExistingSchema: Boolean = false)(
      implicit executionContext: ExecutionContext
  ): Future[Unit] =
    dataSource.use { ds =>
      Future {
        val flyway = configurationBase(dbType)
          .dataSource(ds)
          .baselineOnMigrate(allowExistingSchema)
          .baselineVersion(MigrationVersion.fromVersion("0"))
          .load()
        logger.info("Running Flyway migration...")
        val stepsTaken = flyway.migrate()
        logger.info(s"Flyway schema migration finished successfully, applying $stepsTaken steps.")
      }
    }

  def reset()(implicit executionContext: ExecutionContext): Future[Unit] =
    dataSource.use { ds =>
      Future {
        val flyway = configurationBase(dbType).dataSource(ds).load()
        logger.info("Running Flyway clean...")
        flyway.clean()
        logger.info("Flyway schema clean finished successfully.")
      }
    }

  private def dataSource: ResourceOwner[HikariDataSource] =
    HikariConnection.owner(
      serverRole = ServerRole.IndexMigrations,
      jdbcUrl = jdbcUrl,
      minimumIdle = 2,
      maxPoolSize = 2,
      connectionTimeout = 250.millis,
      metrics = None,
    )
}

object FlywayMigrations {
  def configurationBase(dbType: DbType): FluentConfiguration =
    Flyway.configure().locations("classpath:db/migration/" + dbType.name)
}