From cef6ec561c14f4296903cc76c13d5e0ef52d2b8f Mon Sep 17 00:00:00 2001 From: chuzhang Date: Sun, 6 Sep 2015 10:02:01 +0800 Subject: [PATCH] Keep track of reasons for changes. JIRA: PDC-923 --- pdc/apps/changeset/filters.py | 3 +- .../changeset/fixtures/tests/changeset.json | 8 ++++++ pdc/apps/changeset/middleware.py | 3 +- .../0003_changeset_pdc_change_comment.py | 19 +++++++++++++ pdc/apps/changeset/models.py | 1 + pdc/apps/changeset/serializers.py | 2 +- pdc/apps/changeset/tests.py | 28 +++++++++++++++++-- pdc/apps/common/renderers.py | 2 ++ pdc_client/__init__.py | 6 +++- pdc_client/bin/pdc_client | 3 ++ 10 files changed, 68 insertions(+), 7 deletions(-) create mode 100644 pdc/apps/changeset/migrations/0003_changeset_pdc_change_comment.py diff --git a/pdc/apps/changeset/filters.py b/pdc/apps/changeset/filters.py index 4a5f0088..4a0bc70e 100644 --- a/pdc/apps/changeset/filters.py +++ b/pdc/apps/changeset/filters.py @@ -23,6 +23,7 @@ class ChangesetFilterSet(django_filters.FilterSet): widget=widgets.DateTimeInput) changed_until = django_filters.MethodFilter(action='filter_committed_until', widget=widgets.DateTimeInput) + pdc_change_comment = django_filters.CharFilter(name="pdc_change_comment", lookup_type="contains") @value_is_not_empty def filter_author(self, qs, value): @@ -42,4 +43,4 @@ def filter_committed_until(self, qs, value): class Meta: model = models.Changeset - fields = ('author', 'resource', 'changed_since', 'changed_until') + fields = ('author', 'resource', 'changed_since', 'changed_until', 'pdc_change_comment') diff --git a/pdc/apps/changeset/fixtures/tests/changeset.json b/pdc/apps/changeset/fixtures/tests/changeset.json index 696782bc..db86ccbf 100644 --- a/pdc/apps/changeset/fixtures/tests/changeset.json +++ b/pdc/apps/changeset/fixtures/tests/changeset.json @@ -13,6 +13,14 @@ "committed_on": "2015-02-03T05:51:17.262Z" } }, +{ + "pk": 3, + "model": "changeset.changeset", + "fields": { + "committed_on": "2015-01-03T10:00:00.000Z", + "pdc_change_comment": "Test for pdc change comment" + } +}, { "pk": 1, "model": "changeset.change", diff --git a/pdc/apps/changeset/middleware.py b/pdc/apps/changeset/middleware.py index 0458abfc..bbc9f5c8 100644 --- a/pdc/apps/changeset/middleware.py +++ b/pdc/apps/changeset/middleware.py @@ -47,7 +47,8 @@ def process_view(self, request, view_func, view_args, view_kwargs): logger.debug("Start write request on the view %s." % view_func.__name__) try: with transaction.atomic(): - request.changeset = models.Changeset(author=user) + pdc_change_comment = request.META.get("HTTP_PDC_CHANGE_COMMENT", None) + request.changeset = models.Changeset(author=user, pdc_change_comment=pdc_change_comment) response = view_func(request, *view_args, **view_kwargs) # response.exception=True means there is an error occurs. if getattr(response, 'exception', 0) or ( diff --git a/pdc/apps/changeset/migrations/0003_changeset_pdc_change_comment.py b/pdc/apps/changeset/migrations/0003_changeset_pdc_change_comment.py new file mode 100644 index 00000000..ce6a8c33 --- /dev/null +++ b/pdc/apps/changeset/migrations/0003_changeset_pdc_change_comment.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('changeset', '0002_auto_20150525_1410'), + ] + + operations = [ + migrations.AddField( + model_name='changeset', + name='pdc_change_comment', + field=models.TextField(null=True, blank=True), + ), + ] diff --git a/pdc/apps/changeset/models.py b/pdc/apps/changeset/models.py index bb90d701..9887540d 100644 --- a/pdc/apps/changeset/models.py +++ b/pdc/apps/changeset/models.py @@ -16,6 +16,7 @@ class Changeset(models.Model): """ author = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True) committed_on = models.DateTimeField(auto_now_add=True) + pdc_change_comment = models.TextField(null=True, blank=True) def __init__(self, *args, **kwargs): self.tmp_changes = [] diff --git a/pdc/apps/changeset/serializers.py b/pdc/apps/changeset/serializers.py index b853dbda..e1e3a1a4 100644 --- a/pdc/apps/changeset/serializers.py +++ b/pdc/apps/changeset/serializers.py @@ -24,4 +24,4 @@ class ChangesetSerializer(StrictSerializerMixin, serializers.ModelSerializer): class Meta: model = Changeset - fields = ('id', 'author', 'committed_on', 'changes') + fields = ('id', 'author', 'committed_on', 'changes', 'pdc_change_comment') diff --git a/pdc/apps/changeset/tests.py b/pdc/apps/changeset/tests.py index 4d220346..06ada05c 100644 --- a/pdc/apps/changeset/tests.py +++ b/pdc/apps/changeset/tests.py @@ -23,6 +23,7 @@ def setUp(self): def test_passing_arguments(self): self.request.user.is_authenticated = lambda: False + self.request.META.get = lambda x, y: y func = Mock() func.__name__ = "Mock" func.return_value = 123 @@ -31,10 +32,11 @@ def test_passing_arguments(self): self.assertTrue(func.called) self.assertEqual(ret, 123) self.assertEqual(func.call_args, call(self.request, 1, 2, 3, arg='val')) - self.assertEqual(changeset.mock_calls, [call(author=None), call().commit()]) + self.assertEqual(changeset.mock_calls, [call(author=None, pdc_change_comment=None), call().commit()]) def test_no_commit_with_exception(self): self.request.user.is_authenticated = lambda: False + self.request.META.get = lambda x, y: y func = Mock() func.__name__ = "Mock" func.side_effect = Exception("Boom!") @@ -42,12 +44,13 @@ def test_no_commit_with_exception(self): with patch("pdc.apps.changeset.models.Changeset") as changeset: self.assertRaises(Exception, self.cm.process_view, self.request, func, [], {}) self.assertTrue(func.called) - self.assertEqual(changeset.mock_calls, [call(author=None)]) + self.assertEqual(changeset.mock_calls, [call(author=None, pdc_change_comment=None)]) self.assertTrue(changeset_logger.error.called) class ChangesetRESTTestCase(APITestCase): - fixtures = ['pdc/apps/changeset/fixtures/tests/changeset.json', ] + fixtures = ['pdc/apps/changeset/fixtures/tests/changeset.json', + "pdc/apps/component/fixtures/tests/bugzilla_component.json"] def test_get(self): url = reverse('changeset-detail', args=[1]) @@ -98,3 +101,22 @@ def test_query_with_incorrect_datetimeformat(self): response = self.client.get(url + '?changed_since=20150203T02:55:18', format='json') self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + + def test_query_with_pdc_change_comment(self): + url = reverse('changeset-list') + response = self.client.get(url + '?pdc_change_comment=change', format='json') + + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data['count'], 1) + + def test_create_with_pdc_change_comment(self): + url = reverse('bugzillacomponent-list') + data = {'name': 'bin', 'parent_pk': 1} + extra = {'HTTP_PDC_CHANGE_COMMENT': 'New bugzilla component'} + response = self.client.post(url, data, format='json', **extra) + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + + url1 = reverse('changeset-list') + response1 = self.client.get(url1 + '?pdc_change_comment=new', format='json') + self.assertEqual(response1.status_code, status.HTTP_200_OK) + self.assertEqual(response1.data['count'], 1) diff --git a/pdc/apps/common/renderers.py b/pdc/apps/common/renderers.py index 8f0ea13a..7403a72e 100644 --- a/pdc/apps/common/renderers.py +++ b/pdc/apps/common/renderers.py @@ -56,6 +56,8 @@ **Please remember to use your token as HTTP header for every requests that need authentication.** +If you want to record the reason for change, you can add Header (-H "PDC-Change-Comment: reasonforchange") in request. + Responses are available in JSON format. **NOTE:** in order to use secure HTTPS connections, you'd better to add server's certificate as trusted. diff --git a/pdc_client/__init__.py b/pdc_client/__init__.py index e05cfa65..9ddeb176 100644 --- a/pdc_client/__init__.py +++ b/pdc_client/__init__.py @@ -20,6 +20,7 @@ "token": None, "insecure": True, "develop": False, + "comment": None, } GLOBAL_CONFIG_FILE = '/etc/pdc/client_config.json' @@ -76,7 +77,7 @@ def obtain_token(pdc): raise Exception('Could not obtain token from any known URL.') -def pdc_client(url, token=None, insecure=False, develop=False, debug=False): +def pdc_client(url, token=None, insecure=False, develop=False, debug=False, comment=None): session = requests.Session() if not develop: @@ -106,4 +107,7 @@ def pdc_client(url, token=None, insecure=False, develop=False, debug=False): token = obtain_token(pdc) session.headers["Authorization"] = "Token %s" % token + if comment: + session.headers["PDC-Change-Comment"] = comment + return pdc, session diff --git a/pdc_client/bin/pdc_client b/pdc_client/bin/pdc_client index cdc8bc4f..f4eb79b2 100755 --- a/pdc_client/bin/pdc_client +++ b/pdc_client/bin/pdc_client @@ -138,6 +138,7 @@ if __name__ == "__main__": parser.add_option("--debug", help="Show request headers and path for " "debugging.", action="store_true", default=False) + parser.add_option("-c", "--comment", help="Reasons for the PDC change.") options, args = parser.parse_args() if len(args): @@ -166,6 +167,8 @@ if __name__ == "__main__": set_option("insecure", config.get(CONFIG_INSECURE_KEY_NAME)) set_option("develop", config.get(CONFIG_DEVELOP_KEY_NAME)) set_option("token", config.get(CONFIG_TOKEN_KEY_NAME)) + if options.comment: + set_option("comment", options.comment) data = load_data(options)