mirror of https://github.com/ansible/ansible.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
282 lines
11 KiB
Python
282 lines
11 KiB
Python
12 years ago
|
#!/usr/bin/python
|
||
|
# -*- coding: utf-8 -*-
|
||
|
|
||
|
# (c) 2013, Scott Anderson <scottanderson42@gmail.com>
|
||
|
#
|
||
|
# This file is part of Ansible
|
||
|
#
|
||
|
# Ansible is free software: you can redistribute it and/or modify
|
||
|
# it under the terms of the GNU General Public License as published by
|
||
|
# the Free Software Foundation, either version 3 of the License, or
|
||
|
# (at your option) any later version.
|
||
|
#
|
||
|
# Ansible is distributed in the hope that it will be useful,
|
||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
# GNU General Public License for more details.
|
||
|
#
|
||
|
# You should have received a copy of the GNU General Public License
|
||
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||
|
#
|
||
|
|
||
|
DOCUMENTATION = '''
|
||
|
---
|
||
12 years ago
|
module: django_manage
|
||
12 years ago
|
short_description: Manages a Django application.
|
||
|
description:
|
||
12 years ago
|
- Manages a Django application using the I(manage.py) application frontend to I(django-admin). With the I(virtualenv) parameter, all management commands will be executed by the given I(virtualenv) installation.
|
||
12 years ago
|
version_added: "1.1"
|
||
|
options:
|
||
|
command:
|
||
11 years ago
|
choices: [ 'cleanup', 'collectstatic', 'flush', 'loaddata', 'migrate', 'runfcgi', 'syncdb', 'test', 'validate', ]
|
||
12 years ago
|
description:
|
||
11 years ago
|
- The name of the Django management command to run. Built in commands are cleanup, collectstatic, flush, loaddata, migrate, runfcgi, syncdb, test, and validate. Other commands can be entered, but will fail if they're unknown to Django.
|
||
12 years ago
|
required: true
|
||
|
app_path:
|
||
|
description:
|
||
12 years ago
|
- The path to the root of the Django application where B(manage.py) lives.
|
||
12 years ago
|
required: true
|
||
|
settings:
|
||
|
description:
|
||
12 years ago
|
- The Python path to the application's settings module, such as 'myapp.settings'.
|
||
12 years ago
|
required: false
|
||
|
pythonpath:
|
||
|
description:
|
||
12 years ago
|
- A directory to add to the Python path. Typically used to include the settings module if it is located external to the application directory.
|
||
12 years ago
|
required: false
|
||
|
virtualenv:
|
||
|
description:
|
||
12 years ago
|
- An optional path to a I(virtualenv) installation to use while running the manage application.
|
||
12 years ago
|
required: false
|
||
|
apps:
|
||
|
description:
|
||
12 years ago
|
- A list of space-delimited apps to target. Used by the 'test' command.
|
||
12 years ago
|
required: false
|
||
12 years ago
|
cache_table:
|
||
12 years ago
|
description:
|
||
12 years ago
|
- The name of the table used for database-backed caching. Used by the 'createcachetable' command.
|
||
12 years ago
|
required: false
|
||
12 years ago
|
database:
|
||
12 years ago
|
description:
|
||
12 years ago
|
- The database to target. Used by the 'createcachetable', 'flush', 'loaddata', and 'syncdb' commands.
|
||
12 years ago
|
required: false
|
||
|
failfast:
|
||
|
description:
|
||
12 years ago
|
- Fail the command immediately if a test fails. Used by the 'test' command.
|
||
12 years ago
|
required: false
|
||
12 years ago
|
default: "no"
|
||
|
choices: [ "yes", "no" ]
|
||
12 years ago
|
fixtures:
|
||
|
description:
|
||
12 years ago
|
- A space-delimited list of fixture file names to load in the database. B(Required) by the 'loaddata' command.
|
||
12 years ago
|
required: false
|
||
12 years ago
|
skip:
|
||
|
description:
|
||
|
- Will skip over out-of-order missing migrations, you can only use this parameter with I(migrate)
|
||
|
required: false
|
||
11 years ago
|
version_added: "1.3"
|
||
12 years ago
|
merge:
|
||
|
description:
|
||
|
- Will run out-of-order or missing migrations as they are not rollback migrations, you can only use this parameter with 'migrate' command
|
||
|
required: false
|
||
11 years ago
|
version_added: "1.3"
|
||
12 years ago
|
link:
|
||
|
description:
|
||
|
- Will create links to the files instead of copying them, you can only use this parameter with 'collectstatic' command
|
||
|
required: false
|
||
11 years ago
|
version_added: "1.3"
|
||
12 years ago
|
notes:
|
||
12 years ago
|
- I(virtualenv) (U(http://www.virtualenv.org)) must be installed on the remote host if the virtualenv parameter is specified.
|
||
12 years ago
|
- This module will create a virtualenv if the virtualenv parameter is specified and a virtualenv does not already exist at the given location.
|
||
12 years ago
|
- This module assumes English error messages for the 'createcachetable' command to detect table existence, unfortunately.
|
||
12 years ago
|
- To be able to use the migrate command, you must have south installed and added as an app in your settings
|
||
|
- To be able to use the collectstatic command, you must have enabled staticfiles in your settings
|
||
12 years ago
|
requirements: [ "virtualenv", "django" ]
|
||
12 years ago
|
author: Scott Anderson
|
||
|
'''
|
||
|
|
||
12 years ago
|
EXAMPLES = """
|
||
12 years ago
|
# Run cleanup on the application installed in 'django_dir'.
|
||
|
- django_manage: command=cleanup app_path={{ django_dir }}
|
||
12 years ago
|
|
||
12 years ago
|
# Load the initial_data fixture into the application
|
||
|
- django_manage: command=loaddata app_path={{ django_dir }} fixtures={{ initial_data }}
|
||
12 years ago
|
|
||
|
#Run syncdb on the application
|
||
12 years ago
|
- django_manage: >
|
||
11 years ago
|
command=syncdb
|
||
12 years ago
|
app_path={{ django_dir }}
|
||
11 years ago
|
settings={{ settings_app_name }}
|
||
12 years ago
|
pythonpath={{ settings_dir }}
|
||
|
virtualenv={{ virtualenv_dir }}
|
||
12 years ago
|
|
||
|
#Run the SmokeTest test case from the main app. Useful for testing deploys.
|
||
12 years ago
|
- django_manage: command=test app_path=django_dir apps=main.SmokeTest
|
||
12 years ago
|
"""
|
||
|
|
||
|
|
||
12 years ago
|
import os
|
||
|
|
||
|
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):
|
||
12 years ago
|
|
||
12 years ago
|
venv_param = module.params['virtualenv']
|
||
12 years ago
|
if venv_param is None:
|
||
|
return
|
||
12 years ago
|
|
||
11 years ago
|
vbin = os.path.join(os.path.expanduser(venv_param), 'bin')
|
||
12 years ago
|
activate = os.path.join(vbin, 'activate')
|
||
|
|
||
|
if not os.path.exists(activate):
|
||
11 years ago
|
virtualenv = module.get_bin_path('virtualenv', True)
|
||
12 years ago
|
vcmd = '%s %s' % (virtualenv, venv_param)
|
||
|
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"])
|
||
11 years ago
|
os.environ["VIRTUAL_ENV"] = venv_param
|
||
12 years ago
|
|
||
12 years ago
|
def createcachetable_filter_output(line):
|
||
|
return "Already exists" not in line
|
||
|
|
||
12 years ago
|
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)
|
||
|
|
||
11 years ago
|
def migrate_filter_output(line):
|
||
|
return ("Migrating forwards " in line) or ("Installed" in line and "Installed 0 object" not in line)
|
||
|
|
||
12 years ago
|
def main():
|
||
|
command_allowed_param_map = dict(
|
||
|
cleanup=(),
|
||
12 years ago
|
createcachetable=('cache_table', 'database', ),
|
||
12 years ago
|
flush=('database', ),
|
||
|
loaddata=('database', 'fixtures', ),
|
||
|
syncdb=('database', ),
|
||
|
test=('failfast', 'testrunner', 'liveserver', 'apps', ),
|
||
|
validate=(),
|
||
11 years ago
|
migrate=('apps', 'skip', 'merge'),
|
||
12 years ago
|
collectstatic=('link', ),
|
||
12 years ago
|
)
|
||
|
|
||
|
command_required_param_map = dict(
|
||
|
loaddata=('fixtures', ),
|
||
12 years ago
|
createcachetable=('cache_table', ),
|
||
12 years ago
|
)
|
||
|
|
||
|
# forces --noinput on every command that needs it
|
||
|
noinput_commands = (
|
||
|
'flush',
|
||
|
'syncdb',
|
||
12 years ago
|
'migrate',
|
||
12 years ago
|
'test',
|
||
12 years ago
|
'collectstatic',
|
||
12 years ago
|
)
|
||
|
|
||
|
# These params are allowed for certain commands only
|
||
12 years ago
|
specific_params = ('apps', 'database', 'failfast', 'fixtures', 'liveserver', 'testrunner')
|
||
12 years ago
|
|
||
|
# These params are automatically added to the command if present
|
||
11 years ago
|
general_params = ('settings', 'pythonpath', 'database',)
|
||
12 years ago
|
specific_boolean_params = ('failfast', 'skip', 'merge', 'link')
|
||
|
end_of_command_params = ('apps', 'cache_table', 'fixtures')
|
||
12 years ago
|
|
||
|
module = AnsibleModule(
|
||
12 years ago
|
argument_spec=dict(
|
||
11 years ago
|
command = dict(default=None, required=True),
|
||
12 years ago
|
app_path = dict(default=None, required=True),
|
||
|
settings = dict(default=None, required=False),
|
||
|
pythonpath = dict(default=None, required=False, aliases=['python_path']),
|
||
|
virtualenv = dict(default=None, required=False, aliases=['virtual_env']),
|
||
|
|
||
|
apps = dict(default=None, required=False),
|
||
|
cache_table = dict(default=None, required=False),
|
||
|
database = dict(default=None, required=False),
|
||
11 years ago
|
failfast = dict(default='no', required=False, type='bool', aliases=['fail_fast']),
|
||
12 years ago
|
fixtures = dict(default=None, required=False),
|
||
|
liveserver = dict(default=None, required=False, aliases=['live_server']),
|
||
|
testrunner = dict(default=None, required=False, aliases=['test_runner']),
|
||
11 years ago
|
skip = dict(default=None, required=False, type='bool'),
|
||
|
merge = dict(default=None, required=False, type='bool'),
|
||
|
link = dict(default=None, required=False, type='bool'),
|
||
12 years ago
|
),
|
||
|
)
|
||
|
|
||
|
command = module.params['command']
|
||
|
app_path = module.params['app_path']
|
||
|
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))
|
||
|
|
||
12 years ago
|
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))
|
||
12 years ago
|
|
||
|
venv = module.params['virtualenv']
|
||
|
|
||
|
_ensure_virtualenv(module)
|
||
|
|
||
|
cmd = "python 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])
|
||
|
|
||
11 years ago
|
rc, out, err = module.run_command(cmd, cwd=app_path)
|
||
12 years ago
|
if rc != 0:
|
||
12 years ago
|
if command == 'createcachetable' and 'table' in err and 'already exists' in err:
|
||
|
out = 'Already exists.'
|
||
|
else:
|
||
11 years ago
|
if "Unknown command:" in err:
|
||
|
_fail(module, cmd, err, "Unknown django command: %s" % command)
|
||
12 years ago
|
_fail(module, cmd, out, err, path=os.environ["PATH"], syspath=sys.path)
|
||
12 years ago
|
|
||
|
changed = False
|
||
|
|
||
|
lines = out.split('\n')
|
||
|
filt = globals().get(command + "_filter_output", None)
|
||
|
if filt:
|
||
|
filtered_output = filter(filt, out.split('\n'))
|
||
|
if len(filtered_output):
|
||
|
changed = filtered_output
|
||
|
|
||
|
module.exit_json(changed=changed, out=out, cmd=cmd, app_path=app_path, virtualenv=virtualenv,
|
||
|
settings=module.params['settings'], pythonpath=module.params['pythonpath'])
|
||
|
|
||
11 years ago
|
# import module snippets
|
||
11 years ago
|
from ansible.module_utils.basic import *
|
||
12 years ago
|
|
||
|
main()
|