Files
offline_kubespray/collection/community/proxysql/plugins/modules/proxysql_scheduler.py
ByeonJungHun 360c6eef4a offline 작업
2024-02-19 16:02:29 +09:00

410 lines
13 KiB
Python

#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright: (c) 2017, Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = '''
---
module: proxysql_scheduler
author: "Ben Mildren (@bmildren)"
short_description: Adds or removes schedules from proxysql admin interface
description:
- The M(community.proxysql.proxysql_scheduler) module adds or removes schedules using the
proxysql admin interface.
options:
active:
description:
- A schedule with I(active) set to C(False) will be tracked in the
database, but will be never loaded in the in-memory data structures.
type: bool
default: True
interval_ms:
description:
- How often (in millisecond) the job will be started. The minimum value
for I(interval_ms) is 100 milliseconds.
type: int
default: 10000
filename:
description:
- Full path of the executable to be executed.
type: str
required: True
arg1:
description:
- Argument that can be passed to the job.
type: str
arg2:
description:
- Argument that can be passed to the job.
type: str
arg3:
description:
- Argument that can be passed to the job.
type: str
arg4:
description:
- Argument that can be passed to the job.
type: str
arg5:
description:
- Argument that can be passed to the job.
type: str
comment:
description:
- Text field that can be used for any purposed defined by the user.
type: str
state:
description:
- When C(present) - adds the schedule, when C(absent) - removes the
schedule.
type: str
choices: [ "present", "absent" ]
default: present
force_delete:
description:
- By default we avoid deleting more than one schedule in a single batch,
however if you need this behaviour and you are not concerned about the
schedules deleted, you can set I(force_delete) to C(True).
type: bool
default: False
extends_documentation_fragment:
- community.proxysql.proxysql.managing_config
- community.proxysql.proxysql.connectivity
notes:
- Supports C(check_mode).
'''
EXAMPLES = '''
---
# This example adds a schedule, it saves the scheduler config to disk, but
# avoids loading the scheduler config to runtime (this might be because
# several servers are being added and the user wants to push the config to
# runtime in a single batch using the community.general.proxysql_manage_config
# module). It uses supplied credentials to connect to the proxysql admin
# interface.
- name: Add a schedule
community.proxysql.proxysql_scheduler:
login_user: 'admin'
login_password: 'admin'
interval_ms: 1000
filename: "/opt/maintenance.py"
state: present
load_to_runtime: False
# This example removes a schedule, saves the scheduler config to disk, and
# dynamically loads the scheduler config to runtime. It uses credentials
# in a supplied config file to connect to the proxysql admin interface.
- name: Remove a schedule
community.proxysql.proxysql_scheduler:
config_file: '~/proxysql.cnf'
filename: "/opt/old_script.py"
state: absent
'''
RETURN = '''
stdout:
description: The schedule modified or removed from proxysql.
returned: On create/update will return the newly modified schedule, on
delete it will return the deleted record.
type: dict
"sample": {
"changed": true,
"filename": "/opt/test.py",
"msg": "Added schedule to scheduler",
"schedules": [
{
"active": "1",
"arg1": null,
"arg2": null,
"arg3": null,
"arg4": null,
"arg5": null,
"comment": "",
"filename": "/opt/test.py",
"id": "1",
"interval_ms": "10000"
}
],
"state": "present"
}
'''
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.community.proxysql.plugins.module_utils.mysql import (
mysql_connect,
mysql_driver,
proxysql_common_argument_spec,
save_config_to_disk,
load_config_to_runtime,
)
from ansible.module_utils.six import iteritems
from ansible.module_utils._text import to_native
# ===========================================
# proxysql module specific support methods.
#
def perform_checks(module):
if module.params["interval_ms"] < 100 \
or module.params["interval_ms"] > 100000000:
module.fail_json(
msg="interval_ms must between 100ms & 100000000ms"
)
class ProxySQLSchedule(object):
def __init__(self, module):
self.state = module.params["state"]
self.force_delete = module.params["force_delete"]
self.save_to_disk = module.params["save_to_disk"]
self.load_to_runtime = module.params["load_to_runtime"]
self.active = module.params["active"]
self.interval_ms = module.params["interval_ms"]
self.filename = module.params["filename"]
config_data_keys = ["arg1",
"arg2",
"arg3",
"arg4",
"arg5",
"comment"]
self.config_data = dict((k, module.params[k])
for k in config_data_keys)
def check_schedule_config(self, cursor):
query_string = \
"""SELECT count(*) AS `schedule_count`
FROM scheduler
WHERE active = %s
AND interval_ms = %s
AND filename = %s"""
query_data = \
[self.active,
self.interval_ms,
self.filename]
for col, val in iteritems(self.config_data):
if val is not None:
query_data.append(val)
query_string += "\n AND " + col + " = %s"
cursor.execute(query_string, query_data)
check_count = cursor.fetchone()
return int(check_count['schedule_count'])
def get_schedule_config(self, cursor):
query_string = \
"""SELECT *
FROM scheduler
WHERE active = %s
AND interval_ms = %s
AND filename = %s"""
query_data = \
[self.active,
self.interval_ms,
self.filename]
for col, val in iteritems(self.config_data):
if val is not None:
query_data.append(val)
query_string += "\n AND " + col + " = %s"
cursor.execute(query_string, query_data)
schedule = cursor.fetchall()
return schedule
def create_schedule_config(self, cursor):
query_string = \
"""INSERT INTO scheduler (
active,
interval_ms,
filename"""
cols = 0
query_data = \
[self.active,
self.interval_ms,
self.filename]
for col, val in iteritems(self.config_data):
if val is not None:
cols += 1
query_data.append(val)
query_string += ",\n" + col
query_string += \
(")\n" +
"VALUES (%s, %s, %s" +
", %s" * cols +
")")
cursor.execute(query_string, query_data)
return True
def delete_schedule_config(self, cursor):
query_string = \
"""DELETE FROM scheduler
WHERE active = %s
AND interval_ms = %s
AND filename = %s"""
query_data = \
[self.active,
self.interval_ms,
self.filename]
for col, val in iteritems(self.config_data):
if val is not None:
query_data.append(val)
query_string += "\n AND " + col + " = %s"
cursor.execute(query_string, query_data)
check_count = cursor.rowcount
return True, int(check_count)
def manage_config(self, cursor, state):
if state:
if self.save_to_disk:
save_config_to_disk(cursor, "SCHEDULER")
if self.load_to_runtime:
load_config_to_runtime(cursor, "SCHEDULER")
def create_schedule(self, check_mode, result, cursor):
if not check_mode:
result['changed'] = \
self.create_schedule_config(cursor)
result['msg'] = "Added schedule to scheduler"
result['schedules'] = \
self.get_schedule_config(cursor)
self.manage_config(cursor,
result['changed'])
else:
result['changed'] = True
result['msg'] = ("Schedule would have been added to" +
" scheduler, however check_mode" +
" is enabled.")
def delete_schedule(self, check_mode, result, cursor):
if not check_mode:
result['schedules'] = \
self.get_schedule_config(cursor)
result['changed'] = \
self.delete_schedule_config(cursor)
result['msg'] = "Deleted schedule from scheduler"
self.manage_config(cursor,
result['changed'])
else:
result['changed'] = True
result['msg'] = ("Schedule would have been deleted from" +
" scheduler, however check_mode is" +
" enabled.")
# ===========================================
# Module execution.
#
def main():
argument_spec = proxysql_common_argument_spec()
argument_spec.update(
active=dict(default=True, type='bool'),
interval_ms=dict(default=10000, type='int'),
filename=dict(required=True, type='str'),
arg1=dict(type='str'),
arg2=dict(type='str'),
arg3=dict(type='str'),
arg4=dict(type='str'),
arg5=dict(type='str'),
comment=dict(type='str'),
state=dict(default='present', choices=['present',
'absent']),
force_delete=dict(default=False, type='bool'),
save_to_disk=dict(default=True, type='bool'),
load_to_runtime=dict(default=True, type='bool')
)
module = AnsibleModule(
supports_check_mode=True,
argument_spec=argument_spec
)
perform_checks(module)
login_user = module.params["login_user"]
login_password = module.params["login_password"]
config_file = module.params["config_file"]
cursor = None
try:
cursor, db_conn, version = mysql_connect(module,
login_user,
login_password,
config_file,
cursor_class='DictCursor')
except mysql_driver.Error as e:
module.fail_json(
msg="unable to connect to ProxySQL Admin Module.. %s" % to_native(e)
)
proxysql_schedule = ProxySQLSchedule(module)
result = {}
result['state'] = proxysql_schedule.state
result['filename'] = proxysql_schedule.filename
if proxysql_schedule.state == "present":
try:
if proxysql_schedule.check_schedule_config(cursor) <= 0:
proxysql_schedule.create_schedule(module.check_mode,
result,
cursor)
else:
result['changed'] = False
result['msg'] = ("The schedule already exists and doesn't" +
" need to be updated.")
result['schedules'] = \
proxysql_schedule.get_schedule_config(cursor)
except mysql_driver.Error as e:
module.fail_json(
msg="unable to modify schedule.. %s" % to_native(e)
)
elif proxysql_schedule.state == "absent":
try:
existing_schedules = \
proxysql_schedule.check_schedule_config(cursor)
if existing_schedules > 0:
if existing_schedules == 1 or proxysql_schedule.force_delete:
proxysql_schedule.delete_schedule(module.check_mode,
result,
cursor)
else:
module.fail_json(
msg=("Operation would delete multiple records" +
" use force_delete to override this")
)
else:
result['changed'] = False
result['msg'] = ("The schedule is already absent from the" +
" memory configuration")
except mysql_driver.Error as e:
module.fail_json(
msg="unable to remove schedule.. %s" % to_native(e)
)
module.exit_json(**result)
if __name__ == '__main__':
main()