Skip to content

Commit

Permalink
Merge pull request #214 from snowplow/feature/embedded-list
Browse files Browse the repository at this point in the history
Add list-schemas for the embedded repo (close #212)
  • Loading branch information
voropaevp committed Nov 21, 2022
2 parents 3576baf + 3ecc8b8 commit 3ea1755
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,13 @@ object RegistryLookup {
implicit class LookupOps(val repositoryRef: Registry) extends AnyVal with Serializable {
def lookupSchema[F[_]: RegistryLookup](schemaKey: SchemaKey): F[Either[RegistryError, Json]] =
RegistryLookup[F].lookup(repositoryRef, schemaKey)

def list[F[_]: RegistryLookup](
vendor: String,
name: String,
model: Int
): F[Either[RegistryError, SchemaList]] =
RegistryLookup[F].list(repositoryRef, vendor: String, name: String, model: Int)
}

implicit def ioLookupInstance[F[_]](implicit F: Sync[F]): RegistryLookup[F] =
Expand All @@ -98,7 +105,10 @@ object RegistryLookup {
): F[Either[RegistryError, SchemaList]] =
registry match {
case Registry.Http(_, connection) => httpList(connection, vendor, name, model)
case _ => F.pure(RegistryError.NotFound.asLeft)
case Registry.Embedded(_, base) =>
val path = toSubpath(base, vendor, name)
Sync[F].delay(Utils.unsafeEmbeddedList(path, model))
case _ => F.pure(RegistryError.NotFound.asLeft)
}
}

Expand Down Expand Up @@ -128,6 +138,9 @@ object RegistryLookup {
case Registry.Http(_, connection) =>
val subpath = toSubpath(connection.uri.toString, vendor, name, model)
Utils.stringToUri(subpath).flatMap(Utils.unsafeHttpList(_, connection.apikey))
case Registry.Embedded(_, base) =>
val path = toSubpath(base, vendor, name)
Utils.unsafeEmbeddedList(path, model)
case _ =>
RegistryError.NotFound.asLeft
}
Expand All @@ -151,6 +164,13 @@ object RegistryLookup {
): String =
s"${prefix.stripSuffix("/")}/schemas/$vendor/$name/jsonschema/$model"

private def toSubpath(
prefix: String,
vendor: String,
name: String
): String =
s"${prefix.stripSuffix("/")}/schemas/$vendor/$name/jsonschema"

/**
* Retrieves an Iglu Schema from the Embedded Iglu Repo as a JSON
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@ package com.snowplowanalytics.iglu.client
package resolver.registries

// Java
import java.io.InputStream
import com.snowplowanalytics.iglu.core.{SchemaKey, SchemaVer}

import java.io.{File, InputStream}
import java.net.URI
import java.net.http.HttpResponse.BodyHandlers
import java.net.http.{HttpClient, HttpRequest, HttpResponse}
import java.time.Duration
import scala.util.matching.Regex

// Scala
import scala.io.Source
Expand All @@ -29,6 +32,7 @@ import cats.effect.Sync
import cats.syntax.either._
import cats.syntax.option._
import cats.syntax.show._
import cats.syntax.traverse._

// circe
import io.circe.parser.parse
Expand Down Expand Up @@ -72,6 +76,61 @@ private[registries] object Utils {
repoFailure(e).asLeft
}

def unsafeEmbeddedList(path: String, modelMatch: Int): Either[RegistryError, SchemaList] =
try {
val d =
new File(
getClass.getResource(path).getPath
) // this will throw NPE for missing entry in embedded repos
val schemaFileRegex: Regex = (".*/schemas/?" + // path to file
"([a-zA-Z0-9-_.]+)/" + // Vendor
"([a-zA-Z0-9-_]+)/" + // Name
"([a-zA-Z0-9-_]+)/" + // Format
"([1-9][0-9]*)-(\\d+)-(\\d+)$").r // MODEL, REVISION and ADDITION

def getFolderContent(d: File): List[String] = {
d.listFiles
.filter(_.isFile)
.toList
.filter(_.getName.startsWith(s"${modelMatch.toString}-"))
.map(_.getAbsolutePath)
}

val content =
if (d.exists & d.isDirectory)
getFolderContent(d)
else
List.empty[String]

content
.traverse {
case schemaFileRegex(vendor, name, format, model, revision, addition)
if model == modelMatch.toString =>
SchemaKey(
vendor = vendor,
name = name,
format = format,
version = SchemaVer
.Full(model = model.toInt, revision = revision.toInt, addition = addition.toInt)
).asRight
case f => RegistryError.RepoFailure(s"Corrupted schema file name at $f").asLeft
}
.map(_.sortBy(_.version))
.flatMap(s =>
if (s.isEmpty)
RegistryError.NotFound.asLeft
else
s.asRight
)
.map(SchemaList.apply)
} catch {
case NonFatal(e) =>
e match {
case _: NullPointerException => RegistryError.NotFound.asLeft
case _ => repoFailure(e).asLeft
}
}

/** Not-RT analog of [[RegistryLookup.embeddedLookup]] */
def unsafeEmbeddedLookup(path: String): Either[RegistryError, Json] =
try {
Expand All @@ -84,7 +143,10 @@ private[registries] object Utils {
result
} catch {
case NonFatal(e) =>
repoFailure(e).asLeft
e match {
case _: NullPointerException => RegistryError.NotFound.asLeft
case _ => repoFailure(e).asLeft
}
}

/** Non-RT analog of [[RegistryLookup.httpList]] */
Expand Down Expand Up @@ -156,6 +218,7 @@ private[registries] object Utils {
RegistryError.RepoFailure(failure.show)

private[resolver] def repoFailure(failure: Throwable): RegistryError =
RegistryError.RepoFailure(failure.getMessage)

RegistryError.RepoFailure(
if (failure.getMessage != null) failure.getMessage else "Unhandled error"
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ package com.snowplowanalytics.iglu.client.resolver.registries
// Cats
import cats.effect.IO
import cats.effect.testing.specs2.CatsEffect
import com.snowplowanalytics.iglu.core.SchemaList

// circe
import io.circe.literal._
Expand All @@ -38,6 +39,7 @@ class EmbeddedSpec extends Specification with CatsEffect {
retrieving an existent JSON Schema from an embedded RepositoryRef should work $e3
requesting a non-existent JSON Schema from an embedded RepositoryRef should return None $e4
requesting a corrupted JSON Schema from an embedded RepositoryRef should return an appropriate Failure $e5
Schema list should work for embedded repo $e6
"""

val AcmeConfig =
Expand Down Expand Up @@ -119,4 +121,37 @@ class EmbeddedSpec extends Specification with CatsEffect {
.map(result => result must beLeft)
}

def e6 = {
val schemaList = SchemaList(
List(
SchemaKey(
"com.snowplowanalytics.iglu-test",
"test-embedded-list",
"jsonschema",
SchemaVer.Full(1, 0, 0)
),
SchemaKey(
"com.snowplowanalytics.iglu-test",
"test-embedded-list",
"jsonschema",
SchemaVer.Full(1, 0, 1)
),
SchemaKey(
"com.snowplowanalytics.iglu-test",
"test-embedded-list",
"jsonschema",
SchemaVer.Full(1, 2, 0)
),
SchemaKey(
"com.snowplowanalytics.iglu-test",
"test-embedded-list",
"jsonschema",
SchemaVer.Full(1, 2, 11)
)
)
)
SpecHelpers.EmbeddedTest
.list[IO]("com.snowplowanalytics.iglu-test", "test-embedded-list", 1)
.map(result => result must beRight(schemaList))
}
}

0 comments on commit 3ea1755

Please sign in to comment.