2013-02-24 19:33:25 +01:00
#!/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 = '''
- - -
2013-02-28 21:57:27 +01:00
module : django_manage
2013-02-24 19:33:25 +01:00
short_description : Manages a Django application .
description :
2013-02-27 04:11:30 +01:00
- 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 .
2013-02-24 19:33:25 +01:00
version_added : " 1.1 "
options :
command :
2014-05-21 20:00:12 +02:00
choices : [ ' cleanup ' , ' collectstatic ' , ' flush ' , ' loaddata ' , ' migrate ' , ' runfcgi ' , ' syncdb ' , ' test ' , ' validate ' , ]
2013-02-24 19:33:25 +01:00
description :
2014-12-26 07:29:54 +01:00
- 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. Other commands that may prompt for user input should be run with the I(--noinput) flag.
2013-02-24 19:33:25 +01:00
required : true
app_path :
description :
2013-02-27 04:11:30 +01:00
- The path to the root of the Django application where B ( manage . py ) lives .
2013-02-24 19:33:25 +01:00
required : true
settings :
description :
2013-02-27 04:11:30 +01:00
- The Python path to the application ' s settings module, such as ' myapp . settings ' .
2013-02-24 19:33:25 +01:00
required : false
pythonpath :
description :
2013-02-27 04:11:30 +01:00
- A directory to add to the Python path . Typically used to include the settings module if it is located external to the application directory .
2013-02-24 19:33:25 +01:00
required : false
virtualenv :
description :
2013-02-27 04:11:30 +01:00
- An optional path to a I ( virtualenv ) installation to use while running the manage application .
2013-02-24 19:33:25 +01:00
required : false
apps :
description :
2013-02-27 04:11:30 +01:00
- A list of space - delimited apps to target . Used by the ' test ' command .
2013-02-24 19:33:25 +01:00
required : false
2013-02-27 04:11:30 +01:00
cache_table :
2013-02-24 19:33:25 +01:00
description :
2013-02-27 04:11:30 +01:00
- The name of the table used for database - backed caching . Used by the ' createcachetable ' command .
2013-02-24 19:33:25 +01:00
required : false
2013-02-27 04:11:30 +01:00
database :
2013-02-24 19:33:25 +01:00
description :
2013-02-27 04:11:30 +01:00
- The database to target . Used by the ' createcachetable ' , ' flush ' , ' loaddata ' , and ' syncdb ' commands .
2013-02-24 19:33:25 +01:00
required : false
failfast :
description :
2013-02-27 04:11:30 +01:00
- Fail the command immediately if a test fails . Used by the ' test ' command .
2013-02-24 19:33:25 +01:00
required : false
2013-03-12 13:18:12 +01:00
default : " no "
choices : [ " yes " , " no " ]
2013-02-24 19:33:25 +01:00
fixtures :
description :
2013-02-27 04:11:30 +01:00
- A space - delimited list of fixture file names to load in the database . B ( Required ) by the ' loaddata ' command .
2013-02-24 19:33:25 +01:00
required : false
2013-06-14 07:28:24 +02:00
skip :
description :
- Will skip over out - of - order missing migrations , you can only use this parameter with I ( migrate )
required : false
2014-04-08 04:57:49 +02:00
version_added : " 1.3 "
2013-06-14 07:28:24 +02:00
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
2014-04-08 04:57:49 +02:00
version_added : " 1.3 "
2013-06-14 07:28:24 +02:00
link :
description :
- Will create links to the files instead of copying them , you can only use this parameter with ' collectstatic ' command
required : false
2014-04-08 04:57:49 +02:00
version_added : " 1.3 "
2013-02-24 19:33:25 +01:00
notes :
2013-06-13 20:01:32 +02:00
- I ( virtualenv ) ( U ( http : / / www . virtualenv . org ) ) must be installed on the remote host if the virtualenv parameter is specified .
2013-02-27 16:01:12 +01:00
- This module will create a virtualenv if the virtualenv parameter is specified and a virtualenv does not already exist at the given location .
2013-02-27 04:11:30 +01:00
- This module assumes English error messages for the ' createcachetable ' command to detect table existence , unfortunately .
2016-01-23 20:20:18 +01:00
- To be able to use the migrate command with django versions < 1.7 , 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 .
- As of ansible 2. x , your I ( manage . py ) application must be executable ( rwxr - xr - x ) , and must have a valid I ( shebang ) , i . e . " #!/usr/bin/env python " , for invoking the appropriate Python interpreter .
2013-02-27 04:11:30 +01:00
requirements : [ " virtualenv " , " django " ]
2015-06-15 21:53:30 +02:00
author : " Scott Anderson (@tastychutney) "
2013-02-24 19:33:25 +01:00
'''
2013-02-27 02:44:08 +01:00
EXAMPLES = """
2013-06-17 04:15:30 +02:00
# Run cleanup on the application installed in 'django_dir'.
- django_manage : command = cleanup app_path = { { django_dir } }
2013-02-27 02:44:08 +01:00
2013-06-17 04:15:30 +02:00
# Load the initial_data fixture into the application
- django_manage : command = loaddata app_path = { { django_dir } } fixtures = { { initial_data } }
2013-02-27 02:44:08 +01:00
2014-12-26 07:29:54 +01:00
# Run syncdb on the application
2013-06-14 11:53:43 +02:00
- django_manage : >
2013-08-11 23:02:13 +02:00
command = syncdb
2013-06-17 04:15:30 +02:00
app_path = { { django_dir } }
2013-08-11 23:02:13 +02:00
settings = { { settings_app_name } }
2013-06-17 04:15:30 +02:00
pythonpath = { { settings_dir } }
virtualenv = { { virtualenv_dir } }
2013-02-27 04:11:30 +01:00
2014-12-26 07:29:54 +01:00
# Run the SmokeTest test case from the main app. Useful for testing deploys.
- django_manage : command = test app_path = { { django_dir } } apps = main . SmokeTest
2015-07-26 20:56:59 +02:00
# Create an initial superuser.
2014-12-26 07:29:54 +01:00
- django_manage : command = " createsuperuser --noinput --username=admin --email=admin@example.com " app_path = { { django_dir } }
2013-02-27 02:44:08 +01:00
"""
2013-02-24 19:33:25 +01:00
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 ) :
2013-02-28 22:03:23 +01:00
2013-02-24 19:33:25 +01:00
venv_param = module . params [ ' virtualenv ' ]
2013-02-28 22:03:23 +01:00
if venv_param is None :
return
2013-02-24 19:33:25 +01:00
2013-08-11 23:02:13 +02:00
vbin = os . path . join ( os . path . expanduser ( venv_param ) , ' bin ' )
2013-02-24 19:33:25 +01:00
activate = os . path . join ( vbin , ' activate ' )
if not os . path . exists ( activate ) :
2013-12-17 20:45:42 +01:00
virtualenv = module . get_bin_path ( ' virtualenv ' , True )
2013-02-24 19:33:25 +01:00
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 " ] )
2014-06-17 18:01:14 +02:00
os . environ [ " VIRTUAL_ENV " ] = venv_param
2013-02-24 19:33:25 +01:00
2013-02-27 04:11:30 +01:00
def createcachetable_filter_output ( line ) :
return " Already exists " not in line
2013-02-24 19:33:25 +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 )
2013-11-22 20:35:19 +01:00
def migrate_filter_output ( line ) :
2015-04-17 18:43:25 +02:00
return ( " Migrating forwards " in line ) or ( " Installed " in line and " Installed 0 object " not in line ) or ( " Applying " in line )
2013-11-22 20:35:19 +01:00
2015-07-09 22:04:13 +02:00
def collectstatic_filter_output ( line ) :
return " 0 static files " not in line
2013-02-24 19:33:25 +01:00
def main ( ) :
command_allowed_param_map = dict (
cleanup = ( ) ,
2013-02-27 04:11:30 +01:00
createcachetable = ( ' cache_table ' , ' database ' , ) ,
2013-02-24 19:33:25 +01:00
flush = ( ' database ' , ) ,
loaddata = ( ' database ' , ' fixtures ' , ) ,
syncdb = ( ' database ' , ) ,
test = ( ' failfast ' , ' testrunner ' , ' liveserver ' , ' apps ' , ) ,
validate = ( ) ,
2014-12-05 16:08:47 +01:00
migrate = ( ' apps ' , ' skip ' , ' merge ' , ' database ' , ) ,
2015-07-26 20:56:59 +02:00
collectstatic = ( ' clear ' , ' link ' , ) ,
2013-02-24 19:33:25 +01:00
)
command_required_param_map = dict (
loaddata = ( ' fixtures ' , ) ,
)
# forces --noinput on every command that needs it
noinput_commands = (
' flush ' ,
' syncdb ' ,
2013-06-19 05:05:40 +02:00
' migrate ' ,
2013-02-24 19:33:25 +01:00
' test ' ,
2013-06-14 07:28:24 +02:00
' collectstatic ' ,
2013-02-24 19:33:25 +01:00
)
# These params are allowed for certain commands only
2015-07-26 20:56:59 +02:00
specific_params = ( ' apps ' , ' clear ' , ' database ' , ' failfast ' , ' fixtures ' , ' liveserver ' , ' testrunner ' )
2013-02-24 19:33:25 +01:00
# These params are automatically added to the command if present
2013-09-24 17:05:45 +02:00
general_params = ( ' settings ' , ' pythonpath ' , ' database ' , )
2015-07-26 20:56:59 +02:00
specific_boolean_params = ( ' clear ' , ' failfast ' , ' skip ' , ' merge ' , ' link ' )
2013-07-01 00:52:57 +02:00
end_of_command_params = ( ' apps ' , ' cache_table ' , ' fixtures ' )
2013-02-24 19:33:25 +01:00
module = AnsibleModule (
2013-02-27 04:11:30 +01:00
argument_spec = dict (
2013-10-19 02:26:10 +02:00
command = dict ( default = None , required = True ) ,
2013-02-27 04:11:30 +01:00
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 ) ,
2015-07-26 20:56:59 +02:00
clear = dict ( default = None , required = False , type = ' bool ' ) ,
2013-02-27 04:11:30 +01:00
database = dict ( default = None , required = False ) ,
2014-03-12 05:04:19 +01:00
failfast = dict ( default = ' no ' , required = False , type = ' bool ' , aliases = [ ' fail_fast ' ] ) ,
2013-02-27 04:11:30 +01:00
fixtures = dict ( default = None , required = False ) ,
liveserver = dict ( default = None , required = False , aliases = [ ' live_server ' ] ) ,
testrunner = dict ( default = None , required = False , aliases = [ ' test_runner ' ] ) ,
2014-03-12 05:04:19 +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 ' ) ,
2013-02-24 19:33:25 +01:00
) ,
)
command = module . params [ ' command ' ]
2014-11-23 02:59:36 +01:00
app_path = os . path . expanduser ( module . params [ ' app_path ' ] )
2013-02-24 19:33:25 +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 ) )
2013-02-27 04:11:30 +01:00
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 ) )
2013-02-24 19:33:25 +01:00
_ensure_virtualenv ( module )
2015-04-19 09:39:59 +02:00
cmd = " ./manage.py %s " % ( command , )
2013-02-24 19:33:25 +01:00
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 ] )
2015-03-29 21:34:29 +02:00
rc , out , err = module . run_command ( cmd , cwd = os . path . expanduser ( app_path ) )
2013-02-24 19:33:25 +01:00
if rc != 0 :
2013-02-27 04:11:30 +01:00
if command == ' createcachetable ' and ' table ' in err and ' already exists ' in err :
out = ' Already exists. '
else :
2013-10-19 02:26:10 +02:00
if " Unknown command: " in err :
_fail ( module , cmd , err , " Unknown django command: %s " % command )
2013-02-27 04:11:30 +01:00
_fail ( module , cmd , out , err , path = os . environ [ " PATH " ] , syspath = sys . path )
2013-02-24 19:33:25 +01:00
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 ' ] )
2013-12-02 21:13:49 +01:00
# import module snippets
2013-12-02 21:11:23 +01:00
from ansible . module_utils . basic import *
2013-02-24 19:33:25 +01:00
main ( )