Skip to content

Commit c4a33c8

Browse files
Merge branch 'feat/OTA-5412/list-of-all-repos' into 'master'
OTA-5412 Add endpoint for load list of all repos and namespaces (for internal using only) Closes OTA-5412 See merge request olp/edge/ota/connect/back-end/ota-tuf!315
2 parents 29f5922 + 4bb4241 commit c4a33c8

File tree

5 files changed

+40
-10
lines changed

5 files changed

+40
-10
lines changed

reposerver/src/main/scala/com/advancedtelematic/tuf/reposerver/data/RepositoryDataType.scala

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package com.advancedtelematic.tuf.reposerver.data
22

33
import akka.http.scaladsl.model.Uri
4-
import com.advancedtelematic.libats.data.DataType.Checksum
4+
import com.advancedtelematic.libats.data.DataType.{Checksum, Namespace}
55
import com.advancedtelematic.libtuf.data.ClientDataType._
66
import com.advancedtelematic.libtuf.data.TufDataType.{RepoId, TargetFilename}
77

@@ -16,4 +16,15 @@ object RepositoryDataType {
1616
import StorageMethod._
1717

1818
case class TargetItem(repoId: RepoId, filename: TargetFilename, uri: Option[Uri], checksum: Checksum, length: Long, custom: Option[TargetCustom] = None, storageMethod: StorageMethod = Managed)
19+
20+
case class RepoNamespace(repoId: RepoId, namespace: Namespace)
21+
22+
object RepoNamespace {
23+
import io.circe.Codec
24+
import io.circe.generic.semiauto._
25+
import com.advancedtelematic.libats.codecs.CirceCodecs._
26+
27+
implicit val repoNamespaceCodec: Codec[RepoNamespace] = deriveCodec[RepoNamespace]
28+
}
29+
1930
}

reposerver/src/main/scala/com/advancedtelematic/tuf/reposerver/db/Repository.scala

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
package com.advancedtelematic.tuf.reposerver.db
22

33
import java.time.Instant
4-
54
import scala.util.Success
65
import scala.util.Failure
76
import akka.NotUsed
87
import akka.http.scaladsl.model.StatusCodes
98
import akka.http.scaladsl.util.FastFuture
109
import akka.stream.scaladsl.Source
1110
import com.advancedtelematic.libats.data.DataType.Namespace
12-
import com.advancedtelematic.libats.data.ErrorCode
11+
import com.advancedtelematic.libats.data.{ErrorCode, PaginationResult}
1312
import com.advancedtelematic.libats.http.Errors.{EntityAlreadyExists, MissingEntity, MissingEntityId, RawError}
1413
import com.advancedtelematic.libtuf.data.TufDataType.{JsonSignedPayload, RepoId, RoleType, TargetFilename}
1514
import com.advancedtelematic.libtuf.data.TufDataType.RoleType.RoleType
@@ -225,7 +224,7 @@ protected[db] class RepoNamespaceRepository()(implicit db: Database, ec: Executi
225224
val AlreadyExists = EntityAlreadyExists[(RepoId, Namespace)]()
226225

227226
def persist(repoId: RepoId, namespace: Namespace): Future[Unit] = db.run {
228-
(repoNamespaces += (repoId, namespace)).handleIntegrityErrors(AlreadyExists)
227+
(repoNamespaces += RepoNamespace(repoId, namespace)).handleIntegrityErrors(AlreadyExists)
229228
}
230229

231230
def ensureNotExists(namespace: Namespace): Future[Unit] =
@@ -250,6 +249,10 @@ protected[db] class RepoNamespaceRepository()(implicit db: Database, ec: Executi
250249
.result
251250
.map(_ > 0)
252251
}
252+
253+
def list(offset: Long, limit: Long): Future[PaginationResult[RepoNamespace]] = db.run {
254+
repoNamespaces.paginateResult(offset, limit)
255+
}
253256
}
254257

255258
object FilenameCommentRepository {

reposerver/src/main/scala/com/advancedtelematic/tuf/reposerver/db/Schema.scala

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.advancedtelematic.tuf.reposerver.db
22

33
import java.time.Instant
4-
54
import akka.http.scaladsl.model.Uri
65
import com.advancedtelematic.libats.data.DataType.{Checksum, Namespace}
76
import com.advancedtelematic.libtuf.data.ClientDataType.{DelegatedRoleName, TargetCustom}
@@ -13,7 +12,7 @@ import com.advancedtelematic.libtuf_server.data.Requests.TargetComment
1312
import com.advancedtelematic.tuf.reposerver.db.DBDataType.{DbDelegation, DbSignedRole}
1413
import SlickValidatedString._
1514
import com.advancedtelematic.tuf.reposerver.data.RepositoryDataType.StorageMethod.StorageMethod
16-
import com.advancedtelematic.tuf.reposerver.data.RepositoryDataType.TargetItem
15+
import com.advancedtelematic.tuf.reposerver.data.RepositoryDataType.{RepoNamespace, TargetItem}
1716

1817
object Schema {
1918
import com.advancedtelematic.libats.slick.codecs.SlickRefined._
@@ -56,13 +55,13 @@ object Schema {
5655

5756
protected [db] val signedRoles = TableQuery[SignedRoleTable]
5857

59-
class RepoNamespaceTable(tag: Tag) extends Table[(RepoId, Namespace)](tag, "repo_namespaces") {
58+
class RepoNamespaceTable(tag: Tag) extends Table[RepoNamespace](tag, "repo_namespaces") {
6059
def repoId = column[RepoId]("repo_id")
6160
def namespace = column[Namespace]("namespace")
6261

6362
def pk = primaryKey("repo_namespaces_pk", namespace)
6463

65-
override def * = (repoId, namespace)
64+
override def * = (repoId, namespace) <> ((RepoNamespace.apply _).tupled, RepoNamespace.unapply)
6665
}
6766

6867
protected [db] val repoNamespaces = TableQuery[RepoNamespaceTable]

reposerver/src/main/scala/com/advancedtelematic/tuf/reposerver/http/RepoResource.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,5 +384,8 @@ class RepoResource(keyserverClient: KeyserverClient, namespaceValidation: Namesp
384384
createRepo(namespace, repoId)
385385
} ~
386386
modifyRepoRoutes(repoId)
387+
} ~
388+
(path("repos") & parameters('offset.as[Long], 'limit.as[Long]) ) { (offset, limit) =>
389+
complete(repoNamespaceRepo.list(offset, limit))
387390
}
388391
}

reposerver/src/test/scala/com/advancedtelematic/tuf/reposerver/http/RepoResourceSpec.scala

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package com.advancedtelematic.tuf.reposerver.http
22

33
import java.time.Instant
44
import java.time.temporal.ChronoUnit
5-
65
import akka.http.scaladsl.model.Multipart.FormData.BodyPart
76
import akka.http.scaladsl.model._
87
import akka.http.scaladsl.model.headers._
@@ -14,7 +13,7 @@ import cats.syntax.option._
1413
import cats.syntax.show._
1514
import com.advancedtelematic.libats.codecs.CirceCodecs._
1615
import com.advancedtelematic.libats.data.DataType.HashMethod
17-
import com.advancedtelematic.libats.data.ErrorRepresentation
16+
import com.advancedtelematic.libats.data.{ErrorRepresentation, PaginationResult}
1817
import com.advancedtelematic.libats.data.RefinedUtils.RefineTry
1918
import com.advancedtelematic.libats.http.Errors.RawError
2019
import com.advancedtelematic.libtuf.crypt.CanonicalJson._
@@ -28,6 +27,7 @@ import com.advancedtelematic.libtuf_server.crypto.Sha256Digest
2827
import com.advancedtelematic.libtuf_server.data.Requests._
2928
import com.advancedtelematic.libtuf_server.keyserver.KeyserverClient
3029
import com.advancedtelematic.libtuf_server.repo.server.DataType.SignedRole
30+
import com.advancedtelematic.tuf.reposerver.data.RepositoryDataType.RepoNamespace
3131
import com.advancedtelematic.tuf.reposerver.db.SignedRoleDbTestUtil._
3232
import com.advancedtelematic.tuf.reposerver.db.SignedRoleRepositorySupport
3333
import com.advancedtelematic.tuf.reposerver.target_store.TargetStoreEngine.{TargetBytes, TargetRetrieveResult}
@@ -1090,6 +1090,20 @@ class RepoResourceSpec extends TufReposerverSpec with RepoResourceSpecUtil
10901090
}
10911091
}
10921092

1093+
test("GET list of repo namespaces") {
1094+
withRandomNamepace { implicit ns =>
1095+
val newRepoId = Post(apiUri("user_repo"), CreateRepositoryRequest(KeyType.default)).namespaced ~> routes ~> check {
1096+
status shouldBe StatusCodes.OK
1097+
responseAs[RepoId]
1098+
}
1099+
1100+
Get(apiUri(s"repos?offset=0&limit=1000")) ~> routes ~> check {
1101+
responseAs[PaginationResult[RepoNamespace]].values.map(_.repoId) should contain(newRepoId)
1102+
status shouldBe StatusCodes.OK
1103+
}
1104+
}
1105+
}
1106+
10931107
implicit class ErrorRepresentationOps(value: ErrorRepresentation) {
10941108
def firstErrorCause: Option[String] =
10951109
value.cause.flatMap(_.as[NonEmptyList[String]].toOption).map(_.head)

0 commit comments

Comments
 (0)