Reusable utilities for Pysae Python CLIs (k8s pod dispatch, …).
Project description
pysae-cli-tools
Reusable utilities for Pysae Python CLIs.
Installation
pip install pysae-cli-tools
# or
poetry add pysae-cli-tools
What's included
pysae_cli_tools.k8s — run any Typer command in an ephemeral pod
The @k8s_support decorator injects three flags into a Typer command —
--k8s, --k8s-environment {dev|prod}, --k8s-from-local-sources — and
dispatches the call into a freshly-spawned Kubernetes pod when --k8s is set.
It is meant for CLIs that need to run inside the same network as their target
infrastructure (private-link databases, VPC-only APIs, …) without rewriting the
command for kubectl run.
Usage with build_k8s_support (recommended)
Most projects share the same K8sConfig across every decorated command —
declare it once and reuse the bound decorator everywhere:
from pathlib import Path
from typer import Typer
from pysae_cli_tools.k8s import K8sConfig, build_k8s_support
K8S_CONFIG = K8sConfig(
default_image="<registry>/<project>:latest",
project_root=Path(__file__).resolve().parents[1],
copy_paths=("my_pkg", "pyproject.toml", "poetry.lock"),
install_script=(
"apt-get update -qq && pip install poetry && "
"poetry config virtualenvs.create false && "
"poetry install --only main --no-interaction"
),
forwarded_envvars=("MY_API_KEY", "MY_DB_URI"),
redacted_options=("--api-key", "--password"),
env_secret_bindings={
"dev": {"MONGO_URI": "k8s:secret:dev/dev-secrets:api-mongo-uri"},
"prod": {"MONGO_URI": "k8s:secret:prod/prod-secrets:api-mongo-uri"},
},
)
k8s_support = build_k8s_support(K8S_CONFIG)
app = Typer()
@app.command()
@k8s_support()
def my_command() -> None:
...
@app.command()
@k8s_support(pod_name_prefix="my-second-command") # override per-command
def my_second_command() -> None:
...
Usage with the explicit form
When you want to use a different config per command, pass it directly:
from pysae_cli_tools.k8s import K8sConfig, k8s_support
@app.command()
@k8s_support(config=K8S_CONFIG)
def my_command() -> None:
...
Per-environment secret bindings
K8sConfig.env_secret_bindings maps an environment value to a dict of
envvar -> value-or-pattern. Values can be:
- a literal string forwarded verbatim into the pod,
- a
k8s:secret:[<namespace>/]<secret-name>:<key>reference resolved viakubectl get secreton the operator's machine before the pod is created (base64-decoded automatically), - a
k8s:secret:mount:[<namespace>/]<secret-name>:<key>reference, which materialises as asecretKeyRefentry in the pod spec — the value never transits through the operator's machine, the kubelet reads it directly from the API server. The secret must live in the pod's namespace (no cross-namespacesecretKeyRef), and the pod's ServiceAccount must have RBACget secretson it. Mount bindings are skipped by the eager-inject hook, so they cannot serve a requiredArgument(envvar=…)— useOption(envvar=…)with a default, or a non-mount form, when the value must be available during Typer's argv parsing, - an
aws:secret:[<region>:]<secret-id>:<key>reference resolved viaaws secretsmanager get-secret-valueon the operator's machine, or - a
Callable[[Sequence[str]], str]that receives the filtered argv and returns one of the above forms.
Local environment wins: if the operator already exported the envvar locally, that value is propagated as-is. Kubectl resolution is the fallback, not the override. This matters for two reasons:
Argument(envvar="X")in Typer keeps working in both modes — the eager-inject hook seedsos.environbefore Typer parses argv.- The operator can override a binding for a one-off run without editing the config.
Use forwarded_envvars for simple value-only propagation (no kubectl
fallback) and env_secret_bindings whenever you want the convenience
of pulling from a Kubernetes secret automatically.
What happens at runtime
When --k8s is set on the command line, the decorator:
- Spawns an ephemeral pod using
K8sConfig.default_image(or the Dockerfile base image when--k8s-from-local-sourcesis also set). - Forwards every envvar listed in
K8sConfig.forwarded_envvarsfrom your local shell into the pod'senvblock. - Runs
python -m <your.cli.module> <subcommand> <filtered argv>inside the pod, with values matchingK8sConfig.redacted_optionsmasked in the[K8S] Running:log line. - Streams stdout/stderr back to your terminal and deletes the pod on exit.
See pysae_cli_tools/k8s/config.py for the
complete K8sConfig reference.
Development
poetry install
poetry run pre-commit install
poetry run pytest
CI publishes a new version to PyPI on every push to main — see
.gitlab-ci.yml. The version is computed from
git describe via pysae_cli_tools.compute_version.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pysae_cli_tools-0.1.9.tar.gz.
File metadata
- Download URL: pysae_cli_tools-0.1.9.tar.gz
- Upload date:
- Size: 18.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.3.4 CPython/3.12.13 Linux/6.12.80-106.156.amzn2023.x86_64
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c10cb2b5d5cdc5ed5fb25b6342de3e803ee595c867852e251ffadcdc2b152cf0
|
|
| MD5 |
785572808ad9c4a490d7bf3cf5bf8ab6
|
|
| BLAKE2b-256 |
1b03cb0c6094cbf9b318926cfec23a81d4055bcf08b2cbca142b3a04765218f5
|
File details
Details for the file pysae_cli_tools-0.1.9-py3-none-any.whl.
File metadata
- Download URL: pysae_cli_tools-0.1.9-py3-none-any.whl
- Upload date:
- Size: 19.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.3.4 CPython/3.12.13 Linux/6.12.80-106.156.amzn2023.x86_64
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
01faf7729d8d6e3166d992870da62dfaa5f92a647784801b92e8971596ff77e1
|
|
| MD5 |
2a483a12c115faeb6c6ed148d4b172bb
|
|
| BLAKE2b-256 |
fb2881dbe02141d05f63e04ef899ef43b7c338e6bf64027d1432948eb4143df0
|