pytest_kustomize 1.3.1
Parse and validate kustomize output
License: BSD-3-Clause
Requires Python: >=3.7

# pytest_kustomize

Parse and validate kustomize output


## Example

```python
from pytest_kustomize import resolve_configmaps, extract_externalsecret_data
import pytest


@pytest.mark.parametrize("environment, value", [
    ("staging", "shared-db.staging.example.com"),
    ("production", "myservice-db.production.example.com"),
])
def test_database_matches_environment(kustomize_resources, environment, value):
    config = resolve_configmaps(kustomize_resources[environment])
    for deployment in ["webui", "api"]:
        assert config[deployment]["db_host"] == value


def test_production_has_no_staging_vault_paths(kustomize_resources):
    for secret in extract_externalsecret_data(kustomize_resources["production"]).values():
        assert "staging" not in secret["key"]


@pytest.mark.parametrize("environment", ["staging", "production"])
def test_jq(kustomize_jq, environment):
    for apiVersion in kustomize_jq(
        """.[] | select(."kind"=="ConfigMap").apiVersion""", environment
    ):
        assert apiVersion == "v1"
```


## Usage

You can access the kustomize output as follows:

* The `kustomize_manifests` fixture returns a `dict[str, str]`, environment name: `kustomize build` output
* The `kustomize_resources` fixture returns a `dict[str, List[dict]]`, environment name: yaml-parsed output
* The `kustomize_jq` fixture returns a query helper which applies a ![jq query string](https://jqlang.org/) to the given environment and returns an instance of ![`jq._ProgramWithInput`](https://github.com/mwilliamson/jq.py?tab=readme-ov-file#output-methods).
  Only available by explicitly installing `jq` (or `pytest_kustomize[jq]`)

Optionally, define the directory where kustomize manifests are looked up by providing this fixture

```python
@pytest.fixture(scope="session")
def kustomize_root_directory():
    return "/path/to/kustomizations"
```

Default: `./k8s`


Optionally, define for which subdirectories manifests should be generated by providing this fixture

```python
@pytest.fixture(scope="session")
def kustomize_environment_names():
    return ["overlays/staging", "overlays/production"]
```

Default: All direct subdirectories that contain a `kustomization.yaml`


## API

The package provides these helper functions:

* `resolve_configmaps()` resolves `envFrom` references to `ConfigMap`s in `Deployment`s. It takes a list of yaml dicts (usually `kustomize_resources[environment]`) and returns a `dict[str, dict[str, str]]`, deployment+container name: {key: value}.
  The dict keys work as follows:
  * Containers are named `{deployment}-{container}`
  * Init Containers are named `{deployment}-init-{container}`
  * For convenience, the first container is also available just under the name `{deployment}`, and the first init container as `{deployment}-init`
* `extract_externalsecret_data()` extracts the `data` sections of all `ExternalSecret` resources. It takes a list of yaml dicts and returns `{"key_in_secret": {"key": "example/vault/path", "property": "token"}}`

These take an optional `name_transform` callable which defaults to `lambda x: x.rsplit('-', 1)[0]`, to normalize e.g. kustomize-generated `ConfigMap` names like `project-44fb7dkk64`.


## pytest_kustomize Changes

<!-- towncrier release notes start -->

## 1.3.1 (2025-12-08)

### 

- Make jq an optional dependency (jq)


## 1.3.0 (2025-12-08)

### 

- Make jq an optional dependency (jq)


## 1.2.0 (2025-10-02)

### 

- Allow querying manifests via jq


## 1.1.0 (2025-07-09)

### 

- Parse all containers and initContainers in `resolve_configmaps` (initcontainer)
- Normalize names by splitting on the last dash, not the first (nametrans)


## 1.0.0 (2025-07-03)

### 

- Initial release (initial)