diff options
Diffstat (limited to 'core-init/src/main/scala/xyz/driver/core/init/CloudServices.scala')
-rw-r--r-- | core-init/src/main/scala/xyz/driver/core/init/CloudServices.scala | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/core-init/src/main/scala/xyz/driver/core/init/CloudServices.scala b/core-init/src/main/scala/xyz/driver/core/init/CloudServices.scala new file mode 100644 index 0000000..857dd4c --- /dev/null +++ b/core-init/src/main/scala/xyz/driver/core/init/CloudServices.scala @@ -0,0 +1,89 @@ +package xyz.driver.core +package init + +import java.nio.file.Paths + +import xyz.driver.core.messaging.{CreateOnDemand, GoogleBus, QueueBus, StreamBus} +import xyz.driver.core.reporting._ +import xyz.driver.core.rest.DnsDiscovery +import xyz.driver.core.storage.{BlobStorage, FileSystemBlobStorage, GcsBlobStorage} + +import scala.collection.JavaConverters._ + +/** Mixin trait that provides essential cloud utilities. */ +trait CloudServices extends AkkaBootable { self => + + /** The platform that this application is running on. + * @group config + */ + def platform: Platform = Platform.current + + /** Service discovery for the current platform. + * @group utilities + */ + lazy val discovery: DnsDiscovery = { + def getOverrides(): Map[String, String] = { + val block = config.getObject("services.dev-overrides").unwrapped().asScala + for ((key, value) <- block) yield { + require(value.isInstanceOf[String], s"Service URL override for '$key' must be a string. Found '$value'.") + key -> value.toString + } + }.toMap + val overrides = platform match { + case Platform.Dev => getOverrides() + // TODO: currently, deployed services must be configured via Kubernetes DNS resolver. Maybe we may want to + // provide a way to override deployed services as well. + case _ => Map.empty[String, String] + } + new DnsDiscovery(clientTransport, overrides) + } + + /* TODO: this reporter uses the platform to determine if JSON logging should be enabled. + * Since the default logger uses slf4j, its settings must be specified before a logger + * is first accessed. This in turn leads to somewhat convoluted code, + * since we can't log when the platform being is determined. + * A potential fix would be to make the log format independent of the platform, and always log + * as JSON for example. + */ + override lazy val reporter: Reporter with ScalaLoggingCompat = { + Console.println("determining platform") // scalastyle:ignore + val r = platform match { + case p @ Platform.GoogleCloud(_, _) => + new GoogleReporter(p.credentials, p.namespace) with ScalaLoggingCompat with GoogleMdcLogger { + val logger = ScalaLoggingCompat.defaultScalaLogger(true) + } + case Platform.Dev => + new NoTraceReporter with ScalaLoggingCompat { + val logger = ScalaLoggingCompat.defaultScalaLogger(false) + } + } + r.info(s"application started on platform '${platform}'")(SpanContext.fresh()) + r + } + + /** Object storage. + * + * When running on a cloud platform, prepends `$project-` to bucket names, where `$project` + * is the project ID (for example 'driverinc-production` or `driverinc-sandbox`). + * + * @group utilities + */ + def storage(bucketName: String): BlobStorage = + platform match { + case p @ Platform.GoogleCloud(keyfile, _) => + GcsBlobStorage.fromKeyfile(keyfile, s"${p.project}-$bucketName") + case Platform.Dev => + new FileSystemBlobStorage(Paths.get(s".data-$bucketName")) + } + + /** Message bus. + * @group utilities + */ + def messageBus: StreamBus = platform match { + case p @ Platform.GoogleCloud(_, namespace) => + new GoogleBus(p.credentials, namespace) with StreamBus with CreateOnDemand + case Platform.Dev => + new QueueBus()(self.system) with StreamBus + } + +} |