diff --git a/tests/test_guck_admin_deploy.py b/tests/test_guck_admin_deploy.py new file mode 100644 index 0000000..74d1f79 --- /dev/null +++ b/tests/test_guck_admin_deploy.py @@ -0,0 +1,54 @@ +import app +import pytest +from fastapi.testclient import TestClient + + +def valid_bundle(): + files={path:'placeholder' for path in app.GUCK_ADMIN_REPO_FILES} + files['guck-admin/compose.yaml']='''services:\n guck-admin:\n build: .\n network_mode: host\n cap_add: [NET_ADMIN]\n environment:\n GUCK_LIMIT: /host/guck-limit.sh\n volumes:\n - /app-config/guck-admin/data:/data\n control-monitor:\n build: .\n network_mode: host\n cap_add: [NET_ADMIN]\n''' + files['guck-admin/src/control.py']='''CREATE TABLE IF NOT EXISTS custom_networks\n2a00:8c40:f000::/36\n45.58.235.0/24\ndef sync_custom_networks(): pass\n''' + return files + + +def test_guck_admin_bundle_requires_persistent_custom_network_policy(): + files=valid_bundle() + files['guck-admin/src/control.py']='def old_control(): pass\n' + with pytest.raises(ValueError,match='custom VPN'): + app._validate_guck_admin_bundle(files) + + +def test_guck_admin_deploy_dry_run_has_no_remote_side_effect(monkeypatch): + calls=[] + monkeypatch.setattr(app,'_find_inventory_host',lambda host:{'user':'debian','ip':'141.94.237.199'}) + monkeypatch.setattr(app,'_ssh',lambda *args,**kwargs:calls.append(args)) + result=app._deploy_guck_admin_compose(valid_bundle(),dry_run=True) + assert result['status']=='validated' + assert result['host']=='guck-vps' + assert calls==[] + + +def test_guck_admin_deploy_uses_inventory_target_and_verifies_policy(monkeypatch): + calls=[] + monkeypatch.setattr(app,'_find_inventory_host',lambda host:{'user':'debian','ip':'141.94.237.199'}) + def fake_ssh(host,command,timeout=600): + calls.append((host,command,timeout)) + if 'ipset test vpn-v6' in command: + return 0,'policy ok','' + return 0,'ok','' + monkeypatch.setattr(app,'_ssh',fake_ssh) + result=app._deploy_guck_admin_compose(valid_bundle(),dry_run=False) + assert result['status']=='deployed' + assert result['policy']=='verified' + assert all(host=='debian@141.94.237.199' for host,_,_ in calls) + commands='\n'.join(command for _,command,_ in calls) + assert 'docker compose build' in commands + assert '127.0.0.1:9090/health' in commands + assert '/actions/limiter/refresh' in commands + assert 'ipset test vpn-v6 2a00:8c40:f02d:a34c::1' in commands + assert 'ipset test vpn-v4 45.58.235.7' in commands + + +def test_guck_admin_deploy_endpoint_requires_auth(monkeypatch): + monkeypatch.setattr(app,'BUTLER_TOKEN','test-token') + response=TestClient(app.app).post('/vps/guck-admin/deploy',json={'dry_run':True}) + assert response.status_code in (401,403)