387 lines
9.8 KiB
Python
387 lines
9.8 KiB
Python
import os
|
|
import errno
|
|
import logging
|
|
|
|
import fabric.contrib.files
|
|
|
|
from contextlib import contextmanager as _contextmanager
|
|
from fabric.api import env, prefix, local
|
|
from fabric.operations import run, sudo
|
|
|
|
|
|
def printvar(name, value, exit=False):
|
|
print "%s : %s" % (name, value)
|
|
if exit:
|
|
import sys
|
|
sys.exit()
|
|
|
|
|
|
def loggify(module, func, prefix=""):
|
|
"""
|
|
I'm tired of rewriting this logging code in every single function, so I
|
|
decided to just dump it here, and return a logger that can be used and
|
|
thrown away when it's done
|
|
|
|
module - name of the module being used, ie 'nginx', 'deploy', etc
|
|
func - the name of the function this logger is going to be used in
|
|
prefix - anything you want to add to the front of the logger, ie '\n'
|
|
|
|
returns a logging object
|
|
"""
|
|
|
|
loggername = '{module}.{func}'.format(
|
|
module=module, func=func)
|
|
|
|
str_logging = '{prefix}%(levelname)s: {loggername} %(message)s'.format(
|
|
prefix=prefix,
|
|
loggername=loggername)
|
|
|
|
logging.basicConfig(
|
|
format=str_logging,
|
|
level=logging.DEBUG)
|
|
|
|
return logging.getLogger(loggername)
|
|
|
|
|
|
def print_console(string, prepend="\n\n", append="\n\n", sep="-", numsep=44):
|
|
"""
|
|
helper function to take a string, and format it so it prints to the console
|
|
in a way that is pleasing to the eye.
|
|
|
|
string - the string to be printed
|
|
prepend - defaults to two line spaces, can be anything
|
|
append - defaults to two lines spaces after the string is printed
|
|
sep - the character used to print out one line above the string and
|
|
one line after
|
|
numsep - number of times the separator is printed out on a line
|
|
"""
|
|
|
|
print prepend
|
|
|
|
if sep:
|
|
print sep * numsep
|
|
|
|
print string
|
|
|
|
if sep:
|
|
print sep * numsep
|
|
|
|
print append
|
|
|
|
|
|
def print_debug(debugstr, module, function):
|
|
print "%s:%s:%s" \
|
|
% (module, function, debugstr)
|
|
|
|
|
|
def executize(config_execute):
|
|
"""
|
|
A couple of times using fabric I've found that I'll need to switch between
|
|
sudo, run or local depending on where I'm executing the function, because
|
|
repeating this code in every funcion that needs it can be straingint on the
|
|
eyes, I'm putting it here for use.
|
|
|
|
config_execute - a string that can represent the value of 'sudo',
|
|
'run', or 'local'
|
|
|
|
return the fabric command corresponding to the string value
|
|
in config_execute
|
|
"""
|
|
|
|
_execute = local
|
|
if config_execute == 'sudo':
|
|
_execute = sudo
|
|
elif config_execute == 'run':
|
|
_execute = run
|
|
elif config_execute == 'local':
|
|
_execute = local
|
|
|
|
return _execute
|
|
|
|
|
|
def booleanize(value):
|
|
"""
|
|
take the argument and return it as either True or False
|
|
|
|
if the argument is neither, return False by default and warn the user that
|
|
there is a problem
|
|
"""
|
|
|
|
true_values = ("y", "yes", "true", "1")
|
|
false_values = ("n", "no", "false", "0")
|
|
|
|
if isinstance(value, bool):
|
|
return value
|
|
|
|
if value.lower() in true_values:
|
|
return True
|
|
|
|
elif value.lower() in false_values:
|
|
return False
|
|
|
|
raise TypeError("Cannot booleanize ambiguous value '%s'" % value)
|
|
|
|
|
|
def ensure_dir(directory):
|
|
"""
|
|
Create a directory if it's not exists
|
|
"""
|
|
try:
|
|
if not os.path.exists(directory):
|
|
print "creating directory: %s" % directory
|
|
os.makedirs(directory)
|
|
|
|
except OSError, e:
|
|
if e.errno != errno.EEXIST:
|
|
print "Error occurred while creating directory: %s" % directory
|
|
raise
|
|
|
|
|
|
def ensure_file(f):
|
|
"""
|
|
Simulates linux 'touch' command
|
|
"""
|
|
if not os.path.exists(f):
|
|
open(f, 'w').close()
|
|
|
|
|
|
def upload_template(filename, destination, context, use_jinja,
|
|
use_sudo, backup, template_dir, debug=False):
|
|
|
|
if env.debug:
|
|
logging.basicConfig(
|
|
format='\n%(levelname)s: utils.upload_template %(message)s',
|
|
level=logging.DEBUG)
|
|
|
|
command_msg = "\n\tupload_template(" \
|
|
"\n\tfilename={filename}," \
|
|
"\n\tdestination={destination_available}," \
|
|
"\n\tcontext={context}," \
|
|
"\n\tuse_jinja={use_jinja}," \
|
|
"\n\tuse_sudo={use_sudo}," \
|
|
"\n\tbackup={backup}," \
|
|
"\n\ttemplate_dir={template_dir})\n".format(
|
|
filename=filename,
|
|
destination_available=destination,
|
|
context=context,
|
|
use_jinja=use_jinja,
|
|
use_sudo=use_sudo,
|
|
backup=backup,
|
|
template_dir=template_dir)
|
|
|
|
if debug:
|
|
return command_msg
|
|
|
|
else:
|
|
|
|
fabric.contrib.files.upload_template(
|
|
filename=filename,
|
|
destination=destination,
|
|
context=context,
|
|
use_jinja=use_jinja,
|
|
use_sudo=use_sudo,
|
|
backup=backup,
|
|
template_dir=template_dir)
|
|
|
|
|
|
def get_upload_template_msg(filename, destination, context, use_jinja,
|
|
use_sudo, backup, template_dir, debug=False):
|
|
|
|
command_msg = "\n\tupload_template(" \
|
|
"\n\tfilename={filename}," \
|
|
"\n\tdestination={destination_available}," \
|
|
"\n\tcontext={context}," \
|
|
"\n\tuse_jinja={use_jinja}," \
|
|
"\n\tuse_sudo={use_sudo}," \
|
|
"\n\tbackup={backup}," \
|
|
"\n\ttemplate_dir={template_dir})\n".format(
|
|
filename=filename,
|
|
destination_available=destination,
|
|
context=context,
|
|
use_jinja=use_jinja,
|
|
use_sudo=use_sudo,
|
|
backup=backup,
|
|
template_dir=template_dir)
|
|
|
|
return command_msg
|
|
|
|
|
|
@_contextmanager
|
|
def virtualenv_source():
|
|
with prefix("source virtualenvwrapper.sh"):
|
|
yield
|
|
|
|
|
|
@_contextmanager
|
|
def virtualenv():
|
|
configuration = env.config
|
|
with virtualenv_source():
|
|
with prefix("workon %s" % configuration.virtualenv.name):
|
|
yield
|
|
|
|
# with prefix("/bin/bash -c -l 'source %s'" %
|
|
# configuration.virtualenv.activate):
|
|
# yield
|
|
|
|
# with prefix("/bin/bash -c -l 'source /usr/local/bin/' \
|
|
# 'virtualenvwrapper.sh ' \
|
|
# '&& workon %s'" % configuration.virtualenv.name):
|
|
# yield
|
|
|
|
|
|
def generate_template_build_path(section, template_name='conf'):
|
|
"""
|
|
helper function to automate creation of build path
|
|
|
|
section - the template section we are building off of
|
|
template_name - by default this is "conf", but can be different, for
|
|
example, the 'database' section has 3 different template names
|
|
|
|
returns a path to where the template should be placed
|
|
"""
|
|
import os
|
|
|
|
configuration = env.config
|
|
|
|
conf_section = getattr(configuration.templates, section)
|
|
|
|
conf_section_templatename = getattr(conf_section, template_name)
|
|
|
|
build_path = os.path.join(
|
|
conf_section.path.remote,
|
|
'build',
|
|
conf_section_templatename.dst)
|
|
|
|
return build_path
|
|
|
|
|
|
def generate_template_files_path(section):
|
|
"""
|
|
helper function to automate creation of build path
|
|
|
|
section - the template section we are building off of
|
|
|
|
returns a path to where the template jinja file is located
|
|
"""
|
|
import os
|
|
|
|
configuration = env.config
|
|
|
|
conf_section = getattr(configuration.templates, section)
|
|
|
|
files_path = os.path.join(
|
|
conf_section.path.local,
|
|
'files')
|
|
|
|
return files_path
|
|
|
|
|
|
def print_run(command, prefix="\"\n\t", suffix="\n\t\""):
|
|
"""
|
|
helper function for when I want a string that has the form
|
|
|
|
"\n\t run(some_command_string) \t\n"
|
|
|
|
where "somce_command_string" is a bash script commmand or something like
|
|
that
|
|
"""
|
|
|
|
return "run ({prefix}{command}{suffix})".format(
|
|
prefix=prefix,
|
|
suffix=suffix,
|
|
command=command)
|
|
|
|
|
|
def handle_help(param, message, values=None):
|
|
|
|
values_default = ['-h', '--help']
|
|
|
|
if values is None:
|
|
values = values_default
|
|
|
|
if isinstance(param, str):
|
|
if param.lower() in values:
|
|
print message
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
def is_help(key):
|
|
help_keys = ['-h', '--help']
|
|
|
|
return key in help_keys
|
|
|
|
|
|
def link_create(path_src, path_dst, debug=False):
|
|
"""
|
|
takes a source and destination path, then links it
|
|
if the destination path already exists and is a link,
|
|
then delete it. Otherwise sys.exit
|
|
|
|
path_src - source path
|
|
path_dst - destination path
|
|
|
|
returns: if debug=True then it returns a msg
|
|
"""
|
|
|
|
from fabric.contrib.files import is_link
|
|
from fabric.contrib.files import exists
|
|
from fabric.operations import run
|
|
|
|
cmd_rm = "rm {path_dst}".format(
|
|
path_dst=path_dst
|
|
)
|
|
|
|
cmd_link = "ln -sf {path_src} {path_dst}".format(
|
|
path_src=path_src,
|
|
path_dst=path_dst
|
|
)
|
|
|
|
msg_debug = ""
|
|
|
|
if exists(path_dst):
|
|
if is_link(path_dst):
|
|
if debug:
|
|
msg_debug += "link already exists at dst, removing\n" \
|
|
"link_create:cmd_rm : %s" % cmd_rm
|
|
else:
|
|
run(cmd_rm)
|
|
else:
|
|
msg_error = "something exists at dst - '%s' " \
|
|
"- and it's not a link\n kicking out".format(path_dst)
|
|
import sys
|
|
sys.exit(msg_error)
|
|
|
|
if debug:
|
|
msg_debug += "link_create:cmd_link : %s" % cmd_link
|
|
else:
|
|
run(cmd_link)
|
|
|
|
return msg_debug
|
|
|
|
|
|
def prompt_continue(message="Do you want to continue? Y/n", default="Y"):
|
|
""" prompts user if he wants to continue
|
|
|
|
Keyword Arguments:
|
|
|
|
message -- ask if user wants to continue
|
|
default -- what to do if the user hits enter without giving a value
|
|
"""
|
|
|
|
from fabric.operations import prompt
|
|
import sys
|
|
|
|
prompt_val = prompt(message)
|
|
|
|
if prompt_val == "":
|
|
prompt_val = default
|
|
|
|
if env.debug:
|
|
printvar(
|
|
"prompt_val", prompt_val,
|
|
not booleanize(prompt_val))
|
|
else:
|
|
if not booleanize(prompt_val):
|
|
sys.exit()
|