turbulence 0.0.4
Use this in an "outer" airflow DAG to make assertions about an "inner" airflow DAG
Requires Python: >=3.6

# Turbulence

Turbulence is a collection of tools that use Apache Airflow for test automation.

![Jupiter's Red Spot and Surrounding Turbulence](turbulence.png)

**It's Partially Complete / Experimental / A Draft. This warning will be removed when it's ready.**

Turbulence thinks of test automation as an ETL pipeline:

- Extract: Get the latest tests and the latest artifacts to be tested
- Transform: Mix them together and get results
- Load: Update a dashboard somewhere with results

It was designed so that we could write DAGs that test Dags, but you can use it to write DAGs that test anything (as long as it runs in Kubernetes).

## Metaphor

Imagine that you're an astronomer living on one of Jupiter's moons; you study Jupiter's weather patterns.
The workflows that happen in your lab are **outer tests**.
They stay distant from whatever you're testing and they happen in an environment that is relatively stable.

Sometimes, you launch probes into Jupiter. The workflows that happen onboard these probes are **inner tests**.
They happen in disposable environments, and they tell you things that you couldn't learn from afar.

![Outer tests carried out through telescopes on Ganymede, inner tests as disposable probes launched towards Jupiter](outerinner.png)

This inner-outer language is used to distinguish between Kubernetes resources.
It's especially helpful if you have Airflow on both sides--then the outer Airflow gets a stable version and the inner Airflows get the candidate version.

## Local Dependencies

You'll need git, python3.6 or higher, kubectl configured to work with a cluster, and helm.
The cluster will need persistent volume claims and dns enabled.

Turbulence deploys a container registry into your cluster and stages images there.
There's a TODO for securing that registry.
In the meantime, you'll need to configure the underlying container registry to trust it even though it's insecure.

docker: https://docs.docker.com/registry/insecure/
containerd: https://stackoverflow.com/a/65682053/1054322

## Test Dependencies

If your outer tests depend on artifacts that publish new versions periodically, like...

- other git repos
- images in a container registry
- packeges installed via apps like `apt`, `brew`, or `pip`

...then you might want to have one of the DAGs that runs alongside your outer tests periodically check those sources for updates.
When updates are found, make a commit with a new version.

This way, historical test results can be recreated by an outer airflow.
Just create a branch and the commit-of-interest

## The `tblnc` command

`tblnc` bundles together some automation for making this plan work.

| `tblnc` verb | Description                                                                                                                                     |
| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `init`       | Prepares a git repo to deploy an outer airflow instance and prepares the current kubectl context to receive it.                                 |
| `update`     | Updates the repo to include specific-version references to any dependencies. Creates a PR with the changes and merges it if no conflicts exist. |
| `stage`      | Creates a kubernetes namespace and prepares it to house a particular airflow version                                                            |
| `clean`      | Deletes a kubernetes namespace along with its contents                                                                                          |
| `deploy`     | Creates an airflow deployment in the target namespce                                                                                            |

If you're interacting with the outer enviroment, you'll run `tblnc` commands from your local workstation.
If you're writing DAGs **in** the outer environment **for** manipulating an inner environment, you'll run `tblnc` from an Airflow Bash operator, or call its underlying function from an Airflow Python operator.

For instance, here are how the verbs are reused when turbulence is used to test airflow deployments:

![tblnc verbs used in different contexts](reuse.png)

If you're testing something else, your outer DAG might not call `tblnc deploy`--since that will give you an airflow deployment.
Instead you'll need to automate the deployment of your app into the inner environment by hand.