diff --git a/services/webapp/code/rosetta/core_app/api.py b/services/webapp/code/rosetta/core_app/api.py index 70fb7fddc3d469c1bcea5ba542fbcc139374bef4..4953ac0e074c4212d465927e708ffbb4af0d7048 100644 --- a/services/webapp/code/rosetta/core_app/api.py +++ b/services/webapp/code/rosetta/core_app/api.py @@ -11,7 +11,7 @@ from django.conf import settings from rest_framework.response import Response from rest_framework import status, serializers, viewsets from rest_framework.views import APIView -from .utils import format_exception, send_email, os_shell, now_t, get_ssh_access_mode_credentials +from .utils import format_exception, send_email, os_shell, now_t, get_ssh_access_mode_credentials, get_or_create_container_from_repository from .models import Profile, Task, TaskStatuses, Computing, Storage, KeyPair from .exceptions import ConsistencyException import json @@ -1093,6 +1093,43 @@ class FileManagerAPI(PrivateGETAPI, PrivatePOSTAPI): return ok200('ok') +#============================== +# Import repository APIs +#============================== + +class ImportRepositoryAPI(PrivateGETAPI): + """ + get: + Import a repository as a container and get the container uuid. + + """ + + def _get(self, request): + + repository_url = request.GET.get('repository_url', None) + repository_tag = request.GET.get('repository_tag', None) + container_name = request.GET.get('container_name', None) + container_description = request.GET.get('container_description', None) + + if not repository_url: + return error400('Missing "repository_url"') + + if not repository_tag: + return error400('Missing "repository_tag"') + + logger.debug('Importing repository "%s" with tag "%s"', repository_url, repository_tag) + + results = {} + try: + container = get_or_create_container_from_repository(request.user, repository_url, repository_tag, container_name, container_description) + except Exception as e: + results['import_succeded'] = False + results['error_message'] = str(e) + else: + results['import_succeded'] = True + results['container_uuid'] = str(container.uuid) + + return ok200(results) diff --git a/services/webapp/code/rosetta/core_app/templates/add_software.html b/services/webapp/code/rosetta/core_app/templates/add_software.html index 6a0df40268b025878c07aae541cd7569fd34cddb..afebe908314a5fc506d8ad93e2638a65d7b219cd 100644 --- a/services/webapp/code/rosetta/core_app/templates/add_software.html +++ b/services/webapp/code/rosetta/core_app/templates/add_software.html @@ -20,8 +20,8 @@ <br/> {% if data.new_container_from == 'registry' %} - <div style="font-size:1.2em; background:whitesmoke; display:inline-block; padding:2px 15px 2px 15px">New container from registry</div> - <div style="font-size:1.2em; background:white; display:inline-block; padding:2px 15px 2px 15px"><a href="?new_container_from=repository">New container from Git repository</a></div> + <div style="font-size:1.1em; background:whitesmoke; display:inline-block; padding:2px 15px 2px 15px">New container from registry</div> + <div style="font-size:1.1em; background:white; display:inline-block; padding:2px 15px 2px 15px"><a href="?new_container_from=repository">New container from Git repository</a></div> <hr style="margin-top:0;"> <h4>Basics</h4> @@ -166,8 +166,8 @@ {% else %} - <div style="font-size:1.2em; background:white; display:inline-block; padding:2px 15px 2px 15px"><a href="?new_container_from=registry">New container from registry</a></div> - <div style="font-size:1.2em; background:whitesmoke; display:inline-block; padding:2px 15px 2px 15px">New container from Git repository</div> + <div style="font-size:1.1em; background:white; display:inline-block; padding:2px 15px 2px 15px"><a href="?new_container_from=registry">New container from registry</a></div> + <div style="font-size:1.1em; background:whitesmoke; display:inline-block; padding:2px 15px 2px 15px">New container from Git repository</div> <hr style="margin-top:0;"> <h4>Basics</h4> @@ -238,7 +238,7 @@ {% else %} - Ok, software container added. Go back to <a href="/software">software</a>. + Ok, software container added. Go to <a href="/software">software</a>. {% endif %} diff --git a/services/webapp/code/rosetta/core_app/templates/import_repository.html b/services/webapp/code/rosetta/core_app/templates/import_repository.html new file mode 100644 index 0000000000000000000000000000000000000000..ae4ee313418842fa975fa5d743ef0b92e1446601 --- /dev/null +++ b/services/webapp/code/rosetta/core_app/templates/import_repository.html @@ -0,0 +1,93 @@ +{% load static %} +{% include "header.html" %} +{% include "navigation.html" %} + +<br/> +<br/> + +<div class="container"> + <div class="dashboard"> + <div class="span8 offset2"> + {% if data.mode == 'new_task' %} + <h1>New Task</h1> + {% elif data.mode == 'new_container' %} + <h1>Add software container</h1> + {% else %} + <h1>Importing repository</h1> + {% endif %} + <hr> + + <div id="importing"> + Importing repository <code>{{ data.repository_url }}</code>... + <br> + <br> + <br> + <br> + <center><img src="/static/img/ajax-loader.gif"></center> + </div> + + <div id="import_succeded" style="display:none"> + Ok, software container added. Go to <a href="/software">software</a>. + </div> + + + <div id="import_failed" style="display:none"> + FAILED: <span id="import_failed_text"></span> + </div> + + <script type="text/javascript"> + var apiUrl = '/api/v1/import_repository/?repository_url={{data.repository_url}}&repository_tag={{data.repository_tag}}&container_name={{data.container_name}}&container_description={{data.container_description}}'; + fetch(apiUrl).then(response => { + console.log(response) + if (response.status != 200){ + // Throw the error catched below + throw response.statusText; + } + return response.json(); + }).then(data => { + // Work with JSON data here + console.log(data) + + if (data.results.import_succeded){ + + // Terrbile django templating mixed with javascript + {% if data.mode == 'new_task' %} + + window.location.replace("/new_task/?step=two&task_container_uuid="+data.results.container_uuid) + + {% else %} + + $("#importing").hide(); + $("#import_succeded").show(); + + {% endif %} + + } else { + throw data.results.error_message + } + + }).catch(error => { + // Do something for an error here + console.log(error) + $("#importing").hide(); + $("#import_failed").show(); + $("#import_failed_text").html(error); + }); + </script> + + </div> + </div> +</div> +<br/> +<br/> +<br/> +<br/> +<br/> +<br/> +{% include "footer.html" %} + + + + + + diff --git a/services/webapp/code/rosetta/core_app/views.py b/services/webapp/code/rosetta/core_app/views.py index 2082ee51a62a528cf5fa03acdc0d1a8ccc93bacc..13191ccbba9cc086ee3f53c9a74aa3366ae02734 100644 --- a/services/webapp/code/rosetta/core_app/views.py +++ b/services/webapp/code/rosetta/core_app/views.py @@ -1005,11 +1005,14 @@ def add_software(request): elif new_container_from == 'repository': container_description = request.POST.get('container_description', None) - repository_url = request.POST.get('repository_url', None) - repository_tag = request.POST.get('repository_tag', None) + repository_url = request.POST.get('repository_url', None) + repository_tag = request.POST.get('repository_tag', 'HEAD') + + return HttpResponseRedirect('/import_repository/?repository_url={}&repository_tag={}&container_name={}&container_description={}'.format(repository_url,repository_tag,container_name,container_description)) + # The return type here is a container, not created - get_or_create_container_from_repository(request.user, repository_url, repository_tag=repository_tag, container_name=container_name, container_description=container_description) + #get_or_create_container_from_repository(request.user, repository_url, repository_tag=repository_tag, container_name=container_name, container_description=container_description) else: raise Exception('Unknown new container mode "{}"'.format(new_container_from)) @@ -1216,21 +1219,39 @@ def new_binder_task(request, repository): # Set repository name/tag/url repository_tag = repository.split('/')[-1] repository_url = repository.replace('/'+repository_tag, '') - - container = get_or_create_container_from_repository(request.user, repository_url, repository_tag) - # Set the container - data['task_container'] = container + data['repository_url'] = repository_url + data['repository_tag'] = repository_tag + + data['mode'] = 'new_task' #new container - # List all computing resources - data['computings'] = list(Computing.objects.filter(group=None)) + list(Computing.objects.filter(group__user=request.user)) - - data['step'] = 'two' - data['next_step'] = 'three' + # Render the import page. This will call an API, and when the import is done, it + # will automatically redirect to the page "new_task/?step=two&task_container_uuid=..." + return render(request, 'import_repository.html', {'data': data}) - # Render the new task page and handle the rest from there - return render(request, 'new_task.html', {'data': data}) +#========================= +# Import repository +#========================= + +@private_view +def import_repository(request): + + # Init data + data={} + data['user'] = request.user + + data['repository_url'] = request.GET.get('repository_url', None) + data['repository_tag'] = request.GET.get('repository_tag', 'HEAD') + if not data['repository_tag']: + data['repository_tag']='HEAD' + + data['container_name'] = request.GET.get('container_name', None) + data['container_description'] = request.GET.get('container_description', None) + data['mode'] = 'new_container' + # Render the import page. This will call an API, and when the import is done, it + # will automatically say "Ok, crrated, go to software". + return render(request, 'import_repository.html', {'data': data}) diff --git a/services/webapp/code/rosetta/urls.py b/services/webapp/code/rosetta/urls.py index ed69eb3208789fb77c066dd8c2a2465867846e75..cfb187e334182403257dd90eabc9948a85d08024 100644 --- a/services/webapp/code/rosetta/urls.py +++ b/services/webapp/code/rosetta/urls.py @@ -51,6 +51,7 @@ urlpatterns = [ # Software url(r'^software/$', core_app_views.software), url(r'^add_software/$', core_app_views.add_software), + url(r'^import_repository/$', core_app_views.import_repository), #Computing url(r'^computing/$', core_app_views.computing), @@ -84,6 +85,7 @@ urlpatterns = [ path('api/v1/base/logout/', core_app_api.logout_api.as_view(), name='logout_api'), path('api/v1/base/agent/', core_app_api.agent_api.as_view(), name='agent_api'), path('api/v1/filemanager/', core_app_api.FileManagerAPI.as_view(), name='filemanager_api'), + path('api/v1/import_repository/', core_app_api.ImportRepositoryAPI.as_view(), name='import_repository_api'), # Binder compatibility path('v2/git/<path:repository>', core_app_views.new_binder_task),