diff --git a/README.markdown b/README.markdown index c251b53..1ae1933 100644 --- a/README.markdown +++ b/README.markdown @@ -1,7 +1,13 @@ # Python Script Tease ![](https://img.shields.io/badge/status-active-green.svg) -![](https://img.shields.io/badge/stage-development-blue.svg) +![](https://img.shields.io/badge/stage-stable-green.svg) ![](https://img.shields.io/badge/coverage-100%25-green.svg) -A collection of classes and commands for automated command line scripting using Python. \ No newline at end of file +A collection of classes and commands for automated command line scripting using Python. + +## Install + +```bash +pip install python-scripttease; +``` diff --git a/docs/source/_data/cloc.csv b/docs/source/_data/cloc.csv index 5fc8112..580ed03 100644 --- a/docs/source/_data/cloc.csv +++ b/docs/source/_data/cloc.csv @@ -1,4 +1,4 @@ files,language,blank,comment,code -23,Python,1215,1163,2070 +23,Python,1230,1178,2094 12,INI,54,83,174 -35,SUM,1269,1246,2244 +35,SUM,1284,1261,2268 diff --git a/help/docs/cli.md b/help/docs/cli.md index 7d7c5e6..20109e2 100644 --- a/help/docs/cli.md +++ b/help/docs/cli.md @@ -2,7 +2,7 @@ title: CLI --- -The `tease` command may be used to parse a configuration file, providing additional utilities for working with commands. +The `tease` command may be used to parse a steps file, providing additional utilities for working with commands. ## Getting Help @@ -36,7 +36,7 @@ A nice benefit of using configuration for commands is that the information may b Additionally, Script Tease provides the [explain](commands/messages.md#explain) and [screenshot](commands/messages.md#screenshot) commands that help provide extra content for documentary output. ```text -usage: tease docs [-h] [-o= {html,md,plain,rst}] [-C= VARIABLES] [-i= COMMAND_FILE] [-O= OPTIONS] [-P= {centos,ubuntu}] +usage: tease docs [-h] [-o= {html,md,plain,rst}] [-C= VARIABLES] [-i= STEPS_FILE] [-O= OPTIONS] [-P= {centos,ubuntu}] [-T= TEMPLATE_LOCATIONS] [-w= OUTPUT_FILE] [-V= VARIABLES_FILE] [-D] [-p] optional arguments: @@ -45,7 +45,7 @@ optional arguments: The output format; HTML, Markdown, plain text, or ReStructuredText. -C= VARIABLES, --context= VARIABLES Context variables for use in pre-parsing the config and templates. In the form of: name:value - -i= COMMAND_FILE, --input-file= COMMAND_FILE + -i= STEPS_FILE, --input-file= STEPS_FILE The path to the configuration file. -O= OPTIONS, --option= OPTIONS Common command options in the form of: name:value @@ -91,13 +91,13 @@ optional arguments: The `script` sub-command exports command configuration to actual Bash statements. Minimum usage is ```bash -tease -i commands.ini +tease -i steps.ini ``` This will output the statements represented in the specified configuration file. There are quite a few other parameters. ```text -usage: tease script [-h] [-c] [-s] [-C= VARIABLES] [-i= COMMAND_FILE] [-O= OPTIONS] [-P= {centos,ubuntu}] [-T= TEMPLATE_LOCATIONS] +usage: tease script [-h] [-c] [-s] [-C= VARIABLES] [-i= STEPS_FILE] [-O= OPTIONS] [-P= {centos,ubuntu}] [-T= TEMPLATE_LOCATIONS] [-w= OUTPUT_FILE] [-V= VARIABLES_FILE] [-D] [-p] optional arguments: @@ -106,7 +106,7 @@ optional arguments: -s, --shebang Add the shebang to the beginning of the output. -C= VARIABLES, --context= VARIABLES Context variables for use in pre-parsing the config and templates. In the form of: name:value - -i= COMMAND_FILE, --input-file= COMMAND_FILE + -i= STEPS_FILE, --input-file= STEPS_FILE The path to the configuration file. -O= OPTIONS, --option= OPTIONS Common command options in the form of: name:value @@ -146,14 +146,14 @@ value = example.com value = example_com ``` -The variables above are available as template variables in a commands file. +The variables above are available as template variables in a steps file. For example, ``{{ domain_name }}`` becomes ``example.com``. -To load the variables, use the `-V` switch: +To load the variables file, use the `-V` switch: ```bash -tease -V variables.ini +tease -i steps.ini -V variables.ini ``` diff --git a/help/docs/commands/pgsql.md b/help/docs/commands/pgsql.md deleted file mode 100644 index 2fe33f1..0000000 --- a/help/docs/commands/pgsql.md +++ /dev/null @@ -1,70 +0,0 @@ -# PostgreSQL - -Summary: Work with Postgres databases. - -## Common Options - -- `admin_pass`: The password off the admin-authorized user. -- `admin_user`: The user name of the admin-authorized user. Default: `postgres` -- `host`: The host name. Default: `localhost` -- `port`: The TCP port. Default: `5432` - -## Available Commands - -### pgsql.create - -Create a database. Argument is the database name. - -- `owner`: The user name that owns the database. - -```ini -[create the database] -pgsql.create: database_name -``` - -### pgsql.drop - -Drop a database. Argument is the database name. - -### pgsql.dump - -Dump the database schema. Argument is the database name. - -- `path`: The path to the dump file. Default: `dump.sql` - -### pgsql.exec - -Execute an SQL statement. Argument is the SQL statement. - -- `database`: The name of the database where the statement will be executed. Default: `default` - -### pgsql.exists - -Determine if a database exists. Argument is the database name. - -### pgsql.user - -Create a user. Argument is the user name. - -- `password`: The user's password. - -```ini -[create a database user] -pgsql.user: username -``` - -Remove a user. - -```ini -[remove a database user] -pgsql.user: username -op: remove -``` - -Determine if a user exists. - -```ini -[determine if database user exists] -pgsql.user: username -op: exists -``` diff --git a/help/docs/commands/posix.md b/help/docs/commands/posix.md deleted file mode 100644 index b08419d..0000000 --- a/help/docs/commands/posix.md +++ /dev/null @@ -1,148 +0,0 @@ -# POSIX - -Summary: Work with common POSIX-compliant commands.. - -## Available Commands - -### append - -Append content to a file. Argument is the file name. - -- `content`: The content to be appended. - -### archive - -Create an archive (tarball). Argument is the target file or directory. - -- `absolute`: Don't strip leading slashes from file names. -- `view`: View the progress. -- `exclude`: Exclude file name patterns. -- `strip`: Strip component paths to the given depth (integer). -- `to`: The path to where the archive will be created. - -### copy - -Copy a file or directory. First argument is the target file/directory. Second argument is the destination. - -- `overwrite`: Overwrite an existing target. -- `recursive`: Copy directories recursively. - -### dir - -Create a directory. Argument is the path. - -- `group`: Set the group to the given group name. -- `mode`: Set the mode on the path. -- `owner`: Set the owner to the given owner name. -- `recursive`: Create the full path even if intermediate directories do not exist. - -### extract - -Extract an archive (tarball). Argument is the path to the archive file. - -- `absolute`: Strip leading slashes from file names. -- `view`: View the progress. -- `exclude`: Exclude file name patterns. -- `strip`: Strip component paths to the given depth (integer). -- `to`: The path to where the archive will be extracted. Defaults to the current working directory. - -### file - -Create a file. Argument is the path. - -- `content`: The content of the file. Otherwise, an empty file is created. -- `group`: Set the group to the given group name. -- `mode`: Set the mode on the path. -- `owner`: Set the owner to the given owner name. - -### link - -Create a symlink. First argument is the target. Second argument is the destination. - -- `force`: Force creation of the link. - -### move - -Move a file or directory. First argument is the target. Second argument is the desitnation. - -### perms - -Set permissions on a file or directory. Argument is the path. - -- `group`: Set the group to the given group name. -- `mode`: Set the mode on the path. -- `owner`: Set the owner to the given owner name. -- `recursive`: Apply permission recursively (directories only). - -### push - -Push (rsync) a path to a remote server. First argument is the local path. Second argument is the remote path. - -- `delete`: Delete existing files/directories. -- `host`: The host name. Required. -- `key_file`: Use the given SSL (private) key. Required. -- `links`: Copy symlinks. -- `exclude`: Exclude patterns from the given (local) file. -- `port`: The TCP port on the host. Default: `22` -- `recursive`: Operate recursively on directories. -- `user`: The user name. Required. - -### remove - -Remove a file or directory. Argument is the path. - -- `force`: Force the removal. -- `recursive`: Remove (directories) rescurisvely. - -### rename - -Rename a file or directory. First argument is the target. Second argument is the destination. - -### replace - -Replace something in a file. First argument is the path. - -- `backup`: Create a backup. -- `delimiiter`: The sed delimiter. Default: `/` -- `find`: The text to be found. Required. -- `sub`: The text to be replaced. Required. - -### scopy - -Copy a file to a remote server. First argument is the local file name. Second argument is the remote destination. - -- `key_file`: The private key file to use for the connection. -- `host`: The host name. Required. -- `port`: The TCP port. Default: `22` -- `user`: The user name. Required. - -### ssl - -Use Let's Encrypt (certbot) to acquire an SSL certificate. Argument is the domain name. - -- `email`: The email address for "agree tos". Default: `webmaster@domain_name` -- `webroot`: The webroot to use. Default: `/var/www/maint/www` - -### sync - -Sync (rsync) local files and directories. First argument is the target. Second argument is the destination. - -- `delete`: Delete existing files/directories. -- `links`: Copy symlinks. -- `exclude`: Exclude patterns from the given (local) file. -- `recursive`: Operate recursively on directories. - -### touch - -Touch a file, whether it exists or not. Argument is the path. - -### wait - -Wait for n number of seconds before continuing. Argument is the number of seconds. - -### write - -Write to a file. Argument is the path. - -- `content`: The content to write to the file. Replaces existing content. - diff --git a/help/docs/commands/python.md b/help/docs/commands/python.md deleted file mode 100644 index 2f94e5f..0000000 --- a/help/docs/commands/python.md +++ /dev/null @@ -1,20 +0,0 @@ -# Python - -Summary: Work with Python. - -## Available Commands - -### pip - -Use the pip command. Argument is the package name. - -- `op`: The operation; `install` (the default), `remove`, or `updgrade`. -- `venv`: The name of the virtual environment to use. - -### pip3 - -Use Python3 pip. See pip above. - -### virtualenv - -Create a python virtual environment. Argument is the environment name. diff --git a/help/docs/getting-started.md b/help/docs/getting-started.md index 27f8ae5..9654fb7 100644 --- a/help/docs/getting-started.md +++ b/help/docs/getting-started.md @@ -14,11 +14,8 @@ pip install python-scripttease; ## Configuration -See [Commands File](topics/command-file.md) for creating a configuration file. +See [Steps File](topics/steps-file.md) for creating a configuration file. ## FAQs -Have a question? `Just ask`_! - -.. _Just ask: https://develmaycare.com/contact/?product=Script%20Tease - +**Does Script Tease execute commands?** No. Script Tease generates statements that may be [saved to a file for examination and execution](how-to/create-executable-script.md). Or a [custom implementation](how-to/use-with-commonkit.md) may be created to execute the generated statements. \ No newline at end of file diff --git a/help/docs/how-to/use-with-commonkit.md b/help/docs/how-to/use-with-commonkit.md index dbe73e2..ce57228 100644 --- a/help/docs/how-to/use-with-commonkit.md +++ b/help/docs/how-to/use-with-commonkit.md @@ -1,11 +1,12 @@ # 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](https://docs.develmaycare.com/en/python-commonkit/stable/components/#module-commonkit.shell) *does* provide support for executing commands in local POSIX environments. +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](https://docs.develmaycare.com/en/python-commonkit/stable/components/#module-commonkit.shell) *does* provide support for executing commands in local POSIX environments. Here is an example of how to use these packages together: ```python from commonkit.shell import Command +from scripttease.exceptions import InvalidInput from scripttease.lib.factories import command_factory from scripttease.lib.loaders import INILoader @@ -30,16 +31,21 @@ def execute(step): exit(command.code) -ini = INILoader("path/to/commands.ini") +ini = INILoader("path/to/steps.ini") ini.load() -steps = command_factory(ini) + +try: + steps = command_factory(ini) +except InvalidInput as e: + print("%s: I can't go on." % e) + exit(1) # A failure to load results in None. if steps is None: print("Failed to load steps. Bummer.") exit(1) -# Iterate through each step to create a COMMON KIT command instance. +# Iterate through each step to create a Common Kit command instance. for step in steps: # To preview ... diff --git a/help/docs/index.md b/help/docs/index.md index 80d7472..bcafcc0 100644 --- a/help/docs/index.md +++ b/help/docs/index.md @@ -7,7 +7,7 @@ Script Tease is a library and command line tool for generating Bash commands pro The primary focus (and limit) is to convert plain text instructions (in INI or YAML format) into valid command line statements for a given platform. It does *not* provide support for executing those statements. !!! warning - YAML support is untested. + YAML support is currently untested. ## Concepts @@ -16,10 +16,10 @@ The primary focus (and limit) is to convert plain text instructions (in INI or Y Script Tease may be used in three (3) ways: 1. Using the library to programmatically define commands and export them as command line statements. -2. Using the `tease` command to generate commands from a configuration file. See [command file configuration](topics/command-file.md). +2. Using the `tease` command to generate commands from a configuration file. See [steps file](topics/steps-file.md). 3. Using the command file format and library to create a custom implementation. -This documentation focuses on the second method, but the developer docs may be used in your own implementation. +This documentation focuses on the second method, but the [developer docs](./reference) may be used to guide custom implementations for 1 and 3 above. ### Self-Documenting @@ -53,10 +53,13 @@ Profiles import and appropriate all other available commands. ## Terms and Definitions command -: When used in Script Tease documentation, this is a command instance which contains the properties and parameters for assembling a command line statement. +: When used in Script Tease documentation, this is a command instance which contains the properties and parameters for assembling a command line statement. + +profile +: A collection of commands that work for a specific operating system profile. statement -: A specific statement (string) to be executed. A *statement* is generated from a *command*. +: A specific statement (string) to be executed. A *statement* is generated from a *command*. ## License diff --git a/help/docs/topics/command-file.md b/help/docs/topics/steps-file.md similarity index 98% rename from help/docs/topics/command-file.md rename to help/docs/topics/steps-file.md index ccd4a4a..8d50bc9 100644 --- a/help/docs/topics/command-file.md +++ b/help/docs/topics/steps-file.md @@ -1,6 +1,6 @@ -# Command File +# Steps File -A command file contains the metadata about the commands to be generated. INI and YAML formats are supported. +A steps file contains the metadata about the commands to be generated. INI and YAML formats are supported. In an INI file, each section is a command. With YAML, each top-level list item is a command. diff --git a/help/docs/topics/templates.md b/help/docs/topics/templates.md index 81115bb..60b3784 100644 --- a/help/docs/topics/templates.md +++ b/help/docs/topics/templates.md @@ -4,16 +4,22 @@ Script Tease supports processing of template files using Jinja2. ## Location of Templates -By default, the location of template files are reckoned as relative to the commands configuration file. +By default, the location of template files are reckoned as relative to the steps file. ```text package_name/ -|-- commands.ini +|-- steps.ini |-- templates | `-- httpd.conf ``` -Upon loading the `commands.ini` file, any reference to a template file is assumed to be in the `templates/` directory in the same location. +Upon loading the `steps.ini` file, any reference to a template file is assumed to be in the `templates/` directory in the same location. + +```ini +[create the apache config] +template: httpd.conf /etc/apache2/sites-available/example.app.conf + +``` !!! tip The `-T` switch of the `tease` command may be used to add template locations. diff --git a/help/docs/topics/variables.md b/help/docs/topics/variables.md index 03480b0..ff662b3 100644 --- a/help/docs/topics/variables.md +++ b/help/docs/topics/variables.md @@ -1,8 +1,8 @@ # Variables File -A variables file contains variable definitions that may be used as the context for parsing a [command file](command-file.md) *before* the actual commands are generated. +A variables file contains variable definitions that may be used as the context for parsing a [steps file](steps-file.md) *before* the actual commands are generated. -Unlike a command file, the INI format is the only supported format for a variables file. +Unlike a steps file, the INI format is currently the only supported format for a variables file. ## The Variable Name @@ -35,7 +35,6 @@ You may define an environment for any given variable that may be used for filter ```ini [database_host:development] -comment: Local host used in development. value: localhost [database_host:live] @@ -48,6 +47,16 @@ In this way, variables of the same name may be supported across different deploy As demonstrated in the example above, you may comment on a variable by adding a `comment:` attribute to the section. +```ini +[database_host:testing] +comment: Local host used when testing. +value: localhost + +[database_host:live] +comment: Separate server used when live. +value: db1.example.com +``` + ## Defining Tags Tags may be defined for any variable as a comma separated list. This is useful for filtering. @@ -68,7 +77,7 @@ tags: application ## Other Attributes -Any other variable defined in the section is dynamically available. +Any other variable defined in the section is dynamically available. These are not used by Script Tease, but implementers may find this feature useful. ```ini [domain_name] diff --git a/help/docs/profiles/centos.md b/help/docs/usage/centos.md similarity index 94% rename from help/docs/profiles/centos.md rename to help/docs/usage/centos.md index 5f9aab1..cb37335 100644 --- a/help/docs/profiles/centos.md +++ b/help/docs/usage/centos.md @@ -54,8 +54,6 @@ Run any shell command. run: "ls -ls" ``` -Note that commands with arguments will need to be in quotes. - ### start Start a service: @@ -82,6 +80,18 @@ Work with the system. - `update` - `upgrade` +```ini +[update package info] +update: + +[upgrade the system] +upgrade: + +[reboot the system] +reboot: + +``` + ### uninstall Uninstall a package. diff --git a/help/docs/commands/django.md b/help/docs/usage/django.md similarity index 67% rename from help/docs/commands/django.md rename to help/docs/usage/django.md index 1257387..6cc5890 100644 --- a/help/docs/commands/django.md +++ b/help/docs/usage/django.md @@ -16,7 +16,7 @@ venv: ../python ## Automatic Conversion of Django Command Switches -Options provided in the command configuration file are automatically converted to command line switches. +Options provided in the steps file are automatically converted to command line switches. ```ini [run database migrations] @@ -31,6 +31,8 @@ natural_primary: yes ``` +`settings` becomes "--settings=tenants.example_com.settings". `indent` becomes "--indent=4". `natural_foreign` and `natural_primary` become "--natural-foreign" and "--natural-primary" respectively. + ## Available Commands ### check @@ -69,9 +71,9 @@ Alias: dump Dump fixture data. -- target (str): Required. The name of the app or `app.Model`. -- format (str): `json` (default) or `xml`. -- path (str): The path to the output file. When a model is provided, this defaults to `fixtures/app/model.json`. Otherwise, it is `fixtures/app/initial.json`. +- `target` (str): Required. The name of the app or `app.Model`. +- `format` (str): `json` (default) or `xml`. +- `path` (str): The path to the output file. When a model is provided, this defaults to `fixtures/app/model.json`. Otherwise, it is `fixtures/app/initial.json`. ```ini [dump project data] @@ -89,9 +91,9 @@ Alias: load Load fixture data. -- target (str): Required. The name of the app or `app.Model`. -- format (str): `json` (default) or `xml` -- path (str): The path to the JSON file. When a model is provided, this defaults to `fixtures/app/model.json`. Otherwise, it is `fixtures/app/initial.json`. +- `target` (str): Required. The name of the app or `app.Model`. +- `format` (str): `json` (default) or `xml` +- `path` (str): The path to the JSON file. When a model is provided, this defaults to `fixtures/app/model.json`. Otherwise, it is `fixtures/app/initial.json`. ```ini [load project categories] @@ -117,14 +119,14 @@ It is possible to work with any Django management command provided the parameter ```ini [run any django command] django: command_name -first_option_name: asdf -second_option_name: 1234 -third_option_name: yes +option_one: asdf +option_two: 1234 +option_three: yes ``` This will generate a statement like: ```bash -./manage.py command_name --first-option-name="asdf" --second-option-name=1234 --third-option-name +./manage.py command_name --option-one="asdf" --option-two=1234 --option-three ``` diff --git a/help/docs/commands/messages.md b/help/docs/usage/messages.md similarity index 74% rename from help/docs/commands/messages.md rename to help/docs/usage/messages.md index 3fff90f..43c1e67 100644 --- a/help/docs/commands/messages.md +++ b/help/docs/usage/messages.md @@ -8,9 +8,9 @@ Summary: Send feedback to users. Use the dialog CLI to display a message. -- `height`: The height of the dialog box. Default: `15` -- `title`: An optional title to display as part of the dialog box. Default: `Message`. -- `width`: The width of the dialog box. Default: `100` +- `height` (int): The height of the dialog box. Default: `15` +- `title` (str): An optional title to display as part of the dialog box. Default: `Message`. +- `width` (int): The width of the dialog box. Default: `100` ```ini [send some feedback] @@ -56,7 +56,7 @@ echo: "This is a message." Send a message via Slack. -- `url`: Required. The URL to which the message should be sent. +- `url` (str): Required. The URL to which the message should be sent. ```ini [send some feedback] @@ -77,6 +77,11 @@ url: https://subdomain.slack.com/path/to/your/integration Like `explain` above, a screenshot adds detail to comments or documentation, but does not produce a command statement. +- `caption` (str): An optional caption for the image. +- `css` (str): CSS class(es) to be apply to the image. +- `height` (int | str): The height of the image in pixels or as a percentage. +- `width` (int | str): The width of the image in pixels or as a percentage. + ```ini [login screenshot after successful install] screenshot: images/login.png @@ -85,14 +90,14 @@ height: 50% width: 50% ``` -The value of `screenshot` may be relative to the command file or a full URL to the image. If `caption` is omitted the section (comment) is used. +The value of `screenshot` may be relative to the command file or a full URL to the image. If `caption` is omitted the comment is used. ### twist Send a message via [Twist](https://twist.com). -- `title`: The title of the message. Default: `Notice` -- `url`: Required. The URL to which the message should be sent. +- `title` (str): The title of the message. Default: `Notice` +- `url` (str): Required. The URL to which the message should be sent. ```ini [send some feedback] diff --git a/help/docs/commands/mysql.md b/help/docs/usage/mysql.md similarity index 73% rename from help/docs/commands/mysql.md rename to help/docs/usage/mysql.md index c9a10a8..652daa1 100644 --- a/help/docs/commands/mysql.md +++ b/help/docs/usage/mysql.md @@ -30,24 +30,39 @@ Drop a database. Argument is the database name. Dump the database schema. Argument is the database name. -- `path`: The path to the dump file. Default: `dump.sql` +- `path`: The path to the dump file. Default: `database_name.sql` -### mysql.exec - -Execute an SQL statement. Argument is the SQL statement. +```ini +[create a soft backup of the database] +mysql.dump: example_app +path: /tmp/example_app.sql -- `database`: The name of the database where the statement will be executed. Default: `default` +``` ### mysql.exists Determine if a database exists. Argument is the database name. +```ini +[determine if the database exists] +mysql.exists: example_app + +``` + + ### mysql.grant -Grant privileges to a user. Argument is the privileges to be granted. +Grant privileges to a user. - `database`: The database name where privileges are granted. -- `user`: The user name for which the privileges are provided. +- `privileges`: The privileges to be granted. Default: `ALL` + +```ini +[grant select privileges to bob] +mysql.grant: bob +privileges: select + +``` ### mysql.user diff --git a/help/docs/usage/pgsql.md b/help/docs/usage/pgsql.md new file mode 100644 index 0000000..d41a89d --- /dev/null +++ b/help/docs/usage/pgsql.md @@ -0,0 +1,119 @@ +# PostgreSQL + +Summary: Work with Postgres databases. + +## Common Options + +- `host` (str): The host name. Default: `localhost` +- `password` (str): The password of the user executing the command. +- `port` (int): The TCP port. Default: `5432` +- `user` (str): The username of the user executing the command. Default: `postgres` + +## Automatic Conversion of Postgres Command Switches + +Options provided in the steps file are automatically converted to command line switches. For example: + +```ini +[create a soft backup of the database schema] +pgsql.dump: example_app +schema_only: yes +path: /tmp/example_app.sql + +``` + +`schema_only` becomes "--schema-only". + +## Available Commands + +### pgsql.create + +Create a database. Argument is the database name. + +- `owner` (str): The username that owns the database. + +```ini +[create the database] +pgsql.create: database_name +``` + +### pgsql.drop + +Drop a database. Argument is the database name. + +```ini +[drop the testing database] +pgsql.drop: testing_example_app + +``` + +### pgsql.dump + +Dump the database schema. Argument is the database name. + +- `path` (str): The path to the dump file. Default: `database_name.sql` + +```ini +[create a soft backup of the database] +pgsql.dump: example_app +column_inserts: yes +path: /tmp/example_app.sql + +``` + +### pgsql.exists + +Determine if a database exists. Argument is the database name. + +```ini +[determine if the database exists] +pgsql.exists: example_app + +``` + +### pgsql.grant + +Grant privileges to a user. Argument is the username. Database option is required. + +- `database` (str): The name of the database where the target object exists. +- `privileges` (str): The privileges to be granted. Default `ALL` (see [Postgres docs](https://www.postgresql.org/docs/current/sql-grant.html)) +- `schema` (str): The schema name to which the privileges apply. +- `table` (str): The table name to which privileges apply. + +!!! note + A schema name or table name is required. + +```ini +[grant select access to bob] +pgsql.grant: bob +database: example_app +privileges: select +schema: public + +``` + +### pgsql.user + +Create a user. Argument is the user name. + +- `password` (str): The user's password. + +```ini +[create a database user] +pgsql.user: username +``` + +Remove a user. + +```ini +[remove a database user] +pgsql.user: username +op: remove +``` + +Determine if a user exists. + +```ini +[determine if database user exists] +pgsql.user: username +op: exists +``` diff --git a/help/docs/commands/php.md b/help/docs/usage/php.md similarity index 66% rename from help/docs/commands/php.md rename to help/docs/usage/php.md index 12c5a6b..d56fc6b 100644 --- a/help/docs/commands/php.md +++ b/help/docs/usage/php.md @@ -7,3 +7,9 @@ Summary: Work with PHP. ### module Enable a PHP module. Argument is the module name. + +```ini +[enable postgres for PHP] +php.module: pdo_pgsql + +``` \ No newline at end of file diff --git a/help/docs/usage/posix.md b/help/docs/usage/posix.md new file mode 100644 index 0000000..28c3f06 --- /dev/null +++ b/help/docs/usage/posix.md @@ -0,0 +1,264 @@ +# POSIX + +Summary: Work with common POSIX-compliant commands.. + +## Available Commands + +### append + +Append content to a file. Argument is the file name. + +- `content` (str): The content to be appended. + +```ini +[add to the log file] +append: /path/to/file.log +content: This is a test. +``` + +### archive + +Create an archive (tarball). Argument is the target file or directory. + +- `absolute` (bool): Don't strip leading slashes from file names. Default `False` +- `exclude` (str): Exclude file name patterns. +- `file_name` (str): The name of the archive file. Default `archive.tgz` +- `strip` (int): Strip component paths to the given depth. +- `to_path` (str): The path to where the archive will be created. Default `.` +- `view` (bool): View the progress. Default `False` + +```ini +[create an archive of the site] +archive: /path/to/file_or_directory +file_name: testing.tgz +to: /tmp + +``` + +### certbot + +Alias: ssl + +Use Let's Encrypt (certbot) to acquire an SSL certificate. Argument is the domain name. + +- `email`: The email address for "agree tos". Default: `webmaster@domain_name` +- `webroot`: The webroot to use. Default: `/var/www/maint/www` + +```ini +[get an SSL cert] +ssl: example.app +email: webmaster@example.app + +``` + +### copy + +Copy a file or directory. First argument is the target file/directory. Second argument is the destination. + +- `overwrite` (bool): Overwrite an existing target. +- `recursive` (bool): Copy directories recursively. + +```ini +[copy a directory] +copy: /path/to/directory /path/to/new_directory +overwrite: yes +recursive: yes + +``` + +### dir + +Create a directory. Argument is the path. + +- `group` (str): Set the group to the given group name. +- `mode` (str): Set the mode on the path. +- `owner` (str): Set the owner to the given owner name. +- `recursive` (str): Create the full path even if intermediate directories do not exist. + +```ini +[create a directory] +dir: /path/to/directory +group: www-data +mode: 755 +owner: deploy +recursive: yes + +``` + +### extract + +Extract an archive (tarball). Argument is the path to the archive file. + +- `absolute` (bool): Don't strip leading slashes from file names. Default `False` +- `exclude` (str): Exclude file name patterns. +- `strip` (int): Strip component paths to the given depth. +- `to_path` (str): The path to where the archive will be created. Default `./` +- `view` (bool): View the progress. Default `False` + +```ini +[extract an archive] +extract: /path/to/archive.tgz + +``` + +### link + +Create a symlink. First argument is the source. + +- `force` (bool): Force creation of the link. +- `target` (str): The location of the link. Defaults to the current directory and the base name of the source. + +```ini +[create a symlink] +link: /path/to/project/releases/1.0 +cd: /path/to/project +force: yes +target: current + +``` + +### move + +Move a file or directory. First argument is the target. Second argument is the desitnation. + +```ini +[move a file] +move: /path/to/file.txt /new/path/to/file.txt + +``` + +### perms + +Set permissions on a file or directory. Argument is the path. + +- `group` (str): Set the group to the given group name. +- `mode` (str): Set the mode on the path. +- `owner` (str): Set the owner to the given owner name. +- `recursive` (bool): Apply permission recursively (directories only). + +```ini +[set permissions on the shared directory] +perms: /path/to/project/shared +group: www-data +mode: 775 +owner: deploy +recursive: yes + +``` + +### push + +Alias: rsync + +Push (rsync) a path to a remote server. First argument is the local path. Second argument is the remote path. + +- `delete` (bool): Delete existing files/directories. Default `False` +- `host` (str): The host name. Required. +- `key_file` (str): Use the given SSL (private) key. +- `links` (bool): Copy symlinks. Default `True +- `exclude` (str): Exclude patterns from the given (local) file. +- `port` (int): The TCP port on the host. Default: `22` +- `recursive` (bool): Operate recursively on directories. +- `user` (str): The username. + +```ini +[push the project to the server] +push: /path/to/project /path/on/server +key_file: ~/.ssh/example_app +host: example.app +user: deploy + +``` + +### remove + +Remove a file or directory. Argument is the path. + +- `force` (bool): Force the removal. Default `False` +- `recursive` (bool): Remove all directories in the path. Default `False` + +```ini +[remove a directory] +remove: /path/to/directory +force: yes +recusrive: yes +``` + +### replace + +Replace something in a file. First argument is the path. + +- `backup`: Backup file extension. Default `.b` +- `delimiiter`: The sed delimiter. Default: `/` +- `find`: The text to be found. Required. +- `sub`: The text to be replaced. Required. + +```ini +[replace text in a file] +replace: /path/to/file.txt +find: testing +sub: 123 +``` + +### scopy + +Copy a file to a remote server. First argument is the local file name. Second argument is the remote destination. + +- `key_file` (str): The private key file to use for the connection. +- `host` (str): The host name. Required. +- `port` (int): The TCP port. Default: `22` +- `user` (str): The username. Required. + +```ini +[copy a file to the server] +scopy: /path/to/local.txt path/to/remove.txt +host: example.app +user: deploy + +``` + +### sync + +Sync (rsync) local files and directories. First argument is the target. Second argument is the destination. + +- `delete` (bool): Delete existing files/directories. +- `links` (bool): Copy symlinks. +- `exclude` (str): Exclude patterns from the given (local) file. +- `recursive` (bool): Operate recursively on directories. + +```ini +[syncrhonize files on the local machine] +sync: /path/to/project /path/to/sync/directory + +``` + +### touch + +Touch a file, whether it exists or not. Argument is the path. + +```ini +[touch a file] +touch: /path/to/file.txt +``` + +### wait + +Wait for n number of seconds before continuing. Argument is the number of seconds. + +```ini +[wait just a minute] +wait: 60 +``` + +### write + +Write to a file. Argument is the path. + +- `content` (str): The content to write to the file. Replaces existing content. + +```ini +[replace an existing file] +write: /path/to/file.txt +content: This whole file has been replaced. + +``` \ No newline at end of file diff --git a/help/docs/usage/python.md b/help/docs/usage/python.md new file mode 100644 index 0000000..00d1434 --- /dev/null +++ b/help/docs/usage/python.md @@ -0,0 +1,49 @@ +# Python + +Summary: Work with Python. + +## Available Commands + +### pip + +Use the pip command. Argument is the package name. + +- `op` (str): The operation; `install` (the default) or `remove`. +- `upgrade` (bool): Upgrade the package. +- `venv` (str): The name of the virtual environment to use. +- `version` (int): The pip version to use. Default `3` + +```ini +[install django] +pip: django +cd: /path/to/project +venv: python +``` + +### pip_file + +Alias: pipf + +Install packages from a pip file. + +- `venv` (str): The name of the virtual environment to use. +- `version` (int): The pip version to use. Default `3` + +```ini +[install dependencies] +pip_file: deploy/packages/testing.pip +cd: path/to/project +venv: python + +``` + +### virtualenv + +Create a python virtual environment. Argument is the environment name. + +```ini +[create the virtual environment] +virtualenv: python +cd: /path/to/project + +``` diff --git a/help/docs/profiles/ubuntu.md b/help/docs/usage/ubuntu.md similarity index 83% rename from help/docs/profiles/ubuntu.md rename to help/docs/usage/ubuntu.md index ae64fa0..41e16f0 100644 --- a/help/docs/profiles/ubuntu.md +++ b/help/docs/usage/ubuntu.md @@ -54,8 +54,6 @@ Run any shell command. run: "ls -ls" ``` -Note that commands with arguments will need to be in quotes. - ### start Start a service: @@ -82,6 +80,18 @@ Work with the system. - `update` - `upgrade` +```ini +[update package info] +update: + +[upgrade the system] +upgrade: + +[reboot the system] +reboot: + +``` + ### uninstall Uninstall a package. @@ -104,10 +114,10 @@ upgrade: libxyz-dev Create a user: -- `groups`: A comma separated list of groups to which the user should be added. -- `home`: The user's home directory. -- `login`: The shell to use. -- `system`: Create as a system user. +- `groups` (str): A comma separated list of groups to which the user should be added. +- `home` (str): The user's home directory. +- `login` (str): The shell to assign. +- `system` (bool): Create as a system user. ```ini [create the deploy user] diff --git a/help/mkdocs.yml b/help/mkdocs.yml index c9de299..2745c07 100644 --- a/help/mkdocs.yml +++ b/help/mkdocs.yml @@ -11,7 +11,7 @@ nav: - Introduction: index.md - Getting Started: getting-started.md - Topics: - - Command File: topics/command-file.md + - Steps File: topics/steps-file.md - Variables File: topics/variables.md - Itemized Commands: topics/itemized-commands.md - Templates: topics/templates.md @@ -21,17 +21,16 @@ nav: - Post a Message to Slack: how-to/post-message-slack.md - Post a Message to Twist: how-to/post-message-twist.md - Use Script Tease with Common Kit: how-to/use-with-commonkit.md - - Commands: - - Django: commands/django.md - - Messages: commands/messages.md - - MySQL: commands/mysql.md - - PHP: commands/php.md - - Postgres: commands/pgsql.md - - POSIX: commands/posix.md - - Python: commands/python.md - - Profiles: - - CentOS: profiles/centos.md - - Ubuntu: profiles/ubuntu.md + - Usage: + - CentOS: usage/centos.md + - Django: usage/django.md + - Messages: usage/messages.md + - MySQL: usage/mysql.md + - PHP: usage/php.md + - Postgres: usage/pgsql.md + - POSIX: usage/posix.md + - Python: usage/python.md + - Ubuntu: usage/ubuntu.md - CLI: cli.md repo_name: Git Traction repo_url: https://gittraction.com/diff6/python-scripttease diff --git a/scripttease/cli/initialize.py b/scripttease/cli/initialize.py index d7ff000..8234093 100644 --- a/scripttease/cli/initialize.py +++ b/scripttease/cli/initialize.py @@ -184,8 +184,8 @@ class SubCommands(object): sub.add_argument( "-i=", "--input-file=", - default="commands.ini", - dest="command_file", + default="steps.ini", + dest="steps_file", help="The path to the configuration file." ) diff --git a/scripttease/lib/commands/mysql.py b/scripttease/lib/commands/mysql.py index 84bbae0..c6b87f8 100644 --- a/scripttease/lib/commands/mysql.py +++ b/scripttease/lib/commands/mysql.py @@ -156,6 +156,7 @@ def mysql_grant(to, database=None, privileges="ALL", **kwargs): """Grant privileges to a user. :param to: The username to which privileges are granted. + :type to: str :param database: The database name. :type database: str diff --git a/scripttease/lib/commands/pgsql.py b/scripttease/lib/commands/pgsql.py index 724f5cb..6d843bc 100644 --- a/scripttease/lib/commands/pgsql.py +++ b/scripttease/lib/commands/pgsql.py @@ -12,6 +12,7 @@ __all__ = ( "pgsql_drop", "pgsql_dump", "pgsql_exists", + "pgsql_grant", "pgsql_load", "pgsql_user", ) @@ -168,6 +169,58 @@ def pgsql_exists(database, **kwargs): return command +def pgsql_grant(to, database=None, privileges="ALL", schema=None, table=None, **kwargs): + """Grant privileges to a user. + + :param to: The username to which privileges are granted. + :type to: str + + :param database: The database name. Required. + :type database: str + + :param privileges: The privileges to be granted. See https://www.postgresql.org/docs/current/sql-grant.html + :type privileges: str + + :param schema: The schema to which the privileges apply. + :type schema: str + + :param table: The table name to which privileges apply. + :type table: str + + .. note:: + A schema or table is required and the privileges must be compatible with the target object. + + """ + if database is None: + raise InvalidInput("Database is required.") + + kwargs.setdefault("comment", "grant postgres privileges to %s" % to) + kwargs['dbname'] = database + + if schema is not None: + target = "SCHEMA %s" % schema + elif table is not None: + target = "TABLE %s" % table + else: + raise InvalidInput("Either schema or table is required.") + + _privileges = privileges + if privileges.lower() == "all": + _privileges = "ALL PRIVILEGES" + + # See https://www.postgresql.org/docs/current/sql-grant.html + sql = "GRANT %(privileges)s ON %(target)s TO %(user)s" % { + 'privileges': _privileges, + 'target': target, + 'user': to, + } + + command = pgsql("psql", **kwargs) + command.statement += ' -c "%s"' % sql + + return command + + def pgsql_load(database, path, **kwargs): """Load data into a PostgreSQL database. @@ -240,6 +293,7 @@ PGSQL_MAPPINGS = { 'pgsql.drop': pgsql_drop, 'pgsql.dump': pgsql_dump, 'pgsql.exists': pgsql_exists, + 'pgsql.grant': pgsql_grant, # 'pgsql.sql': pgsql_exec, 'pgsql.user': pgsql_user, } diff --git a/scripttease/lib/commands/posix.py b/scripttease/lib/commands/posix.py index bd53917..566cb62 100644 --- a/scripttease/lib/commands/posix.py +++ b/scripttease/lib/commands/posix.py @@ -27,7 +27,7 @@ def archive(from_path, absolute=False, exclude=None, file_name="archive.tgz", st :type from_path: str :param absolute: Set to ``True`` to preserve the leading slash. - :type absolute: str + :type absolute: bool :param exclude: A pattern to be excluded from the archive. :type exclude: str @@ -193,7 +193,7 @@ def extract(from_path, absolute=False, exclude=None, strip=None, to_path=None, v :type from_path: str :param absolute: Set to ``True`` to preserve the leading slash. - :type absolute: str + :type absolute: bool :param exclude: A pattern to be excluded from the extraction. :type exclude: str @@ -416,7 +416,7 @@ def remove(path, force=False, recursive=False, **kwargs): return Command(" ".join(statement), **kwargs) -def replace(path, backup=".b", delimiter="/", find=None, replace=None, **kwargs): +def replace(path, backup=".b", delimiter="/", find=None, sub=None, **kwargs): """Find and replace text in a file. :param path: The path to the file to be edited. @@ -431,8 +431,8 @@ def replace(path, backup=".b", delimiter="/", find=None, replace=None, **kwargs) :param find: The old text. Required. :param find: str - :param replace: The new text. Required. - :type replace: str + :param sub: The new text. Required. + :type sub: str """ @@ -443,7 +443,7 @@ def replace(path, backup=".b", delimiter="/", find=None, replace=None, **kwargs) 'delimiter': delimiter, 'path': path, 'pattern': find, - 'replace': replace, + 'replace': sub, } template = "sed -i %(backup)s 's%(delimiter)s%(pattern)s%(delimiter)s%(replace)s%(delimiter)sg' %(path)s" diff --git a/scripttease/lib/commands/python.py b/scripttease/lib/commands/python.py index 9a5b4fb..62d89d5 100644 --- a/scripttease/lib/commands/python.py +++ b/scripttease/lib/commands/python.py @@ -7,7 +7,7 @@ def python_pip(name, op="install", upgrade=False, venv=None, version=3, **kwargs :param name: The name of the package. :type name: str - :param op: The operation to perform; ``install``, ``uninstall`` + :param op: The operation to perform; ``install``, ``remove`` :type op: str :param upgrade: Upgrade an installed package. diff --git a/tests/test_lib_commands_pgsql.py b/tests/test_lib_commands_pgsql.py index bd462dc..3d33902 100644 --- a/tests/test_lib_commands_pgsql.py +++ b/tests/test_lib_commands_pgsql.py @@ -23,6 +23,23 @@ def test_pgsql_exists(): assert "testing_exists" in s +def test_pgsql_grant(): + with pytest.raises(InvalidInput): + pgsql_grant("bob") + + with pytest.raises(InvalidInput): + pgsql_grant("bob", database="testing") + + c = pgsql_grant("bob", database="testing", schema="public") + s = c.get_statement() + assert '--dbname="testing"' in s + assert "GRANT ALL PRIVILEGES ON SCHEMA public TO bob" in s + + c = pgsql_grant("bob", database="testing", table="testing") + s = c.get_statement() + assert "GRANT ALL PRIVILEGES ON TABLE testing TO bob" in s + + def test_pgsql_drop(): c = pgsql_drop("testing") s = c.get_statement() diff --git a/tests/test_lib_commands_posix.py b/tests/test_lib_commands_posix.py index ea9add4..54fd80a 100644 --- a/tests/test_lib_commands_posix.py +++ b/tests/test_lib_commands_posix.py @@ -208,7 +208,7 @@ def test_scopy(): def test_sed(): - c = replace("/path/to/file.txt", find="testing", replace="123") + c = replace("/path/to/file.txt", find="testing", sub="123") s = c.get_statement() assert "sed -i .b" in s assert "s/testing/123/g" in s