Loading services/webapp/code/rosetta/core_app/api.py +38 −1 Original line number Original line Diff line number Diff line Loading @@ -11,7 +11,7 @@ from django.conf import settings from rest_framework.response import Response from rest_framework.response import Response from rest_framework import status, serializers, viewsets from rest_framework import status, serializers, viewsets from rest_framework.views import APIView 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 .models import Profile, Task, TaskStatuses, Computing, Storage, KeyPair from .exceptions import ConsistencyException from .exceptions import ConsistencyException import json import json Loading Loading @@ -1093,6 +1093,43 @@ class FileManagerAPI(PrivateGETAPI, PrivatePOSTAPI): return ok200('ok') 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 Original line Diff line number Diff line Loading @@ -20,8 +20,8 @@ <br/> <br/> {% if data.new_container_from == 'registry' %} {% 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.1em; 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: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;"> <hr style="margin-top:0;"> <h4>Basics</h4> <h4>Basics</h4> Loading Loading @@ -166,8 +166,8 @@ {% else %} {% 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.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.2em; background:whitesmoke; display:inline-block; padding:2px 15px 2px 15px">New container from Git repository</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;"> <hr style="margin-top:0;"> <h4>Basics</h4> <h4>Basics</h4> Loading Loading @@ -238,7 +238,7 @@ {% else %} {% 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 %} {% endif %} Loading services/webapp/code/rosetta/core_app/templates/import_repository.html 0 → 100644 +93 −0 Original line number Original line 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 Original line Diff line number Diff line Loading @@ -1005,11 +1005,14 @@ def add_software(request): elif new_container_from == 'repository': elif new_container_from == 'repository': container_description = request.POST.get('container_description', None) container_description = request.POST.get('container_description', None) repository_url = request.POST.get('repository_url', 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 # 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: else: raise Exception('Unknown new container mode "{}"'.format(new_container_from)) 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_tag = repository.split('/')[-1] repository_url = repository.replace('/'+repository_tag, '') 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['mode'] = 'new_task' #new container data['task_container'] = container # List all computing resources # Render the import page. This will call an API, and when the import is done, it data['computings'] = list(Computing.objects.filter(group=None)) + list(Computing.objects.filter(group__user=request.user)) # 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 Original line Diff line number Diff line Loading @@ -51,6 +51,7 @@ urlpatterns = [ # Software # Software url(r'^software/$', core_app_views.software), url(r'^software/$', core_app_views.software), url(r'^add_software/$', core_app_views.add_software), url(r'^add_software/$', core_app_views.add_software), url(r'^import_repository/$', core_app_views.import_repository), #Computing #Computing url(r'^computing/$', core_app_views.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/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/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/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 # Binder compatibility path('v2/git/<path:repository>', core_app_views.new_binder_task), 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 Original line Diff line number Diff line Loading @@ -11,7 +11,7 @@ from django.conf import settings from rest_framework.response import Response from rest_framework.response import Response from rest_framework import status, serializers, viewsets from rest_framework import status, serializers, viewsets from rest_framework.views import APIView 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 .models import Profile, Task, TaskStatuses, Computing, Storage, KeyPair from .exceptions import ConsistencyException from .exceptions import ConsistencyException import json import json Loading Loading @@ -1093,6 +1093,43 @@ class FileManagerAPI(PrivateGETAPI, PrivatePOSTAPI): return ok200('ok') 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 Original line Diff line number Diff line Loading @@ -20,8 +20,8 @@ <br/> <br/> {% if data.new_container_from == 'registry' %} {% 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.1em; 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: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;"> <hr style="margin-top:0;"> <h4>Basics</h4> <h4>Basics</h4> Loading Loading @@ -166,8 +166,8 @@ {% else %} {% 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.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.2em; background:whitesmoke; display:inline-block; padding:2px 15px 2px 15px">New container from Git repository</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;"> <hr style="margin-top:0;"> <h4>Basics</h4> <h4>Basics</h4> Loading Loading @@ -238,7 +238,7 @@ {% else %} {% 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 %} {% endif %} Loading
services/webapp/code/rosetta/core_app/templates/import_repository.html 0 → 100644 +93 −0 Original line number Original line 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 Original line Diff line number Diff line Loading @@ -1005,11 +1005,14 @@ def add_software(request): elif new_container_from == 'repository': elif new_container_from == 'repository': container_description = request.POST.get('container_description', None) container_description = request.POST.get('container_description', None) repository_url = request.POST.get('repository_url', 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 # 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: else: raise Exception('Unknown new container mode "{}"'.format(new_container_from)) 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_tag = repository.split('/')[-1] repository_url = repository.replace('/'+repository_tag, '') 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['mode'] = 'new_task' #new container data['task_container'] = container # List all computing resources # Render the import page. This will call an API, and when the import is done, it data['computings'] = list(Computing.objects.filter(group=None)) + list(Computing.objects.filter(group__user=request.user)) # 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 Original line Diff line number Diff line Loading @@ -51,6 +51,7 @@ urlpatterns = [ # Software # Software url(r'^software/$', core_app_views.software), url(r'^software/$', core_app_views.software), url(r'^add_software/$', core_app_views.add_software), url(r'^add_software/$', core_app_views.add_software), url(r'^import_repository/$', core_app_views.import_repository), #Computing #Computing url(r'^computing/$', core_app_views.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/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/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/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 # Binder compatibility path('v2/git/<path:repository>', core_app_views.new_binder_task), path('v2/git/<path:repository>', core_app_views.new_binder_task), Loading