|
|
@ -23,70 +23,74 @@ import os
|
|
|
|
DOCUMENTATION = '''
|
|
|
|
DOCUMENTATION = '''
|
|
|
|
---
|
|
|
|
---
|
|
|
|
module: supervisorctl
|
|
|
|
module: supervisorctl
|
|
|
|
short_description: Manage the state of a program or group of programs running via Supervisord
|
|
|
|
short_description: Manage the state of a program or group of programs running via supervisord
|
|
|
|
description:
|
|
|
|
description:
|
|
|
|
- Manage the state of a program or group of programs running via I(Supervisord)
|
|
|
|
- Manage the state of a program or group of programs running via supervisord
|
|
|
|
version_added: "0.7"
|
|
|
|
version_added: "0.7"
|
|
|
|
options:
|
|
|
|
options:
|
|
|
|
name:
|
|
|
|
name:
|
|
|
|
description:
|
|
|
|
description:
|
|
|
|
- The name of the I(supervisord) program/process to manage
|
|
|
|
- The name of the supervisord program/group to manage. It will be taken as group name when it end with a colon I(:).
|
|
|
|
required: true
|
|
|
|
required: true
|
|
|
|
default: null
|
|
|
|
default: null
|
|
|
|
config:
|
|
|
|
config:
|
|
|
|
description:
|
|
|
|
description:
|
|
|
|
- configuration file path, passed as -c to supervisorctl
|
|
|
|
- configuration file path, passed as -c to supervisorctl.
|
|
|
|
required: false
|
|
|
|
required: false
|
|
|
|
default: null
|
|
|
|
default: null
|
|
|
|
version_added: "1.3"
|
|
|
|
version_added: "1.3"
|
|
|
|
server_url:
|
|
|
|
server_url:
|
|
|
|
description:
|
|
|
|
description:
|
|
|
|
- URL on which supervisord server is listening, passed as -s to supervisorctl
|
|
|
|
- URL on which supervisord server is listening, passed as -s to supervisorctl.
|
|
|
|
required: false
|
|
|
|
required: false
|
|
|
|
default: null
|
|
|
|
default: null
|
|
|
|
version_added: "1.3"
|
|
|
|
version_added: "1.3"
|
|
|
|
username:
|
|
|
|
username:
|
|
|
|
description:
|
|
|
|
description:
|
|
|
|
- username to use for authentication with server, passed as -u to supervisorctl
|
|
|
|
- username to use for authentication with server, passed as -u to supervisorctl.
|
|
|
|
required: false
|
|
|
|
required: false
|
|
|
|
default: null
|
|
|
|
default: null
|
|
|
|
version_added: "1.3"
|
|
|
|
version_added: "1.3"
|
|
|
|
password:
|
|
|
|
password:
|
|
|
|
description:
|
|
|
|
description:
|
|
|
|
- password to use for authentication with server, passed as -p to supervisorctl
|
|
|
|
- password to use for authentication with server, passed as -p to supervisorctl.
|
|
|
|
required: false
|
|
|
|
required: false
|
|
|
|
default: null
|
|
|
|
default: null
|
|
|
|
version_added: "1.3"
|
|
|
|
version_added: "1.3"
|
|
|
|
state:
|
|
|
|
state:
|
|
|
|
description:
|
|
|
|
description:
|
|
|
|
- The state of service
|
|
|
|
- The desired state of program/group. Affected programs' name will be returned in I(affected) field of the result.
|
|
|
|
required: true
|
|
|
|
required: true
|
|
|
|
default: null
|
|
|
|
default: null
|
|
|
|
choices: [ "present", "started", "stopped", "restarted" ]
|
|
|
|
choices: [ "present", "started", "stopped", "restarted" ]
|
|
|
|
supervisorctl_path:
|
|
|
|
supervisorctl_path:
|
|
|
|
description:
|
|
|
|
description:
|
|
|
|
- Path to supervisorctl executable to use
|
|
|
|
- Path to supervisorctl executable to use.
|
|
|
|
required: false
|
|
|
|
required: false
|
|
|
|
default: null
|
|
|
|
default: null
|
|
|
|
version_added: "1.4"
|
|
|
|
version_added: "1.4"
|
|
|
|
requirements:
|
|
|
|
notes:
|
|
|
|
- supervisorctl
|
|
|
|
- When C(state) = I(present), will call C(supervisorctl reread) then call C(supervisorctl add) if the program/group is not exists.
|
|
|
|
requirements: [ ]
|
|
|
|
- When C(state) = I(restarted), will call C(supervisorctl update) then call C(supervisorctl restart).
|
|
|
|
author: Matt Wright
|
|
|
|
requirements: [ "supervisorctl" ]
|
|
|
|
|
|
|
|
author: Matt Wright, Aaron Wang <inetfuture@gmail.com>
|
|
|
|
'''
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
|
|
EXAMPLES = '''
|
|
|
|
EXAMPLES = '''
|
|
|
|
# Manage the state of program to be in 'started' state.
|
|
|
|
# Manage the state of program to be in 'started' state.
|
|
|
|
- supervisorctl: name=my_app state=started
|
|
|
|
- supervisorctl: name=my_app state=started
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Manage the state of program group to be in 'started' state.
|
|
|
|
|
|
|
|
- supervisorctl: name='my_apps:' state=started
|
|
|
|
|
|
|
|
|
|
|
|
# Restart my_app, reading supervisorctl configuration from a specified file.
|
|
|
|
# Restart my_app, reading supervisorctl configuration from a specified file.
|
|
|
|
- supervisorctl: name=my_app state=restarted config=/var/opt/my_project/supervisord.conf
|
|
|
|
- supervisorctl: name=my_app state=restarted config=/var/opt/my_project/supervisord.conf
|
|
|
|
|
|
|
|
|
|
|
|
# Restart my_app, connecting to supervisord with credentials and server URL.
|
|
|
|
# Restart my_app, connecting to supervisord with credentials and server URL.
|
|
|
|
- supervisorctl: name=my_app state=restarted username=test password=testpass server_url=http://localhost:9001
|
|
|
|
- supervisorctl: name=my_app state=restarted username=test password=testpass server_url=http://localhost:9001
|
|
|
|
|
|
|
|
|
|
|
|
'''
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
def main():
|
|
|
|
arg_spec = dict(
|
|
|
|
arg_spec = dict(
|
|
|
|
name=dict(required=True),
|
|
|
|
name=dict(required=True),
|
|
|
@ -101,6 +105,10 @@ def main():
|
|
|
|
module = AnsibleModule(argument_spec=arg_spec, supports_check_mode=True)
|
|
|
|
module = AnsibleModule(argument_spec=arg_spec, supports_check_mode=True)
|
|
|
|
|
|
|
|
|
|
|
|
name = module.params['name']
|
|
|
|
name = module.params['name']
|
|
|
|
|
|
|
|
is_group = False
|
|
|
|
|
|
|
|
if name.endswith(':'):
|
|
|
|
|
|
|
|
is_group = True
|
|
|
|
|
|
|
|
name = name.rstrip(':')
|
|
|
|
state = module.params['state']
|
|
|
|
state = module.params['state']
|
|
|
|
config = module.params.get('config')
|
|
|
|
config = module.params.get('config')
|
|
|
|
server_url = module.params.get('server_url')
|
|
|
|
server_url = module.params.get('server_url')
|
|
|
@ -113,7 +121,8 @@ def main():
|
|
|
|
if os.path.exists(supervisorctl_path) and module.is_executable(supervisorctl_path):
|
|
|
|
if os.path.exists(supervisorctl_path) and module.is_executable(supervisorctl_path):
|
|
|
|
supervisorctl_args = [supervisorctl_path]
|
|
|
|
supervisorctl_args = [supervisorctl_path]
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
module.fail_json(msg="Provided path to supervisorctl does not exist or isn't executable: %s" % supervisorctl_path)
|
|
|
|
module.fail_json(
|
|
|
|
|
|
|
|
msg="Provided path to supervisorctl does not exist or isn't executable: %s" % supervisorctl_path)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
supervisorctl_args = [module.get_bin_path('supervisorctl', True)]
|
|
|
|
supervisorctl_args = [module.get_bin_path('supervisorctl', True)]
|
|
|
|
|
|
|
|
|
|
|
@ -133,61 +142,76 @@ def main():
|
|
|
|
args.append(name)
|
|
|
|
args.append(name)
|
|
|
|
return module.run_command(args, **kwargs)
|
|
|
|
return module.run_command(args, **kwargs)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_matched_processes():
|
|
|
|
|
|
|
|
matched = []
|
|
|
|
rc, out, err = run_supervisorctl('status')
|
|
|
|
rc, out, err = run_supervisorctl('status')
|
|
|
|
present = name in out
|
|
|
|
for line in out.splitlines():
|
|
|
|
|
|
|
|
# One status line may look like one of these two:
|
|
|
|
if state == 'present':
|
|
|
|
# process not in group:
|
|
|
|
if not present:
|
|
|
|
# echo_date_lonely RUNNING pid 7680, uptime 13:22:18
|
|
|
|
if module.check_mode:
|
|
|
|
# process in group:
|
|
|
|
module.exit_json(changed=True)
|
|
|
|
# echo_date_group:echo_date_00 RUNNING pid 7681, uptime 13:22:18
|
|
|
|
run_supervisorctl('reread', check_rc=True)
|
|
|
|
fields = [field for field in line.split(' ') if field != '']
|
|
|
|
rc, out, err = run_supervisorctl('add', name)
|
|
|
|
process_name = fields[0]
|
|
|
|
|
|
|
|
status = fields[1]
|
|
|
|
if '%s: added process group' % name in out:
|
|
|
|
|
|
|
|
module.exit_json(changed=True, name=name, state=state)
|
|
|
|
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:
|
|
|
|
else:
|
|
|
|
module.fail_json(msg=out, name=name, state=state)
|
|
|
|
continue
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
if process_name != name:
|
|
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
|
|
module.exit_json(changed=False, name=name, state=state)
|
|
|
|
matched.append((process_name, status))
|
|
|
|
|
|
|
|
return matched
|
|
|
|
|
|
|
|
|
|
|
|
rc, out, err = run_supervisorctl('status', name)
|
|
|
|
def take_action_on_processes(processes, status_filter, action, expected_result):
|
|
|
|
running = 'RUNNING' in out or '(already running)' in out
|
|
|
|
to_take_action_on = []
|
|
|
|
|
|
|
|
for process_name, status in processes:
|
|
|
|
|
|
|
|
if status_filter(status):
|
|
|
|
|
|
|
|
to_take_action_on.append(process_name)
|
|
|
|
|
|
|
|
|
|
|
|
if running and state == 'started':
|
|
|
|
if len(to_take_action_on) == 0:
|
|
|
|
module.exit_json(changed=False, name=name, state=state)
|
|
|
|
module.exit_json(changed=False, name=name, state=state)
|
|
|
|
|
|
|
|
|
|
|
|
if running and state == 'stopped':
|
|
|
|
|
|
|
|
if module.check_mode:
|
|
|
|
if module.check_mode:
|
|
|
|
module.exit_json(changed=True)
|
|
|
|
module.exit_json(changed=True)
|
|
|
|
rc, out, err = run_supervisorctl('stop', name)
|
|
|
|
for process_name in to_take_action_on:
|
|
|
|
|
|
|
|
rc, out, err = run_supervisorctl(action, process_name)
|
|
|
|
if '%s: stopped' % name in out:
|
|
|
|
if '%s: %s' % (process_name, expected_result) not in out:
|
|
|
|
module.exit_json(changed=True, name=name, state=state)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
module.fail_json(msg=out)
|
|
|
|
module.fail_json(msg=out)
|
|
|
|
|
|
|
|
|
|
|
|
elif state == 'restarted':
|
|
|
|
module.exit_json(changed=True, name=name, state=state, affected=to_take_action_on)
|
|
|
|
if module.check_mode:
|
|
|
|
|
|
|
|
module.exit_json(changed=True)
|
|
|
|
|
|
|
|
rc, out, err = run_supervisorctl('update', name)
|
|
|
|
|
|
|
|
rc, out, err = run_supervisorctl('restart', name)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if '%s: started' % name in out:
|
|
|
|
if state == 'restarted':
|
|
|
|
module.exit_json(changed=True, name=name, state=state)
|
|
|
|
rc, out, err = run_supervisorctl('update')
|
|
|
|
|
|
|
|
processes = get_matched_processes()
|
|
|
|
|
|
|
|
take_action_on_processes(processes, lambda s: True, 'restart', 'started')
|
|
|
|
|
|
|
|
|
|
|
|
module.fail_json(msg=out)
|
|
|
|
processes = get_matched_processes()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if state == 'present':
|
|
|
|
|
|
|
|
if len(processes) > 0:
|
|
|
|
|
|
|
|
module.exit_json(changed=False, name=name, state=state)
|
|
|
|
|
|
|
|
|
|
|
|
elif not running and state == 'started':
|
|
|
|
|
|
|
|
if module.check_mode:
|
|
|
|
if module.check_mode:
|
|
|
|
module.exit_json(changed=True)
|
|
|
|
module.exit_json(changed=True)
|
|
|
|
rc, out, err = run_supervisorctl('start',name)
|
|
|
|
run_supervisorctl('reread', check_rc=True)
|
|
|
|
|
|
|
|
rc, out, err = run_supervisorctl('add', name)
|
|
|
|
if '%s: started' % name in out:
|
|
|
|
if '%s: added process group' % name in out:
|
|
|
|
module.exit_json(changed=True, name=name, state=state)
|
|
|
|
module.exit_json(changed=True, name=name, state=state)
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
module.fail_json(msg=out, name=name, state=state)
|
|
|
|
|
|
|
|
|
|
|
|
module.fail_json(msg=out)
|
|
|
|
if state == 'started':
|
|
|
|
|
|
|
|
take_action_on_processes(processes, lambda s: s != 'RUNNING', 'start', 'started')
|
|
|
|
|
|
|
|
|
|
|
|
module.exit_json(changed=False, name=name, state=state)
|
|
|
|
if state == 'stopped':
|
|
|
|
|
|
|
|
take_action_on_processes(processes, lambda s: s == 'RUNNING', 'stop', 'stopped')
|
|
|
|
|
|
|
|
|
|
|
|
# import module snippets
|
|
|
|
# import module snippets
|
|
|
|
from ansible.module_utils.basic import *
|
|
|
|
from ansible.module_utils.basic import *
|
|
|
|