bitbake: toaster: api Add layer Add api
Add layer adding REST api and remove old views method. (Bitbake rev: 0c8e41d2217fd568a84e857d1be230fcfd4bb5c7) Signed-off-by: Michael Wood <michael.g.wood@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
parent
90d995c637
commit
7e80e501fb
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import logging
|
import logging
|
||||||
|
import json
|
||||||
from collections import Counter
|
from collections import Counter
|
||||||
|
|
||||||
from orm.models import Project, ProjectTarget, Build, Layer_Version
|
from orm.models import Project, ProjectTarget, Build, Layer_Version
|
||||||
|
@ -136,14 +137,17 @@ class XhrBuildRequest(View):
|
||||||
|
|
||||||
|
|
||||||
class XhrLayer(View):
|
class XhrLayer(View):
|
||||||
""" Get and Update Layer information """
|
""" Delete, Get, Add and Update Layer information
|
||||||
|
|
||||||
|
Methods: POST DELETE PUT
|
||||||
|
"""
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Update a layer
|
Update a layer
|
||||||
|
|
||||||
Entry point: /xhr_layer/<layerversion_id>
|
|
||||||
Method: POST
|
Method: POST
|
||||||
|
Entry point: /xhr_layer/<layerversion_id>
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
vcs_url, dirpath, commit, up_branch, summary, description,
|
vcs_url, dirpath, commit, up_branch, summary, description,
|
||||||
|
@ -201,9 +205,100 @@ class XhrLayer(View):
|
||||||
return error_response("Could not update layer version entry: %s"
|
return error_response("Could not update layer version entry: %s"
|
||||||
% e)
|
% e)
|
||||||
|
|
||||||
return JsonResponse({"error": "ok"})
|
return error_response("ok")
|
||||||
|
|
||||||
|
def put(self, request, *args, **kwargs):
|
||||||
|
""" Add a new layer
|
||||||
|
|
||||||
|
Method: PUT
|
||||||
|
Entry point: /xhr_layer/
|
||||||
|
Args:
|
||||||
|
project_id, name,
|
||||||
|
[vcs_url, dir_path, git_ref], [local_source_dir], [layer_deps
|
||||||
|
(csv)]
|
||||||
|
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
project = Project.objects.get(pk=kwargs['pid'])
|
||||||
|
|
||||||
|
layer_data = json.loads(request.body.decode('utf-8'))
|
||||||
|
|
||||||
|
# We require a unique layer name as otherwise the lists of layers
|
||||||
|
# becomes very confusing
|
||||||
|
existing_layers = \
|
||||||
|
project.get_all_compatible_layer_versions().values_list(
|
||||||
|
"layer__name",
|
||||||
|
flat=True)
|
||||||
|
|
||||||
|
add_to_project = False
|
||||||
|
layer_deps_added = []
|
||||||
|
if 'add_to_project' in layer_data:
|
||||||
|
add_to_project = True
|
||||||
|
|
||||||
|
if layer_data['name'] in existing_layers:
|
||||||
|
return JsonResponse({"error": "layer-name-exists"})
|
||||||
|
|
||||||
|
layer = Layer.objects.create(name=layer_data['name'])
|
||||||
|
|
||||||
|
layer_version = Layer_Version.objects.create(
|
||||||
|
layer=layer,
|
||||||
|
project=project,
|
||||||
|
layer_source=LayerSource.TYPE_IMPORTED)
|
||||||
|
|
||||||
|
# Local layer
|
||||||
|
if 'local_source_dir' in layer_data:
|
||||||
|
layer.local_source_dir = layer_data['local_source_dir']
|
||||||
|
# git layer
|
||||||
|
elif 'vcs_url' in layer_data:
|
||||||
|
layer.vcs_url = layer_data['vcs_url']
|
||||||
|
layer_version.dirpath = layer_data['dir_path']
|
||||||
|
layer_version.commit = layer_data['get_ref']
|
||||||
|
layer_version.branch = layer_data['get_ref']
|
||||||
|
|
||||||
|
layer.save()
|
||||||
|
layer_version.save()
|
||||||
|
|
||||||
|
if add_to_project:
|
||||||
|
ProjectLayer.objects.get_or_create(
|
||||||
|
layercommit=layer_version, project=project)
|
||||||
|
|
||||||
|
# Add the layer dependencies
|
||||||
|
if 'layer_deps' in layer_data:
|
||||||
|
for layer_dep_id in layer_data['layer_deps'].split(","):
|
||||||
|
layer_dep = Layer_Version.objects.get(pk=layer_dep_id)
|
||||||
|
LayerVersionDependency.objects.get_or_create(
|
||||||
|
layer_version=layer_version, depends_on=layer_dep)
|
||||||
|
|
||||||
|
# Add layer deps to the project if specified
|
||||||
|
if add_to_project:
|
||||||
|
created, pl = ProjectLayer.objects.get_or_create(
|
||||||
|
layercommit=layer_dep, project=project)
|
||||||
|
layer_deps_added.append(
|
||||||
|
{'name': layer_dep.layer.name,
|
||||||
|
'layerdetailurl':
|
||||||
|
layer_dep.get_detailspage_url(project.pk)})
|
||||||
|
|
||||||
|
except Layer_Version.DoesNotExist:
|
||||||
|
return error_response("layer-dep-not-found")
|
||||||
|
except Project.DoesNotExist:
|
||||||
|
return error_response("project-not-found")
|
||||||
|
except KeyError:
|
||||||
|
return error_response("incorrect-parameters")
|
||||||
|
|
||||||
|
return JsonResponse({'error': "ok",
|
||||||
|
'imported_layer': {
|
||||||
|
'name': layer.name,
|
||||||
|
'layerdetailurl':
|
||||||
|
layer_version.get_detailspage_url()},
|
||||||
|
'deps_added': layer_deps_added})
|
||||||
|
|
||||||
def delete(self, request, *args, **kwargs):
|
def delete(self, request, *args, **kwargs):
|
||||||
|
""" Delete an imported layer
|
||||||
|
|
||||||
|
Method: DELETE
|
||||||
|
Entry point: /xhr_layer/<layerversion_id>
|
||||||
|
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
# We currently only allow Imported layers to be deleted
|
# We currently only allow Imported layers to be deleted
|
||||||
layer_version = Layer_Version.objects.get(
|
layer_version = Layer_Version.objects.get(
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function (){
|
$(document).ready(function (){
|
||||||
var ctx = {
|
var ctx = {
|
||||||
xhrImportLayerUrl : "{% url 'xhr_importlayer' %}",
|
xhrLayerUrl : "{% url 'xhr_layer' project.id %}",
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -190,12 +190,14 @@ urlpatterns = patterns('toastergui.views',
|
||||||
url(r'^xhr_configvaredit/(?P<pid>\d+)$', 'xhr_configvaredit',
|
url(r'^xhr_configvaredit/(?P<pid>\d+)$', 'xhr_configvaredit',
|
||||||
name='xhr_configvaredit'),
|
name='xhr_configvaredit'),
|
||||||
|
|
||||||
url(r'^xhr_importlayer/$', 'xhr_importlayer', name='xhr_importlayer'),
|
|
||||||
|
|
||||||
url(r'^xhr_layer/(?P<pid>\d+)/(?P<layerversion_id>\d+)$',
|
url(r'^xhr_layer/(?P<pid>\d+)/(?P<layerversion_id>\d+)$',
|
||||||
api.XhrLayer.as_view(),
|
api.XhrLayer.as_view(),
|
||||||
name='xhr_layer'),
|
name='xhr_layer'),
|
||||||
|
|
||||||
|
url(r'^xhr_layer/(?P<pid>\d+)$',
|
||||||
|
api.XhrLayer.as_view(),
|
||||||
|
name='xhr_layer'),
|
||||||
|
|
||||||
# JS Unit tests
|
# JS Unit tests
|
||||||
url(r'^js-unit-tests/$', 'jsunittests', name='js-unit-tests'),
|
url(r'^js-unit-tests/$', 'jsunittests', name='js-unit-tests'),
|
||||||
|
|
||||||
|
|
|
@ -1509,121 +1509,6 @@ if True:
|
||||||
return HttpResponse(json.dumps({"error":str(e) + "\n" + traceback.format_exc()}), content_type = "application/json")
|
return HttpResponse(json.dumps({"error":str(e) + "\n" + traceback.format_exc()}), content_type = "application/json")
|
||||||
|
|
||||||
|
|
||||||
def xhr_importlayer(request):
|
|
||||||
if ('vcs_url' not in request.POST or
|
|
||||||
'name' not in request.POST or
|
|
||||||
'git_ref' not in request.POST or
|
|
||||||
'project_id' not in request.POST):
|
|
||||||
return HttpResponse(jsonfilter({"error": "Missing parameters; requires vcs_url, name, git_ref and project_id"}), content_type = "application/json")
|
|
||||||
|
|
||||||
layers_added = [];
|
|
||||||
|
|
||||||
# Rudimentary check for any possible html tags
|
|
||||||
for val in request.POST.values():
|
|
||||||
if "<" in val:
|
|
||||||
return HttpResponse(jsonfilter(
|
|
||||||
{"error": "Invalid character <"}),
|
|
||||||
content_type="application/json")
|
|
||||||
|
|
||||||
prj = Project.objects.get(pk=request.POST['project_id'])
|
|
||||||
|
|
||||||
# Strip trailing/leading whitespace from all values
|
|
||||||
# put into a new dict because POST one is immutable.
|
|
||||||
post_data = dict()
|
|
||||||
for key,val in request.POST.items():
|
|
||||||
post_data[key] = val.strip()
|
|
||||||
|
|
||||||
|
|
||||||
try:
|
|
||||||
layer, layer_created = Layer.objects.get_or_create(name=post_data['name'])
|
|
||||||
except MultipleObjectsReturned:
|
|
||||||
return HttpResponse(jsonfilter({"error": "hint-layer-exists"}), content_type = "application/json")
|
|
||||||
|
|
||||||
if layer:
|
|
||||||
if layer_created:
|
|
||||||
layer.vcs_url = post_data.get('vcs_url')
|
|
||||||
layer.local_source_dir = post_data.get('local_source_dir')
|
|
||||||
layer.up_date = timezone.now()
|
|
||||||
layer.save()
|
|
||||||
else:
|
|
||||||
# We have an existing layer by this name, let's see if the git
|
|
||||||
# url is the same, if it is then we can just create a new layer
|
|
||||||
# version for this layer. Otherwise we need to bail out.
|
|
||||||
if layer.vcs_url != post_data['vcs_url']:
|
|
||||||
return HttpResponse(jsonfilter({"error": "hint-layer-exists-with-different-url" , "current_url" : layer.vcs_url, "current_id": layer.id }), content_type = "application/json")
|
|
||||||
|
|
||||||
layer_version, version_created = \
|
|
||||||
Layer_Version.objects.get_or_create(
|
|
||||||
layer_source=LayerSource.TYPE_IMPORTED,
|
|
||||||
layer=layer, project=prj,
|
|
||||||
release=prj.release,
|
|
||||||
branch=post_data['git_ref'],
|
|
||||||
commit=post_data['git_ref'],
|
|
||||||
dirpath=post_data['dir_path'])
|
|
||||||
|
|
||||||
if layer_version:
|
|
||||||
if not version_created:
|
|
||||||
return HttpResponse(jsonfilter({"error":
|
|
||||||
"hint-layer-version-exists",
|
|
||||||
"existing_layer_version":
|
|
||||||
layer_version.id }),
|
|
||||||
content_type = "application/json")
|
|
||||||
|
|
||||||
layer_version.layer_source = LayerSource.TYPE_IMPORTED
|
|
||||||
|
|
||||||
layer_version.up_date = timezone.now()
|
|
||||||
layer_version.save()
|
|
||||||
|
|
||||||
# Add the dependencies specified for this new layer
|
|
||||||
if ('layer_deps' in post_data and
|
|
||||||
version_created and
|
|
||||||
len(post_data["layer_deps"]) > 0):
|
|
||||||
for layer_dep_id in post_data["layer_deps"].split(","):
|
|
||||||
|
|
||||||
layer_dep_obj = Layer_Version.objects.get(pk=layer_dep_id)
|
|
||||||
LayerVersionDependency.objects.get_or_create(layer_version=layer_version, depends_on=layer_dep_obj)
|
|
||||||
# Now add them to the project, we could get an execption
|
|
||||||
# if the project now contains the exact
|
|
||||||
# dependency already (like modified on another page)
|
|
||||||
try:
|
|
||||||
prj_layer, prj_layer_created = ProjectLayer.objects.get_or_create(layercommit=layer_dep_obj, project=prj)
|
|
||||||
except IntegrityError as e:
|
|
||||||
logger.warning("Integrity error while saving Project Layers: %s (original %s)" % (e, e.__cause__))
|
|
||||||
continue
|
|
||||||
|
|
||||||
if prj_layer_created:
|
|
||||||
layerdepdetailurl = reverse('layerdetails', args=(prj.id, layer_dep_obj.pk))
|
|
||||||
layers_added.append({'id': layer_dep_obj.id, 'name': Layer.objects.get(id=layer_dep_obj.layer_id).name, 'layerdetailurl': layerdepdetailurl })
|
|
||||||
|
|
||||||
|
|
||||||
# If an old layer version exists in our project then remove it
|
|
||||||
for prj_layers in ProjectLayer.objects.filter(project=prj):
|
|
||||||
dup_layer_v = Layer_Version.objects.filter(id=prj_layers.layercommit_id, layer_id=layer.id)
|
|
||||||
if len(dup_layer_v) >0 :
|
|
||||||
prj_layers.delete()
|
|
||||||
|
|
||||||
# finally add the imported layer (version id) to the project
|
|
||||||
ProjectLayer.objects.create(layercommit=layer_version, project=prj,optional=1)
|
|
||||||
|
|
||||||
else:
|
|
||||||
# We didn't create a layer version so back out now and clean up.
|
|
||||||
if layer_created:
|
|
||||||
layer.delete()
|
|
||||||
|
|
||||||
return HttpResponse(jsonfilter({"error": "Uncaught error: Could not create layer version"}), content_type = "application/json")
|
|
||||||
|
|
||||||
layerdetailurl = reverse('layerdetails', args=(prj.id, layer_version.pk))
|
|
||||||
|
|
||||||
json_response = {"error": "ok",
|
|
||||||
"imported_layer" : {
|
|
||||||
"name" : layer.name,
|
|
||||||
"id": layer_version.id,
|
|
||||||
"layerdetailurl": layerdetailurl,
|
|
||||||
},
|
|
||||||
"deps_added": layers_added }
|
|
||||||
|
|
||||||
return HttpResponse(jsonfilter(json_response), content_type = "application/json")
|
|
||||||
|
|
||||||
def customrecipe_download(request, pid, recipe_id):
|
def customrecipe_download(request, pid, recipe_id):
|
||||||
recipe = get_object_or_404(CustomImageRecipe, pk=recipe_id)
|
recipe = get_object_or_404(CustomImageRecipe, pk=recipe_id)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue