Skip to content

Commit

Permalink
✨ : add gitlab import
Browse files Browse the repository at this point in the history
  • Loading branch information
juwit committed Jan 17, 2020
1 parent 317d50c commit 3bb96e6
Show file tree
Hide file tree
Showing 10 changed files with 354 additions and 32 deletions.
4 changes: 2 additions & 2 deletions src/main/java/io/codeka/gaia/registries/RegistryApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ 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
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,6 +7,7 @@ import com.fasterxml.jackson.databind.annotation.JsonNaming
import io.codeka.gaia.registries.RegistryApi
import io.codeka.gaia.registries.RegistryFile
import io.codeka.gaia.registries.RegistryType
import io.codeka.gaia.registries.gitlab.GitlabRepository
import io.codeka.gaia.teams.User
import org.springframework.http.HttpEntity
import org.springframework.http.HttpHeaders
Expand Down Expand Up @@ -40,20 +41,20 @@ class GithubRegistryApi(val restTemplate: RestTemplate): RegistryApi<GithubRepos
}
}

override fun getRepositories(user: User): List<String> {
override fun getRepositories(user: User): List<GithubRepository> {
// 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()
return repos.toList()
}

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

val token = user.oAuth2User?.token!!

Expand All @@ -75,5 +76,5 @@ class GithubRegistryApi(val restTemplate: RestTemplate): RegistryApi<GithubRepos
}

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
@@ -0,0 +1,80 @@
package io.codeka.gaia.registries.gitlab

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.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 GitlabRegistryApi(val restTemplate: RestTemplate): RegistryApi<GitlabRepository> {

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<GitlabRepository> {
// fetching repositories
val url = "https://gitlab.com/api/v4/projects?visibility=public&owned=true"

val token = user.oAuth2User?.token!!

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

return repos.toList()
}

override fun getRepository(user: User, projectId: String): GitlabRepository {
// fetching repositories
val url = "https://gitlab.com/api/v4/projects/$projectId"

val token = user.oAuth2User?.token!!

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

override fun getFileContent(user: User, projectId: String, filename: String): String {
val url = "https://gitlab.com/api/v4/projects/$projectId/repository/files/$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", "")))
}

}

data class GitlabRepository(
@JsonAlias("id") val id: String,
@JsonAlias("path_with_namespace") val fullName: String,
@JsonAlias("web_url") val htmlUrl: String)
30 changes: 16 additions & 14 deletions src/main/resources/templates/modules_import.html
Original file line number Diff line number Diff line change
Expand Up @@ -76,19 +76,19 @@
</template>
</b-card>
</div>
<!-- <div class="col-md-4">-->
<!-- <b-card no-body>-->
<!-- <b-button size="lg" variant="outline-secondary" class="btn-gitlab" squared @click="toggle('gitlab')">-->
<!-- <i class="fab fa-gitlab"></i> from Gitlab-->
<!-- </b-button>-->

<!-- <repository-import v-if="selected == 'gitlab'" :registry="'gitlab'"></repository-import>-->

<!-- <template v-slot:footer>-->
<!-- <em>Import an existing module code from existing Gitlab repository</em>-->
<!-- </template>-->
<!-- </b-card>-->
<!-- </div>-->
<div class="col-md-4">
<b-card no-body>
<b-button size="lg" variant="outline-secondary" class="btn-gitlab" squared @click="toggle('gitlab')">
<i class="fab fa-gitlab"></i> from Gitlab
</b-button>

<repository-import v-if="selected == 'gitlab'" :registry="'gitlab'"></repository-import>

<template v-slot:footer>
<em>Import an existing module code from existing Gitlab repository</em>
</template>
</b-card>
</div>
<div class="col-md-4">
<b-card no-body>
<b-button size="lg" variant="outline-danger" squared @click="toggle('manual')">
Expand All @@ -113,6 +113,7 @@
v-model="selectedRepository"
id="repoSelect"
placeholder="Type to search"
label="fullName"
:options="repositories"
:loading="isLoading"
@open="search">
Expand Down Expand Up @@ -200,7 +201,8 @@
},
importRepository: function() {
this.isImporting = true;
$.get(`/api/registries/${this.registry}/repositories/${this.selectedRepository}/import`).then(module => {
const id = this.selectedRepository.id ? this.selectedRepository.id : this.selectedRepository.fullName;
$.get(`/api/registries/${this.registry}/repositories/${id}/import`).then(module => {
window.location = `/modules/${module.id}`
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,16 @@ class GithubRegistryControllerTest{

val user = User("juwit", null)

val githubRepository = GithubRepository("juwit/terraform-docker-mongo","https://github.com/juwit/terraform-docker-mongo")
whenever(githubRegistryApi.getRepository(user, "juwit", "terraform-docker-mongo")).thenReturn(githubRepository)
val githubRepository = GithubRepository("juwit/terraform-docker-mongo", "https://github.com/juwit/terraform-docker-mongo")
whenever(githubRegistryApi.getRepository(user, "juwit/terraform-docker-mongo")).thenReturn(githubRepository)

val variablesFileContent = "mock file content"
whenever(githubRegistryApi.getFileContent(user, "juwit/terraform-docker-mongo", "variables.tf")).thenReturn(variablesFileContent)
whenever(hclParser.parseVariables(variablesFileContent)).thenReturn(listOf(Variable("dummy")))

val module = githubRegistryController.importRepository("juwit", "terraform-docker-mongo", user)

verify(githubRegistryApi).getRepository(user, "juwit", "terraform-docker-mongo")
verify(githubRegistryApi).getRepository(user, "juwit/terraform-docker-mongo")
verify(githubRegistryApi).getFileContent(user, "juwit/terraform-docker-mongo", "variables.tf")

verifyNoMoreInteractions(githubRegistryApi)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package io.codeka.gaia.registries.controller

import io.codeka.gaia.hcl.HclParser
import io.codeka.gaia.modules.bo.TerraformModule
import io.codeka.gaia.modules.bo.Variable
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.RegistryType
import io.codeka.gaia.registries.github.GithubRepository
import io.codeka.gaia.registries.gitlab.GitlabRepository
import io.codeka.gaia.teams.User
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.mockito.ArgumentMatchers.any
import org.mockito.InjectMocks
import org.mockito.Mock
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.junit.jupiter.MockitoExtension

@ExtendWith(MockitoExtension::class)
class GitlabRegistryControllerTest{

@Mock
lateinit var gitlabRegistryApi: RegistryApi<GitlabRepository>

@Mock
lateinit var hclParser: HclParser

@Mock
lateinit var terraformCLIRepository: TerraformCLIRepository

@Mock
lateinit var moduleRepository: TerraformModuleRepository

@InjectMocks
lateinit var gitlabRegistryController: GitlabRegistryController

@Test
fun `getRepositories() should call the gitlab registry api`() {
// given
val john = User("john", null)
// when
gitlabRegistryController.getRepositories(john)
// then
verify(gitlabRegistryApi).getRepositories(john)
}

@Test
fun `importRepository() should call the gitlab registry and create a module`() {
// returns saved module as first arg
whenever(moduleRepository.save(any(TerraformModule::class.java))).then { it.arguments[0] }

whenever(terraformCLIRepository.listCLIVersion()).thenReturn(listOf("1.12.8", "1.12.7"))

val user = User("juwit", null)

val gitlabRepository = GitlabRepository("15689", "juwit/terraform-docker-mongo", "https://gitlab.com/juwit/terraform-docker-mongo")
whenever(gitlabRegistryApi.getRepository(user, "15689")).thenReturn(gitlabRepository)

val variablesFileContent = "mock file content"
whenever(gitlabRegistryApi.getFileContent(user, "15689", "variables.tf")).thenReturn(variablesFileContent)
whenever(hclParser.parseVariables(variablesFileContent)).thenReturn(listOf(Variable("dummy")))

val module = gitlabRegistryController.importRepository("15689", user)

verify(gitlabRegistryApi).getRepository(user, "15689")
verify(gitlabRegistryApi).getFileContent(user, "15689", "variables.tf")

verifyNoMoreInteractions(gitlabRegistryApi)

assertThat(module.id).isNotBlank()

assertThat(module.name).isEqualTo("juwit/terraform-docker-mongo")
assertThat(module.gitRepositoryUrl).isEqualTo("https://gitlab.com/juwit/terraform-docker-mongo")
assertThat(module.gitBranch).isEqualTo("master")

assertThat(module.registryDetails.registryType).isEqualTo(RegistryType.GITLAB)
assertThat(module.registryDetails.projectId).isEqualTo("15689")

assertThat(module.cliVersion).isEqualTo("1.12.8")
assertThat(module.createdBy).isEqualTo(user)

assertThat(module.variables).containsExactly(Variable("dummy"))

}
}
Loading

0 comments on commit 3bb96e6

Please sign in to comment.