1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00
community.general/plugins/modules/web_infrastructure/django_manage.py

348 lines
12 KiB
Python
Raw Normal View History

2020-03-09 10:11:07 +01:00
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2013, Scott Anderson <scottanderson42@gmail.com>
# 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: django_manage
short_description: Manages a Django application.
description:
- Manages a Django application using the C(manage.py) application frontend to C(django-admin). With the
C(virtualenv) parameter, all management commands will be executed by the given C(virtualenv) installation.
2020-03-09 10:11:07 +01:00
options:
command:
description:
- The name of the Django management command to run. Built in commands are C(cleanup), C(collectstatic),
C(flush), C(loaddata), C(migrate), C(syncdb), C(test), and C(validate).
- Other commands can be entered, but will fail if they're unknown to Django. Other commands that may
prompt for user input should be run with the C(--noinput) flag.
- The module will perform some basic parameter validation (when applicable) to the commands C(cleanup),
C(collectstatic), C(createcachetable), C(flush), C(loaddata), C(migrate), C(syncdb), C(test), and C(validate).
type: str
2020-03-09 10:11:07 +01:00
required: true
project_path:
2020-03-09 10:11:07 +01:00
description:
- The path to the root of the Django application where B(manage.py) lives.
type: path
2020-03-09 10:11:07 +01:00
required: true
aliases: [app_path, chdir]
2020-03-09 10:11:07 +01:00
settings:
description:
- The Python path to the application's settings module, such as C(myapp.settings).
type: path
2020-03-09 10:11:07 +01:00
required: false
pythonpath:
description:
- A directory to add to the Python path. Typically used to include the settings module if it is located
external to the application directory.
type: path
2020-03-09 10:11:07 +01:00
required: false
aliases: [python_path]
2020-03-09 10:11:07 +01:00
virtualenv:
description:
- An optional path to a I(virtualenv) installation to use while running the manage application.
type: path
aliases: [virtual_env]
2020-03-09 10:11:07 +01:00
apps:
description:
- A list of space-delimited apps to target. Used by the C(test) command.
type: str
2020-03-09 10:11:07 +01:00
required: false
cache_table:
description:
- The name of the table used for database-backed caching. Used by the C(createcachetable) command.
type: str
2020-03-09 10:11:07 +01:00
required: false
clear:
description:
- Clear the existing files before trying to copy or link the original file.
- Used only with the 'collectstatic' command. The C(--noinput) argument will be added automatically.
required: false
default: no
type: bool
database:
description:
- The database to target. Used by the C(createcachetable), C(flush), C(loaddata), C(syncdb),
and C(migrate) commands.
type: str
2020-03-09 10:11:07 +01:00
required: false
failfast:
description:
- Fail the command immediately if a test fails. Used by the C(test) command.
2020-03-09 10:11:07 +01:00
required: false
default: false
2020-03-09 10:11:07 +01:00
type: bool
aliases: [fail_fast]
2020-03-09 10:11:07 +01:00
fixtures:
description:
- A space-delimited list of fixture file names to load in the database. B(Required) by the C(loaddata) command.
type: str
2020-03-09 10:11:07 +01:00
required: false
skip:
description:
- Will skip over out-of-order missing migrations, you can only use this parameter with C(migrate) command.
2020-03-09 10:11:07 +01:00
required: false
type: bool
merge:
description:
- Will run out-of-order or missing migrations as they are not rollback migrations, you can only use this
parameter with C(migrate) command.
2020-03-09 10:11:07 +01:00
required: false
type: bool
link:
description:
- Will create links to the files instead of copying them, you can only use this parameter with
C(collectstatic) command.
2020-03-09 10:11:07 +01:00
required: false
type: bool
liveserver:
description:
- This parameter was implemented a long time ago in a galaxy far way. It probably relates to the
django-liveserver package, which is no longer updated.
- Hence, it will be considered DEPRECATED and should be removed in a future release.
type: str
required: false
aliases: [live_server]
testrunner:
description:
- "From the Django docs: Controls the test runner class that is used to execute tests."
- This parameter is passed as-is to C(manage.py).
type: str
required: false
aliases: [test_runner]
2020-03-09 10:11:07 +01:00
notes:
- C(virtualenv) (U(http://www.virtualenv.org)) must be installed on the remote host if the virtualenv parameter
is specified.
- This module will create a virtualenv if the virtualenv parameter is specified and a virtualenv does not already
exist at the given location.
- This module assumes English error messages for the C(createcachetable) command to detect table existence,
unfortunately.
- To be able to use the C(migrate) command with django versions < 1.7, you must have C(south) installed and added
as an app in your settings.
- To be able to use the C(collectstatic) command, you must have enabled staticfiles in your settings.
- Your C(manage.py) application must be executable (rwxr-xr-x), and must have a valid shebang,
i.e. C(#!/usr/bin/env python), for invoking the appropriate Python interpreter.
2020-03-09 10:11:07 +01:00
requirements: [ "virtualenv", "django" ]
author: "Scott Anderson (@tastychutney)"
'''
EXAMPLES = """
- name: Run cleanup on the application installed in django_dir
community.general.django_manage:
2020-03-09 10:11:07 +01:00
command: cleanup
project_path: "{{ django_dir }}"
2020-03-09 10:11:07 +01:00
- name: Load the initial_data fixture into the application
community.general.django_manage:
2020-03-09 10:11:07 +01:00
command: loaddata
project_path: "{{ django_dir }}"
2020-03-09 10:11:07 +01:00
fixtures: "{{ initial_data }}"
- name: Run syncdb on the application
community.general.django_manage:
2020-03-09 10:11:07 +01:00
command: syncdb
project_path: "{{ django_dir }}"
2020-03-09 10:11:07 +01:00
settings: "{{ settings_app_name }}"
pythonpath: "{{ settings_dir }}"
virtualenv: "{{ virtualenv_dir }}"
- name: Run the SmokeTest test case from the main app. Useful for testing deploys
community.general.django_manage:
2020-03-09 10:11:07 +01:00
command: test
project_path: "{{ django_dir }}"
2020-03-09 10:11:07 +01:00
apps: main.SmokeTest
- name: Create an initial superuser
community.general.django_manage:
2020-03-09 10:11:07 +01:00
command: "createsuperuser --noinput --username=admin --email=admin@example.com"
project_path: "{{ django_dir }}"
2020-03-09 10:11:07 +01:00
"""
import os
import sys
from ansible.module_utils.basic import AnsibleModule
def _fail(module, cmd, out, err, **kwargs):
msg = ''
if out:
msg += "stdout: %s" % (out, )
if err:
msg += "\n:stderr: %s" % (err, )
module.fail_json(cmd=cmd, msg=msg, **kwargs)
def _ensure_virtualenv(module):
venv_param = module.params['virtualenv']
if venv_param is None:
return
vbin = os.path.join(venv_param, 'bin')
activate = os.path.join(vbin, 'activate')
if not os.path.exists(activate):
virtualenv = module.get_bin_path('virtualenv', True)
vcmd = [virtualenv, venv_param]
rc, out_venv, err_venv = module.run_command(vcmd)
if rc != 0:
_fail(module, vcmd, out_venv, err_venv)
os.environ["PATH"] = "%s:%s" % (vbin, os.environ["PATH"])
os.environ["VIRTUAL_ENV"] = venv_param
def createcachetable_check_changed(output):
return "already exists" not in output
2020-03-09 10:11:07 +01:00
def flush_filter_output(line):
return "Installed" in line and "Installed 0 object" not in line
def loaddata_filter_output(line):
return "Installed" in line and "Installed 0 object" not in line
def syncdb_filter_output(line):
return ("Creating table " in line) \
or ("Installed" in line and "Installed 0 object" not in line)
2020-03-09 10:11:07 +01:00
def migrate_filter_output(line):
return ("Migrating forwards " in line) \
or ("Installed" in line and "Installed 0 object" not in line) \
or ("Applying" in line)
2020-03-09 10:11:07 +01:00
def collectstatic_filter_output(line):
return line and "0 static files" not in line
def main():
command_allowed_param_map = dict(
cleanup=(),
createcachetable=('cache_table', 'database', ),
flush=('database', ),
loaddata=('database', 'fixtures', ),
syncdb=('database', ),
test=('failfast', 'testrunner', 'liveserver', 'apps', ),
validate=(),
migrate=('apps', 'skip', 'merge', 'database',),
collectstatic=('clear', 'link', ),
)
command_required_param_map = dict(
loaddata=('fixtures', ),
)
# forces --noinput on every command that needs it
noinput_commands = (
'flush',
'syncdb',
'migrate',
'test',
'collectstatic',
)
# These params are allowed for certain commands only
specific_params = ('apps', 'clear', 'database', 'failfast', 'fixtures', 'liveserver', 'testrunner')
# These params are automatically added to the command if present
general_params = ('settings', 'pythonpath', 'database',)
specific_boolean_params = ('clear', 'failfast', 'skip', 'merge', 'link')
end_of_command_params = ('apps', 'cache_table', 'fixtures')
module = AnsibleModule(
argument_spec=dict(
command=dict(required=True, type='str'),
project_path=dict(required=True, type='path', aliases=['app_path', 'chdir']),
settings=dict(default=None, required=False, type='path'),
pythonpath=dict(default=None, required=False, type='path', aliases=['python_path']),
2020-03-09 10:11:07 +01:00
virtualenv=dict(default=None, required=False, type='path', aliases=['virtual_env']),
apps=dict(default=None, required=False),
cache_table=dict(default=None, required=False, type='str'),
2020-03-09 10:11:07 +01:00
clear=dict(default=None, required=False, type='bool'),
database=dict(default=None, required=False, type='str'),
failfast=dict(default=False, required=False, type='bool', aliases=['fail_fast']),
fixtures=dict(default=None, required=False, type='str'),
liveserver=dict(default=None, required=False, type='str', aliases=['live_server'],
removed_in_version='3.0.0', removed_from_collection='community.general'),
testrunner=dict(default=None, required=False, type='str', aliases=['test_runner']),
2020-03-09 10:11:07 +01:00
skip=dict(default=None, required=False, type='bool'),
merge=dict(default=None, required=False, type='bool'),
link=dict(default=None, required=False, type='bool'),
),
)
command = module.params['command']
project_path = module.params['project_path']
2020-03-09 10:11:07 +01:00
virtualenv = module.params['virtualenv']
for param in specific_params:
value = module.params[param]
if param in specific_boolean_params:
value = module.boolean(value)
if value and param not in command_allowed_param_map[command]:
module.fail_json(msg='%s param is incompatible with command=%s' % (param, command))
for param in command_required_param_map.get(command, ()):
if not module.params[param]:
module.fail_json(msg='%s param is required for command=%s' % (param, command))
_ensure_virtualenv(module)
cmd = "./manage.py %s" % (command, )
if command in noinput_commands:
cmd = '%s --noinput' % cmd
for param in general_params:
if module.params[param]:
cmd = '%s --%s=%s' % (cmd, param, module.params[param])
for param in specific_boolean_params:
if module.boolean(module.params[param]):
cmd = '%s --%s' % (cmd, param)
# these params always get tacked on the end of the command
for param in end_of_command_params:
if module.params[param]:
cmd = '%s %s' % (cmd, module.params[param])
rc, out, err = module.run_command(cmd, cwd=project_path)
2020-03-09 10:11:07 +01:00
if rc != 0:
if command == 'createcachetable' and 'table' in err and 'already exists' in err:
out = 'already exists.'
2020-03-09 10:11:07 +01:00
else:
if "Unknown command:" in err:
_fail(module, cmd, err, "Unknown django command: %s" % command)
_fail(module, cmd, out, err, path=os.environ["PATH"], syspath=sys.path)
changed = False
lines = out.split('\n')
filt = globals().get(command + "_filter_output", None)
if filt:
filtered_output = list(filter(filt, lines))
if len(filtered_output):
changed = True
check_changed = globals().get("{0}_check_changed".format(command), None)
if check_changed:
changed = check_changed(out)
2020-03-09 10:11:07 +01:00
module.exit_json(changed=changed, out=out, cmd=cmd, app_path=project_path, project_path=project_path,
virtualenv=virtualenv, settings=module.params['settings'], pythonpath=module.params['pythonpath'])
2020-03-09 10:11:07 +01:00
if __name__ == '__main__':
main()