parent
6fec406d04
commit
b6a7b9dbbc
50 changed files with 2442 additions and 987 deletions
@ -1,8 +1,9 @@ |
|||||||
[run] |
[run] |
||||||
omit = |
omit = |
||||||
docs/* |
docs/* |
||||||
scripttease/cli/__init__.py |
scripttease/cli/* |
||||||
sandbox |
sandbox |
||||||
setup.py |
setup.py |
||||||
|
tests/* |
||||||
tmp/* |
tmp/* |
||||||
tmp.* |
tmp.* |
||||||
|
@ -1 +1 @@ |
|||||||
5.8.18-d |
6.0.0-d |
@ -0,0 +1,204 @@ |
|||||||
|
# Imports |
||||||
|
|
||||||
|
from argparse import ArgumentParser, RawDescriptionHelpFormatter |
||||||
|
from superpython.logging import LoggingHelper |
||||||
|
from ..constants import LOGGER_NAME |
||||||
|
from . import initialize |
||||||
|
from . import subcommands |
||||||
|
|
||||||
|
DEBUG = 10 |
||||||
|
|
||||||
|
logging = LoggingHelper(colorize=True, name=LOGGER_NAME) |
||||||
|
log = logging.setup() |
||||||
|
|
||||||
|
# Commands |
||||||
|
|
||||||
|
|
||||||
|
def main_command(): |
||||||
|
"""Process script configurations.""" |
||||||
|
|
||||||
|
__author__ = "Shawn Davis <shawn@develmaycare.com>" |
||||||
|
__date__ = "2020-07-21" |
||||||
|
__help__ = """NOTES |
||||||
|
|
||||||
|
This command is used to parse configuration files and output the commands. |
||||||
|
|
||||||
|
""" |
||||||
|
__version__ = "0.10.0-d" |
||||||
|
|
||||||
|
# Main argument parser from which sub-commands are created. |
||||||
|
parser = ArgumentParser(description=__doc__, epilog=__help__, formatter_class=RawDescriptionHelpFormatter) |
||||||
|
|
||||||
|
parser.add_argument( |
||||||
|
"path", |
||||||
|
default="commands.ini", |
||||||
|
nargs="?", |
||||||
|
help="The path to the configuration file." |
||||||
|
) |
||||||
|
|
||||||
|
parser.add_argument( |
||||||
|
"-c", |
||||||
|
"--color", |
||||||
|
action="store_true", |
||||||
|
dest="color_enabled", |
||||||
|
help="Enable code highlighting for terminal output." |
||||||
|
) |
||||||
|
|
||||||
|
parser.add_argument( |
||||||
|
"-C=", |
||||||
|
"--context=", |
||||||
|
action="append", |
||||||
|
dest="variables", |
||||||
|
help="Context variables for use in pre-parsing the config and templates. In the form of: name:value" |
||||||
|
) |
||||||
|
|
||||||
|
parser.add_argument( |
||||||
|
"-d", |
||||||
|
"--docs", |
||||||
|
action="store_true", |
||||||
|
dest="docs_enabled", |
||||||
|
help="Output documentation instead of code." |
||||||
|
) |
||||||
|
|
||||||
|
# parser.add_argument( |
||||||
|
# "-d=", |
||||||
|
# "--docs=", |
||||||
|
# choices=["html", "markdown", "plain", "rst"], |
||||||
|
# dest="docs_enabled", |
||||||
|
# help="Output documentation instead of code." |
||||||
|
# ) |
||||||
|
|
||||||
|
parser.add_argument( |
||||||
|
"-D", |
||||||
|
"--debug", |
||||||
|
action="store_true", |
||||||
|
dest="debug_enabled", |
||||||
|
help="Enable debug output." |
||||||
|
) |
||||||
|
|
||||||
|
parser.add_argument( |
||||||
|
"-f=", |
||||||
|
"--filter=", |
||||||
|
action="append", |
||||||
|
dest="filters", |
||||||
|
help="Filter the commands in the form of: attribute:value" |
||||||
|
) |
||||||
|
|
||||||
|
parser.add_argument( |
||||||
|
"-O=", |
||||||
|
"--option=", |
||||||
|
action="append", |
||||||
|
dest="options", |
||||||
|
help="Common command options in the form of: name:value" |
||||||
|
) |
||||||
|
|
||||||
|
# parser.add_argument( |
||||||
|
# "-O=", |
||||||
|
# "--output=", |
||||||
|
# # default=os.path.join("prototype", "output"), |
||||||
|
# dest="output_path", |
||||||
|
# help="Output to the given directory. Defaults to ./prototype/output/" |
||||||
|
# ) |
||||||
|
|
||||||
|
parser.add_argument( |
||||||
|
"-s", |
||||||
|
"--script", |
||||||
|
action="store_true", |
||||||
|
dest="script_enabled", |
||||||
|
help="Output commands as a script." |
||||||
|
) |
||||||
|
|
||||||
|
parser.add_argument( |
||||||
|
"-T=", |
||||||
|
"--template-path=", |
||||||
|
action="append", |
||||||
|
dest="template_locations", |
||||||
|
help="The location of template files that may be used with the template command." |
||||||
|
) |
||||||
|
|
||||||
|
parser.add_argument( |
||||||
|
"-w=", |
||||||
|
"--write=", |
||||||
|
dest="output_file", |
||||||
|
help="Write the output to disk." |
||||||
|
) |
||||||
|
|
||||||
|
parser.add_argument( |
||||||
|
"-V=", |
||||||
|
"--variables-file=", |
||||||
|
dest="variables_file", |
||||||
|
help="Load variables from a file." |
||||||
|
) |
||||||
|
|
||||||
|
# Access to the version number requires special consideration, especially |
||||||
|
# when using sub parsers. The Python 3.3 behavior is different. See this |
||||||
|
# answer: http://stackoverflow.com/questions/8521612/argparse-optional-subparser-for-version |
||||||
|
parser.add_argument( |
||||||
|
"-v", |
||||||
|
action="version", |
||||||
|
help="Show version number and exit.", |
||||||
|
version=__version__ |
||||||
|
) |
||||||
|
|
||||||
|
parser.add_argument( |
||||||
|
"--version", |
||||||
|
action="version", |
||||||
|
help="Show verbose version information and exit.", |
||||||
|
version="%(prog)s" + " %s %s by %s" % (__version__, __date__, __author__) |
||||||
|
) |
||||||
|
|
||||||
|
# Parse arguments. |
||||||
|
args = parser.parse_args() |
||||||
|
|
||||||
|
if args.debug_enabled: |
||||||
|
log.setLevel(DEBUG) |
||||||
|
|
||||||
|
log.debug("Namespace: %s" % args) |
||||||
|
|
||||||
|
# Load context. |
||||||
|
context = dict() |
||||||
|
if args.variables: |
||||||
|
context = initialize.context_from_cli(args.variables) |
||||||
|
|
||||||
|
# Handle filters. |
||||||
|
filters = None |
||||||
|
if args.filters: |
||||||
|
filters = initialize.filters_from_cli(args.filters) |
||||||
|
|
||||||
|
# Handle options. |
||||||
|
options = None |
||||||
|
if args.options: |
||||||
|
options = initialize.options_from_cli(args.options) |
||||||
|
|
||||||
|
if args.variables_file: |
||||||
|
variables = initialize.variable_from_file(args.variables_file) |
||||||
|
if variables: |
||||||
|
context.update(variables) |
||||||
|
|
||||||
|
if args.docs_enabled: |
||||||
|
exit_code = subcommands.output_docs( |
||||||
|
args.path, |
||||||
|
context=context, |
||||||
|
filters=filters, |
||||||
|
locations=args.template_locations, |
||||||
|
options=options |
||||||
|
) |
||||||
|
elif args.script_enabled: |
||||||
|
exit_code = subcommands.output_script( |
||||||
|
args.path, |
||||||
|
color_enabled=args.color_enabled, |
||||||
|
context=context, |
||||||
|
locations=args.template_locations, |
||||||
|
options=options |
||||||
|
) |
||||||
|
else: |
||||||
|
exit_code = subcommands.output_commands( |
||||||
|
args.path, |
||||||
|
color_enabled=args.color_enabled, |
||||||
|
context=context, |
||||||
|
filters=filters, |
||||||
|
locations=args.template_locations, |
||||||
|
options=options |
||||||
|
) |
||||||
|
|
||||||
|
exit(exit_code) |
@ -0,0 +1,58 @@ |
|||||||
|
# Imports |
||||||
|
|
||||||
|
from configparser import ConfigParser |
||||||
|
import logging |
||||||
|
import os |
||||||
|
from superpython.utils import smart_cast |
||||||
|
from ..constants import LOGGER_NAME |
||||||
|
|
||||||
|
log = logging.getLogger(LOGGER_NAME) |
||||||
|
|
||||||
|
# Functions |
||||||
|
|
||||||
|
|
||||||
|
def context_from_cli(variables): |
||||||
|
context = dict() |
||||||
|
for i in variables: |
||||||
|
key, value = i.split(":") |
||||||
|
context[key] = smart_cast(value) |
||||||
|
|
||||||
|
return context |
||||||
|
|
||||||
|
|
||||||
|
def filters_from_cli(filters): |
||||||
|
_filters = dict() |
||||||
|
for i in filters: |
||||||
|
key, value = i.split(":") |
||||||
|
if key not in filters: |
||||||
|
_filters[key] = list() |
||||||
|
|
||||||
|
_filters[key].append(value) |
||||||
|
|
||||||
|
return _filters |
||||||
|
|
||||||
|
|
||||||
|
def options_from_cli(options): |
||||||
|
_options = dict() |
||||||
|
for i in options: |
||||||
|
key, value = i.split(":") |
||||||
|
_options[key] = smart_cast(value) |
||||||
|
|
||||||
|
return _options |
||||||
|
|
||||||
|
|
||||||
|
def variable_from_file(path): |
||||||
|
if not os.path.exists(path): |
||||||
|
log.warning("Variables file does not exist: %s" % path) |
||||||
|
return None |
||||||
|
|
||||||
|
ini = ConfigParser() |
||||||
|
ini.read(path) |
||||||
|
|
||||||
|
variables = dict() |
||||||
|
for section in ini.sections(): |
||||||
|
for key, value in ini.items(section): |
||||||
|
key = "%s_%s" % (section, key) |
||||||
|
variables[key] = smart_cast(vaue) |
||||||
|
|
||||||
|
return variables |
@ -0,0 +1,76 @@ |
|||||||
|
# Imports |
||||||
|
|
||||||
|
from superpython.shell import EXIT |
||||||
|
from superpython.utils import highlight_code |
||||||
|
from ..parsers import load_commands, load_config |
||||||
|
|
||||||
|
# Functions |
||||||
|
|
||||||
|
|
||||||
|
def output_commands(path, color_enabled=False, context=None, filters=None, locations=None, options=None): |
||||||
|
commands = load_commands( |
||||||
|
path, |
||||||
|
context=context, |
||||||
|
filters=filters, |
||||||
|
locations=locations, |
||||||
|
options=options |
||||||
|
) |
||||||
|
if commands is None: |
||||||
|
return EXIT.ERROR |
||||||
|
|
||||||
|
output = list() |
||||||
|
for command in commands: |
||||||
|
statement = command.get_statement(cd=True) |
||||||
|
if statement is None: |
||||||
|
continue |
||||||
|
|
||||||
|
output.append(statement) |
||||||
|
output.append("") |
||||||
|
|
||||||
|
if color_enabled: |
||||||
|
print(highlight_code("\n".join(output), language="bash")) |
||||||
|
else: |
||||||
|
print("\n".join(output)) |
||||||
|
|
||||||
|
return EXIT.OK |
||||||
|
|
||||||
|
|
||||||
|
def output_docs(path, context=None, filters=None, locations=None, options=None): |
||||||
|
commands = load_commands( |
||||||
|
path, |
||||||
|
context=context, |
||||||
|
filters=filters, |
||||||
|
locations=locations, |
||||||
|
options=options |
||||||
|
) |
||||||
|
if commands is None: |
||||||
|
return EXIT.ERROR |
||||||
|
|
||||||
|
count = 1 |
||||||
|
output = list() |
||||||
|
for command in commands: |
||||||
|
output.append("%s. %s" % (count, command.comment)) |
||||||
|
count += 1 |
||||||
|
|
||||||
|
print("\n".join(output)) |
||||||
|
|
||||||
|
return EXIT.OK |
||||||
|
|
||||||
|
|
||||||
|
def output_script(path, color_enabled=False, context=None, filters=None, locations=None, options=None): |
||||||
|
config = load_config( |
||||||
|
path, |
||||||
|
context=context, |
||||||
|
locations=locations, |
||||||
|
options=options |
||||||
|
) |
||||||
|
if config is None: |
||||||
|
return EXIT.ERROR |
||||||
|
|
||||||
|
script = config.as_script() |
||||||
|
if color_enabled: |
||||||
|
print(highlight_code(script.to_string(), language="bash")) |
||||||
|
else: |
||||||
|
print(script) |
||||||
|
|
||||||
|
return EXIT.OK |
@ -1,47 +0,0 @@ |
|||||||
[apache] |
|
||||||
disable_module = a2dismod {{ module_name }} |
|
||||||
disable_site = a2dissite {{ domain_name }}.conf |
|
||||||
enable_module = a2enmod {{ module_name }} |
|
||||||
enable_site = a2ensite {{ domain_name }}.conf |
|
||||||
reload = service apache2 reload |
|
||||||
restart = service apache2 restart |
|
||||||
start = service apache2 start |
|
||||||
stop = service apache2 stop |
|
||||||
test = apachectl configtest |
|
||||||
|
|
||||||
[package_install] |
|
||||||
system = apt-get install -y {{ package_name }} |
|
||||||
pip = pip3 install{% if upgrade %} --upgrade{% endif %} --quiet {{ package_name }} |
|
||||||
|
|
||||||
[package_remove] |
|
||||||
system = apt-get uninstall -y {{ package_name }} |
|
||||||
pip = pip3 uninstall --quiet {{ package_name }} |
|
||||||
|
|
||||||
[system] |
|
||||||
install = apt-get install -y {{ package_name }} |
|
||||||
reboot = reboot |
|
||||||
remove = apt-get uninstall -y {{ package_name }} |
|
||||||
update = apt-get update -y |
|
||||||
upgrade = apt-get upgrade -y |
|
||||||
|
|
||||||
[python] |
|
||||||
virtualenv = virtualenv {{ name }} |
|
||||||
install = pip3 install{% if upgrade %} --upgrade{% endif %} --quiet {{ package_name }} |
|
||||||
remove = pip3 uninstall --quiet {{ package_name }} |
|
||||||
|
|
||||||
[files] |
|
||||||
append = echo "{{ content }}" >> {{ path }} |
|
||||||
chgrp = chgrp{% if recursive %} -R{% endif %} {{ group }} {{ path }} |
|
||||||
chmod = chmod{% if recursive %} -R{% endif %} {{ owner }} {{ path }} |
|
||||||
chown = chown{% if recursive %} -R{% endif %} {{ mode }} {{ path }} |
|
||||||
copy = cp{% if recursive %} -R{% endif %}{% if overwrite %} -n{% endif %} {{ from_path }} {{ to_path }} |
|
||||||
mkdir = mkdir{% if mode %} -m {{ mode }}{% endif %}{% if recursive %} -p{% endif %} {{ path }} |
|
||||||
move = move {{ from_path }} {{ to_path }} |
|
||||||
rename = move {{ from_path }} {{ to_path }} |
|
||||||
remove = rm{% if force %} -f{% endif %}{% if recursive %} -r{% endif %} {{ path }} |
|
||||||
;rsync = ? |
|
||||||
;scopy = ? |
|
||||||
;sed = ? |
|
||||||
symlink = ln -s{% if force %} -f{% endif %} {{ source }} {{ target }} |
|
||||||
touch = touch {{ path }} |
|
||||||
;write = ? |
|
@ -1,224 +0,0 @@ |
|||||||
# Imports |
|
||||||
|
|
||||||
from configparser import RawConfigParser |
|
||||||
import os |
|
||||||
from superpython.utils import parse_jinja_string |
|
||||||
from ..constants import PATH_TO_SCRIPT_TEASE |
|
||||||
|
|
||||||
# Exports |
|
||||||
|
|
||||||
__all__ = ( |
|
||||||
"Overlay", |
|
||||||
) |
|
||||||
|
|
||||||
# Classes |
|
||||||
|
|
||||||
|
|
||||||
class Overlay(object): |
|
||||||
"""An overlay applies commands specific to a given operating system or platform.""" |
|
||||||
|
|
||||||
def __init__(self, name): |
|
||||||
self.is_loaded = False |
|
||||||
self._name = name |
|
||||||
self._path = os.path.join(PATH_TO_SCRIPT_TEASE, "data", "overlays", "%s.ini" % name) |
|
||||||
self._sections = dict() |
|
||||||
|
|
||||||
def __repr__(self): |
|
||||||
return "<%s %s>" % (self.__class__.__name__, self._name) |
|
||||||
|
|
||||||
@property |
|
||||||
def exists(self): |
|
||||||
"""Indicates whether the overlay file exists. |
|
||||||
|
|
||||||
:rtype: bool |
|
||||||
|
|
||||||
""" |
|
||||||
return os.path.exists(self._path) |
|
||||||
|
|
||||||
def get(self, section, key, **kwargs): |
|
||||||
"""Get the command statement for the given section and key. |
|
||||||
|
|
||||||
:param section: The section name. |
|
||||||
:type section: str |
|
||||||
|
|
||||||
:param key: The key within the section. |
|
||||||
:type key: str |
|
||||||
|
|
||||||
kwargs are used to parse the value of the key within the section. |
|
||||||
|
|
||||||
:rtype: str | None |
|
||||||
|
|
||||||
""" |
|
||||||
if not self.has(section, key): |
|
||||||
return None |
|
||||||
|
|
||||||
template = self._sections[section][key] |
|
||||||
|
|
||||||
return parse_jinja_string(template, kwargs) |
|
||||||
|
|
||||||
def has(self, section, key): |
|
||||||
"""Determine whether the overlay contains a given section and key. |
|
||||||
|
|
||||||
:param section: The section name. |
|
||||||
:type section: str |
|
||||||
|
|
||||||
:param key: The key within the section. |
|
||||||
:type key: str |
|
||||||
|
|
||||||
:rtype: bool |
|
||||||
|
|
||||||
""" |
|
||||||
if section not in self._sections: |
|
||||||
return False |
|
||||||
|
|
||||||
if key not in self._sections[section]: |
|
||||||
return False |
|
||||||
|
|
||||||
return True |
|
||||||
|
|
||||||
def load(self): |
|
||||||
"""Load the overlay. |
|
||||||
|
|
||||||
:rtype: bool |
|
||||||
|
|
||||||
""" |
|
||||||
if not self.exists: |
|
||||||
return False |
|
||||||
|
|
||||||
ini = RawConfigParser() |
|
||||||
ini.read(self._path) |
|
||||||
|
|
||||||
for section in ini.sections(): |
|
||||||
self._sections[section] = dict() |
|
||||||
for key, value in ini.items(section): |
|
||||||
self._sections[section][key] = value |
|
||||||
|
|
||||||
self.is_loaded = True |
|
||||||
return True |
|
||||||
|
|
||||||
def to_mapping(self): |
|
||||||
"""Export the overlay as a dictionary with command names as values. |
|
||||||
|
|
||||||
:rtype: dict |
|
||||||
|
|
||||||
""" |
|
||||||
d = dict() |
|
||||||
for section in self._sections: |
|
||||||
d[section] = list() |
|
||||||
for command_name, statement in self._sections[section].items(): |
|
||||||
d[section].append(command_name) |
|
||||||
|
|
||||||
|
|
||||||
class Overlay2(object): |
|
||||||
"""An overlay applies commands specific to a given operating system or platform.""" |
|
||||||
|
|
||||||
def __init__(self, name): |
|
||||||
self.is_loaded = False |
|
||||||
self._name = name |
|
||||||
self._path = os.path.join(PATH_TO_SCRIPT_TEASE, "data", "overlays", "%s.ini" % name) |
|
||||||
self._sections = dict() |
|
||||||
|
|
||||||
self.exists = os.path.exists(self._path) |
|
||||||
|
|
||||||
def __repr__(self): |
|
||||||
return "<%s %s>" % (self.__class__.__name__, self._name) |
|
||||||
|
|
||||||
def command_exists(self, name): |
|
||||||
"""Determine whether a given command exists. |
|
||||||
|
|
||||||
:param name: The name of the command to check. |
|
||||||
:type name: str |
|
||||||
|
|
||||||
:rtype: bool |
|
||||||
|
|
||||||
""" |
|
||||||
section = None |
|
||||||
if "." in name: |
|
||||||
section, name = name.split(".") |
|
||||||
|
|
||||||
if section is not None: |
|
||||||
if section in self._sections: |
|
||||||
return name in self._sections[section] |
|
||||||
|
|
||||||
for section in self._sections.keys(): |
|
||||||
if name in self._sections[section]: |
|
||||||
return True |
|
||||||
|
|
||||||
return False |
|
||||||
|
|
||||||
def get_statement(self, name, *args, **kwargs): |
|
||||||
pass |
|
||||||
|
|
||||||
def get(self, section, key, **kwargs): |
|
||||||
"""Get the command statement for the given section and key. |
|
||||||
|
|
||||||
:param section: The section name. |
|
||||||
:type section: str |
|
||||||
|
|
||||||
:param key: The key within the section. |
|
||||||
:type key: str |
|
||||||
|
|
||||||
kwargs are used to parse the value of the key within the section. |
|
||||||
|
|
||||||
:rtype: str | None |
|
||||||
|
|
||||||
""" |
|
||||||
if not self.has(section, key): |
|
||||||
return None |
|
||||||
|
|
||||||
template = self._sections[section][key] |
|
||||||
|
|
||||||
return parse_jinja_string(template, kwargs) |
|
||||||
|
|
||||||
def has(self, section, key): |
|
||||||
"""Determine whether the overlay contains a given section and key. |
|
||||||
|
|
||||||
:param section: The section name. |
|
||||||
:type section: str |
|
||||||
|
|
||||||
:param key: The key within the section. |
|
||||||
:type key: str |
|
||||||
|
|
||||||
:rtype: bool |
|
||||||
|
|
||||||
""" |
|
||||||
if section not in self._sections: |
|
||||||
return False |
|
||||||
|
|
||||||
if key not in self._sections[section]: |
|
||||||
return False |
|
||||||
|
|
||||||
return True |
|
||||||
|
|
||||||
def load(self): |
|
||||||
"""Load the overlay. |
|
||||||
|
|
||||||
:rtype: bool |
|
||||||
|
|
||||||
""" |
|
||||||
if not self.exists: |
|
||||||
return False |
|
||||||
|
|
||||||
ini = RawConfigParser() |
|
||||||
ini.read(self._path) |
|
||||||
|
|
||||||
for section in ini.sections(): |
|
||||||
self._sections[section] = dict() |
|
||||||
for command_name, statement_template in ini.items(section): |
|
||||||
self._sections[section][command_name] = statement_template |
|
||||||
|
|
||||||
self.is_loaded = True |
|
||||||
|
|
||||||
return True |
|
||||||
|
|
||||||
def to_mapping(self): |
|
||||||
"""Export the overlay as a dictionary with command names as values. |
|
||||||
|
|
||||||
:rtype: dict |
|
||||||
|
|
||||||
""" |
|
||||||
d = dict() |
|
||||||
for section in self._sections: |
|
||||||
d[section] = list() |
|
||||||
for command_name, statement in self._sections[section].items(): |
|
||||||
d[section].append(command_name) |
|
@ -1,2 +1,2 @@ |
|||||||
from .base import Command, ItemizedCommand |
from .base import Command, ItemizedCommand |
||||||
from .factory import command_factory |
# from .factory import command_factory |
||||||
|
@ -1,134 +0,0 @@ |
|||||||
# Imports |
|
||||||
|
|
||||||
import logging |
|
||||||
from ...constants import LOGGER_NAME |
|
||||||
from .base import Command |
|
||||||
|
|
||||||
log = logging.getLogger(LOGGER_NAME) |
|
||||||
|
|
||||||
# Exports |
|
||||||
|
|
||||||
__all__ = ( |
|
||||||
"MAPPING", |
|
||||||
"ConfigTest", |
|
||||||
"DisableModule", |
|
||||||
"DisableSite", |
|
||||||
"EnableModule", |
|
||||||
"EnableSite", |
|
||||||
"Reload", |
|
||||||
"Restart", |
|
||||||
"Start", |
|
||||||
"Stop", |
|
||||||
) |
|
||||||
|
|
||||||
# Classes |
|
||||||
|
|
||||||
|
|
||||||
class ConfigTest(Command): |
|
||||||
"""Run an apache config test.""" |
|
||||||
|
|
||||||
def __init__(self, overlay=None, **kwargs): |
|
||||||
"""There is no argument.""" |
|
||||||
if overlay is not None: |
|
||||||
statement = overlay.get("apache", "test") |
|
||||||
else: |
|
||||||
statement = "apachectl configtest" |
|
||||||
|
|
||||||
kwargs.setdefault('register', "apache_checks_out") |
|
||||||
|
|
||||||
super().__init__(statement, **kwargs) |
|
||||||
|
|
||||||
|
|
||||||
class DisableModule(Command): |
|
||||||
"""Disable an Apache module.""" |
|
||||||
|
|
||||||
def __init__(self, module_name, overlay=None, **kwargs): |
|
||||||
"""Initialize the command. |
|
||||||
|
|
||||||
:param module_name: The module name. |
|
||||||
:type module_name: str |
|
||||||
|
|
||||||
""" |
|
||||||
if overlay is not None: |
|
||||||
statement = overlay.get("apache", "disable_module", module_name=module_name) |
|
||||||
|
|
||||||
statement = "a2dismod %s" % module_name |
|
||||||
|
|
||||||
super().__init__(statement, **kwargs) |
|
||||||
|
|
||||||
|
|
||||||
class DisableSite(Command): |
|
||||||
"""Disable a virtual host.""" |
|
||||||
|
|
||||||
def __init__(self, domain_name, **kwargs): |
|
||||||
"""Initialize the command. |
|
||||||
|
|
||||||
:param domain_name: The domain name. |
|
||||||
:type domain_name: str |
|
||||||
|
|
||||||
""" |
|
||||||
statement = "a2dissite %s.conf" % domain_name |
|
||||||
|
|
||||||
super().__init__(statement, **kwargs) |
|
||||||
|
|
||||||
|
|
||||||
class Enable(Command): |
|
||||||
|
|
||||||
def __init__(self, what, name, **kwargs): |
|
||||||
if what in ("mod", "module"): |
|
||||||
statement = EnableModule(name, **kwargs).statement |
|
||||||
elif what == "site": |
|
||||||
statement = EnableSite(name, **kwargs).statement |
|
||||||
else: |
|
||||||
raise ValueError("Invalid Apache item to be enabled: %s" % what) |
|
||||||
|
|
||||||
super().__init__(statement, **kwargs) |
|
||||||
|
|
||||||
|
|
||||||
class EnableModule(Command): |
|
||||||
"""Enable an Apache module.""" |
|
||||||
|
|
||||||
def __init__(self, module_name, **kwargs): |
|
||||||
"""Initialize the command. |
|
||||||
|
|
||||||
:param module_name: The module name. |
|
||||||
:type module_name: str |
|
||||||
|
|
||||||
""" |
|
||||||
statement = "a2enmod %s" % module_name |
|
||||||
|
|
||||||
super().__init__(statement, **kwargs) |
|
||||||
|
|
||||||
|
|
||||||
class EnableSite(Command): |
|
||||||
"""Enable a virtual host.""" |
|
||||||
|
|
||||||
def __init__(self, domain_name, **kwargs): |
|
||||||
"""Initialize the command. |
|
||||||
|
|
||||||
:param domain_name: The domain name. |
|
||||||
:type domain_name: str |
|
||||||
|
|
||||||
""" |
|
||||||
statement = "a2ensite %s.conf" % domain_name |
|
||||||
|
|
||||||
super().__init__(statement, **kwargs) |
|
||||||
|
|
||||||
|
|
||||||
MAPPING = { |
|
||||||
# 'apache': Apache, |
|
||||||
'apache.check': ConfigTest, |
|
||||||
'apache.config': ConfigTest, |
|
||||||
'apache.configtest': ConfigTest, |
|
||||||
'apache.disable': Disable, |
|
||||||
'apache.disable_mod': DisableModule, |
|
||||||
'apache.disable_module': DisableModule, |
|
||||||
'apache.disable_site': DisableSite, |
|
||||||
'apache.enable': Enable, |
|
||||||
'apache.enable_mod': EnableModule, |
|
||||||
'apache.enable_module': EnableModule, |
|
||||||
'apache.enable_site': EnableSite, |
|
||||||
'apache.mod': EnableModule, |
|
||||||
'apache.module': EnableModule, |
|
||||||
'apache.test': ConfigTest, |
|
||||||
} |
|
@ -1,119 +0,0 @@ |
|||||||
# Imports |
|
||||||
|
|
||||||
from importlib import import_module |
|
||||||
import logging |
|
||||||
# from ..scripts import Function |
|
||||||
from ...constants import LOGGER_NAME |
|
||||||
# from .base import ItemizedCommand |
|
||||||
# from .mappings import MAPPING |
|
||||||
|
|
||||||
log = logging.getLogger(LOGGER_NAME) |
|
||||||
|
|
||||||
# Functions |
|
||||||
|
|
||||||
|
|
||||||
def command_factory(name, comment, overlay, *args, **kwargs): |
|
||||||
# try: |
|
||||||
# _overlay = import_module("scripttease.library.overlays.%s" % overlay) |
|
||||||
# except ImportError as e: |
|
||||||
# log.error("The %s overlay could not be imported: %s" % (overlay, str(e))) |
|
||||||
# return None |
|
||||||
|
|
||||||
if not overlay.command_exists(name): |
|
||||||
log.warning("Command does not exist in %s overlay: %s" % (overlay.name, name)) |
|
||||||
return None |
|
||||||
|
|
||||||
kwargs['comment'] = comment |
|
||||||
|
|
||||||
callback = overlay.MAPPINGS[name] |
|
||||||
return callback(*args, **kwargs) |
|
||||||
|
|
||||||
''' |
|
||||||
def command_exists(name): |
|
||||||
"""Indicates whether the named command exists. |
|
||||||
|
|
||||||
:param name: The name of the command to be checked. |
|
||||||
:type name: str |
|
||||||
|
|
||||||
:rtype: bool |
|
||||||
|
|
||||||
""" |
|
||||||
return name in MAPPING |
|
||||||
|
|
||||||
|
|
||||||
def command_factory(name, comment, overlay, *args, **kwargs): |
|
||||||
# if name in ("func", "function"): |
|
||||||
# kwargs['comment'] = comment |
|
||||||
# return Function(*args, **kwargs) |
|
||||||
|
|
||||||
if not command_exists(name): |
|
||||||
log.warning("No mapping for command: %s" % name) |
|
||||||
return None |
|
||||||
|
|
||||||
_args = list(args) |
|
||||||
kwargs['comment'] = comment |
|
||||||
kwargs['overlay'] = overlay |
|
||||||
|
|
||||||
log.debug("%s: %s" % (comment, kwargs)) |
|
||||||
|
|
||||||
command_class = MAPPING[name] |
|
||||||
try: |
|
||||||
items = kwargs.pop("items", None) |
|
||||||
if items is not None: |
|
||||||
return ItemizedCommand(command_class, items, *_args, **kwargs) |
|
||||||
|
|
||||||
return command_class(*_args, **kwargs) |
|
||||||
except (KeyError, TypeError, ValueError) as e: |
|
||||||
log.critical("Failed to load %s command: %s" % (name, e)) |
|
||||||
return None |
|
||||||
''' |
|
||||||
|
|
||||||
# |
|
||||||
# |
|
||||||
# |
|
||||||
# MAPPINGS = { |
|
||||||
# 'apache.disable_module': apache_disable_module, |
|
||||||
# 'apache.disable_site': apache_disable_site, |
|
||||||
# 'apache.enable_module': apache_enable_module, |
|
||||||
# 'apache.enable_site': apache_enable_site, |
|
||||||
# 'apache.reload': apache_reload, |
|
||||||
# 'apache.restart': apache_restart, |
|
||||||
# 'apache.start': apache_start, |
|
||||||
# 'apache.stop': apache_stop, |
|
||||||
# 'apache.test': apache_test, |
|
||||||
# 'copy': file_copy, |
|
||||||
# 'pip': python_pip, |
|
||||||
# 'virtualenv': python_virtualenv, |
|
||||||
# # 'python': ("pip", "virtualenv"), |
|
||||||
# # 'apache': ("disable_module", "disable_site", "enable_module", "enable_site", "test"), |
|
||||||
# } |
|
||||||
|
|
||||||
|
|
||||||
def nother_command_exists(name): |
|
||||||
return name in MAPPINGS |
|
||||||
|
|
||||||
|
|
||||||
def other_command_exists(name, section=None): |
|
||||||
if section is not None: |
|
||||||
if section not in MAPPINGS: |
|
||||||
return False |
|
||||||
|
|
||||||
return name in MAPPINGS[section] |
|
||||||
|
|
||||||
for _section, commands in MAPPINGS.items(): |
|
||||||
if name in commands: |
|
||||||
return True |
|
||||||
|
|
||||||
return False |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def other_command_factory(name, comment, overlay, *args, **kwargs): |
|
||||||
if not overlay.command_exists(name): |
|
||||||
log.warning("The %s overlay does not have a mapping for command: %s" % (overlay, name)) |
|
||||||
return None |
|
||||||
|
|
||||||
items = kwargs.pop("items", None) |
|
||||||
if items is not None: |
|
||||||
return ItemizedCommand |
|
||||||
|
|
@ -1,4 +0,0 @@ |
|||||||
from .python import MAPPING as PYTHON_MAPPING |
|
||||||
|
|
||||||
MAPPING = dict() |
|
||||||
MAPPING.update(PYTHON_MAPPING) |
|
@ -1,23 +0,0 @@ |
|||||||
# Classes |
|
||||||
|
|
||||||
|
|
||||||
class Install(object): |
|
||||||
|
|
||||||
def __init__(self, name, manager="pip", overlay=None, upgrade=False, **kwargs): |
|
||||||
if overlay is not None: |
|
||||||
statement = overlay.get("package_install", manager, package_name=name, upgrade=upgrade) |
|
||||||
else: |
|
||||||
statement = "%s install %s" % (manager, name) |
|
||||||
|
|
||||||
self.statement = statement |
|
||||||
|
|
||||||
|
|
||||||
class Remove(object): |
|
||||||
|
|
||||||
def __init__(self, name, manager="pip", overlay=None): |
|
||||||
if overlay is not None: |
|
||||||
statement = overlay.get("package_remove", manager, package_name=name) |
|
||||||
else: |
|
||||||
statement = "%s uninstall %s" % (manager, name) |
|
||||||
|
|
||||||
|
|
@ -1,43 +0,0 @@ |
|||||||
# Imports |
|
||||||
|
|
||||||
from .base import Command |
|
||||||
|
|
||||||
# Exports |
|
||||||
|
|
||||||
__all__ = ( |
|
||||||
"Pip", |
|
||||||
"VirtualEnv", |
|
||||||
) |
|
||||||
|
|
||||||
# Classes |
|
||||||
|
|
||||||
|
|
||||||
class Pip(Command): |
|
||||||
|
|
||||||
def __init__(self, name, op="install", overlay=None, upgrade=False, venv=None, **kwargs): |
|
||||||
if overlay is not None: |
|
||||||
statement = overlay.get("python", op, package_name=name, upgrade=upgrade) |
|
||||||
else: |
|
||||||
statement = "pip %s -y %s" % (op, name) |
|
||||||
|
|
||||||
if venv is not None: |
|
||||||
kwargs['prefix'] = "source %s/bin/activate" % venv |
|
||||||
|
|
||||||
kwargs.setdefault("comment", "%s %s" % (op, name)) |
|
||||||
|
|
||||||
super().__init__(statement, **kwargs) |
|
||||||
|
|
||||||
|
|
||||||
class VirtualEnv(Command): |
|
||||||
|
|
||||||
def __init__(self, name="python", overlay=None, **kwargs): |
|
||||||
kwargs.setdefault("comment", "create %s virtual environment" % name) |
|
||||||
|
|
||||||
statement = "virtualenv %s" % name |
|
||||||
super().__init__(statement, **kwargs) |
|
||||||
|
|
||||||
|
|
||||||
MAPPING = { |
|
||||||
'pip': Pip, |
|
||||||
'virtualenv': VirtualEnv, |
|
||||||
} |
|
@ -0,0 +1,164 @@ |
|||||||
|
# Imports |
||||||
|
|
||||||
|
import os |
||||||
|
from ..commands import Command |
||||||
|
|
||||||
|
# Exports |
||||||
|
|
||||||
|
__all__ = ( |
||||||
|
"DJANGO_MAPPINGS", |
||||||
|
"django", |
||||||
|
"django_check", |
||||||
|
"django_collect_static", |
||||||
|
"django_dumpdata", |
||||||
|
"django_loaddata", |
||||||
|
"django_migrate", |
||||||
|
) |
||||||
|
|
||||||
|
# Functions |
||||||
|
|
||||||
|
|
||||||
|
def _django(name, *args, venv=None, **kwargs): |
||||||
|
if venv is not None: |
||||||
|
kwargs['prefix'] = "source %s/bin/activate" % venv |
||||||
|
|
||||||
|
kwargs.setdefault("comment", "run %s django management command" % name) |
||||||
|
|
||||||
|
# Base parameters need to be captured, because all others are assumed to be switches for the management command. |
||||||
|
_kwargs = { |
||||||
|
'comment': kwargs.pop("comment", None), |
||||||
|
'condition': kwargs.pop("condition", None), |
||||||
|
'cd': kwargs.pop("cd", None), |
||||||
|
'environments': kwargs.pop("environments", None), |
||||||
|
'function': kwargs.pop("function", None), |
||||||
|
# 'local': kwargs.pop("local", False), |
||||||
|
'prefix': kwargs.pop("prefix", None), |
||||||
|
'register': kwargs.pop("register", None), |
||||||
|
'shell': kwargs.pop("shell", "/bin/bash"), |
||||||
|
'stop': kwargs.pop("stop", False), |
||||||
|
'sudo': kwargs.pop('sudo', False), |
||||||
|
'tags': kwargs.pop("tags", None), |
||||||
|
} |
||||||
|
|
||||||
|
statement = list() |
||||||
|
statement.append("./manage.py %s" % name) |
||||||
|
|
||||||
|
# Remaining kwargs are assumed to be switches. |
||||||
|
for key, value in kwargs.items(): |
||||||
|
key = key.replace("_", "-") |
||||||
|
if type(value) is bool: |
||||||
|
if value is True: |
||||||
|
statement.append("--%s" % key) |
||||||
|
else: |
||||||
|
statement.append("--%s=%s" % (key, value)) |
||||||
|
|
||||||
|
if len(args) > 0: |
||||||
|
statement.append(" ".join(args)) |
||||||
|
|
||||||
|
return Command(" ".join(statement), **_kwargs) |
||||||
|
|
||||||
|
|
||||||
|
def django(name, *args, venv=None, **kwargs): |
||||||
|
if name == "check": |
||||||
|
return django_check(venv=venv, **kwargs) |
||||||
|
elif name in ("collectstatic", "static"): |
||||||
|
return django_collect_static(venv=venv, **kwargs) |
||||||
|
elif name == "migrate": |
||||||
|
return django_migrate(venv=venv, **kwargs) |
||||||
|
else: |
||||||
|
return _django(name, *args, venv=venv, **kwargs) |
||||||
|
|
||||||
|
|
||||||
|
def django_check(venv=None, **kwargs): |
||||||
|
kwargs.setdefault("comment", "run django checks") |
||||||
|
kwargs.setdefault("register", "django_checks_out") |
||||||
|
|
||||||
|
return _django("check", venv=venv, **kwargs) |
||||||
|
|
||||||
|
|
||||||
|
def django_collect_static(venv=None, **kwargs): |
||||||
|
kwargs.setdefault("comment", "collect static files") |
||||||
|
|
||||||
|
return _django("collectstatic", venv=venv, **kwargs) |
||||||
|
|
||||||
|
|
||||||
|
def django_dumpdata(app_name, base_path="local", file_name="initial", indent=4, natural_foreign=False, |
||||||
|
natural_primary=False, path=None, venv=None, **kwargs): |
||||||
|
"""Initialize the command. |
||||||
|
|
||||||
|
:param app_name: The name (app label) of the app. ``app_label.ModelName`` may also be given. |
||||||
|
:type app_name: str |
||||||
|
|
||||||
|
:param file_name: The file name to which the data will be dumped. |
||||||
|
:type file_name: str |
||||||
|
|
||||||
|
:param indent: Indentation of the exported fixtures. |
||||||
|
:type indent: int |
||||||
|
|
||||||
|
:param natural_foreign: Use the natural foreign parameter. |
||||||
|
:type natural_foreign: bool |
||||||
|
|
||||||
|
:param natural_primary: Use the natural primary parameter. |
||||||
|
:type natural_primary: bool |
||||||
|
|
||||||
|
:param path: The path to the data file. |
||||||
|
:type path: str |
||||||
|
|
||||||
|
""" |
||||||
|
kwargs.setdefault("comment", "export fixtures for %s" % app_name) |
||||||
|
|
||||||
|
output_format = kwargs.pop("format", "json") |
||||||
|
|
||||||
|
_path = path or os.path.join(base_path, app_name, "fixtures", "%s.%s" % (file_name, output_format)) |
||||||
|
|
||||||
|
return _django( |
||||||
|
"dumpdata", |
||||||
|
app_name, |
||||||
|
"> %s" % _path, |
||||||
|
format=output_format, |
||||||
|
indent=indent, |
||||||
|
natural_foreign=natural_foreign, |
||||||
|
natural_primary=natural_primary, |
||||||
|
venv=venv, |
||||||
|
**kwargs |
||||||
|
) |
||||||
|
|
||||||
|
|
||||||
|
def django_loaddata(app_name, base_path="local", file_name="initial", path=None, venv=None, **kwargs): |
||||||
|
"""Initialize the command. |
||||||
|
|
||||||
|
:param app_name: The name (app label) of the app. |
||||||
|
:type app_name: str |
||||||
|
|
||||||
|
:param file_name: The file name to which the data will be dumped. |
||||||
|
:type file_name: str |
||||||
|
|
||||||
|
:param path: The path to the data file. |
||||||
|
:type path: str |
||||||
|
|
||||||
|
""" |
||||||
|
kwargs.setdefault("comment", "load fixtures for %s" % app_name) |
||||||
|
|
||||||
|
output_format = kwargs.pop("format", "json") |
||||||
|
|
||||||
|
_path = path or os.path.join(base_path, app_name, "fixtures", "%s.%s" % (file_name, output_format)) |
||||||
|
|
||||||
|
return _django("loaddata", _path, venv=venv, **kwargs) |
||||||
|
|
||||||
|
|
||||||
|
def django_migrate(venv=None, **kwargs): |
||||||
|
kwargs.setdefault("comment", "run django database migrations") |
||||||
|
|
||||||
|
return _django("migrate", venv=venv, **kwargs) |
||||||
|
|
||||||
|
# Mapping |
||||||
|
|
||||||
|
|
||||||
|
DJANGO_MAPPINGS = { |
||||||
|
'django': django, |
||||||
|
'django.check': django_check, |
||||||
|
'django.collect_static': django_collect_static, |
||||||
|
'django.dumpdata': django_dumpdata, |
||||||
|
'django.loaddata': django_loaddata, |
||||||
|
'django.migrate': django_migrate, |
||||||
|
} |
@ -0,0 +1,292 @@ |
|||||||
|
# Imports |
||||||
|
|
||||||
|
from ..commands import Command |
||||||
|
|
||||||
|
# Exports |
||||||
|
|
||||||
|
__all__ = ( |
||||||
|
"PGSQL_MAPPINGS", |
||||||
|
"pg_create_database", |
||||||
|
"pg_create_user", |
||||||
|
"pg_database_exists", |
||||||
|
"pg_drop_database", |
||||||
|
"pg_drop_user", |
||||||
|
"pg_dump_database", |
||||||
|
"psql", |
||||||
|
) |
||||||
|
|
||||||
|
# Functions |
||||||
|
|
||||||
|
|
||||||
|
def _get_pgsql_command(name, host="localhost", password=None, port=5432, user="postgres"): |
||||||
|
a = list() |
||||||
|
|
||||||
|
if password: |
||||||
|
a.append('export PGPASSWORD="%s" &&' % password) |
||||||
|
|
||||||
|
a.append(name) |
||||||
|
|
||||||
|
a.append("--host=%s" % host) |
||||||
|
a.append("--port=%s" % port) |
||||||
|
a.append("--username=%s" % user) |
||||||
|
|
||||||
|
return a |
||||||
|
|
||||||
|
|
||||||
|
def pg_create_database(name, admin_pass=None, admin_user="postgres", host="localhost", owner=None, port=5432, |
||||||
|
template=None, **kwargs): |
||||||
|
"""Create a PostgreSQL database. |
||||||
|
|
||||||
|
:param name: The database name. |
||||||
|
:type name: str |
||||||
|
|
||||||
|
:param admin_pass: The password for the user with sufficient access privileges to execute the command. |
||||||
|
:type admin_pass: str |
||||||
|
|
||||||
|
:param admin_user: The name of the user with sufficient access privileges to execute the command. |
||||||
|
:type admin_user: str |
||||||
|
|
||||||
|
:param host: The database host name or IP address. |
||||||
|
:type host: str |
||||||
|
|
||||||
|
:param owner: The owner (user/role name) of the new database. |
||||||
|
:type owner: str |
||||||
|
|
||||||
|
:param port: The port number of the Postgres service running on the host. |
||||||
|
:type port: int |
||||||
|
|
||||||
|
:param template: The database template name to use, if any. |
||||||
|
:type template: str |
||||||
|
|
||||||
|
""" |
||||||
|
_owner = owner or admin_user |
||||||
|
|
||||||
|
# Postgres commands always run without sudo because the -U may be provided. |
||||||
|
kwargs['sudo'] = False |
||||||
|
|
||||||
|
# Assemble the command. |
||||||
|
base = _get_pgsql_command("createdb", host=host, password=admin_pass, port=port) |
||||||
|
base.append("--owner=%s" % _owner) |
||||||
|
|
||||||
|
if template is not None: |
||||||
|
base.append("--template=%s" % template) |
||||||
|
|
||||||
|
base.append(name) |
||||||
|
|
||||||
|
return Command(" ".join(base), **kwargs) |
||||||
|
|
||||||
|
|
||||||
|
def pg_create_user(name, admin_pass=None, admin_user="postgres", host="localhost", password=None, port=5432, **kwargs): |
||||||
|
"""Create a PostgreSQL user. |
||||||
|
|
||||||
|
:param name: The user name. |
||||||
|
:type name: str |
||||||
|
|
||||||
|
:param admin_pass: The password for the user with sufficient access privileges to execute the command. |
||||||
|
:type admin_pass: str |
||||||
|
|
||||||
|
:param admin_user: The name of the user with sufficient access privileges to execute the command. |
||||||
|
:type admin_user: str |
||||||
|
|
||||||
|
:param host: The database host name or IP address. |
||||||
|
:type host: str |
||||||
|
|
||||||
|
:param password: The password for the new user. |
||||||
|
:type password: str |
||||||
|
|
||||||
|
:param port: The port number of the Postgres service running on the host. |
||||||
|
:type port: int |
||||||
|
|
||||||
|
""" |
||||||
|
# Postgres commands always run without sudo because the -U may be provided. |
||||||
|
kwargs['sudo'] = False |
||||||
|
|
||||||
|
# Assemble the command. |
||||||
|
base = _get_pgsql_command("createuser", host=host, password=admin_pass, port=port) |
||||||
|
base.append("-DRS") |
||||||
|
base.append(name) |
||||||
|
|
||||||
|
if password is not None: |
||||||
|
base.append("&& psql -h %s -U %s" % (host, admin_user)) |
||||||
|
base.append("-c \"ALTER USER %s WITH ENCRYPTED PASSWORD '%s';\"" % (name, password)) |
||||||
|
|
||||||
|
return Command(" ".join(base), **kwargs) |
||||||
|
|
||||||
|
|
||||||
|
def pg_database_exists(name, admin_pass=None, admin_user="postgres", host="localhost", port=5432, **kwargs): |
||||||
|
"""Determine if a Postgres database exists. |
||||||
|
|
||||||
|
:param name: The database name. |
||||||
|
:type name: str |
||||||
|
|
||||||
|
:param admin_pass: The password for the user with sufficient access privileges to execute the command. |
||||||
|
:type admin_pass: str |
||||||
|
|
||||||
|
:param admin_user: The name of the user with sufficient access privileges to execute the command. |
||||||
|
:type admin_user: str |
||||||
|
|
||||||
|
:param host: The database host name or IP address. |
||||||
|
:type host: str |
||||||
|
|
||||||
|
:param port: The port number of the Postgres service running on the host. |
||||||
|
:type port: int |
||||||
|
|
||||||
|
""" |
||||||
|
# Postgres commands always run without sudo because the -U may be provided. However, sudo may be required for |
||||||
|
# file writing. |
||||||
|
# kwargs['sudo'] = False |
||||||
|
|
||||||
|
kwargs.setdefault("register", "%s_db_exists" % name) |
||||||
|
|
||||||
|
base = _get_pgsql_command("psql", host=host, password=admin_pass, port=port, user=admin_user) |
||||||
|
base.append(r"-lqt | cut -d \| -f 1 | grep -qw %s" % name) |
||||||
|
|
||||||
|
return Command(" ".join(base), **kwargs) |
||||||
|
|
||||||
|
|
||||||
|
def pg_drop_database(name, admin_pass=None, admin_user="postgres", host="localhost", port=5432, **kwargs): |
||||||
|
"""Remove a PostgreSQL database. |
||||||
|
|
||||||
|
:param name: The database name. |
||||||
|
:type name: str |
||||||
|
|
||||||
|
:param admin_pass: The password for the user with sufficient access privileges to execute the command. |
||||||
|
:type admin_pass: str |
||||||
|
|
||||||
|
:param admin_user: The name of the user with sufficient access privileges to execute the command. |
||||||
|
:type admin_user: str |
||||||
|
|
||||||
|
:param host: The database host name or IP address. |
||||||
|
:type host: str |
||||||
|
|
||||||
|
:param port: The port number of the Postgres service running on the host. |
||||||
|
:type port: int |
||||||
|
|
||||||
|
""" |
||||||
|
# Postgres commands always run without sudo because the -U may be provided. |
||||||
|
kwargs['sudo'] = False |
||||||
|
|
||||||
|
# Assemble the command. |
||||||
|
base = _get_pgsql_command("dropdb", host=host, password=admin_pass, port=port, user=admin_user) |
||||||
|
base.append(name) |
||||||
|
|
||||||
|
return Command(" ".join(base), **kwargs) |
||||||
|
|
||||||
|
|
||||||
|
def pg_drop_user(name, admin_pass=None, admin_user="postgres", host="localhost", port=5432, **kwargs): |
||||||
|
"""Remove a Postgres user. |
||||||
|
|
||||||
|
:param name: The user name. |
||||||
|
:type name: str |
||||||
|
|
||||||
|
:param admin_pass: The password for the user with sufficient access privileges to execute the command. |
||||||
|
:type admin_pass: str |
||||||
|
|
||||||
|
:param admin_user: The name of the user with sufficient access privileges to execute the command. |
||||||
|
:type admin_user: str |
||||||
|
|
||||||
|
:param host: The database host name or IP address. |
||||||
|
:type host: str |
||||||
|
|
||||||
|
:param port: The port number of the Postgres service running on the host. |
||||||
|
:type port: int |
||||||
|
|
||||||
|
""" |
||||||
|
# Postgres commands always run without sudo because the -U may be provided. |
||||||
|
kwargs['sudo'] = False |
||||||
|
|
||||||
|
# Assemble the command. |
||||||
|
base = _get_pgsql_command("dropuser", host=host, password=admin_pass, port=port, user=admin_user) |
||||||
|
base.append(name) |
||||||
|
|
||||||
|
return Command(" ".join(base), **kwargs) |
||||||
|
|
||||||
|
|
||||||
|
def pg_dump_database(name, admin_pass=None, admin_user="postgres", file_name=None, host="localhost", port=5432, |
||||||
|
**kwargs): |
||||||
|
"""Export a Postgres database. |
||||||
|
|
||||||
|
:param name: The database name. |
||||||
|
:type name: str |
||||||
|
|
||||||
|
:param admin_pass: The password for the user with sufficient access privileges to execute the command. |
||||||
|
:type admin_pass: str |
||||||
|
|
||||||
|
:param admin_user: The name of the user with sufficient access privileges to execute the command. |
||||||
|
:type admin_user: str |
||||||
|
|
||||||
|
:param host: The database host name or IP address. |
||||||
|
:type host: str |
||||||
|
|
||||||
|
:param file_name: The name (including the path, if desired) of the export file. Defaults to the |
||||||
|
``database_name`` plus ".sql" |
||||||
|
:type file_name: str |
||||||
|
|
||||||
|
:param port: The port number of the Postgres service running on the host. |
||||||
|
:type port: int |
||||||
|
|
||||||
|
""" |
||||||
|
_file_name = file_name or "%s.sql" % name |
||||||
|
|
||||||
|
# Postgres commands always run without sudo because the -U may be provided. |
||||||
|
kwargs['sudo'] = False |
||||||
|
|
||||||
|
# Assemble the command. |
||||||
|
base = _get_pgsql_command("pg_dump", host=host, password=admin_pass, port=port, user=admin_user) |
||||||
|
base.append("--column-inserts") |
||||||
|
base.append("--file=%s" % _file_name) |
||||||
|
base.append(name) |
||||||
|
|
||||||
|
return Command(" ".join(base), **kwargs) |
||||||
|
|
||||||
|
|
||||||
|
def psql(sql, database="template1", host="localhost", password=None, port=5432, user="postgres", **kwargs): |
||||||
|
"""Execute a psql command. |
||||||
|
|
||||||
|
:param sql: The SQL to be executed. |
||||||
|
:type sql: str |
||||||
|
|
||||||
|
:param database: The database name. |
||||||
|
:type database: str |
||||||
|
|
||||||
|
:param password: The password for the user with sufficient access privileges to execute the command. |
||||||
|
:type password: str |
||||||
|
|
||||||
|
:param host: The database host name or IP address. |
||||||
|
:type host: str |
||||||
|
|
||||||
|
:param port: The port number of the Postgres service running on the host. |
||||||
|
:type port: int |
||||||
|
|
||||||
|
:param user: The name of the user with sufficient access privileges to execute the command. |
||||||
|
:type user: str |
||||||
|
|
||||||
|
""" |
||||||
|
# Postgres commands always run without sudo because the -U may be provided. |
||||||
|
kwargs['sudo'] = False |
||||||
|
|
||||||
|
# Assemble the command. |
||||||
|
base = _get_pgsql_command("psql", host=host, password=password, port=port, user=user) |
||||||
|
base.append("--dbname=%s" % database) |
||||||
|
base.append('-c "%s"' % sql) |
||||||
|
|
||||||
|
return Command(" ".join(base), **kwargs) |
||||||
|
|
||||||
|
|
||||||
|
PGSQL_MAPPINGS = { |
||||||
|
'pg.client': psql, |
||||||
|
'pg.createdatabase': pg_create_database, |
||||||
|
'pg.createdb': pg_create_database, |
||||||
|
'pg.createuser': pg_create_user, |
||||||
|
'pg.database': pg_create_database, |
||||||
|
'pg.database_exists': pg_database_exists, |
||||||
|
'pg.db': pg_create_database, |
||||||
|
'pg.dropdatabase': pg_drop_database, |
||||||
|
'pg.dropdb': pg_drop_database, |
||||||
|
'pg.dropuser': pg_drop_user, |
||||||
|
'pg.dump': pg_dump_database, |
||||||
|
'pg.dumpdb': pg_dump_database, |
||||||
|
'pg.exists': pg_database_exists, |
||||||
|
'pg.user': pg_create_user, |
||||||
|
'psql': psql, |
||||||
|
} |
@ -1,85 +1,4 @@ |
|||||||
# Imports |
# Imports |
||||||
|
|
||||||
import logging |
|
||||||
from superpython.utils import any_list_item |
|
||||||
from ..constants import LOGGER_NAME |
|
||||||
from .ini import Config |
from .ini import Config |
||||||
|
from .utils import filter_commands, load_commands, load_config |
||||||
log = logging.getLogger(LOGGER_NAME) |
|
||||||
|
|
||||||
# Exports |
|
||||||
|
|
||||||
__all__ = ( |
|
||||||
"filter_commands", |
|
||||||
"load_commands", |
|
||||||
) |
|
||||||
|
|
||||||
# Functions |
|
||||||
|
|
||||||
|
|
||||||
def filter_commands(commands, environments=None, tags=None): |
|
||||||
"""Filter commands based on the given criteria. |
|
||||||
|
|
||||||
:param commands: The commands to be filtered. |
|
||||||
:type commands: list |
|
||||||
|
|
||||||
:param environments: Environment names to be matched. |
|
||||||
:type environments: list[str] |
|
||||||
|
|
||||||
:param tags: Tag names to be matched. |
|
||||||
:type tags |
|
||||||
:return: |
|
||||||
""" |
|
||||||
filtered = list() |
|
||||||
for command in commands: |
|
||||||
if environments is not None: |
|
||||||
if not any_list_item(environments, command.environments): |
|
||||||
continue |
|
||||||
|
|
||||||
if tags is not None: |
|
||||||
if not any_list_item(tags, command.tags): |
|
||||||
continue |
|
||||||
|
|
||||||
filtered.append(command) |
|
||||||
|
|
||||||
return filtered |
|
||||||
|
|
||||||
|
|
||||||
def load_commands(path, filters=None, overlay=None, **kwargs): |
|
||||||
"""Load commands from a configuration file. |
|
||||||
|
|
||||||
:param path: The path to the configuration file. |
|
||||||
:type path: str |
|
||||||
|
|
||||||
:param filters: Used to filter commands. |
|
||||||
:type filters: dict |
|
||||||
|
|
||||||
:rtype: list[BaseType[Command] | ItemizedCommand] | None |
|
||||||
|
|
||||||
:returns: A list of command instances or ``None`` if the configuration could not be loaded. |
|
||||||
|
|
||||||
kwargs are passed to the configuration class for instantiation. |
|
||||||
|
|
||||||
""" |
|
||||||
if path.endswith(".ini"): |
|
||||||
_config = Config(path, overlay=overlay, **kwargs) |
|
||||||
# elif path.endswith(".yml"): |
|
||||||
# _config = YAML(path, **kwargs) |
|
||||||
else: |
|
||||||
log.warning("Input file format is not currently supported: %s" % path) |
|
||||||
return None |
|
||||||
|
|
||||||
if _config.load(): |
|
||||||
commands = _config.get_commands() |
|
||||||
|
|
||||||
if filters is not None: |
|
||||||
criteria = dict() |
|
||||||
for attribute, values in filters.items(): |
|
||||||
criteria[attribute] = values |
|
||||||
|
|
||||||
commands = filter_commands(commands, **criteria) |
|
||||||
|
|
||||||
return commands |
|
||||||
|
|
||||||
log.error("Failed to load config file: %s" % path) |
|
||||||
return None |
|
||||||
|
@ -0,0 +1,110 @@ |
|||||||
|
# Imports |
||||||
|
|
||||||
|
import logging |
||||||
|
from superpython.utils import any_list_item |
||||||
|
from ..constants import LOGGER_NAME |
||||||
|
from .ini import Config |
||||||
|
|
||||||
|
log = logging.getLogger(LOGGER_NAME) |
||||||
|
|
||||||
|
# Exports |
||||||
|
|
||||||
|
__all__ = ( |
||||||
|
"filter_commands", |
||||||
|
"load_commands", |
||||||
|
) |
||||||
|
|
||||||
|
# Functions |
||||||
|
|
||||||
|
|
||||||
|
def filter_commands(commands, environments=None, tags=None): |
||||||
|
"""Filter commands based on the given criteria. |
||||||
|
|
||||||
|
:param commands: The commands to be filtered. |
||||||
|
:type commands: list |
||||||
|
|
||||||
|
:param environments: Environment names to be matched. |
||||||
|
:type environments: list[str] |
||||||
|
|
||||||
|
:param tags: Tag names to be matched. |
||||||
|
:type tags |
||||||
|
:return: |
||||||
|
""" |
||||||
|
filtered = list() |
||||||
|
for command in commands: |
||||||
|
if environments is not None: |
||||||
|
if not any_list_item(environments, command.environments): |
||||||
|
continue |
||||||
|
|
||||||
|
if tags is not None: |
||||||
|
if not any_list_item(tags, command.tags): |
||||||
|
continue |
||||||
|
|
||||||
|
filtered.append(command) |
||||||
|
|
||||||
|
return filtered |
||||||
|
|
||||||
|
|
||||||
|
def load_commands(path, filters=None, overlay="ubuntu", **kwargs): |
||||||
|
"""Load commands from a configuration file. |
||||||
|
|
||||||
|
:param path: The path to the configuration file. |
||||||
|
:type path: str |
||||||
|
|
||||||
|
:param filters: Used to filter commands. |
||||||
|
:type filters: dict |
||||||
|
|
||||||
|
:param overlay: The name of the command overlay to apply to generated commands. |
||||||
|
:type overlay: str |
||||||
|
|
||||||
|
:rtype: list[scriptetease.library.commands.base.Command] | scriptetease.library.commands.base.ItemizedCommand] | |
||||||
|
None |
||||||
|
|
||||||
|
:returns: A list of command instances or ``None`` if the configuration could not be loaded. |
||||||
|
|
||||||
|
kwargs are passed to the configuration class for instantiation. |
||||||
|
|
||||||
|
""" |
||||||
|
_config = load_config(path, overlay, **kwargs) |
||||||
|
if _config is None: |
||||||
|
return None |
||||||
|
|
||||||
|
commands = _config.get_commands() |
||||||
|
|
||||||
|
if filters is not None: |
||||||
|
criteria = dict() |
||||||
|
for attribute, values in filters.items(): |
||||||
|
criteria[attribute] = values |
||||||
|
|
||||||
|
commands = filter_commands(commands, **criteria) |
||||||
|
|
||||||
|
return commands |
||||||
|
|
||||||
|
|
||||||
|
def load_config(path, overlay="ubuntu", **kwargs): |
||||||
|
"""Load a command configuration. |
||||||
|
|
||||||
|
:param path: The path to the configuration file. |
||||||
|
:type path: str |
||||||
|
|
||||||
|
:param overlay: The name of the command overlay to apply to generated commands. |
||||||
|
:type overlay: str |
||||||
|
|
||||||
|
:rtype: Config | None |
||||||
|
|
||||||
|
kwargs are passed to the configuration class for instantiation. |
||||||
|
|
||||||
|
""" |
||||||
|
if path.endswith(".ini"): |
||||||
|
_config = Config(path, overlay=overlay, **kwargs) |
||||||
|
# elif path.endswith(".yml"): |
||||||
|
# _config = YAML(path, **kwargs) |
||||||
|
else: |
||||||
|
log.warning("Input file format is not currently supported: %s" % path) |
||||||
|
return None |
||||||
|
|
||||||
|
if not _config.load(): |
||||||
|
log.error("Failed to load config file: %s" % path) |
||||||
|
return None |
||||||
|
|
||||||
|
return _config |
@ -1,159 +0,0 @@ |
|||||||
# Imports |
|
||||||
|
|
||||||
from pygments import highlight |
|
||||||
from pygments.lexers import get_lexer_by_name |
|
||||||
from pygments.formatters import get_formatter_by_name |
|
||||||
|
|
||||||
BashLexer = get_lexer_by_name("bash") |
|
||||||
JSONLexer = get_lexer_by_name("json") |
|
||||||
PythonLexer = get_lexer_by_name("python") |
|
||||||
TerminalFormatter = get_formatter_by_name("terminal", linenos=True) |
|
||||||
|
|
||||||
# Exports |
|
||||||
|
|
||||||
__all__ = ( |
|
||||||
"any_list_item", |
|
||||||
"filter_commands", |
|
||||||
"filter_objects", |
|
||||||
"highlight_code", |
|
||||||
"split_csv", |
|
||||||
) |
|
||||||
|
|
||||||
# Functions |
|
||||||
|
|
||||||
|
|
||||||
def any_list_item(a, b): |
|
||||||
"""Determine whether any item in ``a`` also exists in ``b``. |
|
||||||
|
|
||||||
:param a: The first list to be compared. |
|
||||||
:type a: list |
|
||||||
|
|
||||||
:param b: The second list to be compared. |
|
||||||
:type b: list |
|
||||||
|
|
||||||
:rtype: bool |
|
||||||
|
|
||||||
""" |
|
||||||
for i in a: |
|
||||||
for j in b: |
|
||||||
if i == j: |
|
||||||
return True |
|
||||||
|
|
||||||
return False |
|
||||||
|
|
||||||
|
|
||||||
def filter_commands(commands, values, attribute="tags"): |
|
||||||
"""Filter commands for a given set of values. |
|
||||||
|
|
||||||
:param commands: The commands to be filtered. |
|
||||||
:type commands: list[BaseType[Command]] |
|
||||||
|
|
||||||
:param values: The values to be compared. |
|
||||||
:type values: list |
|
||||||
|
|
||||||
:param attribute: The name of the command attribute to check. This attribute must be a list or tuple of values of |
|
||||||
the same type given in ``values``. |
|
||||||
:type attribute: str |
|
||||||
|
|
||||||
:rtype: bool |
|
||||||
|
|
||||||
.. code-block:: python |
|
||||||
|
|
||||||
commands = [ |
|
||||||
AddUser("bob"), |
|
||||||
Apt("apache2", tags=["apache", "www"]), |
|
||||||
Reload("postgresql", tags=["database", "pgsql"]), |
|
||||||
Touch("/var/www/index.html", tags=["www"]), |
|
||||||
] |
|
||||||
|
|
||||||
values = ["apache", "www"] |
|
||||||
|
|
||||||
# Outputs the Apt and Touch commands above. |
|
||||||
filtered_commands = filter_commands(command, values) |
|
||||||
print(filtered_commands) |
|
||||||
|
|
||||||
""" |
|
||||||
filtered = list() |
|
||||||
for command in commands: |
|
||||||
try: |
|
||||||
list_b = getattr(command, attribute) |
|
||||||
except AttributeError: |
|
||||||
continue |
|
||||||
|
|
||||||
if not any_list_item(values, list_b): |
|
||||||
continue |
|
||||||
|
|
||||||
filtered.append(command) |
|
||||||
|
|
||||||
return filtered |
|
||||||
|
|
||||||
|
|
||||||
def filter_objects(objects, environments=None, scope=None, tags=None): |
|
||||||
"""Filter the given objects by the given keys. |
|
||||||
|
|
||||||
:param objects: The objects to be filtered. |
|
||||||
:type objects: list |
|
||||||
|
|
||||||
:param environments: The environments to be included. |
|
||||||
:type environments: list[str] |
|
||||||
|
|
||||||
:param scope: The scope by which to filter; deploy, provision, tenant. |
|
||||||
:type scope: str |
|
||||||
|
|
||||||
:param tags: The tags to be included. |
|
||||||
:type tags: list[str] |
|
||||||
|
|
||||||
:rtype: list |
|
||||||
:returns: Returns the objects that match the given keys. |
|
||||||
|
|
||||||
""" |
|
||||||
filtered = list() |
|
||||||
|
|
||||||
# print("object, object environments, environments, any_list_item") |
|
||||||
|
|
||||||
for o in objects: |
|
||||||
|
|
||||||
# print(o, o.environments, environments, any_list_item(environments, o.environments)) |
|
||||||
|
|
||||||
# Apply environment filter. |
|
||||||
if environments is not None: |
|
||||||
if hasattr(o, "environment"): |
|
||||||
if o.environment is not None and o.environment not in environments: |
|
||||||
continue |
|
||||||
elif hasattr(o, "environments"): |
|
||||||
if type(o.environments) in (list, tuple) and not any_list_item(environments, o.environments): |
|
||||||
continue |
|
||||||
else: |
|
||||||
pass |
|
||||||
|
|
||||||
# # Apply scope filter. |
|
||||||
# if scope is not None: |
|
||||||
# if o.scope not in [None, SCOPE_ALL, scope]: |
|
||||||
# continue |
|
||||||
|
|
||||||
# Apply tag filter. |
|
||||||
if tags is not None: |
|
||||||
if not any_list_item(tags, o.tags): |
|
||||||
continue |
|
||||||
|
|
||||||
# The object has passed the tests above. |
|
||||||
filtered.append(o) |
|
||||||
|
|
||||||
return filtered |
|
||||||
|
|
||||||
|
|
||||||
def highlight_code(string, lexer=None): |
|
||||||
"""Highlight (colorize) the given string as Python code. |
|
||||||
|
|
||||||
:param string: The string to be highlighted. |
|
||||||
:type string: str |
|
||||||
|
|
||||||
:rtype: str |
|
||||||
|
|
||||||
""" |
|
||||||
if lexer is None: |
|
||||||
lexer = BashLexer |
|
||||||
|
|
||||||
return highlight(string, lexer, TerminalFormatter) |
|
||||||
|
|
||||||
|
|
@ -0,0 +1,2 @@ |
|||||||
|
[this command will fail to load] |
||||||
|
nonexistent = testing |
@ -0,0 +1,2 @@ |
|||||||
|
[this command will fail to load] |
||||||
|
run - testing |
@ -0,0 +1,6 @@ |
|||||||
|
[create the site directory] |
||||||
|
mkdir: /var/www/domains/{{ domain_tld }} |
||||||
|
|
||||||
|
[this will cause template parsing to fail] |
||||||
|
touch: /path/to/{% if this.will.break %}testing |
||||||
|
|
@ -0,0 +1,25 @@ |
|||||||
|
[function for setting up apache] |
||||||
|
func = apache_setup |
||||||
|
|
||||||
|
[install apache] |
||||||
|
install: apache2 |
||||||
|
func: apache_setup |
||||||
|
|
||||||
|
[install wsgi] |
||||||
|
install: mod_wsgi |
||||||
|
func: apache_setup |
||||||
|
|
||||||
|
[enable wsgi] |
||||||
|
apache.enable_module: mod_wsgi |
||||||
|
func: apache_setup |
||||||
|
|
||||||
|
[disable the default site] |
||||||
|
apache.disable_site = default |
||||||
|
func: apache_setup |
||||||
|
|
||||||
|
[restart apache] |
||||||
|
apache: restart |
||||||
|
func: apache_setup |
||||||
|
|
||||||
|
[call apache setup] |
||||||
|
run: apache_setup |
@ -0,0 +1,192 @@ |
|||||||
|
[update system repos] |
||||||
|
system: update |
||||||
|
|
||||||
|
[upgrade the system] |
||||||
|
system: upgrade |
||||||
|
|
||||||
|
[reboot the system] |
||||||
|
system: reboot |
||||||
|
|
||||||
|
[function for setting up apache] |
||||||
|
func = apache_setup |
||||||
|
|
||||||
|
[install apache] |
||||||
|
install: apache2 |
||||||
|
func: apache_setup |
||||||
|
|
||||||
|
[install wsgi] |
||||||
|
install: mod_wsgi |
||||||
|
func: apache_setup |
||||||
|
|
||||||
|
[enable wsgi] |
||||||
|
apache.enable_module: mod_wsgi |
||||||
|
func: apache_setup |
||||||
|
|
||||||
|
[disable the default site in function] |
||||||
|
apache.disable_site = default |
||||||
|
func: apache_setup |
||||||
|
|
||||||
|
[restart apache] |
||||||
|
apache: restart |
||||||
|
func: apache_setup |
||||||
|
|
||||||
|
[call apache setup] |
||||||
|
run: apache_setup |
||||||
|
|
||||||
|
[disable the default site] |
||||||
|
apache.disable_site = default |
||||||
|
|
||||||
|
[enable mod SSL] |
||||||
|
apache.enable_module = mod_ssl |
||||||
|
|
||||||
|
[enable more than one apache module at once] |
||||||
|
apache.enable_module = $item |
||||||
|
items = mod_wsgi, mod_rewrite |
||||||
|
|
||||||
|
[make sure apache can be reloaded] |
||||||
|
apache: test |
||||||
|
|
||||||
|
[restart apache outside of function] |
||||||
|
apache: restart |
||||||
|
condition: $apache_checks_out -eq 0 |
||||||
|
|
||||||
|
[install the virtualenv package] |
||||||
|
pip = virtualenv |
||||||
|
|
||||||
|
[install django debug toolbar] |
||||||
|
pip: django-debug-toolbar |
||||||
|
env: development |
||||||
|
tags: python, project |
||||||
|
|
||||||
|
[create a virtual environment] |
||||||
|
virtualenv = python |
||||||
|
cd = /path/to/project |
||||||
|
tags = python, project |
||||||
|
|
||||||
|
[install pillow] |
||||||
|
pip = Pillow |
||||||
|
cd = /path/to/project |
||||||
|
upgrade = yes |
||||||
|
venv = python |
||||||
|
tags = python, project |
||||||
|
|
||||||
|
[apply database migrations] |
||||||
|
django: migrate |
||||||
|
cd: /path/to/project |
||||||
|
venv: python |
||||||
|
|
||||||
|
[run a custom django command] |
||||||
|
django = custom_command arg1 arg2 |
||||||
|
cd = /path/to/project |
||||||
|
venv = python |
||||||
|
settings = tenants.example_app.settings |
||||||
|
quiet = yes |
||||||
|
|
||||||
|
[collect the project's static files] |
||||||
|
django: collectstatic |
||||||
|
cd: /path/to/project |
||||||
|
venv: python |
||||||
|
|
||||||
|
[load data fixtures] |
||||||
|
django.loaddata: categories |
||||||
|
cd: /path/to/project |
||||||
|
venv: python |
||||||
|
|
||||||
|
[dump data fixtures] |
||||||
|
django.dumpdata: projects |
||||||
|
cd: /path/to/project |
||||||
|
venv: python |
||||||
|
|
||||||
|
[reload a service] |
||||||
|
reload: postfix |
||||||
|
|
||||||
|
[restart a service] |
||||||
|
restart: postfix |
||||||
|
|
||||||
|
[stop a service] |
||||||
|
stop: postfix |
||||||
|
|
||||||
|
[start a service] |
||||||
|
start: postfix |
||||||
|
|
||||||
|
[install a package] |
||||||
|
install: python3 |
||||||
|
|
||||||
|
[remove a package] |
||||||
|
uninstall: apache-top |
||||||
|
|
||||||
|
[add to a file] |
||||||
|
append: /path/to/file.txt |
||||||
|
content: this is a test |
||||||
|
|
||||||
|
[copy a file] |
||||||
|
copy: /path/to/file.txt /new/path/to/file.txt |
||||||
|
|
||||||
|
[write (overwrite) a file] |
||||||
|
write: /path/to/file.txt |
||||||
|
content: this replaces all text in the file |
||||||
|
|
||||||
|
[create a directory] |
||||||
|
mkdir: /path/to/dir |
||||||
|
mode: 755 |
||||||
|
|
||||||
|
[move a file] |
||||||
|
move: /path/to/file.txt /path/to/file.txt.b |
||||||
|
|
||||||
|
[set permissions on a file] |
||||||
|
perms: /path/to/file.txt |
||||||
|
group: www-data |
||||||
|
mode: 755 |
||||||
|
owner: deploy |
||||||
|
recursive: yes |
||||||
|
|
||||||
|
[remove a file] |
||||||
|
remove: /path/to/file.txt |
||||||
|
|
||||||
|
[sync a directory] |
||||||
|
rsync: /path/to/source /path/to/target |
||||||
|
|
||||||
|
[copy a file to remote server] |
||||||
|
scopy: /path/to/file.txt /path/to/server/file.txt |
||||||
|
host: example.com |
||||||
|
|
||||||
|
[replace text in a file] |
||||||
|
sed: /path/to/file.txt |
||||||
|
find: logging = no |
||||||
|
replace: logging = yes |
||||||
|
|
||||||
|
[create a symlink] |
||||||
|
symlink: /var/www/domains |
||||||
|
|
||||||
|
[touch a file] |
||||||
|
touch: /path/to/file.txt |
||||||
|
|
||||||
|
[create a postgres user/role] |
||||||
|
pg.user: example_app |
||||||
|
|
||||||
|
[create a postgres database] |
||||||
|
pg.db: example_app |
||||||
|
owner: example_app |
||||||
|
|
||||||
|
[determine whether a postgres database exists] |
||||||
|
pg.database_exists: example_app |
||||||
|
|
||||||
|
[export a postgres database] |
||||||
|
pg.dump: testing |
||||||
|
|
||||||
|
[drop a postgres user/role] |
||||||
|
pg.dropuser: testing |
||||||
|
|
||||||
|
[drop a postgres database] |
||||||
|
pg.dropdb: testing |
||||||
|
|
||||||
|
[run an SQL command on a postgres database] |
||||||
|
psql: "SELECT * FROM projects WHERE category = 'testing'" |
||||||
|
database: example_app |
||||||
|
owner: example_app |
||||||
|
|
||||||
|
[create a file archive] |
||||||
|
archive: /var/www/domains/example_com |
||||||
|
|
||||||
|
[extract a file archive] |
||||||
|
extract: /var/www/domains/example_com.tgz |
@ -1,12 +1,15 @@ |
|||||||
[install the virtualenv package] |
[install the virtualenv package] |
||||||
pip = virtualenv |
pip = virtualenv |
||||||
|
tags = python-support |
||||||
|
|
||||||
[create a virtual environment] |
[create a virtual environment] |
||||||
virtualenv = python |
virtualenv = python |
||||||
cd = /path/to/project |
cd = /path/to/project |
||||||
|
tags = python-support |
||||||
|
|
||||||
[install pillow] |
[install pillow] |
||||||
pip = Pillow |
pip = Pillow |
||||||
cd = /path/to/project |
cd = /path/to/project |
||||||
upgrade = yes |
upgrade = yes |
||||||
venv = python |
venv = python |
||||||
|
tags = depends |
@ -0,0 +1,2 @@ |
|||||||
|
[create the site directory] |
||||||
|
mkdir: /var/www/domains/{{ domain_tld }} |
@ -0,0 +1,40 @@ |
|||||||
|
from scripttease.library.commands import Command, ItemizedCommand |
||||||
|
from scripttease.factory import Factory |
||||||
|
|
||||||
|
|
||||||
|
class TestFactory(object): |
||||||
|
|
||||||
|
def test_get_command(self): |
||||||
|
f = Factory("ubuntu") |
||||||
|
f.load() |
||||||
|
|
||||||
|
# Non-existent command. |
||||||
|
c = f.get_command("nonexistent") |
||||||
|
assert c is None |
||||||
|
|
||||||
|
# A good command with itemized parameters. |
||||||
|
c = f.get_command( |
||||||
|
"pip", |
||||||
|
"$item", |
||||||
|
items=["Pillow", "psycopg2-binary", "django"] |
||||||
|
) |
||||||
|
assert isinstance(c, ItemizedCommand) |
||||||
|
|
||||||
|
# A good, normal command. |
||||||
|
c = f.get_command("pip", "django") |
||||||
|
assert isinstance(c, Command) |
||||||
|
|
||||||
|
# Command exists, but given bad arguments. |
||||||
|
c = f.get_command("pip") |
||||||
|
assert c is None |
||||||
|
|
||||||
|
def test_load(self): |
||||||
|
f = Factory("nonexistent") |
||||||
|
assert f.load() is False |
||||||
|
|
||||||
|
f = Factory("ubuntu") |
||||||
|
assert f.load() is True |
||||||
|
|
||||||
|
def test_repr(self): |
||||||
|
f = Factory("centos") |
||||||
|
assert repr(f) == "<Factory centos>" |
@ -1,20 +0,0 @@ |
|||||||
from scripttease.library.commands import command_factory, ItemizedCommand |
|
||||||
from scripttease.library.commands.python import Pip |
|
||||||
from scripttease.library.overlays import Overlay |
|
||||||
|
|
||||||
|
|
||||||
def test_command_factory(): |
|
||||||
overlay = Overlay("ubuntu") |
|
||||||
overlay.load() |
|
||||||
|
|
||||||
command = command_factory("nonexistent", "non existent command", overlay) |
|
||||||
assert command is None |
|
||||||
|
|
||||||
command = command_factory("pip", "install pillow", overlay) |
|
||||||
assert command is None |
|
||||||
|
|
||||||
command = command_factory("pip", "install pillow", overlay, "Pillow") |
|
||||||
assert isinstance(command, Pip) |
|
||||||
|
|
||||||
command = command_factory("pip", "install various", overlay, "$item", items=["Pillow", "pyscopg2-binary", "django"]) |
|
||||||
assert isinstance(command, ItemizedCommand) |
|
@ -1,18 +0,0 @@ |
|||||||
from scripttease.library.commands.python import * |
|
||||||
from scripttease.library.overlays import Overlay |
|
||||||
|
|
||||||
|
|
||||||
def test_pip(): |
|
||||||
pip = Pip("Pillow") |
|
||||||
assert "pip install -y Pillow" in pip.get_statement() |
|
||||||
|
|
||||||
overlay = Overlay("ubuntu") |
|
||||||
overlay.load() |
|
||||||
|
|
||||||
pip = Pip("Pillow", op="remove", overlay=overlay, venv="python") |
|
||||||
assert "source python/bin/activate && pip3 uninstall --quiet Pillow" in pip.get_statement() |
|
||||||
|
|
||||||
|
|
||||||
def test_virtualenv(): |
|
||||||
virt = VirtualEnv() |
|
||||||
assert "virtualenv python" in virt.get_statement() |
|
@ -0,0 +1,17 @@ |
|||||||
|
from scripttease.library.overlays.common import * |
||||||
|
|
||||||
|
|
||||||
|
def test_python_pip(): |
||||||
|
c = python_pip("Pillow") |
||||||
|
assert "pip install -y Pillow" in c.get_statement() |
||||||
|
|
||||||
|
c = python_pip("Pillow", upgrade=True) |
||||||
|
assert "--upgrade" in c.get_statement() |
||||||
|
|
||||||
|
c = python_pip("Pillow", venv="python") |
||||||
|
assert "source python/bin/activate" in c.get_statement() |
||||||
|
|
||||||
|
|
||||||
|
def test_python_virtual_env(): |
||||||
|
c = python_virtualenv() |
||||||
|
assert "virtualenv python" in c.get_statement() |
@ -0,0 +1,61 @@ |
|||||||
|
from scripttease.library.overlays.django import * |
||||||
|
|
||||||
|
|
||||||
|
def test_django(): |
||||||
|
c = django("check") |
||||||
|
assert "./manage.py check" in c.get_statement() |
||||||
|
|
||||||
|
c = django("collectstatic") |
||||||
|
assert "./manage.py collectstatic" in c.get_statement() |
||||||
|
|
||||||
|
c = django("migrate") |
||||||
|
assert "./manage.py migrate" in c.get_statement() |
||||||
|
|
||||||
|
c = django("custom", "arg1", "arg2", venv="python", settings="tenants.example.settings", quiet=True) |
||||||
|
s = c.get_statement() |
||||||
|
assert "./manage.py custom" in s |
||||||
|
assert "arg1" in s |
||||||
|
assert "arg2" in s |
||||||
|
assert "--settings=" in s |
||||||
|
assert "source python/bin/activate" in s |
||||||
|
assert "--quiet" in s |
||||||
|
|
||||||
|
|
||||||
|
def test_django_check(): |
||||||
|
c = django_check(venv="python") |
||||||
|
s = c.get_statement() |
||||||
|
assert "./manage.py check" in s |
||||||
|
assert "source python/bin/activate" in s |
||||||
|
|
||||||
|
|
||||||
|
def test_django_collect_static(): |
||||||
|
c = django_collect_static(venv="python") |
||||||
|
s = c.get_statement() |
||||||
|
assert "./manage.py collectstatic" in s |
||||||
|
assert "source python/bin/activate" in s |
||||||
|
|
||||||
|
|
||||||
|
def test_django_dumpdata(): |
||||||
|
c = django_dumpdata("projects") |
||||||
|
s = c.get_statement() |
||||||
|
assert "./manage.py dumpdata" in s |
||||||
|
assert "projects >" in s |
||||||
|
assert "--format=json" in s |
||||||
|
assert "--indent=4" in s |
||||||
|
assert "local/projects/fixtures/initial.json" in s |
||||||
|
|
||||||
|
|
||||||
|
def test_django_loaddata(): |
||||||
|
c = django_loaddata("projects") |
||||||
|
s = c.get_statement() |
||||||
|
print(s) |
||||||
|
assert "./manage.py loaddata" in s |
||||||
|
assert "local/projects/fixtures/initial.json" in s |
||||||
|
|
||||||
|
|
||||||
|
def test_django_migrate(): |
||||||
|
c = django_migrate(cd="/path/to/project/", venv="python") |
||||||
|
s = c.get_statement(cd=True) |
||||||
|
assert "./manage.py migrate" in s |
||||||
|
assert "source python/bin/activate" in s |
||||||
|
assert "cd /path/to/project/" in s |
@ -0,0 +1,60 @@ |
|||||||
|
from scripttease.library.overlays.pgsql import * |
||||||
|
|
||||||
|
|
||||||
|
def test_pg_create_database(): |
||||||
|
c = pg_create_database("testing", admin_pass="secret", template="mytemplate") |
||||||
|
s = c.get_statement() |
||||||
|
assert "createdb" in s |
||||||
|
assert "export PGPASSWORD=" in s |
||||||
|
assert "--host=" in s |
||||||
|
assert "--port=" in s |
||||||
|
assert "--username=" in s |
||||||
|
assert "--owner=" in s |
||||||
|
assert "--template=mytemplate" in s |
||||||
|
assert "testing" in s |
||||||
|
|
||||||
|
|
||||||
|
def test_pg_create_user(): |
||||||
|
c = pg_create_user("testing", password="secret") |
||||||
|
s = c.get_statement() |
||||||
|
assert "createuser" in s |
||||||
|
assert "-DRS" in s |
||||||
|
assert "testing" in s |
||||||
|
assert "ALTER USER testing" in s |
||||||
|
|
||||||
|
|
||||||
|
def test_pg_database_exists(): |
||||||
|
c = pg_database_exists("testing") |
||||||
|
s = c.get_statement() |
||||||
|
assert "psql" in s |
||||||
|
assert "testing_db_exists" in s |
||||||
|
|
||||||
|
|
||||||
|
def test_pg_drop_database(): |
||||||
|
c = pg_drop_database("testing") |
||||||
|
s = c.get_statement() |
||||||
|
assert "dropdb" in s |
||||||
|
assert "testing" in s |
||||||
|
|
||||||
|
|
||||||
|
def test_pg_drop_user(): |
||||||
|
c = pg_drop_user("testing") |
||||||
|
s = c.get_statement() |
||||||
|
assert "dropuser" in s |
||||||
|
assert "testing" in s |
||||||
|
|
||||||
|
|
||||||
|
def test_pg_dump_database(): |
||||||
|
c = pg_dump_database("testing") |
||||||
|
s = c.get_statement() |
||||||
|
assert "pg_dump" in s |
||||||
|
assert "--column-inserts" in s |
||||||
|
assert "--file=testing.sql" in s |
||||||
|
|
||||||
|
|
||||||
|
def test_psql(): |
||||||
|
c = psql("SELECT * FROM projects", database="testing") |
||||||
|
s = c.get_statement() |
||||||
|
assert "psql" in s |
||||||
|
assert "--dbname=testing" in s |
||||||
|
assert '-c "SELECT * FROM projects"' in s |
@ -0,0 +1,209 @@ |
|||||||
|
import pytest |
||||||
|
from scripttease.library.overlays.posix import * |
||||||
|
|
||||||
|
|
||||||
|
def test_archive(): |
||||||
|
c = archive( |
||||||
|
"/path/to/target", |
||||||
|
absolute=True, |
||||||
|
exclude="*.log", |
||||||
|
strip=1, |
||||||
|
view=True |
||||||
|
) |
||||||
|
s = c.get_statement() |
||||||
|
print(s) |
||||||
|
# tar -czPv --exclude *.log --strip-components 1 -f ./archive.tgz /path/to/target |
||||||
|
assert "tar -czPv --exclude *.log --strip-components 1" in s |
||||||
|
assert "-f ./archive.tgz /path/to/target" in s |
||||||
|
|
||||||
|
|
||||||
|
def test_certbot(): |
||||||
|
with pytest.raises(ValueError): |
||||||
|
c = certbot("example.com") |
||||||
|
|
||||||
|
c = certbot("example.com", email="webmaster@example.com") |
||||||
|
s = c.get_statement() |
||||||
|
assert "certbot certonly --agree-tos --email webmaster@example.com -n" in s |
||||||
|
assert "--webroot -w /var/www/domains/example_com/www -d example.com" in s |
||||||
|
|
||||||
|
|
||||||
|
def test_extract(): |
||||||
|
c = extract( |
||||||
|
"/path/to/archive.tgz", |
||||||
|
absolute=True, |
||||||
|
exclude="*.log", |
||||||
|
strip=1, |
||||||
|
view=True |
||||||
|
) |
||||||
|
s = c.get_statement() |
||||||
|
assert "tar -xzPv --exclude *.log --strip-components 1" in s |
||||||
|
assert "-f /path/to/archive.tgz ./" in s |
||||||
|
|
||||||
|
|
||||||
|
def test_file_append(): |
||||||
|
c = file_append("/path/to/file.txt", content="testing = yes") |
||||||
|
assert 'echo "testing = yes" >> /path/to/file.txt' in c.get_statement() |
||||||
|
|
||||||
|
|
||||||
|
def test_file_copy(): |
||||||
|
c = file_copy("/path/to/file.txt", "/path/to/new-file.txt") |
||||||
|
s = c.get_statement() |
||||||
|
assert "cp" in s |
||||||
|
assert "-n" in s |
||||||
|
assert "/path/to/file.txt /path/to/new-file.txt" in s |
||||||
|
|
||||||
|
c = file_copy("/path/to/dir", "/path/to/newdir", recursive=True) |
||||||
|
s = c.get_statement() |
||||||
|
assert "cp" in s |
||||||
|
assert "-R" in s |
||||||
|
assert "/path/to/dir /path/to/newdir" in s |
||||||
|
|
||||||
|
|
||||||
|
def test_file_write(): |
||||||
|
c = file_write("/path/to/file.txt", content="testing 123") |
||||||
|
assert 'echo "testing 123" > /path/to/file.txt' in c.get_statement() |
||||||
|
|
||||||
|
content = [ |
||||||
|
"I am testing", |
||||||
|
"I am testing", |
||||||
|
"I am testing", |
||||||
|
"testing 123", |
||||||
|
] |
||||||
|
c = file_write("/path/to/file.txt", content="\n".join(content)) |
||||||
|
s = c.get_statement() |
||||||
|
assert "cat > /path/to/file.txt << EOF" in s |
||||||
|
assert "I am testing" in s |
||||||
|
assert "testing 123" in s |
||||||
|
|
||||||
|
|
||||||
|
def test_mkdir(): |
||||||
|
c = mkdir("/path/to/dir", mode=755, recursive=True) |
||||||
|
s = c.get_statement() |
||||||
|
assert "mkdir" in s |
||||||
|
assert "-m 755" in s |
||||||
|
assert "-p" in s |
||||||
|
assert "/path/to/dir" in s |
||||||
|
|
||||||
|
|
||||||
|
def test_move(): |
||||||
|
c = move("/path/to/file.txt", "/path/to/file.txt.b") |
||||||
|
assert "mv /path/to/file.txt /path/to/file.txt.b" in c.get_statement() |
||||||
|
|
||||||
|
|
||||||
|
def test_perms(): |
||||||
|
c = perms("/path/to/dir", group="www-data", mode=755, owner="deploy", recursive=True) |
||||||
|
s = c.get_statement() |
||||||
|
assert "chgrp -R www-data /path/to/dir" in s |
||||||
|
assert "chown -R deploy /path/to/dir" in s |
||||||
|
assert "chmod -R 755 /path/to/dir" in s |
||||||
|
|
||||||
|
|
||||||
|
def test_remove(): |
||||||
|
c = remove("/path/to/dir", force=True, recursive=True) |
||||||
|
s = c.get_statement() |
||||||
|
assert "rm" in s |
||||||
|
assert "-f" in s |
||||||
|
assert "-r" in s |
||||||
|
assert "/path/to/dir" in s |
||||||
|
|
||||||
|
|
||||||
|
def test_rsync(): |
||||||
|
c = rsync( |
||||||
|
"/path/to/local/", |
||||||
|
"/path/to/remote", |
||||||
|
links=True, |
||||||
|
delete=True, |
||||||
|
exclude="deploy/exclude.txt", |
||||||
|
recursive=True, |
||||||
|
host="example.com", |
||||||
|
key_file="~/.ssh/deploy", |
||||||
|
user="deploy" |
||||||
|
) |
||||||
|
s = c.get_statement() |
||||||
|
assert "rsync --cvs-exclude --checksum --compress --copy-links --delete" in s |
||||||
|
assert "--exclude-from=deploy/exclude.txt" in s |
||||||
|
assert "-P" in s |
||||||
|
assert "--recursive /path/to/local/" in s |
||||||
|
assert '-e "ssh -i ~/.ssh/deploy -p 22"' in s |
||||||
|
assert "deploy@example.com:/path/to/remote" in s |
||||||
|
|
||||||
|
c = rsync( |
||||||
|
"/path/to/local/", |
||||||
|
"/path/to/remote", |
||||||
|
links=True, |
||||||
|
delete=True, |
||||||
|
exclude="deploy/exclude.txt", |
||||||
|
recursive=True, |
||||||
|
) |
||||||
|
s = c.get_statement() |
||||||
|
assert "rsync --cvs-exclude --checksum --compress --copy-links --delete" in s |
||||||
|
assert "--exclude-from=deploy/exclude.txt" in s |
||||||
|
assert "-P" in s |
||||||
|
assert "--recursive" in s |
||||||
|
assert "/path/to/local/" in s |
||||||
|
assert "/path/to/remote" in s |
||||||
|
|
||||||
|
|
||||||
|
def test_run(): |
||||||
|
c = run("ls -ls") |
||||||
|
assert "ls -ls" in c.get_statement() |
||||||
|
|
||||||
|
|
||||||
|
def test_scopy(): |
||||||
|
with pytest.raises(ValueError): |
||||||
|
c = scopy("/path/to/local/file.txt", "/path/to/remote/file.txt") |
||||||
|
|
||||||
|
c = scopy( |
||||||
|
"/path/to/local/file.txt", |
||||||
|
"/path/to/remote/file.txt", |
||||||
|
key_file="~/.ssh/deploy", |
||||||
|
host="example.com", |
||||||
|
user="deploy" |
||||||
|
) |
||||||
|
s = c.get_statement() |
||||||
|
assert "scp -i ~/.ssh/deploy" in s |
||||||
|
assert "-P 22" in s |
||||||
|
assert "/path/to/local/file.txt" in s |
||||||
|
assert "deploy@example.com:/path/to/remote/file.txt" in s |
||||||
|
|
||||||
|
c = scopy( |
||||||
|
"/path/to/local/file.txt", |
||||||
|
"/path/to/remote/file.txt", |
||||||
|
host="example.com", |
||||||
|
) |
||||||
|
s = c.get_statement() |
||||||
|
assert "scp -P 22" in s |
||||||
|
assert "/path/to/local/file.txt" in s |
||||||
|
assert "example.com:/path/to/remote/file.txt" in s |
||||||
|
|
||||||
|
|
||||||
|
def test_sed(): |
||||||
|
c = sed("/path/to/file.txt", find="testing", replace="123") |
||||||
|
s = c.get_statement() |
||||||
|
assert "sed -i .b" in s |
||||||
|
assert "s/testing/123/g" in s |
||||||
|
assert "/path/to/file.txt" in s |
||||||
|
|
||||||
|
|
||||||
|
def test_symlink(): |
||||||
|
c = symlink("/var/www/domains", force=True) |
||||||
|
s = c.get_statement() |
||||||
|
assert "ln -s" in s |
||||||
|
assert "-f" in s |
||||||
|
assert "/var/www/domains" in s |
||||||
|
|
||||||
|
|
||||||
|
def test_touch(): |
||||||
|
c = touch("/path/to/file.txt") |
||||||
|
assert "touch /path/to/file.txt" in c.get_statement() |
||||||
|
|
||||||
|
|
||||||
|
class TestFunction(object): |
||||||
|
|
||||||
|
def test_to_string(self): |
||||||
|
f = Function("testing", comment="A test function.") |
||||||
|
f.commands.append(touch("/path/to/file.txt")) |
||||||
|
s = f.to_string() |
||||||
|
assert "# A test function." in s |
||||||
|
assert "function testing()" in s |
||||||
|
assert "touch /path/to/file.txt" in s |
@ -0,0 +1,86 @@ |
|||||||
|
import pytest |
||||||
|
from scripttease.library.overlays.ubuntu import * |
||||||
|
|
||||||
|
|
||||||
|
def test_apache(): |
||||||
|
c = apache("reload") |
||||||
|
assert "service apache2 reload" in c.get_statement() |
||||||
|
|
||||||
|
c = apache("restart") |
||||||
|
assert "service apache2 restart" in c.get_statement() |
||||||
|
|
||||||
|
c = apache("start") |
||||||
|
assert "service apache2 start" in c.get_statement() |
||||||
|
|
||||||
|
c = apache("stop") |
||||||
|
assert "service apache2 stop" in c.get_statement() |
||||||
|
|
||||||
|
c = apache("test") |
||||||
|
assert "apachectl configtest" in c.get_statement() |
||||||
|
|
||||||
|
with pytest.raises(NameError): |
||||||
|
apache("nonexistent") |
||||||
|
|
||||||
|
|
||||||
|
def test_apache_disable_module(): |
||||||
|
c = apache_disable_module("mod_ssl") |
||||||
|
assert "a2dismod mod_ssl" in c.get_statement() |
||||||
|
|
||||||
|
|
||||||
|
def test_apache_disable_site(): |
||||||
|
c = apache_disable_site("default") |
||||||
|
assert "a2dissite default" in c.get_statement() |
||||||
|
|
||||||
|
|
||||||
|
def test_apache_enable_module(): |
||||||
|
c = apache_enable_module("mod_wsgi") |
||||||
|
assert "a2enmod mod_wsgi" in c.get_statement() |
||||||
|
|
||||||
|
|
||||||
|
def test_apache_enable_site(): |
||||||
|
c = apache_enable_site("example.com") |
||||||
|
assert "a2ensite example.com" in c.get_statement() |
||||||
|
|
||||||
|
|
||||||
|
def test_service_reload(): |
||||||
|
c = service_reload("postfix") |
||||||
|
assert "service postfix reload" in c.get_statement() |
||||||
|
|
||||||
|
|
||||||
|
def test_service_restart(): |
||||||
|
c = service_restart("postfix") |
||||||
|
assert "service postfix restart" in c.get_statement() |
||||||
|
|
||||||
|
|
||||||
|
def test_service_start(): |
||||||
|
c = service_start("postfix") |
||||||
|
assert "service postfix start" in c.get_statement() |
||||||
|
|
||||||
|
|
||||||
|
def test_service_stop(): |
||||||
|
c = service_stop("postfix") |
||||||
|
assert "service postfix stop" in c.get_statement() |
||||||
|
|
||||||
|
|
||||||
|
def test_system(): |
||||||
|
c = system("reboot") |
||||||
|
assert "reboot" in c.get_statement() |
||||||
|
|
||||||
|
c = system("update") |
||||||
|
assert "apt-get update -y" in c.get_statement() |
||||||
|
|
||||||
|
c = system("upgrade") |
||||||
|
assert "apt-get upgrade -y" in c.get_statement() |
||||||
|
|
||||||
|
with pytest.raises(NameError): |
||||||
|
system("nonexistent") |
||||||
|
|
||||||
|
|
||||||
|
def test_system_install(): |
||||||
|
c = system_install("vim") |
||||||
|
assert "apt-get install -y vim" in c.get_statement() |
||||||
|
|
||||||
|
|
||||||
|
def test_system_uninstall(): |
||||||
|
c = system_uninstall("lftp") |
||||||
|
assert "apt-get uninstall -y lftp" in c.get_statement() |
@ -0,0 +1,31 @@ |
|||||||
|
from scripttease.library.commands import Command, ItemizedCommand |
||||||
|
from scripttease.library.overlays.posix import Function |
||||||
|
from scripttease.library.scripts import Script |
||||||
|
|
||||||
|
|
||||||
|
class TestScript(object): |
||||||
|
|
||||||
|
def test_append(self): |
||||||
|
s = Script("testing") |
||||||
|
s.append(Command("ls -ls", comment="list some stuff")) |
||||||
|
s.append(Command("touch /path/to/file.txt", comment="touch a file")) |
||||||
|
s.append(Command("ln -s /path/to/file.txt", comment="link to a file")) |
||||||
|
|
||||||
|
assert len(s.commands) == 3 |
||||||
|
|
||||||
|
def test_to_string(self): |
||||||
|
s = Script("testing") |
||||||
|
s.append(Command("ls -ls", comment="list some stuff")) |
||||||
|
s.append(Command("touch /path/to/file.txt", comment="touch a file")) |
||||||
|
s.append(Command("ln -s /path/to/file.txt", comment="link to a file")) |
||||||
|
|
||||||
|
s.functions = list() |
||||||
|
s.functions.append(Function("testing")) |
||||||
|
|
||||||
|
output = s.to_string() |
||||||
|
assert output == str(s) |
||||||
|
|
||||||
|
assert "ls -ls" in output |
||||||
|
assert "touch /path/to/file.txt" in output |
||||||
|
assert "ln -s /path/to/file.txt" in output |
||||||
|
assert "function testing()" in output |
@ -1,19 +0,0 @@ |
|||||||
from scripttease.library.overlays import Overlay |
|
||||||
|
|
||||||
|
|
||||||
class TestOverlay(object): |
|
||||||
|
|
||||||
def test_get(self): |
|
||||||
overlay = Overlay("ubuntu") |
|
||||||
overlay.load() |
|
||||||
assert overlay.get("nonexistent", "nonexistent") is None |
|
||||||
|
|
||||||
def test_has(self): |
|
||||||
overlay = Overlay("ubuntu") |
|
||||||
overlay.load() |
|
||||||
assert overlay.has("nonexistent", "nonexistent") is False |
|
||||||
assert overlay.has("python", "nonexistent") is False |
|
||||||
|
|
||||||
def test_load(self): |
|
||||||
overlay = Overlay("nonexistent") |
|
||||||
assert overlay.load() is False |
|
@ -0,0 +1,22 @@ |
|||||||
|
import pytest |
||||||
|
from scripttease.library.scripts import Script |
||||||
|
# from scripttease.parsers import filter_commands, load_commands |
||||||
|
from scripttease.parsers.base import Parser |
||||||
|
|
||||||
|
|
||||||
|
class TestParser(object): |
||||||
|
|
||||||
|
def test_as_script(self): |
||||||
|
p = Parser("/path/to/nonexistent.txt") |
||||||
|
assert isinstance(p.as_script(), Script) |
||||||
|
|
||||||
|
# def test_get_commands(self): |
||||||
|
# pass |
||||||
|
# |
||||||
|
# def test_get_functions(self): |
||||||
|
# pass |
||||||
|
|
||||||
|
def test_load(self): |
||||||
|
p = Parser("/path/to/nonexistent.txt") |
||||||
|
with pytest.raises(NotImplementedError): |
||||||
|
p.load() |
@ -0,0 +1,45 @@ |
|||||||
|
import pytest |
||||||
|
from scripttease.parsers.ini import Config |
||||||
|
|
||||||
|
|
||||||
|
class TestConfig(object): |
||||||
|
|
||||||
|
def test_get_commands(self): |
||||||
|
c = Config("tests/examples/kitchen_sink.ini") |
||||||
|
assert c.load() is True |
||||||
|
|
||||||
|
assert len(c.get_commands()) > 0 |
||||||
|
|
||||||
|
def test_get_functions(self): |
||||||
|
c = Config("tests/examples/kitchen_sink.ini") |
||||||
|
assert c.load() is True |
||||||
|
|
||||||
|
assert len(c.get_functions()) > 0 |
||||||
|
|
||||||
|
def test_load(self): |
||||||
|
c = Config("nonexistent.ini") |
||||||
|
assert c.load() is False |
||||||
|
|
||||||
|
c = Config("tests/examples/python_examples.ini", overlay="nonexistent") |
||||||
|
assert c.load() is False |
||||||
|
|
||||||
|
c = Config("tests/examples/bad_examples.ini") |
||||||
|
assert c.load() is False |
||||||
|
|
||||||
|
c = Config("tests/examples/kitchen_sink.ini") |
||||||
|
assert c.load() is True |
||||||
|
|
||||||
|
c = Config("tests/examples/bad_command.ini") |
||||||
|
assert c.load() is False |
||||||
|
|
||||||
|
context = { |
||||||
|
'domain_tld': "example_com", |
||||||
|
} |
||||||
|
c = Config("tests/examples/template_example.ini", context=context) |
||||||
|
assert c.load() is True |
||||||
|
|
||||||
|
context = { |
||||||
|
'domain_tld': "example_com", |
||||||
|
} |
||||||
|
c = Config("tests/examples/bad_template_example.ini", context=context) |
||||||
|
assert c.load() is False |
@ -0,0 +1,42 @@ |
|||||||
|
import pytest |
||||||
|
from scripttease.library.commands import Command, ItemizedCommand |
||||||
|
from scripttease.parsers import filter_commands, load_commands |
||||||
|
|
||||||
|
|
||||||
|
def test_filter_commands(): |
||||||
|
commands = [ |
||||||
|
Command("apt-get install apache2 -y", environments=["base"], tags=["web"]), |
||||||
|
Command("apt-get install apache-top -y", environments=["live"], tags=["web"]), |
||||||
|
Command("pip install django-debug-toolbar", environments=["development"], tags=["django"]), |
||||||
|
Command("pip install django", environments=["base"], tags=["django"]), |
||||||
|
] |
||||||
|
f1 = filter_commands(commands, environments=["base", "live"]) |
||||||
|
assert len(f1) == 3 |
||||||
|
|
||||||
|
f2 = filter_commands(commands, tags=["django"]) |
||||||
|
assert len(f2) == 2 |
||||||
|
|
||||||
|
f3 = filter_commands(commands, environments=["base", "development"]) |
||||||
|
assert len(f3) == 3 |
||||||
|
|
||||||
|
f4 = filter_commands(commands, environments=["base"], tags=["web"]) |
||||||
|
assert len(f4) == 1 |
||||||
|
|
||||||
|
|
||||||
|
def test_load_commands(): |
||||||
|
commands = load_commands("nonexistent.xml") |
||||||
|
assert commands is None |
||||||
|
|
||||||
|
commands = load_commands("nonexistent.ini") |
||||||
|
assert commands is None |
||||||
|
|
||||||
|
commands = load_commands("tests/examples/bad_examples.ini") |
||||||
|
assert commands is None |
||||||
|
|
||||||
|
commands = load_commands( |
||||||
|
"tests/examples/python_examples.ini", |
||||||
|
filters={ |
||||||
|
'tags': ["python-support"], |
||||||
|
} |
||||||
|
) |
||||||
|
assert len(commands) == 2 |
Loading…
Reference in new issue