# k8s.client

> A module of k8s's API.

The calls: create, get, delete, list and watch, for Pods, Services and Jobs in a namespace, and a pod's log.

```mojo
var k = Client(Config.load())
_ = k.create(PODS, '{"apiVersion": "v1", "kind": "Pod", ...}')
var pod = k.get(PODS, "smoke")                  # None if there's none
var w = k.watch(PODS, "app=smoke")
while True:
    var e = w.next()                            # None once the watch ends
    if not e or e.value().object.at("/status/phase").string_value() == "Succeeded":
        break
_ = k.delete_all(PODS, "app=smoke")
```

Objects go in as JSON text and come back as json's `Value`, so a caller
writes the manifests it needs and reads the fields it needs (`at` takes a
JSON pointer), and this tin knows no schema. An answer that isn't 2xx
raises `Error("k8s: <METHOD> <path>: <code> <reason>: <message>")` with the
API's own `Status` message, except a 404 from `get` and `delete`, which
answer None and False.

A watch is one long response of JSON lines, one event each (`ADDED`,
`MODIFIED`, `DELETED`, `ERROR`), which `Watch.next` reads as they arrive.
The server ends it after `timeout_seconds`; to see every change, list
first and watch from the list's `resource_version`, and on a watch that
ended, watch again from the last event's. A 410 (the version is too old)
raises; list again.

## Structs

### `Resource`

```mojo
struct Resource
```

A kind of namespaced object, by where the API serves it.

Implements: `Copyable`, `ImplicitlyCopyable`, `Movable`

Fields:

- `prefix: StaticString`: `/api/v1` for the core group, `/apis/<group>/<version>` otherwise.
- `plural: StaticString`

### `Listed`

```mojo
struct Listed
```

Implements: `Movable`

Fields:

- `items: List[Value]`
- `resource_version: String`: The list's, to watch from.

### `Event`

```mojo
struct Event
```

Implements: `Copyable`, `Movable`

Fields:

- `type: String`: `ADDED`, `MODIFIED`, `DELETED` or `ERROR`.
- `object: Value`: The object as it is after the change, or for `ERROR` a `Status`.

### `Watch`

```mojo
struct Watch
```

The events of one watch request, as they arrive.

Implements: `Movable`

Fields:

- `resource_version: String`: The last event's, to watch again from.

#### `__init__`

```mojo
def __init__(out self, var stream: HttpStreamResponse, path: String, since: String)
```

#### `next`

```mojo
def next(mut self) -> Optional[Event]
```

The next event, waiting for it; None once the server has ended the watch. An `ERROR` event raises.

#### `close`

```mojo
def close(mut self)
```

### `Client`

```mojo
struct Client
```

Calls to the API server `config` names, as its user.

Implements: `Movable`

Fields:

- `config: Config`

#### `__init__`

```mojo
def __init__(out self, var config: Config)
```

#### `create`

```mojo
def create(self, r: Resource, manifest: String, namespace: String = "") -> Value
```

Creates the object `manifest` describes, and returns it as the server made it.

#### `get`

```mojo
def get(self, r: Resource, name: String, namespace: String = "") -> Optional[Value]
```

#### `logs`

```mojo
def logs(self, pod: String, container: String = "", namespace: String = "") -> String
```

A pod's log, of its only container or of `container`; empty for a pod that's gone.

#### `delete`

```mojo
def delete(self, r: Resource, name: String, namespace: String = "", propagation: String = "Background") -> Bool
```

Deletes the object, and what it owns by `propagation` (`Background`, `Foreground` or `Orphan`); False if there was none.

#### `list`

```mojo
def list(self, r: Resource, selector: String = "", namespace: String = "") -> Listed
```

The objects whose labels match `selector` (`app=x,run=7`), or all of them.

#### `delete_all`

```mojo
def delete_all(self, r: Resource, selector: String, namespace: String = "") -> Int
```

Deletes every object matching `selector`, which mustn't be empty, and returns how many there were.

#### `watch`

```mojo
def watch(self, r: Resource, selector: String = "", resource_version: String = "", timeout_seconds: Int = Int(300), namespace: String = "") -> Watch
```

A watch of the objects matching `selector`, from `resource_version` (else from now, with an `ADDED` event for each that exists), until the server ends it after `timeout_seconds`.

## Functions

### `query_escape`

```mojo
def query_escape(s: String) -> String
```

`s` with everything but unreserved characters percent-encoded.

## Aliases

### `PODS`

```mojo
comptime PODS = Resource(StringSpan("/api/v1"), StringSpan("pods"))
```

### `SERVICES`

```mojo
comptime SERVICES = Resource(StringSpan("/api/v1"), StringSpan("services"))
```

### `JOBS`

```mojo
comptime JOBS = Resource(StringSpan("/apis/batch/v1"), StringSpan("jobs"))
```
