mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Add a (configurable) limit to the number of pgAgent job history rows displayed on the statistics tab. Fixes #3072
This commit is contained in:
committed by
Dave Page
parent
fa1854bd85
commit
8ec51412c3
@@ -22,6 +22,7 @@ from pgadmin.browser.server_groups import servers
|
||||
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
|
||||
make_response as ajax_response, gone, success_return
|
||||
from pgadmin.utils.driver import get_driver
|
||||
from pgadmin.utils.preferences import Preferences
|
||||
|
||||
|
||||
class JobModule(CollectionNodeModule):
|
||||
@@ -415,10 +416,16 @@ SELECT EXISTS(
|
||||
otherwise it will return statistics for all the databases in that
|
||||
server.
|
||||
"""
|
||||
pref = Preferences.module('browser')
|
||||
rows_threshold = pref.preference(
|
||||
'pgagent_row_threshold'
|
||||
)
|
||||
|
||||
status, res = self.conn.execute_dict(
|
||||
render_template(
|
||||
"/".join([self.template_path, 'stats.sql']),
|
||||
jid=jid, conn=self.conn
|
||||
jid=jid, conn=self.conn,
|
||||
rows_threshold=rows_threshold.get()
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ from pgadmin.browser.utils import PGChildNodeView
|
||||
from pgadmin.utils.ajax import make_json_response, gone, \
|
||||
make_response as ajax_response, internal_server_error
|
||||
from pgadmin.utils.driver import get_driver
|
||||
from pgadmin.utils.preferences import Preferences
|
||||
|
||||
from config import PG_DEFAULT_DRIVER
|
||||
|
||||
@@ -570,10 +571,16 @@ SELECT EXISTS(
|
||||
otherwise it will return statistics for all the databases in that
|
||||
server.
|
||||
"""
|
||||
pref = Preferences.module('browser')
|
||||
rows_threshold = pref.preference(
|
||||
'pgagent_row_threshold'
|
||||
)
|
||||
|
||||
status, res = self.conn.execute_dict(
|
||||
render_template(
|
||||
"/".join([self.template_path, 'stats.sql']),
|
||||
jid=jid, jstid=jstid, conn=self.conn
|
||||
jid=jid, jstid=jstid, conn=self.conn,
|
||||
rows_threshold=rows_threshold.get()
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -8,4 +8,5 @@ FROM
|
||||
pgagent.pga_joblog
|
||||
WHERE
|
||||
jlgjobid = {{ jid|qtLiteral }}::integer
|
||||
ORDER BY jlgid DESC;
|
||||
ORDER BY jlgid DESC
|
||||
LIMIT {{ rows_threshold }};
|
||||
|
||||
@@ -10,4 +10,5 @@ FROM
|
||||
pgagent.pga_jobsteplog
|
||||
WHERE
|
||||
jsljstid = {{ jstid|qtLiteral }}::integer
|
||||
ORDER BY jslid DESC;
|
||||
ORDER BY jslid DESC
|
||||
LIMIT {{ rows_threshold }};
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
from pgadmin.utils.route import BaseTestGenerator
|
||||
|
||||
|
||||
class PgAgentCreateTestCase(BaseTestGenerator):
|
||||
def runTest(self):
|
||||
return
|
||||
@@ -0,0 +1,89 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
import simplejson as json
|
||||
import uuid
|
||||
from pgadmin.utils.route import BaseTestGenerator
|
||||
from regression.python_test_utils import test_utils as utils
|
||||
from . import utils as pgagent_utils
|
||||
|
||||
|
||||
class PgAgentAddTestCase(BaseTestGenerator):
|
||||
"""This class will test the add pgAgent job API"""
|
||||
scenarios = [
|
||||
('Add 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)
|
||||
|
||||
def runTest(self):
|
||||
"""This function will adds pgAgent job"""
|
||||
self.pgagent_job = "test_job_add%s" % str(uuid.uuid4())[1:8]
|
||||
data = {
|
||||
'jobname': self.pgagent_job,
|
||||
'jobenabled': True,
|
||||
'jobhostagent': '',
|
||||
'jobjclid': 1,
|
||||
'jobdesc': '',
|
||||
'jsteps': [{
|
||||
'jstid': None,
|
||||
'jstjobid': None,
|
||||
'jstname': 'test_step',
|
||||
'jstdesc': '',
|
||||
'jstenabled': True,
|
||||
'jstkind': True,
|
||||
'jstconntype': True,
|
||||
'jstcode': 'SELECT 1;',
|
||||
'jstconnstr': None,
|
||||
'jstdbname': 'postgres',
|
||||
'jstonerror': 'f',
|
||||
'jstnextrun': '',
|
||||
}],
|
||||
'jschedules': [{
|
||||
'jscid': None,
|
||||
'jscjobid': None,
|
||||
'jscname': 'test_sch',
|
||||
'jscdesc': '',
|
||||
'jscenabled': True,
|
||||
'jscstart': '2050-01-01 12:14:21 +05:30',
|
||||
'jscend': None,
|
||||
'jscweekdays': [False] * 7,
|
||||
'jscmonthdays': [False] * 32,
|
||||
'jscmonths': [False] * 12,
|
||||
'jschours': [False] * 24,
|
||||
'jscminutes': [False] * 60,
|
||||
'jscexceptions': [],
|
||||
}],
|
||||
}
|
||||
|
||||
response = self.tester.post(
|
||||
'{0}{1}/{2}/'.format(
|
||||
self.url, str(utils.SERVER_GROUP), str(self.server_id)
|
||||
),
|
||||
data=json.dumps(data),
|
||||
content_type='html/json'
|
||||
)
|
||||
self.assertEquals(response.status_code, 200)
|
||||
|
||||
response_data = json.loads(response.data)
|
||||
self.job_id = response_data['node']['_id']
|
||||
is_present = pgagent_utils.verify_pgagent_job(self)
|
||||
self.assertTrue(
|
||||
is_present, "pgAgent job was not created successfully"
|
||||
)
|
||||
|
||||
def tearDown(self):
|
||||
"""Clean up code"""
|
||||
pgagent_utils.delete_pgagent_job(self)
|
||||
@@ -0,0 +1,49 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
import uuid
|
||||
from pgadmin.utils.route import BaseTestGenerator
|
||||
from regression.python_test_utils import test_utils as utils
|
||||
from . import utils as pgagent_utils
|
||||
|
||||
|
||||
class PgAgentDeleteTestCase(BaseTestGenerator):
|
||||
"""This class will test the delete pgAgent job API"""
|
||||
scenarios = [
|
||||
('Delete 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)
|
||||
name = "test_job_delete%s" % str(uuid.uuid4())[1:8]
|
||||
self.job_id = pgagent_utils.create_pgagent_job(self, name)
|
||||
|
||||
def runTest(self):
|
||||
"""This function will deletes pgAgent job"""
|
||||
response = self.tester.delete(
|
||||
'{0}{1}/{2}/{3}'.format(
|
||||
self.url, str(utils.SERVER_GROUP), str(self.server_id),
|
||||
str(self.job_id)
|
||||
),
|
||||
content_type='html/json'
|
||||
)
|
||||
self.assertEquals(response.status_code, 200)
|
||||
is_present = pgagent_utils.verify_pgagent_job(self)
|
||||
self.assertFalse(
|
||||
is_present, "pgAgent job was not deleted successfully"
|
||||
)
|
||||
|
||||
def tearDown(self):
|
||||
"""Clean up code"""
|
||||
pgagent_utils.delete_pgagent_job(self)
|
||||
@@ -0,0 +1,51 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
import simplejson as json
|
||||
import uuid
|
||||
from pgadmin.utils.route import BaseTestGenerator
|
||||
from regression.python_test_utils import test_utils as utils
|
||||
from . import utils as pgagent_utils
|
||||
|
||||
|
||||
class PgAgentPutTestCase(BaseTestGenerator):
|
||||
"""This class will test the put pgAgent job API"""
|
||||
scenarios = [
|
||||
('Put 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)
|
||||
name = "test_job_put%s" % str(uuid.uuid4())[1:8]
|
||||
self.job_id = pgagent_utils.create_pgagent_job(self, name)
|
||||
|
||||
def runTest(self):
|
||||
"""This function will put pgAgent job"""
|
||||
data = {
|
||||
"jobdesc": "This is a test comment",
|
||||
}
|
||||
|
||||
response = self.tester.put(
|
||||
'{0}{1}/{2}/{3}'.format(
|
||||
self.url, str(utils.SERVER_GROUP), str(self.server_id),
|
||||
str(self.job_id)
|
||||
),
|
||||
data=json.dumps(data),
|
||||
follow_redirects=True,
|
||||
content_type='html/json'
|
||||
)
|
||||
self.assertEquals(response.status_code, 200)
|
||||
|
||||
def tearDown(self):
|
||||
"""Clean up code"""
|
||||
pgagent_utils.delete_pgagent_job(self)
|
||||
@@ -0,0 +1,45 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
import uuid
|
||||
from pgadmin.utils.route import BaseTestGenerator
|
||||
from regression.python_test_utils import test_utils as utils
|
||||
from . import utils as pgagent_utils
|
||||
|
||||
|
||||
class PgAgentGetTestCase(BaseTestGenerator):
|
||||
"""This class will test the get pgAgent job API"""
|
||||
scenarios = [
|
||||
('Get 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)
|
||||
name = "test_job_get%s" % str(uuid.uuid4())[1:8]
|
||||
self.job_id = pgagent_utils.create_pgagent_job(self, name)
|
||||
|
||||
def runTest(self):
|
||||
"""This function will get pgAgent job"""
|
||||
response = self.tester.get(
|
||||
'{0}{1}/{2}/{3}'.format(
|
||||
self.url, str(utils.SERVER_GROUP), str(self.server_id),
|
||||
str(self.job_id)
|
||||
),
|
||||
content_type='html/json'
|
||||
)
|
||||
self.assertEquals(response.status_code, 200)
|
||||
|
||||
def tearDown(self):
|
||||
"""Clean up code"""
|
||||
pgagent_utils.delete_pgagent_job(self)
|
||||
@@ -0,0 +1,45 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
import uuid
|
||||
from pgadmin.utils.route import BaseTestGenerator
|
||||
from regression.python_test_utils import test_utils as utils
|
||||
from . import utils as pgagent_utils
|
||||
|
||||
|
||||
class PgAgentStatsTestCase(BaseTestGenerator):
|
||||
"""This class will test the stats pgAgent job API"""
|
||||
scenarios = [
|
||||
('Check the stats of pgAgent job', dict(url='/browser/pga_job/stats/'))
|
||||
]
|
||||
|
||||
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_job_get%s" % str(uuid.uuid4())[1:8]
|
||||
self.job_id = pgagent_utils.create_pgagent_job(self, name)
|
||||
|
||||
def runTest(self):
|
||||
"""This function will check stats of pgAgent job"""
|
||||
response = self.tester.get(
|
||||
'{0}{1}/{2}/{3}'.format(
|
||||
self.url, str(utils.SERVER_GROUP), str(self.server_id),
|
||||
str(self.job_id)
|
||||
),
|
||||
content_type='html/json'
|
||||
)
|
||||
self.assertEquals(response.status_code, 200)
|
||||
|
||||
def tearDown(self):
|
||||
"""Clean up code"""
|
||||
pgagent_utils.delete_pgagent_job(self)
|
||||
175
web/pgadmin/browser/server_groups/servers/pgagent/tests/utils.py
Normal file
175
web/pgadmin/browser/server_groups/servers/pgagent/tests/utils.py
Normal file
@@ -0,0 +1,175 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
from regression.python_test_utils import test_utils as utils
|
||||
from regression import parent_node_dict
|
||||
from pgadmin.utils import server_utils as server_utils
|
||||
|
||||
|
||||
def is_valid_server_to_run_pgagent(self):
|
||||
"""
|
||||
This function checks if server is valid for the pgAgent job.
|
||||
"""
|
||||
self.server_id = parent_node_dict["server"][-1]["server_id"]
|
||||
server_con = server_utils.connect_server(self, self.server_id)
|
||||
if not server_con["info"] == "Server connected.":
|
||||
raise Exception("Could not connect to server to add pgAgent job.")
|
||||
if "type" in server_con["data"]:
|
||||
if server_con["data"]["type"] == "gpdb":
|
||||
message = "pgAgent is not supported by Greenplum."
|
||||
return False, message
|
||||
return True, None
|
||||
|
||||
|
||||
def is_pgagent_installed_on_server(self):
|
||||
"""
|
||||
This function checks if the pgAgent is installed properly.
|
||||
"""
|
||||
try:
|
||||
connection = utils.get_db_connection(
|
||||
self.server['db'],
|
||||
self.server['username'],
|
||||
self.server['db_password'],
|
||||
self.server['host'],
|
||||
self.server['port'],
|
||||
self.server['sslmode']
|
||||
)
|
||||
pg_cursor = connection.cursor()
|
||||
|
||||
SQL = """
|
||||
SELECT
|
||||
has_table_privilege(
|
||||
'pgagent.pga_job', 'INSERT, SELECT, UPDATE'
|
||||
) has_priviledge
|
||||
WHERE EXISTS(
|
||||
SELECT has_schema_privilege('pgagent', 'USAGE')
|
||||
WHERE EXISTS(
|
||||
SELECT cl.oid FROM pg_class cl
|
||||
LEFT JOIN pg_namespace ns ON ns.oid=relnamespace
|
||||
WHERE relname='pga_job' AND nspname='pgagent'
|
||||
)
|
||||
)
|
||||
"""
|
||||
pg_cursor.execute(SQL)
|
||||
result = pg_cursor.fetchone()
|
||||
if result is None:
|
||||
connection.close()
|
||||
message = "Make sure pgAgent is installed properly."
|
||||
return False, message
|
||||
|
||||
SQL = """
|
||||
SELECT EXISTS(
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE
|
||||
table_schema='pgagent' AND table_name='pga_jobstep' AND
|
||||
column_name='jstconnstr'
|
||||
) has_connstr
|
||||
"""
|
||||
pg_cursor.execute(SQL)
|
||||
result = pg_cursor.fetchone()
|
||||
if result is None:
|
||||
connection.close()
|
||||
message = "Make sure pgAgent is installed properly."
|
||||
return False, message
|
||||
|
||||
connection.close()
|
||||
return True, None
|
||||
except Exception:
|
||||
traceback.print_exc(file=sys.stderr)
|
||||
|
||||
|
||||
def create_pgagent_job(self, name):
|
||||
"""
|
||||
This function create the pgAgent job.
|
||||
"""
|
||||
try:
|
||||
connection = utils.get_db_connection(
|
||||
self.server['db'],
|
||||
self.server['username'],
|
||||
self.server['db_password'],
|
||||
self.server['host'],
|
||||
self.server['port'],
|
||||
self.server['sslmode']
|
||||
)
|
||||
old_isolation_level = connection.isolation_level
|
||||
connection.set_isolation_level(0)
|
||||
pg_cursor = connection.cursor()
|
||||
pg_cursor.execute(
|
||||
"""
|
||||
INSERT INTO pgagent.pga_job(
|
||||
jobjclid, jobname, jobdesc, jobhostagent, jobenabled
|
||||
) VALUES (
|
||||
1::integer, '{0}'::text, ''::text, ''::text, true
|
||||
) RETURNING jobid;
|
||||
""".format(name)
|
||||
)
|
||||
job_id = pg_cursor.fetchone()
|
||||
connection.set_isolation_level(old_isolation_level)
|
||||
connection.commit()
|
||||
connection.close()
|
||||
return job_id[0]
|
||||
except Exception:
|
||||
traceback.print_exc(file=sys.stderr)
|
||||
|
||||
|
||||
def delete_pgagent_job(self):
|
||||
"""
|
||||
This function deletes the pgAgent job.
|
||||
"""
|
||||
try:
|
||||
connection = utils.get_db_connection(
|
||||
self.server['db'],
|
||||
self.server['username'],
|
||||
self.server['db_password'],
|
||||
self.server['host'],
|
||||
self.server['port'],
|
||||
self.server['sslmode']
|
||||
)
|
||||
old_isolation_level = connection.isolation_level
|
||||
connection.set_isolation_level(0)
|
||||
pg_cursor = connection.cursor()
|
||||
pg_cursor.execute(
|
||||
"DELETE FROM pgagent.pga_job "
|
||||
"WHERE jobid = '%s'::integer;" % self.job_id
|
||||
)
|
||||
connection.set_isolation_level(old_isolation_level)
|
||||
connection.commit()
|
||||
connection.close()
|
||||
except Exception:
|
||||
traceback.print_exc(file=sys.stderr)
|
||||
|
||||
|
||||
def verify_pgagent_job(self):
|
||||
"""
|
||||
This function deletes the pgAgent job.
|
||||
"""
|
||||
try:
|
||||
connection = utils.get_db_connection(
|
||||
self.server['db'],
|
||||
self.server['username'],
|
||||
self.server['db_password'],
|
||||
self.server['host'],
|
||||
self.server['port'],
|
||||
self.server['sslmode']
|
||||
)
|
||||
pg_cursor = connection.cursor()
|
||||
pg_cursor.execute(
|
||||
"SELECT COUNT(*) FROM pgagent.pga_job "
|
||||
"WHERE jobid = '%s'::integer;" % self.job_id
|
||||
)
|
||||
result = pg_cursor.fetchone()
|
||||
count = result[0]
|
||||
connection.close()
|
||||
return count is not None and int(count) != 0
|
||||
except Exception:
|
||||
traceback.print_exc(file=sys.stderr)
|
||||
Reference in New Issue
Block a user