# Client usage

## Core surfaces

`OmniClient` and `AsyncOmniClient` expose:

- `resources`: generic resource CRUD/list/watch APIs.
- `management`: management RPC APIs (`kubeconfig`, `talosconfig`, `machine_logs`, etc.).
- `oidc`: OIDC RPC facade.
- `auth`: auth-key lifecycle APIs.
- `raw`: low-level typed RPC calls.

## Unified sync/async pattern

`OmniClient` sync methods are unprefixed and async methods are prefixed with `a`.

```python
from omni import OmniClient

client = OmniClient()

# Sync
kcfg = client.get_kubeconfig(service_account=False)

# Async on same object
kcfg_async = await client.aget_kubeconfig(service_account=False)
```

## Resource APIs

```python
payload = client.resources.get(
    {
        "namespace": "default",
        "type": "ClusterStatuses.omni.sidero.dev",
        "id": "cluster-a",
    }
)
```

## Retry and caching defaults

- Retry attempts: `4`
- Retried statuses: `429, 500, 502, 503, 504`
- Default cache: enabled, conservative allowlist, short TTLs
- Cache invalidation: mutation-aware by service prefix

## Context overrides

```python
from omni import use_instance, use_cluster, get_sync_client

with use_instance("staging"), use_cluster("cluster-b"):
    client = get_sync_client()
    print(client.get_cluster_status("cluster-b"))
```

## Common management tasks

### Download kubeconfig for a cluster

```python
import base64
from pathlib import Path
from omni import OmniClient

client = OmniClient()
payload = client.management.kubeconfig(
    {"service_account": False, "break_glass": False},
    metadata={"cluster": "cluster-a"},
)
Path("cluster-a.kubeconfig").write_bytes(base64.b64decode(payload["kubeconfig"]))
client.close()
```

### Ensure managed talosconfig for talosctl workflows

```python
from omni import OmniClient

client = OmniClient()
path = client.ensure_talosconfig(cluster="cluster-a", ttl_seconds=300)
print(path)
client.close()
```

### Service account lifecycle

```python
from omni import OmniClient

client = OmniClient()
created = client.management.create_service_account({"name": "ci-bot"})
listed = client.management.list_service_accounts()
renewed = client.management.renew_service_account({"name": "ci-bot"})
print(created, listed, renewed)
client.close()
```

### Join token creation for machine registration

```python
from omni import OmniClient

client = OmniClient()
token = client.management.create_join_token({"name": "bootstrap", "ttl": "3600s"})
print(token)
client.close()
```

### Stream audit log data (async)

```python
import asyncio
import base64
from omni import AsyncOmniClient

async def main() -> None:
    client = AsyncOmniClient()
    async for event in client.management.read_audit_log(
        {"start_time": "2026-01-01", "end_time": "2026-01-02"}
    ):
        data = event.get("audit_log")
        if isinstance(data, str):
            print(base64.b64decode(data).decode("utf-8"), end="")
    await client.aclose()

asyncio.run(main())
```
