# pytest-kind
[![Build Status](https://travis-ci.com/hjacobs/pytest-kind.svg?branch=master)](https://travis-ci.com/hjacobs/pytest-kind)
[![PyPI](https://img.shields.io/pypi/v/pytest-kind)](https://pypi.org/project/pytest-kind/)
![PyPI - Python Version](https://img.shields.io/pypi/pyversions/pytest-kind)
![License](https://img.shields.io/github/license/hjacobs/pytest-kind)
![CalVer](https://img.shields.io/badge/calver-YY.MM.MICRO-22bfda.svg)
Test your Python Kubernetes app/operator end-to-end with [kind](https://kind.sigs.k8s.io/) and [pytest](https://pytest.org).
`pytest-kind` is a plugin for pytest which provides the `kind_cluster` fixture.
The fixture will install kind 0.17.0, create a Kubernetes 1.25 cluster, and provide convenience functionality such as port forwarding.
## Usage
Install `pytest-kind` via pip or via [poetry](https://poetry.eustace.io/), e.g.:
```
poetry add --dev pytest-kind
```
Write your pytest functions and use the provided `kind_cluster` fixture, e.g.:
```python
def test_kubernetes_version(kind_cluster):
assert kind_cluster.api.version == ('1', '25')
```
To load your custom Docker image and apply deployment manifests:
```python
import requests
from pykube import Pod
def test_myapp(kind_cluster):
kind_cluster.load_docker_image("myapp")
kind_cluster.kubectl("apply", "-f", "deployment.yaml")
kind_cluster.kubectl("rollout", "status", "deployment/myapp")
# using Pykube to query pods
for pod in Pod.objects(kind_cluster.api).filter(selector="app=myapp"):
assert "Sucessfully started" in pod.logs()
with kind_cluster.port_forward("service/myapp", 80) as port:
r = requests.get(f"http://localhost:{port}/hello/world")
r.raise_for_status()
assert r.text == "Hello world!"
```
See the `examples` directory for sample projects and also check out [kube-web-view](https://codeberg.org/hjacobs/kube-web-view) which uses pytest-kind for its e2e tests.
## KindCluster object
The `kind_cluster` fixture is an instance of the KindCluster class with the following methods:
* `load_docker_image(docker_image)`: load the specified Docker image into the kind cluster
* `kubectl(*args)`: run the `kubectl` binary against the cluster with the specified arguments. Returns the process output as string.
* `port_forward(service_or_pod_name, remote_port, *args)`: run "kubectl port-forward" for the given service/pod and return the (random) local port. To be used as context manager ("with" statement). Pass the namespace as additional args to kubectl via "-n", "mynamespace".
KindCluster has the following attributes:
* `name`: the kind cluster name
* `kubeconfig_path`: the path to the Kubeconfig file to access the cluster
* `kind_path`: path to the `kind` binary
* `kubectl_path`: path to the `kubectl` binary
* `api`: [pykube](https://pykube.readthedocs.io/) HTTPClient instance to access the cluster from Python
You can also use KindCluster directly without pytest:
```python
from pytest_kind import KindCluster
cluster = KindCluster("myclustername")
cluster.create()
cluster.kubectl("apply", "-f", "..")
# ...
cluster.delete()
```
## Pytest Options
The kind cluster name can be set via the `--cluster-name` CLI option.
The kind cluster is deleted after each pytest session, you can keep the cluster by passing `--keep-cluster` to pytest.
Note that you can use the `PYTEST_ADDOPTS` environment variable to pass these options to pytest. This also works if you call pytest from a Makefile:
```bash
# for test debugging: don't delete the kind cluster
PYTEST_ADDOPTS=--keep-cluster make test
```
## Notes
* The `kind_cluster` fixture is session-scoped, i.e. the same cluster will be used across all test modules/functions.
* The `kind` and `kubectl` binaries will be downloaded once to the local directory `./.pytest-kind/{cluster-name}/`. You can use them to interact with the cluster (e.g. when `--keep-cluster` is used).
* Some cluster pods might not be ready immediately (e.g. kind's CoreDNS take a moment), add wait/poll functionality as required to make your tests predictable.
Raw data
{
"_id": null,
"home_page": "https://codeberg.org/hjacobs/pytest-kind",
"name": "pytest-kind",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": "",
"keywords": "",
"author": "Henning Jacobs",
"author_email": "henning@jacobs1.de",
"download_url": "https://files.pythonhosted.org/packages/28/bc/5816716a372636e90251bbf81a2d51c2eb340dc77cb5e7237c1a455fa3f4/pytest-kind-22.11.1.tar.gz",
"platform": null,
"description": "# pytest-kind\n\n[![Build Status](https://travis-ci.com/hjacobs/pytest-kind.svg?branch=master)](https://travis-ci.com/hjacobs/pytest-kind)\n[![PyPI](https://img.shields.io/pypi/v/pytest-kind)](https://pypi.org/project/pytest-kind/)\n![PyPI - Python Version](https://img.shields.io/pypi/pyversions/pytest-kind)\n![License](https://img.shields.io/github/license/hjacobs/pytest-kind)\n![CalVer](https://img.shields.io/badge/calver-YY.MM.MICRO-22bfda.svg)\n\nTest your Python Kubernetes app/operator end-to-end with [kind](https://kind.sigs.k8s.io/) and [pytest](https://pytest.org).\n\n`pytest-kind` is a plugin for pytest which provides the `kind_cluster` fixture.\nThe fixture will install kind 0.17.0, create a Kubernetes 1.25 cluster, and provide convenience functionality such as port forwarding.\n\n\n## Usage\n\nInstall `pytest-kind` via pip or via [poetry](https://poetry.eustace.io/), e.g.:\n\n```\npoetry add --dev pytest-kind\n```\n\nWrite your pytest functions and use the provided `kind_cluster` fixture, e.g.:\n\n```python\ndef test_kubernetes_version(kind_cluster):\n assert kind_cluster.api.version == ('1', '25')\n```\n\nTo load your custom Docker image and apply deployment manifests:\n\n```python\nimport requests\nfrom pykube import Pod\n\ndef test_myapp(kind_cluster):\n kind_cluster.load_docker_image(\"myapp\")\n kind_cluster.kubectl(\"apply\", \"-f\", \"deployment.yaml\")\n kind_cluster.kubectl(\"rollout\", \"status\", \"deployment/myapp\")\n\n # using Pykube to query pods\n for pod in Pod.objects(kind_cluster.api).filter(selector=\"app=myapp\"):\n assert \"Sucessfully started\" in pod.logs()\n\n with kind_cluster.port_forward(\"service/myapp\", 80) as port:\n r = requests.get(f\"http://localhost:{port}/hello/world\")\n r.raise_for_status()\n assert r.text == \"Hello world!\"\n```\n\nSee the `examples` directory for sample projects and also check out [kube-web-view](https://codeberg.org/hjacobs/kube-web-view) which uses pytest-kind for its e2e tests.\n\n\n## KindCluster object\n\nThe `kind_cluster` fixture is an instance of the KindCluster class with the following methods:\n\n* `load_docker_image(docker_image)`: load the specified Docker image into the kind cluster\n* `kubectl(*args)`: run the `kubectl` binary against the cluster with the specified arguments. Returns the process output as string.\n* `port_forward(service_or_pod_name, remote_port, *args)`: run \"kubectl port-forward\" for the given service/pod and return the (random) local port. To be used as context manager (\"with\" statement). Pass the namespace as additional args to kubectl via \"-n\", \"mynamespace\".\n\nKindCluster has the following attributes:\n\n* `name`: the kind cluster name\n* `kubeconfig_path`: the path to the Kubeconfig file to access the cluster\n* `kind_path`: path to the `kind` binary\n* `kubectl_path`: path to the `kubectl` binary\n* `api`: [pykube](https://pykube.readthedocs.io/) HTTPClient instance to access the cluster from Python\n\nYou can also use KindCluster directly without pytest:\n\n```python\nfrom pytest_kind import KindCluster\n\ncluster = KindCluster(\"myclustername\")\ncluster.create()\ncluster.kubectl(\"apply\", \"-f\", \"..\")\n# ...\ncluster.delete()\n```\n\n\n## Pytest Options\n\nThe kind cluster name can be set via the `--cluster-name` CLI option.\n\nThe kind cluster is deleted after each pytest session, you can keep the cluster by passing `--keep-cluster` to pytest.\n\nNote that you can use the `PYTEST_ADDOPTS` environment variable to pass these options to pytest. This also works if you call pytest from a Makefile:\n\n```bash\n# for test debugging: don't delete the kind cluster\nPYTEST_ADDOPTS=--keep-cluster make test\n```\n\n\n## Notes\n\n* The `kind_cluster` fixture is session-scoped, i.e. the same cluster will be used across all test modules/functions.\n* The `kind` and `kubectl` binaries will be downloaded once to the local directory `./.pytest-kind/{cluster-name}/`. You can use them to interact with the cluster (e.g. when `--keep-cluster` is used).\n* Some cluster pods might not be ready immediately (e.g. kind's CoreDNS take a moment), add wait/poll functionality as required to make your tests predictable.\n",
"bugtrack_url": null,
"license": "GPL-3.0+",
"summary": "Kubernetes test support with KIND for pytest",
"version": "22.11.1",
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"md5": "abd790716ca4d74928a43cd2f915d95e",
"sha256": "35fd99e4f94e0374834b5893ee4a95e33ad5dc1c18080356f01fadf21224e830"
},
"downloads": -1,
"filename": "pytest_kind-22.11.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "abd790716ca4d74928a43cd2f915d95e",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 18530,
"upload_time": "2022-11-30T17:06:08",
"upload_time_iso_8601": "2022-11-30T17:06:08.080091Z",
"url": "https://files.pythonhosted.org/packages/7d/f2/c9eda764e0a32b8c14eab539d6dcb409d7b1cabaceb5caa9db89c769b2f0/pytest_kind-22.11.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"md5": "85d27f3b4035580a04ef7b7b0fd225dc",
"sha256": "ae7a4c753fcbbf9e44a0cc587d5219a0b8b2b1e7bcc9cbe14234f745dd5db681"
},
"downloads": -1,
"filename": "pytest-kind-22.11.1.tar.gz",
"has_sig": false,
"md5_digest": "85d27f3b4035580a04ef7b7b0fd225dc",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 18014,
"upload_time": "2022-11-30T17:06:06",
"upload_time_iso_8601": "2022-11-30T17:06:06.734579Z",
"url": "https://files.pythonhosted.org/packages/28/bc/5816716a372636e90251bbf81a2d51c2eb340dc77cb5e7237c1a455fa3f4/pytest-kind-22.11.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2022-11-30 17:06:06",
"github": false,
"gitlab": false,
"bitbucket": false,
"lcname": "pytest-kind"
}