# Copyright (C) 2015-2022 The Sipwise Team - http://sipwise.com # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see <http://www.gnu.org/licenses/>. import re import structlog from django.contrib.auth.decorators import login_required from django.http import Http404 from django.http import JsonResponse from django.shortcuts import render from django.views.decorators.http import require_http_methods from rest_framework import generics from rest_framework import status from rest_framework.response import Response from . import _common_versions from . import _hash_versions from . import _projects_versions from . import regex_mr from .. import serializers from ..conf import settings from ..forms.docker import BuildDockerForm from ..models import DockerImage from ..models import DockerTag from ..models import Project from ..tasks import docker_fetch_all from ..tasks import docker_fetch_project from ..tasks import docker_remove_tag from ..utils import docker logger = structlog.get_logger(__name__) def _get_docker_tags(project, tag=None): repos = docker.get_docker_repositories() r = re.compile(f".*{project}.*") project_repos = filter(r.match, repos) logger.debug(f"{project}: {project_repos}") docker_tags = [] for image in project_repos: res = {"name": image} tags = docker.get_docker_tags(image) if tag: logger.debug(f"non filtered tags: {tags}") tags = filter(re.compile(tag).match, tags) res["tags"] = tags docker_tags.append(res) logger.debug(f"docker_tags: {docker_tags}") return docker_tags def _build_docker_logic(form, projects): result = _hash_versions(form.cleaned_data, projects) context = {"projects": []} for pro in projects: try: logger.debug( "trying to trigger docker image at branch %s for project %s", result[pro], pro, ) url = docker.trigger_docker_build(pro, result[pro]) context["projects"].append({"name": pro, "url": url}) except KeyError: msg = f"Houston, we have a problem with trigger for {pro}" logger.error(msg) context["projects"].append({"name": pro, "url": None}) return context @login_required def build_docker_images(request): if request.method == "POST": form = BuildDockerForm(request.POST) if form.is_valid(): context = _build_docker_logic( form, settings.RELEASE_DASHBOARD_DOCKER_PROJECTS ) else: context = {"error": "form validation error"} return render(request, "release_dashboard/docker_result.html", context) else: context = { "projects": _projects_versions( settings.RELEASE_DASHBOARD_DOCKER_PROJECTS, regex_mr, False, True, True, ), "common_versions": {"tags": [], "branches": ["master"]}, "docker": True, } _common_versions(context, False, True) return render(request, "release_dashboard/build_docker.html", context) @login_required def refresh_all(request): if request.method == "POST": res = docker_fetch_all.delay() return JsonResponse({"url": "/flower/task/%s" % res.id}, status=201) else: template = "release_dashboard/refresh_docker.html" projects = [] for project in settings.RELEASE_DASHBOARD_DOCKER_PROJECTS: info = {"name": project, "tags": None} projects.append(info) return render(request, template, {"projects": projects}) @login_required @require_http_methods(["POST"]) def refresh(request, project): res = docker_fetch_project.delay(project) return JsonResponse({"url": "/flower/task/%s" % res.id}, status=201) @login_required @require_http_methods(["GET"]) def docker_images(request): images = DockerImage.objects.images_with_tags context = { "images": images, "URL_BASE": settings.DOCKER_REGISTRY_URL.format(""), } return render(request, "release_dashboard/docker_images.html", context) @login_required @require_http_methods(["GET"]) def docker_project_images(request, project): try: Project.objects.get(name=project) except Project.DoesNotExist: raise Http404("Project does not exist") images = DockerImage.objects.images_with_tags(project) context = { "images": images, "URL_BASE": settings.DOCKER_REGISTRY_URL.format(""), } return render(request, "release_dashboard/docker_images.html", context) @login_required @require_http_methods(["GET"]) def docker_image_tags(request, project, image): try: proj = Project.objects.get(name=project) image = DockerImage.objects.get(name=image, project=proj) except Project.DoesNotExist: raise Http404("Project does not exist") except DockerImage.DoesNotExist: raise Http404("Project does not exist") context = { "images": [image], "URL_BASE": settings.DOCKER_REGISTRY_URL.format(""), } return render(request, "release_dashboard/docker_image.html", context) class DockerImageList(generics.ListAPIView): queryset = DockerImage.objects.all() serializer_class = serializers.DockerImageSerializer class DockerImageDetail(generics.RetrieveDestroyAPIView): queryset = DockerImage.objects.all() serializer_class = serializers.DockerImageSerializer class DockerTagList(generics.ListAPIView): queryset = DockerTag.objects.all() serializer_class = serializers.DockerTagSerializer class DockerTagDetail(generics.RetrieveDestroyAPIView): queryset = DockerTag.objects.all() serializer_class = serializers.DockerTagSerializer def destroy(self, request, *args, **kwargs): instance = self.get_object() docker_remove_tag.delay(instance.image.name, instance.name) return Response(status=status.HTTP_202_ACCEPTED)