Initial version of nextcloud collection
Signed-off-by: Nis Wechselberg <enbewe@enbewe.de>
This commit is contained in:
parent
e559257349
commit
87eac5bded
13 changed files with 911 additions and 0 deletions
279
plugins/modules/nextcloud_app.py
Normal file
279
plugins/modules/nextcloud_app.py
Normal file
|
@ -0,0 +1,279 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright: Nis Wechselberg <enbewe@enbewe.de>
|
||||
# MIT License (see https://spdx.org/licenses/MIT.html)
|
||||
# Based upon code by s3lph <s3lph@kabelsalat.ch>
|
||||
# MIT License (see https://spdx.org/licenses/MIT.html)
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: nextcloud_app
|
||||
|
||||
short_description: Enable or disable Nextcloud apps.
|
||||
|
||||
version_added: "1.0.0"
|
||||
|
||||
description: Enable or disable Nextcloud apps via C(occ app:) in the running container.
|
||||
|
||||
options:
|
||||
name:
|
||||
description: Name of the app or apps to install/remove/enable/disable.
|
||||
required: true
|
||||
type: list
|
||||
elements: str
|
||||
state:
|
||||
description: State the app or apps should be in.
|
||||
required: false
|
||||
default: enabled
|
||||
type: str
|
||||
choices:
|
||||
- enabled
|
||||
- disabled
|
||||
- absent
|
||||
force:
|
||||
description: Install and enable apps that are not compatible with the current Nextcloud version.
|
||||
required: false
|
||||
default: false
|
||||
type: bool
|
||||
engine:
|
||||
description: Engine to use for the OCI runtime.
|
||||
required: false
|
||||
default: podman
|
||||
type: str
|
||||
container_user:
|
||||
description: The user to run the occ command as while in the container.
|
||||
required: false
|
||||
default: www-data
|
||||
type: str
|
||||
container_name:
|
||||
description: The name of the container to run the command in.
|
||||
required: false
|
||||
default: nextcloud-app
|
||||
type: str
|
||||
|
||||
author:
|
||||
- Nis Wechselberg
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
- name: Install and enable photos app
|
||||
enbewe.nextcloud.nextcloud_app:
|
||||
name: photos
|
||||
|
||||
- name: Install and enable PIM apps
|
||||
enbewe.nextcloud.nextcloud_app:
|
||||
name:
|
||||
- contacts
|
||||
- calendar
|
||||
- mail
|
||||
|
||||
- name: Disable resource hungry dashboard
|
||||
enbewe.nextcloud.nextcloud_app:
|
||||
name: dashboard
|
||||
state: disabled
|
||||
'''
|
||||
|
||||
RETURN = r'''
|
||||
'''
|
||||
|
||||
import json
|
||||
import subprocess
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
||||
def check_nextcloud_status(module, result):
|
||||
'''
|
||||
Gather nextcloud status through calling `occ status`.
|
||||
'''
|
||||
sc = subprocess.run([module.params['engine'], 'exec',
|
||||
'--user', module.params['container_user'],
|
||||
module.params['container_name'],
|
||||
'php', 'occ', 'status', '--output=json'],
|
||||
capture_output=True, encoding='utf-8', check=False)
|
||||
if sc.returncode != 0:
|
||||
result['stdout'] = sc.stdout
|
||||
result['stderr'] = sc.stderr
|
||||
module.fail_json(
|
||||
msg='occ status returned non-zero exit code. Run with -vvv to view the output',
|
||||
**result)
|
||||
|
||||
status = json.loads(sc.stdout)
|
||||
if not status['installed']:
|
||||
module.fail_json(
|
||||
msg='Nextcloud installation has not been completed, so occ app is not available.',
|
||||
**result)
|
||||
|
||||
def get_app_status(module, result):
|
||||
'''
|
||||
Gather state of installed apps in nextcloud.
|
||||
'''
|
||||
# Gather Nextcloud app list
|
||||
ac = subprocess.run([module.params['engine'], 'exec',
|
||||
'--user', module.params['container_user'],
|
||||
module.params['container_name'],
|
||||
'php', 'occ', 'app:list', '--output=json'],
|
||||
capture_output=True, encoding='utf-8', check=False)
|
||||
if ac.returncode != 0:
|
||||
result['stdout'] = ac.stdout
|
||||
result['stderr'] = ac.stderr
|
||||
module.fail_json(
|
||||
msg='occ app:list returned non-zero exit code. Run with -vvv to view the output',
|
||||
**result)
|
||||
|
||||
return json.loads(ac.stdout)
|
||||
|
||||
def remove_app(module, result, app):
|
||||
'''
|
||||
Remove the given app from the installation.
|
||||
'''
|
||||
result['changed'] = True
|
||||
if not module.check_mode:
|
||||
c = subprocess.run([module.params['engine'], 'exec',
|
||||
'--user', module.params['container_user'],
|
||||
module.params['container_name'],
|
||||
'php', 'occ', 'app:remove', '--keep-data', app],
|
||||
capture_output=True, encoding='utf-8', check=False)
|
||||
if c.returncode != 0:
|
||||
result['stdout'] = c.stdout
|
||||
result['stderr'] = c.stderr
|
||||
module.fail_json(
|
||||
msg='occ app:remove returned non-zero exit code. Run with -vvv to view the output',
|
||||
**result)
|
||||
|
||||
def install_app(module, result, app):
|
||||
'''
|
||||
Install the given app to the installation.
|
||||
'''
|
||||
state = module.params['state']
|
||||
result['changed'] = True
|
||||
if not module.check_mode:
|
||||
cmdline = [module.params['engine'], 'exec',
|
||||
'--user', module.params['container_user'],
|
||||
module.params['container_name'],
|
||||
'php', 'occ', 'app:install']
|
||||
if state == 'disabled':
|
||||
cmdline.append('--keep-disabled')
|
||||
if module.params['force']:
|
||||
cmdline.append('--force')
|
||||
cmdline.append(app)
|
||||
c = subprocess.run(cmdline,
|
||||
capture_output=True, encoding='utf-8', check=False)
|
||||
if c.returncode != 0:
|
||||
result['stdout'] = c.stdout
|
||||
result['stderr'] = c.stderr
|
||||
module.fail_json(
|
||||
msg='occ app:install returned non-zero exit code. Run with -vvv to view the output',
|
||||
**result)
|
||||
|
||||
def enable_app(module, result, app):
|
||||
'''
|
||||
Enable the (already installed) app.
|
||||
'''
|
||||
result['changed'] = True
|
||||
if not module.check_mode:
|
||||
cmdline = [module.params['engine'], 'exec',
|
||||
'--user', module.params['container_user'],
|
||||
module.params['container_name'],
|
||||
'php', 'occ', 'app:enable']
|
||||
if module.params['force']:
|
||||
cmdline.append('--force')
|
||||
cmdline.append(app)
|
||||
c = subprocess.run(cmdline,
|
||||
capture_output=True, encoding='utf-8', check=False)
|
||||
if c.returncode != 0:
|
||||
result['stdout'] = c.stdout
|
||||
result['stderr'] = c.stderr
|
||||
module.fail_json(
|
||||
msg='occ app:enable returned non-zero exit code. Run with -vvv to view the output',
|
||||
**result)
|
||||
|
||||
def disable_app(module, result, app):
|
||||
'''
|
||||
Disable the given app without removing it.
|
||||
'''
|
||||
result['changed'] = True
|
||||
if not module.check_mode:
|
||||
c = subprocess.run([module.params['engine'], 'exec',
|
||||
'--user', module.params['container_user'],
|
||||
module.params['container_name'],
|
||||
'php', 'occ', 'app:disable', app],
|
||||
capture_output=True, encoding='utf-8', check=False)
|
||||
if c.returncode != 0:
|
||||
result['stdout'] = c.stdout
|
||||
result['stderr'] = c.stderr
|
||||
module.fail_json(
|
||||
msg='occ app:disable returned non-zero exit code. Run with -vvv to view the output',
|
||||
**result)
|
||||
|
||||
def apply_app_status(module, result, app_status):
|
||||
'''
|
||||
Apply the status from the configuration to the applications in nextcloud.
|
||||
'''
|
||||
state = module.params['state']
|
||||
apps = module.params['name']
|
||||
if isinstance(apps, str):
|
||||
apps = [apps]
|
||||
|
||||
# Apply app configuration changes
|
||||
for app in apps:
|
||||
if state == 'absent' and (app in app_status['enabled'] or app in app_status['disabled']):
|
||||
remove_app(module, result, app)
|
||||
elif (state in ['enabled', 'disabled']
|
||||
and app not in app_status['enabled']
|
||||
and app not in app_status['disabled']):
|
||||
install_app(module, result, app)
|
||||
elif state == 'enabled' and app in app_status['disabled']:
|
||||
enable_app(module, result, app)
|
||||
elif state == 'disabled' and app in app_status['enabled']:
|
||||
disable_app(module, result, app)
|
||||
|
||||
def run_module():
|
||||
'''
|
||||
Run the ansible module code.
|
||||
'''
|
||||
# define available arguments/parameters a user can pass to the module
|
||||
module_args = {
|
||||
'name': { 'required': True, 'type': 'list' },
|
||||
'state': { 'required': False, 'default': 'enabled', 'type': 'str' },
|
||||
'force': { 'required': False, 'default': False, 'type': 'bool' },
|
||||
'engine': { 'required': False, 'default': 'podman', 'type': 'str' },
|
||||
'container_user': { 'required': False, 'default': 'www-data', 'type': 'str' },
|
||||
'container_name': { 'required': False, 'default': 'nextcloud-app', 'type': 'str' },
|
||||
}
|
||||
|
||||
# seed the result dict in the object
|
||||
# we primarily care about changed and state
|
||||
# changed is if this module effectively modified the target
|
||||
# state will include any data that you want your module to pass back
|
||||
# for consumption, for example, in a subsequent task
|
||||
result = { 'changed': False }
|
||||
|
||||
# the AnsibleModule object will be our abstraction working with Ansible
|
||||
# this includes instantiation, a couple of common attr would be the
|
||||
# args/params passed to the execution, as well as if the module
|
||||
# supports check mode
|
||||
module = AnsibleModule(
|
||||
argument_spec=module_args,
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
if module.params['state'] not in ['enabled', 'disabled', 'absent']:
|
||||
module.fail_json(msg='state must be one of enabled, disabled or absent', **result)
|
||||
|
||||
check_nextcloud_status(module, result)
|
||||
app_status = get_app_status(module, result)
|
||||
apply_app_status(module, result, app_status)
|
||||
|
||||
module.exit_json(**result)
|
||||
|
||||
|
||||
def main():
|
||||
'''
|
||||
The main method called for the module.
|
||||
'''
|
||||
run_module()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Add table
Add a link
Reference in a new issue