harbor-check-cli 0.1.0__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.
- harbor_check_cli-0.1.0/PKG-INFO +76 -0
- harbor_check_cli-0.1.0/README.md +65 -0
- harbor_check_cli-0.1.0/harbor_check_cli/__init__.py +5 -0
- harbor_check_cli-0.1.0/harbor_check_cli/__main__.py +40 -0
- harbor_check_cli-0.1.0/harbor_check_cli/client.py +26 -0
- harbor_check_cli-0.1.0/harbor_check_cli.egg-info/PKG-INFO +76 -0
- harbor_check_cli-0.1.0/harbor_check_cli.egg-info/SOURCES.txt +11 -0
- harbor_check_cli-0.1.0/harbor_check_cli.egg-info/dependency_links.txt +1 -0
- harbor_check_cli-0.1.0/harbor_check_cli.egg-info/entry_points.txt +2 -0
- harbor_check_cli-0.1.0/harbor_check_cli.egg-info/requires.txt +1 -0
- harbor_check_cli-0.1.0/harbor_check_cli.egg-info/top_level.txt +1 -0
- harbor_check_cli-0.1.0/pyproject.toml +14 -0
- harbor_check_cli-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: harbor-check-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: CLI for Harbor Check review status and rubric summaries
|
|
5
|
+
License: MIT
|
|
6
|
+
Classifier: Programming Language :: Python :: 3
|
|
7
|
+
Classifier: Environment :: Console
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
Requires-Dist: httpx>=0.27
|
|
11
|
+
|
|
12
|
+
# Harbor Check CLI
|
|
13
|
+
|
|
14
|
+
Install with `python -m pip install ./saas/harbor-check-cli`.
|
|
15
|
+
|
|
16
|
+
Login once; the token is stored with mode 0600 and reused by later commands:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
harbor-check login --server 101.46.8.169 --username alice --password 'secret'
|
|
20
|
+
harbor-check tasks
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
An address without a scheme is treated as `http://`; use `--server
|
|
24
|
+
http://101.46.8.169:8000` when Harbor Check is listening on a non-default port.
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
harbor-check --server https://review.example.com tasks
|
|
28
|
+
harbor-check --server https://review.example.com folders
|
|
29
|
+
harbor-check --server https://review.example.com folder-tasks batch-name
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The CLI authenticates with the server's `/api/auth/login` endpoint. Configure
|
|
33
|
+
Django with `HARBOR_CHECK_AUTH_REQUIRED=1` and `HARBOR_CHECK_USERS_JSON`.
|
|
34
|
+
Values may be plaintext for local development or `pbkdf2_sha256$rounds$salt$hex`
|
|
35
|
+
hashes for deployment. Authenticated users can see all users' tasks and folders.
|
|
36
|
+
Use `--json` for machine-readable output.
|
|
37
|
+
|
|
38
|
+
For cloud hosts whose users are real SSH/system accounts, set
|
|
39
|
+
`HARBOR_CHECK_OS_AUTH=1` on the server. The login endpoint then verifies the
|
|
40
|
+
same username/password against the server's SSH daemon (optionally using
|
|
41
|
+
`HARBOR_CHECK_SSH_HOST`). This lets a laptop authenticate without copying the
|
|
42
|
+
password into the application database.
|
|
43
|
+
|
|
44
|
+
Plain HTTP exposes the login password and review data to anyone able to observe
|
|
45
|
+
the network path. For public access, put Django behind HTTPS, or use an SSH
|
|
46
|
+
tunnel from the laptop:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
ssh -N -L 8000:127.0.0.1:8000 alice@101.46.8.169
|
|
50
|
+
harbor-check login --server http://127.0.0.1:8000 --username alice
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
## Install and use from `101.46.8.169`
|
|
55
|
+
|
|
56
|
+
On a laptop with network access to the server:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
python -m pip install --upgrade harbor-check-cli
|
|
60
|
+
harbor-check login --server http://101.46.8.169:8000 --username YOUR_SERVER_USERNAME
|
|
61
|
+
harbor-check tasks
|
|
62
|
+
harbor-check folders
|
|
63
|
+
harbor-check folder-tasks YOUR_FOLDER_NAME
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The token is stored in `~/.config/harbor-check/credentials.json` with 0600
|
|
67
|
+
permissions. Use `--json` for scripts. If the server is exposed only through
|
|
68
|
+
SSH, create a tunnel first:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
ssh -N -L 8000:127.0.0.1:8000 YOUR_SERVER_USERNAME@101.46.8.169
|
|
72
|
+
harbor-check login --server http://127.0.0.1:8000 --username YOUR_SERVER_USERNAME
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The server must enable `HARBOR_CHECK_AUTH_REQUIRED=1` and configure either
|
|
76
|
+
`HARBOR_CHECK_USERS_JSON` or `HARBOR_CHECK_OS_AUTH=1`.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Harbor Check CLI
|
|
2
|
+
|
|
3
|
+
Install with `python -m pip install ./saas/harbor-check-cli`.
|
|
4
|
+
|
|
5
|
+
Login once; the token is stored with mode 0600 and reused by later commands:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
harbor-check login --server 101.46.8.169 --username alice --password 'secret'
|
|
9
|
+
harbor-check tasks
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
An address without a scheme is treated as `http://`; use `--server
|
|
13
|
+
http://101.46.8.169:8000` when Harbor Check is listening on a non-default port.
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
harbor-check --server https://review.example.com tasks
|
|
17
|
+
harbor-check --server https://review.example.com folders
|
|
18
|
+
harbor-check --server https://review.example.com folder-tasks batch-name
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The CLI authenticates with the server's `/api/auth/login` endpoint. Configure
|
|
22
|
+
Django with `HARBOR_CHECK_AUTH_REQUIRED=1` and `HARBOR_CHECK_USERS_JSON`.
|
|
23
|
+
Values may be plaintext for local development or `pbkdf2_sha256$rounds$salt$hex`
|
|
24
|
+
hashes for deployment. Authenticated users can see all users' tasks and folders.
|
|
25
|
+
Use `--json` for machine-readable output.
|
|
26
|
+
|
|
27
|
+
For cloud hosts whose users are real SSH/system accounts, set
|
|
28
|
+
`HARBOR_CHECK_OS_AUTH=1` on the server. The login endpoint then verifies the
|
|
29
|
+
same username/password against the server's SSH daemon (optionally using
|
|
30
|
+
`HARBOR_CHECK_SSH_HOST`). This lets a laptop authenticate without copying the
|
|
31
|
+
password into the application database.
|
|
32
|
+
|
|
33
|
+
Plain HTTP exposes the login password and review data to anyone able to observe
|
|
34
|
+
the network path. For public access, put Django behind HTTPS, or use an SSH
|
|
35
|
+
tunnel from the laptop:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
ssh -N -L 8000:127.0.0.1:8000 alice@101.46.8.169
|
|
39
|
+
harbor-check login --server http://127.0.0.1:8000 --username alice
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
## Install and use from `101.46.8.169`
|
|
44
|
+
|
|
45
|
+
On a laptop with network access to the server:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
python -m pip install --upgrade harbor-check-cli
|
|
49
|
+
harbor-check login --server http://101.46.8.169:8000 --username YOUR_SERVER_USERNAME
|
|
50
|
+
harbor-check tasks
|
|
51
|
+
harbor-check folders
|
|
52
|
+
harbor-check folder-tasks YOUR_FOLDER_NAME
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The token is stored in `~/.config/harbor-check/credentials.json` with 0600
|
|
56
|
+
permissions. Use `--json` for scripts. If the server is exposed only through
|
|
57
|
+
SSH, create a tunnel first:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
ssh -N -L 8000:127.0.0.1:8000 YOUR_SERVER_USERNAME@101.46.8.169
|
|
61
|
+
harbor-check login --server http://127.0.0.1:8000 --username YOUR_SERVER_USERNAME
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The server must enable `HARBOR_CHECK_AUTH_REQUIRED=1` and configure either
|
|
65
|
+
`HARBOR_CHECK_USERS_JSON` or `HARBOR_CHECK_OS_AUTH=1`.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import argparse, getpass, json, os, sys, asyncio
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
import httpx
|
|
4
|
+
CONFIG=Path(os.getenv('XDG_CONFIG_HOME', Path.home()/'.config'))/'harbor-check'/'credentials.json'
|
|
5
|
+
|
|
6
|
+
class Client:
|
|
7
|
+
def __init__(self, base):
|
|
8
|
+
if '://' not in base: base='http://'+base
|
|
9
|
+
self.base=base.rstrip('/'); self.token=None
|
|
10
|
+
def login(self,u,p):
|
|
11
|
+
r=httpx.post(self.base+'/api/auth/login',json={'username':u,'password':p},timeout=20); r.raise_for_status(); self.token=r.json()['token']
|
|
12
|
+
def get(self,path):
|
|
13
|
+
r=httpx.get(self.base+path,headers={'Authorization':'Bearer '+self.token},timeout=30); r.raise_for_status(); return r.json()
|
|
14
|
+
|
|
15
|
+
def main():
|
|
16
|
+
ap=argparse.ArgumentParser(prog='harbor-check'); ap.add_argument('--server',default=os.getenv('HARBOR_CHECK_SERVER','http://127.0.0.1:8000')); ap.add_argument('--local',action='store_true',help='read the server workspace directly (only when running on the review server)'); ap.add_argument('--username'); ap.add_argument('--password'); ap.add_argument('--json',action='store_true'); sub=ap.add_subparsers(dest='cmd',required=True); login=sub.add_parser('login'); login.add_argument('--server',dest='login_server'); login.add_argument('--username',dest='login_username'); login.add_argument('--password',dest='login_password'); sub.add_parser('tasks'); sub.add_parser('folders'); f=sub.add_parser('folder-tasks'); f.add_argument('folder')
|
|
17
|
+
a=ap.parse_args()
|
|
18
|
+
try:
|
|
19
|
+
if a.cmd=='login':
|
|
20
|
+
server=a.login_server or a.server; u=a.login_username or input('Username: '); p=a.login_password or getpass.getpass('Password: '); c=Client(server); c.login(u,p); CONFIG.parent.mkdir(parents=True,exist_ok=True); CONFIG.write_text(json.dumps({'server':server,'username':u,'token':c.token})); CONFIG.chmod(0o600); print(f'Logged in to {server} as {u}'); return 0
|
|
21
|
+
if a.local:
|
|
22
|
+
repo=Path(os.getenv('HARBOR_CHECK_REPO',Path.cwd())); sys.path.insert(0,str(repo/'saas/harbor-check')); from app import all_tasks; data=asyncio.run(all_tasks())
|
|
23
|
+
else:
|
|
24
|
+
saved=json.loads(CONFIG.read_text()) if CONFIG.exists() else {}; c=Client(saved.get('server') or a.server); c.token=saved.get('token');
|
|
25
|
+
if not c.token:
|
|
26
|
+
u=a.username or input('Username: '); p=a.password or getpass.getpass('Password: '); c.login(u,p)
|
|
27
|
+
data=c.get('/api/tasks')
|
|
28
|
+
except Exception as e: print(f'harbor-check: {e}',file=sys.stderr); return 2
|
|
29
|
+
if a.cmd=='folder-tasks': data=[x for x in data if x['dirname']==a.folder]
|
|
30
|
+
if a.json: print(json.dumps(data,indent=2)); return 0
|
|
31
|
+
if a.cmd=='tasks':
|
|
32
|
+
print('USER/FOLDER/TASK | STATE | RUNTIME | LAST ACTIVE | FAILS BY CATEGORY')
|
|
33
|
+
for g in data:
|
|
34
|
+
for t in g.get('tasks',[]): print(f"{g['username']}/{g['dirname']}/{t['task']} | {t.get('state','-')} | {t.get('elapsed_seconds','-')}s | {t.get('last_activity_at','-')} | {json.dumps((t.get('result') or {}).get('failed_by_category',{}),sort_keys=True)}")
|
|
35
|
+
else:
|
|
36
|
+
print('USER/FOLDER | TASKS | FAILS BY CATEGORY | FAIL RATE')
|
|
37
|
+
for g in data:
|
|
38
|
+
rep=g.get('report') or {}; groups=rep.get('groups') or {}; total=sum(v.get('total',0) for v in groups.values()); fails=sum(v.get('fail',0) for v in groups.values()); cats={k:v.get('fail',0) for k,v in groups.items()}; print(f"{g['username']}/{g['dirname']} | {len(g.get('tasks',[]))} | {json.dumps(cats,sort_keys=True)} | {fails}/{total} ({(fails/total*100 if total else 0):.1f}%)")
|
|
39
|
+
return 0
|
|
40
|
+
if __name__=='__main__': raise SystemExit(main())
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import httpx
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class HarborCheckClient:
|
|
7
|
+
"""Small authenticated client for embedding Harbor Check in Python tools."""
|
|
8
|
+
|
|
9
|
+
def __init__(self, server: str, token: str | None = None):
|
|
10
|
+
if "://" not in server:
|
|
11
|
+
server = "http://" + server
|
|
12
|
+
self.server = server.rstrip("/")
|
|
13
|
+
self.token = token
|
|
14
|
+
|
|
15
|
+
def login(self, username: str, password: str) -> dict:
|
|
16
|
+
response = httpx.post(f"{self.server}/api/auth/login", json={"username": username, "password": password}, timeout=20)
|
|
17
|
+
response.raise_for_status()
|
|
18
|
+
payload = response.json()
|
|
19
|
+
self.token = payload["token"]
|
|
20
|
+
return payload
|
|
21
|
+
|
|
22
|
+
def tasks(self) -> list[dict]:
|
|
23
|
+
headers = {"Authorization": f"Bearer {self.token}"} if self.token else {}
|
|
24
|
+
response = httpx.get(f"{self.server}/api/tasks", headers=headers, timeout=30)
|
|
25
|
+
response.raise_for_status()
|
|
26
|
+
return response.json()
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: harbor-check-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: CLI for Harbor Check review status and rubric summaries
|
|
5
|
+
License: MIT
|
|
6
|
+
Classifier: Programming Language :: Python :: 3
|
|
7
|
+
Classifier: Environment :: Console
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
Requires-Dist: httpx>=0.27
|
|
11
|
+
|
|
12
|
+
# Harbor Check CLI
|
|
13
|
+
|
|
14
|
+
Install with `python -m pip install ./saas/harbor-check-cli`.
|
|
15
|
+
|
|
16
|
+
Login once; the token is stored with mode 0600 and reused by later commands:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
harbor-check login --server 101.46.8.169 --username alice --password 'secret'
|
|
20
|
+
harbor-check tasks
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
An address without a scheme is treated as `http://`; use `--server
|
|
24
|
+
http://101.46.8.169:8000` when Harbor Check is listening on a non-default port.
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
harbor-check --server https://review.example.com tasks
|
|
28
|
+
harbor-check --server https://review.example.com folders
|
|
29
|
+
harbor-check --server https://review.example.com folder-tasks batch-name
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The CLI authenticates with the server's `/api/auth/login` endpoint. Configure
|
|
33
|
+
Django with `HARBOR_CHECK_AUTH_REQUIRED=1` and `HARBOR_CHECK_USERS_JSON`.
|
|
34
|
+
Values may be plaintext for local development or `pbkdf2_sha256$rounds$salt$hex`
|
|
35
|
+
hashes for deployment. Authenticated users can see all users' tasks and folders.
|
|
36
|
+
Use `--json` for machine-readable output.
|
|
37
|
+
|
|
38
|
+
For cloud hosts whose users are real SSH/system accounts, set
|
|
39
|
+
`HARBOR_CHECK_OS_AUTH=1` on the server. The login endpoint then verifies the
|
|
40
|
+
same username/password against the server's SSH daemon (optionally using
|
|
41
|
+
`HARBOR_CHECK_SSH_HOST`). This lets a laptop authenticate without copying the
|
|
42
|
+
password into the application database.
|
|
43
|
+
|
|
44
|
+
Plain HTTP exposes the login password and review data to anyone able to observe
|
|
45
|
+
the network path. For public access, put Django behind HTTPS, or use an SSH
|
|
46
|
+
tunnel from the laptop:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
ssh -N -L 8000:127.0.0.1:8000 alice@101.46.8.169
|
|
50
|
+
harbor-check login --server http://127.0.0.1:8000 --username alice
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
## Install and use from `101.46.8.169`
|
|
55
|
+
|
|
56
|
+
On a laptop with network access to the server:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
python -m pip install --upgrade harbor-check-cli
|
|
60
|
+
harbor-check login --server http://101.46.8.169:8000 --username YOUR_SERVER_USERNAME
|
|
61
|
+
harbor-check tasks
|
|
62
|
+
harbor-check folders
|
|
63
|
+
harbor-check folder-tasks YOUR_FOLDER_NAME
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The token is stored in `~/.config/harbor-check/credentials.json` with 0600
|
|
67
|
+
permissions. Use `--json` for scripts. If the server is exposed only through
|
|
68
|
+
SSH, create a tunnel first:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
ssh -N -L 8000:127.0.0.1:8000 YOUR_SERVER_USERNAME@101.46.8.169
|
|
72
|
+
harbor-check login --server http://127.0.0.1:8000 --username YOUR_SERVER_USERNAME
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The server must enable `HARBOR_CHECK_AUTH_REQUIRED=1` and configure either
|
|
76
|
+
`HARBOR_CHECK_USERS_JSON` or `HARBOR_CHECK_OS_AUTH=1`.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
harbor_check_cli/__init__.py
|
|
4
|
+
harbor_check_cli/__main__.py
|
|
5
|
+
harbor_check_cli/client.py
|
|
6
|
+
harbor_check_cli.egg-info/PKG-INFO
|
|
7
|
+
harbor_check_cli.egg-info/SOURCES.txt
|
|
8
|
+
harbor_check_cli.egg-info/dependency_links.txt
|
|
9
|
+
harbor_check_cli.egg-info/entry_points.txt
|
|
10
|
+
harbor_check_cli.egg-info/requires.txt
|
|
11
|
+
harbor_check_cli.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
httpx>=0.27
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
harbor_check_cli
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
[project]
|
|
5
|
+
name = "harbor-check-cli"
|
|
6
|
+
version = "0.1.0"
|
|
7
|
+
description = "CLI for Harbor Check review status and rubric summaries"
|
|
8
|
+
requires-python = ">=3.10"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
classifiers = ["Programming Language :: Python :: 3", "Environment :: Console"]
|
|
12
|
+
dependencies = ["httpx>=0.27"]
|
|
13
|
+
[project.scripts]
|
|
14
|
+
harbor-check = "harbor_check_cli.__main__:main"
|