Commit 060a8b1d authored by Guilhem Saurel's avatar Guilhem Saurel
Browse files

Docker Image, DRY Project*View

parent 2a44c9ed
ARG TARGET
ARG REGISTRY=eur0c.laas.fr:4567
ARG FROM=gsaurel/buildfarm/robotpkg
FROM ${REGISTRY}/${FROM}:${TARGET}
ARG ROBOTPKG
ARG ROBOTPKG_DEPS=true
ARG ADDITIONAL_DEPENDENCIES=""
RUN /get_deps.sh robotpkg-${ROBOTPKG}
RUN apt-get update -qq && apt-get install -qqy \
$(sort -u /system_deps $(${ROBOTPKG_DEPS} && echo /robotpkg_deps)) \
${ADDITIONAL_DEPENDENCIES} \
&& rm -rf /var/lib/apt/lists/*
......@@ -24,8 +24,3 @@ You can then go to http://localhost:8000
## TODO
- fix urls (https://api.github.com/repos/stack-of-tasks/pinocchio)
- retrieve dependencies
- classify system / rpkg
- get their version depending on the target os
- dockerfile
- generic Vs. using dependencies
......@@ -158,3 +158,4 @@ LOGGING = {
RAINBOARD_DATA = Path('/srv/dashboard')
RAINBOARD_GITS = RAINBOARD_DATA / 'repositories'
RAINBOARD_RPKG = RAINBOARD_DATA / 'robotpkg'
REGISTRY = 'eur0c.laas.fr:4567'
# Generated by Django 2.0.2 on 2018-02-12 15:41
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('rainboard', '0002_forges_groups'),
]
operations = [
migrations.CreateModel(
name='Image',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('target', models.PositiveSmallIntegerField(choices=[(1, '14.04'), (2, '16.04'), (3, '17.10'), (4, '18.04'), (5, 'dubnium')])),
('created', models.DateTimeField(blank=True, null=True)),
('image', models.CharField(blank=True, max_length=12, null=True)),
('robotpkg', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='rainboard.Robotpkg')),
],
),
migrations.AlterUniqueTogether(
name='image',
unique_together={('robotpkg', 'target')},
),
]
import json
import logging
import re
from subprocess import check_output
from subprocess import check_output, CalledProcessError
from django.conf import settings
from django.db import models
......@@ -546,6 +547,11 @@ class Robotpkg(NamedModel):
with (cwd / 'DESCR').open() as f:
self.description = f.read().strip()
for target in TARGETS:
image, created = Image.objects.get_or_create(robotpkg=self, target=target)
if created:
image.update()
self.save()
......@@ -555,6 +561,45 @@ class RobotpkgBuild(TimeStampedModel):
passed = models.BooleanField(default=False)
class Image(models.Model):
robotpkg = models.ForeignKey(Robotpkg, on_delete=models.CASCADE)
target = models.PositiveSmallIntegerField(choices=enum_to_choices(TARGETS))
created = models.DateTimeField(blank=True, null=True)
image = models.CharField(max_length=12, blank=True, null=True)
class Meta:
unique_together = ('robotpkg', 'target')
def __str__(self):
return f'{self.robotpkg}-{self.get_target_display()}'
def get_build_args(self):
return {'TARGET': self.get_target_display(), 'ROBOTPKG': self.robotpkg}
def get_image_name(self):
project = self.robotpkg.project
return f'{settings.REGISTRY}/{project.main_namespace.slug}/{project}:{self.get_target_display()}'
def build(self):
args = self.get_build_args()
build_args = sum((['--build-arg', f'{key}={value}'] for key, value in args.items()), list())
cmd = ['docker', 'build', '-t', self.get_image_name()] + build_args + ['.']
return ' '.join(cmd)
def update(self):
image = check_output(['docker', 'images', '-q', self.get_image_name()]).decode().strip()
if not image:
try:
logger.info(f' pulling {self}')
check_output(['docker', 'pull', self.get_image_name()])
image = check_output(['docker', 'images', '-q', self.get_image_name()]).decode().strip()
except CalledProcessError:
return
self.image = image
self.created = parse_datetime(json.loads(check_output(['docker', 'inspect', image]))[0]['Created'])
self.save()
class CIBuild(models.Model):
repo = models.ForeignKey(Repo, on_delete=models.CASCADE)
passed = models.NullBooleanField()
......
......@@ -87,3 +87,9 @@ class BranchTable(StrippedTable):
# TODO: this works, but we have to hide the pinned from the main dataset
# def get_top_pinned_data(self):
# return self.data.data.filter(name__in=models.MAIN_BRANCHES)
class ImageTable(StrippedTable):
class Meta:
model = models.Image
fields = ('robotpkg', 'target', 'image', 'created')
......@@ -33,12 +33,25 @@
</div>
<ul class="nav nav-tabs">
<li role="presentation" {% if 'robotpkg' in request.path %}class="active"{% endif %}><a href="{% url 'rainboard:project' slug=project.slug %}">Robotpkg</a></h2></li>
<li role="presentation" {% if 'repos' in request.path %}class="active"{% endif %}><a href="{% url 'rainboard:project-repos' slug=project.slug %}">Repos</a></h2></li>
<li role="presentation" {% if 'robotpkg' in request.path %}class="active"{% endif %}><a href="{% url 'rainboard:project' slug=project.slug %}">Robotpkg</a></h2></li>
<li role="presentation" {% if 'repos' in request.path %}class="active"{% endif %}><a href="{% url 'rainboard:project-repos' slug=project.slug %}">Repos </a></h2></li>
<li role="presentation" {% if 'branches' in request.path %}class="active"{% endif %}><a href="{% url 'rainboard:project-branches' slug=project.slug %}">Branches</a></h2></li>
<li role="presentation" {% if 'images' in request.path %}class="active"{% endif %}><a href="{% url 'rainboard:project-images' slug=project.slug %}">Images </a></h2></li>
</ul>
{% block project_detail_content %}
{% if table %}
{% render_table table %}
{% if 'images' in request.path %}
<pre>
{% for image in object_list %}
{{ image.build }}
{% endfor %}
</pre>
{% endif %}
{% else %}
<h2>Robotpkg</h2>
{% for rpkg in project.robotpkg_set.all %}
......@@ -61,6 +74,6 @@
</dl>
{% endfor %}
{% endblock %}
{% endif %}
{% endblock %}
{% extends 'rainboard/project_detail.html' %}
{% load django_tables2 %}
{% block project_detail_content %}
{% render_table branches %}
{% endblock %}
{% extends 'rainboard/project_detail.html' %}
{% load django_tables2 %}
{% block project_detail_content %}
{% render_table repos %}
{% endblock %}
......@@ -14,4 +14,5 @@ urlpatterns = [
path('project/<str:slug>/robotpkg', views.ProjectView.as_view(), name='project'),
path('project/<str:slug>/repos', views.ProjectReposView.as_view(), name='project-repos'),
path('project/<str:slug>/branches', views.ProjectBranchesView.as_view(), name='project-branches'),
path('project/<str:slug>/images', views.ProjectImagesView.as_view(), name='project-images'),
]
......@@ -38,23 +38,36 @@ class ProjectView(DetailView):
model = models.Project
class ProjectReposView(ProjectView):
template_name = 'rainboard/project_detail_repos.html'
class ProjectTableView(ProjectView):
order_by = None
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
repos = tables.RepoTable(self.object.repo_set.all())
RequestConfig(self.request).configure(repos)
ctx['repos'] = repos
object_list = self.get_object_list()
table = self.table_class(object_list, order_by=self.order_by)
RequestConfig(self.request).configure(table)
ctx.update(table=table, object_list=object_list)
return ctx
class ProjectBranchesView(ProjectView):
template_name = 'rainboard/project_detail_branches.html'
class ProjectReposView(ProjectTableView):
table_class = tables.RepoTable
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
branches = tables.BranchTable(self.object.branch_set.all(), order_by='-updated')
RequestConfig(self.request).configure(branches)
ctx['branches'] = branches
return ctx
def get_object_list(self):
return self.object.repo_set.all()
class ProjectBranchesView(ProjectTableView):
table_class = tables.BranchTable
order_by = '-updated'
def get_object_list(self):
return self.object.branch_set.all()
class ProjectImagesView(ProjectTableView):
table_class = tables.ImageTable
order_by = 'target'
def get_object_list(self):
return models.Image.objects.filter(robotpkg__project=self.object)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment