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

net.relaysoft.testing.azure.blob.mock.AzureBlobMock.scala Maven / Gradle / Ivy

The newest version!
package net.relaysoft.testing.azure.blob.mock

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.{HttpResponse, StatusCodes}
import akka.http.scaladsl.server.Directives._
import akka.stream.ActorMaterializer
import com.typesafe.scalalogging.LazyLogging
import net.relaysoft.testing.azure.blob.mock.providers.{InMemoryProvider, Provider}
import net.relaysoft.testing.azure.blob.mock.routes._

import scala.concurrent.duration._
import scala.concurrent.Await
import scala.language.postfixOps

class AzureBlobMock(port:Int = 10000,
                    accountName:String = "devstoreaccount1",
                    provider:Provider = new InMemoryProvider(10000, "devstoreaccount1"))
                   (implicit system:ActorSystem = ActorSystem.create("azureBlobMock"))

  extends LazyLogging {

  implicit val prov: Provider = provider
  private var bind:Http.ServerBinding = _

  def start: Http.ServerBinding = {
    implicit val mat: ActorMaterializer = ActorMaterializer()
    val http = Http(system)
    val route = {
      pathPrefix(accountName) {
        pathEnd {
          parameterMap { params =>
            extractRequest { request =>
              val headers = request.headers.map(header => header.name() -> header.value()).toMap
              ListContainers().route(accountName, params, headers)
            }
          }
        }
      } ~ pathPrefix(accountName / Segment) { container =>
          pathEnd {
            parameterMap { params =>
              extractRequest { request =>
                val headers = request.headers.map(header => header.name() -> header.value()).toMap
                concat(
                  ListBlobs().route(accountName, container, params, headers),
                  GetContainerProperties().route(accountName, container, headers),
                  CreateContainer().route(accountName, container, headers),
                  DeleteContainer().route(accountName, container, headers)
                )
              }
            }
          }
        } ~ pathPrefix(accountName / Segments) { segments =>
        pathEnd {
          parameterMap { _ =>
            extractRequest { request =>
              val headers = request.headers.map(header => header.name() -> header.value()).toMap
              extractDataBytes { dataSource =>
                val futureData = dataSource.runFold(Array[Byte]()) { (_, i) => i.toArray }
                onSuccess(futureData) { data =>
                  concat(
                    GetBlobMetadata().route(accountName, segments.head, segments.last, headers),
                    GetBlobProperties().route(accountName, segments.head, segments.last, headers),
                    GetBlob().route(accountName, segments.head, segments.last, headers),
                    SetBlobMetadata().route(accountName, segments.head, segments.last, headers),
                    PutBlob().route(accountName, segments.head, segments.last, data, headers),
                    DeleteBlob().route(accountName, segments.head, segments.last, headers)
                  )
                }
              }
            }
          }
        }
      } ~ extractRequest { request =>
        complete {
          logger.error(s"Method not implemented: ${request.method.value} ${request.uri.toString}")
          HttpResponse(status = StatusCodes.NotImplemented)
        }
      }
    }

    bind = Await.result(http.bindAndHandle(route, "0.0.0.0", port), Duration.Inf)
    logger.info(s"bound to 0.0.0.0:$port")
    bind
  }

  def clear(): Unit = prov.clear()

  def stop(): Unit = Await.result(bind.unbind(), Duration.Inf)

  def shutdown(): Unit = {
    import system.dispatcher
    val stopped = for {
      _ <- bind.unbind()
      _ <- Http().shutdownAllConnectionPools()
      _ <- system.terminate()
    } yield {
      ()
    }
    Await.result(stopped, Duration.Inf)
  }

}

object AzureBlobMock {
  def apply(port:Int, accountName:String): AzureBlobMock = new AzureBlobMock(port, accountName, new InMemoryProvider(port, accountName))

  /**
   * Create an in-memory Azure Blob Mock instance
   * @param port a port to bind to.
   * @return Azure Blob Mock instance
   */
  def create(port:Int, accountName:String): AzureBlobMock = apply(port, accountName) // Java API

  /**
   * Builder class for java api.
   */
  class Builder {
    private var defaultPort: Int = 8001
    private var defaultAccount: String = "devstoreaccount1"
    private var defaultProvider: Provider = new InMemoryProvider(defaultPort, defaultAccount)

    /**
     * Set port to bind to
     * @param port port number
     * @return Builder instance
     */
    def withPort(port: Int): Builder = {
      defaultPort = port
      this
    }

    /**
     * Set storage account to bind to
     * @param account Account name
     * @return Builder instance
     */
    def withAccount(account: String): Builder = {
      defaultAccount = account
      this
    }

    /**
     * Use in-memory backend.
     * @return Builder instance
     */
    def withInMemoryBackend(): Builder = {
      defaultProvider = new InMemoryProvider(defaultPort, defaultAccount)
      this
    }

    /**
     * Build Azure Blob Mock instance.
     * @return New Azure Blob Mock instance.
     */
    def build(): AzureBlobMock = {
      if(defaultProvider.isInstanceOf[InMemoryProvider]) {
        defaultProvider = new InMemoryProvider(defaultPort, defaultAccount)
      }
      new AzureBlobMock(defaultPort, defaultAccount, defaultProvider)
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy