Skip to content
This repository has been archived by the owner on Jan 14, 2024. It is now read-only.

Commit

Permalink
#66: Update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
blackandred committed Aug 15, 2021
1 parent 8cb5195 commit 677dff7
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 19 deletions.
56 changes: 56 additions & 0 deletions docs/source/extending-tasks.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,28 @@
Extending tasks
===============

Introduction
------------

RKD is designed to provide ready-to-configure automations. In practice you can install almost ready set of tasks using Python's PIP tool, then adjust those tasks to your needs.

Every Base Task implements some mechanism, in this chapter we will use Docker Container as an example.

::

Given you have a Base Task RunInContainerBaseTask, it lets you do something, while a container is running.
You can execute commands in container, copy files between host and the container.

According to the RunInContainerBaseTask's documentation you need to extend the it.
Which means to make your own task that extends RunInContainerBaseTask as a base,
then override a method, put your code.

Voilà! Your own task basing on RunInContainerBaseTask is now ready to be executed!


Practical tips
--------------

In order to successfully extend a Base Task a few steps needs to be marked.
Check Base Task documentation, especially for:

Expand Down Expand Up @@ -34,6 +56,10 @@ There are three decorators that allows to decide if the parent method will be ex
Not all methods supports decorators. For example argument parsing always inherits argument parsing from parent.
Decorators can be used for configure, compile, execute, inner_execute.

.. WARNING::
Using multiple decorators for single method is not allowed and leads to syntax validation error.


.. tabs::

.. tab:: YAML
Expand All @@ -59,3 +85,33 @@ There are three decorators that allows to decide if the parent method will be ex
print('BEFORE PARENT')
super().execute(ctx) # make a parent method call
print('AFTER PARENT')
Example #1: Using inner_execute
-------------------------------

Check :ref:`RunInContainerBaseTask` documentation first. It says that execute() should not be overridden, but inner_execute() should be used instead.

.. include:: ../../src/core/rkd/core/standardlib/docker.py
:start-after: <sphinx:extending-tasks>
:end-before: # </sphinx:extending-tasks>


Example #2: Advanced - extending a task that extends other task
---------------------------------------------------------------

In Example #1 there is a *base task that runs something inside a docker container*, going further in Example #2 there is a task that runs any code in a PHP container.

**Architecture:**

- Our example creates a Task from :ref:`PhpScriptTask` (we extend it, and create a "runnable" Task from it)
- :code:`rkd.php.script.PhpScriptTask` extends :code:`rkd.core.standardlib.docker.RunInContainerBaseTask`

Again, to properly prepare your task basing on existing Base Task check the Base Task documentation for tips.
In case of :ref:`PhpScriptTask` the documentation says the parent :code:`inner_execute` method should be executed to still allow providing PHP code via stdin.
To coexist parent and new method in place of :code:`inner_execute` just use one of decorators to control the inheritance behavior.

**Complete example:**

.. include:: ../../src/php/rkd/php/script.py
:start-after: <sphinx:extending-tasks>
:end-before: # </sphinx:extending-tasks>
55 changes: 50 additions & 5 deletions docs/source/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ Tasks arguments usage in shell and in scripts

.. code:: bash
rkd :task1 :task2
./rkdw :task1 :task2
**Multiple tasks with different switches:**

.. code:: bash
rkd :task1 --hello :task2 --world --become=root
./rkdw :task1 --hello :task2 --world --become=root
Second task will run as root user, additionally with :code:`--world` parameter.
Expand All @@ -40,7 +40,7 @@ Both tasks will receive switch "--hello"
# expands to:
# :task1 --hello
# :task2 --hello
rkd @ --hello :task1 :task2
./rkdw @ --hello :task1 :task2
# handy, huh?
Expand All @@ -56,7 +56,7 @@ Operator "@" can set switches anytime, it can also clear or replace switches in
# :task3
# :task4 --world
# :task5 --world
rkd @ --hello :task1 :task2 @ :task3 @ --world :task4 :task5
./rkdw @ --hello :task1 :task2 @ :task3 @ --world :task4 :task5
**Written as a pipeline (regular bash syntax)**
Expand All @@ -65,7 +65,7 @@ It's exactly the same example as above, but written multiline. It's recommended

.. code:: bash
rkd @ --hello \
./rkdw @ --hello \
:task1 \
:task2 \
@
Expand All @@ -74,3 +74,48 @@ It's exactly the same example as above, but written multiline. It's recommended
:task4 \
:task5
Advanced: Blocks for error handling
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Blocks allow to retry single failed task, or a group of tasks, execute a failure or rescue task.

.. TIP::
Blocks cannot be nested.

**Retry a task - @retry**

Retry task until it will return success, up to defined retries.
If there are multiple tasks, then a single task is repeated, not a whole block.

.. code:: bash
./rkdw '{@retry 3}' :unstable-task '{/@}'
**Retry a block (set of tasks) - @retry-block**

Works very similar to @retry, but in case, when at least one task fails - all tasks in the block are repeated.


.. code:: bash
./rkdw '{@retry-block 3}' :unstable-task :task2 '{/@}'
**Rescue - @rescue**

When a failure happens in any of tasks, then those tasks are interrupted and a rollback task is executed.
Whole block status depends on the rollback task status. After a successful rollback execution next tasks from outside of the blocks are normally executed.

.. code:: bash
./rkdw :db:shutdown :db:backup '{@rescue :db:restore}' :db:upgrade '{/@}' :db:start
**Error - @error**

When at least one task fails, then a error task is notified and the execution is stopped.

.. code:: bash
./rkdw '{@error :notify "Task failed!"}' :some-task :some-other-task '{/@}'
1 change: 1 addition & 0 deletions docs/source/standardlib/docker.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
Docker
======

.. _RunInContainerBaseTask:
RunInContainerBaseTask
~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down
1 change: 1 addition & 0 deletions docs/source/standardlib/php.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
PHP
===

.. _PhpScriptTask:
PhpScriptTask
~~~~~~~~~~~~~

Expand Down
47 changes: 36 additions & 11 deletions src/core/rkd/core/standardlib/docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,48 @@

class RunInContainerBaseTask(ExtendableTaskInterface, ABC):
"""
RunInContainerBaseTask
----------------------
# <sphinx:extending-tasks>
Allows to work inside of a temporary docker container.
Configuration:
mount(): Mount directories/files as volumes
add_file_to_copy(): Copy given files to container before container starts
user: Container username, defaults to "root"
shell: Shell binary path, defaults to "/bin/sh"
docker_image: Full docker image name with registry (optional), group, image name and tag
entrypoint: Entrypoint
command: Command to execute on entrypoint
- mount(): Mount directories/files as volumes
- add_file_to_copy(): Copy given files to container before container starts
- user: Container username, defaults to "root"
- shell: Shell binary path, defaults to "/bin/sh"
- docker_image: Full docker image name with registry (optional), group, image name and tag
- entrypoint: Entrypoint
- command: Command to execute on entrypoint
Runtime:
copy_to_container(): Copy files/directory to container immediately
in_container(): Execute inside container
- copy_to_container(): Copy files/directory to container immediately
- in_container(): Execute inside container
Example:
.. code:: yaml
version: org.riotkit.rkd/yaml/v1
imports:
- rkd.core.standardlib.docker.RunInContainerBaseTask
tasks:
:something-in-docker:
extends: rkd.core.standardlib.docker.RunInContainerBaseTask
configure: |
self.docker_image = 'php:7.3'
self.user = 'www-data'
self.mount(local='./build', remote='/build')
self.add_file_to_copy('build.php', '/build/build.php')
inner_execute: |
self.in_container('php build.php')
return True
# do not extend just "execute", because "execute" is used by RunInContainerBaseTask
# to spawn docker container, run inner_execute(), and after just destroy the container
# </sphinx:extending-tasks>
"""

docker_image: str
Expand Down
10 changes: 7 additions & 3 deletions src/php/rkd/php/script.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@

class PhpScriptTask(RunInContainerBaseTask):
"""
# <sphinx:extending-tasks>
Execute a PHP code (using a docker container)
Can be extended - this is a base task.
Inherits settings from `RunInContainerBaseTask`.
Configuration:
script: Path to script to load instead of stdin (could be a relative path)
version: PHP version. Leave None to use default 8.0-alpine version
- script: Path to script to load instead of stdin (could be a relative path)
- version: PHP version. Leave None to use default 8.0-alpine version
Example of usage:
Expand All @@ -35,12 +37,14 @@ class PhpScriptTask(RunInContainerBaseTask):
configure@before_parent: |
self.version = '7.2-alpine'
inner_execute@after_parent: |
print('IM AFTER PARENT')
self.in_container('php --version')
print('IM AFTER PARENT. At first the PHP code from "input" will be executed.')
return True
input: |
var_dump(getcwd());
var_dump(phpversion());
# </sphinx:extending-tasks>
"""

script: Optional[str]
Expand Down

0 comments on commit 677dff7

Please sign in to comment.