|
|
|
@ -1,4 +1,5 @@ |
|
|
|
|
import logging |
|
|
|
|
from ..constants import EXCLUDED_KWARGS, PROFILE |
|
|
|
|
from .commands.base import Command, ItemizedCommand, Template |
|
|
|
|
from .commands.centos import CENTOS_MAPPINGS |
|
|
|
|
from .commands.ubuntu import UBUNTU_MAPPINGS |
|
|
|
@ -6,26 +7,54 @@ from .commands.ubuntu import UBUNTU_MAPPINGS |
|
|
|
|
log = logging.getLogger(__name__) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def command_exists(mappings, name): |
|
|
|
|
"""Indicates whether a given command exists in this overlay. |
|
|
|
|
def command_factory(loader, excluded_kwargs=None, mappings=None, profile=PROFILE.UBUNTU): |
|
|
|
|
"""Get command instances. |
|
|
|
|
|
|
|
|
|
:param mappings: A dictionary of command names and command functions. |
|
|
|
|
:param loader: The loader instance used to generate commands. |
|
|
|
|
:type loader: BaseType[scripttease.lib.loaders.BaseLoader] |
|
|
|
|
|
|
|
|
|
:param excluded_kwargs: For commands that support ad hoc sub-commands (like Django), this is a list of keyword |
|
|
|
|
argument names that must be removed. Defaults to the names of common command attributes. |
|
|
|
|
If your implementation requires custom but otherwise standard command attributes, you'll |
|
|
|
|
need to import the ``EXCLUDED_KWARGS`` constant and add your attribute names before |
|
|
|
|
calling the command factory. |
|
|
|
|
:type excluded_kwargs: list[str] |
|
|
|
|
|
|
|
|
|
:param mappings: Additional command mappings which may be used to override or extend those provided by the selected |
|
|
|
|
profile. This is a dictionary of the command name and the callback. |
|
|
|
|
:type mappings: dict |
|
|
|
|
|
|
|
|
|
:param name: The name of the command. |
|
|
|
|
:type name: str |
|
|
|
|
:param profile: The operating system profile to use for finding commands. |
|
|
|
|
:type profile: str |
|
|
|
|
|
|
|
|
|
:rtype: bool |
|
|
|
|
:returns: A list of instances that may be Command, ItemizedCommand, or Template. |
|
|
|
|
|
|
|
|
|
""" |
|
|
|
|
return name in mappings |
|
|
|
|
# Identify the command mappings to be used. |
|
|
|
|
if profile == "centos": |
|
|
|
|
_mappings = CENTOS_MAPPINGS |
|
|
|
|
elif profile == "ubuntu": |
|
|
|
|
_mappings = UBUNTU_MAPPINGS |
|
|
|
|
else: |
|
|
|
|
log.error("Unsupported or unrecognized profile: %s" % profile) |
|
|
|
|
return None |
|
|
|
|
|
|
|
|
|
# Update mappings if custom mappings have been supplied. |
|
|
|
|
if mappings is not None: |
|
|
|
|
_mappings.update(mappings) |
|
|
|
|
|
|
|
|
|
# Support custom exclusion of kwargs when instantiating a command instance. This is specific to the implementation |
|
|
|
|
# and is not used by scripttease CLI. Most callbacks will ignore this; however, those that support subcommands may |
|
|
|
|
# use this to identify keyword arguments that are standard to scripttease versus those that are custom. |
|
|
|
|
_excluded_kwargs = excluded_kwargs or EXCLUDED_KWARGS |
|
|
|
|
|
|
|
|
|
def command_factory(loader, profile): |
|
|
|
|
# Generate the command instances. |
|
|
|
|
commands = list() |
|
|
|
|
number = 1 |
|
|
|
|
for command_name, args, kwargs in loader.commands: |
|
|
|
|
command = get_command(command_name, profile, *args, **kwargs) |
|
|
|
|
kwargs['excluded_kwargs'] = _excluded_kwargs |
|
|
|
|
|
|
|
|
|
command = get_command(_mappings, command_name, *args, locations=loader.locations, **kwargs) |
|
|
|
|
if command is not None: |
|
|
|
|
command.number = number |
|
|
|
|
commands.append(command) |
|
|
|
@ -35,44 +64,44 @@ def command_factory(loader, profile): |
|
|
|
|
return commands |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_command(name, profile, *args, **kwargs): |
|
|
|
|
def get_command(mappings, name, *args, locations=None, **kwargs): |
|
|
|
|
"""Get a command instance. |
|
|
|
|
|
|
|
|
|
:param mappings: The command mappings. |
|
|
|
|
:type mappings: dict |
|
|
|
|
|
|
|
|
|
:param name: The name of the command. |
|
|
|
|
:type name: str |
|
|
|
|
|
|
|
|
|
:param profile: The operating system profile name. |
|
|
|
|
:type profile: str |
|
|
|
|
:param locations: A list of paths where templates may be found. |
|
|
|
|
:type locations: list[str] |
|
|
|
|
|
|
|
|
|
args and kwargs are passed to the command function. |
|
|
|
|
args and kwargs are passed to the callback. |
|
|
|
|
|
|
|
|
|
:rtype: scripttease.lib.commands.base.Command | scripttease.lib.commands.base.ItemizedCommand | |
|
|
|
|
scripttease.lib.commands.base.Template |
|
|
|
|
|
|
|
|
|
""" |
|
|
|
|
if profile == "centos": |
|
|
|
|
mappings = CENTOS_MAPPINGS |
|
|
|
|
elif profile == "ubuntu": |
|
|
|
|
mappings = UBUNTU_MAPPINGS |
|
|
|
|
else: |
|
|
|
|
log.error("Unsupported or unrecognized profile: %s" % profile) |
|
|
|
|
return None |
|
|
|
|
|
|
|
|
|
# Args need to be mutable. |
|
|
|
|
_args = list(args) |
|
|
|
|
|
|
|
|
|
# Handle templates special. |
|
|
|
|
if name == "template": |
|
|
|
|
source = _args.pop(0) |
|
|
|
|
target = _args.pop(0) |
|
|
|
|
return Template(source, target, **kwargs) |
|
|
|
|
return Template(source, target, locations=locations, **kwargs) |
|
|
|
|
|
|
|
|
|
if not command_exists(mappings, name): |
|
|
|
|
# Command is not recognized, is spelled wrong, etc. |
|
|
|
|
if name not in mappings: |
|
|
|
|
log.warning("Command does not exist: %s" % name) |
|
|
|
|
return None |
|
|
|
|
|
|
|
|
|
callback = mappings[name] |
|
|
|
|
|
|
|
|
|
# Itemization wraps the callback. |
|
|
|
|
if "items" in kwargs: |
|
|
|
|
items = kwargs.pop("items") |
|
|
|
|
return ItemizedCommand(callback, items, *args, **kwargs) |
|
|
|
|
|
|
|
|
|
# The callback generates the Command instance. |
|
|
|
|
return callback(*args, **kwargs) |
|
|
|
|