mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-05-28 03:49:09 -07:00
Unflatmap community.general (#5461)
* Move files. * Update imports and references. * Move wrongly placed files. * Reverse redirects, deprecate long → short name redirects. * Simplify contribution guidelines for new modules. * Rewrite BOTMETA. * Add changelog fragment. * Fix ignore.txt files.
This commit is contained in:
parent
2b0bebc8fc
commit
b531ecdc9b
1033 changed files with 4802 additions and 1989 deletions
263
plugins/modules/supervisorctl.py
Normal file
263
plugins/modules/supervisorctl.py
Normal file
|
@ -0,0 +1,263 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2012, Matt Wright <matt@nobien.net>
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: supervisorctl
|
||||
short_description: Manage the state of a program or group of programs running via supervisord
|
||||
description:
|
||||
- Manage the state of a program or group of programs running via supervisord
|
||||
options:
|
||||
name:
|
||||
type: str
|
||||
description:
|
||||
- The name of the supervisord program or group to manage.
|
||||
- The name will be taken as group name when it ends with a colon I(:)
|
||||
- Group support is only available in Ansible version 1.6 or later.
|
||||
- If I(name=all), all programs and program groups will be managed.
|
||||
required: true
|
||||
config:
|
||||
type: path
|
||||
description:
|
||||
- The supervisor configuration file path
|
||||
server_url:
|
||||
type: str
|
||||
description:
|
||||
- URL on which supervisord server is listening
|
||||
username:
|
||||
type: str
|
||||
description:
|
||||
- username to use for authentication
|
||||
password:
|
||||
type: str
|
||||
description:
|
||||
- password to use for authentication
|
||||
state:
|
||||
type: str
|
||||
description:
|
||||
- The desired state of program/group.
|
||||
required: true
|
||||
choices: [ "present", "started", "stopped", "restarted", "absent", "signalled" ]
|
||||
signal:
|
||||
type: str
|
||||
description:
|
||||
- The signal to send to the program/group, when combined with the 'signalled' state. Required when l(state=signalled).
|
||||
supervisorctl_path:
|
||||
type: path
|
||||
description:
|
||||
- path to supervisorctl executable
|
||||
notes:
|
||||
- When C(state) = I(present), the module will call C(supervisorctl reread) then C(supervisorctl add) if the program/group does not exist.
|
||||
- When C(state) = I(restarted), the module will call C(supervisorctl update) then call C(supervisorctl restart).
|
||||
- When C(state) = I(absent), the module will call C(supervisorctl reread) then C(supervisorctl remove) to remove the target program/group.
|
||||
requirements: [ "supervisorctl" ]
|
||||
author:
|
||||
- "Matt Wright (@mattupstate)"
|
||||
- "Aaron Wang (@inetfuture) <inetfuture@gmail.com>"
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: Manage the state of program to be in started state
|
||||
community.general.supervisorctl:
|
||||
name: my_app
|
||||
state: started
|
||||
|
||||
- name: Manage the state of program group to be in started state
|
||||
community.general.supervisorctl:
|
||||
name: 'my_apps:'
|
||||
state: started
|
||||
|
||||
- name: Restart my_app, reading supervisorctl configuration from a specified file
|
||||
community.general.supervisorctl:
|
||||
name: my_app
|
||||
state: restarted
|
||||
config: /var/opt/my_project/supervisord.conf
|
||||
|
||||
- name: Restart my_app, connecting to supervisord with credentials and server URL
|
||||
community.general.supervisorctl:
|
||||
name: my_app
|
||||
state: restarted
|
||||
username: test
|
||||
password: testpass
|
||||
server_url: http://localhost:9001
|
||||
|
||||
- name: Send a signal to my_app via supervisorctl
|
||||
community.general.supervisorctl:
|
||||
name: my_app
|
||||
state: signalled
|
||||
signal: USR1
|
||||
|
||||
- name: Restart all programs and program groups
|
||||
community.general.supervisorctl:
|
||||
name: all
|
||||
state: restarted
|
||||
'''
|
||||
|
||||
import os
|
||||
from ansible.module_utils.basic import AnsibleModule, is_executable
|
||||
|
||||
|
||||
def main():
|
||||
arg_spec = dict(
|
||||
name=dict(type='str', required=True),
|
||||
config=dict(type='path'),
|
||||
server_url=dict(type='str'),
|
||||
username=dict(type='str'),
|
||||
password=dict(type='str', no_log=True),
|
||||
supervisorctl_path=dict(type='path'),
|
||||
state=dict(type='str', required=True, choices=['present', 'started', 'restarted', 'stopped', 'absent', 'signalled']),
|
||||
signal=dict(type='str'),
|
||||
)
|
||||
|
||||
module = AnsibleModule(
|
||||
argument_spec=arg_spec,
|
||||
supports_check_mode=True,
|
||||
required_if=[('state', 'signalled', ['signal'])],
|
||||
)
|
||||
|
||||
name = module.params['name']
|
||||
is_group = False
|
||||
if name.endswith(':'):
|
||||
is_group = True
|
||||
name = name.rstrip(':')
|
||||
state = module.params['state']
|
||||
config = module.params.get('config')
|
||||
server_url = module.params.get('server_url')
|
||||
username = module.params.get('username')
|
||||
password = module.params.get('password')
|
||||
supervisorctl_path = module.params.get('supervisorctl_path')
|
||||
signal = module.params.get('signal')
|
||||
|
||||
# we check error message for a pattern, so we need to make sure that's in C locale
|
||||
module.run_command_environ_update = dict(LANG='C', LC_ALL='C', LC_MESSAGES='C', LC_CTYPE='C')
|
||||
|
||||
if supervisorctl_path:
|
||||
if os.path.exists(supervisorctl_path) and is_executable(supervisorctl_path):
|
||||
supervisorctl_args = [supervisorctl_path]
|
||||
else:
|
||||
module.fail_json(
|
||||
msg="Provided path to supervisorctl does not exist or isn't executable: %s" % supervisorctl_path)
|
||||
else:
|
||||
supervisorctl_args = [module.get_bin_path('supervisorctl', True)]
|
||||
|
||||
if config:
|
||||
supervisorctl_args.extend(['-c', config])
|
||||
if server_url:
|
||||
supervisorctl_args.extend(['-s', server_url])
|
||||
if username:
|
||||
supervisorctl_args.extend(['-u', username])
|
||||
if password:
|
||||
supervisorctl_args.extend(['-p', password])
|
||||
|
||||
def run_supervisorctl(cmd, name=None, **kwargs):
|
||||
args = list(supervisorctl_args) # copy the master args
|
||||
args.append(cmd)
|
||||
if name:
|
||||
args.append(name)
|
||||
return module.run_command(args, **kwargs)
|
||||
|
||||
def get_matched_processes():
|
||||
matched = []
|
||||
rc, out, err = run_supervisorctl('status')
|
||||
for line in out.splitlines():
|
||||
# One status line may look like one of these two:
|
||||
# process not in group:
|
||||
# echo_date_lonely RUNNING pid 7680, uptime 13:22:18
|
||||
# process in group:
|
||||
# echo_date_group:echo_date_00 RUNNING pid 7681, uptime 13:22:18
|
||||
fields = [field for field in line.split(' ') if field != '']
|
||||
process_name = fields[0]
|
||||
status = fields[1]
|
||||
|
||||
if is_group:
|
||||
# If there is ':', this process must be in a group.
|
||||
if ':' in process_name:
|
||||
group = process_name.split(':')[0]
|
||||
if group != name:
|
||||
continue
|
||||
else:
|
||||
continue
|
||||
else:
|
||||
if process_name != name and name != "all":
|
||||
continue
|
||||
|
||||
matched.append((process_name, status))
|
||||
return matched
|
||||
|
||||
def take_action_on_processes(processes, status_filter, action, expected_result):
|
||||
to_take_action_on = []
|
||||
for process_name, status in processes:
|
||||
if status_filter(status):
|
||||
to_take_action_on.append(process_name)
|
||||
|
||||
if len(to_take_action_on) == 0:
|
||||
module.exit_json(changed=False, name=name, state=state)
|
||||
if module.check_mode:
|
||||
module.exit_json(changed=True)
|
||||
for process_name in to_take_action_on:
|
||||
rc, out, err = run_supervisorctl(action, process_name, check_rc=True)
|
||||
if '%s: %s' % (process_name, expected_result) not in out:
|
||||
module.fail_json(msg=out)
|
||||
|
||||
module.exit_json(changed=True, name=name, state=state, affected=to_take_action_on)
|
||||
|
||||
if state == 'restarted':
|
||||
rc, out, err = run_supervisorctl('update', check_rc=True)
|
||||
processes = get_matched_processes()
|
||||
if len(processes) == 0:
|
||||
module.fail_json(name=name, msg="ERROR (no such process)")
|
||||
|
||||
take_action_on_processes(processes, lambda s: True, 'restart', 'started')
|
||||
|
||||
processes = get_matched_processes()
|
||||
|
||||
if state == 'absent':
|
||||
if len(processes) == 0:
|
||||
module.exit_json(changed=False, name=name, state=state)
|
||||
|
||||
if module.check_mode:
|
||||
module.exit_json(changed=True)
|
||||
run_supervisorctl('reread', check_rc=True)
|
||||
rc, out, err = run_supervisorctl('remove', name)
|
||||
if '%s: removed process group' % name in out:
|
||||
module.exit_json(changed=True, name=name, state=state)
|
||||
else:
|
||||
module.fail_json(msg=out, name=name, state=state)
|
||||
|
||||
if state == 'present':
|
||||
if len(processes) > 0:
|
||||
module.exit_json(changed=False, name=name, state=state)
|
||||
|
||||
if module.check_mode:
|
||||
module.exit_json(changed=True)
|
||||
run_supervisorctl('reread', check_rc=True)
|
||||
dummy, out, dummy = run_supervisorctl('add', name)
|
||||
if '%s: added process group' % name in out:
|
||||
module.exit_json(changed=True, name=name, state=state)
|
||||
else:
|
||||
module.fail_json(msg=out, name=name, state=state)
|
||||
|
||||
# from this point onwards, if there are no matching processes, module cannot go on.
|
||||
if len(processes) == 0:
|
||||
module.fail_json(name=name, msg="ERROR (no such process)")
|
||||
|
||||
if state == 'started':
|
||||
take_action_on_processes(processes, lambda s: s not in ('RUNNING', 'STARTING'), 'start', 'started')
|
||||
|
||||
if state == 'stopped':
|
||||
take_action_on_processes(processes, lambda s: s in ('RUNNING', 'STARTING'), 'stop', 'stopped')
|
||||
|
||||
if state == 'signalled':
|
||||
take_action_on_processes(processes, lambda s: s in ('RUNNING',), "signal %s" % signal, 'signalled')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Add table
Add a link
Reference in a new issue