Skip to content

Commit

Permalink
GH-458 Provide working directory to FS storage implementation and fix…
Browse files Browse the repository at this point in the history
… repository initialization. Bump CDN to 1.9.1 and cover deployment with its unit test
  • Loading branch information
dzikoysk committed Aug 3, 2021
1 parent 843e19e commit 9777031
Show file tree
Hide file tree
Showing 18 changed files with 116 additions and 32 deletions.
3 changes: 2 additions & 1 deletion reposilite-backend/reposilite-backend.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ dependencies {

/* Utilities */

implementation("net.dzikoysk:cdn:1.9.0")
implementation("net.dzikoysk:cdn:1.9.1")
implementation("org.panda-lang:expressible:1.0.2")
implementation("info.picocli:picocli:4.6.1")
implementation("com.google.guava:guava:30.1.1-jre")
Expand All @@ -114,6 +114,7 @@ dependencies {
testImplementation("com.google.http-client:google-http-client-jackson2:1.39.2")
testImplementation("org.mockito:mockito-inline:3.9.0")
testImplementation("org.mockito:mockito-core:3.9.0")
testImplementation("org.junit.jupiter:junit-jupiter-params:5.7.1")
testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.1")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ class Reposilite(
logger.info("")

logger.info("--- Repositories")
mavenFacade.getRepositories().forEach { logger.info("+ ${it.name} (${it.visibility.toString().toLowerCase()})") }
mavenFacade.getRepositories().forEach { logger.info("+ ${it.name} (${it.visibility.toString().lowercase()})") }
logger.info("${mavenFacade.getRepositories().size} repositories have been found")
logger.info("")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ object ReposiliteWebConfiguration {
val webServer = WebConfiguration.createWebServer()
val failureFacade = FailureWebConfiguration.createFacade(logger)
val consoleFacade = ConsoleWebConfiguration.createFacade(logger, failureFacade)
val mavenFacade = MavenWebConfiguration.createFacade(logger, failureFacade, configuration.repositories)
val mavenFacade = MavenWebConfiguration.createFacade(logger, failureFacade, workingDirectory, configuration.repositories)
val frontendFacade = FrontendWebConfiguration.createFacade(configuration)
val statisticFacade = StatisticsWebConfiguration.createFacade(logger)
val accessTokenFacade = AccessTokenWebConfiguration.createFacade(logger)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package org.panda_lang.reposilite.config

import net.dzikoysk.cdn.entity.Contextual
import net.dzikoysk.cdn.entity.Description
import org.panda_lang.reposilite.maven.api.RepositoryVisibility
import org.panda_lang.reposilite.maven.api.RepositoryVisibility.PRIVATE
import java.io.Serializable

Expand Down Expand Up @@ -107,15 +108,15 @@ class Configuration : Serializable {
var repositories: Map<String, RepositoryConfiguration> = mutableMapOf(
"releases" to RepositoryConfiguration(),
"snapshots" to RepositoryConfiguration(),
"private" to RepositoryConfiguration().also { it.visibility = PRIVATE.name.toLowerCase() }
"private" to RepositoryConfiguration().also { it.visibility = PRIVATE }
)

@Contextual
class RepositoryConfiguration : Serializable {

@Description("# Supported visibilities: public, hidden, private")
@JvmField
var visibility = "public"
var visibility = RepositoryVisibility.PUBLIC

@Description(
"# Used storage type. Supported storage providers:",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,6 @@ internal class ProxyService(
}

private fun store(uri: String, remoteResponse: HttpResponse, context: ReposiliteContext): Result<FileDetails, ErrorResponse> {
var uri = uri

if (storageProvider.isFull()) {
val error = "Not enough storage space available for $uri"
context.logger.warn(error)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@ package org.panda_lang.reposilite.maven
import net.dzikoysk.dynamiclogger.Journalist
import org.panda_lang.reposilite.config.Configuration.RepositoryConfiguration
import org.panda_lang.reposilite.maven.api.Repository
import org.panda_lang.reposilite.maven.api.RepositoryVisibility
import org.panda_lang.reposilite.storage.StorageProviderFactory
import java.nio.file.Path

internal object RepositoryFactory {

fun createRepository(journalist: Journalist, repositoryName: String, repositoryConfiguration: RepositoryConfiguration): Repository =
fun createRepository(journalist: Journalist, workingDirectory: Path, repositoryName: String, repositoryConfiguration: RepositoryConfiguration): Repository =
Repository(
repositoryName,
RepositoryVisibility.valueOf(repositoryConfiguration.visibility.toUpperCase()),
StorageProviderFactory.createStorageProvider(journalist, repositoryName, repositoryConfiguration.storageProvider),
repositoryConfiguration.visibility,
StorageProviderFactory.createStorageProvider(journalist, workingDirectory, repositoryName, repositoryConfiguration.storageProvider, repositoryConfiguration.diskQuota),
repositoryConfiguration.deployEnabled
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import net.dzikoysk.dynamiclogger.Journalist
import net.dzikoysk.dynamiclogger.Logger
import org.panda_lang.reposilite.config.Configuration.RepositoryConfiguration
import org.panda_lang.reposilite.maven.api.Repository
import java.nio.file.Path

internal class RepositoryService(
private val journalist: Journalist,
Expand All @@ -38,11 +39,11 @@ internal class RepositoryService(

internal object RepositoryServiceFactory {

fun createRepositoryService(journalist: Journalist, repositoriesConfigurations: Map<String, RepositoryConfiguration>): RepositoryService {
fun createRepositoryService(journalist: Journalist, workingDirectory: Path, repositoriesConfigurations: Map<String, RepositoryConfiguration>): RepositoryService {
val repositories: MutableMap<String, Repository> = LinkedHashMap(repositoriesConfigurations.size)

for ((repositoryName, repositoryConfiguration) in repositoriesConfigurations) {
repositories[repositoryName] = RepositoryFactory.createRepository(journalist, repositoryName, repositoryConfiguration)
repositories[repositoryName] = RepositoryFactory.createRepository(journalist, workingDirectory, repositoryName, repositoryConfiguration)
}

return RepositoryService(journalist, repositories)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class Repository internal constructor(
) : Comparator<Path> {

companion object {
private val REPOSITORIES_PATH = Paths.get("repositories")
val REPOSITORIES_PATH = Paths.get("repositories")
}

private fun <R> relativize(file: String, consumer: (Path) -> Result<R, ErrorResponse>): Result<R, ErrorResponse> =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ import org.panda_lang.reposilite.maven.RepositorySecurityProvider
import org.panda_lang.reposilite.maven.RepositoryServiceFactory
import org.panda_lang.reposilite.maven.infrastructure.MavenFileEndpoint
import org.panda_lang.reposilite.web.api.Routes
import java.nio.file.Path

internal object MavenWebConfiguration {

fun createFacade(journalist: Journalist, failureFacade: FailureFacade, repositoriesConfiguration: Map<String, RepositoryConfiguration>): MavenFacade {
val repositoryService = RepositoryServiceFactory.createRepositoryService(journalist, repositoriesConfiguration)
fun createFacade(journalist: Journalist, failureFacade: FailureFacade, workingDirectory: Path, repositoriesConfiguration: Map<String, RepositoryConfiguration>): MavenFacade {
val repositoryService = RepositoryServiceFactory.createRepositoryService(journalist, workingDirectory, repositoriesConfiguration)
val metadataService = MetadataService(failureFacade)

return MavenFacade(journalist, metadataService, RepositorySecurityProvider(), repositoryService)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ object FilesUtils {

val value = match.group(1).toLong()

return when (match.group(2).toUpperCase()) {
return when (match.group(2).uppercase()) {
"GB" -> value * GB_FACTOR
"MB" -> value * MB_FACTOR
"KB" -> value * KB_FACTOR
Expand Down Expand Up @@ -95,7 +95,7 @@ object FilesUtils {
fun getMimeType(path: String, defaultType: String): String =
MimeTypes.getMimeType(getExtension(path), defaultType)

fun writeFileChecksums(repository: Repository, path: Path, bytes: ByteArray?) {
fun writeFileChecksums(repository: Repository, path: Path, bytes: ByteArray) {
val relativePath = repository.relativize(path)

val md5 = relativePath.resolveSibling(relativePath.fileName.toString() + ".md5")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ internal class SqlStatisticsRepository : StatisticsRepository {

private fun toRecord(row: ResultRow) =
Record(
RecordType.valueOf(row[StatisticsTable.type].toUpperCase()),
RecordType.valueOf(row[StatisticsTable.type].uppercase()),
row[StatisticsTable.identifier],
row[StatisticsTable.count]
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,26 @@
package org.panda_lang.reposilite.storage

import net.dzikoysk.dynamiclogger.Journalist
import org.panda_lang.reposilite.maven.api.Repository
import org.panda_lang.reposilite.storage.infrastructure.FileSystemStorageProviderFactory
import org.panda_lang.reposilite.storage.infrastructure.S3StorageProvider
import org.panda_lang.reposilite.storage.infrastructure.S3StorageProviderSettings
import picocli.CommandLine
import java.nio.file.Paths
import java.nio.file.Files
import java.nio.file.Path

internal object StorageProviderFactory {

fun createStorageProvider(journalist: Journalist, repositoryName: String, storageDescription: String): StorageProvider {
fun createStorageProvider(journalist: Journalist, workingDirectory: Path, repositoryName: String, storageDescription: String, quota: String): StorageProvider {
if (storageDescription.startsWith("fs")) {
return FileSystemStorageProviderFactory.of(
Paths.get("repositories").resolve(repositoryName),
Long.MAX_VALUE // TOFIX: Move quota's implementation to Repository level
)
val repositoryDirectory = workingDirectory.resolve(Repository.REPOSITORIES_PATH).resolve(repositoryName)
Files.createDirectories(repositoryDirectory)

return FileSystemStorageProviderFactory.of(journalist, repositoryDirectory, quota)
}

if (storageDescription.startsWith("s3")) {
// Implement quota
val settings = loadConfiguration(S3StorageProviderSettings(), storageDescription)
return S3StorageProvider(journalist, settings.bucketName, settings.region)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@ enum class Permission(val type: PermissionType, val identifier: String) {
}

override fun toString(): String =
"${type.name.toLowerCase()}:$name"
"${type.name.lowercase()}:$name"

}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class ReposiliteContextFactory internal constructor(

val session = authenticationFacade.authenticateByHeader(context.headerMap())
.map {
authenticationFacade.createSession(normalizedUri, SessionMethod.valueOf(context.method().toUpperCase()), host, it)
authenticationFacade.createSession(normalizedUri, SessionMethod.valueOf(context.method().uppercase()), host, it)
}

return ok(ReposiliteContext(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ internal object JavalinWebServerConfiguration {
val server = Server()

configureJavalin(config)
configureJsonSerialization(config)
configureJsonSerialization()
configureSSL(reposilite, configuration, config, server)
configureCors(config)
configureOpenApi(configuration, config)
Expand All @@ -43,7 +43,7 @@ internal object JavalinWebServerConfiguration {
config.showJavalinBanner = false
}

private fun configureJsonSerialization(config: JavalinConfig) {
private fun configureJsonSerialization() {
val objectMapper = ObjectMapper()
objectMapper.setSerializationInclusion(Include.NON_NULL)
JavalinJackson.configure(objectMapper)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package org.panda_lang.reposilite.maven

import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.fail
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.EnumSource
import org.panda_lang.reposilite.config.Configuration.RepositoryConfiguration
import org.panda_lang.reposilite.maven.api.DeployRequest
import org.panda_lang.reposilite.maven.api.FileType.FILE
import org.panda_lang.reposilite.maven.api.RepositoryVisibility

internal class MavenFacadeTest : MavenSpec() {

override fun repositories() = mapOf(
"public" to RepositoryConfiguration().also {
it.visibility = RepositoryVisibility.PUBLIC
},
"hidden" to RepositoryConfiguration().also {
it.visibility = RepositoryVisibility.HIDDEN
},
"private" to RepositoryConfiguration().also {
it.visibility = RepositoryVisibility.PRIVATE
}
)

@ParameterizedTest
@EnumSource(RepositoryVisibility::class)
fun `should deploy file under the given path`(visibility: RepositoryVisibility) {
// given: an uri and file to store
val repository = visibility.name.lowercase()
val gav = "/org/panda-lang/reposilite/3.0.0/reposilite-3.0.0.jar"
val by = "[email protected]"
val file = "content".byteInputStream()

// when: the following file is deployed
val fileDetails = mavenFacade.deployFile(DeployRequest(repository, gav, by, file))
.onError { fail { it.toString() } }
.get()

// then: file has been successfully stored
assertEquals(FILE, fileDetails.type)
assertEquals("reposilite-3.0.0.jar", fileDetails.name)
assertFalse(fileDetails.isReadable())
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.panda_lang.reposilite.maven

import net.dzikoysk.dynamiclogger.backend.InMemoryLogger
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.io.TempDir
import org.panda_lang.reposilite.config.Configuration.RepositoryConfiguration
import org.panda_lang.reposilite.failure.FailureFacade
import java.io.File

@Suppress("LeakingThis")
internal abstract class MavenSpec {

@TempDir
@JvmField
var workingDirectory: File? = null

lateinit var mavenFacade: MavenFacade

@BeforeEach
private fun initializeFacade() {
val logger = InMemoryLogger()
val failureFacade = FailureFacade(logger)
val metadataService = MetadataService(failureFacade)
val repositorySecurityProvider = RepositorySecurityProvider()
val repositoryService = RepositoryServiceFactory.createRepositoryService(logger, workingDirectory!!.toPath(), repositories())

this.mavenFacade = MavenFacade(logger, metadataService, repositorySecurityProvider, repositoryService)
}

protected abstract fun repositories(): Map<String, RepositoryConfiguration>

}
6 changes: 3 additions & 3 deletions reposilite-backend/src/test/workspace/reposilite.cdn
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ enforceSsl: false
repositories {
releases {
# Supported visibilities: public, hidden, private
visibility: public
visibility: PUBLIC
# Used storage type. Supported storage providers:
# - fs
# - s3 bucket-name region
Expand All @@ -54,7 +54,7 @@ repositories {
}
snapshots {
# Supported visibilities: public, hidden, private
visibility: public
visibility: PUBLIC
# Used storage type. Supported storage providers:
# - fs
# - s3 bucket-name region
Expand All @@ -69,7 +69,7 @@ repositories {
}
private {
# Supported visibilities: public, hidden, private
visibility: private
visibility: PRIVATE
# Used storage type. Supported storage providers:
# - fs
# - s3 bucket-name region
Expand Down

0 comments on commit 9777031

Please sign in to comment.