Skip to content

Commit

Permalink
Merge pull request #202 from gaia-app/gitlab_module_import
Browse files Browse the repository at this point in the history
✨️ : gitlab module import
  • Loading branch information
cdubuisson committed Jan 19, 2020
2 parents 317d50c + d9797e0 commit e505eb5
Show file tree
Hide file tree
Showing 24 changed files with 534 additions and 295 deletions.
2 changes: 1 addition & 1 deletion src/main/java/io/codeka/gaia/modules/bo/Variable.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ data class Variable @JvmOverloads constructor(@field:NotBlank val name: String,
var type: String? = null,
var description: String? = null,
var defaultValue: String? = null,
var editable: Boolean = false,
var editable: Boolean = true,
var mandatory: Boolean = false,
var validationRegex: String? = null)
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public TerraformModuleGitRepository(List<RegistryRawContent> registryRawContents
*/
public Optional<String> getReadme(TerraformModule module){
var strategy = registryRawContents.stream()
.filter(s -> s.matches(module.getGitRepositoryUrl()))
.filter(s -> s.matches(module))
.findFirst();

if(strategy.isEmpty()){
Expand Down
63 changes: 63 additions & 0 deletions src/main/java/io/codeka/gaia/registries/AbstractRegistryApi.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package io.codeka.gaia.registries

import io.codeka.gaia.teams.User
import org.springframework.http.HttpEntity
import org.springframework.http.HttpHeaders
import org.springframework.http.HttpMethod
import org.springframework.http.HttpStatus
import org.springframework.web.client.RestTemplate
import java.util.*

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

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

val requestEntity = HttpEntity<Any>(headers)

val response = restTemplate.exchange(
url,
HttpMethod.GET,
requestEntity,
responseType)
if(response.statusCode == HttpStatus.OK) {
return response.body
}
else {
TODO("error code mgmt")
}
}

override fun getRepositories(user: User): List<K> {
// fetching repositories
val url = registryType.repositoriesUrl

val token = user.oAuth2User?.token!!

return callWithAuth(url, token, registryListFileClass).toList()
}

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

val token = user.oAuth2User?.token!!

return callWithAuth(url, token, registryFileClass)
}

override fun getFileContent(user: User, projectId: String, filename: String): String {
val url = registryType.fileContentUrl.format(projectId, filename)

val token = user.oAuth2User?.token!!

val file = callWithAuth(url, token, RegistryFile::class.java)

// removing trailing \n
return String(Base64.getDecoder().decode(file.content.replace("\n", "")))
}
}
6 changes: 2 additions & 4 deletions src/main/java/io/codeka/gaia/registries/RegistryApi.kt
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
package io.codeka.gaia.registries

import io.codeka.gaia.registries.github.GithubRepository
import io.codeka.gaia.teams.User
import org.springframework.web.client.RestTemplate

interface RegistryApi<T> {

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

fun getRepository(user: User, owner: String, repo: String): T
fun getRepository(user: User, projectId: String): T

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

Expand Down
10 changes: 1 addition & 9 deletions src/main/java/io/codeka/gaia/registries/RegistryRawContent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,7 @@ import java.util.regex.Pattern

abstract class RegistryRawContent(private val registryType: RegistryType, private val restTemplate: RestTemplate) {

/**
* Returns the pattern to match the repository url.
* The pattern should contains at least one group to extract the part of the repository to keep
*/
protected abstract val pattern: Pattern

open fun matches(url: String): Boolean {
return pattern.matcher(url).matches()
}
open fun matches(module: TerraformModule) = registryType == module.registryDetails?.registryType

open fun getReadme(module: TerraformModule): Optional<String> {
// no project details, impossible to load a readme, so returning empty
Expand Down
18 changes: 15 additions & 3 deletions src/main/java/io/codeka/gaia/registries/bo.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
package io.codeka.gaia.registries

enum class RegistryType(val readmeUrl: String){
GITHUB("https://api.github.com/repos/{id}/contents/README.md?ref=master"),
GITLAB("https://gitlab.com/api/v4/projects/{id}/repository/files/README.md?ref=master")
enum class RegistryType(val repositoriesUrl: String,
val repositoryUrl: String,
val fileContentUrl: String,
val readmeUrl: String){

GITHUB("https://api.github.com/user/repos?visibility=public",
"https://api.github.com/repos/%s",
"https://api.github.com/repos/%s/contents/%s?ref=master",
"https://api.github.com/repos/{id}/contents/README.md?ref=master"),

GITLAB("https://gitlab.com/api/v4/projects?visibility=public&owned=true",
"https://gitlab.com/api/v4/projects/%s",
"https://gitlab.com/api/v4/projects/%s/repository/files/%s?ref=master",
"https://gitlab.com/api/v4/projects/{id}/repository/files/README.md?ref=master")

}

data class RegistryDetails(val registryType: RegistryType, val projectId: String)
Expand Down
10 changes: 0 additions & 10 deletions src/main/java/io/codeka/gaia/registries/config/RegistryConfig.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
package io.codeka.gaia.registries.config;

import io.codeka.gaia.registries.RegistryOAuth2Provider;
import io.codeka.gaia.registries.RegistryRawContent;
import io.codeka.gaia.registries.github.GitHubOAuth2Provider;
import io.codeka.gaia.registries.github.GitHubRawContent;
import io.codeka.gaia.registries.gitlab.GitLabOAuth2Provider;
import io.codeka.gaia.registries.gitlab.GitLabRawContent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

import java.util.List;

Expand All @@ -19,11 +14,6 @@
@Configuration
public class RegistryConfig {

@Bean
List<RegistryRawContent> registryRawContents(@Autowired RestTemplate restTemplate) {
return List.of(new GitHubRawContent(restTemplate), new GitLabRawContent(restTemplate));
}

@Bean
List<RegistryOAuth2Provider> registryOAuth2Providers() {
return List.of(new GitHubOAuth2Provider(), new GitLabOAuth2Provider());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class GithubRegistryController(
private val moduleRepository: TerraformModuleRepository) {

@GetMapping("/repositories")
fun getRepositories(user: User): List<String> {
fun getRepositories(user: User): List<GithubRepository> {
return this.githubRegistryApi.getRepositories(user)
}

Expand All @@ -34,7 +34,7 @@ class GithubRegistryController(
val module = TerraformModule()
module.id = UUID.randomUUID().toString()

val githubRepository = githubRegistryApi.getRepository(user, owner, repo)
val githubRepository = githubRegistryApi.getRepository(user, "$owner/$repo")

module.gitRepositoryUrl = githubRepository.htmlUrl
module.gitBranch = "master"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package io.codeka.gaia.registries.controller

import io.codeka.gaia.hcl.HclParser
import io.codeka.gaia.modules.bo.TerraformModule
import io.codeka.gaia.modules.repository.TerraformCLIRepository
import io.codeka.gaia.modules.repository.TerraformModuleRepository
import io.codeka.gaia.registries.RegistryApi
import io.codeka.gaia.registries.RegistryDetails
import io.codeka.gaia.registries.RegistryType
import io.codeka.gaia.registries.gitlab.GitlabRepository
import io.codeka.gaia.teams.User
import org.springframework.http.HttpStatus
import org.springframework.security.access.annotation.Secured
import org.springframework.web.bind.annotation.*
import java.util.*

@RestController
@RequestMapping("/api/registries/gitlab")
@Secured
class GitlabRegistryController(
private val gitlabRegistryApi: RegistryApi<GitlabRepository>,
private val hclParser: HclParser,
private val cliRepository: TerraformCLIRepository,
private val moduleRepository: TerraformModuleRepository) {

@GetMapping("/repositories")
fun getRepositories(user: User): List<GitlabRepository> {
return this.gitlabRegistryApi.getRepositories(user)
}

@GetMapping("/repositories/{projectId}/import")
@ResponseStatus(HttpStatus.CREATED)
fun importRepository(@PathVariable projectId: String, user: User): TerraformModule {
val module = TerraformModule()
module.id = UUID.randomUUID().toString()

val gitlabRepository = gitlabRegistryApi.getRepository(user, projectId)

module.gitRepositoryUrl = gitlabRepository.htmlUrl
module.gitBranch = "master"
module.name = gitlabRepository.fullName
module.cliVersion = cliRepository.listCLIVersion().first()

module.registryDetails = RegistryDetails(RegistryType.GITLAB, gitlabRepository.id)
module.createdBy = user

// get variables
val variablesFile = gitlabRegistryApi.getFileContent(user, projectId, "variables.tf")
module.variables = hclParser.parseVariables(variablesFile)

// saving module !
return moduleRepository.save(module)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,4 @@ import org.springframework.web.client.RestTemplate
import java.util.regex.Pattern

@Component
class GitHubRawContent(restTemplate: RestTemplate) : RegistryRawContent(RegistryType.GITHUB, restTemplate) {

override val pattern: Pattern = Pattern.compile("^https?:\\/\\/(w{3}\\.)?github\\.com(.*)(.git)?\$")

}
class GitHubRawContent(restTemplate: RestTemplate) : RegistryRawContent(RegistryType.GITHUB, restTemplate)
Original file line number Diff line number Diff line change
@@ -1,79 +1,18 @@
package io.codeka.gaia.registries.github

import com.fasterxml.jackson.annotation.JsonAlias
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.annotation.JsonValue
import com.fasterxml.jackson.databind.annotation.JsonNaming
import io.codeka.gaia.registries.RegistryApi
import io.codeka.gaia.registries.RegistryFile
import io.codeka.gaia.registries.AbstractRegistryApi
import io.codeka.gaia.registries.RegistryType
import io.codeka.gaia.teams.User
import org.springframework.http.HttpEntity
import org.springframework.http.HttpHeaders
import org.springframework.http.HttpMethod
import org.springframework.http.HttpStatus
import org.springframework.stereotype.Service
import org.springframework.web.client.RestTemplate
import java.util.*

@Service
class GithubRegistryApi(val restTemplate: RestTemplate): RegistryApi<GithubRepository> {

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

val requestEntity = HttpEntity<Any>(headers)

val response = restTemplate.exchange(
url,
HttpMethod.GET,
requestEntity,
responseType)
if(response.statusCode == HttpStatus.OK) {
return response.body
}
else {
TODO("error code mgmt")
}
}

override fun getRepositories(user: User): List<String> {
// fetching repositories
val url = "https://api.github.com/user/repos?visibility=public"

val token = user.oAuth2User?.token!!

val repos = callWithAuth(url, token, Array<GithubRepository>::class.java)

return repos.map { it.fullName }.toList()
}

override fun getRepository(user: User, owner: String, repo: String): GithubRepository {
// fetching repositories
val url = "https://api.github.com/repos/$owner/$repo"

val token = user.oAuth2User?.token!!

return callWithAuth(url, token, GithubRepository::class.java)
}

override fun getFileContent(user: User, projectId: String, filename: String): String {
val url = "https://api.github.com/repos/$projectId/contents/$filename?ref=master";

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

val file = callWithAuth(url, token, RegistryFile::class.java)

// removing trailing \n
println(file.content.replace("\n", ""))
return String(Base64.getDecoder().decode(file.content.replace("\n", "")))
}

}
class GithubRegistryApi(restTemplate: RestTemplate): AbstractRegistryApi<GithubRepository>(
restTemplate,
RegistryType.GITHUB,
GithubRepository::class.java,
Array<GithubRepository>::class.java)

data class GithubRepository(
@JsonProperty("full_name") val fullName: String,
@JsonProperty("html_url") val htmlUrl: String)
@JsonAlias("full_name") val fullName: String,
@JsonAlias("html_url") val htmlUrl: String)
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ package io.codeka.gaia.registries.gitlab

import io.codeka.gaia.registries.RegistryType
import io.codeka.gaia.registries.RegistryRawContent
import org.springframework.stereotype.Component
import org.springframework.web.client.RestTemplate
import java.util.regex.Pattern

class GitLabRawContent(restTemplate: RestTemplate) : RegistryRawContent(RegistryType.GITLAB, restTemplate) {

override val pattern: Pattern = Pattern.compile("^(http[s]?://[www.]?gitlab.*).git$")

}
@Component
class GitLabRawContent(restTemplate: RestTemplate) : RegistryRawContent(RegistryType.GITLAB, restTemplate)
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package io.codeka.gaia.registries.gitlab

import com.fasterxml.jackson.annotation.JsonAlias
import io.codeka.gaia.registries.AbstractRegistryApi
import io.codeka.gaia.registries.RegistryType
import org.springframework.stereotype.Service
import org.springframework.web.client.RestTemplate

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

data class GitlabRepository(
@JsonAlias("id") val id: String,
@JsonAlias("path_with_namespace") val fullName: String,
@JsonAlias("web_url") val htmlUrl: String)
Loading

0 comments on commit e505eb5

Please sign in to comment.