Commit 84d139e8 authored by Georgios Ouzounis's avatar Georgios Ouzounis
Browse files

Merge pull request #272 from ioantsaf/app-upload

[Bug 8] Application upload improvements
parents 27ec75c8 6e552206
......@@ -276,11 +276,6 @@ class ApplicationViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
if not uploaded_file:
raise CustomParseError(CustomParseError.messages['no_file_error'])
# Check if another file with same name already exists.
if self.get_queryset().filter(name=uploaded_file.name).count() > 0:
raise CustomParseError(CustomParseError
.messages['filename_already_exists_error'])
# Get the description provided with the request.
description = request.data.get('description', '')
......@@ -306,6 +301,12 @@ class ApplicationViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
chosen_project = [project for project in user_projects
if project['name'] == project_name][0]
# Check if another file with same name, in the same project, already exists
if self.get_queryset().filter(name=uploaded_file.name,
project_id=chosen_project['id']).count() > 0:
raise CustomParseError(CustomParseError
.messages['filename_already_exists_error'])
# Generate a uuid for the uploaded application.
application_uuid = uuid.uuid4()
......
......@@ -132,6 +132,66 @@
</table>
</div>
<!--col-xs-12-->
<!-- About The Application -->
<div class="col-md-4 pull-right">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title"><i class="fa fa-bullhorn"></i> About The Application</h3>
<span style='margin-left:10px;'>
{{#if (compare model.application.status_message "===" "UPLOADING")}}
<i class="fa fa-circle text-danger "></i>
{{/if}}
{{#if (compare model.application.status_message "===" "FAILED")}}
<i class="fa fa-circle text-warning "></i>
{{/if}}
{{#if (compare model.application.status_message "===" "UPLOADED")}}
<i class="fa fa-circle text-success "></i>
{{/if}}
{{model.application.status_message}}
</span>
</div>
<!-- /.box-header -->
<div class="box-body">
<strong><i class="fa fa-pencil margin-r-5"></i> Status</strong>
<p>
<ul class="timeline">
<!-- timeline time label -->
<li class="time-label">
{{#if (compare model.application.status_message "===" "UPLOADING")}}
<span class="bg-orange">Status: {{model.application.status_message}}</span>
<div class="spinner-loader" style="position: relative;top:0;bottom: 0;left: 15%;right: 0;margin: auto;"></div>
{{/if}}
{{#if (compare model.application.status_message "===" "FAILED")}}
<span class="bg-red">Status: {{model.application.status_message}}</span>
{{/if}}
{{#if (compare model.application.status_message "===" "UPLOADED")}}
<span class="bg-green">Status: {{model.application.status_message}}</span>
{{/if}}
</li>
<li>
<i class="fa fa-clock-o bg-gray"></i>
<div class="timeline-item">
<span class="time"><i class="fa fa-clock-o"></i> Now </span>
<h3 class="timeline-header"><strong>{{model.application.status_message}}</strong> </h3>
<div class="timeline-body">{{model.application.status_detail}}</div> <!-- class="timeline-body"-->
</div> <!-- class="timeline-item" -->
</li>
</ul>
</p>
<strong><i class="fa fa-file-text-o margin-r-5"></i> Notes</strong>
{{#if (compare model.application.status_message "===" "UPLOADING")}}
<p>Your lambda application is being uploaded. Please wait...</p>
{{/if}}
{{#if (compare model.application.status_message "===" "FAILED")}}
<p>Your lambda application upload has failed. You can delete it an try uploading it again.</p>
{{/if}}
{{#if (compare model.application.status_message "===" "UPLOADED")}}
<p>Your lambda application has been uploaded. You can deploy it on a lambda instance.</p>
{{/if}}
</div> <!-- /.box-body -->
</div><!-- /.box -->
</div> <!--col-md-3 pull-right -->
<!-- About The Application -->
</div>
<!--row-->
</div>
......
......@@ -96,7 +96,19 @@
{{lambda-application.name}}
{{/link-to}}
</td>
<td>{{lambda-application.status_detail}}</td>
<td>
{{#if (compare lambda-application.status_message "===" "UPLOADING")}}
<span style="font-size: .9em;" class="label bg-orange">{{lambda-application.status_detail}}
<i class="fa fa-spinner fa-spin" style="position: relative;left: 1%;"></i>
</span>
{{/if}}
{{#if (compare lambda-application.status_message "===" "FAILED")}}
<span style="font-size: .9em;" class="label bg-red">{{lambda-application.status_detail}}</span>
{{/if}}
{{#if (compare lambda-application.status_message "===" "UPLOADED")}}
<span style="font-size: .9em;" class="label bg-green">{{lambda-application.status_detail}}</span>
{{/if}}
</td>
<td>{{lower-case lambda-application.app_type}}</td>
......
......@@ -38,11 +38,13 @@ class TestApplicationUpload(APITestCase):
application_type_streaming = "streaming"
# project_name
project_name = "lambda.grnet.gr"
# project_id
project_id = uuid.uuid4()
# execution_environment_name
execution_environment_name = "Stream"
user_projects = [
{'name': "lambda.grnet.gr", 'id': uuid.uuid4()},
{'name': "lambda.grnet.gr", 'id': project_id},
{'name': "project_1", 'id': uuid.uuid4()},
{'name': "project_2", 'id': uuid.uuid4()},
{'name': "project_3", 'id': uuid.uuid4()},
......@@ -108,11 +110,15 @@ class TestApplicationUpload(APITestCase):
application_id, self.application.name, self.application_description)
# Test for uploading an application when all the required information are provided
# but there is already an application with the same name uploaded.
def test_existent_name(self):
# but there is already an application with the same name, in the same project uploaded
@mock.patch('backend.views.get_user_okeanos_projects')
def test_existent_name_on_same_project(self, mock_get_user_okeanos_projects):
# Configure return values for mocks
mock_get_user_okeanos_projects.return_value = self.user_projects
# Create an application on the database.
Application.objects.create(uuid=uuid.uuid4(), name="existing_application.jar",
type=Application.BATCH)
type=Application.BATCH, project_id=self.project_id)
# file
existing_application = SimpleUploadedFile("existing_application.jar", "Hello World")
......@@ -133,6 +139,60 @@ class TestApplicationUpload(APITestCase):
self.assertEqual(response.data['errors'][0]['detail'],
CustomParseError.messages['filename_already_exists_error'])
# Test for uploading an application when all the required information are provided
# and there is already an application with the same name, on a different project uploaded
@mock.patch('backend.views.get_user_okeanos_projects')
@mock.patch('backend.views.events.create_new_application')
@mock.patch('backend.views.tasks.upload_application_to_pithos')
def test_existent_name_on_other_project(self, mock_upload_application_to_pithos_task,
mock_create_new_application_event,
mock_get_user_okeanos_projects):
# Configure return values for mocks.
chosen_project = self.user_projects[0]
mock_get_user_okeanos_projects.return_value = self.user_projects
# Create an application on the database.
Application.objects.create(uuid=uuid.uuid4(), name="existing_application.jar",
type=Application.BATCH)
# Make a request to upload an application.
response = self.client.post("/api/apps/", {'description': self.application_description,
'file': self.application,
'type': self.application_type_batch,
'project_name': self.project_name,
'execution_environment_name':
self.execution_environment_name})
# Assert the structure of the response.
self._assert_accepted_response_structure(response)
# Assert the contents of the response.
self.assertEqual(response.data['status']['code'], status.HTTP_202_ACCEPTED)
self.assertEqual(response.data['status']['short_description'],
ResponseMessages.short_descriptions['application_upload'])
self.assertIsInstance(response.data['data'][0]['id'], uuid.UUID)
self.assertRegexpMatches(response.data['data'][0]['links']['self'],
r'^http://testserver/api/apps/([^/.]+)$')
# Get the id of the uploaded application.
application_id = response.data['data'][0]['id']
# Assert that the proper tasks and views have been called.
mock_create_new_application_event.delay.\
assert_called_with(application_id, self.application.name, chosen_project['id'],
ApplicationViewSet.pithos_container + "_" + chosen_project['name'],
self.application_description, self.application_type_batch,
self.user, self.execution_environment_name)
mock_upload_application_to_pithos_task.delay.\
assert_called_with(self.AUTHENTICATION_URL, self.AUTHENTICATION_TOKEN,
ApplicationViewSet.pithos_container + "_" + chosen_project['name'],
chosen_project['id'],
path.join(settings.TEMPORARY_FILE_STORAGE, self.application.name),
application_id, self.application.name, self.application_description)
# Test for uploading an application when no description is provided.
@mock.patch('backend.views.get_user_okeanos_projects')
@mock.patch('backend.views.events.create_new_application')
......
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