diff --git a/storage_service/locations/api/resources.py b/storage_service/locations/api/resources.py index e10fbd587..15d8b44fc 100644 --- a/storage_service/locations/api/resources.py +++ b/storage_service/locations/api/resources.py @@ -35,7 +35,7 @@ from common import utils from locations.api.sword import views as sword_views -from ..models import (Callback, CallbackError, Event, File, Package, Location, Space, Pipeline, StorageException, Async, PosixMoveUnsupportedError) +from ..models import (Callback, CallbackError, Event, File, Package, Location, LocationPipeline, Space, Pipeline, StorageException, Async, PosixMoveUnsupportedError) from ..forms import SpaceForm from ..constants import PROTOCOL from locations import signals @@ -238,7 +238,6 @@ def browse(self, request, bundle, **kwargs): class LocationResource(ModelResource): space = fields.ForeignKey(SpaceResource, 'space') path = fields.CharField(attribute='full_path', readonly=True) - description = fields.CharField(attribute='get_description', readonly=True) pipeline = fields.ToManyField(PipelineResource, 'pipeline') class Meta: @@ -248,8 +247,9 @@ class Meta: # validation = CleanedDataFormValidation(form_class=LocationForm) resource_name = 'location' - fields = ['enabled', 'relative_path', 'purpose', 'quota', 'used', 'uuid'] - list_allowed_methods = ['get'] + fields = ['enabled', 'relative_path', 'purpose', 'quota', 'used', + 'uuid', 'description'] + list_allowed_methods = ['get', 'post'] detail_allowed_methods = ['get', 'post'] detail_uri_name = 'uuid' always_return_data = True @@ -261,6 +261,7 @@ class Meta: 'space': ALL_WITH_RELATIONS, 'used': ALL, 'uuid': ALL, + 'description': ALL, } def prepend_urls(self): @@ -303,6 +304,23 @@ def default(self, request, **kwargs): 'uuid': uuid, })) + def save_m2m(self, bundle): + for field_name, field_object in self.fields.items(): + if field_name != 'pipeline': + continue + + if not getattr(field_object, 'is_m2m', False): + continue + + if not field_object.attribute: + continue + + pipelines = bundle.data['pipeline'] + for item in pipelines: + LocationPipeline.objects.get_or_create( + pipeline=item.obj, + location=bundle.obj) + @_custom_endpoint(expected_methods=['get']) def browse(self, request, bundle, **kwargs): """ Returns all of the entries in a location, optionally at a subpath. diff --git a/storage_service/locations/api/v2.py b/storage_service/locations/api/v2.py index 94fc03128..424089242 100644 --- a/storage_service/locations/api/v2.py +++ b/storage_service/locations/api/v2.py @@ -22,7 +22,6 @@ def get_objects(self, space, path): class LocationResource(resources.LocationResource): space = fields.ForeignKey(SpaceResource, 'space') path = fields.CharField(attribute='full_path', readonly=True) - description = fields.CharField(attribute='get_description', readonly=True) pipeline = fields.ToManyField(PipelineResource, 'pipeline') def decode_path(self, path): diff --git a/storage_service/locations/tests/test_api.py b/storage_service/locations/tests/test_api.py index 0865713c3..a01b5f749 100644 --- a/storage_service/locations/tests/test_api.py +++ b/storage_service/locations/tests/test_api.py @@ -29,6 +29,39 @@ def test_requires_auth(self): response = self.client.post('/api/v2/location/213086c8-232e-4b9e-bb03-98fbc7a7966a/') assert response.status_code == 401 + def test_create_location(self): + space = models.Space.objects.get( + uuid='7d20c992-bc92-4f92-a794-7161ff2cc08b') + data = { + 'space': '/api/v2/space/7d20c992-bc92-4f92-a794-7161ff2cc08b/', + 'description': 'automated workflow', + 'relative_path': 'automated-workflow/foo/bar', + 'purpose': 'TS', + 'pipeline': [ + '/api/v2/pipeline/b25f6b71-3ebf-4fcc-823c-1feb0a2553dd/' + ], + } + + response = self.client.post( + '/api/v2/location/', + data=json.dumps(data), + content_type='application/json') + assert response.status_code == 201 + + # Verify content + body = json.loads(response.content) + assert body['description'] == data['description'] + assert body['purpose'] == data['purpose'] + assert body['path'] == '{}{}'.format(space.path, data['relative_path']) + assert body['enabled'] is True + assert data['pipeline'][0] in body['pipeline'] + + # Verify that the record was populated properly + location = models.Location.objects.get(uuid=body['uuid']) + assert location.purpose == data['purpose'] + assert location.relative_path == data['relative_path'] + assert location.description == data['description'] + def test_cant_move_from_non_existant_locations(self): data = { 'origin_location': '/api/v2/location/dne1aacf-8492-4382-8ef3-262cc5420dne/',