mirror of
https://github.com/VinylDNS/vinyldns
synced 2025-08-22 10:10:12 +00:00
Boot load repos in api (#214)
* conf changes to dynamically load * have boot dynamically load repos based on config * update sbt version
This commit is contained in:
parent
8875a6848e
commit
675cd110d0
@ -18,6 +18,7 @@ cache:
|
|||||||
directories:
|
directories:
|
||||||
- $HOME/.ivy2/cache
|
- $HOME/.ivy2/cache
|
||||||
- $HOME/.sbt
|
- $HOME/.sbt
|
||||||
|
timeout: 900
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- rvm use 2.2.8 --install --fuzzy
|
- rvm use 2.2.8 --install --fuzzy
|
||||||
@ -26,6 +27,8 @@ install:
|
|||||||
|
|
||||||
before_cache:
|
before_cache:
|
||||||
# Cleanup the cached directories to avoid unnecessary cache updates (https://www.scala-sbt.org/1.0/docs/Travis-CI-with-sbt.html)
|
# Cleanup the cached directories to avoid unnecessary cache updates (https://www.scala-sbt.org/1.0/docs/Travis-CI-with-sbt.html)
|
||||||
|
- sudo chown -R travis:travis $HOME/.sbt
|
||||||
|
- sudo chown -R travis:travis $HOME/.ivy2/cache
|
||||||
- find $HOME/.ivy2/cache -name "ivydata-*.properties" -print -delete
|
- find $HOME/.ivy2/cache -name "ivydata-*.properties" -print -delete
|
||||||
- find $HOME/.sbt -name "*.lock" -print -delete
|
- find $HOME/.sbt -name "*.lock" -print -delete
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ vinyldns {
|
|||||||
type = "vinyldns.core.crypto.NoOpCrypto"
|
type = "vinyldns.core.crypto.NoOpCrypto"
|
||||||
}
|
}
|
||||||
|
|
||||||
data-stores = ["mysql"]
|
data-stores = ["mysql", "dynamodb"]
|
||||||
|
|
||||||
mysql {
|
mysql {
|
||||||
settings {
|
settings {
|
||||||
@ -75,69 +75,59 @@ vinyldns {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# default settings point to the docker compose setup
|
dynamodb {
|
||||||
dynamo {
|
settings {
|
||||||
key = "x"
|
# default settings point to the docker compose setup
|
||||||
key = ${?AWS_ACCESS_KEY}
|
key = "x"
|
||||||
secret = "x"
|
key = ${?AWS_ACCESS_KEY}
|
||||||
secret = ${?AWS_SECRET_ACCESS_KEY}
|
secret = "x"
|
||||||
endpoint = "http://vinyldns-dynamodb:8000"
|
secret = ${?AWS_SECRET_ACCESS_KEY}
|
||||||
endpoint = ${?DYNAMODB_ENDPOINT}
|
endpoint = "http://vinyldns-dynamodb:8000"
|
||||||
}
|
endpoint = ${?DYNAMODB_ENDPOINT}
|
||||||
|
|
||||||
zoneChanges {
|
|
||||||
dynamo {
|
|
||||||
tableName = "zoneChange"
|
|
||||||
provisionedReads = 30
|
|
||||||
provisionedWrites = 30
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
recordSet {
|
repositories {
|
||||||
dynamo {
|
zone-change {
|
||||||
tableName = "recordSet"
|
table-name = "zoneChange"
|
||||||
provisionedReads = 30
|
provisioned-reads = 30
|
||||||
provisionedWrites = 30
|
provisioned-writes = 30
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
recordChange {
|
record-set {
|
||||||
dynamo {
|
table-name = "recordSet"
|
||||||
tableName = "recordChange"
|
provisioned-reads = 30
|
||||||
provisionedReads = 30
|
provisioned-writes = 30
|
||||||
provisionedWrites = 30
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
users {
|
record-change {
|
||||||
dynamo {
|
table-name = "recordChange"
|
||||||
tableName = "users"
|
provisioned-reads = 30
|
||||||
provisionedReads = 30
|
provisioned-writes = 30
|
||||||
provisionedWrites = 30
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
groups {
|
user {
|
||||||
dynamo {
|
table-name = "users"
|
||||||
tableName = "groups"
|
provisioned-reads = 30
|
||||||
provisionedReads = 30
|
provisioned-writes = 30
|
||||||
provisionedWrites = 30
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
groupChanges {
|
group {
|
||||||
dynamo {
|
table-name = "groups"
|
||||||
tableName = "groupChanges"
|
provisioned-reads = 30
|
||||||
provisionedReads = 30
|
provisioned-writes = 30
|
||||||
provisionedWrites = 30
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
membership {
|
group-change {
|
||||||
dynamo {
|
table-name = "groupChanges"
|
||||||
tableName = "membership"
|
provisioned-reads = 30
|
||||||
provisionedReads = 30
|
provisioned-writes = 30
|
||||||
provisionedWrites = 30
|
}
|
||||||
|
|
||||||
|
membership {
|
||||||
|
table-name = "membership"
|
||||||
|
provisioned-reads = 30
|
||||||
|
provisioned-writes = 30
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,24 +31,42 @@ vinyldns {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
recordSet {
|
|
||||||
# use the dummy store, this should only be used local
|
|
||||||
dummy = true
|
|
||||||
|
|
||||||
dynamo {
|
dynamodb.repositories {
|
||||||
tableName = "recordSetTest"
|
record-set {
|
||||||
provisionedReads=30
|
table-name = "recordSetTest"
|
||||||
provisionedWrites=30
|
provisioned-reads = 30
|
||||||
|
provisioned-writes = 20
|
||||||
}
|
}
|
||||||
}
|
record-change {
|
||||||
recordChange {
|
table-name = "recordChangeTest"
|
||||||
# use the dummy store, this should only be used local
|
provisioned-reads = 30
|
||||||
dummy = true
|
provisioned-writes = 20
|
||||||
|
}
|
||||||
dynamo {
|
zone-change {
|
||||||
tableName = "recordChangeTest"
|
table-name = "zoneChangesTest"
|
||||||
provisionedReads = 30
|
provisioned-reads = 30
|
||||||
provisionedWrites = 30
|
provisioned-writes = 20
|
||||||
|
}
|
||||||
|
user {
|
||||||
|
table-name = "usersTest"
|
||||||
|
provisioned-reads = 30
|
||||||
|
provisioned-writes = 20
|
||||||
|
}
|
||||||
|
group {
|
||||||
|
table-name = "groupsTest"
|
||||||
|
provisioned-reads = 30
|
||||||
|
provisioned-writes = 20
|
||||||
|
}
|
||||||
|
group-change {
|
||||||
|
table-name = "groupChangesTest"
|
||||||
|
provisioned-reads = 30
|
||||||
|
provisioned-writes = 20
|
||||||
|
}
|
||||||
|
membership {
|
||||||
|
table-name = "membershipTest"
|
||||||
|
provisioned-reads = 30
|
||||||
|
provisioned-writes = 20
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,13 +23,14 @@ import cats.implicits._
|
|||||||
import fs2.{Scheduler, Stream}
|
import fs2.{Scheduler, Stream}
|
||||||
import org.joda.time.DateTime
|
import org.joda.time.DateTime
|
||||||
import org.scalatest.concurrent.Eventually
|
import org.scalatest.concurrent.Eventually
|
||||||
|
import org.scalatest.mockito.MockitoSugar
|
||||||
import org.scalatest.time.{Millis, Seconds, Span}
|
import org.scalatest.time.{Millis, Seconds, Span}
|
||||||
import vinyldns.api.{DynamoDBApiIntegrationSpec, VinylDNSTestData}
|
import vinyldns.api.{DynamoDBApiIntegrationSpec, VinylDNSTestData}
|
||||||
import vinyldns.api.domain.record.RecordSetChangeGenerator
|
import vinyldns.api.domain.record.RecordSetChangeGenerator
|
||||||
import vinyldns.core.domain.batch.BatchChangeRepository
|
|
||||||
import vinyldns.core.domain.record._
|
import vinyldns.core.domain.record._
|
||||||
import vinyldns.api.domain.zone._
|
import vinyldns.api.domain.zone._
|
||||||
import vinyldns.api.engine.sqs.SqsConnection
|
import vinyldns.api.engine.sqs.SqsConnection
|
||||||
|
import vinyldns.api.repository.ApiDataAccessor
|
||||||
import vinyldns.dynamodb.repository.{
|
import vinyldns.dynamodb.repository.{
|
||||||
DynamoDBRecordChangeRepository,
|
DynamoDBRecordChangeRepository,
|
||||||
DynamoDBRecordSetRepository,
|
DynamoDBRecordSetRepository,
|
||||||
@ -37,14 +38,21 @@ import vinyldns.dynamodb.repository.{
|
|||||||
DynamoDBZoneChangeRepository
|
DynamoDBZoneChangeRepository
|
||||||
}
|
}
|
||||||
import vinyldns.api.repository.mysql.TestMySqlInstance
|
import vinyldns.api.repository.mysql.TestMySqlInstance
|
||||||
|
import vinyldns.core.domain.membership.{
|
||||||
|
GroupChangeRepository,
|
||||||
|
GroupRepository,
|
||||||
|
MembershipRepository,
|
||||||
|
UserRepository
|
||||||
|
}
|
||||||
import vinyldns.core.domain.zone._
|
import vinyldns.core.domain.zone._
|
||||||
|
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
import scala.concurrent.{Await, ExecutionContext}
|
import scala.concurrent.ExecutionContext
|
||||||
|
|
||||||
class ZoneCommandHandlerIntegrationSpec
|
class ZoneCommandHandlerIntegrationSpec
|
||||||
extends DynamoDBApiIntegrationSpec
|
extends DynamoDBApiIntegrationSpec
|
||||||
with VinylDNSTestData
|
with VinylDNSTestData
|
||||||
|
with MockitoSugar
|
||||||
with Eventually {
|
with Eventually {
|
||||||
|
|
||||||
import vinyldns.api.engine.sqs.SqsConverters._
|
import vinyldns.api.engine.sqs.SqsConverters._
|
||||||
@ -65,11 +73,7 @@ class ZoneCommandHandlerIntegrationSpec
|
|||||||
PatienceConfig(timeout = Span(5, Seconds), interval = Span(500, Millis))
|
PatienceConfig(timeout = Span(5, Seconds), interval = Span(500, Millis))
|
||||||
private implicit val ec: ExecutionContext = scala.concurrent.ExecutionContext.global
|
private implicit val ec: ExecutionContext = scala.concurrent.ExecutionContext.global
|
||||||
|
|
||||||
private var recordChangeRepo: RecordChangeRepository = _
|
private var repositories: ApiDataAccessor = _
|
||||||
private var recordSetRepo: RecordSetRepository = _
|
|
||||||
private var zoneChangeRepo: ZoneChangeRepository = _
|
|
||||||
private var zoneRepo: ZoneRepository = _
|
|
||||||
private var batchChangeRepo: BatchChangeRepository = _
|
|
||||||
private var sqsConn: SqsConnection = _
|
private var sqsConn: SqsConnection = _
|
||||||
private var str: Stream[IO, Unit] = _
|
private var str: Stream[IO, Unit] = _
|
||||||
private val stopSignal = fs2.async.signalOf[IO, Boolean](false).unsafeRunSync()
|
private val stopSignal = fs2.async.signalOf[IO, Boolean](false).unsafeRunSync()
|
||||||
@ -119,38 +123,36 @@ class ZoneCommandHandlerIntegrationSpec
|
|||||||
}
|
}
|
||||||
|
|
||||||
def setup(): Unit = {
|
def setup(): Unit = {
|
||||||
val repos = (
|
val dynamoRepos = (
|
||||||
DynamoDBRecordChangeRepository(recordChangeStoreConfig, dynamoIntegrationConfig),
|
|
||||||
DynamoDBRecordSetRepository(recordSetStoreConfig, dynamoIntegrationConfig),
|
DynamoDBRecordSetRepository(recordSetStoreConfig, dynamoIntegrationConfig),
|
||||||
|
DynamoDBRecordChangeRepository(recordChangeStoreConfig, dynamoIntegrationConfig),
|
||||||
DynamoDBZoneChangeRepository(zoneChangeStoreConfig, dynamoIntegrationConfig)
|
DynamoDBZoneChangeRepository(zoneChangeStoreConfig, dynamoIntegrationConfig)
|
||||||
).parTupled.unsafeRunSync()
|
).parTupled.unsafeRunSync()
|
||||||
|
|
||||||
recordChangeRepo = repos._1
|
repositories = ApiDataAccessor(
|
||||||
recordSetRepo = repos._2
|
mock[UserRepository],
|
||||||
zoneChangeRepo = repos._3
|
mock[GroupRepository],
|
||||||
zoneRepo = TestMySqlInstance.zoneRepository
|
mock[MembershipRepository],
|
||||||
batchChangeRepo = TestMySqlInstance.batchChangeRepository
|
mock[GroupChangeRepository],
|
||||||
|
dynamoRepos._1,
|
||||||
|
dynamoRepos._2,
|
||||||
|
dynamoRepos._3,
|
||||||
|
TestMySqlInstance.zoneRepository,
|
||||||
|
TestMySqlInstance.batchChangeRepository
|
||||||
|
)
|
||||||
|
|
||||||
sqsConn = SqsConnection()
|
sqsConn = SqsConnection()
|
||||||
|
|
||||||
//seed items database
|
//seed items database
|
||||||
waitForSuccess(zoneRepo.save(testZone))
|
(
|
||||||
waitForSuccess(recordChangeRepo.save(inDbRecordChange))
|
repositories.zoneRepository.save(testZone),
|
||||||
waitForSuccess(recordChangeRepo.save(inDbRecordChangeForSyncTest))
|
repositories.recordChangeRepository.save(inDbRecordChange),
|
||||||
waitForSuccess(recordSetRepo.apply(inDbRecordChange))
|
repositories.recordChangeRepository.save(inDbRecordChangeForSyncTest),
|
||||||
waitForSuccess(recordSetRepo.apply(inDbRecordChangeForSyncTest))
|
repositories.recordSetRepository.apply(inDbRecordChange),
|
||||||
waitForSuccess(zoneChangeRepo.save(inDbZoneChange))
|
repositories.recordSetRepository.apply(inDbRecordChangeForSyncTest),
|
||||||
// Run a noop query to make sure recordSetRepo is up
|
repositories.zoneChangeRepository.save(inDbZoneChange)).parTupled.unsafeRunSync()
|
||||||
waitForSuccess(recordSetRepo.listRecordSets("1", None, None, None))
|
|
||||||
|
|
||||||
str = ZoneCommandHandler.mainFlow(
|
str = ZoneCommandHandler.mainFlow(repositories, sqsConn, 100.millis, stopSignal)
|
||||||
zoneRepo,
|
|
||||||
zoneChangeRepo,
|
|
||||||
recordSetRepo,
|
|
||||||
recordChangeRepo,
|
|
||||||
batchChangeRepo,
|
|
||||||
sqsConn,
|
|
||||||
100.millis,
|
|
||||||
stopSignal)
|
|
||||||
str.compile.drain.unsafeRunAsync { _ =>
|
str.compile.drain.unsafeRunAsync { _ =>
|
||||||
()
|
()
|
||||||
}
|
}
|
||||||
@ -168,7 +170,7 @@ class ZoneCommandHandlerIntegrationSpec
|
|||||||
|
|
||||||
sendCommand(change, sqsConn).unsafeRunSync()
|
sendCommand(change, sqsConn).unsafeRunSync()
|
||||||
eventually {
|
eventually {
|
||||||
val getZone = zoneRepo.getZone(testZone.id).unsafeToFuture()
|
val getZone = repositories.zoneRepository.getZone(testZone.id).unsafeToFuture()
|
||||||
whenReady(getZone) { zn =>
|
whenReady(getZone) { zn =>
|
||||||
zn.get.email shouldBe "updated@test.com"
|
zn.get.email shouldBe "updated@test.com"
|
||||||
}
|
}
|
||||||
@ -180,7 +182,9 @@ class ZoneCommandHandlerIntegrationSpec
|
|||||||
RecordSetChangeGenerator.forUpdate(inDbRecordSet, inDbRecordSet.copy(ttl = 1234), testZone)
|
RecordSetChangeGenerator.forUpdate(inDbRecordSet, inDbRecordSet.copy(ttl = 1234), testZone)
|
||||||
sendCommand(change, sqsConn).unsafeRunSync()
|
sendCommand(change, sqsConn).unsafeRunSync()
|
||||||
eventually {
|
eventually {
|
||||||
val getRs = recordSetRepo.getRecordSet(testZone.id, inDbRecordSet.id).unsafeToFuture()
|
val getRs = repositories.recordSetRepository
|
||||||
|
.getRecordSet(testZone.id, inDbRecordSet.id)
|
||||||
|
.unsafeToFuture()
|
||||||
whenReady(getRs) { rs =>
|
whenReady(getRs) { rs =>
|
||||||
rs.get.ttl shouldBe 1234
|
rs.get.ttl shouldBe 1234
|
||||||
}
|
}
|
||||||
@ -192,8 +196,9 @@ class ZoneCommandHandlerIntegrationSpec
|
|||||||
sendCommand(change, sqsConn).unsafeRunSync()
|
sendCommand(change, sqsConn).unsafeRunSync()
|
||||||
eventually {
|
eventually {
|
||||||
val validatingQueries = for {
|
val validatingQueries = for {
|
||||||
rs <- recordSetRepo.getRecordSet(testZone.id, inDbRecordSetForSyncTest.id)
|
rs <- repositories.recordSetRepository
|
||||||
ch <- recordChangeRepo.listRecordSetChanges(testZone.id)
|
.getRecordSet(testZone.id, inDbRecordSetForSyncTest.id)
|
||||||
|
ch <- repositories.recordChangeRepository.listRecordSetChanges(testZone.id)
|
||||||
} yield (rs, ch)
|
} yield (rs, ch)
|
||||||
|
|
||||||
whenReady(validatingQueries.unsafeToFuture()) { data =>
|
whenReady(validatingQueries.unsafeToFuture()) { data =>
|
||||||
@ -210,9 +215,4 @@ class ZoneCommandHandlerIntegrationSpec
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private def waitForSuccess[T](f: => IO[T]): T = {
|
|
||||||
val waiting = f.unsafeToFuture().recover { case _ => Thread.sleep(2000); waitForSuccess(f) }
|
|
||||||
Await.result[T](waiting, 15.seconds)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -20,11 +20,15 @@ import vinyldns.api.VinylDNSConfig
|
|||||||
import vinyldns.api.crypto.Crypto
|
import vinyldns.api.crypto.Crypto
|
||||||
import vinyldns.core.domain.batch.BatchChangeRepository
|
import vinyldns.core.domain.batch.BatchChangeRepository
|
||||||
import vinyldns.core.domain.zone.{ZoneChangeRepository, ZoneRepository}
|
import vinyldns.core.domain.zone.{ZoneChangeRepository, ZoneRepository}
|
||||||
import vinyldns.core.repository.{DataStore, RepositoryName}
|
import vinyldns.core.repository.{DataStore, DataStoreConfig, RepositoryName}
|
||||||
|
|
||||||
object TestMySqlInstance {
|
object TestMySqlInstance {
|
||||||
|
|
||||||
|
lazy val mySqlConfig: DataStoreConfig =
|
||||||
|
pureconfig.loadConfigOrThrow[DataStoreConfig](VinylDNSConfig.vinyldnsConfig, "mysql")
|
||||||
|
|
||||||
lazy val instance: DataStore =
|
lazy val instance: DataStore =
|
||||||
new MySqlDataStoreProvider().load(VinylDNSConfig.mySqlConfig, Crypto.instance).unsafeRunSync()
|
new MySqlDataStoreProvider().load(mySqlConfig, Crypto.instance).unsafeRunSync()
|
||||||
|
|
||||||
lazy val zoneRepository: ZoneRepository =
|
lazy val zoneRepository: ZoneRepository =
|
||||||
instance.get[ZoneRepository](RepositoryName.zone).get
|
instance.get[ZoneRepository](RepositoryName.zone).get
|
||||||
|
@ -46,6 +46,44 @@ vinyldns {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dynamodb.repositories {
|
||||||
|
record-set {
|
||||||
|
table-name = "recordSetTest"
|
||||||
|
provisioned-reads = 30
|
||||||
|
provisioned-writes = 20
|
||||||
|
}
|
||||||
|
record-change {
|
||||||
|
table-name = "recordChangeTest"
|
||||||
|
provisioned-reads = 30
|
||||||
|
provisioned-writes = 20
|
||||||
|
}
|
||||||
|
zone-change {
|
||||||
|
table-name = "zoneChangesTest"
|
||||||
|
provisioned-reads = 30
|
||||||
|
provisioned-writes = 20
|
||||||
|
}
|
||||||
|
user {
|
||||||
|
table-name = "usersTest"
|
||||||
|
provisioned-reads = 30
|
||||||
|
provisioned-writes = 20
|
||||||
|
}
|
||||||
|
group {
|
||||||
|
table-name = "groupsTest"
|
||||||
|
provisioned-reads = 30
|
||||||
|
provisioned-writes = 20
|
||||||
|
}
|
||||||
|
group-change {
|
||||||
|
table-name = "groupChangesTest"
|
||||||
|
provisioned-reads = 30
|
||||||
|
provisioned-writes = 20
|
||||||
|
}
|
||||||
|
membership {
|
||||||
|
table-name = "membershipTest"
|
||||||
|
provisioned-reads = 30
|
||||||
|
provisioned-writes = 20
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sync-delay = 10000 # 10 second delay for resyncing zone
|
sync-delay = 10000 # 10 second delay for resyncing zone
|
||||||
|
|
||||||
batch-change-limit = 20 # Max change limit per batch request
|
batch-change-limit = 20 # Max change limit per batch request
|
||||||
|
@ -33,7 +33,7 @@ vinyldns {
|
|||||||
port = 9000
|
port = 9000
|
||||||
}
|
}
|
||||||
|
|
||||||
data-stores = ["mysql"]
|
data-stores = ["mysql", "dynamodb"]
|
||||||
|
|
||||||
mysql {
|
mysql {
|
||||||
class-name = "vinyldns.api.repository.mysql.MySqlDataStoreProvider"
|
class-name = "vinyldns.api.repository.mysql.MySqlDataStoreProvider"
|
||||||
@ -59,60 +59,18 @@ vinyldns {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamo {
|
dynamodb {
|
||||||
key = "vinyldnsTest"
|
class-name = "vinyldns.dynamodb.repository.DynamoDBDataStoreProvider"
|
||||||
secret = "notNeededForDynamoDbLocal"
|
|
||||||
endpoint = "http://127.0.0.1:19000"
|
|
||||||
region = "us-east-1" # note: we are always in us-east-1, but this can be overridden
|
|
||||||
}
|
|
||||||
|
|
||||||
zoneChanges {
|
settings {
|
||||||
dynamo {
|
key = "vinyldnsTest"
|
||||||
tableName = "zoneChanges"
|
secret = "notNeededForDynamoDbLocal"
|
||||||
provisionedReads=30
|
endpoint = "http://127.0.0.1:19000"
|
||||||
provisionedWrites=30
|
region = "us-east-1" # note: we are always in us-east-1, but this can be overridden
|
||||||
}
|
}
|
||||||
}
|
|
||||||
recordSet {
|
repositories {
|
||||||
dynamo {
|
# override
|
||||||
tableName = "recordSet"
|
|
||||||
provisionedReads=30
|
|
||||||
provisionedWrites=30
|
|
||||||
}
|
|
||||||
}
|
|
||||||
recordChange {
|
|
||||||
dynamo {
|
|
||||||
tableName = "recordChange"
|
|
||||||
provisionedReads=30
|
|
||||||
provisionedWrites=30
|
|
||||||
}
|
|
||||||
}
|
|
||||||
users {
|
|
||||||
dynamo {
|
|
||||||
tableName = "users"
|
|
||||||
provisionedReads=30
|
|
||||||
provisionedWrites=30
|
|
||||||
}
|
|
||||||
}
|
|
||||||
groups {
|
|
||||||
dynamo {
|
|
||||||
tableName = "groups"
|
|
||||||
provisionedReads=30
|
|
||||||
provisionedWrites=30
|
|
||||||
}
|
|
||||||
}
|
|
||||||
groupChanges {
|
|
||||||
dynamo {
|
|
||||||
tableName = "groupChanges"
|
|
||||||
provisionedReads=30
|
|
||||||
provisionedWrites=30
|
|
||||||
}
|
|
||||||
}
|
|
||||||
membership {
|
|
||||||
dynamo {
|
|
||||||
tableName = "membership"
|
|
||||||
provisionedReads=30
|
|
||||||
provisionedWrites=30
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,14 +32,10 @@ import vinyldns.api.domain.record.RecordSetService
|
|||||||
import vinyldns.api.domain.zone._
|
import vinyldns.api.domain.zone._
|
||||||
import vinyldns.api.engine.ProductionZoneCommandHandler
|
import vinyldns.api.engine.ProductionZoneCommandHandler
|
||||||
import vinyldns.api.engine.sqs.{SqsCommandBus, SqsConnection}
|
import vinyldns.api.engine.sqs.{SqsCommandBus, SqsConnection}
|
||||||
import vinyldns.dynamodb.repository._
|
import vinyldns.api.repository.{ApiDataAccessor, ApiDataAccessorProvider, TestDataLoader}
|
||||||
import vinyldns.api.repository.TestDataLoader
|
|
||||||
import vinyldns.api.repository.mysql.MySqlDataStoreProvider
|
|
||||||
import vinyldns.api.route.{HealthService, VinylDNSService}
|
import vinyldns.api.route.{HealthService, VinylDNSService}
|
||||||
import vinyldns.core.VinylDNSMetrics
|
import vinyldns.core.VinylDNSMetrics
|
||||||
import vinyldns.core.domain.batch.BatchChangeRepository
|
import vinyldns.core.repository.DataStoreLoader
|
||||||
import vinyldns.core.domain.zone.ZoneRepository
|
|
||||||
import vinyldns.core.repository.{DataStoreStartupError, RepositoryName}
|
|
||||||
|
|
||||||
import scala.concurrent.{ExecutionContext, Future}
|
import scala.concurrent.{ExecutionContext, Future}
|
||||||
import scala.io.{Codec, Source}
|
import scala.io.{Codec, Source}
|
||||||
@ -65,41 +61,10 @@ object Boot extends App {
|
|||||||
for {
|
for {
|
||||||
banner <- vinyldnsBanner()
|
banner <- vinyldnsBanner()
|
||||||
crypto <- IO(Crypto.instance) // load crypto
|
crypto <- IO(Crypto.instance) // load crypto
|
||||||
// TODO datastore loading will not be hardcoded by type here
|
repoConfigs <- VinylDNSConfig.dataStoreConfigs
|
||||||
mySqlDataStore <- new MySqlDataStoreProvider().load(VinylDNSConfig.mySqlConfig, crypto)
|
repositories <- DataStoreLoader
|
||||||
zoneRepo <- IO.fromEither(
|
.loadAll[ApiDataAccessor](repoConfigs, crypto, ApiDataAccessorProvider)
|
||||||
mySqlDataStore
|
_ <- TestDataLoader.loadTestData(repositories.userRepository)
|
||||||
.get[ZoneRepository](RepositoryName.zone)
|
|
||||||
.toRight[Throwable](DataStoreStartupError("Missing zone repository")))
|
|
||||||
batchChangeRepo <- IO.fromEither(
|
|
||||||
mySqlDataStore
|
|
||||||
.get[BatchChangeRepository](RepositoryName.batchChange)
|
|
||||||
.toRight[Throwable](DataStoreStartupError("Missing zone repository")))
|
|
||||||
// TODO this also will all be removed with dynamic loading
|
|
||||||
userRepo <- DynamoDBUserRepository(
|
|
||||||
VinylDNSConfig.usersStoreConfig,
|
|
||||||
VinylDNSConfig.dynamoConfig,
|
|
||||||
crypto
|
|
||||||
)
|
|
||||||
groupRepo <- DynamoDBGroupRepository(
|
|
||||||
VinylDNSConfig.groupsStoreConfig,
|
|
||||||
VinylDNSConfig.dynamoConfig)
|
|
||||||
membershipRepo <- DynamoDBMembershipRepository(
|
|
||||||
VinylDNSConfig.membershipStoreConfig,
|
|
||||||
VinylDNSConfig.dynamoConfig)
|
|
||||||
groupChangeRepo <- DynamoDBGroupChangeRepository(
|
|
||||||
VinylDNSConfig.groupChangesStoreConfig,
|
|
||||||
VinylDNSConfig.dynamoConfig)
|
|
||||||
recordSetRepo <- DynamoDBRecordSetRepository(
|
|
||||||
VinylDNSConfig.recordSetStoreConfig,
|
|
||||||
VinylDNSConfig.dynamoConfig)
|
|
||||||
recordChangeRepo <- DynamoDBRecordChangeRepository(
|
|
||||||
VinylDNSConfig.recordChangeStoreConfig,
|
|
||||||
VinylDNSConfig.dynamoConfig)
|
|
||||||
zoneChangeRepo <- DynamoDBZoneChangeRepository(
|
|
||||||
VinylDNSConfig.zoneChangeStoreConfig,
|
|
||||||
VinylDNSConfig.dynamoConfig)
|
|
||||||
_ <- TestDataLoader.loadTestData(userRepo)
|
|
||||||
sqsConfig <- IO(VinylDNSConfig.sqsConfig)
|
sqsConfig <- IO(VinylDNSConfig.sqsConfig)
|
||||||
sqsConnection <- IO(SqsConnection(sqsConfig))
|
sqsConnection <- IO(SqsConnection(sqsConfig))
|
||||||
processingDisabled <- IO(VinylDNSConfig.vinyldnsConfig.getBoolean("processing-disabled"))
|
processingDisabled <- IO(VinylDNSConfig.vinyldnsConfig.getBoolean("processing-disabled"))
|
||||||
@ -109,47 +74,26 @@ object Boot extends App {
|
|||||||
batchChangeLimit <- IO(VinylDNSConfig.vinyldnsConfig.getInt("batch-change-limit"))
|
batchChangeLimit <- IO(VinylDNSConfig.vinyldnsConfig.getInt("batch-change-limit"))
|
||||||
syncDelay <- IO(VinylDNSConfig.vinyldnsConfig.getInt("sync-delay"))
|
syncDelay <- IO(VinylDNSConfig.vinyldnsConfig.getInt("sync-delay"))
|
||||||
_ <- fs2.async.start(
|
_ <- fs2.async.start(
|
||||||
ProductionZoneCommandHandler.run(
|
ProductionZoneCommandHandler.run(sqsConnection, processingSignal, repositories, sqsConfig))
|
||||||
sqsConnection,
|
|
||||||
processingSignal,
|
|
||||||
zoneRepo,
|
|
||||||
zoneChangeRepo,
|
|
||||||
recordChangeRepo,
|
|
||||||
recordSetRepo,
|
|
||||||
batchChangeRepo,
|
|
||||||
sqsConfig))
|
|
||||||
} yield {
|
} yield {
|
||||||
val zoneValidations = new ZoneValidations(syncDelay)
|
val zoneValidations = new ZoneValidations(syncDelay)
|
||||||
val batchChangeValidations = new BatchChangeValidations(batchChangeLimit, AccessValidations)
|
val batchChangeValidations = new BatchChangeValidations(batchChangeLimit, AccessValidations)
|
||||||
val commandBus = new SqsCommandBus(sqsConnection)
|
val commandBus = new SqsCommandBus(sqsConnection)
|
||||||
val membershipService =
|
val membershipService = MembershipService(repositories)
|
||||||
new MembershipService(groupRepo, userRepo, membershipRepo, zoneRepo, groupChangeRepo)
|
|
||||||
val connectionValidator =
|
val connectionValidator =
|
||||||
new ZoneConnectionValidator(VinylDNSConfig.defaultZoneConnection)
|
new ZoneConnectionValidator(VinylDNSConfig.defaultZoneConnection)
|
||||||
val recordSetService = new RecordSetService(
|
val recordSetService = RecordSetService(repositories, commandBus, AccessValidations)
|
||||||
zoneRepo,
|
val zoneService = ZoneService(
|
||||||
recordSetRepo,
|
repositories,
|
||||||
recordChangeRepo,
|
|
||||||
userRepo,
|
|
||||||
commandBus,
|
|
||||||
AccessValidations)
|
|
||||||
val zoneService = new ZoneService(
|
|
||||||
zoneRepo,
|
|
||||||
groupRepo,
|
|
||||||
userRepo,
|
|
||||||
zoneChangeRepo,
|
|
||||||
connectionValidator,
|
connectionValidator,
|
||||||
commandBus,
|
commandBus,
|
||||||
zoneValidations,
|
zoneValidations,
|
||||||
AccessValidations)
|
AccessValidations)
|
||||||
val healthService = new HealthService(zoneRepo)
|
val healthService = new HealthService(repositories.zoneRepository)
|
||||||
val batchChangeConverter = new BatchChangeConverter(batchChangeRepo, commandBus)
|
val batchChangeConverter =
|
||||||
val batchChangeService = new BatchChangeService(
|
new BatchChangeConverter(repositories.batchChangeRepository, commandBus)
|
||||||
zoneRepo,
|
val batchChangeService =
|
||||||
recordSetRepo,
|
BatchChangeService(repositories, batchChangeValidations, batchChangeConverter)
|
||||||
batchChangeValidations,
|
|
||||||
batchChangeRepo,
|
|
||||||
batchChangeConverter)
|
|
||||||
val collectorRegistry = CollectorRegistry.defaultRegistry
|
val collectorRegistry = CollectorRegistry.defaultRegistry
|
||||||
val vinyldnsService = new VinylDNSService(
|
val vinyldnsService = new VinylDNSService(
|
||||||
membershipService,
|
membershipService,
|
||||||
@ -158,7 +102,10 @@ object Boot extends App {
|
|||||||
healthService,
|
healthService,
|
||||||
recordSetService,
|
recordSetService,
|
||||||
batchChangeService,
|
batchChangeService,
|
||||||
collectorRegistry)
|
collectorRegistry,
|
||||||
|
repositories.userRepository,
|
||||||
|
repositories.membershipRepository
|
||||||
|
)
|
||||||
|
|
||||||
DefaultExports.initialize()
|
DefaultExports.initialize()
|
||||||
collectorRegistry.register(new DropwizardExports(VinylDNSMetrics.metricsRegistry))
|
collectorRegistry.register(new DropwizardExports(VinylDNSMetrics.metricsRegistry))
|
||||||
|
@ -17,7 +17,10 @@
|
|||||||
package vinyldns.api
|
package vinyldns.api
|
||||||
|
|
||||||
import akka.actor.ActorSystem
|
import akka.actor.ActorSystem
|
||||||
|
import cats.effect.IO
|
||||||
|
import cats.implicits._
|
||||||
import com.typesafe.config.{Config, ConfigFactory}
|
import com.typesafe.config.{Config, ConfigFactory}
|
||||||
|
import pureconfig.module.catseffect.loadConfigF
|
||||||
import pureconfig.{CamelCase, ConfigFieldMapping, ProductHint}
|
import pureconfig.{CamelCase, ConfigFieldMapping, ProductHint}
|
||||||
import vinyldns.api.VinylDNSConfig.vinyldnsConfig
|
import vinyldns.api.VinylDNSConfig.vinyldnsConfig
|
||||||
import vinyldns.api.crypto.Crypto
|
import vinyldns.api.crypto.Crypto
|
||||||
@ -33,21 +36,18 @@ object VinylDNSConfig {
|
|||||||
lazy val config: Config = ConfigFactory.load()
|
lazy val config: Config = ConfigFactory.load()
|
||||||
lazy val vinyldnsConfig: Config = config.getConfig("vinyldns")
|
lazy val vinyldnsConfig: Config = config.getConfig("vinyldns")
|
||||||
|
|
||||||
lazy val dynamoConfig = DynamoConfig.dynamoConfig
|
lazy val dataStoreConfigs: IO[List[DataStoreConfig]] =
|
||||||
lazy val zoneChangeStoreConfig: DynamoDBRepositorySettings = DynamoConfig.zoneChangeStoreConfig
|
vinyldnsConfig
|
||||||
lazy val recordSetStoreConfig: DynamoDBRepositorySettings = DynamoConfig.recordSetStoreConfig
|
.getStringList("data-stores")
|
||||||
lazy val recordChangeStoreConfig: DynamoDBRepositorySettings =
|
.asScala
|
||||||
DynamoConfig.recordChangeStoreConfig
|
.toList
|
||||||
lazy val usersStoreConfig: DynamoDBRepositorySettings = DynamoConfig.usersStoreConfig
|
.map { configKey =>
|
||||||
lazy val groupsStoreConfig: DynamoDBRepositorySettings = DynamoConfig.groupsStoreConfig
|
loadConfigF[IO, DataStoreConfig](vinyldnsConfig, configKey)
|
||||||
lazy val groupChangesStoreConfig: DynamoDBRepositorySettings =
|
}
|
||||||
DynamoConfig.groupChangesStoreConfig
|
.parSequence
|
||||||
lazy val membershipStoreConfig: DynamoDBRepositorySettings = DynamoConfig.membershipStoreConfig
|
|
||||||
|
|
||||||
lazy val restConfig: Config = vinyldnsConfig.getConfig("rest")
|
lazy val restConfig: Config = vinyldnsConfig.getConfig("rest")
|
||||||
lazy val monitoringConfig: Config = vinyldnsConfig.getConfig("monitoring")
|
lazy val monitoringConfig: Config = vinyldnsConfig.getConfig("monitoring")
|
||||||
lazy val mySqlConfig: DataStoreConfig =
|
|
||||||
pureconfig.loadConfigOrThrow[DataStoreConfig](vinyldnsConfig, "mysql")
|
|
||||||
lazy val sqsConfig: Config = vinyldnsConfig.getConfig("sqs")
|
lazy val sqsConfig: Config = vinyldnsConfig.getConfig("sqs")
|
||||||
lazy val cryptoConfig: Config = vinyldnsConfig.getConfig("crypto")
|
lazy val cryptoConfig: Config = vinyldnsConfig.getConfig("crypto")
|
||||||
lazy val system: ActorSystem = ActorSystem("VinylDNS", VinylDNSConfig.config)
|
lazy val system: ActorSystem = ActorSystem("VinylDNS", VinylDNSConfig.config)
|
||||||
|
@ -17,10 +17,7 @@
|
|||||||
package vinyldns.api.domain.auth
|
package vinyldns.api.domain.auth
|
||||||
|
|
||||||
import cats.effect._
|
import cats.effect._
|
||||||
import vinyldns.api.VinylDNSConfig
|
|
||||||
import vinyldns.api.crypto.Crypto
|
|
||||||
import vinyldns.core.domain.membership.{MembershipRepository, User, UserRepository}
|
import vinyldns.core.domain.membership.{MembershipRepository, User, UserRepository}
|
||||||
import vinyldns.dynamodb.repository.{DynamoDBMembershipRepository, DynamoDBUserRepository}
|
|
||||||
import vinyldns.core.domain.auth.AuthPrincipal
|
import vinyldns.core.domain.auth.AuthPrincipal
|
||||||
import vinyldns.core.route.Monitored
|
import vinyldns.core.route.Monitored
|
||||||
|
|
||||||
@ -52,19 +49,3 @@ class MembershipAuthPrincipalProvider(
|
|||||||
membershipRepo.getGroupsForUser(userId)
|
membershipRepo.getGroupsForUser(userId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object MembershipAuthPrincipalProvider {
|
|
||||||
// TODO this has to be dynamic!!!
|
|
||||||
val userRepository: UserRepository =
|
|
||||||
DynamoDBUserRepository(
|
|
||||||
VinylDNSConfig.usersStoreConfig,
|
|
||||||
VinylDNSConfig.dynamoConfig,
|
|
||||||
Crypto.instance)
|
|
||||||
.unsafeRunSync()
|
|
||||||
val membershipRepository: MembershipRepository =
|
|
||||||
DynamoDBMembershipRepository(VinylDNSConfig.membershipStoreConfig, VinylDNSConfig.dynamoConfig)
|
|
||||||
.unsafeRunSync()
|
|
||||||
|
|
||||||
def apply(): MembershipAuthPrincipalProvider =
|
|
||||||
new MembershipAuthPrincipalProvider(userRepository, membershipRepository)
|
|
||||||
}
|
|
||||||
|
@ -29,8 +29,22 @@ import vinyldns.core.domain.record.RecordType._
|
|||||||
import vinyldns.core.domain.record.{RecordSet, RecordSetRepository}
|
import vinyldns.core.domain.record.{RecordSet, RecordSetRepository}
|
||||||
import vinyldns.core.domain.zone.ZoneRepository
|
import vinyldns.core.domain.zone.ZoneRepository
|
||||||
import vinyldns.api.domain.{RecordAlreadyExists, ZoneDiscoveryError}
|
import vinyldns.api.domain.{RecordAlreadyExists, ZoneDiscoveryError}
|
||||||
|
import vinyldns.api.repository.ApiDataAccessor
|
||||||
import vinyldns.core.domain.batch.{BatchChange, BatchChangeRepository, BatchChangeSummaryList}
|
import vinyldns.core.domain.batch.{BatchChange, BatchChangeRepository, BatchChangeSummaryList}
|
||||||
|
|
||||||
|
object BatchChangeService {
|
||||||
|
def apply(
|
||||||
|
dataAccessor: ApiDataAccessor,
|
||||||
|
batchChangeValidations: BatchChangeValidationsAlgebra,
|
||||||
|
batchChangeConverter: BatchChangeConverterAlgebra): BatchChangeService =
|
||||||
|
new BatchChangeService(
|
||||||
|
dataAccessor.zoneRepository,
|
||||||
|
dataAccessor.recordSetRepository,
|
||||||
|
batchChangeValidations,
|
||||||
|
dataAccessor.batchChangeRepository,
|
||||||
|
batchChangeConverter)
|
||||||
|
}
|
||||||
|
|
||||||
class BatchChangeService(
|
class BatchChangeService(
|
||||||
zoneRepository: ZoneRepository,
|
zoneRepository: ZoneRepository,
|
||||||
recordSetRepository: RecordSetRepository,
|
recordSetRepository: RecordSetRepository,
|
||||||
|
@ -18,11 +18,23 @@ package vinyldns.api.domain.membership
|
|||||||
|
|
||||||
import cats.implicits._
|
import cats.implicits._
|
||||||
import vinyldns.api.Interfaces._
|
import vinyldns.api.Interfaces._
|
||||||
|
import vinyldns.api.repository.ApiDataAccessor
|
||||||
import vinyldns.core.domain.auth.AuthPrincipal
|
import vinyldns.core.domain.auth.AuthPrincipal
|
||||||
import vinyldns.core.domain.membership.LockStatus.LockStatus
|
import vinyldns.core.domain.membership.LockStatus.LockStatus
|
||||||
import vinyldns.core.domain.zone.ZoneRepository
|
import vinyldns.core.domain.zone.ZoneRepository
|
||||||
import vinyldns.core.domain.membership._
|
import vinyldns.core.domain.membership._
|
||||||
|
|
||||||
|
object MembershipService {
|
||||||
|
def apply(dataAccessor: ApiDataAccessor): MembershipService =
|
||||||
|
new MembershipService(
|
||||||
|
dataAccessor.groupRepository,
|
||||||
|
dataAccessor.userRepository,
|
||||||
|
dataAccessor.membershipRepository,
|
||||||
|
dataAccessor.zoneRepository,
|
||||||
|
dataAccessor.groupChangeRepository
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
class MembershipService(
|
class MembershipService(
|
||||||
groupRepo: GroupRepository,
|
groupRepo: GroupRepository,
|
||||||
userRepo: UserRepository,
|
userRepo: UserRepository,
|
||||||
|
@ -22,10 +22,26 @@ import vinyldns.core.domain.auth.AuthPrincipal
|
|||||||
import vinyldns.api.domain.engine.EngineCommandBus
|
import vinyldns.api.domain.engine.EngineCommandBus
|
||||||
import vinyldns.core.domain.membership.{User, UserRepository}
|
import vinyldns.core.domain.membership.{User, UserRepository}
|
||||||
import vinyldns.api.domain.zone._
|
import vinyldns.api.domain.zone._
|
||||||
|
import vinyldns.api.repository.ApiDataAccessor
|
||||||
import vinyldns.api.route.ListRecordSetsResponse
|
import vinyldns.api.route.ListRecordSetsResponse
|
||||||
import vinyldns.core.domain.record._
|
import vinyldns.core.domain.record._
|
||||||
import vinyldns.core.domain.zone.{Zone, ZoneCommandResult, ZoneRepository}
|
import vinyldns.core.domain.zone.{Zone, ZoneCommandResult, ZoneRepository}
|
||||||
|
|
||||||
|
object RecordSetService {
|
||||||
|
def apply(
|
||||||
|
dataAccessor: ApiDataAccessor,
|
||||||
|
commandBus: EngineCommandBus,
|
||||||
|
accessValidation: AccessValidationAlgebra): RecordSetService =
|
||||||
|
new RecordSetService(
|
||||||
|
dataAccessor.zoneRepository,
|
||||||
|
dataAccessor.recordSetRepository,
|
||||||
|
dataAccessor.recordChangeRepository,
|
||||||
|
dataAccessor.userRepository,
|
||||||
|
commandBus,
|
||||||
|
accessValidation
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
class RecordSetService(
|
class RecordSetService(
|
||||||
zoneRepository: ZoneRepository,
|
zoneRepository: ZoneRepository,
|
||||||
recordSetRepository: RecordSetRepository,
|
recordSetRepository: RecordSetRepository,
|
||||||
|
@ -21,9 +21,29 @@ import vinyldns.api.Interfaces._
|
|||||||
import vinyldns.api.domain.AccessValidationAlgebra
|
import vinyldns.api.domain.AccessValidationAlgebra
|
||||||
import vinyldns.core.domain.auth.AuthPrincipal
|
import vinyldns.core.domain.auth.AuthPrincipal
|
||||||
import vinyldns.api.domain.engine.EngineCommandBus
|
import vinyldns.api.domain.engine.EngineCommandBus
|
||||||
|
import vinyldns.api.repository.ApiDataAccessor
|
||||||
import vinyldns.core.domain.membership.{Group, GroupRepository, User, UserRepository}
|
import vinyldns.core.domain.membership.{Group, GroupRepository, User, UserRepository}
|
||||||
import vinyldns.core.domain.zone._
|
import vinyldns.core.domain.zone._
|
||||||
|
|
||||||
|
object ZoneService {
|
||||||
|
def apply(
|
||||||
|
dataAccessor: ApiDataAccessor,
|
||||||
|
connectionValidator: ZoneConnectionValidatorAlgebra,
|
||||||
|
commandBus: EngineCommandBus,
|
||||||
|
zoneValidations: ZoneValidations,
|
||||||
|
accessValidation: AccessValidationAlgebra): ZoneService =
|
||||||
|
new ZoneService(
|
||||||
|
dataAccessor.zoneRepository,
|
||||||
|
dataAccessor.groupRepository,
|
||||||
|
dataAccessor.userRepository,
|
||||||
|
dataAccessor.zoneChangeRepository,
|
||||||
|
connectionValidator,
|
||||||
|
commandBus,
|
||||||
|
zoneValidations,
|
||||||
|
accessValidation
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
class ZoneService(
|
class ZoneService(
|
||||||
zoneRepository: ZoneRepository,
|
zoneRepository: ZoneRepository,
|
||||||
groupRepository: GroupRepository,
|
groupRepository: GroupRepository,
|
||||||
|
@ -26,10 +26,10 @@ import fs2.async.mutable.Signal
|
|||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import vinyldns.api.VinylDNSConfig
|
import vinyldns.api.VinylDNSConfig
|
||||||
import vinyldns.api.domain.dns.DnsConnection
|
import vinyldns.api.domain.dns.DnsConnection
|
||||||
import vinyldns.core.domain.record.{RecordChangeRepository, RecordSetChange, RecordSetRepository}
|
import vinyldns.core.domain.record.RecordSetChange
|
||||||
import vinyldns.core.domain.zone.{ZoneChange, ZoneChangeRepository, ZoneChangeType, ZoneRepository}
|
import vinyldns.core.domain.zone.{ZoneChange, ZoneChangeType}
|
||||||
import vinyldns.api.engine.sqs.SqsConnection
|
import vinyldns.api.engine.sqs.SqsConnection
|
||||||
import vinyldns.core.domain.batch.BatchChangeRepository
|
import vinyldns.api.repository.ApiDataAccessor
|
||||||
|
|
||||||
import scala.collection.JavaConverters._
|
import scala.collection.JavaConverters._
|
||||||
import scala.concurrent.ExecutionContext.Implicits.global
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
@ -63,11 +63,7 @@ object ZoneCommandHandler {
|
|||||||
extends ChangeRequest
|
extends ChangeRequest
|
||||||
|
|
||||||
def mainFlow(
|
def mainFlow(
|
||||||
zoneRepository: ZoneRepository,
|
dataAccessor: ApiDataAccessor,
|
||||||
zoneChangeRepository: ZoneChangeRepository,
|
|
||||||
recordSetRepository: RecordSetRepository,
|
|
||||||
recordChangeRepository: RecordChangeRepository,
|
|
||||||
batchChangeRepository: BatchChangeRepository,
|
|
||||||
sqsConnection: SqsConnection,
|
sqsConnection: SqsConnection,
|
||||||
pollingInterval: FiniteDuration,
|
pollingInterval: FiniteDuration,
|
||||||
pauseSignal: Signal[IO, Boolean])(implicit scheduler: Scheduler): Stream[IO, Unit] = {
|
pauseSignal: Signal[IO, Boolean])(implicit scheduler: Scheduler): Stream[IO, Unit] = {
|
||||||
@ -79,10 +75,15 @@ object ZoneCommandHandler {
|
|||||||
val increaseTimeoutForZoneSyncs = changeVisibilityTimeoutForZoneSyncs(sqsConnection)
|
val increaseTimeoutForZoneSyncs = changeVisibilityTimeoutForZoneSyncs(sqsConnection)
|
||||||
|
|
||||||
// Handlers for each type of change request
|
// Handlers for each type of change request
|
||||||
val zoneChangeHandler = ZoneChangeHandler(zoneRepository, zoneChangeRepository)
|
val zoneChangeHandler =
|
||||||
|
ZoneChangeHandler(dataAccessor.zoneRepository, dataAccessor.zoneChangeRepository)
|
||||||
val recordChangeHandler =
|
val recordChangeHandler =
|
||||||
RecordSetChangeHandler(recordSetRepository, recordChangeRepository, batchChangeRepository)
|
RecordSetChangeHandler(
|
||||||
val zoneSyncHandler = ZoneSyncHandler(recordSetRepository, recordChangeRepository)
|
dataAccessor.recordSetRepository,
|
||||||
|
dataAccessor.recordChangeRepository,
|
||||||
|
dataAccessor.batchChangeRepository)
|
||||||
|
val zoneSyncHandler =
|
||||||
|
ZoneSyncHandler(dataAccessor.recordSetRepository, dataAccessor.recordChangeRepository)
|
||||||
|
|
||||||
val changeRequestProcessor =
|
val changeRequestProcessor =
|
||||||
processChangeRequests(zoneChangeHandler, recordChangeHandler, zoneSyncHandler)
|
processChangeRequests(zoneChangeHandler, recordChangeHandler, zoneSyncHandler)
|
||||||
@ -237,11 +238,7 @@ object ProductionZoneCommandHandler {
|
|||||||
def run(
|
def run(
|
||||||
sqsConnection: SqsConnection,
|
sqsConnection: SqsConnection,
|
||||||
processingSignal: Signal[IO, Boolean],
|
processingSignal: Signal[IO, Boolean],
|
||||||
zoneRepository: ZoneRepository,
|
dataAccessor: ApiDataAccessor,
|
||||||
zoneChangeRepository: ZoneChangeRepository,
|
|
||||||
recordChangeRepository: RecordChangeRepository,
|
|
||||||
recordSetRepository: RecordSetRepository,
|
|
||||||
batchChangeRepository: BatchChangeRepository,
|
|
||||||
config: Config): IO[Unit] = {
|
config: Config): IO[Unit] = {
|
||||||
implicit val scheduler: Scheduler =
|
implicit val scheduler: Scheduler =
|
||||||
Scheduler.fromScheduledExecutorService(Executors.newScheduledThreadPool(2))
|
Scheduler.fromScheduledExecutorService(Executors.newScheduledThreadPool(2))
|
||||||
@ -250,15 +247,7 @@ object ProductionZoneCommandHandler {
|
|||||||
pollingInterval <- IO.pure(
|
pollingInterval <- IO.pure(
|
||||||
config.getDuration("polling-interval", TimeUnit.MILLISECONDS).milliseconds)
|
config.getDuration("polling-interval", TimeUnit.MILLISECONDS).milliseconds)
|
||||||
flow <- ZoneCommandHandler
|
flow <- ZoneCommandHandler
|
||||||
.mainFlow(
|
.mainFlow(dataAccessor, sqsConnection, pollingInterval, processingSignal)
|
||||||
zoneRepository,
|
|
||||||
zoneChangeRepository,
|
|
||||||
recordSetRepository,
|
|
||||||
recordChangeRepository,
|
|
||||||
batchChangeRepository,
|
|
||||||
sqsConnection,
|
|
||||||
pollingInterval,
|
|
||||||
processingSignal)
|
|
||||||
.compile
|
.compile
|
||||||
.drain
|
.drain
|
||||||
} yield flow
|
} yield flow
|
||||||
|
@ -21,7 +21,7 @@ import akka.http.scaladsl.server.RequestContext
|
|||||||
import cats.effect._
|
import cats.effect._
|
||||||
import cats.syntax.all._
|
import cats.syntax.all._
|
||||||
import vinyldns.api.crypto.Crypto
|
import vinyldns.api.crypto.Crypto
|
||||||
import vinyldns.api.domain.auth.{AuthPrincipalProvider, MembershipAuthPrincipalProvider}
|
import vinyldns.api.domain.auth.AuthPrincipalProvider
|
||||||
import vinyldns.core.crypto.CryptoAlgebra
|
import vinyldns.core.crypto.CryptoAlgebra
|
||||||
import vinyldns.core.domain.auth.AuthPrincipal
|
import vinyldns.core.domain.auth.AuthPrincipal
|
||||||
import vinyldns.core.domain.membership.LockStatus
|
import vinyldns.core.domain.membership.LockStatus
|
||||||
@ -34,9 +34,27 @@ final case class AuthMissing(msg: String) extends VinylDNSAuthenticationError(ms
|
|||||||
final case class AuthRejected(reason: String) extends VinylDNSAuthenticationError(reason)
|
final case class AuthRejected(reason: String) extends VinylDNSAuthenticationError(reason)
|
||||||
final case class AccountLocked(reason: String) extends VinylDNSAuthenticationError(reason)
|
final case class AccountLocked(reason: String) extends VinylDNSAuthenticationError(reason)
|
||||||
|
|
||||||
trait VinylDNSAuthentication extends Monitored {
|
trait VinylDNSAuthenticator {
|
||||||
val authenticator: Aws4Authenticator
|
def authenticate(
|
||||||
val authPrincipalProvider: AuthPrincipalProvider
|
ctx: RequestContext,
|
||||||
|
content: String): IO[Either[VinylDNSAuthenticationError, AuthPrincipal]]
|
||||||
|
}
|
||||||
|
|
||||||
|
class ProductionVinylDNSAuthenticator(
|
||||||
|
val authenticator: Aws4Authenticator,
|
||||||
|
val authPrincipalProvider: AuthPrincipalProvider)
|
||||||
|
extends VinylDNSAuthenticator
|
||||||
|
with Monitored {
|
||||||
|
|
||||||
|
def authenticate(
|
||||||
|
ctx: RequestContext,
|
||||||
|
content: String): IO[Either[VinylDNSAuthenticationError, AuthPrincipal]] =
|
||||||
|
// Need to refactor getAuthPrincipal to be an IO[Either[E, A]] instead of how it is implemented.
|
||||||
|
getAuthPrincipal(ctx, content).attempt.flatMap {
|
||||||
|
case Left(e: VinylDNSAuthenticationError) => IO.pure(Left(e))
|
||||||
|
case Right(ok) => IO.pure(Right(ok))
|
||||||
|
case Left(e) => IO.raiseError(e)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the auth header from the request. If the auth header is not found then the
|
* Gets the auth header from the request. If the auth header is not found then the
|
||||||
@ -111,7 +129,7 @@ trait VinylDNSAuthentication extends Monitored {
|
|||||||
* @param ctx The Http Request Context
|
* @param ctx The Http Request Context
|
||||||
* @return A Future containing the AuthPrincipal for the request.
|
* @return A Future containing the AuthPrincipal for the request.
|
||||||
*/
|
*/
|
||||||
def authenticate(ctx: RequestContext, content: String): IO[AuthPrincipal] =
|
def getAuthPrincipal(ctx: RequestContext, content: String): IO[AuthPrincipal] =
|
||||||
for {
|
for {
|
||||||
authHeader <- getAuthHeader(ctx)
|
authHeader <- getAuthHeader(ctx)
|
||||||
regexMatch <- parseAuthHeader(authHeader)
|
regexMatch <- parseAuthHeader(authHeader)
|
||||||
@ -138,30 +156,3 @@ trait VinylDNSAuthentication extends Monitored {
|
|||||||
IO.raiseError(AuthRejected(s"Account with accessKey $accessKey specified was not found"))
|
IO.raiseError(AuthRejected(s"Account with accessKey $accessKey specified was not found"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class VinylDNSAuthenticator(
|
|
||||||
val authenticator: Aws4Authenticator,
|
|
||||||
val authPrincipalProvider: AuthPrincipalProvider)
|
|
||||||
extends VinylDNSAuthentication {
|
|
||||||
|
|
||||||
def apply(
|
|
||||||
ctx: RequestContext,
|
|
||||||
content: String): IO[Either[VinylDNSAuthenticationError, AuthPrincipal]] =
|
|
||||||
// Need to refactor authenticate to be an IO[Either[E, A]] instead of how it is implemented, for the time being...
|
|
||||||
authenticate(ctx, content).attempt.flatMap {
|
|
||||||
case Left(e: VinylDNSAuthenticationError) => IO.pure(Left(e))
|
|
||||||
case Right(ok) => IO.pure(Right(ok))
|
|
||||||
case Left(e) => IO.raiseError(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
object VinylDNSAuthenticator {
|
|
||||||
lazy val aws4Authenticator = new Aws4Authenticator
|
|
||||||
lazy val authPrincipalProvider = MembershipAuthPrincipalProvider()
|
|
||||||
lazy val authenticator = new VinylDNSAuthenticator(aws4Authenticator, authPrincipalProvider)
|
|
||||||
|
|
||||||
def apply(
|
|
||||||
ctx: RequestContext,
|
|
||||||
content: String): IO[Either[VinylDNSAuthenticationError, AuthPrincipal]] =
|
|
||||||
authenticator.apply(ctx, content)
|
|
||||||
}
|
|
||||||
|
@ -22,7 +22,6 @@ import akka.http.scaladsl.server._
|
|||||||
import akka.http.scaladsl.server.directives.BasicDirectives
|
import akka.http.scaladsl.server.directives.BasicDirectives
|
||||||
import cats.data.Validated.{Invalid, Valid}
|
import cats.data.Validated.{Invalid, Valid}
|
||||||
import cats.data.ValidatedNel
|
import cats.data.ValidatedNel
|
||||||
import cats.effect._
|
|
||||||
import org.json4s.JsonDSL._
|
import org.json4s.JsonDSL._
|
||||||
import org.json4s.jackson.JsonMethods._
|
import org.json4s.jackson.JsonMethods._
|
||||||
import vinyldns.core.domain.auth.AuthPrincipal
|
import vinyldns.core.domain.auth.AuthPrincipal
|
||||||
@ -34,21 +33,14 @@ import scala.util.control.NonFatal
|
|||||||
|
|
||||||
trait VinylDNSDirectives extends Directives {
|
trait VinylDNSDirectives extends Directives {
|
||||||
|
|
||||||
/**
|
val vinylDNSAuthenticator: VinylDNSAuthenticator
|
||||||
* Authenticator that takes a request context and yields an Authentication, which is an Either
|
|
||||||
* that holds a Left - Rejection, or Right - AuthPrincipal.
|
|
||||||
* @return an Authentication with the AuthPrincipal as looked up from the request, or a Left(Rejection)
|
|
||||||
*/
|
|
||||||
def vinyldnsAuthenticator(
|
|
||||||
ctx: RequestContext,
|
|
||||||
content: String): IO[Either[VinylDNSAuthenticationError, AuthPrincipal]] =
|
|
||||||
VinylDNSAuthenticator(ctx, content)
|
|
||||||
|
|
||||||
def authenticate: Directive1[AuthPrincipal] =
|
def authenticate: Directive1[AuthPrincipal] =
|
||||||
extractExecutionContext.flatMap { implicit ec ⇒
|
extractExecutionContext.flatMap { implicit ec ⇒
|
||||||
extractRequestContext.flatMap { ctx =>
|
extractRequestContext.flatMap { ctx =>
|
||||||
extractStrictEntity(10.seconds).flatMap { strictEntity =>
|
extractStrictEntity(10.seconds).flatMap { strictEntity =>
|
||||||
onSuccess(vinyldnsAuthenticator(ctx, strictEntity.data.utf8String).unsafeToFuture())
|
onSuccess(
|
||||||
|
vinylDNSAuthenticator.authenticate(ctx, strictEntity.data.utf8String).unsafeToFuture())
|
||||||
.flatMap {
|
.flatMap {
|
||||||
case Right(authPrincipal) ⇒
|
case Right(authPrincipal) ⇒
|
||||||
provide(authPrincipal)
|
provide(authPrincipal)
|
||||||
|
@ -25,10 +25,12 @@ import akka.http.scaladsl.server.directives.LogEntry
|
|||||||
import cats.effect.IO
|
import cats.effect.IO
|
||||||
import fs2.async.mutable.Signal
|
import fs2.async.mutable.Signal
|
||||||
import io.prometheus.client.CollectorRegistry
|
import io.prometheus.client.CollectorRegistry
|
||||||
|
import vinyldns.api.domain.auth.MembershipAuthPrincipalProvider
|
||||||
import vinyldns.api.domain.batch.BatchChangeServiceAlgebra
|
import vinyldns.api.domain.batch.BatchChangeServiceAlgebra
|
||||||
import vinyldns.api.domain.membership.MembershipServiceAlgebra
|
import vinyldns.api.domain.membership.MembershipServiceAlgebra
|
||||||
import vinyldns.api.domain.record.RecordSetServiceAlgebra
|
import vinyldns.api.domain.record.RecordSetServiceAlgebra
|
||||||
import vinyldns.api.domain.zone.ZoneServiceAlgebra
|
import vinyldns.api.domain.zone.ZoneServiceAlgebra
|
||||||
|
import vinyldns.core.domain.membership.{MembershipRepository, UserRepository}
|
||||||
|
|
||||||
import scala.util.matching.Regex
|
import scala.util.matching.Regex
|
||||||
|
|
||||||
@ -103,7 +105,9 @@ class VinylDNSService(
|
|||||||
val healthService: HealthService,
|
val healthService: HealthService,
|
||||||
val recordSetService: RecordSetServiceAlgebra,
|
val recordSetService: RecordSetServiceAlgebra,
|
||||||
val batchChangeService: BatchChangeServiceAlgebra,
|
val batchChangeService: BatchChangeServiceAlgebra,
|
||||||
val collectorRegistry: CollectorRegistry)
|
val collectorRegistry: CollectorRegistry,
|
||||||
|
userRepository: UserRepository,
|
||||||
|
membershipRepository: MembershipRepository)
|
||||||
extends VinylDNSDirectives
|
extends VinylDNSDirectives
|
||||||
with PingRoute
|
with PingRoute
|
||||||
with ZoneRoute
|
with ZoneRoute
|
||||||
@ -117,6 +121,12 @@ class VinylDNSService(
|
|||||||
with VinylDNSJsonProtocol
|
with VinylDNSJsonProtocol
|
||||||
with JsonValidationRejection {
|
with JsonValidationRejection {
|
||||||
|
|
||||||
|
val aws4Authenticator = new Aws4Authenticator
|
||||||
|
val authPrincipalProvider =
|
||||||
|
new MembershipAuthPrincipalProvider(userRepository, membershipRepository)
|
||||||
|
val vinylDNSAuthenticator: VinylDNSAuthenticator =
|
||||||
|
new ProductionVinylDNSAuthenticator(aws4Authenticator, authPrincipalProvider)
|
||||||
|
|
||||||
// Authenticated routes must go first
|
// Authenticated routes must go first
|
||||||
def authenticatedRoutes: server.Route =
|
def authenticatedRoutes: server.Route =
|
||||||
handleRejections(validationRejectionHandler)(authenticate { authPrincipal =>
|
handleRejections(validationRejectionHandler)(authenticate { authPrincipal =>
|
||||||
|
@ -30,67 +30,41 @@ vinyldns {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
accounts {
|
dynamodb.repositories {
|
||||||
dummy = true
|
record-set {
|
||||||
|
table-name = "recordSetTest"
|
||||||
dynamo {
|
provisioned-reads = 30
|
||||||
key = "dynamoKey"
|
provisioned-writes = 20
|
||||||
secret = "dynamoSecret"
|
|
||||||
endpoint = "dynamoEndpoint"
|
|
||||||
}
|
}
|
||||||
}
|
record-change {
|
||||||
|
table-name = "recordChangeTest"
|
||||||
dynamo {
|
provisioned-reads = 30
|
||||||
key="dynamoKey"
|
provisioned-writes = 20
|
||||||
secret="dynamoSecret"
|
|
||||||
endpoint="dynamoEndpoint"
|
|
||||||
}
|
|
||||||
|
|
||||||
zoneChanges {
|
|
||||||
dynamo {
|
|
||||||
tableName = "zoneChanges"
|
|
||||||
provisionedReads=40
|
|
||||||
provisionedWrites=30
|
|
||||||
}
|
}
|
||||||
}
|
zone-change {
|
||||||
|
table-name = "zoneChangesTest"
|
||||||
recordSet {
|
provisioned-reads = 30
|
||||||
dynamo {
|
provisioned-writes = 20
|
||||||
tableName = "recordSet"
|
|
||||||
provisionedReads=40
|
|
||||||
provisionedWrites=30
|
|
||||||
}
|
}
|
||||||
}
|
user {
|
||||||
|
table-name = "usersTest"
|
||||||
recordChange {
|
provisioned-reads = 30
|
||||||
dynamo {
|
provisioned-writes = 20
|
||||||
tableName = "recordChange"
|
|
||||||
provisionedReads=40
|
|
||||||
provisionedWrites=30
|
|
||||||
}
|
}
|
||||||
}
|
group {
|
||||||
|
table-name = "groupsTest"
|
||||||
groups {
|
provisioned-reads = 30
|
||||||
dynamo {
|
provisioned-writes = 20
|
||||||
tableName = "groups"
|
|
||||||
provisionedReads=40
|
|
||||||
provisionedWrites=30
|
|
||||||
}
|
}
|
||||||
}
|
group-change {
|
||||||
|
table-name = "groupChangesTest"
|
||||||
groupChanges {
|
provisioned-reads = 30
|
||||||
dynamo {
|
provisioned-writes = 20
|
||||||
tableName = "groupChanges"
|
|
||||||
provisionedReads=40
|
|
||||||
provisionedWrites=30
|
|
||||||
}
|
}
|
||||||
}
|
membership {
|
||||||
|
table-name = "membershipTest"
|
||||||
membership {
|
provisioned-reads = 30
|
||||||
dynamo {
|
provisioned-writes = 20
|
||||||
tableName = "membership"
|
|
||||||
provisionedReads=40
|
|
||||||
provisionedWrites=30
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package vinyldns.api
|
package vinyldns.api
|
||||||
|
|
||||||
import org.scalatest.{Matchers, WordSpec}
|
import org.scalatest.{Matchers, WordSpec}
|
||||||
|
import vinyldns.core.repository.RepositoryName._
|
||||||
|
|
||||||
class VinylDNSConfigSpec extends WordSpec with Matchers {
|
class VinylDNSConfigSpec extends WordSpec with Matchers {
|
||||||
|
|
||||||
@ -26,46 +27,26 @@ class VinylDNSConfigSpec extends WordSpec with Matchers {
|
|||||||
restConfig.getInt("port") shouldBe 9000
|
restConfig.getInt("port") shouldBe 9000
|
||||||
}
|
}
|
||||||
|
|
||||||
"load the dynamo config" in {
|
"properly load the datastore configs" in {
|
||||||
val dynamoConfig = VinylDNSConfig.dynamoConfig
|
|
||||||
dynamoConfig.key shouldBe "dynamoKey"
|
|
||||||
dynamoConfig.secret shouldBe "dynamoSecret"
|
|
||||||
dynamoConfig.endpoint shouldBe "dynamoEndpoint"
|
|
||||||
}
|
|
||||||
|
|
||||||
"load the zone change repository config" in {
|
VinylDNSConfig.dataStoreConfigs.unsafeRunSync.length shouldBe 2
|
||||||
val config = VinylDNSConfig.zoneChangeStoreConfig
|
|
||||||
config.tableName shouldBe "zoneChanges"
|
|
||||||
config.provisionedReads shouldBe 40
|
|
||||||
config.provisionedWrites shouldBe 30
|
|
||||||
}
|
}
|
||||||
|
"assign the correct mysql repositories" in {
|
||||||
|
val mysqlConfig =
|
||||||
|
VinylDNSConfig.dataStoreConfigs.unsafeRunSync
|
||||||
|
.find(_.className == "vinyldns.api.repository.mysql.MySqlDataStoreProvider")
|
||||||
|
.get
|
||||||
|
|
||||||
"load the record change repository config" in {
|
mysqlConfig.repositories.keys should contain theSameElementsAs Set(zone, batchChange)
|
||||||
val config = VinylDNSConfig.recordChangeStoreConfig
|
|
||||||
config.tableName shouldBe "recordChange"
|
|
||||||
config.provisionedReads shouldBe 40
|
|
||||||
config.provisionedWrites shouldBe 30
|
|
||||||
}
|
}
|
||||||
|
"assign the correct dynamodb repositories" in {
|
||||||
|
val dynamodbConfig =
|
||||||
|
VinylDNSConfig.dataStoreConfigs.unsafeRunSync
|
||||||
|
.find(_.className == "vinyldns.dynamodb.repository.DynamoDBDataStoreProvider")
|
||||||
|
.get
|
||||||
|
|
||||||
"load the membership repository config" in {
|
dynamodbConfig.repositories.keys should contain theSameElementsAs
|
||||||
val config = VinylDNSConfig.membershipStoreConfig
|
Set(user, group, membership, groupChange, recordSet, recordChange, zoneChange)
|
||||||
config.tableName shouldBe "membership"
|
|
||||||
config.provisionedReads shouldBe 40
|
|
||||||
config.provisionedWrites shouldBe 30
|
|
||||||
}
|
|
||||||
|
|
||||||
"load the record set repository config" in {
|
|
||||||
val config = VinylDNSConfig.recordSetStoreConfig
|
|
||||||
config.tableName shouldBe "recordSet"
|
|
||||||
config.provisionedReads shouldBe 40
|
|
||||||
config.provisionedWrites shouldBe 30
|
|
||||||
}
|
|
||||||
|
|
||||||
"load the group repository config" in {
|
|
||||||
val config = VinylDNSConfig.groupsStoreConfig
|
|
||||||
config.tableName shouldBe "groups"
|
|
||||||
config.provisionedReads shouldBe 40
|
|
||||||
config.provisionedWrites shouldBe 30
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,7 @@ class BatchChangeRoutingSpec
|
|||||||
with GroupTestData {
|
with GroupTestData {
|
||||||
|
|
||||||
val batchChangeService: BatchChangeServiceAlgebra = TestBatchChangeService
|
val batchChangeService: BatchChangeServiceAlgebra = TestBatchChangeService
|
||||||
|
val vinylDNSAuthenticator: VinylDNSAuthenticator = new TestVinylDNSAuthenticator(okUserAuth)
|
||||||
|
|
||||||
import vinyldns.core.domain.batch.SingleChangeStatus._
|
import vinyldns.core.domain.batch.SingleChangeStatus._
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@ import org.mockito.Mockito.doReturn
|
|||||||
import org.scalatest.mockito.MockitoSugar
|
import org.scalatest.mockito.MockitoSugar
|
||||||
import org.scalatest.{Matchers, OneInstancePerTest, WordSpec}
|
import org.scalatest.{Matchers, OneInstancePerTest, WordSpec}
|
||||||
import vinyldns.core.domain.zone.ZoneRepository
|
import vinyldns.core.domain.zone.ZoneRepository
|
||||||
|
|
||||||
import cats.effect._
|
import cats.effect._
|
||||||
|
|
||||||
class HealthCheckRoutingSpec
|
class HealthCheckRoutingSpec
|
||||||
@ -34,7 +33,6 @@ class HealthCheckRoutingSpec
|
|||||||
with Directives
|
with Directives
|
||||||
with HealthCheckRoute
|
with HealthCheckRoute
|
||||||
with VinylDNSJsonProtocol
|
with VinylDNSJsonProtocol
|
||||||
with VinylDNSDirectives
|
|
||||||
with OneInstancePerTest
|
with OneInstancePerTest
|
||||||
with Matchers
|
with Matchers
|
||||||
with MockitoSugar {
|
with MockitoSugar {
|
||||||
|
@ -51,6 +51,7 @@ class MembershipRoutingSpec
|
|||||||
with BeforeAndAfterEach {
|
with BeforeAndAfterEach {
|
||||||
|
|
||||||
val membershipService: MembershipService = mock[MembershipService]
|
val membershipService: MembershipService = mock[MembershipService]
|
||||||
|
val vinylDNSAuthenticator: VinylDNSAuthenticator = new TestVinylDNSAuthenticator(okAuth)
|
||||||
|
|
||||||
override protected def beforeEach(): Unit = reset(membershipService)
|
override protected def beforeEach(): Unit = reset(membershipService)
|
||||||
|
|
||||||
|
@ -17,9 +17,8 @@
|
|||||||
package vinyldns.api.route
|
package vinyldns.api.route
|
||||||
|
|
||||||
import akka.http.scaladsl.model.{ContentTypes, HttpEntity, HttpRequest, StatusCodes}
|
import akka.http.scaladsl.model.{ContentTypes, HttpEntity, HttpRequest, StatusCodes}
|
||||||
import akka.http.scaladsl.server.{Directives, RequestContext, Route}
|
import akka.http.scaladsl.server.{Directives, Route}
|
||||||
import akka.http.scaladsl.testkit.ScalatestRouteTest
|
import akka.http.scaladsl.testkit.ScalatestRouteTest
|
||||||
import cats.effect._
|
|
||||||
import org.joda.time.DateTime
|
import org.joda.time.DateTime
|
||||||
import org.json4s.JsonDSL._
|
import org.json4s.JsonDSL._
|
||||||
import org.json4s._
|
import org.json4s._
|
||||||
@ -482,10 +481,7 @@ class RecordSetRoutingSpec
|
|||||||
|
|
||||||
val recordSetService: RecordSetServiceAlgebra = new TestService
|
val recordSetService: RecordSetServiceAlgebra = new TestService
|
||||||
|
|
||||||
override def vinyldnsAuthenticator(
|
val vinylDNSAuthenticator = new TestVinylDNSAuthenticator(okAuth)
|
||||||
ctx: RequestContext,
|
|
||||||
content: String): IO[Either[VinylDNSAuthenticationError, AuthPrincipal]] =
|
|
||||||
IO.pure(Right(okAuth))
|
|
||||||
|
|
||||||
private def rsJson(recordSet: RecordSet): String =
|
private def rsJson(recordSet: RecordSet): String =
|
||||||
compact(render(Extraction.decompose(recordSet)))
|
compact(render(Extraction.decompose(recordSet)))
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 Comcast Cable Communications Management, LLC
|
||||||
|
*
|
||||||
|
* 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 vinyldns.api.route
|
||||||
|
|
||||||
|
import akka.http.scaladsl.server.RequestContext
|
||||||
|
import cats.effect.IO
|
||||||
|
import vinyldns.core.domain.auth.AuthPrincipal
|
||||||
|
|
||||||
|
class TestVinylDNSAuthenticator(authPrincipal: AuthPrincipal) extends VinylDNSAuthenticator {
|
||||||
|
|
||||||
|
def authenticate(
|
||||||
|
ctx: RequestContext,
|
||||||
|
content: String): IO[Either[VinylDNSAuthenticationError, AuthPrincipal]] =
|
||||||
|
IO.pure(Right(authPrincipal))
|
||||||
|
}
|
@ -24,7 +24,7 @@ import org.mockito.Mockito._
|
|||||||
import org.scalatest.mockito.MockitoSugar
|
import org.scalatest.mockito.MockitoSugar
|
||||||
import org.scalatest.{Matchers, WordSpec}
|
import org.scalatest.{Matchers, WordSpec}
|
||||||
import vinyldns.api.domain.auth.AuthPrincipalProvider
|
import vinyldns.api.domain.auth.AuthPrincipalProvider
|
||||||
import vinyldns.api.{GroupTestData}
|
import vinyldns.api.GroupTestData
|
||||||
import vinyldns.core.crypto.CryptoAlgebra
|
import vinyldns.core.crypto.CryptoAlgebra
|
||||||
|
|
||||||
class VinylDNSAuthenticatorSpec
|
class VinylDNSAuthenticatorSpec
|
||||||
@ -35,7 +35,8 @@ class VinylDNSAuthenticatorSpec
|
|||||||
private val mockAuthenticator = mock[Aws4Authenticator]
|
private val mockAuthenticator = mock[Aws4Authenticator]
|
||||||
private val mockAuthPrincipalProvider = mock[AuthPrincipalProvider]
|
private val mockAuthPrincipalProvider = mock[AuthPrincipalProvider]
|
||||||
|
|
||||||
private val underTest = new VinylDNSAuthenticator(mockAuthenticator, mockAuthPrincipalProvider)
|
private val underTest =
|
||||||
|
new ProductionVinylDNSAuthenticator(mockAuthenticator, mockAuthPrincipalProvider)
|
||||||
|
|
||||||
"VinylDNSAuthenticator" should {
|
"VinylDNSAuthenticator" should {
|
||||||
"use Crypto" in {
|
"use Crypto" in {
|
||||||
@ -74,7 +75,7 @@ class VinylDNSAuthenticatorSpec
|
|||||||
.when(mockAuthenticator)
|
.when(mockAuthenticator)
|
||||||
.authenticateReq(any[HttpRequest], any[List[String]], any[String], any[String])
|
.authenticateReq(any[HttpRequest], any[List[String]], any[String], any[String])
|
||||||
|
|
||||||
val result = underTest.apply(context, "").unsafeRunSync()
|
val result = underTest.authenticate(context, "").unsafeRunSync()
|
||||||
result shouldBe Right(okUserAuth)
|
result shouldBe Right(okUserAuth)
|
||||||
}
|
}
|
||||||
"fail if missing Authorization header" in {
|
"fail if missing Authorization header" in {
|
||||||
@ -95,7 +96,7 @@ class VinylDNSAuthenticatorSpec
|
|||||||
.when(mockAuthenticator)
|
.when(mockAuthenticator)
|
||||||
.authenticateReq(any[HttpRequest], any[List[String]], any[String], any[String])
|
.authenticateReq(any[HttpRequest], any[List[String]], any[String], any[String])
|
||||||
|
|
||||||
val result = underTest.apply(context, "").unsafeRunSync()
|
val result = underTest.authenticate(context, "").unsafeRunSync()
|
||||||
result shouldBe Left(AuthMissing("Authorization header not found"))
|
result shouldBe Left(AuthMissing("Authorization header not found"))
|
||||||
}
|
}
|
||||||
"fail if Authorization header can not be parsed" in {
|
"fail if Authorization header can not be parsed" in {
|
||||||
@ -110,7 +111,7 @@ class VinylDNSAuthenticatorSpec
|
|||||||
val context: RequestContext = mock[RequestContext]
|
val context: RequestContext = mock[RequestContext]
|
||||||
doReturn(httpRequest).when(context).request
|
doReturn(httpRequest).when(context).request
|
||||||
|
|
||||||
val result = underTest.apply(context, "").unsafeRunSync()
|
val result = underTest.authenticate(context, "").unsafeRunSync()
|
||||||
result shouldBe Left(AuthRejected("Authorization header could not be parsed"))
|
result shouldBe Left(AuthRejected("Authorization header could not be parsed"))
|
||||||
}
|
}
|
||||||
"fail if the access key is missing" in {
|
"fail if the access key is missing" in {
|
||||||
@ -133,7 +134,7 @@ class VinylDNSAuthenticatorSpec
|
|||||||
.when(mockAuthenticator)
|
.when(mockAuthenticator)
|
||||||
.extractAccessKey(any[String])
|
.extractAccessKey(any[String])
|
||||||
|
|
||||||
val result = underTest.apply(context, "").unsafeRunSync()
|
val result = underTest.authenticate(context, "").unsafeRunSync()
|
||||||
result shouldBe Left(AuthMissing("accessKey not found"))
|
result shouldBe Left(AuthMissing("accessKey not found"))
|
||||||
}
|
}
|
||||||
"fail if the access key can not be retrieved" in {
|
"fail if the access key can not be retrieved" in {
|
||||||
@ -156,7 +157,7 @@ class VinylDNSAuthenticatorSpec
|
|||||||
.when(mockAuthenticator)
|
.when(mockAuthenticator)
|
||||||
.extractAccessKey(any[String])
|
.extractAccessKey(any[String])
|
||||||
|
|
||||||
val result = underTest.apply(context, "").unsafeRunSync()
|
val result = underTest.authenticate(context, "").unsafeRunSync()
|
||||||
result shouldBe Left(AuthRejected("Invalid authorization header"))
|
result shouldBe Left(AuthRejected("Invalid authorization header"))
|
||||||
}
|
}
|
||||||
"fail if the user is locked" in {
|
"fail if the user is locked" in {
|
||||||
@ -182,7 +183,7 @@ class VinylDNSAuthenticatorSpec
|
|||||||
.when(mockAuthPrincipalProvider)
|
.when(mockAuthPrincipalProvider)
|
||||||
.getAuthPrincipal(any[String])
|
.getAuthPrincipal(any[String])
|
||||||
|
|
||||||
val result = underTest.apply(context, "").unsafeRunSync()
|
val result = underTest.authenticate(context, "").unsafeRunSync()
|
||||||
result shouldBe Left(AccountLocked("Account with username locked is locked"))
|
result shouldBe Left(AccountLocked("Account with username locked is locked"))
|
||||||
}
|
}
|
||||||
"fail if the user can not be found" in {
|
"fail if the user can not be found" in {
|
||||||
@ -209,7 +210,7 @@ class VinylDNSAuthenticatorSpec
|
|||||||
.when(mockAuthPrincipalProvider)
|
.when(mockAuthPrincipalProvider)
|
||||||
.getAuthPrincipal(any[String])
|
.getAuthPrincipal(any[String])
|
||||||
|
|
||||||
val result = underTest.apply(context, "").unsafeRunSync()
|
val result = underTest.authenticate(context, "").unsafeRunSync()
|
||||||
result shouldBe Left(AuthRejected("Account with accessKey fakeKey specified was not found"))
|
result shouldBe Left(AuthRejected("Account with accessKey fakeKey specified was not found"))
|
||||||
}
|
}
|
||||||
"fail if signatures can not be validated" in {
|
"fail if signatures can not be validated" in {
|
||||||
@ -240,7 +241,7 @@ class VinylDNSAuthenticatorSpec
|
|||||||
.when(mockAuthenticator)
|
.when(mockAuthenticator)
|
||||||
.authenticateReq(any[HttpRequest], any[List[String]], any[String], any[String])
|
.authenticateReq(any[HttpRequest], any[List[String]], any[String], any[String])
|
||||||
|
|
||||||
val result = underTest.apply(context, "").unsafeRunSync()
|
val result = underTest.authenticate(context, "").unsafeRunSync()
|
||||||
result shouldBe Left(AuthRejected("Request signature could not be validated"))
|
result shouldBe Left(AuthRejected("Request signature could not be validated"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ import org.mockito.Matchers._
|
|||||||
import org.mockito.Mockito._
|
import org.mockito.Mockito._
|
||||||
import org.scalatest.mockito.MockitoSugar
|
import org.scalatest.mockito.MockitoSugar
|
||||||
import org.scalatest.{BeforeAndAfterEach, Matchers, OneInstancePerTest, WordSpec}
|
import org.scalatest.{BeforeAndAfterEach, Matchers, OneInstancePerTest, WordSpec}
|
||||||
|
import vinyldns.core.domain.auth.AuthPrincipal
|
||||||
import vinyldns.core.route.Monitor
|
import vinyldns.core.route.Monitor
|
||||||
|
|
||||||
import scala.util.Failure
|
import scala.util.Failure
|
||||||
@ -43,6 +44,9 @@ class VinylDNSDirectivesSpec
|
|||||||
private val mockLatency = mock[Histogram]
|
private val mockLatency = mock[Histogram]
|
||||||
private val mockErrors = mock[Meter]
|
private val mockErrors = mock[Meter]
|
||||||
|
|
||||||
|
val vinylDNSAuthenticator: VinylDNSAuthenticator = new TestVinylDNSAuthenticator(
|
||||||
|
mock[AuthPrincipal])
|
||||||
|
|
||||||
class TestMonitor extends Monitor("test") {
|
class TestMonitor extends Monitor("test") {
|
||||||
override val latency: Histogram = mockLatency
|
override val latency: Histogram = mockLatency
|
||||||
override val errors: Meter = mockErrors
|
override val errors: Meter = mockErrors
|
||||||
|
@ -22,6 +22,7 @@ import akka.event.Logging._
|
|||||||
import akka.http.scaladsl.model.headers.RawHeader
|
import akka.http.scaladsl.model.headers.RawHeader
|
||||||
import akka.http.scaladsl.model._
|
import akka.http.scaladsl.model._
|
||||||
import akka.http.scaladsl.server.directives.LogEntry
|
import akka.http.scaladsl.server.directives.LogEntry
|
||||||
|
import vinyldns.core.domain.auth.AuthPrincipal
|
||||||
|
|
||||||
class VinylDNSServiceSpec
|
class VinylDNSServiceSpec
|
||||||
extends WordSpec
|
extends WordSpec
|
||||||
@ -30,6 +31,9 @@ class VinylDNSServiceSpec
|
|||||||
with OneInstancePerTest
|
with OneInstancePerTest
|
||||||
with VinylDNSDirectives {
|
with VinylDNSDirectives {
|
||||||
|
|
||||||
|
val vinylDNSAuthenticator: VinylDNSAuthenticator = new TestVinylDNSAuthenticator(
|
||||||
|
mock[AuthPrincipal])
|
||||||
|
|
||||||
private def buildMockRequest(
|
private def buildMockRequest(
|
||||||
path: String = "/path/to/resource",
|
path: String = "/path/to/resource",
|
||||||
body: String = "request body") = {
|
body: String = "request body") = {
|
||||||
|
@ -16,12 +16,10 @@
|
|||||||
|
|
||||||
package vinyldns.api.route
|
package vinyldns.api.route
|
||||||
|
|
||||||
import akka.actor.ActorSystem
|
|
||||||
import akka.http.scaladsl.model.StatusCodes._
|
import akka.http.scaladsl.model.StatusCodes._
|
||||||
import akka.http.scaladsl.model.{ContentTypes, HttpEntity, HttpRequest}
|
import akka.http.scaladsl.model.{ContentTypes, HttpEntity, HttpRequest}
|
||||||
import akka.http.scaladsl.server.{Directives, RequestContext, Route}
|
import akka.http.scaladsl.server.{Directives, Route}
|
||||||
import akka.http.scaladsl.testkit.ScalatestRouteTest
|
import akka.http.scaladsl.testkit.ScalatestRouteTest
|
||||||
import cats.effect._
|
|
||||||
import org.json4s.JsonDSL._
|
import org.json4s.JsonDSL._
|
||||||
import org.json4s._
|
import org.json4s._
|
||||||
import org.json4s.jackson.JsonMethods._
|
import org.json4s.jackson.JsonMethods._
|
||||||
@ -46,8 +44,6 @@ class ZoneRoutingSpec
|
|||||||
with Matchers
|
with Matchers
|
||||||
with GroupTestData {
|
with GroupTestData {
|
||||||
|
|
||||||
def actorRefFactory: ActorSystem = system
|
|
||||||
|
|
||||||
private val okAuth = okGroupAuth
|
private val okAuth = okGroupAuth
|
||||||
private val alreadyExists = Zone("already.exists.", "test@test.com")
|
private val alreadyExists = Zone("already.exists.", "test@test.com")
|
||||||
private val notFound = Zone("not.found.", "test@test.com")
|
private val notFound = Zone("not.found.", "test@test.com")
|
||||||
@ -329,10 +325,7 @@ class ZoneRoutingSpec
|
|||||||
|
|
||||||
val zoneService: ZoneServiceAlgebra = TestZoneService
|
val zoneService: ZoneServiceAlgebra = TestZoneService
|
||||||
|
|
||||||
override def vinyldnsAuthenticator(
|
val vinylDNSAuthenticator = new TestVinylDNSAuthenticator(okAuth)
|
||||||
ctx: RequestContext,
|
|
||||||
content: String): IO[Either[VinylDNSAuthenticationError, AuthPrincipal]] =
|
|
||||||
IO.pure(Right(okAuth))
|
|
||||||
|
|
||||||
def zoneJson(name: String, email: String): String =
|
def zoneJson(name: String, email: String): String =
|
||||||
zoneJson(Zone(name, email, connection = null, created = null, status = null, id = null))
|
zoneJson(Zone(name, email, connection = null, created = null, status = null, id = null))
|
||||||
|
@ -28,6 +28,8 @@ vinyldns {
|
|||||||
type = "vinyldns.core.crypto.NoOpCrypto"
|
type = "vinyldns.core.crypto.NoOpCrypto"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data-stores = ["mysql", "dynamodb"]
|
||||||
|
|
||||||
# default settings point to the setup from docker compose
|
# default settings point to the setup from docker compose
|
||||||
mysql {
|
mysql {
|
||||||
settings {
|
settings {
|
||||||
@ -52,67 +54,50 @@ vinyldns {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# dynamodb settings, for local docker compose the secrets are not needed
|
dynamodb {
|
||||||
dynamo {
|
# dynamodb settings, for local docker compose the secrets are not needed
|
||||||
key = "x"
|
settings {
|
||||||
secret = "x"
|
key = "x"
|
||||||
endpoint = "http://vinyldns-dynamodb:8000"
|
secret = "x"
|
||||||
}
|
endpoint = "http://vinyldns-dynamodb:8000"
|
||||||
|
|
||||||
# dynamodb table settings follow
|
|
||||||
zoneChanges {
|
|
||||||
dynamo {
|
|
||||||
tableName = "zoneChange"
|
|
||||||
provisionedReads = 30
|
|
||||||
provisionedWrites = 30
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
recordSet {
|
repositories {
|
||||||
dynamo {
|
record-set {
|
||||||
tableName = "recordSet"
|
table-name = "recordSet"
|
||||||
provisionedReads = 30
|
provisioned-reads = 30
|
||||||
provisionedWrites = 30
|
provisioned-writes = 30
|
||||||
}
|
}
|
||||||
}
|
record-change {
|
||||||
|
table-name = "recordChange"
|
||||||
recordChange {
|
provisioned-reads = 30
|
||||||
dynamo {
|
provisioned-writes = 30
|
||||||
tableName = "recordChange"
|
}
|
||||||
provisionedReads = 30
|
zone-change {
|
||||||
provisionedWrites = 30
|
table-name = "zoneChange"
|
||||||
}
|
provisioned-reads = 30
|
||||||
}
|
provisioned-writes = 30
|
||||||
|
}
|
||||||
users {
|
user {
|
||||||
dynamo {
|
table-name = "users"
|
||||||
tableName = "users"
|
provisioned-reads = 30
|
||||||
provisionedReads = 30
|
provisioned-writes = 30
|
||||||
provisionedWrites = 30
|
}
|
||||||
}
|
group {
|
||||||
}
|
table-name = "groups"
|
||||||
|
provisioned-reads = 30
|
||||||
groups {
|
provisioned-writes = 30
|
||||||
dynamo {
|
}
|
||||||
tableName = "groups"
|
group-change {
|
||||||
provisionedReads = 30
|
table-name = "groupChanges"
|
||||||
provisionedWrites = 30
|
provisioned-reads = 30
|
||||||
}
|
provisioned-writes = 30
|
||||||
}
|
}
|
||||||
|
membership {
|
||||||
groupChanges {
|
table-name = "membership"
|
||||||
dynamo {
|
provisioned-reads = 30
|
||||||
tableName = "groupChanges"
|
provisioned-writes = 30
|
||||||
provisionedReads = 30
|
}
|
||||||
provisionedWrites = 30
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
membership {
|
|
||||||
dynamo {
|
|
||||||
tableName = "membership"
|
|
||||||
provisionedReads = 30
|
|
||||||
provisionedWrites = 30
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,27 +20,33 @@ import cats.data._
|
|||||||
import cats.effect.IO
|
import cats.effect.IO
|
||||||
import cats.implicits._
|
import cats.implicits._
|
||||||
import vinyldns.core.crypto.CryptoAlgebra
|
import vinyldns.core.crypto.CryptoAlgebra
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
import vinyldns.core.repository.RepositoryName._
|
import vinyldns.core.repository.RepositoryName._
|
||||||
|
|
||||||
import scala.reflect.ClassTag
|
import scala.reflect.ClassTag
|
||||||
|
|
||||||
object DataStoreLoader {
|
object DataStoreLoader {
|
||||||
|
|
||||||
|
private val logger = LoggerFactory.getLogger("DataStoreLoader")
|
||||||
|
|
||||||
def loadAll[A <: DataAccessor](
|
def loadAll[A <: DataAccessor](
|
||||||
configs: List[DataStoreConfig],
|
configs: List[DataStoreConfig],
|
||||||
crypto: CryptoAlgebra,
|
crypto: CryptoAlgebra,
|
||||||
dataAccessorProvider: DataAccessorProvider[A]): IO[DataAccessor] =
|
dataAccessorProvider: DataAccessorProvider[A]): IO[A] =
|
||||||
for {
|
for {
|
||||||
activeConfigs <- IO.fromEither(getValidatedConfigs(configs, dataAccessorProvider.repoNames))
|
activeConfigs <- IO.fromEither(getValidatedConfigs(configs, dataAccessorProvider.repoNames))
|
||||||
dataStores <- activeConfigs.map(load(_, crypto)).parSequence
|
dataStores <- activeConfigs.map(load(_, crypto)).parSequence
|
||||||
accessor <- IO.fromEither(generateAccessor(dataStores, dataAccessorProvider))
|
accessor <- IO.fromEither(generateAccessor(dataStores, dataAccessorProvider))
|
||||||
} yield accessor
|
} yield accessor
|
||||||
|
|
||||||
def load(config: DataStoreConfig, crypto: CryptoAlgebra): IO[(DataStoreConfig, DataStore)] =
|
def load(config: DataStoreConfig, crypto: CryptoAlgebra): IO[(DataStoreConfig, DataStore)] = {
|
||||||
|
logger.error(s"Attempting to load repos ${config.repositories.keys} from ${config.className}")
|
||||||
for {
|
for {
|
||||||
className <- IO.pure(config.className)
|
className <- IO.pure(config.className)
|
||||||
provider <- IO(Class.forName(className).newInstance.asInstanceOf[DataStoreProvider])
|
provider <- IO(Class.forName(className).newInstance.asInstanceOf[DataStoreProvider])
|
||||||
dataStore <- provider.load(config, crypto)
|
dataStore <- provider.load(config, crypto)
|
||||||
} yield (config, dataStore)
|
} yield (config, dataStore)
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Validates that there's exactly one repo defined across all datastore configs. Returns only
|
* Validates that there's exactly one repo defined across all datastore configs. Returns only
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package vinyldns.dynamodb.repository
|
package vinyldns.dynamodb.repository
|
||||||
|
|
||||||
|
import cats.effect.IO
|
||||||
import cats.implicits._
|
import cats.implicits._
|
||||||
import com.amazonaws.services.dynamodbv2.model.DeleteTableRequest
|
import com.amazonaws.services.dynamodbv2.model.DeleteTableRequest
|
||||||
import com.typesafe.config.{Config, ConfigFactory}
|
import com.typesafe.config.{Config, ConfigFactory}
|
||||||
@ -77,10 +78,10 @@ class DynamoDBDataStoreProviderIntegrationSpec extends DynamoDBIntegrationSpec {
|
|||||||
)
|
)
|
||||||
val userRepo = dataStore.get[UserRepository](user)
|
val userRepo = dataStore.get[UserRepository](user)
|
||||||
|
|
||||||
val save = userRepo.map(_.save(testUser)).parSequence
|
val save = userRepo.map(_.save(testUser)).sequence[IO, User]
|
||||||
save.unsafeRunSync() shouldBe Some(testUser)
|
save.unsafeRunSync() shouldBe Some(testUser)
|
||||||
|
|
||||||
val get = userRepo.map(_.getUser(testUser.id)).parSequence
|
val get = userRepo.map(_.getUser(testUser.id)).sequence[IO, Option[User]]
|
||||||
get.unsafeRunSync().flatten shouldBe Some(testUser)
|
get.unsafeRunSync().flatten shouldBe Some(testUser)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,10 +74,17 @@ class DynamoDBDataStoreProvider extends DataStoreProvider {
|
|||||||
|
|
||||||
def initializeSingleRepo[T <: Repository](
|
def initializeSingleRepo[T <: Repository](
|
||||||
repoName: RepositoryName,
|
repoName: RepositoryName,
|
||||||
fn: DynamoDBRepositorySettings => IO[T]): IO[Option[T]] = {
|
fn: DynamoDBRepositorySettings => IO[T]): IO[Option[T]] =
|
||||||
logger.info(s"Loading dynamodb repo for type: $repoName")
|
repoSettings
|
||||||
repoSettings.get(repoName).map(fn(_)).parSequence
|
.get(repoName)
|
||||||
}
|
.map { configuredOn =>
|
||||||
|
for {
|
||||||
|
_ <- IO(logger.error(s"Loading dynamodb repo for type: $repoName"))
|
||||||
|
repo <- fn(configuredOn)
|
||||||
|
_ <- IO(logger.error(s"Completed dynamodb load for type: $repoName"))
|
||||||
|
} yield repo
|
||||||
|
}
|
||||||
|
.sequence
|
||||||
|
|
||||||
(
|
(
|
||||||
initializeSingleRepo[UserRepository](
|
initializeSingleRepo[UserRepository](
|
||||||
|
@ -1 +1 @@
|
|||||||
sbt.version=1.1.4
|
sbt.version=1.1.6
|
||||||
|
Loading…
x
Reference in New Issue
Block a user