diff --git a/docs/Makefile b/docs/Makefile index c235a09..a15051b 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -54,8 +54,8 @@ clean: .PHONY: html html: - resrc pkg docs -I ../packages.ini -O rst --no-heading > source/_includes/project-dependencies.rst; - ./generate_command_signatures.py > source/_includes/overlays.rst + #resrc pkg docs -I ../packages.ini -O rst --no-heading > source/_includes/project-dependencies.rst; + #./generate_command_signatures.py > source/_includes/overlays.rst $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." diff --git a/docs/generate_command_signatures.py b/docs/generate_command_signatures.py deleted file mode 100755 index 540b693..0000000 --- a/docs/generate_command_signatures.py +++ /dev/null @@ -1,139 +0,0 @@ -#! /usr/bin/env python - -# Imports - -from collections import OrderedDict -import inspect -import sys - -# Set path before importing overlays. -sys.path.append("../") - -# Import overlays -from scripttease.library.overlays.common import COMMON_MAPPINGS -from scripttease.library.overlays.centos import MAPPINGS as CENTOS_MAPPINGS -from scripttease.library.overlays.django import DJANGO_MAPPINGS -from scripttease.library.overlays.mysql import MYSQL_MAPPINGS -from scripttease.library.overlays.pgsql import PGSQL_MAPPINGS -from scripttease.library.overlays.posix import POSIX_MAPPINGS -from scripttease.library.overlays.ubuntu import MAPPINGS as UBUNTU_MAPPINGS - -# Functions - - -# https://stackoverflow.com/a/52003056/241720 -def get_signature(fn): - params = inspect.signature(fn).parameters - args = [] - kwargs = OrderedDict() - for p in params.values(): - if p.default is p.empty: - args.append(p.name) - else: - kwargs[p.name] = p.default - return args, kwargs - - -def print_description(text): - print(text) - print("") - - -def print_heading(title): - print(title) - print("=" * len(title)) - print("") - - -def print_mapping(commands, excludes=None): - keys = list(commands.keys()) - keys.sort() - - _excludes = excludes or dict() - - for key in keys: - if key in _excludes: - continue - - func = commands[key] - - docstring = func.__doc__ - if not docstring: - continue - - print(key) - print("-" * len(key)) - print("") - for i in docstring.split("\n"): - print(i.strip()) - # print("") - - print(".. code-block:: ini") - print("") - print(" [run %s command]" % key) - - args, kwargs = get_signature(func) - - line = list() - for a in args: - if a != "kwargs": - line.append(a) - - print(" %s: %s" % (key, " ".join(line))) - - for option, value in kwargs.items(): - if value is True: - _value = "yes" - elif value is False: - _value = "no" - else: - _value = value - - print(" %s: %s" % (option, value)) - - print("") - - -# Overlay output. -print(".. generated by generate_command_signatures.py") -print("") - -print_heading("Common") -print_description("Common commands are available to all overlays.") -print_mapping(COMMON_MAPPINGS) - -print_heading("Django") -print_description("Django commands are available to all overlays.") -print_mapping(DJANGO_MAPPINGS) - -print_heading("MySQL") -print_description("MySQL commands.") -print_mapping(MYSQL_MAPPINGS) - -print_heading("Postgres") -print_description("Postgres commands.") -print_mapping(PGSQL_MAPPINGS) - -print_heading("POSIX") -print_description("Posix commands form the basis of overlays for *nix platforms.") -print_mapping(POSIX_MAPPINGS, excludes=["func"]) - -exclude_from_centos = COMMON_MAPPINGS.copy() -exclude_from_centos.update(DJANGO_MAPPINGS) -exclude_from_centos.update(MYSQL_MAPPINGS) -exclude_from_centos.update(PGSQL_MAPPINGS) -exclude_from_centos.update(POSIX_MAPPINGS) -print_heading("Cent OS") -print_description("The Cent OS overlay incorporates commands specific to that platform as well as commands from " - "common, Django, MySQL, Postgres, and POSIX.") -print_mapping(CENTOS_MAPPINGS, excludes=exclude_from_centos) - -exclude_from_ubuntu = COMMON_MAPPINGS.copy() -exclude_from_ubuntu.update(DJANGO_MAPPINGS) -exclude_from_ubuntu.update(MYSQL_MAPPINGS) -exclude_from_ubuntu.update(PGSQL_MAPPINGS) -exclude_from_ubuntu.update(POSIX_MAPPINGS) -print_heading("Ubuntu") -print_description("The Ubuntu overlay incorporates commands specific to that platform as well as commands from " - "common, Django, MySQL, Postgres, and POSIX.") -print_mapping(UBUNTU_MAPPINGS, excludes=exclude_from_ubuntu) diff --git a/docs/source/_data/cloc.csv b/docs/source/_data/cloc.csv index fccd4f2..5fc8112 100644 --- a/docs/source/_data/cloc.csv +++ b/docs/source/_data/cloc.csv @@ -1,3 +1,4 @@ files,language,blank,comment,code -22,Python,1124,981,1847 -22,SUM,1124,981,1847 +23,Python,1215,1163,2070 +12,INI,54,83,174 +35,SUM,1269,1246,2244 diff --git a/docs/source/_includes/project-dependencies.rst b/docs/source/_includes/dependencies.rst similarity index 91% rename from docs/source/_includes/project-dependencies.rst rename to docs/source/_includes/dependencies.rst index 73a38eb..4289919 100644 --- a/docs/source/_includes/project-dependencies.rst +++ b/docs/source/_includes/dependencies.rst @@ -1,10 +1,6 @@ -Requirements ------------- - jinja2 ------ - **Install** .. code-block:: bash @@ -14,7 +10,6 @@ jinja2 pygments -------- - **Install** .. code-block:: bash @@ -24,7 +19,6 @@ pygments python-commonkit ---------------- - **URLs** - `Source Code `_ diff --git a/docs/source/_includes/overlays.rst b/docs/source/_includes/overlays.rst deleted file mode 100644 index bd92d29..0000000 --- a/docs/source/_includes/overlays.rst +++ /dev/null @@ -1,1294 +0,0 @@ -.. generated by generate_command_signatures.py - -Common -====== - -Common commands are available to all overlays. - -pip ---- - -Use pip to install or uninstall a Python package. - -- name (str): The name of the package. -- op (str): The operation to perform; install, uninstall -- upgrade (bool): Upgrade an installed package. -- venv (str): The name of the virtual environment to load. -- version (int): The Python version to use, e.g. ``2`` or ``3``. - - -.. code-block:: ini - - [run pip command] - pip: name - op: install - upgrade: False - venv: None - version: 3 - -run ---- - -Run any statement. - -- statement (str): The statement to be executed. - - -.. code-block:: ini - - [run run command] - run: statement - -slack ------ - -Send a message to Slack. - -- message (str): The message to be sent. -- url (str): The webhook URL. This is required. See documentation. - - -.. code-block:: ini - - [run slack command] - slack: message - url: None - -twist ------ - -Send a message to Twist. - -- message (str): The message to be sent. -- title (str): The message title. -- url (str): The webhook URL. This is required. See documentation. - - -.. code-block:: ini - - [run twist command] - twist: message - title: Notice - url: None - -udf ---- - -Create a UDF prompt for a StackScript. - -- name (str): The name of the variable. -- default: The default value. -- example: An example value, instead of a default. -- label (str): The label for the variable. - - -.. code-block:: ini - - [run udf command] - udf: name - default: None - example: None - label: None - -virtualenv ----------- - -Create a Python virtual environment. - -- name (str): The name of the environment to create. - - -.. code-block:: ini - - [run virtualenv command] - virtualenv: name - -Django -====== - -Django commands are available to all overlays. - -django ------- - -Run any Django management command. - -- name (str): The name of the management command. -- venv (str): The of the virtual environment to use. - -args are passed as positional arguments, while kwargs are given as switches. - - -.. code-block:: ini - - [run django command] - django: name args - venv: None - -django.check ------------- - -Run the Django check command. - -- venv (str): The of the virtual environment to use. - - -.. code-block:: ini - - [run django.check command] - django.check: - venv: None - -django.collect_static ---------------------- - -Collect static files. - -- venv (str): The of the virtual environment to use. - - -.. code-block:: ini - - [run django.collect_static command] - django.collect_static: - venv: None - -django.dumpdata ---------------- - -Dump data from the database. - -- app_name (str): The name (app label) of the app. ``app_label.ModelName`` may also be given. -- base_path (str): The path under which apps are located in source. -- file_name (str): The file name to which the data will be dumped. -- indent (int): Indentation of the exported fixtures. -- natural_foreign (bool): Use the natural foreign parameter. -- natural_primary (bool): Use the natural primary parameter. -- path (str): The path to the data file. -- venv (str): The of the virtual environment to use. - - -.. code-block:: ini - - [run django.dumpdata command] - django.dumpdata: app_name - base_path: local - file_name: initial - indent: 4 - natural_foreign: False - natural_primary: False - path: None - venv: None - -django.loaddata ---------------- - -Load data into the database. - -- app_name (str): The name (app label) of the app. ``app_label.ModelName`` may also be given. -- base_path (str): The path under which apps are located in source. -- file_name (str): The file name to which the data will be dumped. -- path (str): The path to the data file. -- venv (str): The of the virtual environment to use. - - -.. code-block:: ini - - [run django.loaddata command] - django.loaddata: app_name - base_path: local - file_name: initial - path: None - venv: None - -django.migrate --------------- - -Apply database migrations. - -- venv (str): The of the virtual environment to use. - - -.. code-block:: ini - - [run django.migrate command] - django.migrate: - venv: None - -MySQL -===== - -MySQL commands. - -mysql.create ------------- - -Create a MySQL database. - -- database (str): The database name. -- host (str): The database host name or IP address. -- password (str): The password for the user with sufficient access privileges to execute the command. -- owner (str): The owner (user/role name) of the new database. -- port (int): The TCP port number of the MySQL service running on the host. -- user (str): The name of the user with sufficient access privileges to execute the command. - - -.. code-block:: ini - - [run mysql.create command] - mysql.create: database - host: localhost - owner: None - password: None - port: 3306 - user: root - -mysql.drop ----------- - -Drop (remove) a MySQL database. - -- database (str): The database name. -- host (str): The database host name or IP address. -- password (str): The password for the user with sufficient access privileges to execute the command. -- port (int): The TCP port number of the MySQL service running on the host. -- user (str): The name of the user with sufficient access privileges to execute the command. - - -.. code-block:: ini - - [run mysql.drop command] - mysql.drop: database - host: localhost - password: None - port: 3306 - user: root - -mysql.dump ----------- - -Dump (export) a MySQL database. - -- database (str): The database name. -- host (str): The database host name or IP address. -- password (str): The password for the user with sufficient access privileges to execute the command. -- port (int): The TCP port number of the MySQL service running on the host. -- user (str): The name of the user with sufficient access privileges to execute the command. - - -.. code-block:: ini - - [run mysql.dump command] - mysql.dump: database - file_name: None - host: localhost - inserts: False - password: None - port: 3306 - user: root - -mysql.exists ------------- - -Determine if a MySQL database exists. - -- database (str): The database name. -- host (str): The database host name or IP address. -- password (str): The password for the user with sufficient access privileges to execute the command. -- port (int): The TCP port number of the MySQL service running on the host. -- user (str): The name of the user with sufficient access privileges to execute the command. - - -.. code-block:: ini - - [run mysql.exists command] - mysql.exists: database - host: localhost - password: None - port: 3306 - user: root - -mysql.grant ------------ - -Grant privileges to a user. - -- to (str): The user name to which privileges are granted. -- database (str): The database name. -- host (str): The database host name or IP address. -- password (str): The password for the user with sufficient access privileges to execute the command. -- port (int): The TCP port number of the MySQL service running on the host. -- privileges (str): The privileges to be granted. -- user (str): The name of the user with sufficient access privileges to execute the command. - - -.. code-block:: ini - - [run mysql.grant command] - mysql.grant: to - database: None - host: localhost - password: None - port: 3306 - privileges: ALL - user: root - -mysql.sql ---------- - -Execute a MySQL statement. - -- sql (str): The SQL to run. -- database (str): The name of the database. -- host (str): The host name. -- password (str): The password for the user with sufficient access privileges to execute the command. -- port (int): The TCP port number. -- user (str): The name of the user with sufficient access privileges to execute the command. - - -.. code-block:: ini - - [run mysql.sql command] - mysql.sql: sql - database: default - host: localhost - password: None - port: 3306 - user: root - -mysql.user ----------- - -Work with a MySQL user. - -- name (str): The user name. -- host (str): The host name. -- op (str): The operation to perform: ``create``, ``drop``, ``exists``. -- passwd (str): The password for a new user. -- password (str): The password for the user with sufficient access privileges to execute the command. -- port (int): The TCP port number. -- user (str): The name of the user with sufficient access privileges to execute the command. - - -.. code-block:: ini - - [run mysql.user command] - mysql.user: name - host: localhost - op: create - passwd: None - password: None - port: 3306 - user: root - -Postgres -======== - -Postgres commands. - -pgsql.create ------------- - -Create a PostgreSQL database. - -- database (str): The database name. -- admin_pass (str): The password for the user with sufficient access privileges to execute the command. -- admin_user (str): The name of the user with sufficient access privileges to execute the command. -- host (str): The database host name or IP address. -- owner (str): The owner (user/role name) of the new database. -- port (int): The port number of the Postgres service running on the host. -- template (str): The database template name to use, if any. - - -.. code-block:: ini - - [run pgsql.create command] - pgsql.create: database - admin_pass: None - admin_user: postgres - host: localhost - owner: None - port: 5432 - template: None - -pgsql.drop ----------- - -Remove a PostgreSQL database. - -- database (str): The database name. -- admin_pass (str): The password for the user with sufficient access privileges to execute the command. -- admin_user (str): The name of the user with sufficient access privileges to execute the command. -- host (str): The database host name or IP address. -- port (int): The port number of the Postgres service running on the host. - - -.. code-block:: ini - - [run pgsql.drop command] - pgsql.drop: database - admin_pass: None - admin_user: postgres - host: localhost - port: 5432 - -pgsql.dump ----------- - -Export a Postgres database. - -- database (str): The database name. -- admin_pass (str): The password for the user with sufficient access privileges to execute the command. -- admin_user (str): The name of the user with sufficient access privileges to execute the command. -- file_name (str): The name/path of the export file. Defaults the database name plus ``.sql``. -- host (str): The database host name or IP address. -- port (int): The port number of the Postgres service running on the host. - - -.. code-block:: ini - - [run pgsql.dump command] - pgsql.dump: database - admin_pass: None - admin_user: postgres - file_name: None - host: localhost - port: 5432 - -pgsql.exists ------------- - -Determine if a Postgres database exists. - -- database (str): The database name. -- admin_pass (str): The password for the user with sufficient access privileges to execute the command. -- admin_user (str): The name of the user with sufficient access privileges to execute the command. -- host (str): The database host name or IP address. -- owner (str): The owner (user/role name) of the new database. -- port (int): The port number of the Postgres service running on the host. - - -.. code-block:: ini - - [run pgsql.exists command] - pgsql.exists: database - admin_pass: None - admin_user: postgres - host: localhost - port: 5432 - -pgsql.sql ---------- - -Execute a psql command. - -- sql (str): The SQL to be executed. -- database (str): The database name. -- admin_pass (str): The password for the user with sufficient access privileges to execute the command. -- admin_user (str): The name of the user with sufficient access privileges to execute the command. -- host (str): The database host name or IP address. -- port (int): The port number of the Postgres service running on the host. - - -.. code-block:: ini - - [run pgsql.sql command] - pgsql.sql: sql - database: template1 - host: localhost - password: None - port: 5432 - user: postgres - -pgsql.user ----------- - -Work with a PostgreSQL user. - -- name (str): The user name. -- host (str): The host name. -- op (str): The operation to perform: ``create``, ``drop``, ``exists``. -- passwd (str): The password for a new user. -- password (str): The password for the user with sufficient access privileges to execute the command. -- port (int): The TCP port number. -- user (str): The name of the user with sufficient access privileges to execute the command. - - -.. code-block:: ini - - [run pgsql.user command] - pgsql.user: name - admin_pass: None - admin_user: postgres - host: localhost - op: create - password: None - port: 5432 - -POSIX -===== - -Posix commands form the basis of overlays for *nix platforms. - -append ------- - -Append content to a file. - -- path (str): The path to the file. -- content (str): The content to be appended. - - -.. code-block:: ini - - [run append command] - append: path - content: None - -archive -------- - -Create a file archive. - -- from_path (str): The path that should be archived. -- absolute (bool): Set to ``True`` to preserve the leading slash. -- exclude (str): A pattern to be excluded from the archive. -- strip (int): Remove the specified number of leading elements from the path. -- to_path (str): Where the archive should be created. This should *not* include the file name. -- view (bool): View the output of the command as it happens. - - -.. code-block:: ini - - [run archive command] - archive: from_path - absolute: False - exclude: None - file_name: archive.tgz - strip: None - to_path: . - view: False - -certbot -------- - -Get new SSL certificate from Let's Encrypt. - -- domain_name (str): The domain name for which the SSL certificate is requested. -- email (str): The email address of the requester sent to the certificate authority. Required. -- webroot (str): The directory where the challenge file will be created. - - -.. code-block:: ini - - [run certbot command] - certbot: domain_name - email: None - webroot: None - -copy ----- - -Copy a file or directory. - -- from_path (str): The file or directory to be copied. -- to_path (str): The location to which the file or directory should be copied. -- overwrite (bool): Indicates files and directories should be overwritten if they exist. -- recursive (bool): Copy sub-directories. - - -.. code-block:: ini - - [run copy command] - copy: from_path to_path - overwrite: False - recursive: False - -dialog ------- - -Display a dialog message. - -- message (str): The message to be displayed. -- height (int): The height of the dialog. -- title (str): The title of the dialog. -- width (int): The width of the dialog. - - -.. code-block:: ini - - [run dialog command] - dialog: message - height: 15 - title: Message - width: 100 - -echo ----- - -Echo a message. - -- message (str): The message to be printed to screen. - - -.. code-block:: ini - - [run echo command] - echo: message - -extract -------- - -Extract a file archive. - -- from_path (str): The path that should be archived. -- absolute (bool): Set to ``True`` to preserve the leading slash. -- exclude (str): A pattern to be excluded from the archive. -- strip (int): Remove the specified number of leading elements from the path. -- to_path (str): Where the archive should be extracted. This should *not* include the file name. -- view (bool): View the output of the command as it happens. - - -.. code-block:: ini - - [run extract command] - extract: from_path - absolute: False - exclude: None - strip: None - to_path: None - view: False - -mkdir ------ - -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. - - -.. code-block:: ini - - [run mkdir command] - mkdir: path - mode: None - recursive: True - -move ----- - -Move a file or directory. - -- from_path (str): The current path. -- to_path (str): The new path. - - -.. code-block:: ini - - [run move command] - move: from_path to_path - -perms ------ - -Set permissions on a file or directory. - -- path (str): The path to be changed. -- group (str): The name of the group to be applied. -- mode (int | str): The access permissions of the file or directory. -- owner (str): The name of the user to be applied. -- recursive: Create all directories along the path. - - -.. code-block:: ini - - [run perms command] - perms: path - group: None - mode: None - owner: None - recursive: False - -prompt ------- - -Prompt the user for input. - -- name (str): The programmatic name of the input. -- back_title (str): The back title used with the dialog command. -- choices (str | list): A list of valid choices. -- default: The default value. -- fancy (bool): Use a dialog command for the prompt. -- help_text (str): The text to display with the dialog command. -- label (str): The label for the input. - - -.. code-block:: ini - - [run prompt command] - prompt: name - back_title: Input - choices: None - default: None - fancy: False - help_text: None - label: None - -push ----- - -Synchronize a directory structure. - -- source (str): The source directory. -- target (str): The target directory. -- delete (bool): Indicates target files that exist in source but not in target should be removed. -- exclude (str): The path to an exclude file. -- host (str): The host name or IP address. This causes the command to run over SSH. -- key_file (str): The privacy SSH key (path) for remote connections. User expansion is automatically applied. -- links (bool): Include symlinks in the sync. -- port (int): The SSH port to use for remote connections. -- recursive (bool): Indicates source contents should be recursively synchronized. -- user (str): The user name to use for remote connections. - - -.. code-block:: ini - - [run push command] - push: source target - delete: False - exclude: None - host: None - key_file: None - links: True - port: 22 - recursive: True - user: None - -remove ------- - -Remove a file or directory. - -- path (str): The path to be removed. -- force (bool): Force the removal. -- recursive (bool): Remove all directories along the path. - - -.. code-block:: ini - - [run remove command] - remove: path - force: False - recursive: False - -rename ------- - -Rename a file or directory. - -- from_name (str): The name (or path) of the existing file. -- to_name (str): The name (or path) of the new file. - - -.. code-block:: ini - - [run rename command] - rename: from_name to_name - -rsync ------ - -Synchronize a directory structure. - -- source (str): The source directory. -- target (str): The target directory. -- delete (bool): Indicates target files that exist in source but not in target should be removed. -- exclude (str): The path to an exclude file. -- host (str): The host name or IP address. This causes the command to run over SSH. -- key_file (str): The privacy SSH key (path) for remote connections. User expansion is automatically applied. -- links (bool): Include symlinks in the sync. -- port (int): The SSH port to use for remote connections. -- recursive (bool): Indicates source contents should be recursively synchronized. -- user (str): The user name to use for remote connections. - - -.. code-block:: ini - - [run rsync command] - rsync: source target - delete: False - exclude: None - host: None - key_file: None - links: True - port: 22 - recursive: True - user: None - -scopy ------ - -Copy a file or directory to a remote server. - -- from_path (str): The source directory. -- to_path (str): The target directory. -- host (str): The host name or IP address. Required. -- key_file (str): The privacy SSH key (path) for remote connections. User expansion is automatically applied. -- port (int): The SSH port to use for remote connections. -- user (str): The user name to use for remote connections. - - -.. code-block:: ini - - [run scopy command] - scopy: from_path to_path - host: None - key_file: None - port: 22 - user: None - -sed ---- - -Find and replace text in a file. - -- path (str): The path to the file to be edited. -- backup (str): The backup file extension to use. -- delimiter (str): The pattern delimiter. -- find (str): The old text. Required. -- replace (str): The new text. Required. - - -.. code-block:: ini - - [run sed command] - sed: path - backup: .b - delimiter: / - find: None - replace: None - -ssl ---- - -Get new SSL certificate from Let's Encrypt. - -- domain_name (str): The domain name for which the SSL certificate is requested. -- email (str): The email address of the requester sent to the certificate authority. Required. -- webroot (str): The directory where the challenge file will be created. - - -.. code-block:: ini - - [run ssl command] - ssl: domain_name - email: None - webroot: None - -symlink -------- - -Create a symlink. - -- source (str): The source of the link. -- force (bool): Force the creation of the link. -- target (str): The name or path of the target. Defaults to the base name of the source path. - - -.. code-block:: ini - - [run symlink command] - symlink: source - force: False - target: None - -touch ------ - -Touch a file or directory. - -- path (str): The file or directory to touch. - - -.. code-block:: ini - - [run touch command] - touch: path - -wait ----- - -Pause execution for a number of seconds. - -- seconds (int): The number of seconds to wait. - - -.. code-block:: ini - - [run wait command] - wait: seconds - -write ------ - -Write to a file. - -- path (str): The file to be written. -- content (str): The content to be written. Note: If omitted, this command is equivalent to ``touch``. - - -.. code-block:: ini - - [run write command] - write: path - content: None - -Cent OS -======= - -The Cent OS overlay incorporates commands specific to that platform as well as commands from common, Django, MySQL, Postgres, and POSIX. - -apache ------- - -Execute an Apache-related command. - -- op (str): The operation to perform; reload, restart, start, stop, test. - - -.. code-block:: ini - - [run apache command] - apache: op - -install -------- - -Install a system-level package. - -- name (str): The name of the package to install. - - -.. code-block:: ini - - [run install command] - install: name - -reload ------- - -Reload a service. - -- name (str): The service name. - - -.. code-block:: ini - - [run reload command] - reload: name - -restart -------- - -Restart a service. - -- name (str): The service name. - - -.. code-block:: ini - - [run restart command] - restart: name - -start ------ - -Start a service. - -- name (str): The service name. - - -.. code-block:: ini - - [run start command] - start: name - -stop ----- - -Stop a service. - -- name (str): The service name. - - -.. code-block:: ini - - [run stop command] - stop: name - -system ------- - -Perform a system operation. - -- op (str): The operation to perform; reboot, update, upgrade. - - -.. code-block:: ini - - [run system command] - system: op - -template --------- - -Create a file from a template. - -- source (str): The path to the template file. -- target (str): The path to where the new file should be created. -- backup (bool): Indicates whether a backup should be made if the target file already exists. -- parser (str): The parser to use ``jinja`` (the default) or ``simple``. - - -.. code-block:: ini - - [run template command] - template: source target - backup: True - parser: None - -uninstall ---------- - -Uninstall a system-level package. - -- name (str): The name of the package to uninstall. - - -.. code-block:: ini - - [run uninstall command] - uninstall: name - -user ----- - -Create or remove a user. - -- name (str): The user name. -- groups (str | list): A list of groups to which the user should belong. -- home (str): The path to the user's home directory. -- op (str); The operation to perform; ``add`` or ``remove``. -- password (str): The user's password. (NOT IMPLEMENTED) - - -.. code-block:: ini - - [run user command] - user: name - groups: None - home: None - op: add - password: None - -Ubuntu -====== - -The Ubuntu overlay incorporates commands specific to that platform as well as commands from common, Django, MySQL, Postgres, and POSIX. - -apache ------- - -Execute an Apache-related command. - -- op (str): The operation to perform; reload, restart, start, stop, test. - - -.. code-block:: ini - - [run apache command] - apache: op - -apache.disable_module ---------------------- - -Disable an Apache module. - -- name (str): The module name. - - -.. code-block:: ini - - [run apache.disable_module command] - apache.disable_module: name - -apache.disable_site -------------------- - -Disable an Apache site. - -- name (str): The domain name. - - -.. code-block:: ini - - [run apache.disable_site command] - apache.disable_site: name - -apache.enable_module --------------------- - -Enable an Apache module. - -- name (str): The module name. - - -.. code-block:: ini - - [run apache.enable_module command] - apache.enable_module: name - -apache.enable_site ------------------- - -Enable an Apache site. - - - -.. code-block:: ini - - [run apache.enable_site command] - apache.enable_site: name - -install -------- - -Install a system-level package. - -- name (str): The name of the package to install. - - -.. code-block:: ini - - [run install command] - install: name - -reload ------- - -Reload a service. - -- name (str): The service name. - - -.. code-block:: ini - - [run reload command] - reload: name - -restart -------- - -Restart a service. - -- name (str): The service name. - - -.. code-block:: ini - - [run restart command] - restart: name - -start ------ - -Start a service. - -- name (str): The service name. - - -.. code-block:: ini - - [run start command] - start: name - -stop ----- - -Stop a service. - -- name (str): The service name. - - -.. code-block:: ini - - [run stop command] - stop: name - -system ------- - -Perform a system operation. - -- op (str): The operation to perform; reboot, update, upgrade. - - -.. code-block:: ini - - [run system command] - system: op - -template --------- - -Create a file from a template. - -- source (str): The path to the template file. -- target (str): The path to where the new file should be created. -- backup (bool): Indicates whether a backup should be made if the target file already exists. -- parser (str): The parser to use ``jinja`` (the default) or ``simple``. - - -.. code-block:: ini - - [run template command] - template: source target - backup: True - parser: None - -uninstall ---------- - -Uninstall a system-level package. - -- name (str): The name of the package to uninstall. - - -.. code-block:: ini - - [run uninstall command] - uninstall: name - -user ----- - -Create or remove a user. - -- name (str): The user name. -- groups (str | list): A list of groups to which the user should belong. -- home (str): The path to the user's home directory. -- op (str); The operation to perform; ``add`` or ``remove``. -- password (str): The user's password. (NOT IMPLEMENTED) - - -.. code-block:: ini - - [run user command] - user: name - groups: None - home: None - op: add - password: None - diff --git a/docs/source/_includes/project-tests.rst b/docs/source/_includes/tests.rst similarity index 75% rename from docs/source/_includes/project-tests.rst rename to docs/source/_includes/tests.rst index 30707f7..8616f12 100644 --- a/docs/source/_includes/project-tests.rst +++ b/docs/source/_includes/tests.rst @@ -1,7 +1,7 @@ Coverage Requirements ---------------------- +..................... -100% coverage is required for the ``master`` branch. +We always strive for 100% coverage in the ``master`` branch. The CLI is currently ignored. See `current coverage report `_. @@ -9,7 +9,7 @@ See `current coverage report `_. :file: ../_data/cloc.csv Set Up for Testing ------------------- +.................. Install requirements: @@ -35,16 +35,16 @@ Run a specific test: .. code-block:: bash - python -m pytest tests/units/path/to/test.py + python -m pytest tests/path/to/test.py To allow output from print statements within a test method, add the ``-s`` switch: .. code-block:: bash - python -m pytest -s tests/units/path/to/test.py + python -m pytest -s tests/path/to/test.py Reference ---------- +......... - `coverage `_ - `pytest `_ diff --git a/docs/source/_static/images/architecture-diagram.png b/docs/source/_static/images/architecture-diagram.png new file mode 100644 index 0000000..c7d7b43 Binary files /dev/null and b/docs/source/_static/images/architecture-diagram.png differ diff --git a/docs/source/_static/images/slack-1.jpg b/docs/source/_static/images/slack-1.jpg deleted file mode 100644 index 192b2a3..0000000 Binary files a/docs/source/_static/images/slack-1.jpg and /dev/null differ diff --git a/docs/source/_static/images/slack-2.jpg b/docs/source/_static/images/slack-2.jpg deleted file mode 100644 index 69c7db6..0000000 Binary files a/docs/source/_static/images/slack-2.jpg and /dev/null differ diff --git a/docs/source/_static/images/slack-3.jpg b/docs/source/_static/images/slack-3.jpg deleted file mode 100644 index a6778a8..0000000 Binary files a/docs/source/_static/images/slack-3.jpg and /dev/null differ diff --git a/docs/source/_static/images/twist-1.png b/docs/source/_static/images/twist-1.png deleted file mode 100644 index a2806e4..0000000 Binary files a/docs/source/_static/images/twist-1.png and /dev/null differ diff --git a/docs/source/_static/images/twist-2.png b/docs/source/_static/images/twist-2.png deleted file mode 100644 index deb31ef..0000000 Binary files a/docs/source/_static/images/twist-2.png and /dev/null differ diff --git a/docs/source/commands.rst b/docs/source/commands.rst deleted file mode 100644 index 2dcbc60..0000000 --- a/docs/source/commands.rst +++ /dev/null @@ -1,86 +0,0 @@ -.. _commands: - -******** -Commands -******** - -.. code-block:: text - - usage: tease [-h] [-c] [-C= VARIABLES] [-d] [-D] [-f= FILTERS] [-O= OPTIONS] [-s] [-T= TEMPLATE_LOCATIONS] [-w= OUTPUT_FILE] [-V= VARIABLES_FILE] - [-v] [--version] - [path] - - positional arguments: - path The path to the configuration file. - - optional arguments: - -h, --help show this help message and exit - -c, --color Enable code highlighting for terminal output. - -C= VARIABLES, --context= VARIABLES - Context variables for use in pre-parsing the config and templates. In the form of: name:value - -d, --docs Output documentation instead of code. - -D, --debug Enable debug output. - -f= FILTERS, --filter= FILTERS - Filter the commands in the form of: attribute:value - -O= OPTIONS, --option= OPTIONS - Common command options in the form of: name:value - -s, --script Output commands as a script. - -T= TEMPLATE_LOCATIONS, --template-path= TEMPLATE_LOCATIONS - The location of template files that may be used with the template command. - -w= OUTPUT_FILE, --write= OUTPUT_FILE - Write the output to disk. - -V= VARIABLES_FILE, --variables-file= VARIABLES_FILE - Load variables from a file. - -v Show version number and exit. - --version Show verbose version information and exit. - - NOTES - - This command is used to parse configuration files and output the commands. - -Using the Tease Command -======================= - -The ``tease`` command may be used to parse a configuration file, providing additional utilities for working with commands. - -The ``path`` argument defaults to ``commands.ini``. - -Context Variables May be Provided on the Command Line ------------------------------------------------------ - -To supply context variables on the command line: - -.. code-block:: bash - - tease -C domain_name:example.com -C domain_tld:example_com - -Loading Context Variables from a File -------------------------------------- - -Context variables may be loaded from a file: - -.. code-block:: ini - - [domain] - name = example.com - tld = example_com - -The variables above are available as ``section_key``. For example, ``domain_name`` is ``example.com``. - -.. code-block:: bash - - tease -V variables.ini - -Setting Common Options for All Commands ---------------------------------------- - -Rather than include a common parameter in the configuration file, it is possible to specify a common option on the command line. - -.. code-block:: bash - - tease -O sudo:yes - -The Difference Between Variables and Options --------------------------------------------- - -Variables are used to pre-process configuration files as templates, while common options are passed to *all* command instances. diff --git a/docs/source/contact.rst b/docs/source/contact.rst index c6f0e25..9ced6bd 100644 --- a/docs/source/contact.rst +++ b/docs/source/contact.rst @@ -10,14 +10,14 @@ General Contact Please use the `contact form at develmaycare.com`_ to inquire about training, commercial development or support, to report security issues, and other questions or communications. -.. _contact form at develmaycare.com: https://develmaycare.com/contact/?product=ScriptTease +.. _contact form at develmaycare.com: https://develmaycare.com/contact/?product=python-scripttease Issue Tracker ============= Bugs and feature requests are logged with the `issue tracker`_. Do *not* log security issues here. -.. _issue tracker: https://github.com/develmaycare/python-scripttease/issues +.. _issue tracker: https://gittraction.com/diff6/python-scripttease/issues Support ======= diff --git a/docs/source/contributing.rst b/docs/source/contributing.rst new file mode 100644 index 0000000..7528106 --- /dev/null +++ b/docs/source/contributing.rst @@ -0,0 +1,77 @@ +************ +Contributing +************ + +We welcome contributions to this and any of `our open source projects`_. There are a number of ways to participate and contribute. See :ref:`contact`. + +.. _our open source projects: https://docs.diff6.com + +Issue Management +================ + +Reporting Issues +---------------- + +If you have found a bug or error in the documentation, please submit a request. See :ref:`contact`. + +.. important:: + Do **not** report security issues using the issue tracker. Instead, send an email to security@develmaycare.com with details on the issue you've discovered. + +Submitting Feature Requests +--------------------------- + +Although we reserve the right to decline new features, we welcome all feature requests. See :ref:`contact`. + +Testing and Quality Control +--------------------------- + +Testing involves using Script Tease in real life or in development. Feel free to report any issues you find, or to improve the unit tests. + +Pull Requests +------------- + +Pull requests are welcome. Such requests should be associated with an issue. We may ignore pull requests that do not have a corresponding issue, so create an issue if one does not already exist. + +Promotion +========= + +You may help spread awareness of Script Tease by writing blog posts. We are happy to link out to reviews and tutorials from our web site. `Let us know if you've created a blog post`_ that we can share. Be sure to include a link to the post. + +You may also provide us with a guest post to be included on our blog. + +.. _Let us know if you've created a blog post: https://develmaycare.com/contact/?product=Script%20Tease + +.. note:: + We reserve the right to proof and approve or decline all content posted on our web site. + +Development +=========== + +Setting Up For Development +-------------------------- + +1. Clone the repo at https://github.com/develmaycare/python-scripttease +2. Create a virtual environment and install the requirements from ``requirements.pip`` + +Style Guide +----------- + +Script Tease follows `PEP8`_ and (where appropriate) the `Django style guide`_ and `JavaScript Standard Style`_. + +.. _Django style guide: https://docs.djangoproject.com/en/stable/internals/contributing/writing-code/coding-style/ +.. _JavaScript Standard Style: https://standardjs.com +.. _PEP8: https://www.python.org/dev/peps/pep-0008/ + +We *do* make a few exceptions and provide additional guidance which is documented in our `developer docs`_. + +.. _developer docs: https://docs.develmaycare.com/en/developer/ + +Dependencies +------------ + +.. include:: _includes/dependencies.rst + +Testing +------- + +.. include:: _includes/tests.rst diff --git a/docs/source/getting-started.rst b/docs/source/getting-started.rst deleted file mode 100644 index c0b48af..0000000 --- a/docs/source/getting-started.rst +++ /dev/null @@ -1,32 +0,0 @@ -.. _getting-started: - -*************** -Getting Started -*************** - -System Requirements -=================== - -Python 3.6 or greater is required. - -Install -======= - -To install: - -.. code-block:: bash - - pip install python-scripttease; - -Configuration -============= - -See :ref:`topics-configuration` for creating a command configuration file. - -FAQs -==== - -Have a question? `Just ask`_! - -.. _Just ask: https://develmaycare.com/contact/?product=Script%20Tease - diff --git a/docs/source/how-to.rst b/docs/source/how-to.rst deleted file mode 100644 index 1e11500..0000000 --- a/docs/source/how-to.rst +++ /dev/null @@ -1,236 +0,0 @@ -.. _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. - diff --git a/docs/source/index.rst b/docs/source/index.rst index 46ea8ef..6b085b7 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,22 +1,20 @@ -Script Tease -============ +Script Tease Developer Documentation +==================================== -.. raw:: html +Resources for turning plain text instructions (INI, YAML) into Bash scripting statements. -

- Project Home Page -

+.. note:: + This documentation is for developers interested in working with the Script Tease library to create a custom implementation, or to contribute to the product. For usage information, please refer to the `user help page`_. + +.. _user help page: https://docs.diff6.com/en/python-scripttease .. toctree:: :maxdepth: 2 Introduction - Getting Started - How To - Commands - Topics - Reference - Project + Code Reference + Releases + Contributing Contact Indices and tables diff --git a/docs/source/introduction.rst b/docs/source/introduction.rst index 9af58ff..9f028cf 100644 --- a/docs/source/introduction.rst +++ b/docs/source/introduction.rst @@ -7,30 +7,96 @@ Introduction Overview ======== -Script Tease is a library and command line tool for generating commands programmatically or (especially) using configuration files. +The Script Tease package takes plain text instructions in INI or YAML (currently untested) format and converts them into valid command line statements for a given platform (currently CentOS and Ubuntu are supported). It does *not* provide support for executing these statements. -The primary focus (and limit) is to convert plain text instructions into valid command line statements for a given platform (see `Overlays`_). It does *not* provide support for executing those statements. +Architecture +============ + +The provided command line interface (the ``tease`` command) loads configuration files containing instructions and may output these as a Bash script or as documentation. + +However, it is possible to create your own implementation to provide input and gather output from the Script Tease library. + +.. image:: _static/images/architecture-diagram.png Concepts ======== -Generating Commands -------------------- +Loaders +------- + +A Loader instance is responsible for reading configuration files and parsing the contents into a) a command name, b) arguments, c) keyword arguments. + +Command instances are *not* created by the loader. This is the job of the :py:func:`scriptease.lib.factories.command_factory`. + +Separating Command generation from loading configuration files makes the loader classes simpler, and keeps the overall system more flexible. + +Command Functions +----------------- -Script Tease may be used in two (2) ways: +Commands are represented by Python functions. All functions return either a :py:class:`scripttease.lib.commands.base.Command` instance, or in some cases an instance of :py:class:`scripttease.lib.commands.base.MultipleCommands`. (The Template command may also be returned; it is handled specially.) -1. Using the library to programmatically define commands and export them as command line statements. See :ref:`developer-reference`. -2. Using the ``tease`` command to generate commands from a configuration file. See :ref:`topics-configuration`. +.. code-block:: python -Overlays + def copy(from_path, to_path, overwrite=False, recursive=False, **kwargs): + # ... + +You could of course use this function directly: + +.. code-block:: python + + command = copy("/etc", "/tmp/", recursive=True) + print(command.get_statement()) + +But the point of Script Tease is to take plain text instructions and turn them into command line statements. + +Mappings -------- -An *overlay* is a set of command meta functions that define the capabilities of a specific operating system. +So the `copy` function is mapped to a name that may be used in a configuration file: + +.. code-block:: python + + MAPPINGS = { + # ... + 'copy': copy, + # ... + } -.. note:: - At present, the only fully defined operating system overlays are for Cent OS and Ubuntu. +Such mappings are used by the :py:func:`scriptease.lib.factories.command_factory` to match a command name in a configuration file to the Python function that instantiates the Command. -See :ref:`topics-overlays`. +Configuration File +------------------ + +The configuration that invokes this command would like like: + +.. code-block:: ini + + [create a copy of the etc directory] + copy: /etc /tmp/ + recursive: yes + +Note that the configuration is self-documenting, and in fact, it is possible to output commands as documentation rather than a script. + +Variables File +-------------- + +Prior to a Loader processing commands, configuration files may be parsed as Jinja2 templates. This allows variables to be loaded from a file and passed to the loader as a Context instance. + +.. code-block:: ini + + # variables.ini + [db_name] + comment: The name of the database is the same as the domain name. + value: example_app + +In the configuration file: + +.. code-block:: ini + + [create the database] + pgsql.create: {{ db_name }} + +Variables are collected in a :py:class:`scripttease.lib.contexts.Context` instance and are passed to the Loader. Terms and Definitions ===================== @@ -38,10 +104,43 @@ Terms and Definitions command When used in Script Tease documentation, this is a command instance which contains the properties and parameters for a command line statement. +profile + A profile represents the commands available to a specific operating system. + statement - A specific statement (string) to be executed. A *statement* is contained within a *command*. + A specific statement (string) to be executed. A *statement* is generated by a *command*. License ======= Script Tease is released under the BSD 3 clause license. + +.. code-block:: text + + Copyright (c) Pleasant Tents, LLC + + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of Pleasant Tents, LLC nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/docs/source/project.rst b/docs/source/project.rst deleted file mode 100644 index 5ee60e5..0000000 --- a/docs/source/project.rst +++ /dev/null @@ -1,140 +0,0 @@ -******* -Project -******* - -Contributing -============ - -We welcome contributions to this and any of `our open source projects`_. There are a number of ways to participate and contribute. See :ref:`contact`. - -.. _our open source projects: https://develmaycare.com/products/ - -Reporting Issues ----------------- - -Perhaps the easiest way to contribute is to submit an issue. If you have found a bug or error in the documentation, please submit a request. See :ref:`contact`. - -.. important:: - Do **not** report security issues using the issue tracker. Instead, send an email to security@develmaycare.com with details on the issue you've discovered. - -Submitting Feature Requests ---------------------------- - -Although we reserve the right to decline new features, we welcome all feature requests. See :ref:`contact`. - -Testing and Quality Control ---------------------------- - -Testing involves using Script Tease in real life or in development. Feel free to report any issues you find, or to improve the unit tests. - -Pull Requests -------------- - -Pull requests are welcome. Such requests should be associated with an issue. We may ignore pull requests that do not have a corresponding issue, so create an issue if one does not already exist. - -Blogging --------- - -You may help spread awareness of Script Tease by writing blog posts. We are happy to link out to reviews and tutorials from our web site. `Let us know if you've created a blog post`_ that we can share. Be sure to include a link to the post. - -You may also provide us with a guest post to be included on our blog. - -.. _Let us know if you've created a blog post: https://develmaycare.com/contact/?product=Script%20Tease - -.. note:: - We reserve the right to proof and approve or decline all content posted on our web site. - -Development -=========== - -Setting Up For Development --------------------------- - -1. Clone the repo at https://github.com/develmaycare/python-scripttease -2. Create a virtual environment and install the requirements from ``requirements.pip`` -3. See :ref:`how-to`. - -Style Guide ------------ - -Script Tease follows `PEP8`_ and (where appropriate) the `Django style guide`_ and `JavaScript Standard Style`_. - -.. _Django style guide: https://docs.djangoproject.com/en/stable/internals/contributing/writing-code/coding-style/ -.. _JavaScript Standard Style: https://standardjs.com -.. _PEP8: https://www.python.org/dev/peps/pep-0008/ - -We *do* make a few exceptions and provide additional guidance which is documented in our `developer docs`_. - -.. _developer docs: https://docs.develmaycare.com/en/developer/ - -Dependencies -============ - -.. include:: _includes/project-dependencies.rst - -Tests -===== - -.. include:: _includes/project-tests.rst - -Releasing -========= - -Versioning ----------- - -Script Tease follows a loose form of `semantic versioning`_. The use of semantic versioning makes it clear when deprecation occurs and backward compatibility is removed. Documented incompatibilities may still exist where deprecation is not feasible (technically or financially). - -.. _semantic versioning: https://semver.org/ - -Cadence -------- - -New features (and especially new overlays) are planned for release every 3 months. Patch-level changes (to fix bugs or security issues) are always released as needed. - -Long-Term Support ------------------ - -Some releases may be designated as long-term support (LTS) releases. Such releases will have security and critical bug fixes applied for 6 months. - -Deprecation Policy ------------------- - -Minor releases may deprecate features from a previous minor release. For example, if a feature is deprecated in release 1.1, it will continue to work in the 1.2 release, though warnings may be raised. However, the deprecated feature may be removed in release 1.3 and may not function as previously expected or will raise errors. - -Major releases may *always* remove deprecated features. - -Patch-level releases *never* remove deprecated features. - -Legal -===== - -.. code-block:: text - - Copyright (c) Pleasant Tents, LLC - - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of Pleasant Tents, LLC nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/docs/source/reference.rst b/docs/source/reference.rst index 120741b..2c6eca9 100644 --- a/docs/source/reference.rst +++ b/docs/source/reference.rst @@ -1,8 +1,8 @@ -.. _developer-reference: +.. _code-reference: -******************* -Developer Reference -******************* +************** +Code Reference +************** Constants ========= @@ -12,11 +12,19 @@ Constants :show-inheritance: :special-members: __init__ -Library -======= +Exceptions +========== + +.. automodule:: scripttease.exceptions + :members: + :show-inheritance: + :special-members: __init__ Commands --------- +======== + +Base +---- .. automodule:: scripttease.lib.commands.base :members: @@ -24,7 +32,7 @@ Commands :special-members: __init__ Centos -...... +------ .. automodule:: scripttease.lib.commands.centos :members: @@ -32,7 +40,7 @@ Centos :special-members: __init__ Django -...... +------ .. automodule:: scripttease.lib.commands.django :members: @@ -40,7 +48,7 @@ Django :special-members: __init__ Messages -........ +-------- .. automodule:: scripttease.lib.commands.messages :members: @@ -48,7 +56,7 @@ Messages :special-members: __init__ MySQL -...... +----- .. automodule:: scripttease.lib.commands.mysql :members: @@ -56,7 +64,7 @@ MySQL :special-members: __init__ PHP -... +--- .. automodule:: scripttease.lib.commands.php :members: @@ -64,7 +72,7 @@ PHP :special-members: __init__ Postgres -........ +-------- .. automodule:: scripttease.lib.commands.pgsql :members: @@ -72,7 +80,7 @@ Postgres :special-members: __init__ Posix -..... +----- .. automodule:: scripttease.lib.commands.posix :members: @@ -80,7 +88,7 @@ Posix :special-members: __init__ Python -...... +------ .. automodule:: scripttease.lib.commands.python :members: @@ -88,7 +96,7 @@ Python :special-members: __init__ Ubuntu -...... +------ .. automodule:: scripttease.lib.commands.ubuntu :members: @@ -98,7 +106,7 @@ Ubuntu Contexts ======== -.. automodule:: scripttease.contexts +.. automodule:: scripttease.lib.contexts :members: :show-inheritance: :special-members: __init__ @@ -106,7 +114,7 @@ Contexts Factories ========= -.. automodule:: scripttease.factories +.. automodule:: scripttease.lib.factories :members: :show-inheritance: :special-members: __init__ @@ -122,10 +130,18 @@ Base :show-inheritance: :special-members: __init__ -Config (INI) ------------- +INI +--- .. automodule:: scripttease.lib.loaders.ini :members: :show-inheritance: :special-members: __init__ + +YAML +---- + +.. automodule:: scripttease.lib.loaders.yaml + :members: + :show-inheritance: + :special-members: __init__ diff --git a/docs/source/releases.rst b/docs/source/releases.rst new file mode 100644 index 0000000..927da05 --- /dev/null +++ b/docs/source/releases.rst @@ -0,0 +1,29 @@ +******** +Releases +******** + +Versioning +========== + +Script Tease follows a loose form of `semantic versioning`_. The use of semantic versioning makes it clear when deprecation occurs and backward compatibility is removed. Documented incompatibilities may still exist where deprecation is not feasible (technically or financially). + +.. _semantic versioning: https://semver.org/ + +Cadence +======= + +New features (and especially new overlays) are planned for release every 3 months. Patch-level changes (to fix bugs or security issues) are always released as needed. + +Long-Term Support +================= + +Some releases may be designated as long-term support (LTS) releases. Such releases will have security and critical bug fixes applied for 6 months. + +Deprecation Policy +================== + +Minor releases may deprecate features from a previous minor release. For example, if a feature is deprecated in release 1.1, it will continue to work in the 1.2 release, though warnings may be raised. However, the deprecated feature may be removed in release 1.3 and may not function as previously expected or will raise errors. + +Major releases may *always* remove deprecated features. + +Patch-level releases *never* remove deprecated features. diff --git a/docs/source/topics-configuration.rst b/docs/source/topics-configuration.rst deleted file mode 100644 index 3c2369f..0000000 --- a/docs/source/topics-configuration.rst +++ /dev/null @@ -1,115 +0,0 @@ -.. _topics-configuration: - -************* -Configuration -************* - -Generating Commands From a File -=============================== - -The :py:class:`scripttease.parsers.ini.Config` class may instantiate commands by loading a configuration file. - -.. note:: - Additional formats such as JSON or YAML may be supported in the future. - -An example file: - -.. code-block:: ini - - [install apache] - install: apache2 - - [create the web site directory] - mkdir: /var/www/domains/example_com/www - recursive: yes - - [set permissions on the website directory] - perms: /var/www/domains/example_com/www - group: www-data - mode: 775 - owner: www-data - -Notes regarding this format: - -- This is the standard format for Python's ConfigParser. If you prefer, you may use ``=`` instead of ``:``. -- The first part of each command is the INI section and is used as the default comment. -- The command name *must* be the *first* option in the section. -- The arguments for the command appear as the value of the first option in the section. Arguments are separated by a - space. -- Arguments that should be treated as a single value should be enclosed in double quotes. -- ``yes`` and ``no`` are interpreted as boolean values. -- List values, where required, are separated by commas. - -.. _topics-configuration-common-parameters: - -Common Parameters ------------------ - -All commands support the following common parameters: - -- ``comment``: A comment regarding the command. -- ``condition``: A condition for execution. For example, ``! -f /path/to/some/file.txt`` -- ``cd``: The path from which a command should be executed. -- ``environments``: A string or list of comma-separated strings indicating the operational environments in which the command runs. This is *not* used by default, but may be used to programmatically filter commands for a specific environment. For example, development versus live. -- ``prefix``: A statement to be added prior to executing the command. -- ``register``: A variable name to which the the success or failure (exit code) of the statement is captured. -- ``shell``: The shell used to run the commands. For example, ``/bin/bash``. This is generally not important, but can be a problem when attempting to execute some commands (such as Django management commands). -- ``stop``: ``True`` indicates no other commands should be executed if the given command fails. -- ``sudo``: ``True`` indicates the command should be automatically prefixed with ``sudo``. If provided as a string, the command is also prefixed with a specific user name. -- ``tags``: A list of tags used to classify the command. - -Defining an "Itemized" Command ------------------------------- - -Certain command definitions may be repeated by defining a list of items. - -Example of an "itemized" command: - -.. code-block:: ini - - [create multiple directories] - mkdir: /var/www/domains/example_com/$item - items: www, www/assets, www/content - recursive: yes - - [touch a bunch of files] - touch: /var/www/domains/example_com/www/$item - items: index.html, assets/index.html, content/index.html - -.. note:: - Command itemization may vary with the command type. - -Pre-Parsing Command Files as Templates -====================================== - -Configuration file may be pre-processed as a Jinja2 template by providing a context dictionary: - -.. code-block:: ini - - [install apache] - install: apache - - [create the website directory] - mkdir: /var/www/domains/{{ domain_tld }}/www - recursive: yes - - [set permissions on the website directory] - perms: /var/www/domains/{{ domain_tld }}/www - group: www-data - mode: 775 - owner: www-data - -Then with a config instance: - -.. code-block:: python - - context = { - 'domain_tld': "example_com", - } - - config = Config("commands.ini", context=context) - config.load() - - for command in config.get_commands(): - print(command.get_statement(cd=True)) - print("") diff --git a/docs/source/topics-overlays.rst b/docs/source/topics-overlays.rst deleted file mode 100644 index 3eb02d2..0000000 --- a/docs/source/topics-overlays.rst +++ /dev/null @@ -1,24 +0,0 @@ -.. _topics-overlays: - -******** -Overlays -******** - -An overlay is a collection of functions that provide an interface to command creation. An overlay allows configuration files to specify commands in a generic way. When the file is loaded, an overlay may be specified which Script Tease uses to generate commands that are specific to a given operating system. - -There are currently four (5) general and re-usable overlays: - -- common -- django -- mysql -- pgsql -- posix - -And two (2) overlays that are specific to operating systems: - -- centos -- ubuntu - -The examples that follow instantiate command instances from an INI file. Each example is shown with the defaults. All commands support a number of :ref:`topics-configuration-common-parameters`. - -.. include:: _includes/overlays.rst diff --git a/docs/source/topics.rst b/docs/source/topics.rst deleted file mode 100644 index bd86579..0000000 --- a/docs/source/topics.rst +++ /dev/null @@ -1,11 +0,0 @@ -.. _topics: - -****** -Topics -****** - -.. toctree:: - :maxdepth: 2 - - Configuration - Overlays diff --git a/scripttease/lib/commands/base.py b/scripttease/lib/commands/base.py index 494dc52..7a44db3 100644 --- a/scripttease/lib/commands/base.py +++ b/scripttease/lib/commands/base.py @@ -24,8 +24,47 @@ __all__ = ( class Command(object): + """A command collects parameters and establishes the standard interface for creating a command line statement.""" def __init__(self, statement, cd=None, comment=None, condition=None, name=None, prefix=None, register=None, shell=None, stop=False, sudo=None, tags=None, **kwargs): + """Initialize a command. + + :param statement: The command statement. + :type statement: str + + :param cd: Change directory to this path. + :type cd: str + + :param comment: A comment on the command. + :type comment: str + + :param condition: A condition to be met before the command should execute. This must be in the form of a Bash + conditional. For example, ``-f path/to/file.txt`` + :type condition: str + + :param name: The canonical name of the command. Provided automatically when using the command factory. + :type name: str + + :param prefix: Any valid statement that should come before the command statement. + :type prefix: str + + :param register: Register the result of the command to this variable name. + :type register: str + + :param shell: The shell to use. Not used by Script Tease, but may be important to integrators. + :type shell: str + + :param stop: Don't continue with additional commands if this one fails. + :type stop: bool + + :param sudo: A username or boolean that indicates sudo should be used. + :type sudo: bool | str + + :param tags: A list of tags that help classify the command. + :type tags: list[str] + + kwargs are added to the Command instance as ``options`` and are dynamically accessible. + """ self.cd = cd self.comment = comment self.condition = condition @@ -124,6 +163,7 @@ class Command(object): class Content(object): + """A special command-like resource for capturing non-statement content such as explanations and screenshots.""" def __init__(self, content_type, caption=None, css=None, heading=None, height=None, image=None, message=None, width=None, **kwargs): @@ -564,12 +604,34 @@ class Sudo(object): class Template(object): + """A command-like resource that may be used to process template files.""" PARSER_JINJA = "jinja2" PARSER_PYTHON = "python" PARSER_SIMPLE = "simple" def __init__(self, source, target, backup=True, parser=PARSER_JINJA, **kwargs): + """Initialize a template. + + :param source: The path to the template file. + :type source: str + + :param target: The path to where the rendered template should be saved. + :type target: str + + :param backup: Indicates whether a backup of an existing target should be created. + :type backup: bool + + :param parser: The parser to use; ``jinja``, ``python``, or ``simple``. + :type parser: str + + kwargs are the same as that of :py:class:`scripttease.lib.commands.base.Command` + + Python templates are parsed using string interpolation. For example, ``%(variable_name)s``. + + Simple templates look for variables in the form of ``$variable_name$``. + + """ self.backup_enabled = backup self.cd = kwargs.pop("cd", None) self.comment = kwargs.pop("comment", "create template %s" % target) @@ -686,6 +748,11 @@ class Template(object): return "\n".join(lines) def get_target_language(self): + """Get the target language of the template output. Used when generating documentation. + + :rtype: str + + """ if self.language is not None: return self.language diff --git a/scripttease/lib/commands/centos.py b/scripttease/lib/commands/centos.py index bb3a384..157c595 100644 --- a/scripttease/lib/commands/centos.py +++ b/scripttease/lib/commands/centos.py @@ -39,9 +39,11 @@ __all__ = ( def apache(op, **kwargs): """Execute an Apache-related command. - - op (str): The operation to perform; reload, restart, start, stop, test. + :param op: The operation to perform; ``reload``, ``restart``, ``start``, ``stop``, ``test``. + :type op: str """ + # See https://unix.stackexchange.com/questions/258854/disable-and-enable-modules-in-apache-centos7 if op == "reload": return apache_reload(**kwargs) elif op == "restart": @@ -57,6 +59,7 @@ def apache(op, **kwargs): def apache_reload(**kwargs): + """Reload the apache service.""" kwargs.setdefault("comment", "reload apache") kwargs.setdefault("register", "apache_reloaded") @@ -64,6 +67,7 @@ def apache_reload(**kwargs): def apache_restart(**kwargs): + """Restart the apache service.""" kwargs.setdefault("comment", "restart apache") kwargs.setdefault("register", "apache_restarted") @@ -71,6 +75,7 @@ def apache_restart(**kwargs): def apache_start(**kwargs): + """Start the apache service.""" kwargs.setdefault("comment", "start apache") kwargs.setdefault("register", "apache_started") @@ -78,12 +83,14 @@ def apache_start(**kwargs): def apache_stop(**kwargs): + """Stop the apache service.""" kwargs.setdefault("comment", "stop apache") return Command("apachectl –k stop", **kwargs) def apache_test(**kwargs): + """Run a configuration test on apache.""" kwargs.setdefault("comment", "check apache configuration") kwargs.setdefault("register", "apache_checks_out") @@ -93,7 +100,8 @@ def apache_test(**kwargs): def service_reload(service, **kwargs): """Reload a service. - - name (str): The service name. + :param service: The service name. + :type service: str """ kwargs.setdefault("comment", "reload %s service" % service) @@ -105,7 +113,8 @@ def service_reload(service, **kwargs): def service_restart(service, **kwargs): """Restart a service. - - name (str): The service name. + :param service: The service name. + :type service: str """ kwargs.setdefault("comment", "restart %s service" % service) @@ -117,7 +126,8 @@ def service_restart(service, **kwargs): def service_start(service, **kwargs): """Start a service. - - name (str): The service name. + :param service: The service name. + :type service: str """ kwargs.setdefault("comment", "start %s service" % service) @@ -129,7 +139,8 @@ def service_start(service, **kwargs): def service_stop(service, **kwargs): """Stop a service. - - name (str): The service name. + :param service: The service name. + :type service: str """ kwargs.setdefault("comment", "stop %s service" % service) @@ -141,7 +152,8 @@ def service_stop(service, **kwargs): def system(op, **kwargs): """Perform a system operation. - - op (str): The operation to perform; reboot, update, upgrade. + :param op: The operation to perform; ``reboot``, ``update``, ``upgrade``. + :type op: str """ if op == "reboot": @@ -157,7 +169,8 @@ def system(op, **kwargs): def system_install(package, **kwargs): """Install a system-level package. - - name (str): The name of the package to install. + :param package: The name of the package to install. + :type package: str """ kwargs.setdefault("comment", "install system package %s" % package) @@ -166,6 +179,7 @@ def system_install(package, **kwargs): def system_reboot(**kwargs): + """Reboot the system.""" kwargs.setdefault("comment", "reboot the system") return Command("reboot", **kwargs) @@ -174,7 +188,8 @@ def system_reboot(**kwargs): def system_uninstall(package, **kwargs): """Uninstall a system-level package. - - name (str): The name of the package to uninstall. + :param package: The name of the package to remove. + :type package: str """ kwargs.setdefault("comment", "remove system package %s" % package) @@ -183,12 +198,14 @@ def system_uninstall(package, **kwargs): def system_update(**kwargs): + """Update the system's package info.""" kwargs.setdefault("comment", "update system package info") return Command("yum check-update", **kwargs) def system_upgrade(**kwargs): + """updated the system.""" kwargs.setdefault("comment", "upgrade the system") return Command("yum update -y", **kwargs) @@ -197,11 +214,20 @@ def system_upgrade(**kwargs): def user(name, groups=None, home=None, op="add", password=None, **kwargs): """Create or remove a user. - - name (str): The user name. - - groups (str | list): A list of groups to which the user should belong. - - home (str): The path to the user's home directory. - - op (str); The operation to perform; ``add`` or ``remove``. - - password (str): The user's password. (NOT IMPLEMENTED) + :param name: The username. + :type name: str + + :param groups: A list of groups to which the user should belong. + :type groups: list | str + + :param home: The path to the user's home directory. + :type home: str + + :param op: The operation to perform; ``add`` or ``remove``. + :type op: + + :param password: The user's password. (NOT IMPLEMENTED) + :type password: str """ if op == "add": diff --git a/scripttease/lib/commands/django.py b/scripttease/lib/commands/django.py index 8d02aa1..21788e8 100644 --- a/scripttease/lib/commands/django.py +++ b/scripttease/lib/commands/django.py @@ -1,23 +1,3 @@ -""" -[run django checks] -django: check - -[export fixtures] -django: dump lookups.Category - -[import fixtures] -django: load lookups.Category - -[migrate the database] -django: migrate - -[collect static files] -django: static - -[create super user (ad hoc command)] -django: createsuperuser root - -""" from ...constants import EXCLUDED_KWARGS from .base import Command diff --git a/scripttease/lib/commands/messages.py b/scripttease/lib/commands/messages.py index d7d8360..5aff258 100644 --- a/scripttease/lib/commands/messages.py +++ b/scripttease/lib/commands/messages.py @@ -3,6 +3,21 @@ from ...exceptions import InvalidInput def dialog(message, height=15, title="Message", width=100, **kwargs): + """Display a graphical feedback box to the user. Note that the ``dialog`` command must be available. + + :param message: The message to be displayed. + :type message: str + + :param height: The height of the dialog box. + :type height: int + + :param title: The title displayed. + :type title: str + + :param width: The width of the dialog box. + :type width: int + + """ statement = list() statement.append("dialog --clear") statement.append('--backtitle "%s"' % title) @@ -13,18 +28,60 @@ def dialog(message, height=15, title="Message", width=100, **kwargs): def echo(message, **kwargs): + """Display a message. + + :param message: The message to be displayed. + :type message: str + + """ return Command('echo "%s"' % message, **kwargs) def explain(message, heading=None, **kwargs): + """Create an explanation for documentation. + + :param message: The message to be displayed. + :type message: str + + :param heading: Optional heading for the output. + :type heading: str + + """ return Content("explain", message=message, heading=heading, **kwargs) def screenshot(image, caption=None, css=None, height=None, width=None, **kwargs): + """Create a screenshot for documentation. + + :param image: The URL or path to the image file. + :type image: str + + :param caption: A caption for the image. + :type caption: str + + :param css: CSS classes to be applied to the image tag. + :type css: str + + :param height: The maximum height of the image. + :type height: int + + :param width: The maximum widht of the image. + :type width: int + + """ return Content("screenshot", caption=caption, css=css, height=height, image=image, width=width, **kwargs) def slack(message, url=None, **kwargs): + """Send a message to Slack. + + :param message: The message to be displayed. + :type message: str + + :param url: The channel URL. + :type url: str + + """ if url is None: raise InvalidInput("Slack command requires a url parameter.") @@ -37,6 +94,18 @@ def slack(message, url=None, **kwargs): def twist(message, title="Notice", url=None, **kwargs): + """Send a message to Twist. + + :param message: The message to be displayed. + :type message: str + + :param title: A title for the message. + :type title: str + + :param url: The channel URL. + :type url: str + + """ if url is None: raise InvalidInput("Twist command requires a url parameter.") diff --git a/scripttease/lib/commands/mysql.py b/scripttease/lib/commands/mysql.py index 8f2fe5e..84bbae0 100644 --- a/scripttease/lib/commands/mysql.py +++ b/scripttease/lib/commands/mysql.py @@ -18,7 +18,27 @@ __all__ = ( ) -def mysql(command, *args, host="localhost", excluded_kwargs=None, password=None, port=3306, user="root", **kwargs): +def mysql(command, *args, excluded_kwargs=None, host="localhost", password=None, port=3306, user="root", **kwargs): + """Get a mysql-related command using commonly required parameters. + + :param command: The name of the command. + :type command: str + + :param excluded_kwargs: Keyword arguments to exclude from automatic switch creation. + :type excluded_kwargs: list[str] + + :param host: The host name. + :type host: str + + :param password: The password to use. + :type password: str + + :param port: The TCP port number. + :type port: int + + :param user: The username that will be used to execute the command. + + """ # The excluded parameters (filtered below) may vary based on implementation. We do, however, need a default. excluded_kwargs = excluded_kwargs or EXCLUDED_KWARGS @@ -63,6 +83,15 @@ def mysql(command, *args, host="localhost", excluded_kwargs=None, password=None, def mysql_create(database, owner=None, **kwargs): + """Create a MySQL database. + + :param database: The database name. + :type database: str + + :param owner: The owner (user/role name) of the new database. + :type owner: str + + """ kwargs.setdefault("comment", "create mysql database") command = mysql("mysqladmin create", database, **kwargs) @@ -75,12 +104,27 @@ def mysql_create(database, owner=None, **kwargs): def mysql_drop(database, **kwargs): + """Remove a MySQL database. + + :param database: The database name. + :type database: str + + """ kwargs.setdefault("comment", "drop %s mysql database" % database) return mysql("mysqladmin drop", database, **kwargs) def mysql_dump(database, path=None, **kwargs): + """Export a MySQL database. + + :param database: The database name. + :type database: str + + :param path: The name/path of the export file. Defaults the database name plus ``.sql``. + :type path: str + + """ kwargs.setdefault("comment", "dump mysql database") if path is None: @@ -90,6 +134,12 @@ def mysql_dump(database, path=None, **kwargs): def mysql_exists(database, **kwargs): + """Determine if a MySQL database exists. + + :param database: The database name. + :type database: str + + """ kwargs.setdefault("comment", "determine if %s mysql database exists" % database) kwargs.setdefault("register", "%s_exists" % database) @@ -105,13 +155,13 @@ def mysql_exists(database, **kwargs): def mysql_grant(to, database=None, privileges="ALL", **kwargs): """Grant privileges to a user. - - to (str): The user name to which privileges are granted. - - database (str): The database name. - - host (str): The database host name or IP address. - - password (str): The password for the user with sufficient access privileges to execute the command. - - port (int): The TCP port number of the MySQL service running on the host. - - privileges (str): The privileges to be granted. - - user (str): The name of the user with sufficient access privileges to execute the command. + :param to: The username to which privileges are granted. + + :param database: The database name. + :type database: str + + :param privileges: The privileges to be granted. + :type privileges: str """ kwargs.setdefault("comment", "grant mysql privileges to %s" % to) @@ -134,12 +184,39 @@ def mysql_grant(to, database=None, privileges="ALL", **kwargs): def mysql_load(database, path, **kwargs): + """Load data into a MySQL database. + + :param database: The database name. + :type database: str + + :param path: The path to the file to be loaded. + :type path: str + + """ kwargs.setdefault("comment", "load data into a mysql database") return mysql("mysql", database, "< %s" % path, **kwargs) def mysql_user(name, admin_pass=None, admin_user="root", op="create", password=None, **kwargs): + """Work with a MySQL user. + + :param name: The username. + :type name: str + + :param admin_pass: The password for the user with admin privileges. + :type admin_pass: str + + :param admin_user: The username of the user with admin privileges. + :type admin_user: str + + :param op: The operation to perform: ``create``, ``drop``, ``exists``. + :type op: str + + :param password: The password for a new user. + :type password: str + + """ host = kwargs.get("host", "localhost") if op == "create": diff --git a/scripttease/lib/commands/pgsql.py b/scripttease/lib/commands/pgsql.py index 2bc45e9..724f5cb 100644 --- a/scripttease/lib/commands/pgsql.py +++ b/scripttease/lib/commands/pgsql.py @@ -17,7 +17,27 @@ __all__ = ( ) -def pgsql(command, *args, host="localhost", excluded_kwargs=None, password=None, port=5432, user="postgres", **kwargs): +def pgsql(command, *args, excluded_kwargs=None, host="localhost", password=None, port=5432, user="postgres", **kwargs): + """Get a postgres-related command using commonly required parameters. + + :param command: The name of the command. + :type command: str + + :param excluded_kwargs: Keyword arguments to exclude from automatic switch creation. + :type excluded_kwargs: list[str] + + :param host: The host name. + :type host: str + + :param password: The password to use. + :type password: str + + :param port: The TCP port number. + :type port: int + + :param user: The username that will be used to execute the command. + + """ # The excluded parameters (filtered below) may vary based on implementation. We do, however, need a default. excluded_kwargs = excluded_kwargs or EXCLUDED_KWARGS @@ -59,6 +79,18 @@ def pgsql(command, *args, host="localhost", excluded_kwargs=None, password=None, def pgsql_create(database, owner=None, template=None, **kwargs): + """Create a PostgreSQL database. + + :param database: The database name. + :type database: str + + :param owner: The owner (user/role name) of the new database. + :type owner: str + + :param template: The database template name to use, if any. + :type template: str + + """ kwargs.setdefault("comment", "create %s postgres database" % database) if owner is not None: @@ -87,12 +119,27 @@ def pgsql_create(database, owner=None, template=None, **kwargs): def pgsql_drop(database, **kwargs): + """Remove a PostgreSQL database. + + :param database: The database name. + :type database: str + + """ kwargs.setdefault("comment", "drop %s postgres database" % database) return pgsql("dropdb", database, **kwargs) def pgsql_dump(database, path=None, **kwargs): + """Export a PostgreSQL database. + + :param database: The database name. + :type database: str + + :param path: The name/path of the export file. Defaults the database name plus ``.sql``. + :type path: str + + """ kwargs.setdefault("comment", "dump postgres database") kwargs.setdefault("column_inserts", True) @@ -106,6 +153,12 @@ def pgsql_dump(database, path=None, **kwargs): def pgsql_exists(database, **kwargs): + """Determine if a PostgreSQL database exists. + + :param database: The database name. + :type database: str + + """ kwargs.setdefault("comment", "determine if %s postgres database exists" % database) kwargs.setdefault("register", "%s_exists" % database) @@ -116,6 +169,15 @@ def pgsql_exists(database, **kwargs): def pgsql_load(database, path, **kwargs): + """Load data into a PostgreSQL database. + + :param database: The database name. + :type database: str + + :param path: The path to the file to be loaded. + :type path: str + + """ kwargs.setdefault("comment", "load data into a postgres database") kwargs['dbname'] = database @@ -125,6 +187,24 @@ def pgsql_load(database, path, **kwargs): def pgsql_user(name, admin_pass=None, admin_user="postgres", op="create", password=None, **kwargs): + """Work with a PostgreSQL user. + + :param name: The username. + :type name: str + + :param admin_pass: The password for the user with admin privileges. + :type admin_pass: str + + :param admin_user: The username of the user with admin privileges. + :type admin_user: str + + :param op: The operation to perform: ``create``, ``drop``, ``exists``. + :type op: str + + :param password: The password for a new user. + :type password: str + + """ if op == "create": kwargs.setdefault("comment", "create %s postgres user" % name) diff --git a/scripttease/lib/commands/php.py b/scripttease/lib/commands/php.py index 175783f..ef652e3 100644 --- a/scripttease/lib/commands/php.py +++ b/scripttease/lib/commands/php.py @@ -2,6 +2,12 @@ from .base import Command def php_module(name, **kwargs): + """Enable a PHP module. + + :param name: The module name. + :type name: str + + """ statement = "phpenmod %s" % name return Command(statement, **kwargs) diff --git a/scripttease/lib/commands/posix.py b/scripttease/lib/commands/posix.py index 9099cf6..bd53917 100644 --- a/scripttease/lib/commands/posix.py +++ b/scripttease/lib/commands/posix.py @@ -5,8 +5,11 @@ from .base import Command, MultipleCommands, Prompt def append(path, content=None, **kwargs): """Append content to a file. - - path (str): The path to the file. - - content (str): The content to be appended. + :param path: The path to the file. + :type path: str + + :param content: The content to be appended. + :type content: str """ kwargs.setdefault("comment", "append to %s" % path) @@ -20,12 +23,26 @@ def archive(from_path, absolute=False, exclude=None, file_name="archive.tgz", st **kwargs): """Create a file archive. - - from_path (str): The path that should be archived. - - absolute (bool): Set to ``True`` to preserve the leading slash. - - exclude (str): A pattern to be excluded from the archive. - - strip (int): Remove the specified number of leading elements from the path. - - to_path (str): Where the archive should be created. This should *not* include the file name. - - view (bool): View the output of the command as it happens. + :param from_path: The path that should be archived. + :type from_path: str + + :param absolute: Set to ``True`` to preserve the leading slash. + :type absolute: str + + :param exclude: A pattern to be excluded from the archive. + :type exclude: str + + :param file_name: The name of the archive file. + :type file_name: str + + :param strip: Remove the specified number of leading elements from the path. + :type strip: int + + :param to_path: Where the archive should be created. This should *not* include the file name. + :type to_path: str + + :param view: View the output of the command as it happens. + :type view: bool """ tokens = ["tar"] @@ -56,9 +73,14 @@ def archive(from_path, absolute=False, exclude=None, file_name="archive.tgz", st def certbot(domain_name, email=None, webroot=None, **kwargs): """Get new SSL certificate from Let's Encrypt. - - domain_name (str): The domain name for which the SSL certificate is requested. - - email (str): The email address of the requester sent to the certificate authority. Required. - - webroot (str): The directory where the challenge file will be created. + :param domain_name: The domain name for which the SSL certificate is requested. + :type domain_name: str + + :param email: The email address of the requester sent to the certificate authority. Required. + :type email: str + + :param webroot: The directory where the challenge file will be created. + :type webroot: str """ _email = email or os.environ.get("SCRIPTTEASE_CERTBOT_EMAIL", None) @@ -80,10 +102,17 @@ def certbot(domain_name, email=None, webroot=None, **kwargs): def copy(from_path, to_path, overwrite=False, recursive=False, **kwargs): """Copy a file or directory. - - from_path (str): The file or directory to be copied. - - to_path (str): The location to which the file or directory should be copied. - - overwrite (bool): Indicates files and directories should be overwritten if they exist. - - recursive (bool): Copy sub-directories. + :param from_path: The file or directory to be copied. + :type from_path: str + + :param to_path: The location to which the file or directory should be copied. + :type to_path: str + + :param overwrite: Indicates files and directories should be overwritten if they exist. + :type overwrite: bool + + :param recursive: Copy sub-directories. + :type recursive: bool """ kwargs.setdefault("comment", "copy %s to %s" % (from_path, to_path)) @@ -106,9 +135,14 @@ def copy(from_path, to_path, overwrite=False, recursive=False, **kwargs): def directory(path, group=None, mode=None, owner=None, recursive=False, **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. + :param path: The path to be created. + :type path: str + + :param mode: The access permissions of the new directory. + :type mode: int | str + + :param recursive: Create all directories along the path. + :type recursive: bool """ comment = kwargs.pop("comment", "create directory %s" % path) @@ -155,12 +189,23 @@ def directory(path, group=None, mode=None, owner=None, recursive=False, **kwargs def extract(from_path, absolute=False, exclude=None, strip=None, to_path=None, view=False, **kwargs): """Extract a file archive. - - from_path (str): The path that should be archived. - - absolute (bool): Set to ``True`` to preserve the leading slash. - - exclude (str): A pattern to be excluded from the archive. - - strip (int): Remove the specified number of leading elements from the path. - - to_path (str): Where the archive should be extracted. This should *not* include the file name. - - view (bool): View the output of the command as it happens. + :param from_path: The path to be extracted. + :type from_path: str + + :param absolute: Set to ``True`` to preserve the leading slash. + :type absolute: str + + :param exclude: A pattern to be excluded from the extraction. + :type exclude: str + + :param strip: Remove the specified number of leading elements from the path. + :type strip: int + + :param to_path: Where the extraction should occur. + :type to_path: str + + :param view: View the output of the command as it happens. + :type view: bool """ _to_path = to_path or "./" @@ -192,9 +237,14 @@ def extract(from_path, absolute=False, exclude=None, strip=None, to_path=None, v def link(source, force=False, target=None, **kwargs): """Create a symlink. - - source (str): The source of the link. - - force (bool): Force the creation of the link. - - target (str): The name or path of the target. Defaults to the base name of the source path. + :param source: The source of the link. + :type source: str + + :param force: Force the creation of the link. + :type force: bool + + :param target: The name or path of the target. Defaults to the base name of the source path. + :type target: str """ _target = target or os.path.basename(source) @@ -215,8 +265,11 @@ def link(source, force=False, target=None, **kwargs): def move(from_path, to_path, **kwargs): """Move a file or directory. - - from_path (str): The current path. - - to_path (str): The new path. + :param from_path: The current path. + :type from_path: str + + :param to_path: The new path. + :type to_path: str """ kwargs.setdefault("comment", "move %s to %s" % (from_path, to_path)) @@ -228,11 +281,20 @@ def move(from_path, to_path, **kwargs): def perms(path, group=None, mode=None, owner=None, recursive=False, **kwargs): """Set permissions on a file or directory. - - path (str): The path to be changed. - - group (str): The name of the group to be applied. - - mode (int | str): The access permissions of the file or directory. - - owner (str): The name of the user to be applied. - - recursive: Create all directories along the path. + :param path: The path to be changed. + :type path: str + + :param group: The name of the group to be applied. + :type group: str + + :param mode: The access permissions of the file or directory. + :type mode: int | str + + :param owner: The name of the user to be applied. + :type owner: str + + :param recursive: Update all files and directories along the path. + :type recursive: bool """ comment = kwargs.pop("comment", "set permissions on %s" % path) @@ -292,13 +354,26 @@ def perms(path, group=None, mode=None, owner=None, recursive=False, **kwargs): def prompt(name, back_title="Input", choices=None, default=None, dialog=False, help_text=None, label=None, **kwargs): """Prompt the user for input. - - name (str): The programmatic name of the input. - - back_title (str): The back title used with the dialog command. - - choices (str | list): A list of valid choices. - - default: The default value. - - dialog (bool): Use a dialog command for the prompt. - - help_text (str): The text to display with the dialog command. - - label (str): The label for the input. + :param name: The programmatic name of the input. + :type name: str + + :param back_title: The back title used with the dialog command. + :type back_title: str + + :param choices: A list of valid choices. + :type choices: list | str + + :param default: The default value. + :type default: str + + :param dialog: Use a dialog command for the prompt. + :type dialog: bool + + :param help_text: The text to display with the dialog command. + :type help_text: str + + :param label: The label for the input. + :type label: str """ return Prompt( @@ -316,9 +391,14 @@ def prompt(name, back_title="Input", choices=None, default=None, dialog=False, h def remove(path, force=False, recursive=False, **kwargs): """Remove a file or directory. - - path (str): The path to be removed. - - force (bool): Force the removal. - - recursive (bool): Remove all directories along the path. + :param path: The path to be removed. + :type path: str + + :param force: Force the removal. + :type force: bool + + :param recursive: Remove all directories along the path. + :type recursive: bool """ kwargs.setdefault("comment", "remove %s" % path) @@ -339,11 +419,20 @@ def remove(path, force=False, recursive=False, **kwargs): def replace(path, backup=".b", delimiter="/", find=None, replace=None, **kwargs): """Find and replace text in a file. - - path (str): The path to the file to be edited. - - backup (str): The backup file extension to use. - - delimiter (str): The pattern delimiter. - - find (str): The old text. Required. - - replace (str): The new text. Required. + :param path: The path to the file to be edited. + :type path: str + + :param backup: The backup file extension to use. + :type backup: str + + :param delimiter: The pattern delimiter. + :type delimiter: str + + :param find: The old text. Required. + :param find: str + + :param replace: The new text. Required. + :type replace: str """ @@ -365,7 +454,12 @@ def replace(path, backup=".b", delimiter="/", find=None, replace=None, **kwargs) def run(statement, **kwargs): - """Run any command.""" + """Run any command. + + :param statement: The statement to be executed. + :type statement: str + + """ kwargs.setdefault("comment", "run statement") return Command(statement, **kwargs) @@ -375,16 +469,35 @@ def rsync(source, target, delete=False, exclude=None, host=None, key_file=None, recursive=True, user=None, **kwargs): """Synchronize a directory structure. - - source (str): The source directory. - - target (str): The target directory. - - delete (bool): Indicates target files that exist in source but not in target should be removed. - - exclude (str): The path to an exclude file. - - host (str): The host name or IP address. This causes the command to run over SSH. - - key_file (str): The privacy SSH key (path) for remote connections. User expansion is automatically applied. - - links (bool): Include symlinks in the sync. - - port (int): The SSH port to use for remote connections. - - recursive (bool): Indicates source contents should be recursively synchronized. - - user (str): The user name to use for remote connections. + :param source: The source directory. + :type source: str + + :param target: The target directory. + :type target: str + + :param delete: Indicates target files that exist in source but not in target should be removed. + :type delete: bool + + :param exclude: The path to an exclude file. + :type exclude: str + + :param host: The host name or IP address. + :type host: str + + :param key_file: The privacy SSH key (path) for remote connections. User expansion is automatically applied. + :type key_file: str + + :param links: Include symlinks in the sync. + :type links: bool + + :param port: The SSH port to use for remote connections. + :type port: int + + :param recursive: Indicates source contents should be recursively synchronized. + :type recursive: bool + + :param user: The username to use for remote connections. + :type user: str """ # - guess: When ``True``, the ``host``, ``key_file``, and ``user`` will be guessed based on the base name of @@ -455,12 +568,23 @@ def rsync(source, target, delete=False, exclude=None, host=None, key_file=None, def scopy(from_path, to_path, host=None, key_file=None, port=22, user=None, **kwargs): """Copy a file or directory to a remote server. - - from_path (str): The source directory. - - to_path (str): The target directory. - - host (str): The host name or IP address. Required. - - key_file (str): The privacy SSH key (path) for remote connections. User expansion is automatically applied. - - port (int): The SSH port to use for remote connections. - - user (str): The user name to use for remote connections. + :param from_path: The source of the copy. + :type from_path: str + + :param to_path: The remote target of the copy. + :type to_path: str + + :param host: The host name or IP address. Required. + :type host: str + + :param key_file: The privacy SSH key (path) for remote connections. User expansion is automatically applied. + :type key_file: str + + :param port: The SSH port to use for remote connections. + :type port: int + + :param user: The username to use for remote connections. + :type user: str """ kwargs.setdefault("comment", "copy %s to remote %s" % (from_path, to_path)) @@ -491,16 +615,23 @@ def scopy(from_path, to_path, host=None, key_file=None, port=22, user=None, **kw def sync(source, target, delete=False, exclude=None, links=True, recursive=True, **kwargs): """Synchronize a local directory structure. - - source (str): The source directory. - - target (str): The target directory. - - delete (bool): Indicates target files that exist in source but not in target should be removed. - - exclude (str): The path to an exclude file. - - host (str): The host name or IP address. This causes the command to run over SSH. - - key_file (str): The privacy SSH key (path) for remote connections. User expansion is automatically applied. - - links (bool): Include symlinks in the sync. - - port (int): The SSH port to use for remote connections. - - recursive (bool): Indicates source contents should be recursively synchronized. - - user (str): The user name to use for remote connections. + :param source: The source directory. + :type source: str + + :param target: The target directory. + :type target: str + + :param delete: Indicates target files that exist in source but not in target should be removed. + :type delete: bool + + :param exclude: The path to an exclude file. + :type exclude: str + + :param links: Include symlinks in the sync. + :type links: bool + + :param recursive: Indicates source contents should be recursively synchronized. + :type recursive: bool """ # - guess: When ``True``, the ``host``, ``key_file``, and ``user`` will be guessed based on the base name of @@ -552,7 +683,8 @@ def sync(source, target, delete=False, exclude=None, links=True, recursive=True, def touch(path, **kwargs): """Touch a file or directory. - - path (str): The file or directory to touch. + :param path: The file or directory to touch. + :type path: str """ kwargs.setdefault("comment", "touch %s" % path) @@ -563,7 +695,8 @@ def touch(path, **kwargs): def wait(seconds, **kwargs): """Pause execution for a number of seconds. - - seconds (int): The number of seconds to wait. + :param seconds: The number of seconds to wait. + :type seconds: int """ kwargs.setdefault("comment", "pause for %s seconds" % seconds) @@ -574,8 +707,11 @@ def wait(seconds, **kwargs): def write(path, content=None, **kwargs): """Write to a file. - - path (str): The file to be written. - - content (str): The content to be written. Note: If omitted, this command is equivalent to ``touch``. + :param path: The file to be written. + :type path: str + + :param content: The content to be written. Note: If omitted, this command is equivalent to ``touch``. + :type content: str """ _content = content or "" diff --git a/scripttease/lib/commands/python.py b/scripttease/lib/commands/python.py index 0e4c861..9a5b4fb 100644 --- a/scripttease/lib/commands/python.py +++ b/scripttease/lib/commands/python.py @@ -4,11 +4,20 @@ from .base import Command def python_pip(name, op="install", upgrade=False, venv=None, version=3, **kwargs): """Use pip to install or uninstall a Python package. - - name (str): The name of the package. - - op (str): The operation to perform; install, uninstall - - upgrade (bool): Upgrade an installed package. - - venv (str): The name of the virtual environment to load. - - version (int): The Python version to use, e.g. ``2`` or ``3``. + :param name: The name of the package. + :type name: str + + :param op: The operation to perform; ``install``, ``uninstall`` + :type op: str + + :param upgrade: Upgrade an installed package. + :type upgrade: bool + + :param venv: The name of the virtual environment to load. + :type venv: str + + :param version: The Python version to use, e.g. ``2`` or ``3``. + :type version: int """ manager = "pip" @@ -57,7 +66,8 @@ def python_pip_file(path, venv=None, version=3, **kwargs): def python_virtualenv(name, **kwargs): """Create a Python virtual environment. - - name (str): The name of the environment to create. + :param name: The name of the environment to create. + :type name: str """ kwargs.setdefault("comment", "create %s virtual environment" % name) diff --git a/scripttease/lib/commands/ubuntu.py b/scripttease/lib/commands/ubuntu.py index 3aef7c6..8610c95 100644 --- a/scripttease/lib/commands/ubuntu.py +++ b/scripttease/lib/commands/ubuntu.py @@ -44,7 +44,8 @@ __all__ = ( def apache(op, **kwargs): """Execute an Apache-related command. - - op (str): The operation to perform; reload, restart, start, stop, test. + :param op: The operation to perform; ``reload``, ``restart``, ``start``, ``stop``, ``test``. + :type op: str """ if op == "reload": @@ -64,7 +65,8 @@ def apache(op, **kwargs): def apache_disable_module(module, **kwargs): """Disable an Apache module. - - name (str): The module name. + :param module: The name of the module. + :type module: str """ kwargs.setdefault("comment", "disable %s apache module" % module) @@ -75,7 +77,8 @@ def apache_disable_module(module, **kwargs): def apache_disable_site(site, **kwargs): """Disable an Apache site. - - name (str): The domain name. + :param site: The site/domain name. + :type site: str """ kwargs.setdefault("comment", "disable %s apache site" % site) @@ -86,7 +89,8 @@ def apache_disable_site(site, **kwargs): def apache_enable_module(module, **kwargs): """Enable an Apache module. - - name (str): The module name. + :param module: The name of the module. + :type module: str """ kwargs.setdefault("comment", "enable %s apache module" % module) @@ -97,6 +101,8 @@ def apache_enable_module(module, **kwargs): def apache_enable_site(site, **kwargs): """Enable an Apache site. + :param site: The site/domain name. + :type site: str """ kwargs.setdefault("comment", "enable %s apache module" % site) @@ -105,6 +111,7 @@ def apache_enable_site(site, **kwargs): def apache_reload(**kwargs): + """Reload the apache service.""" kwargs.setdefault("comment", "reload apache") kwargs.setdefault("register", "apache_reloaded") @@ -112,6 +119,7 @@ def apache_reload(**kwargs): def apache_restart(**kwargs): + """Restart the apache service.""" kwargs.setdefault("comment", "restart apache") kwargs.setdefault("register", "apache_restarted") @@ -119,6 +127,7 @@ def apache_restart(**kwargs): def apache_start(**kwargs): + """Start the apache service.""" kwargs.setdefault("comment", "start apache") kwargs.setdefault("register", "apache_started") @@ -126,12 +135,14 @@ def apache_start(**kwargs): def apache_stop(**kwargs): + """Stop the apache service.""" kwargs.setdefault("comment", "stop apache") return Command("service apache2 stop", **kwargs) def apache_test(**kwargs): + """Run a configuration test on apache.""" kwargs.setdefault("comment", "check apache configuration") kwargs.setdefault("register", "apache_checks_out") @@ -141,7 +152,8 @@ def apache_test(**kwargs): def service_reload(service, **kwargs): """Reload a service. - - name (str): The service name. + :param service: The service name. + :type service: str """ kwargs.setdefault("comment", "reload %s service" % service) @@ -153,7 +165,8 @@ def service_reload(service, **kwargs): def service_restart(service, **kwargs): """Restart a service. - - name (str): The service name. + :param service: The service name. + :type service: str """ kwargs.setdefault("comment", "restart %s service" % service) @@ -165,7 +178,8 @@ def service_restart(service, **kwargs): def service_start(service, **kwargs): """Start a service. - - name (str): The service name. + :param service: The service name. + :type service: str """ kwargs.setdefault("comment", "start %s service" % service) @@ -177,7 +191,8 @@ def service_start(service, **kwargs): def service_stop(service, **kwargs): """Stop a service. - - name (str): The service name. + :param service: The service name. + :type service: str """ kwargs.setdefault("comment", "stop %s service" % service) @@ -189,7 +204,8 @@ def service_stop(service, **kwargs): def system(op, **kwargs): """Perform a system operation. - - op (str): The operation to perform; reboot, update, upgrade. + :param op: The operation to perform; ``reboot``, ``update``, ``upgrade``. + :type op: str """ if op == "reboot": @@ -205,7 +221,8 @@ def system(op, **kwargs): def system_install(package, **kwargs): """Install a system-level package. - - name (str): The name of the package to install. + :param package: The name of the package to install. + :type package: str """ kwargs.setdefault("comment", "install system package %s" % package) @@ -214,6 +231,7 @@ def system_install(package, **kwargs): def system_reboot(**kwargs): + """Reboot the system.""" kwargs.setdefault("comment", "reboot the system") return Command("reboot", **kwargs) @@ -222,7 +240,8 @@ def system_reboot(**kwargs): def system_uninstall(package, **kwargs): """Uninstall a system-level package. - - name (str): The name of the package to uninstall. + :param package: The name of the package to remove. + :type package: str """ kwargs.setdefault("comment", "remove system package %s" % package) @@ -231,12 +250,14 @@ def system_uninstall(package, **kwargs): def system_update(**kwargs): + """Update the system's package info.""" kwargs.setdefault("comment", "update system package info") return Command("apt update -y", **kwargs) def system_upgrade(**kwargs): + """updated the system.""" kwargs.setdefault("comment", "upgrade the system") return Command("apt upgrade -y", **kwargs) @@ -245,11 +266,20 @@ def system_upgrade(**kwargs): def user(name, groups=None, home=None, op="add", password=None, **kwargs): """Create or remove a user. - - name (str): The user name. - - groups (str | list): A list of groups to which the user should belong. - - home (str): The path to the user's home directory. - - op (str); The operation to perform; ``add`` or ``remove``. - - password (str): The user's password. (NOT IMPLEMENTED) + :param name: The username. + :type name: str + + :param groups: A list of groups to which the user should belong. + :type groups: list | str + + :param home: The path to the user's home directory. + :type home: str + + :param op: The operation to perform; ``add`` or ``remove``. + :type op: + + :param password: The user's password. (NOT IMPLEMENTED) + :type password: str """ if op == "add": diff --git a/scripttease/lib/loaders/base.py b/scripttease/lib/loaders/base.py index f8e54ea..8823f56 100644 --- a/scripttease/lib/loaders/base.py +++ b/scripttease/lib/loaders/base.py @@ -125,8 +125,7 @@ class BaseLoader(File): :param path: The path to the command file. :type path: str - :param context: Global context that may be used when to parse the command file, snippets, and templates. This is - converted to a ``dict`` when passed to a Snippet or Template. + :param context: Global context that may be used to parse the command file and templates. :type context: scripttease.lib.contexts.Context :param locations: A list of paths where templates and other external files may be found. The ``templates/``