From b79606d9d365fd63b5340ae9ad1aff75300db566 Mon Sep 17 00:00:00 2001 From: AlanCoding Date: Fri, 11 May 2018 09:41:21 -0400 Subject: [PATCH] update project if certain params changed --- awx/main/models/projects.py | 21 +++++++++++- .../tests/functional/models/test_project.py | 33 +++++++++++++++++++ .../task_management/test_scheduler.py | 2 +- 3 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 awx/main/tests/functional/models/test_project.py diff --git a/awx/main/models/projects.py b/awx/main/models/projects.py index d99fe5bafb..3bad19c8eb 100644 --- a/awx/main/models/projects.py +++ b/awx/main/models/projects.py @@ -241,6 +241,7 @@ class Project(UnifiedJobTemplate, ProjectOptions, ResourceMixin, CustomVirtualEn SOFT_UNIQUE_TOGETHER = [('polymorphic_ctype', 'name', 'organization')] FIELDS_TO_PRESERVE_AT_COPY = ['labels', 'instance_groups', 'credentials'] FIELDS_TO_DISCARD_AT_COPY = ['local_path'] + FIELDS_TRIGGER_UPDATE = frozenset(['scm_url', 'scm_branch', 'scm_type']) class Meta: app_label = 'main' @@ -323,6 +324,11 @@ class Project(UnifiedJobTemplate, ProjectOptions, ResourceMixin, CustomVirtualEn ['name', 'description', 'schedule'] ) + def __init__(self, *args, **kwargs): + r = super(Project, self).__init__(*args, **kwargs) + self._prior_values_store = self._current_sensitive_fields() + return r + def save(self, *args, **kwargs): new_instance = not bool(self.pk) # If update_fields has been specified, add our field names to it, @@ -354,9 +360,22 @@ class Project(UnifiedJobTemplate, ProjectOptions, ResourceMixin, CustomVirtualEn with disable_activity_stream(): self.save(update_fields=update_fields) # If we just created a new project with SCM, start the initial update. - if new_instance and self.scm_type and not skip_update: + # also update if certain fields have changed + relevant_change = False + new_values = self._current_sensitive_fields() + if hasattr(self, '_prior_values_store') and self._prior_values_store != new_values: + relevant_change = True + self._prior_values_store = new_values + if (relevant_change or new_instance) and (not skip_update) and self.scm_type: self.update() + def _current_sensitive_fields(self): + new_values = {} + for attr, val in self.__dict__.items(): + if attr in Project.FIELDS_TRIGGER_UPDATE: + new_values[attr] = val + return new_values + def _get_current_status(self): if self.scm_type: if self.current_job and self.current_job.status: diff --git a/awx/main/tests/functional/models/test_project.py b/awx/main/tests/functional/models/test_project.py new file mode 100644 index 0000000000..71352ed633 --- /dev/null +++ b/awx/main/tests/functional/models/test_project.py @@ -0,0 +1,33 @@ +import pytest +import mock + +from awx.main.models import Project + + +@pytest.mark.django_db +def test_project_initial_update(): + with mock.patch.object(Project, "update") as mock_update: + Project.objects.create(name='foo', scm_type='git') + mock_update.assert_called_once_with() + + +@pytest.mark.django_db +def test_does_not_update_nonsensitive_change(project): + with mock.patch.object(Project, "update") as mock_update: + project.scm_update_on_launch = not project.scm_update_on_launch + project.save() + mock_update.assert_not_called() + + +@pytest.mark.django_db +def test_sensitive_change_triggers_update(project): + with mock.patch.object(Project, "update") as mock_update: + project.scm_url = 'https://foo.invalid' + project.save() + mock_update.assert_called_once_with() + # test other means of initialization + project = Project.objects.get(pk=project.pk) + with mock.patch.object(Project, "update") as mock_update: + project.scm_url = 'https://foo2.invalid' + project.save() + mock_update.assert_called_once_with() diff --git a/awx/main/tests/functional/task_management/test_scheduler.py b/awx/main/tests/functional/task_management/test_scheduler.py index 1d87417b17..116deba3ad 100644 --- a/awx/main/tests/functional/task_management/test_scheduler.py +++ b/awx/main/tests/functional/task_management/test_scheduler.py @@ -113,7 +113,7 @@ def test_single_job_dependencies_project_launch(default_instance_group, job_temp p.scm_update_cache_timeout = 0 p.scm_type = "git" p.scm_url = "http://github.com/ansible/ansible.git" - p.save() + p.save(skip_update=True) with mock.patch("awx.main.scheduler.TaskManager.start_task"): tm = TaskManager() with mock.patch.object(TaskManager, "create_project_update", wraps=tm.create_project_update) as mock_pu: