Skip to content
This repository has been archived by the owner on Feb 21, 2022. It is now read-only.

Jgrgicevic/sw 593 envs #342

Merged
merged 4 commits into from
Jun 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 37 additions & 3 deletions test/repos/tasks/test_sync_repos.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,22 @@
import pytest
from faker import Faker

from zoo.repos.models import Provider, Repository
from zoo.repos.models import Provider, Repository, RepositoryEnvironment
from zoo.repos.tasks import sync_repos

pytestmark = pytest.mark.django_db


class FakeGitlabEnviroment:
def __init__(self, id=None, name=None, external_url=None, slug=None):
self.fake = Faker()
self.id = self.fake.pyint() if id is None else id
self.name = self.fake.word() if name is None else name
self.slug = self.fake.word() if slug is None else slug
self.external_url = self.fake.url() if external_url is None else external_url
self.state = "available"


class FakeGitProject:
def __init__(self, pid):
self.fake = Faker()
Expand Down Expand Up @@ -53,38 +63,58 @@ def generate_project_list(pid=None, owner=None, name=None, url=None, **kwargs):
}


def generate_proj_envs_list():
return [FakeGitlabEnviroment()]


def test_sync_untouched_repo(repository):
project_list = generate_project_list(
repository.remote_id, repository.owner, repository.name, repository.url
)
gitlab_envs = generate_proj_envs_list()
with patch(
"gitlab.v4.objects.ProjectManager.list", return_value=project_list["gitlab"]
), patch(
"github.AuthenticatedUser.AuthenticatedUser.get_repos",
return_value=project_list["github"],
), patch(
"zoo.repos.tasks.get_project_enviroments",
return_value=gitlab_envs,
):
sync_repos()

gitlab_project = project_list["gitlab"][0]
assert gitlab_project.id == repository.remote_id
repository = Repository.objects.get(
remote_id=gitlab_project.id, provider=Provider.GITLAB.value
)
assert gitlab_project.namespace["full_path"] == repository.owner
assert gitlab_project.path == repository.name
assert gitlab_project.web_url == repository.url

repo_env = repository.repository_environments.first()
assert gitlab_envs[0].name == repo_env.name
assert gitlab_envs[0].external_url == repo_env.external_url

github_project = project_list["github"][0]
assert github_project.id == repository.remote_id + 1
repository = Repository.objects.get(
remote_id=github_project.id, provider=Provider.GITHUB.value
)
assert github_project.owner.login == repository.owner
assert github_project.name == repository.name
assert github_project.svn_url == repository.url


def test_sync_moved_repo(repository):
project_list = generate_project_list(repository.remote_id)
gitlab_envs = generate_proj_envs_list()
with patch(
"gitlab.v4.objects.ProjectManager.list", return_value=project_list["gitlab"]
), patch(
"github.AuthenticatedUser.AuthenticatedUser.get_repos",
return_value=project_list["github"],
), patch(
"zoo.repos.tasks.get_project_enviroments",
return_value=gitlab_envs,
):
sync_repos()

Expand All @@ -96,6 +126,10 @@ def test_sync_moved_repo(repository):
assert gitlab_project.path == repository.name
assert gitlab_project.web_url == repository.url

repo_env = repository.repository_environments.first()
assert gitlab_envs[0].name == repo_env.name
assert gitlab_envs[0].external_url == repo_env.external_url

github_project = project_list["github"][0]
repository = Repository.objects.get(
remote_id=github_project.id, provider=Provider.GITHUB.value
Expand Down
2 changes: 2 additions & 0 deletions test/services/test_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,13 @@ def test_service_form__complete__incorrect_status(repository):
"environments-0-service_urls_0": fake.url(),
"environments-0-service_urls_1": fake.url(),
"environments-0-DELETE": False,
"environments-0-type": "zoo",
"environments-1-name": fake.word(),
"environments-1-dashboard_url": fake.url(),
"environments-1-service_urls_0": fake.url(),
"environments-1-service_urls_1": fake.url(),
"environments-1-DELETE": False,
"environments-1-type": "zoo",
}


Expand Down
8 changes: 8 additions & 0 deletions zoo/base/assets/js/components/RepoInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
import { match } from "ramda"
import RepoInputSuggestions from "./RepoInputSuggestions"
import $ from 'jquery/src/jquery'
import { gitlabEnvs } from "../../../../services/assets/js/gitlab_envs.js"


function createPopup () {
$('i.magic.icon').popup({
Expand All @@ -51,6 +53,11 @@ function popupAction (action) {
$('i.magic.icon').popup(action)
}

function loadGitlabEnvs(repoId) {
gitlabEnvsInfo["repoId"] = repoId
gitlabEnvs.load(gitlabEnvsInfo)
}

export default {
template: "#repo-input-text-field-markup",
data () {
Expand Down Expand Up @@ -153,6 +160,7 @@ export default {
this.$refs.suggestions.selectSuggestion();
this.isOnEditMode = false
this.$store.commit("refreshEnteredText")
loadGitlabEnvs(parseInt(this.inputValue))
},
},
components: {
Expand Down
11 changes: 10 additions & 1 deletion zoo/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from zoo.auditing.check_discovery import Kind
from zoo.auditing.models import Issue
from zoo.datacenters.models import InfraNode
from zoo.repos.models import Repository
from zoo.repos.models import Repository, RepositoryEnvironment
from zoo.services.models import Environment, Impact, Link, Service, Status, Tier


Expand All @@ -33,6 +33,15 @@ class Meta:
url = LazyAttribute(lambda o: f"https://gitlab.com/{o.owner}/{o.name}")


class RepositoryEnvironmentFactory(DjangoModelFactory):
class Meta:
model = RepositoryEnvironment

name = Faker("domain_word")
repository = SubFactory(RepositoryFactory)
external_url = LazyAttribute(lambda o: f"https://gitlab.com/{o.name}/{o.name}")


class IssueFactory(DjangoModelFactory):
class Meta:
model = Issue
Expand Down
5 changes: 5 additions & 0 deletions zoo/repos/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,8 @@
@admin.register(models.Repository)
class RepoAdmin(admin.ModelAdmin):
search_fields = ("remote_id", "owner", "name", "provider")


@admin.register(models.RepositoryEnvironment)
class RepoEnvAdmin(admin.ModelAdmin):
search_fields = ("name", "external_url")
2 changes: 2 additions & 0 deletions zoo/repos/forms.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from django.forms import widgets

from ..services.constants import EnviromentType
from .models import Repository


Expand All @@ -19,4 +20,5 @@ def get_context(self, name, value, attrs):
)

context["widget"]["value"] = value
context["env_type_gitlab"] = EnviromentType.GITLAB.value
return context
8 changes: 8 additions & 0 deletions zoo/repos/gitlab.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@
log = structlog.get_logger()


def get_project_enviroments(remote_id):
try:
project = gitlab.projects.get(remote_id)
return project.environments.list(as_list=False)
except (GitlabGetError, GitlabListError):
return []


def get_project(remote_id):
try:
project = gitlab.projects.get(remote_id)
Expand Down
43 changes: 43 additions & 0 deletions zoo/repos/migrations/0008_repositoryenvironment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Generated by Django 2.2.19 on 2021-04-30 14:24

import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("repos", "0007_endpoint"),
]

operations = [
migrations.CreateModel(
name="RepositoryEnvironment",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField(max_length=200)),
("external_url", models.CharField(max_length=300, null=True)),
(
"repository",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="repository_environments",
related_query_name="repository_environment",
to="repos.Repository",
),
),
],
options={
"ordering": ["name"],
"unique_together": {("repository", "name")},
},
),
]
16 changes: 16 additions & 0 deletions zoo/repos/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,19 @@ class Meta:
)
summary = models.CharField(max_length=500, null=True, blank=True)
operation = models.CharField(max_length=200, null=True, blank=True)


class RepositoryEnvironment(models.Model):
class Meta:
unique_together = ("repository", "name")
ordering = ["name"]

repository = models.ForeignKey(
Repository,
on_delete=models.CASCADE,
related_name="repository_environments",
related_query_name="repository_environment",
)

name = models.CharField(max_length=200)
external_url = models.CharField(max_length=300, null=True)
58 changes: 56 additions & 2 deletions zoo/repos/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@
from ..auditing import runner
from ..auditing.check_discovery import CHECKS as AUDITING_CHECKS
from ..repos.models import Endpoint
from ..services.constants import EnviromentType
from ..services.models import Environment, Service
from .exceptions import MissingFilesError, RepositoryNotFoundError
from .github import get_repositories as get_github_repositories
from .gitlab import get_project_enviroments
from .gitlab import get_repositories as get_gitlab_repositories
from .models import Repository
from .models import Repository, RepositoryEnvironment
from .utils import download_repository, get_scm_module, openapi_definition
from .zoo_yml import parse, validate

Expand All @@ -39,14 +41,17 @@

@shared_task
def sync_repos():

i = 0
for project in itertools.chain(
get_github_repositories(), get_gitlab_repositories()
):
if settings.SYNC_REPOS_SKIP_FORKS and project["is_fork"]:
continue
if settings.SYNC_REPOS_SKIP_PERSONAL and project["is_personal"]:
continue

i += 1
log.info("sync_repos.fetch", repo_number=i, project=project)
try:
repo = Repository.objects.get(
remote_id=project["id"], provider=project["provider"]
Expand All @@ -68,6 +73,12 @@ def sync_repos():
repo.full_clean()
repo.save()

if project["provider"] == "gitlab":
log.info("sync_repos.calling.sync_enviroments_from_gitlab")
sync_enviroments_from_gitlab(repo)

log.info("sync_repos.total", repo_number=i)


@shared_task
def schedule_pulls():
Expand Down Expand Up @@ -208,3 +219,46 @@ def get_zoo_file_content(proj: Dict) -> str:
return provider.get_file_content(
proj["id"], settings.ZOO_YAML_FILE, settings.ZOO_YAML_DEFAULT_REF
)


def sync_enviroments_from_gitlab(repo: Repository):
gl_envs = get_project_enviroments(repo.remote_id)

if not gl_envs:
log.info("sync_enviroments_from_gitlab.no_envs")
return

envs = []
i = 0
log.info("sync_enviroments_from_gitlab.start")
for gl_env in gl_envs:
if gl_env.state != "available":
continue
env, _ = RepositoryEnvironment.objects.get_or_create(
repository_id=repo.id, name=gl_env.name
)
env.external_url = gl_env.external_url
env.save()
envs.append(env)
i += 1

RepositoryEnvironment.objects.filter(repository_id=repo.id).exclude(
id__in=[env.id for env in envs]
).delete()

# update gitlab envs on every service
services = Service.objects.filter(repository_id=repo.id)
for service in services:
Environment.objects.filter(
service_id=service.id, type=EnviromentType.GITLAB.value
).exclude(name__in=[env.name for env in envs]).delete()
for env in envs:
service_env, _ = Environment.objects.get_or_create(
service_id=service.id,
name=env.name,
type=EnviromentType.GITLAB.value,
)
service_env.dashboard_url = env.external_url
service_env.save()

log.info("sync_enviroments_from_gitlab.total.synced", envs_synced=i)
5 changes: 5 additions & 0 deletions zoo/repos/templates/repos/fields/repo_input.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
{% load static %}

<div id="repo-input" class="repo-input-container">
<repo-input></repo-input>
</div>
Expand All @@ -20,4 +22,7 @@
name: '{{ widget.name }}',
initialValue: '{{ widget.value|default:"" }}'
};
const gitlabEnvsInfo = {
envsUrl: '{% url "get_gitlab_envs" %}'
}
</script>
1 change: 1 addition & 0 deletions zoo/repos/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@
urlpatterns = [
path("", views.RepoList.as_view(), name="repo_list"),
path("<provider>/<int:repo_id>/", views.repo_details, name="repo_details"),
path("api/get-gitlab-envs/", views.get_gitlab_envs, name="get_gitlab_envs"),
]
Loading