All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dev.profunktor.fs2rabbit.DockerRabbit.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2017-2019 ProfunKtor
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package dev.profunktor.fs2rabbit

import cats.effect.{ContextShift, IO}
import dev.profunktor.fs2rabbit.config.Fs2RabbitConfig
import org.scalatest.{BeforeAndAfterAll, Suite}

import scala.concurrent.ExecutionContext
import scala.sys.process._

trait DockerRabbit extends BeforeAndAfterAll { self: Suite =>

  import DockerRabbit._

  // override this if the Docker container has to be started before invocation
  // when developing tests, this likely shall be false, so there is no additional overhead starting Rabbit
  protected lazy val startContainers: Boolean = false

  protected lazy val rabbitPort: Int           = 5672
  protected lazy val rabbitUser: String        = "guest"
  protected lazy val rabbitPassword: String    = "guest"
  protected lazy val rabbitVirtualHost: String = "/"

  private var dockerInstanceId: Option[String] = None

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

  override protected def beforeAll(): Unit = {
    super.beforeAll()
    if (startContainers) {
      assertDockerAvailable()
      dockerInstanceId = Some(startDocker(rabbitPort, rabbitUser, rabbitPassword, rabbitVirtualHost))
    }
  }

  override protected def afterAll(): Unit = {
    super.afterAll()
    dockerInstanceId.foreach(stopDocker)
  }

  lazy val rabbitConfig = Fs2RabbitConfig(
    host = "localhost",
    port = rabbitPort,
    virtualHost = rabbitVirtualHost,
    connectionTimeout = 30,
    ssl = false,
    username = Some(rabbitUser),
    password = Some(rabbitPassword),
    requeueOnNack = false,
    internalQueueSize = Some(500)
  )

}

object DockerRabbit {

  val dockerImage         = "rabbitmq:alpine"
  val dockerContainerName = "fs2rabbit-docker"

  /** asserts that docker is available on host os **/
  def assertDockerAvailable(): Unit = {
    val r = "docker -v".!!
    println(s"Verifying docker is available: $r")
  }

  def startDocker(port: Int, user: String, password: String, virtualHost: String): String = {
    val dockerId = new java.util.concurrent.LinkedBlockingQueue[String](1)

    val removeCmd = s"docker rm -f $dockerContainerName"

    val runCmd =
      s"docker run --name $dockerContainerName -d -p $port:5672 " +
        s"-e RABBITMQ_DEFAULT_USER=$user -e RABBITMQ_DEFAULT_PASS=$password -e RABBITMQ_DEFAULT_VHOST=$virtualHost " +
        dockerImage

    val thread = new Thread(
      new Runnable {
        def run(): Unit = {
          removeCmd.!
          val result = runCmd.!!.trim

          var observer: Option[Process] = None

          val onMessage: String => Unit = str => {
            if (str.contains("Server startup complete")) {
              observer.foreach(_.destroy())
              dockerId.put(result)
            } else {
              println(str)
            }
          }

          val logger = ProcessLogger(onMessage, _ => ())

          println(s"Awaiting Docker startup ($dockerImage @ 127.0.0.1:$port)")
          val observeCmd = s"docker logs -f $result"
          observer = Some(observeCmd.run(logger))
        }
      },
      s"Docker $dockerImage startup observer"
    )
    thread.start()
    val id = dockerId.peek
    println(s"Docker ($dockerImage @ 127.0.0.1:$port) started successfully as $id ")
    id
  }

  def stopDocker(instance: String): Unit = {
    s"docker rm -f $instance".!!
    ()
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy