Loading services/webapp/code/rosetta/core_app/api.py +38 −1 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) Loading services/webapp/code/rosetta/core_app/templates/add_software.html +5 −5 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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> Loading Loading @@ -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 %} Loading services/webapp/code/rosetta/core_app/templates/import_repository.html 0 → 100644 +93 −0 Original line number Diff line number Diff line {% 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" %} services/webapp/code/rosetta/core_app/views.py +35 −14 Original line number Diff line number Diff line Loading @@ -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_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)) Loading Loading @@ -1217,20 +1220,38 @@ def new_binder_task(request, repository): repository_tag = repository.split('/')[-1] repository_url = repository.replace('/'+repository_tag, '') container = get_or_create_container_from_repository(request.user, repository_url, repository_tag) data['repository_url'] = repository_url data['repository_tag'] = repository_tag # Set the container data['task_container'] = container 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)) # 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}) data['step'] = 'two' data['next_step'] = 'three' # 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}) services/webapp/code/rosetta/urls.py +2 −0 Original line number Diff line number Diff line Loading @@ -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), Loading Loading @@ -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), Loading Loading
services/webapp/code/rosetta/core_app/api.py +38 −1 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) Loading
services/webapp/code/rosetta/core_app/templates/add_software.html +5 −5 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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> Loading Loading @@ -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 %} Loading
services/webapp/code/rosetta/core_app/templates/import_repository.html 0 → 100644 +93 −0 Original line number Diff line number Diff line {% 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" %}
services/webapp/code/rosetta/core_app/views.py +35 −14 Original line number Diff line number Diff line Loading @@ -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_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)) Loading Loading @@ -1217,20 +1220,38 @@ def new_binder_task(request, repository): repository_tag = repository.split('/')[-1] repository_url = repository.replace('/'+repository_tag, '') container = get_or_create_container_from_repository(request.user, repository_url, repository_tag) data['repository_url'] = repository_url data['repository_tag'] = repository_tag # Set the container data['task_container'] = container 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)) # 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}) data['step'] = 'two' data['next_step'] = 'three' # 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})
services/webapp/code/rosetta/urls.py +2 −0 Original line number Diff line number Diff line Loading @@ -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), Loading Loading @@ -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), Loading