Skip to content

Commit

Permalink
added geocamUtilWeb submodule and bootstrap.py
Browse files Browse the repository at this point in the history
  • Loading branch information
trey0 committed Mar 2, 2011
1 parent dc94d42 commit 833a99e
Show file tree
Hide file tree
Showing 6 changed files with 269 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -17,3 +17,4 @@ django.wsgi
apps/geocamTrack/media/avatars/cache/*.png apps/geocamTrack/media/avatars/cache/*.png
apps/geocamTrack/media/avatars/gravatars apps/geocamTrack/media/avatars/gravatars
apps/geocamTrack/media/avatars/*.png apps/geocamTrack/media/avatars/*.png
apps/geocamUtil
3 changes: 3 additions & 0 deletions .gitmodules
@@ -0,0 +1,3 @@
[submodule "submodules/geocamUtilWeb"]
path = submodules/geocamUtilWeb
url = git@github.com:geocam/geocamUtilWeb.git
8 changes: 8 additions & 0 deletions manage.py
Expand Up @@ -5,6 +5,14 @@
# All Rights Reserved. # All Rights Reserved.
# __END_LICENSE__ # __END_LICENSE__


import os
import sys

# try to bootstrap before hooking into django management stuff
ret = os.spawnl(os.P_WAIT, sys.executable, sys.executable, '%s/management/bootstrap.py' % os.path.dirname(__file__), '-v')
if ret != 0:
sys.exit(ret)

from django.core.management import execute_manager from django.core.management import execute_manager
try: try:
import settings # Assumed to be in the same directory. import settings # Assumed to be in the same directory.
Expand Down
246 changes: 246 additions & 0 deletions management/bootstrap.py
@@ -0,0 +1,246 @@
#!/usr/bin/env python
# __BEGIN_LICENSE__
# Copyright (C) 2008-2010 United States Government as represented by
# the Administrator of the National Aeronautics and Space Administration.
# All Rights Reserved.
# __END_LICENSE__

"""
This bootstrap script does the first stage of prep work for a Django
site that consists of multiple apps pulled in from separate repos via
git submodules. The script does just enough so that our subsequent
Django management commands will work -- they need Django to be installed
and minimally configured, and they need the apps to be present
and linked into the right place relative to the PYTHONPATH.
This script is intended to be generic across sites. Please don't put
any site-specific customizations in here. If you need to modify it,
please check your changes into
geocamDjangoSiteSkeleton/skel/bin/bootstrap.py so other sites can
benefit. Normally we would put code like this in geocamUtil, but the
whole reason we need a bootstrap step is to make sure things like
geocamUtil are available...
"""

import os
import sys
from glob import glob
import logging
from random import choice

DEFAULT_SITE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

SOURCEME_NAME = 'sourceme.sh'
SETTINGS_NAME = 'settings.py'
STATUS_PATH_TEMPLATE = 'build/management/bootstrap/%sStatus.txt'

ACTIONS = (dict(name='gitInitSubmodules',
desc="init and update submodules",
confirm=True),
dict(name='linkSubmodules',
desc='link submodules into apps directory',
confirm=True),
dict(name='installDjango',
desc='install Django',
confirm=True,
needed='needDjango'),
dict(name='genSourceme',
needed='needSourceme'),
dict(name='genSettings',
needed='needSettings'),
)
ACTION_DICT = dict([(a['name'], a) for a in ACTIONS])

def getConfirmation(opts, actionStr):
if opts.yes:
sys.stdout.write(actionStr+'? [Y/n] ')
print 'y'
return True
else:
while 1:
sys.stdout.write(actionStr+'? [Y/n] ')
response = raw_input().strip().lower()
if not response:
return True
elif response == 'y':
return True
elif response == 'n':
return False

def dosys(cmd, continueOnError=False):
if cmd.startswith('sudo'):
# force print before user gets password prompt
print 'running: ' + cmd
else:
logging.info('running: ' + cmd)
ret = os.system(cmd)
if ret != 0:
if continueOnError:
logging.warning('warning: command returned non-zero return value %d' % ret)
else:
logging.error('error: command returned non-zero return value %d' % ret)
sys.exit(1)

def writeFileMakeDir(path, text):
dir = os.path.dirname(path)
if not os.path.exists(dir):
os.makedirs(dir)
f = file(path, 'w')
f.write(text+'\n')
f.close()

def fillTemplate(inputFile, outputFile, context):
from django.template import Template, Context
from django.conf import settings
if not settings.configured:
settings.configure()
tmpl = Template(file(inputFile, 'r').read())
text = tmpl.render(Context(context))
file(outputFile, 'w').write(text)

######################################################################
# ACTION DEFINITIONS

def gitInitSubmodules(opts):
dosys('git submodule init')
dosys('git submodule update')

def linkSubmodules(opts):
# assumes each submodule app has a models dir or a models.py file
submoduleAppDirs = [os.path.dirname(d) for d in glob('submodules/*/*/models*')]
for src in submoduleAppDirs:
appName = os.path.basename(src)
relativeSrc = '../%s' % src
dst = 'apps/%s' % appName
if os.path.lexists(dst):
logging.debug(' %s -> %s skipped (already exists)' % (dst, relativeSrc))
else:
logging.debug(' %s -> %s' % (dst, relativeSrc))
os.symlink(relativeSrc, dst)

def needDjango(opts):
try:
import django
except ImportError:
return True
return False

def installDjango(opts):
needSudo = not os.environ.has_key('VIRTUALENV')
if needSudo:
sudoStr = 'sudo '
else:
sudoStr = ''
dosys('%spip install django' % sudoStr)

def needSourceme(opts):
return not os.path.exists(SOURCEME_NAME)

def genSourceme(opts):
logging.info('generating %s' % SOURCEME_NAME)

fillTemplate('management/templates/%s' % SOURCEME_NAME,
SOURCEME_NAME,
dict(virtualEnvDir=os.environ.get('VIRTUALENV', None),
parentDir=os.path.dirname(os.path.abspath(os.getcwd())),
appsDir=os.path.abspath('apps')
))

def needSettings(opts):
return not os.path.exists(SETTINGS_NAME)

def genSettings(opts):
logging.info('generating %s' % SETTINGS_NAME)

secretKey = ''.join([choice('abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)') for i in range(50)])

fillTemplate('management/templates/%s' % SETTINGS_NAME,
SETTINGS_NAME,
dict(secretKey=secretKey))

def needAction(opts, action):
statusFile = STATUS_PATH_TEMPLATE % action['name']
if os.path.exists(statusFile):
return file(statusFile, 'r').read().strip()
else:
return False

######################################################################
# TOP-LEVEL CODE

def doAction(opts, action):
# check if we need to do the action
neededName = action.get('needed', None)
if neededName:
# special check function defined for this action
neededFunc = globals()[neededName]
actionIsNeeded = neededFunc(opts)
if not actionIsNeeded:
logging.info('skipping step %s, not needed' % action['name'])
return
else:
# standard check function
status = needAction(opts, action)
if status:
logging.info('skipping step %s, status is %s' % (action['name'], status))
return

# confirm with user
if action.has_key('confirm') and not getConfirmation(opts, action['desc']):
writeFileMakeDir(STATUS_PATH_TEMPLATE % action['name'], 'UNWANTED')
return

# do the action
actionFunc = globals()[action['name']]
actionFunc(opts)

# mark completion (unless special check function is defined)
if not neededName:
writeFileMakeDir(STATUS_PATH_TEMPLATE % action['name'], 'DONE')

def doit(opts, args):
os.chdir(opts.siteDir)
if os.path.exists('build/management/bootstrap/bootstrapStatus.txt'):
sys.exit(0)
print 'bootstrapping...'

logging.basicConfig(level=(logging.WARNING - opts.verbose * 10),
format='%(message)s')

if args:
for arg in args:
if arg not in ACTION_DICT:
print >>sys.stderr, 'ERROR: there is no action %s' % arg
print >>sys.stderr, 'available actions are: %s' % (' '.join([a['name'] for a in ACTIONS]))
sys.exit(1)
actions = [ACTION_DICT[arg] for arg in args]
else:
actions = ACTIONS

logging.info('working in %s' % os.getcwd())
for action in ACTIONS:
doAction(opts, action)

# mark overall completion
writeFileMakeDir(STATUS_PATH_TEMPLATE % 'bootstrap', 'DONE')

print '\nnow "source sourceme.sh" before running manage.py again'
sys.exit(1)

def main():
import optparse
parser = optparse.OptionParser('usage: %prog [action1 action2 ...]')
parser.add_option('-y', '--yes',
action='store_true', default=False,
help='Automatically answer yes to all confirmation questions')
parser.add_option('-s', '--siteDir',
default=DEFAULT_SITE_DIR,
help='Site directory to work in [%default]')
parser.add_option('-v', '--verbose',
action='count', default=0,
help='Increase verbosity, can specify multiple times')
opts, args = parser.parse_args()
doit(opts, args)

if __name__ == '__main__':
main()
10 changes: 10 additions & 0 deletions management/requirements.txt
@@ -0,0 +1,10 @@
# This is a pip requirements file
# http://pip.openplans.org/requirement-format.html

# If you have the geocamUtil app, these requirements will be installed
# when you run "manage.py installreqs". This default version just
# installs the requirements of the apps within the site by including the
# auto-generated appRequirements.txt file, but you can do whatever you
# want.

-r ../build/management/appRequirements.txt
1 change: 1 addition & 0 deletions submodules/geocamUtilWeb
Submodule geocamUtilWeb added at 469722

0 comments on commit 833a99e

Please sign in to comment.