app/conf/context.scala (196 lines of code) (raw):
package conf
import agent._
import conf.PrismConfiguration.getCrawlRates
import play.api.{Configuration, Mode}
import software.amazon.awssdk.regions.Region
import software.amazon.awssdk.services.ec2.Ec2Client
import software.amazon.awssdk.services.ec2.model.DescribeRegionsRequest
import utils.{Logging, UnnaturalOrdering}
import scala.concurrent.duration.DurationInt
import scala.jdk.CollectionConverters._
import scala.language.postfixOps
import scala.util.Try
import scala.util.control.NonFatal
trait ConfigurationSource {
def configuration(mode: Mode): Configuration
}
class PrismConfiguration(configuration: Configuration) extends Logging {
implicit class option2getOrException[T](option: Option[T]) {
def getOrException(exceptionMessage: String): T = {
option.getOrElse {
throw new IllegalStateException(exceptionMessage)
}
}
}
def subConfigurations(prefix: String): Map[String, Configuration] = {
val config = configuration
.getOptional[Configuration](prefix)
.getOrElse(Configuration.empty)
config.subKeys.flatMap { subKey =>
Try(config.getOptional[Configuration](subKey))
.getOrElse(None)
.map(subKey ->)
}.toMap
}
object accounts {
lazy val lazyStartup: Boolean = configuration
.getOptional[String]("accounts.lazyStartup")
.exists("true" ==)
lazy val prismServerRegion: String = configuration
.getOptional[String]("accounts.aws.prismServerRegion")
.getOrElse(Region.EU_WEST_1.id)
lazy val allRegions = {
val ec2Client = Ec2Client.builder.region(Region.EU_WEST_1).build
try {
val request = DescribeRegionsRequest.builder.build
val response = ec2Client.describeRegions(request)
val regions = response.regions.asScala.toList.map(_.regionName)
regions
} finally {
ec2Client.close
}
}
object aws {
lazy val regionsToCrawl: Seq[String] = configuration
.getOptional[Seq[String]]("accounts.aws.regionsToCrawl")
.getOrElse(allRegions)
lazy val highPriorityRegions: Seq[String] = configuration
.getOptional[Seq[String]]("accounts.aws.regionsHighPriority")
.getOrElse(Seq(prismServerRegion)) :+ Region.AWS_GLOBAL.id
lazy val crawlRates = getCrawlRates(highPriorityRegions)
lazy val defaultOwnerId: Option[String] =
configuration.getOptional[String]("accounts.aws.defaultOwnerId")
val list: Seq[AmazonOrigin] = subConfigurations("accounts.aws").flatMap {
case (name, subConfig) =>
val regions = subConfig
.getOptional[Seq[String]]("regions")
.getOrElse(regionsToCrawl) :+ Region.AWS_GLOBAL.id
val accessKey = subConfig.getOptional[String]("accessKey")
val secretKey = subConfig.getOptional[String]("secretKey")
val role = subConfig.getOptional[String]("role")
val ownerId =
subConfig.getOptional[String]("ownerId").orElse(defaultOwnerId)
val profile = subConfig.getOptional[String]("profile")
val resources =
subConfig.getOptional[Seq[String]]("resources").getOrElse(Nil)
val stagePrefix = subConfig.getOptional[String]("stagePrefix")
regions.map { region =>
val credentials =
Credentials(accessKey, role, profile, prismServerRegion)(
secretKey
)
AmazonOrigin(
name,
region,
resources.toSet,
stagePrefix,
credentials,
ownerId,
crawlRates(region)
)
}
}.toList
}
object amis {
lazy val regionsToCrawl: Seq[String] = configuration
.getOptional[Seq[String]]("accounts.ami.regionsToCrawl")
.getOrElse(Seq(prismServerRegion))
lazy val crawlRates: Map[String, Map[String, CrawlRate]] = getCrawlRates(
regionsToCrawl
)
val list: Seq[AmazonOrigin] = subConfigurations("accounts.amis").flatMap {
case (name, subConfig) =>
val regions = subConfig
.getOptional[Seq[String]]("regions")
.getOrElse(regionsToCrawl)
val accessKey = subConfig.getOptional[String]("accessKey")
val secretKey = subConfig.getOptional[String]("secretKey")
val role = subConfig.getOptional[String]("role")
val profile = subConfig.getOptional[String]("profile")
val accountNumber = subConfig.getOptional[String]("accountNumber")
regions.map { region =>
val credentials =
Credentials(accessKey, role, profile, region)(secretKey)
AmazonOrigin.amis(
name,
region,
accountNumber,
credentials,
ownerId = None,
crawlRates(region)
)
}
}.toList
}
object json {
lazy val list: Seq[JsonOrigin] = subConfigurations("accounts.json").map {
case (name, config) =>
log.info(s"processing $name")
try {
val vendor = config.getOptional[String]("vendor").getOrElse("file")
val account = config
.getOptional[String]("account")
.getOrException("Account must be specified")
val resources =
config.getOptional[Seq[String]]("resources").getOrElse(Nil)
val url = config
.getOptional[String]("url")
.getOrException("URL must be specified")
val crawlRates: Map[String, CrawlRate] =
Map("data" -> CrawlRate(5 minutes, 1 minute))
val o =
JsonOrigin(vendor, account, url, resources.toSet, crawlRates)
log.info(s"Parsed $name, got $o")
o
} catch {
case NonFatal(e) =>
log.warn(s"Failed to process $name", e)
throw e
}
}.toList
}
}
object logging {
lazy val verbose: Boolean = configuration
.getOptional[String]("logging")
.exists(_.equalsIgnoreCase("VERBOSE"))
}
object stages {
lazy val order: List[String] = configuration
.getOptional[Seq[String]]("stages.order")
.getOrElse(Nil)
.toList
.filterNot("" ==)
lazy val ordering: UnnaturalOrdering[String] = UnnaturalOrdering(order)
}
object urls {
lazy val publicPrefix: String = configuration
.getOptional[String]("urls.publicPrefix")
.getOrElse("http://localhost:9000")
}
override def toString: String = configuration.toString
}
object PrismConfiguration {
val fastCrawlRate: CrawlRate = CrawlRate(15 minutes, 1 minute)
val defaultCrawlRate: CrawlRate = CrawlRate(1 hour, 5 minutes)
val slowCrawlRate: CrawlRate = CrawlRate(1 day, 1 hour)
val highPriorityRegionCrawlRate: Map[String, CrawlRate] = {
Map(
"reservation" -> fastCrawlRate,
"instance" -> fastCrawlRate,
"images" -> fastCrawlRate,
"data" -> fastCrawlRate,
"cloudformationStacks" -> slowCrawlRate
).withDefaultValue(defaultCrawlRate)
}
val lowPriorityRegionCrawlRate: Map[String, CrawlRate] =
Map.empty.withDefaultValue(slowCrawlRate)
def getCrawlRates(
highPriorityRegions: Seq[String]
): Map[String, Map[String, CrawlRate]] = {
highPriorityRegions
.map(region => (region, highPriorityRegionCrawlRate))
.toMap
.withDefaultValue(lowPriorityRegionCrawlRate)
}
}