From 29fd83dc6c5ee5c00d1b1f89261b23195878a2cc Mon Sep 17 00:00:00 2001 From: Akshay Joshi Date: Fri, 12 Jul 2019 10:37:41 +0100 Subject: [PATCH] Fix dropping of pgAgent schedules through the Job properties. Fixes #3996 --- docs/en_US/release_notes_4_11.rst | 1 + .../servers/pgagent/schedules/__init__.py | 26 ++++++--- .../schedules/static/js/pga_schedule.js | 1 + .../servers/pgagent/steps/__init__.py | 26 ++++++--- .../pgagent/steps/static/js/pga_jobstep.js | 1 + .../tests/test_pgagent_delete_multiple.py | 47 ++++++++++++++++ ...tests_pgagent_delete_multiple_schedules.py | 56 +++++++++++++++++++ .../tests_pgagent_delete_multiple_steps.py | 54 ++++++++++++++++++ 8 files changed, 194 insertions(+), 18 deletions(-) create mode 100644 web/pgadmin/browser/server_groups/servers/pgagent/tests/test_pgagent_delete_multiple.py create mode 100644 web/pgadmin/browser/server_groups/servers/pgagent/tests/tests_pgagent_delete_multiple_schedules.py create mode 100644 web/pgadmin/browser/server_groups/servers/pgagent/tests/tests_pgagent_delete_multiple_steps.py diff --git a/docs/en_US/release_notes_4_11.rst b/docs/en_US/release_notes_4_11.rst index bac325440..aec17b477 100644 --- a/docs/en_US/release_notes_4_11.rst +++ b/docs/en_US/release_notes_4_11.rst @@ -28,6 +28,7 @@ Bug fixes ********* | `Issue #3919 `_ - Allow keyboard navigation of all controls on subnode grids. +| `Issue #3996 `_ - Fix dropping of pgAgent schedules through the Job properties. | `Issue #4224 `_ - Prevent flickering of large tooltips on the Graphical EXPLAIN canvas. | `Issue #4389 `_ - Fix an error that could be seen when editing column privileges. | `Issue #4393 `_ - Ensure parameter values are quoted when needed when editing roles. diff --git a/web/pgadmin/browser/server_groups/servers/pgagent/schedules/__init__.py b/web/pgadmin/browser/server_groups/servers/pgagent/schedules/__init__.py index c96db32d4..c19031884 100644 --- a/web/pgadmin/browser/server_groups/servers/pgagent/schedules/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/pgagent/schedules/__init__.py @@ -140,7 +140,7 @@ class JobScheduleView(PGChildNodeView): operations = dict({ 'obj': [ {'get': 'properties', 'put': 'update', 'delete': 'delete'}, - {'get': 'list', 'post': 'create'} + {'get': 'list', 'post': 'create', 'delete': 'delete'} ], 'nodes': [{'get': 'nodes'}, {'get': 'nodes'}], 'msql': [{'get': 'msql'}, {'get': 'msql'}], @@ -474,17 +474,25 @@ class JobScheduleView(PGChildNodeView): ) @check_precondition - def delete(self, gid, sid, jid, jscid): + def delete(self, gid, sid, jid, jscid=None): """Delete the Job Schedule.""" - status, res = self.conn.execute_void( - render_template( - "/".join([self.template_path, 'delete.sql']), - jid=jid, jscid=jscid, conn=self.conn + if jscid is None: + data = request.form if request.form else json.loads( + request.data, encoding='utf-8' ) - ) - if not status: - return internal_server_error(errormsg=res) + else: + data = {'ids': [jscid]} + + for jscid in data['ids']: + status, res = self.conn.execute_void( + render_template( + "/".join([self.template_path, 'delete.sql']), + jid=jid, jscid=jscid, conn=self.conn + ) + ) + if not status: + return internal_server_error(errormsg=res) return make_json_response(success=1) diff --git a/web/pgadmin/browser/server_groups/servers/pgagent/schedules/static/js/pga_schedule.js b/web/pgadmin/browser/server_groups/servers/pgagent/schedules/static/js/pga_schedule.js index 6ab403b9d..a5480ac14 100644 --- a/web/pgadmin/browser/server_groups/servers/pgagent/schedules/static/js/pga_schedule.js +++ b/web/pgadmin/browser/server_groups/servers/pgagent/schedules/static/js/pga_schedule.js @@ -24,6 +24,7 @@ define('pgadmin.node.pga_schedule', [ type: 'coll-pga_schedule', columns: ['jscid', 'jscname', 'jscenabled'], hasStatistics: false, + canDropCascade: false, }); } diff --git a/web/pgadmin/browser/server_groups/servers/pgagent/steps/__init__.py b/web/pgadmin/browser/server_groups/servers/pgagent/steps/__init__.py index a7d84885f..1f9a3ab42 100644 --- a/web/pgadmin/browser/server_groups/servers/pgagent/steps/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/pgagent/steps/__init__.py @@ -159,7 +159,7 @@ class JobStepView(PGChildNodeView): operations = dict({ 'obj': [ {'get': 'properties', 'put': 'update', 'delete': 'delete'}, - {'get': 'list', 'post': 'create'} + {'get': 'list', 'post': 'create', 'delete': 'delete'} ], 'nodes': [{'get': 'nodes'}, {'get': 'nodes'}], 'msql': [{'get': 'msql'}, {'get': 'msql'}], @@ -474,17 +474,25 @@ SELECT EXISTS( ) @check_precondition - def delete(self, gid, sid, jid, jstid): + def delete(self, gid, sid, jid, jstid=None): """Delete the Job step.""" - status, res = self.conn.execute_void( - render_template( - "/".join([self.template_path, 'delete.sql']), - jid=jid, jstid=jstid, conn=self.conn + if jstid is None: + data = request.form if request.form else json.loads( + request.data, encoding='utf-8' ) - ) - if not status: - return internal_server_error(errormsg=res) + else: + data = {'ids': [jstid]} + + for jstid in data['ids']: + status, res = self.conn.execute_void( + render_template( + "/".join([self.template_path, 'delete.sql']), + jid=jid, jstid=jstid, conn=self.conn + ) + ) + if not status: + return internal_server_error(errormsg=res) return make_json_response(success=1) diff --git a/web/pgadmin/browser/server_groups/servers/pgagent/steps/static/js/pga_jobstep.js b/web/pgadmin/browser/server_groups/servers/pgagent/steps/static/js/pga_jobstep.js index cb74f6506..e0ead97a6 100644 --- a/web/pgadmin/browser/server_groups/servers/pgagent/steps/static/js/pga_jobstep.js +++ b/web/pgadmin/browser/server_groups/servers/pgagent/steps/static/js/pga_jobstep.js @@ -24,6 +24,7 @@ define('pgadmin.node.pga_jobstep', [ 'jstonerror', ], hasStatistics: false, + canDropCascade: false, }); } diff --git a/web/pgadmin/browser/server_groups/servers/pgagent/tests/test_pgagent_delete_multiple.py b/web/pgadmin/browser/server_groups/servers/pgagent/tests/test_pgagent_delete_multiple.py new file mode 100644 index 000000000..e7dee1213 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/pgagent/tests/test_pgagent_delete_multiple.py @@ -0,0 +1,47 @@ +########################################################################## +# +# pgAdmin 4 - PostgreSQL Tools +# +# Copyright (C) 2013 - 2019, The pgAdmin Development Team +# This software is released under the PostgreSQL Licence +# +########################################################################## + +import uuid +import json +from pgadmin.utils.route import BaseTestGenerator +from regression.python_test_utils import test_utils as utils +from . import utils as pgagent_utils + + +class PgAgentDeleteMultipleTestCase(BaseTestGenerator): + """This class will test the delete multiple pgAgent job API""" + scenarios = [ + ('Delete multiple pgAgent job', dict(url='/browser/pga_job/obj/')) + ] + + def setUp(self): + flag, msg = pgagent_utils.is_valid_server_to_run_pgagent(self) + if not flag: + self.skipTest(msg) + flag, msg = pgagent_utils.is_pgagent_installed_on_server(self) + if not flag: + self.skipTest(msg) + name1 = "test_job1_delete%s" % str(uuid.uuid4())[1:8] + self.job_id1 = pgagent_utils.create_pgagent_job(self, name1) + name2 = "test_job2_delete%s" % str(uuid.uuid4())[1:8] + self.job_id2 = pgagent_utils.create_pgagent_job(self, name2) + + def runTest(self): + """This function will deletes pgAgent job""" + response = self.tester.delete( + '{0}{1}/{2}/'.format( + self.url, str(utils.SERVER_GROUP), str(self.server_id) + ), + data=json.dumps({'ids': [self.job_id1, self.job_id2]}), + content_type='html/json' + ) + self.assertEquals(response.status_code, 200) + + def tearDown(self): + """Clean up code""" diff --git a/web/pgadmin/browser/server_groups/servers/pgagent/tests/tests_pgagent_delete_multiple_schedules.py b/web/pgadmin/browser/server_groups/servers/pgagent/tests/tests_pgagent_delete_multiple_schedules.py new file mode 100644 index 000000000..f9432c179 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/pgagent/tests/tests_pgagent_delete_multiple_schedules.py @@ -0,0 +1,56 @@ +########################################################################## +# +# pgAdmin 4 - PostgreSQL Tools +# +# Copyright (C) 2013 - 2019, The pgAdmin Development Team +# This software is released under the PostgreSQL Licence +# +########################################################################## + +import uuid +import json +from pgadmin.utils.route import BaseTestGenerator +from regression.python_test_utils import test_utils as utils +from . import utils as pgagent_utils + + +class PgAgentDeleteMultipleSchedulesTestCase(BaseTestGenerator): + """This class will test the delete pgAgent job schedule API""" + scenarios = [ + ('Delete multiple pgAgent schedules', + dict(url='/browser/pga_schedule/obj/')) + ] + + def setUp(self): + flag, msg = pgagent_utils.is_valid_server_to_run_pgagent(self) + if not flag: + self.skipTest(msg) + flag, msg = pgagent_utils.is_pgagent_installed_on_server(self) + if not flag: + self.skipTest(msg) + name = "test_multi_sc_job_delete%s" % str(uuid.uuid4())[1:8] + self.job_id = pgagent_utils.create_pgagent_job(self, name) + sch1_name = "test_multi_schedule1_delete%s" % str(uuid.uuid4())[1:8] + self.schedule_id1 = pgagent_utils.create_pgagent_schedule( + self, sch1_name, self.job_id) + + # Create one more schedule + sch2_name = "test_multi_schedule2_delete%s" % str(uuid.uuid4())[1:8] + self.schedule_id2 = pgagent_utils.create_pgagent_schedule( + self, sch2_name, self.job_id) + + def runTest(self): + """This function will deletes pgAgent job schedule""" + response = self.tester.delete( + '{0}{1}/{2}/{3}/'.format( + self.url, str(utils.SERVER_GROUP), str(self.server_id), + str(self.job_id) + ), + data=json.dumps({'ids': [self.schedule_id1, self.schedule_id2]}), + content_type='html/json' + ) + self.assertEquals(response.status_code, 200) + + def tearDown(self): + """Clean up code""" + pgagent_utils.delete_pgagent_job(self) diff --git a/web/pgadmin/browser/server_groups/servers/pgagent/tests/tests_pgagent_delete_multiple_steps.py b/web/pgadmin/browser/server_groups/servers/pgagent/tests/tests_pgagent_delete_multiple_steps.py new file mode 100644 index 000000000..a9db9e85f --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/pgagent/tests/tests_pgagent_delete_multiple_steps.py @@ -0,0 +1,54 @@ +########################################################################## +# +# pgAdmin 4 - PostgreSQL Tools +# +# Copyright (C) 2013 - 2019, The pgAdmin Development Team +# This software is released under the PostgreSQL Licence +# +########################################################################## + +import uuid +import json +from pgadmin.utils.route import BaseTestGenerator +from regression.python_test_utils import test_utils as utils +from . import utils as pgagent_utils + + +class PgAgentDeleteMultipleStepsTestCase(BaseTestGenerator): + """This class will test the delete pgAgent job steps API""" + scenarios = [ + ('Delete multiple pgAgent steps', + dict(url='/browser/pga_jobstep/obj/')) + ] + + def setUp(self): + flag, msg = pgagent_utils.is_valid_server_to_run_pgagent(self) + if not flag: + self.skipTest(msg) + flag, msg = pgagent_utils.is_pgagent_installed_on_server(self) + if not flag: + self.skipTest(msg) + name = "test_multiple_st_job_delete%s" % str(uuid.uuid4())[1:8] + self.job_id = pgagent_utils.create_pgagent_job(self, name) + step_name1 = "test_multiple_step1_delete%s" % str(uuid.uuid4())[1:8] + self.step_id1 = pgagent_utils.create_pgagent_step( + self, step_name1, self.job_id) + step_name2 = "test_multiple_step2_delete%s" % str(uuid.uuid4())[1:8] + self.step_id2 = pgagent_utils.create_pgagent_step( + self, step_name2, self.job_id) + + def runTest(self): + """This function will deletes pgAgent job schedule""" + response = self.tester.delete( + '{0}{1}/{2}/{3}/'.format( + self.url, str(utils.SERVER_GROUP), str(self.server_id), + str(self.job_id) + ), + data=json.dumps({'ids': [self.step_id1, self.step_id2]}), + content_type='html/json' + ) + self.assertEquals(response.status_code, 200) + + def tearDown(self): + """Clean up code""" + pgagent_utils.delete_pgagent_job(self)