checkdk-cli 0.2.2__tar.gz → 0.2.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {checkdk_cli-0.2.2 → checkdk_cli-0.2.5}/PKG-INFO +45 -21
- {checkdk_cli-0.2.2 → checkdk_cli-0.2.5}/README.md +44 -20
- {checkdk_cli-0.2.2 → checkdk_cli-0.2.5}/checkdk_cli.egg-info/PKG-INFO +45 -21
- {checkdk_cli-0.2.2 → checkdk_cli-0.2.5}/checkdkcli/__init__.py +1 -1
- checkdk_cli-0.2.5/checkdkcli/commands/auth.py +110 -0
- {checkdk_cli-0.2.2 → checkdk_cli-0.2.5}/pyproject.toml +1 -1
- checkdk_cli-0.2.2/checkdkcli/commands/auth.py +0 -181
- {checkdk_cli-0.2.2 → checkdk_cli-0.2.5}/checkdk_cli.egg-info/SOURCES.txt +0 -0
- {checkdk_cli-0.2.2 → checkdk_cli-0.2.5}/checkdk_cli.egg-info/dependency_links.txt +0 -0
- {checkdk_cli-0.2.2 → checkdk_cli-0.2.5}/checkdk_cli.egg-info/entry_points.txt +0 -0
- {checkdk_cli-0.2.2 → checkdk_cli-0.2.5}/checkdk_cli.egg-info/requires.txt +0 -0
- {checkdk_cli-0.2.2 → checkdk_cli-0.2.5}/checkdk_cli.egg-info/top_level.txt +0 -0
- {checkdk_cli-0.2.2 → checkdk_cli-0.2.5}/checkdkcli/client.py +0 -0
- {checkdk_cli-0.2.2 → checkdk_cli-0.2.5}/checkdkcli/commands/__init__.py +0 -0
- {checkdk_cli-0.2.2 → checkdk_cli-0.2.5}/checkdkcli/commands/chaos.py +0 -0
- {checkdk_cli-0.2.2 → checkdk_cli-0.2.5}/checkdkcli/commands/docker.py +0 -0
- {checkdk_cli-0.2.2 → checkdk_cli-0.2.5}/checkdkcli/commands/init.py +0 -0
- {checkdk_cli-0.2.2 → checkdk_cli-0.2.5}/checkdkcli/commands/kubectl.py +0 -0
- {checkdk_cli-0.2.2 → checkdk_cli-0.2.5}/checkdkcli/commands/monitor.py +0 -0
- {checkdk_cli-0.2.2 → checkdk_cli-0.2.5}/checkdkcli/commands/playground.py +0 -0
- {checkdk_cli-0.2.2 → checkdk_cli-0.2.5}/checkdkcli/commands/predict.py +0 -0
- {checkdk_cli-0.2.2 → checkdk_cli-0.2.5}/checkdkcli/display.py +0 -0
- {checkdk_cli-0.2.2 → checkdk_cli-0.2.5}/checkdkcli/main.py +0 -0
- {checkdk_cli-0.2.2 → checkdk_cli-0.2.5}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: checkdk-cli
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.5
|
|
4
4
|
Summary: checkDK CLI – AI-powered Docker/Kubernetes issue detector and pod failure predictor
|
|
5
5
|
Author-email: checkDK Team <team@checkdk.app>
|
|
6
6
|
License: MIT
|
|
@@ -50,6 +50,29 @@ dependencies — it is a thin HTTP/WebSocket client with a rich terminal UI.
|
|
|
50
50
|
|
|
51
51
|
## Install
|
|
52
52
|
|
|
53
|
+
### npm (no Python required)
|
|
54
|
+
|
|
55
|
+
The easiest way to install for JavaScript / Node.js users.
|
|
56
|
+
Pre-compiled standalone binaries are distributed per-platform — nothing else needs to be installed.
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm install -g @checkdk/cli
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Supported platforms:
|
|
63
|
+
|
|
64
|
+
| Platform | Package |
|
|
65
|
+
| --------------------------- | --------------------------- |
|
|
66
|
+
| Linux x64 | `@checkdk/cli-linux-x64` |
|
|
67
|
+
| Linux arm64 | `@checkdk/cli-linux-arm64` |
|
|
68
|
+
| macOS x64 (Intel) | `@checkdk/cli-darwin-x64` |
|
|
69
|
+
| macOS arm64 (Apple Silicon) | `@checkdk/cli-darwin-arm64` |
|
|
70
|
+
| Windows x64 | `@checkdk/cli-win32-x64` |
|
|
71
|
+
|
|
72
|
+
After install, `checkdk` is available on your PATH immediately.
|
|
73
|
+
|
|
74
|
+
### pip / pipx (Python required)
|
|
75
|
+
|
|
53
76
|
```bash
|
|
54
77
|
# Recommended — isolated install, checkdk on PATH globally
|
|
55
78
|
pipx install checkdk-cli
|
|
@@ -58,6 +81,8 @@ pipx install checkdk-cli
|
|
|
58
81
|
pip install checkdk-cli
|
|
59
82
|
```
|
|
60
83
|
|
|
84
|
+
Requires Python 3.10 or later.
|
|
85
|
+
|
|
61
86
|
The `checkdk` command is available immediately after install.
|
|
62
87
|
No configuration required — the CLI talks to `https://checkdk.app/api` by default.
|
|
63
88
|
|
|
@@ -107,21 +132,21 @@ checkdk predict --cpu 93 --memory 91 --restarts 3 \
|
|
|
107
132
|
checkdk predict --cpu 85 --memory 70 --json # CI/scripting output
|
|
108
133
|
```
|
|
109
134
|
|
|
110
|
-
| Option
|
|
111
|
-
|
|
112
|
-
| `--cpu`
|
|
113
|
-
| `--memory`
|
|
114
|
-
| `--disk`
|
|
115
|
-
| `--latency`
|
|
116
|
-
| `--restarts`
|
|
117
|
-
| `--probe-failures` | 0
|
|
118
|
-
| `--cpu-pressure`
|
|
119
|
-
| `--mem-pressure`
|
|
120
|
-
| `--age`
|
|
121
|
-
| `--service`
|
|
122
|
-
| `--platform`
|
|
123
|
-
| `--no-ai`
|
|
124
|
-
| `--json`
|
|
135
|
+
| Option | Default | Description |
|
|
136
|
+
| ------------------ | -------- | --------------------------------- |
|
|
137
|
+
| `--cpu` | required | CPU usage % |
|
|
138
|
+
| `--memory` | required | Memory usage % |
|
|
139
|
+
| `--disk` | 50 | Disk usage % |
|
|
140
|
+
| `--latency` | 10 | Network latency ms |
|
|
141
|
+
| `--restarts` | 0 | Container restart count |
|
|
142
|
+
| `--probe-failures` | 0 | Liveness/readiness probe failures |
|
|
143
|
+
| `--cpu-pressure` | 0 | Node CPU pressure (0 or 1) |
|
|
144
|
+
| `--mem-pressure` | 0 | Node memory pressure (0 or 1) |
|
|
145
|
+
| `--age` | 60 | Pod age in minutes |
|
|
146
|
+
| `--service` | — | Service/pod name (label only) |
|
|
147
|
+
| `--platform` | docker | `docker` or `kubernetes` |
|
|
148
|
+
| `--no-ai` | — | Skip LLM, return ML result only |
|
|
149
|
+
| `--json` | — | Raw JSON output for scripting |
|
|
125
150
|
|
|
126
151
|
### Monitor (real-time)
|
|
127
152
|
|
|
@@ -152,10 +177,10 @@ Experiments: `cpu`, `memory`, `disk`, `network`, `pod-kill` (k8s only).
|
|
|
152
177
|
|
|
153
178
|
## Environment variables
|
|
154
179
|
|
|
155
|
-
| Variable
|
|
156
|
-
|
|
157
|
-
| `CHECKDK_API_URL` | `https://checkdk.app/api` | Backend API base URL
|
|
158
|
-
| `CHECKDK_TOKEN`
|
|
180
|
+
| Variable | Default | Description |
|
|
181
|
+
| ----------------- | ------------------------- | -------------------------------------------- |
|
|
182
|
+
| `CHECKDK_API_URL` | `https://checkdk.app/api` | Backend API base URL |
|
|
183
|
+
| `CHECKDK_TOKEN` | — | JWT auth token (set by `checkdk auth login`) |
|
|
159
184
|
|
|
160
185
|
The CLI auto-loads `~/.checkdk/.env` and `./.env` on startup.
|
|
161
186
|
|
|
@@ -183,4 +208,3 @@ pytest
|
|
|
183
208
|
# Lint
|
|
184
209
|
ruff check .
|
|
185
210
|
```
|
|
186
|
-
|
|
@@ -12,6 +12,29 @@ dependencies — it is a thin HTTP/WebSocket client with a rich terminal UI.
|
|
|
12
12
|
|
|
13
13
|
## Install
|
|
14
14
|
|
|
15
|
+
### npm (no Python required)
|
|
16
|
+
|
|
17
|
+
The easiest way to install for JavaScript / Node.js users.
|
|
18
|
+
Pre-compiled standalone binaries are distributed per-platform — nothing else needs to be installed.
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install -g @checkdk/cli
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Supported platforms:
|
|
25
|
+
|
|
26
|
+
| Platform | Package |
|
|
27
|
+
| --------------------------- | --------------------------- |
|
|
28
|
+
| Linux x64 | `@checkdk/cli-linux-x64` |
|
|
29
|
+
| Linux arm64 | `@checkdk/cli-linux-arm64` |
|
|
30
|
+
| macOS x64 (Intel) | `@checkdk/cli-darwin-x64` |
|
|
31
|
+
| macOS arm64 (Apple Silicon) | `@checkdk/cli-darwin-arm64` |
|
|
32
|
+
| Windows x64 | `@checkdk/cli-win32-x64` |
|
|
33
|
+
|
|
34
|
+
After install, `checkdk` is available on your PATH immediately.
|
|
35
|
+
|
|
36
|
+
### pip / pipx (Python required)
|
|
37
|
+
|
|
15
38
|
```bash
|
|
16
39
|
# Recommended — isolated install, checkdk on PATH globally
|
|
17
40
|
pipx install checkdk-cli
|
|
@@ -20,6 +43,8 @@ pipx install checkdk-cli
|
|
|
20
43
|
pip install checkdk-cli
|
|
21
44
|
```
|
|
22
45
|
|
|
46
|
+
Requires Python 3.10 or later.
|
|
47
|
+
|
|
23
48
|
The `checkdk` command is available immediately after install.
|
|
24
49
|
No configuration required — the CLI talks to `https://checkdk.app/api` by default.
|
|
25
50
|
|
|
@@ -69,21 +94,21 @@ checkdk predict --cpu 93 --memory 91 --restarts 3 \
|
|
|
69
94
|
checkdk predict --cpu 85 --memory 70 --json # CI/scripting output
|
|
70
95
|
```
|
|
71
96
|
|
|
72
|
-
| Option
|
|
73
|
-
|
|
74
|
-
| `--cpu`
|
|
75
|
-
| `--memory`
|
|
76
|
-
| `--disk`
|
|
77
|
-
| `--latency`
|
|
78
|
-
| `--restarts`
|
|
79
|
-
| `--probe-failures` | 0
|
|
80
|
-
| `--cpu-pressure`
|
|
81
|
-
| `--mem-pressure`
|
|
82
|
-
| `--age`
|
|
83
|
-
| `--service`
|
|
84
|
-
| `--platform`
|
|
85
|
-
| `--no-ai`
|
|
86
|
-
| `--json`
|
|
97
|
+
| Option | Default | Description |
|
|
98
|
+
| ------------------ | -------- | --------------------------------- |
|
|
99
|
+
| `--cpu` | required | CPU usage % |
|
|
100
|
+
| `--memory` | required | Memory usage % |
|
|
101
|
+
| `--disk` | 50 | Disk usage % |
|
|
102
|
+
| `--latency` | 10 | Network latency ms |
|
|
103
|
+
| `--restarts` | 0 | Container restart count |
|
|
104
|
+
| `--probe-failures` | 0 | Liveness/readiness probe failures |
|
|
105
|
+
| `--cpu-pressure` | 0 | Node CPU pressure (0 or 1) |
|
|
106
|
+
| `--mem-pressure` | 0 | Node memory pressure (0 or 1) |
|
|
107
|
+
| `--age` | 60 | Pod age in minutes |
|
|
108
|
+
| `--service` | — | Service/pod name (label only) |
|
|
109
|
+
| `--platform` | docker | `docker` or `kubernetes` |
|
|
110
|
+
| `--no-ai` | — | Skip LLM, return ML result only |
|
|
111
|
+
| `--json` | — | Raw JSON output for scripting |
|
|
87
112
|
|
|
88
113
|
### Monitor (real-time)
|
|
89
114
|
|
|
@@ -114,10 +139,10 @@ Experiments: `cpu`, `memory`, `disk`, `network`, `pod-kill` (k8s only).
|
|
|
114
139
|
|
|
115
140
|
## Environment variables
|
|
116
141
|
|
|
117
|
-
| Variable
|
|
118
|
-
|
|
119
|
-
| `CHECKDK_API_URL` | `https://checkdk.app/api` | Backend API base URL
|
|
120
|
-
| `CHECKDK_TOKEN`
|
|
142
|
+
| Variable | Default | Description |
|
|
143
|
+
| ----------------- | ------------------------- | -------------------------------------------- |
|
|
144
|
+
| `CHECKDK_API_URL` | `https://checkdk.app/api` | Backend API base URL |
|
|
145
|
+
| `CHECKDK_TOKEN` | — | JWT auth token (set by `checkdk auth login`) |
|
|
121
146
|
|
|
122
147
|
The CLI auto-loads `~/.checkdk/.env` and `./.env` on startup.
|
|
123
148
|
|
|
@@ -145,4 +170,3 @@ pytest
|
|
|
145
170
|
# Lint
|
|
146
171
|
ruff check .
|
|
147
172
|
```
|
|
148
|
-
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: checkdk-cli
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.5
|
|
4
4
|
Summary: checkDK CLI – AI-powered Docker/Kubernetes issue detector and pod failure predictor
|
|
5
5
|
Author-email: checkDK Team <team@checkdk.app>
|
|
6
6
|
License: MIT
|
|
@@ -50,6 +50,29 @@ dependencies — it is a thin HTTP/WebSocket client with a rich terminal UI.
|
|
|
50
50
|
|
|
51
51
|
## Install
|
|
52
52
|
|
|
53
|
+
### npm (no Python required)
|
|
54
|
+
|
|
55
|
+
The easiest way to install for JavaScript / Node.js users.
|
|
56
|
+
Pre-compiled standalone binaries are distributed per-platform — nothing else needs to be installed.
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm install -g @checkdk/cli
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Supported platforms:
|
|
63
|
+
|
|
64
|
+
| Platform | Package |
|
|
65
|
+
| --------------------------- | --------------------------- |
|
|
66
|
+
| Linux x64 | `@checkdk/cli-linux-x64` |
|
|
67
|
+
| Linux arm64 | `@checkdk/cli-linux-arm64` |
|
|
68
|
+
| macOS x64 (Intel) | `@checkdk/cli-darwin-x64` |
|
|
69
|
+
| macOS arm64 (Apple Silicon) | `@checkdk/cli-darwin-arm64` |
|
|
70
|
+
| Windows x64 | `@checkdk/cli-win32-x64` |
|
|
71
|
+
|
|
72
|
+
After install, `checkdk` is available on your PATH immediately.
|
|
73
|
+
|
|
74
|
+
### pip / pipx (Python required)
|
|
75
|
+
|
|
53
76
|
```bash
|
|
54
77
|
# Recommended — isolated install, checkdk on PATH globally
|
|
55
78
|
pipx install checkdk-cli
|
|
@@ -58,6 +81,8 @@ pipx install checkdk-cli
|
|
|
58
81
|
pip install checkdk-cli
|
|
59
82
|
```
|
|
60
83
|
|
|
84
|
+
Requires Python 3.10 or later.
|
|
85
|
+
|
|
61
86
|
The `checkdk` command is available immediately after install.
|
|
62
87
|
No configuration required — the CLI talks to `https://checkdk.app/api` by default.
|
|
63
88
|
|
|
@@ -107,21 +132,21 @@ checkdk predict --cpu 93 --memory 91 --restarts 3 \
|
|
|
107
132
|
checkdk predict --cpu 85 --memory 70 --json # CI/scripting output
|
|
108
133
|
```
|
|
109
134
|
|
|
110
|
-
| Option
|
|
111
|
-
|
|
112
|
-
| `--cpu`
|
|
113
|
-
| `--memory`
|
|
114
|
-
| `--disk`
|
|
115
|
-
| `--latency`
|
|
116
|
-
| `--restarts`
|
|
117
|
-
| `--probe-failures` | 0
|
|
118
|
-
| `--cpu-pressure`
|
|
119
|
-
| `--mem-pressure`
|
|
120
|
-
| `--age`
|
|
121
|
-
| `--service`
|
|
122
|
-
| `--platform`
|
|
123
|
-
| `--no-ai`
|
|
124
|
-
| `--json`
|
|
135
|
+
| Option | Default | Description |
|
|
136
|
+
| ------------------ | -------- | --------------------------------- |
|
|
137
|
+
| `--cpu` | required | CPU usage % |
|
|
138
|
+
| `--memory` | required | Memory usage % |
|
|
139
|
+
| `--disk` | 50 | Disk usage % |
|
|
140
|
+
| `--latency` | 10 | Network latency ms |
|
|
141
|
+
| `--restarts` | 0 | Container restart count |
|
|
142
|
+
| `--probe-failures` | 0 | Liveness/readiness probe failures |
|
|
143
|
+
| `--cpu-pressure` | 0 | Node CPU pressure (0 or 1) |
|
|
144
|
+
| `--mem-pressure` | 0 | Node memory pressure (0 or 1) |
|
|
145
|
+
| `--age` | 60 | Pod age in minutes |
|
|
146
|
+
| `--service` | — | Service/pod name (label only) |
|
|
147
|
+
| `--platform` | docker | `docker` or `kubernetes` |
|
|
148
|
+
| `--no-ai` | — | Skip LLM, return ML result only |
|
|
149
|
+
| `--json` | — | Raw JSON output for scripting |
|
|
125
150
|
|
|
126
151
|
### Monitor (real-time)
|
|
127
152
|
|
|
@@ -152,10 +177,10 @@ Experiments: `cpu`, `memory`, `disk`, `network`, `pod-kill` (k8s only).
|
|
|
152
177
|
|
|
153
178
|
## Environment variables
|
|
154
179
|
|
|
155
|
-
| Variable
|
|
156
|
-
|
|
157
|
-
| `CHECKDK_API_URL` | `https://checkdk.app/api` | Backend API base URL
|
|
158
|
-
| `CHECKDK_TOKEN`
|
|
180
|
+
| Variable | Default | Description |
|
|
181
|
+
| ----------------- | ------------------------- | -------------------------------------------- |
|
|
182
|
+
| `CHECKDK_API_URL` | `https://checkdk.app/api` | Backend API base URL |
|
|
183
|
+
| `CHECKDK_TOKEN` | — | JWT auth token (set by `checkdk auth login`) |
|
|
159
184
|
|
|
160
185
|
The CLI auto-loads `~/.checkdk/.env` and `./.env` on startup.
|
|
161
186
|
|
|
@@ -183,4 +208,3 @@ pytest
|
|
|
183
208
|
# Lint
|
|
184
209
|
ruff check .
|
|
185
210
|
```
|
|
186
|
-
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"""checkdk auth commands - login, logout, whoami."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import sys
|
|
7
|
+
import webbrowser
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
import click
|
|
11
|
+
from rich.console import Console
|
|
12
|
+
from rich.panel import Panel
|
|
13
|
+
from rich.table import Table
|
|
14
|
+
|
|
15
|
+
from ..client import get_api_url, get_current_user, validate_token
|
|
16
|
+
|
|
17
|
+
_console = Console()
|
|
18
|
+
_ENV_FILE = Path.home() / ".checkdk" / ".env"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _save_token(token: str) -> None:
|
|
22
|
+
_ENV_FILE.parent.mkdir(parents=True, exist_ok=True)
|
|
23
|
+
lines = _ENV_FILE.read_text().splitlines() if _ENV_FILE.exists() else []
|
|
24
|
+
lines = [l for l in lines if not l.startswith("CHECKDK_TOKEN=")]
|
|
25
|
+
lines.append(f"CHECKDK_TOKEN={token}")
|
|
26
|
+
_ENV_FILE.write_text("\n".join(lines) + "\n")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _remove_token() -> None:
|
|
30
|
+
if not _ENV_FILE.exists():
|
|
31
|
+
return
|
|
32
|
+
lines = [l for l in _ENV_FILE.read_text().splitlines()
|
|
33
|
+
if not l.startswith("CHECKDK_TOKEN=")]
|
|
34
|
+
_ENV_FILE.write_text("\n".join(lines) + "\n")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@click.group("auth")
|
|
38
|
+
def auth_cmd() -> None:
|
|
39
|
+
"""Authentication - log in, log out, or check who you are."""
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@auth_cmd.command("login")
|
|
43
|
+
def login_cmd() -> None:
|
|
44
|
+
"""Log in to checkDK via GitHub or Google OAuth.
|
|
45
|
+
|
|
46
|
+
Opens the sign-in page in your browser, then prompts you to paste
|
|
47
|
+
the JWT token shown after a successful login.
|
|
48
|
+
"""
|
|
49
|
+
login_url = f"{get_api_url().replace('/api', '')}/login" if "/api" in get_api_url() else "https://checkdk.app/login"
|
|
50
|
+
_console.print(f"\n[bold]Opening sign-in page:[/] [cyan]{login_url}[/]")
|
|
51
|
+
_console.print("[dim]Sign in with GitHub or Google, then copy the token from the page.[/]\n")
|
|
52
|
+
|
|
53
|
+
try:
|
|
54
|
+
webbrowser.open(login_url)
|
|
55
|
+
except Exception:
|
|
56
|
+
_console.print("[yellow]Could not open browser automatically.[/]")
|
|
57
|
+
_console.print(f"Please visit: [cyan]{login_url}[/]\n")
|
|
58
|
+
|
|
59
|
+
token = _console.input("[bold]Paste your JWT token here:[/] ").strip()
|
|
60
|
+
if not token:
|
|
61
|
+
_console.print("[red]No token provided. Login cancelled.[/]")
|
|
62
|
+
sys.exit(1)
|
|
63
|
+
|
|
64
|
+
try:
|
|
65
|
+
user = validate_token(token)
|
|
66
|
+
except Exception as exc:
|
|
67
|
+
_console.print(f"[bold red]Token validation failed:[/] {exc}")
|
|
68
|
+
_console.print("[yellow]Make sure CHECKDK_API_URL points to a running backend.[/]")
|
|
69
|
+
sys.exit(1)
|
|
70
|
+
|
|
71
|
+
_save_token(token)
|
|
72
|
+
os.environ["CHECKDK_TOKEN"] = token
|
|
73
|
+
|
|
74
|
+
_console.print(Panel(
|
|
75
|
+
f"[bold green]Logged in successfully![/]\n\n"
|
|
76
|
+
f" Name: {user.get('name', '?')}\n"
|
|
77
|
+
f" Email: {user.get('email', '?')}\n"
|
|
78
|
+
f" Provider: {user.get('provider', '?')}\n\n"
|
|
79
|
+
f"[dim]Token saved to {_ENV_FILE}[/]",
|
|
80
|
+
border_style="green",
|
|
81
|
+
))
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@auth_cmd.command("logout")
|
|
85
|
+
def logout_cmd() -> None:
|
|
86
|
+
"""Remove the stored JWT token."""
|
|
87
|
+
_remove_token()
|
|
88
|
+
if "CHECKDK_TOKEN" in os.environ:
|
|
89
|
+
del os.environ["CHECKDK_TOKEN"]
|
|
90
|
+
_console.print("[bold green]Logged out.[/] Token removed from local config.")
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@auth_cmd.command("whoami")
|
|
94
|
+
def whoami_cmd() -> None:
|
|
95
|
+
"""Show the currently logged-in user."""
|
|
96
|
+
try:
|
|
97
|
+
user = get_current_user()
|
|
98
|
+
except Exception as exc:
|
|
99
|
+
_console.print(f"[bold red]Not logged in or API unreachable:[/] {exc}")
|
|
100
|
+
_console.print("[dim]Run [bold]checkdk auth login[/] first.[/]")
|
|
101
|
+
sys.exit(1)
|
|
102
|
+
|
|
103
|
+
t = Table.grid(padding=(0, 2))
|
|
104
|
+
t.add_column(style="bold cyan")
|
|
105
|
+
t.add_column()
|
|
106
|
+
t.add_row("Name:", user.get("name", "?"))
|
|
107
|
+
t.add_row("Email:", user.get("email", "?"))
|
|
108
|
+
t.add_row("Provider:", user.get("provider", "?"))
|
|
109
|
+
t.add_row("User ID:", user.get("userId", "?"))
|
|
110
|
+
_console.print(Panel(t, title="Current User", border_style="cyan"))
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "checkdk-cli"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.5"
|
|
8
8
|
description = "checkDK CLI – AI-powered Docker/Kubernetes issue detector and pod failure predictor"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
"""checkdk auth commands - login, logout, whoami."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
import os
|
|
6
|
-
import socket
|
|
7
|
-
import sys
|
|
8
|
-
import threading
|
|
9
|
-
import time
|
|
10
|
-
import urllib.parse
|
|
11
|
-
import webbrowser
|
|
12
|
-
from http.server import BaseHTTPRequestHandler, HTTPServer
|
|
13
|
-
from pathlib import Path
|
|
14
|
-
|
|
15
|
-
import click
|
|
16
|
-
from rich.console import Console
|
|
17
|
-
from rich.panel import Panel
|
|
18
|
-
from rich.table import Table
|
|
19
|
-
|
|
20
|
-
from ..client import get_api_url, get_current_user, validate_token
|
|
21
|
-
|
|
22
|
-
_console = Console()
|
|
23
|
-
_ENV_FILE = Path.home() / ".checkdk" / ".env"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def _save_token(token: str) -> None:
|
|
27
|
-
_ENV_FILE.parent.mkdir(parents=True, exist_ok=True)
|
|
28
|
-
lines = _ENV_FILE.read_text().splitlines() if _ENV_FILE.exists() else []
|
|
29
|
-
lines = [l for l in lines if not l.startswith("CHECKDK_TOKEN=")]
|
|
30
|
-
lines.append(f"CHECKDK_TOKEN={token}")
|
|
31
|
-
_ENV_FILE.write_text("\n".join(lines) + "\n")
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
def _remove_token() -> None:
|
|
35
|
-
if not _ENV_FILE.exists():
|
|
36
|
-
return
|
|
37
|
-
lines = [l for l in _ENV_FILE.read_text().splitlines()
|
|
38
|
-
if not l.startswith("CHECKDK_TOKEN=")]
|
|
39
|
-
_ENV_FILE.write_text("\n".join(lines) + "\n")
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def _find_free_port() -> int:
|
|
43
|
-
"""Return an available localhost port."""
|
|
44
|
-
with socket.socket() as s:
|
|
45
|
-
s.bind(("127.0.0.1", 0))
|
|
46
|
-
return s.getsockname()[1]
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
def _wait_for_token(port: int, timeout: int = 120) -> "str | None":
|
|
50
|
-
"""Start a temporary HTTP server on localhost and wait for the OAuth callback."""
|
|
51
|
-
received: dict = {"token": None}
|
|
52
|
-
server_ready = threading.Event()
|
|
53
|
-
|
|
54
|
-
class _Handler(BaseHTTPRequestHandler):
|
|
55
|
-
def do_GET(self) -> None:
|
|
56
|
-
parsed = urllib.parse.urlparse(self.path)
|
|
57
|
-
params = urllib.parse.parse_qs(parsed.query)
|
|
58
|
-
token = (params.get("token") or [None])[0]
|
|
59
|
-
received["token"] = token
|
|
60
|
-
|
|
61
|
-
if token:
|
|
62
|
-
body = (
|
|
63
|
-
b"<html><body style=\"font-family:sans-serif;text-align:center;"
|
|
64
|
-
b"margin-top:10vh;background:#0f172a;color:#e2e8f0\">"
|
|
65
|
-
b"<h2 style=\"color:#818cf8\">checkDK CLI</h2>"
|
|
66
|
-
b"<p style=\"font-size:1.2rem\">You\'re logged in!"
|
|
67
|
-
b" You can close this tab.</p></body></html>"
|
|
68
|
-
)
|
|
69
|
-
else:
|
|
70
|
-
body = b"<html><body>Authentication failed. Please try again.</body></html>"
|
|
71
|
-
|
|
72
|
-
self.send_response(200)
|
|
73
|
-
self.send_header("Content-Type", "text/html; charset=utf-8")
|
|
74
|
-
self.send_header("Content-Length", str(len(body)))
|
|
75
|
-
self.end_headers()
|
|
76
|
-
self.wfile.write(body)
|
|
77
|
-
|
|
78
|
-
def log_message(self, *_) -> None:
|
|
79
|
-
pass # silence access logs
|
|
80
|
-
|
|
81
|
-
httpd = HTTPServer(("127.0.0.1", port), _Handler)
|
|
82
|
-
httpd.timeout = 1 # poll interval
|
|
83
|
-
|
|
84
|
-
def _serve() -> None:
|
|
85
|
-
server_ready.set()
|
|
86
|
-
deadline = time.time() + timeout
|
|
87
|
-
while received["token"] is None and time.time() < deadline:
|
|
88
|
-
httpd.handle_request()
|
|
89
|
-
httpd.server_close()
|
|
90
|
-
|
|
91
|
-
t = threading.Thread(target=_serve, daemon=True)
|
|
92
|
-
t.start()
|
|
93
|
-
server_ready.wait()
|
|
94
|
-
t.join(timeout + 2)
|
|
95
|
-
return received["token"]
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
@click.group("auth")
|
|
99
|
-
def auth_cmd() -> None:
|
|
100
|
-
"""Authentication - log in, log out, or check who you are."""
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
@auth_cmd.command("login")
|
|
104
|
-
def login_cmd() -> None:
|
|
105
|
-
"""Log in to checkDK via GitHub or Google OAuth.
|
|
106
|
-
|
|
107
|
-
Starts a local callback server, opens the sign-in page in your browser,
|
|
108
|
-
and receives the token automatically - no copy-pasting required.
|
|
109
|
-
"""
|
|
110
|
-
port = _find_free_port()
|
|
111
|
-
callback_url = f"http://127.0.0.1:{port}/callback"
|
|
112
|
-
|
|
113
|
-
api = get_api_url()
|
|
114
|
-
base = api[: api.rindex("/api")] if "/api" in api else "https://checkdk.app"
|
|
115
|
-
encoded_cb = urllib.parse.quote(callback_url, safe="")
|
|
116
|
-
login_url = f"{base}/login?cli_callback={encoded_cb}"
|
|
117
|
-
|
|
118
|
-
_console.print("\n[bold]Opening browser for sign-in...[/]")
|
|
119
|
-
_console.print(
|
|
120
|
-
" [dim]If the browser did not open, visit:[/]\n"
|
|
121
|
-
f" [cyan]{login_url}[/]\n"
|
|
122
|
-
)
|
|
123
|
-
|
|
124
|
-
try:
|
|
125
|
-
webbrowser.open(login_url)
|
|
126
|
-
except Exception:
|
|
127
|
-
_console.print(f"[yellow]Open this URL in your browser:[/] [cyan]{login_url}[/]\n")
|
|
128
|
-
|
|
129
|
-
with _console.status("[bold cyan]Waiting for authentication (2-min timeout)...[/]"):
|
|
130
|
-
token = _wait_for_token(port, timeout=120)
|
|
131
|
-
|
|
132
|
-
if not token:
|
|
133
|
-
_console.print("[bold red]Login timed out or was cancelled.[/]")
|
|
134
|
-
sys.exit(1)
|
|
135
|
-
|
|
136
|
-
try:
|
|
137
|
-
user = validate_token(token)
|
|
138
|
-
except Exception as exc:
|
|
139
|
-
_console.print(f"[bold red]Token validation failed:[/] {exc}")
|
|
140
|
-
sys.exit(1)
|
|
141
|
-
|
|
142
|
-
_save_token(token)
|
|
143
|
-
os.environ["CHECKDK_TOKEN"] = token
|
|
144
|
-
|
|
145
|
-
_console.print(Panel(
|
|
146
|
-
f"[bold green]Logged in successfully![/]\n\n"
|
|
147
|
-
f" Name: {user.get('name', '?\')}\n"
|
|
148
|
-
f" Email: {user.get('email', '?\')}\n"
|
|
149
|
-
f" Provider: {user.get('provider', '?\')}\n\n"
|
|
150
|
-
f"[dim]Token saved to {_ENV_FILE}[/]",
|
|
151
|
-
border_style="green",
|
|
152
|
-
))
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
@auth_cmd.command("logout")
|
|
156
|
-
def logout_cmd() -> None:
|
|
157
|
-
"""Remove the stored JWT token."""
|
|
158
|
-
_remove_token()
|
|
159
|
-
if "CHECKDK_TOKEN" in os.environ:
|
|
160
|
-
del os.environ["CHECKDK_TOKEN"]
|
|
161
|
-
_console.print("[bold green]Logged out.[/] Token removed from local config.")
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
@auth_cmd.command("whoami")
|
|
165
|
-
def whoami_cmd() -> None:
|
|
166
|
-
"""Show the currently logged-in user."""
|
|
167
|
-
try:
|
|
168
|
-
user = get_current_user()
|
|
169
|
-
except Exception as exc:
|
|
170
|
-
_console.print(f"[bold red]Not logged in or API unreachable:[/] {exc}")
|
|
171
|
-
_console.print("[dim]Run [bold]checkdk auth login[/] first.[/]")
|
|
172
|
-
sys.exit(1)
|
|
173
|
-
|
|
174
|
-
t = Table.grid(padding=(0, 2))
|
|
175
|
-
t.add_column(style="bold cyan")
|
|
176
|
-
t.add_column()
|
|
177
|
-
t.add_row("Name:", user.get("name", "?"))
|
|
178
|
-
t.add_row("Email:", user.get("email", "?"))
|
|
179
|
-
t.add_row("Provider:", user.get("provider", "?"))
|
|
180
|
-
t.add_row("User ID:", user.get("userId", "?"))
|
|
181
|
-
_console.print(Panel(t, title="Current User", border_style="cyan"))
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|