You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
236 lines
7.1 KiB
236 lines
7.1 KiB
.. _how-to:
|
|
|
|
******
|
|
How To
|
|
******
|
|
|
|
Create a New Command Overlay
|
|
============================
|
|
|
|
:ref:`topics-overlays` are used to define the commands supported by a given application, service, or operating system. Commands are defined as a function.
|
|
|
|
1) Define a Module
|
|
------------------
|
|
|
|
The first step is to create a new module in which functions will be defined.
|
|
|
|
.. code-block:: python
|
|
|
|
# module_name.py
|
|
from ..commands import Command
|
|
|
|
For overlays that represent an operating system, the ``command_exists()`` function is required:
|
|
|
|
.. code-block:: python
|
|
|
|
def command_exists(name):
|
|
return name in MAPPINGS
|
|
|
|
|
|
2) Define Command Function
|
|
--------------------------
|
|
|
|
The purpose of each function is to provide an interface for instantiating a :py:class:`scripttease.library.commands.base.Command` instance. The example below is taken from the ``posix`` module.
|
|
|
|
.. code-block:: python
|
|
|
|
# module_name.py
|
|
# ...
|
|
|
|
def mkdir(path, mode=None, recursive=True, **kwargs):
|
|
"""Create a directory.
|
|
|
|
- path (str): The path to be created.
|
|
- mode (int | str): The access permissions of the new directory.
|
|
- recursive (bool): Create all directories along the path.
|
|
|
|
"""
|
|
kwargs.setdefault("comment", "create directory %s" % path)
|
|
|
|
statement = ["mkdir"]
|
|
if mode is not None:
|
|
statement.append("-m %s" % mode)
|
|
|
|
if recursive:
|
|
statement.append("-p")
|
|
|
|
statement.append(path)
|
|
|
|
return Command(" ".join(statement), **kwargs)
|
|
|
|
The arguments and any specific keyword arguments are automatically used by the parser, but also serve as a simple interface for programmatic use.
|
|
|
|
Each function *must* also accept ``**kwargs`` and should set a default for ``comment`` as above.
|
|
|
|
.. important::
|
|
Rather than the usual Spinx-based documentation, define the docstring as shown above. This is used to automatically create the documentation for the command.
|
|
|
|
3) Add Functions to the Mapping
|
|
-------------------------------
|
|
|
|
The final step adds the function to the mapping. This makes it available to the command factory.
|
|
|
|
.. code-block:: python
|
|
|
|
# module_name.py
|
|
# ...
|
|
|
|
MAPPINGS = {
|
|
'mkdir': mkdir,
|
|
}
|
|
|
|
For overlays that represent an operating system, ``MAPPINGS`` is required -- in addition to ``command_exists()`` above. For commands that are specific to service or application, the name of the dictionary may be anything that is appropriate. For example, ``DJANGO_MAPPINGS``.
|
|
|
|
Additionally, for an operating system overlay, you may wish to import other mappings and incorporate them into ``MAPPINGS``.
|
|
|
|
.. code-block:: python
|
|
|
|
# module_name.py
|
|
from ..commands import Command
|
|
from .common import COMMON_MAPPINGS
|
|
from .django import DJANGO_MAPPINGS
|
|
from .pgsql import PGSQL_MAPPINGS
|
|
|
|
MAPPINGS = {
|
|
# ...
|
|
}
|
|
|
|
MAPPINGS.update(COMMON_MAPPINGS)
|
|
MAPPINGS.update(DJANGO_MAPPINGS)
|
|
MAPPINGS.update(PGSQL_MAPPINGS)
|
|
|
|
4) Update Documentation
|
|
-----------------------
|
|
|
|
Add the command mappings to the ``docs/generate_command_signatures.py`` file. See the script for more details.
|
|
|
|
Export Commands as a Script
|
|
===========================
|
|
|
|
You can export commands as a read-to-use script. For example:
|
|
|
|
.. code-block:: python
|
|
|
|
config = Config("commands.ini")
|
|
if not config.load():
|
|
print("Bummer!")
|
|
exit()
|
|
|
|
script = config.as_script()
|
|
print(script)
|
|
|
|
Post a Message to Slack
|
|
=======================
|
|
|
|
The slack function may be used to send a message to a Slack channel. This uses the Incoming Webhooks feature, which requires some additional setup.
|
|
|
|
.. note::
|
|
The following steps were accurate as of September 2020.
|
|
|
|
**1.** Log in to Slack and go to `Your Apps`_.
|
|
|
|
.. _Your Apps: https://api.slack.com/apps
|
|
|
|
**2.** Create a new Slack app.
|
|
|
|
**3.** On the next page, select Incoming Webhooks and then toggle activation.
|
|
|
|
.. image:: /_static/images/slack-1.jpg
|
|
|
|
**4.** Next click Add new Webhook to Workspace and select the channel to which the message will be posted.
|
|
|
|
.. image:: /_static/images/slack-2.jpg
|
|
|
|
.. image:: /_static/images/slack-3.jpg
|
|
|
|
**5.** Copy the URL for the new webhook to use as the ``url`` parameter for the Slack command.
|
|
|
|
.. code-block:: ini
|
|
|
|
[send a message to slack]
|
|
slack: "This is a test message."
|
|
url: the URL you created goes here
|
|
|
|
Post a Message to Twist
|
|
=======================
|
|
|
|
The twist function may be used to send a message to Twist, which requires some additional setup.
|
|
|
|
.. note::
|
|
The following steps were accurate as of September 2020.
|
|
|
|
**1.** Log in to Twist and from the profile menu go to Add Integrations. Then click on Build and "Add a new integration".
|
|
|
|
**2.** Provide the requested info.
|
|
|
|
.. image:: _static/images/twist-1.png
|
|
|
|
**3.** After submitting this info, go to Installation. Select a channel and who to notify. Then click "Install integration".
|
|
|
|
.. image:: _static/images/twist-2.png
|
|
|
|
**4.** Copy the "Post content manually" URL for use in your configuration file.
|
|
|
|
.. code-block:: ini
|
|
|
|
[post a message to twist]
|
|
twist: "This is a test message."
|
|
url: the URL you created goes here
|
|
|
|
Use Script Tease With Common Kit
|
|
================================
|
|
|
|
Since the focus of Script Tease is to convert plain text instructions into valid command line statements, it does *not* provide support for executing those statements either locally or remotely. However, The shell component of `python-commonkit`_ *does* provide support for executing commands in local POSIX environments.
|
|
|
|
.. _python-commonkit: https://docs.develmaycare.com/en/python-commonkit/stable/components/#module-commonkit.shell
|
|
|
|
Here is an example of how to use these packages together:
|
|
|
|
.. code-block:: python
|
|
|
|
from commonkit.shell import Command
|
|
from scripttease.parsers.utils import load_commands
|
|
|
|
def execute(step):
|
|
command = Command(
|
|
step.statement,
|
|
comment=step.comment,
|
|
path=step.cd,
|
|
prefix=step.prefix,
|
|
shell=step.shell
|
|
)
|
|
|
|
# Sudo is a different class, but identical in behavior.
|
|
command.sudo = step.sudo
|
|
|
|
if command.run():
|
|
print("[success] %s" % step.comment)
|
|
else:
|
|
print("[failure] %s" % step.comment)
|
|
if step.stop:
|
|
print("I can't go on: %s" % command.error)
|
|
exit(command.code)
|
|
|
|
# Load SCRIPT TEASE commands from an INI file. These are instances of either Command or ItemizedCommand found in
|
|
# scripttease.library.commands
|
|
steps = load_commands("path/to/steps.ini")
|
|
|
|
# A failure to load results in None.
|
|
if steps is None:
|
|
print("Failed to load steps.")
|
|
exit(1)
|
|
|
|
# Iterate through each step to create a COMMON KIT command.
|
|
for step in steps:
|
|
|
|
# To preview ...
|
|
# print(step.get_statement(cd=True))
|
|
|
|
if step.is_itemized:
|
|
for substep in step.get_commands():
|
|
execute(substep)
|
|
else:
|
|
execute(step)
|
|
|
|
Common Kit is already a dependency of Script Tease so it is installed by default. The ``execute()`` function is a shortcut that helps deal with itemized commands. The path (``step.cd``) is automatically handled by Common Kit's Command class.
|
|
|
|
|