Skip to content

Commit

Permalink
✨ : compute registry details for Gitlab urls
Browse files Browse the repository at this point in the history
  • Loading branch information
juwit committed May 8, 2022
1 parent c0c3153 commit 8436476
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 19 deletions.
46 changes: 43 additions & 3 deletions src/main/java/io/gaia_app/modules/ModuleServiceImpl.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package io.gaia_app.modules;

import io.gaia_app.modules.bo.TerraformModule;
import io.gaia_app.registries.RegistryApi;
import io.gaia_app.registries.RegistryDetails;
import io.gaia_app.registries.RegistryType;
import io.gaia_app.registries.SourceRepository;
import io.gaia_app.registries.github.GithubRegistryApi;
import io.gaia_app.registries.gitlab.GitlabRegistryApi;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;
Expand All @@ -26,16 +31,51 @@ public class ModuleServiceImpl implements ModuleService {
*/
private static final Pattern GITHUB_SSH_REPOSITORY_URL_REGEX = Pattern.compile("git@github\\.com:(.+?)(?:$|\\.git$)");

/**
* matches https://gitlab.com/something(.git), and captures 'something'.
* The first group (.+?) expands as few times as possible.
* The second non-capturing group (?:) matches the end of the line or .git
*/
private static final Pattern GITLAB_HTTPS_REPOSITORY_URL_REGEX = Pattern.compile("https://gitlab\\.com/(.+?)(?:/?$|\\.git$)");

/**
* matches git@gitlab.com:something(.git), and captures 'something'.
* The first group (.+?) expands as few times as possible.
* The second non-capturing group (?:) matches the end of the line or .git
*/
private static final Pattern GITLAB_SSH_REPOSITORY_URL_REGEX = Pattern.compile("git@gitlab\\.com:(.+?)(?:$|\\.git$)");

private Map<RegistryType, RegistryApi<? extends SourceRepository>> registryApis;

public ModuleServiceImpl(GithubRegistryApi githubRegistryApi, GitlabRegistryApi gitlabRegistryApiMap) {
this.registryApis = Map.of(RegistryType.GITHUB, githubRegistryApi, RegistryType.GITLAB, gitlabRegistryApiMap);
}

@Override
public void updateRegistryDetails(TerraformModule module) {
RegistryType registryType;
if (module.getGitRepositoryUrl().contains("github")) {
registryType = RegistryType.GITHUB;
} else if (module.getGitRepositoryUrl().contains("gitlab")) {
registryType = RegistryType.GITLAB;
} else {
// could not match any registry type from the URL
return;
}
// find first pattern that matches, then computes the details
Stream.of(GITHUB_HTTPS_REPOSITORY_URL_REGEX, GITHUB_SSH_REPOSITORY_URL_REGEX)
Stream.of(
GITHUB_HTTPS_REPOSITORY_URL_REGEX,
GITHUB_SSH_REPOSITORY_URL_REGEX,
GITLAB_HTTPS_REPOSITORY_URL_REGEX,
GITLAB_SSH_REPOSITORY_URL_REGEX)
.map(pattern -> pattern.matcher(module.getGitRepositoryUrl()))
.filter(Matcher::matches)
.findFirst()
.ifPresent(it -> {
var projectId = it.group(1);
module.setRegistryDetails(new RegistryDetails(RegistryType.GITHUB, projectId));
var projectName = it.group(1);
// get project id from project name
var repository = registryApis.get(registryType).getRepository(projectName);
module.setRegistryDetails(new RegistryDetails(registryType, repository.getId()));
});
}
}
43 changes: 32 additions & 11 deletions src/main/java/io/gaia_app/registries/AbstractRegistryApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,40 @@ import org.springframework.web.client.RestTemplate
import java.net.http.HttpClient
import java.util.*

abstract class AbstractRegistryApi<K: SourceRepository>(val restTemplate: RestTemplate,
private val registryType: RegistryType,
private val registryFileClass: Class<K>,
private val registryListFileClass: Class<Array<K>>): RegistryApi<K> {
abstract class AbstractRegistryApi<K : SourceRepository>(val restTemplate: RestTemplate,
private val registryType: RegistryType,
private val registryFileClass: Class<K>,
private val registryListFileClass: Class<Array<K>>) : RegistryApi<K> {

fun <T> callWithoutAuth(url: String, responseType: Class<T>): T? {
try {
val response = restTemplate.getForEntity(
url,
responseType)
return response.body
} catch (e: HttpClientErrorException) {
// in case of 404, returns null as an empty body
return null
}
}

private fun <T> callWithAuth(url: String, token: String, responseType: Class<T>): T? {
fun <T> callWithAuth(url: String, token: String, responseType: Class<T>): T? {
val headers = HttpHeaders()
headers.add("Authorization", "Bearer $token")

val requestEntity = HttpEntity<Any>(headers)

try{
try {
val response = restTemplate.exchange(
url,
HttpMethod.GET,
requestEntity,
responseType)
return response.body
}
catch (e:HttpClientErrorException){
} catch (e: HttpClientErrorException) {
// in case of 404, returns null as an empty body
return null
}

}

override fun getRepositories(user: User): List<K> {
Expand All @@ -45,6 +55,13 @@ abstract class AbstractRegistryApi<K: SourceRepository>(val restTemplate: RestTe
return callWithAuth(url, token, registryListFileClass)?.toList() ?: emptyList()
}

override fun getRepository(projectId: String): K {
// fetching repositories
val url = registryType.repositoryUrl.format(projectId)

return callWithoutAuth(url, registryFileClass)!!
}

override fun getRepository(user: User, projectId: String): K {
// fetching repositories
val url = registryType.repositoryUrl.format(projectId)
Expand All @@ -57,9 +74,13 @@ abstract class AbstractRegistryApi<K: SourceRepository>(val restTemplate: RestTe
override fun getFileContent(user: User, projectId: String, filename: String): String {
val url = registryType.fileContentUrl.format(projectId, filename)

val token = user.oAuth2User?.token!!
val token = user.oAuth2User?.token

val file = callWithAuth(url, token, RegistryFile::class.java)
val file = if (token != null) {
callWithAuth(url, token, RegistryFile::class.java)
} else {
callWithoutAuth(url, RegistryFile::class.java)
}

// removing trailing \n
return String(Base64.getDecoder().decode(file?.content?.replace("\n", "") ?: ""))
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/io/gaia_app/registries/RegistryApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,16 @@ interface RegistryApi<T> {

fun getRepositories(user: User) : List<T>

/**
* Gets a repository data for an authenticated user
*/
fun getRepository(user: User, projectId: String): T

/**
* Gets a repository data for an anonymous user
*/
fun getRepository(projectId: String): T

fun getFileContent(user: User, projectId: String, filename: String): String

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,20 @@ import io.gaia_app.registries.RegistryType
import io.gaia_app.registries.SourceRepository
import org.springframework.stereotype.Service
import org.springframework.web.client.RestTemplate
import java.net.URLEncoder
import java.nio.charset.Charset

@Service
class GitlabRegistryApi(restTemplate: RestTemplate): AbstractRegistryApi<GitlabRepository>(
restTemplate,
RegistryType.GITLAB,
GitlabRepository::class.java,
Array<GitlabRepository>::class.java)
Array<GitlabRepository>::class.java) {

override fun getRepository(projectId: String): GitlabRepository {
return super.getRepository(URLEncoder.encode(projectId, Charset.defaultCharset()))
}
}

/**
* Gitlab source repository implementation
Expand Down
53 changes: 49 additions & 4 deletions src/test/java/io/gaia_app/modules/ModuleServiceImplTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,34 @@

import io.gaia_app.modules.bo.TerraformModule;
import io.gaia_app.registries.RegistryType;
import org.junit.jupiter.api.Test;
import io.gaia_app.registries.github.GithubRegistryApi;
import io.gaia_app.registries.github.GithubRepository;
import io.gaia_app.registries.gitlab.GitlabRegistryApi;
import io.gaia_app.registries.gitlab.GitlabRepository;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.util.stream.Stream;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class ModuleServiceImplTest {

@Mock
private GitlabRegistryApi gitlabRegistryApi;

@Mock
private GithubRegistryApi githubRegistryApi;

@InjectMocks
private ModuleServiceImpl moduleService;

public static Stream<String> updateRegistryDetails_forGithubModule() {
return Stream.of(
"https://github.com/juwit/terraform-docker-mongo",
Expand All @@ -26,10 +42,11 @@ public static Stream<String> updateRegistryDetails_forGithubModule() {
@ParameterizedTest
@MethodSource
void updateRegistryDetails_forGithubModule(String registryUrl) {
when(githubRegistryApi.getRepository("juwit/terraform-docker-mongo")).thenReturn(new GithubRepository("juwit/terraform-docker-mongo", ""));

var module = new TerraformModule();
module.setGitRepositoryUrl(registryUrl);

var moduleService = new ModuleServiceImpl();
moduleService.updateRegistryDetails(module);

assertThat(module.getRegistryDetails())
Expand All @@ -39,4 +56,32 @@ void updateRegistryDetails_forGithubModule(String registryUrl) {
assertThat(it.getProjectId()).isEqualTo("juwit/terraform-docker-mongo");
});
}

public static Stream<String> updateRegistryDetails_forGitlabModule() {
return Stream.of(
"https://gitlab.com/juwit/terraform-docker-mongo",
"https://gitlab.com/juwit/terraform-docker-mongo/",
"https://gitlab.com/juwit/terraform-docker-mongo.git",
"git@gitlab.com:juwit/terraform-docker-mongo",
"git@gitlab.com:juwit/terraform-docker-mongo.git"
);
}

@ParameterizedTest
@MethodSource
void updateRegistryDetails_forGitlabModule(String registryUrl) {
when(gitlabRegistryApi.getRepository("juwit/terraform-docker-mongo")).thenReturn(new GitlabRepository("16181047", "", ""));

var module = new TerraformModule();
module.setGitRepositoryUrl(registryUrl);

moduleService.updateRegistryDetails(module);

assertThat(module.getRegistryDetails())
.isNotNull()
.satisfies(it -> {
assertThat(it.getRegistryType()).isEqualTo(RegistryType.GITLAB);
assertThat(it.getProjectId()).isEqualTo("16181047");
});
}
}

0 comments on commit 8436476

Please sign in to comment.