Agent chat, config editor, vault reader, network status - initial implementation
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
"""Test the config editor API endpoints."""
|
||||
import multiprocessing
|
||||
import time
|
||||
import json
|
||||
import sys
|
||||
import os
|
||||
|
||||
os.chdir(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
# Start server
|
||||
import uvicorn
|
||||
import requests
|
||||
|
||||
def run_server():
|
||||
uvicorn.run('server:app', host='127.0.0.1', port=8891, log_level='warning')
|
||||
|
||||
p = multiprocessing.Process(target=run_server, daemon=True)
|
||||
p.start()
|
||||
time.sleep(2)
|
||||
print('=== Server started ===')
|
||||
|
||||
BASE = 'http://127.0.0.1:8891'
|
||||
AUTH = ('shawn', 'Brett85!@')
|
||||
|
||||
def t(name, ok, detail=''):
|
||||
status = 'PASS' if ok else 'FAIL'
|
||||
print(f' [{status}] {name}' + (f' — {detail}' if detail else ''))
|
||||
|
||||
# 1. Health
|
||||
r = requests.get(f'{BASE}/health')
|
||||
t('Health endpoint', r.ok and r.json()['status'] == 'ok')
|
||||
|
||||
# 2. Config list
|
||||
r = requests.get(f'{BASE}/api/config/list', auth=AUTH)
|
||||
t('Config list returns 200', r.status_code == 200)
|
||||
data = r.json()
|
||||
t('Has files array', 'files' in data and len(data['files']) > 0, f'{len(data["files"])} files')
|
||||
|
||||
# 3. Read first file
|
||||
first_file = data['files'][0]['path']
|
||||
r = requests.get(f'{BASE}/api/config/read?path={requests.utils.quote(first_file)}', auth=AUTH)
|
||||
t('Read file returns 200', r.status_code == 200)
|
||||
rd = r.json()
|
||||
t('Has content and metadata', all(k in rd for k in ('content', 'line_count', 'size', 'last_modified')))
|
||||
t('Line count matches content', rd['line_count'] == len(rd['content'].split('\n')))
|
||||
|
||||
# 4. Unauthorized path
|
||||
r = requests.get(f'{BASE}/api/config/read?path=/etc/passwd', auth=AUTH)
|
||||
t('Rejects /etc/passwd', r.status_code == 403)
|
||||
|
||||
r = requests.get(f'{BASE}/api/config/read?path={requests.utils.quote("/home/oplabs/.bashrc")}', auth=AUTH)
|
||||
t('Rejects .bashrc', r.status_code == 403)
|
||||
|
||||
# 5. Missing file in whitelist
|
||||
missing_files = [f for f in data['files'] if f.get('missing')]
|
||||
t('Missing files reported correctly', not missing_files or all(f.get('missing') for f in missing_files))
|
||||
|
||||
# 6. YAML validation - invalid YAML
|
||||
yaml_files = [f for f in data['files'] if f['filename'].endswith('.yaml')]
|
||||
assert len(yaml_files) > 0, 'Need at least one yaml file to test validation'
|
||||
yaml_path = yaml_files[0]['path']
|
||||
|
||||
r = requests.post(f'{BASE}/api/config/save',
|
||||
json={'path': yaml_path, 'content': 'invalid: yaml: [[[bad'},
|
||||
auth=AUTH)
|
||||
t('Rejects invalid YAML', r.status_code == 400 and 'YAML validation' in r.json().get('error', ''))
|
||||
|
||||
# 7. Save valid YAML
|
||||
r = requests.post(f'{BASE}/api/config/save',
|
||||
json={'path': yaml_path, 'content': 'key: value\nnested:\n sub: data\n'},
|
||||
auth=AUTH)
|
||||
t('Saves valid YAML', r.status_code == 200 and r.json().get('saved') and 'backup_path' in r.json())
|
||||
saved = r.json()
|
||||
print(f' Backup created: {saved["backup_path"]}')
|
||||
|
||||
# 8. Verify backup exists
|
||||
bak_path = saved['backup_path']
|
||||
r = requests.get(f'{BASE}/api/config/read?path={requests.utils.quote(first_file)}', auth=AUTH)
|
||||
t('Backup file path is returned', 'bak.' in bak_path)
|
||||
print(f' Original: {saved["path"]}')
|
||||
print(f' Lines: {saved["line_count"]}, Size: {saved["size"]}')
|
||||
|
||||
# 9. Test backup endpoint directly
|
||||
r = requests.post(f'{BASE}/api/config/backup?path={requests.utils.quote(yaml_path)}', auth=AUTH)
|
||||
t('Manual backup endpoint', r.status_code == 200 and 'backup_path' in r.json())
|
||||
|
||||
# 10. HTML serving
|
||||
r = requests.get(f'{BASE}/', auth=AUTH)
|
||||
t('Serves index.html', r.status_code == 200 and 'Config Files' in r.text)
|
||||
|
||||
p.terminate()
|
||||
p.join()
|
||||
print('\n=== All tests complete ===')
|
||||
Reference in New Issue
Block a user