diff --git a/ara/api/serializers.py b/ara/api/serializers.py index 4724a2b..469a560 100644 --- a/ara/api/serializers.py +++ b/ara/api/serializers.py @@ -118,6 +118,8 @@ class ResultSerializer(serializers.ModelSerializer): model = models.Result fields = '__all__' + content = CompressedObjectField(default=zlib.compress(json.dumps({}).encode('utf8'))) + class PlaybookSerializer(DurationSerializer): class Meta: diff --git a/ara/api/tests/factories.py b/ara/api/tests/factories.py index 189d265..dab158e 100644 --- a/ara/api/tests/factories.py +++ b/ara/api/tests/factories.py @@ -65,3 +65,13 @@ class HostFactory(factory.DjangoModelFactory): skipped = 1 unreachable = 0 play = factory.SubFactory(PlayFactory) + + +class ResultFactory(factory.DjangoModelFactory): + class Meta: + model = models.Result + + content = b'x\x9c\xabVJ\xcb\xcfW\xb2RPJJ,R\xaa\x05\x00 \x98\x04T' + status = 'ok' + host = factory.SubFactory(HostFactory) + task = factory.SubFactory(TaskFactory) diff --git a/ara/api/tests/tests_result.py b/ara/api/tests/tests_result.py new file mode 100644 index 0000000..94153dc --- /dev/null +++ b/ara/api/tests/tests_result.py @@ -0,0 +1,92 @@ +from rest_framework.test import APITestCase + +from ara.api import models, serializers +from ara.api.tests import factories + + +class ResultTestCase(APITestCase): + def test_result_factory(self): + result = factories.ResultFactory(status='failed') + self.assertEqual(result.status, 'failed') + + def test_result_serializer(self): + host = factories.HostFactory() + task = factories.TaskFactory() + serializer = serializers.ResultSerializer(data={ + 'status': 'skipped', + 'host': host.id, + 'task': task.id + }) + serializer.is_valid() + result = serializer.save() + result.refresh_from_db() + self.assertEqual(result.status, 'skipped') + self.assertEqual(result.host.id, host.id) + self.assertEqual(result.task.id, task.id) + + def test_result_serializer_compress_content(self): + host = factories.HostFactory() + task = factories.TaskFactory() + serializer = serializers.ResultSerializer(data={ + 'host': host.id, + 'task': task.id, + 'content': {'foo': 'bar'} + }) + serializer.is_valid() + result = serializer.save() + result.refresh_from_db() + self.assertEqual( + result.content, b'x\x9c\xabVJ\xcb\xcfW\xb2RPJJ,R\xaa\x05\x00 \x98\x04T' + ) + + def test_result_serializer_decompress_content(self): + result = factories.ResultFactory( + content=b'x\x9c\xabVJ\xcb\xcfW\xb2RPJJ,R\xaa\x05\x00 \x98\x04T' + ) + serializer = serializers.ResultSerializer(instance=result) + self.assertEqual(serializer.data['content'], {'foo': 'bar'}) + + def test_get_no_results(self): + request = self.client.get('/api/v1/results/') + self.assertEqual(0, len(request.data['results'])) + + def test_get_results(self): + result = factories.ResultFactory() + request = self.client.get('/api/v1/results/') + self.assertEqual(1, len(request.data['results'])) + self.assertEqual(result.status, request.data['results'][0]['status']) + + def test_delete_result(self): + result = factories.ResultFactory() + self.assertEqual(1, models.Result.objects.all().count()) + request = self.client.delete('/api/v1/results/%s/' % result.id) + self.assertEqual(204, request.status_code) + self.assertEqual(0, models.Result.objects.all().count()) + + def test_create_result(self): + host = factories.HostFactory() + task = factories.TaskFactory() + self.assertEqual(0, models.Result.objects.count()) + request = self.client.post('/api/v1/results/', { + 'status': 'ok', + 'host': host.id, + 'task': task.id, + 'content': {'foo': 'bar'} + }) + self.assertEqual(201, request.status_code) + self.assertEqual(1, models.Result.objects.count()) + + def test_partial_update_result(self): + result = factories.ResultFactory() + self.assertNotEqual('unreachable', result.status) + request = self.client.patch('/api/v1/results/%s/' % result.id, { + 'status': 'unreachable' + }) + self.assertEqual(200, request.status_code) + result_updated = models.Result.objects.get(id=result.id) + self.assertEqual('unreachable', result_updated.status) + + def test_get_result(self): + result = factories.ResultFactory() + request = self.client.get('/api/v1/results/%s/' % result.id) + self.assertEqual(result.status, request.data['status']) diff --git a/ara/api/urls.py b/ara/api/urls.py index 4815acd..52948d8 100644 --- a/ara/api/urls.py +++ b/ara/api/urls.py @@ -30,6 +30,8 @@ urlpatterns = [ url(r'^tasks/(?P[0-9]+)/$', views.TaskDetail.as_view(), name='task-detail'), url(r'^hosts/$', views.HostList.as_view(), name='host-list'), url(r'^hosts/(?P[0-9]+)/$', views.HostDetail.as_view(), name='host-detail'), + url(r'^results/$', views.ResultList.as_view(), name='result-list'), + url(r'^results/(?P[0-9]+)/$', views.ResultDetail.as_view(), name='result-detail'), url(r'^files/$', views.FileList.as_view(), name='file-list'), url(r'^files/(?P[0-9]+)/$', views.FileDetail.as_view(), name='file-detail'), ] diff --git a/ara/api/views.py b/ara/api/views.py index 193f230..474c6ba 100644 --- a/ara/api/views.py +++ b/ara/api/views.py @@ -30,7 +30,8 @@ def api_root(request, format=None): 'plays': reverse('play-list', request=request, format=format), 'tasks': reverse('task-list', request=request, format=format), 'files': reverse('file-list', request=request, format=format), - 'hosts': reverse('host-list', request=request, format=format) + 'hosts': reverse('host-list', request=request, format=format), + 'results': reverse('result-list', request=request, format=format) }) @@ -88,6 +89,16 @@ class HostDetail(generics.RetrieveUpdateDestroyAPIView): serializer_class = serializers.HostSerializer +class ResultList(generics.ListCreateAPIView): + queryset = models.Result.objects.all() + serializer_class = serializers.ResultSerializer + + +class ResultDetail(generics.RetrieveUpdateDestroyAPIView): + queryset = models.Result.objects.all() + serializer_class = serializers.ResultSerializer + + class FileList(generics.ListCreateAPIView): queryset = models.File.objects.all() serializer_class = serializers.FileSerializer