From 1f8cab41717e7b252ca99c30f738096ec4739214 Mon Sep 17 00:00:00 2001 From: AlanCoding Date: Thu, 30 Nov 2017 08:12:25 -0500 Subject: [PATCH 1/2] intentionally forget start_args when job is done --- awx/main/models/unified_jobs.py | 3 ++- awx/main/scheduler/task_manager.py | 3 ++- awx/main/tasks.py | 3 ++- awx/main/tests/unit/models/test_unified_job_unit.py | 4 ++-- awx/main/tests/unit/test_tasks.py | 2 +- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/awx/main/models/unified_jobs.py b/awx/main/models/unified_jobs.py index 0e3507ceac..821089d98d 100644 --- a/awx/main/models/unified_jobs.py +++ b/awx/main/models/unified_jobs.py @@ -1236,7 +1236,8 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique if not self.cancel_flag: self.cancel_flag = True - cancel_fields = ['cancel_flag'] + self.start_args = '' # blank field to remove encrypted passwords + cancel_fields = ['cancel_flag', 'start_args'] if self.status in ('pending', 'waiting', 'new'): self.status = 'canceled' cancel_fields.append('status') diff --git a/awx/main/scheduler/task_manager.py b/awx/main/scheduler/task_manager.py index 9d5994d01e..bc64ca81fa 100644 --- a/awx/main/scheduler/task_manager.py +++ b/awx/main/scheduler/task_manager.py @@ -479,6 +479,7 @@ class TaskManager(): if isolated: new_status = 'error' task.status = new_status + task.start_args = '' # blank field to remove encrypted passwords if isolated: # TODO: cancel and reap artifacts of lost jobs from heartbeat task.job_explanation += ' '.join(( @@ -493,7 +494,7 @@ class TaskManager(): 'Celery, so it has been marked as failed.', )) try: - task.save(update_fields=['status', 'job_explanation']) + task.save(update_fields=['status', 'start_args', 'job_explanation']) except DatabaseError: logger.error("Task {} DB error in marking failed. Job possibly deleted.".format(task.log_format)) continue diff --git a/awx/main/tasks.py b/awx/main/tasks.py index 7fbbe6bc46..c6129f7c97 100644 --- a/awx/main/tasks.py +++ b/awx/main/tasks.py @@ -759,7 +759,8 @@ class BaseTask(LogErrorsTask): execution_node = settings.CLUSTER_HOST_ID if isolated_host is not None: execution_node = isolated_host - instance = self.update_model(pk, status='running', execution_node=execution_node) + instance = self.update_model(pk, status='running', execution_node=execution_node, + start_args='') # blank field to remove encrypted passwords instance.websocket_emit_status("running") status, rc, tb = 'error', None, '' diff --git a/awx/main/tests/unit/models/test_unified_job_unit.py b/awx/main/tests/unit/models/test_unified_job_unit.py index 2d9981e073..faae9e87a7 100644 --- a/awx/main/tests/unit/models/test_unified_job_unit.py +++ b/awx/main/tests/unit/models/test_unified_job_unit.py @@ -52,7 +52,7 @@ def test_cancel(unified_job): # Some more thought may want to go into only emitting canceled if/when the job record # status is changed to canceled. Unlike, currently, where it's emitted unconditionally. unified_job.websocket_emit_status.assert_called_with("canceled") - unified_job.save.assert_called_with(update_fields=['cancel_flag', 'status']) + unified_job.save.assert_called_with(update_fields=['cancel_flag', 'start_args', 'status']) def test_cancel_job_explanation(unified_job): @@ -61,7 +61,7 @@ def test_cancel_job_explanation(unified_job): unified_job.cancel(job_explanation=job_explanation) assert unified_job.job_explanation == job_explanation - unified_job.save.assert_called_with(update_fields=['cancel_flag', 'status', 'job_explanation']) + unified_job.save.assert_called_with(update_fields=['cancel_flag', 'start_args', 'status', 'job_explanation']) def test_log_representation(): diff --git a/awx/main/tests/unit/test_tasks.py b/awx/main/tests/unit/test_tasks.py index 066cfaf684..cc18eb1c57 100644 --- a/awx/main/tests/unit/test_tasks.py +++ b/awx/main/tests/unit/test_tasks.py @@ -271,7 +271,7 @@ class TestGenericRun(TestJobExecution): with pytest.raises(Exception): self.task.run(self.pk) for c in [ - mock.call(self.pk, execution_node=settings.CLUSTER_HOST_ID, status='running'), + mock.call(self.pk, execution_node=settings.CLUSTER_HOST_ID, status='running', start_args=''), mock.call(self.pk, status='canceled') ]: assert c in self.task.update_model.call_args_list From 0bf06479d59e8fe101bf0b467f63fbccd2d07273 Mon Sep 17 00:00:00 2001 From: AlanCoding Date: Fri, 8 Dec 2017 14:49:20 -0500 Subject: [PATCH 2/2] add migration to remove old start_args --- awx/main/migrations/0011_blank_start_args.py | 22 ++++++++++++++++++++ awx/main/migrations/_reencrypt.py | 17 +++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 awx/main/migrations/0011_blank_start_args.py diff --git a/awx/main/migrations/0011_blank_start_args.py b/awx/main/migrations/0011_blank_start_args.py new file mode 100644 index 0000000000..ba3648a31e --- /dev/null +++ b/awx/main/migrations/0011_blank_start_args.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Python +from __future__ import unicode_literals + +# Django +from django.db import migrations, models + +# AWX +from awx.main.migrations import _migration_utils as migration_utils +from awx.main.migrations._reencrypt import blank_old_start_args + + +class Migration(migrations.Migration): + + dependencies = [ + ('main', '0010_saved_launchtime_configs'), + ] + + operations = [ + migrations.RunPython(migration_utils.set_current_apps_for_migrations, migrations.RunPython.noop), + migrations.RunPython(blank_old_start_args, migrations.RunPython.noop), + ] diff --git a/awx/main/migrations/_reencrypt.py b/awx/main/migrations/_reencrypt.py index 84b95e8160..6a293a5e3c 100644 --- a/awx/main/migrations/_reencrypt.py +++ b/awx/main/migrations/_reencrypt.py @@ -74,3 +74,20 @@ def _unified_jobs(apps): uj.start_args = decrypt_field(uj, 'start_args') uj.start_args = encrypt_field(uj, 'start_args') uj.save() + + +def blank_old_start_args(apps, schema_editor): + UnifiedJob = apps.get_model('main', 'UnifiedJob') + for uj in UnifiedJob.objects.defer('result_stdout_text').exclude(start_args='').iterator(): + if uj.status in ['running', 'pending', 'new', 'waiting']: + continue + try: + args_dict = decrypt_field(uj, 'start_args') + except ValueError: + args_dict = None + if args_dict == {}: + continue + if uj.start_args: + logger.debug('Blanking job args for %s', uj.pk) + uj.start_args = '' + uj.save()