Skip to content

Commit

Permalink
improve contribution documentation
Browse files Browse the repository at this point in the history
Signed-off-by: Sylvain Hellegouarch <[email protected]>
  • Loading branch information
Lawouach committed Apr 9, 2024
1 parent ef9abaf commit df18cf1
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 89 deletions.
6 changes: 6 additions & 0 deletions sources/reference/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,9 @@ case a contributor account is breached.

Every project in the Chaos Toolkit and the Chaos Toolkit Incubator is licensed
under the [Apache License, Version 2.0](https://github.com/chaostoolkit/chaostoolkit/blob/master/LICENSE) and abides by the [Developer Certificate of Origin](https://developercertificate.org/) on all accepted commits to the `master` branch.


## Contributing code to an Existing Project

Contributions are alwasy welcome. You can help the maintainers and improve
merge by following a set of simple baseline [rules](./developing/guidelines.md).
192 changes: 109 additions & 83 deletions sources/reference/developing/guidelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Toolkit is implemented in Python so make sure to have the right tooling for it.

The most basics are:

* Python 3.6+ installed.
* Python 3.8+ installed.
* A virtual environment so you can deploy the dependencies in a specific
environment

Expand All @@ -25,30 +25,12 @@ such [The Hitchhiker’s Guide to Python][hitchhiker].

[hitchhiker]: http://docs.python-guide.org/en/latest/

#### The Ultimate Trick
Historically, Chaos Toolkit used [pip][pip] to manage its projects from a Python
dependencies and packages perspectives. However, we have now migrated
to [PDM][pdm] which provides a better all-in-one experience.

Whenever you code on one of the projects, you should run the following command
so that the project you are hacking on is part of your virtual environment
without being installed:

```console
cd <project-name>
python setup.py develop
```

Sometimes, your virtual env may be borked and not point to your development
directory. In that case, make sure to remove any previously installed version
of the project:

```console
pip uninstall <project-name>
```

Then make sure your virtual environment point at your local directory with:

```console
pip freeze
```
[pip]: https://pip.pypa.io/en/stable/
[pdm]: https://pdm-project.org/en/latest/

### GitHub

Expand All @@ -62,76 +44,120 @@ why.

[gh]: https://github.com/chaostoolkit/

### Chaos Toolkit Projects At A Glance

The Chaos Toolkit is made of several projects. The core ones are:

* [chaostoolkit](https://github.com/chaostoolkit/chaostoolkit): the CLI
* [chaostoolkit-lib](https://github.com/chaostoolkit/chaostoolkit-lib): the core
library that propels the CLI

Basically, those projects represent the Chaos Toolkit itself. However, the
toolkit is naked without extensions. The currently core extensions are:
### Code Contributions Good Practices

Whether you contribute documentation or code, you should try follow the
high-level rules here:

* One PR per functional change. Try to keep your PR focused

* A PR should always have the following:
* Signed commits (as per the [DCO][dco]) to notify the project you are
allowed to submit this code change
* A `CHANGELOG` entry. Do not set the version or date on the entry
* Tests wherever possible to control non-regression down the road and help
with maintainance
* Linted code. If the project uses [pdm][], you can run `pdm run format`
and `pdm run lint` usually
* Code must have the appropriate typing annotation

* What to look for in a contribution:
* Try to draw inspiration from other modules in the same extension or from
other extensions. Respect the style as much as possible and use the linter
to ensure you follow it
* If you had an entirely new module containing actions/probes, make sure
to make it discoverable by adding it to the `__init__.py` module of the
extension package. It usually already has existing entries.
* Make actions/probes not too complex, better to have more specific actions
sometimes. Otherwise, this increases the risk of breaking compatibility
when they change
* Be conservative in changes you make to existing actions/probes. We thrive
for backward compatibility
* Keep simple types for actions/probes arguments: string, integer, floats...
* Raise a Chaos Toolkit exception when you want to notify the user about
a particular error/edge case that will prevent the function from working
correctly
* Use the `logger` as much as needed, it helps figuring out what is going on.
However think of who will read these messages in the future, likely not
yourself
* The returned value of an action/probe must be JSON serializable by the
Python [json][] module


[dco]: https://developercertificate.org/
[json]: https://docs.python.org/3/library/json.html#module-json

Here is a typical action:

* [chaostoolkit-kubernetes](https://github.com/chaostoolkit/chaostoolkit-kubernetes)
* [chaostoolkit-addons](https://github.com/chaostoolkit/chaostoolkit-addons)

In addition, there are a
[bunch of incubating projects](https://github.com/chaostoolkit-incubator).

## Creating an Extension

Please review the various [approaches](../extending/approaches.md) to extend
the toolkit.

## Creating a Notification Plugin
```python
import logging
from typing import Any, Dict

The Chaos Toolkit triggers events while it runs. Those events may be forwarded
to any endpoint that you care for through HTTP or, when you need more control,
a full Python project.

There is no template for such a project yet but it is very close to an
extension project except it doesn't have probes and actions. You can therefore
start by cloning the [extension template project][ext] and start from there.
from chaoslib.exceptions import ActivityFailed
from chaoslib.types import Configuration, Secrets

[ext]: https://github.com/chaostoolkit/chaostoolkit-extension-template
__all__ = ["change_the_system"]

Instead, it should define a function in a module. That function takes two
parameters:
logger = logging.getLogger("chaostoolkit")

* the notification channel settings (coming from the
[Chaos Toolkit settings file](../usage/cli.md#create-the-settings-file)) as a dictionary
* the event payload as a Python dictionary which is documented
[here](https://github.com/chaostoolkit/chaostoolkit-lib/blob/master/chaoslib/notification.py#L97)

The event has a `payload` key which is the content associated to the event. It
can be one of:
def change_the_system(
address: str,
value: int,
configuration: Configuration = None,
secrets: Secrets = None
) -> Dict[str, Any]:
"""
Change the system in funny ways and return the information about
what changed
"""
if value < 0:
logger.debug(f"change_the_system got {value}")
raise ActivityFailed("value cannot be negative")

* `None` when there was no payload ()
* a string
* an [experiment](../api/experiment.md) dictionary
* an [journal](../api/journal.md) dictionary
# do something to your system with the given arguments

Three kind of events can be triggered: `started`, `completed` and `failed` for
each phase of the flow. Those events are defined
[here](https://github.com/chaostoolkit/chaostoolkit-lib/blob/master/chaoslib/notification.py#L21).
return {}
```

A typical notification callback function will look like this:
Since we have just added this action in a new module, we'll also make the
module discoverable as follows:

```python
from typing import Any, Dict

from chaoslib.notification import RunFlowEvent
from chaoslib.types import EventPayload
import logzero

def notify(settings: Dict[str, Any], event: EventPayload):
if event["name"] == RunFlowEvent.RunStarted.value:
logzero.info("Event phase " + event["phase"])
logzero.info("Event timestamp " + event["ts"])
logzero.info("Event payload " + event["payload"])
logzero.info("Event error " + event.get("error", "N/A"))
activities.extend(discover_actions("extension.actions"))
```

`logzero` is a third-party package that the Chaos Toolkit uses to log when
it runs.
This is done in the top-level `__init__.py` module of the extension in the
`discover` function. Usually, it already contains this function and you can
simply add the line above.

A typical CHANGELOG entry for this new action would be:

```markdown
## [Unreleased][]

[Unreleased]: https://github.com/....

### Added

* The `extension.actions.change_the_system` action to change the system. Use
it like this:

```json
"method": [
{
"name": "do-something",
"type": "action",
"provider": {
"type": "python",
"module": "extension.actions",
"func": "change_the_system",
"arguments": {
"address": "192.56.67.78",
"value": 56
}
}
}
]
```
12 changes: 6 additions & 6 deletions sources/reference/extending/extending-with-python.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,15 @@ Then you can exercise your discovery functionality using the `--no-install` flag

## Log From Your Extension

You can write to the Chaos Toolkit log by using the [logzero][] package.
You can write to the Chaos Toolkit log by using the [logging][] package
and the `chaostoolkit` logger.

[logzero]: https://logzero.readthedocs.io/en/latest/
[logging]: https://docs.python.org/3/library/logging.html#module-logging

```python
from logzero import logger
import logging

logger = logging.getLogger("chaostoolkit")

logger.info("Hello!")
```

Make sure to add `logzero` as an entry of the `requirements.txt` file of your
extension.

0 comments on commit df18cf1

Please sign in to comment.