Files
rdp-proxy/backend/internal/modules/cluster/module_admin_runtime_test.go
T
m 20d361a886
build / backend (push) Has been cancelled
build / node-agent (push) Has been cancelled
build / worker (push) Has been cancelled
рабочий вариант, но скороть 10 МБит
2026-05-22 21:46:49 +03:00

230 lines
7.5 KiB
Go

package cluster
import (
"bytes"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"github.com/go-chi/chi/v5"
)
func TestProjectAdminRuntimeReturnsReadOnlyManifest(t *testing.T) {
router := chi.NewRouter()
module := &Module{}
router.Post("/clusters/{clusterID}/nodes/{nodeID}/admin-runtime/projection", module.projectAdminRuntime)
req := httptest.NewRequest(http.MethodPost, "/clusters/cluster-1/nodes/node-1/admin-runtime/projection", bytes.NewReader([]byte(`{
"schema_version":"rap.web_ingress.control_api_projection_request.v1",
"method":"GET",
"path":"/admin/ui-manifest",
"scope":"platform",
"service_class":"admin-ingress"
}`)))
rec := httptest.NewRecorder()
router.ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("status = %d body=%s", rec.Code, rec.Body.String())
}
var response struct {
SchemaVersion string `json:"schema_version"`
Status string `json:"status"`
Reason string `json:"reason"`
StatusCode int `json:"status_code"`
Headers map[string]string `json:"headers"`
Body json.RawMessage `json:"body"`
}
if err := json.Unmarshal(rec.Body.Bytes(), &response); err != nil {
t.Fatalf("decode response: %v", err)
}
if response.SchemaVersion != "rap.web_ingress.control_api_projection_response.v1" ||
response.Status != "ready" ||
response.Reason != "ui_manifest_ready" ||
response.StatusCode != http.StatusOK ||
response.Headers["Content-Type"] != "application/json" {
t.Fatalf("response = %+v", response)
}
var body struct {
SchemaVersion string `json:"schema_version"`
ClusterID string `json:"cluster_id"`
NodeID string `json:"node_id"`
Manifest map[string]any `json:"manifest"`
}
if err := json.Unmarshal(response.Body, &body); err != nil {
t.Fatalf("decode body: %v", err)
}
if body.ClusterID != "cluster-1" ||
body.NodeID != "node-1" ||
body.Manifest["projection_binding"] != "control_api_read_only" ||
body.Manifest["mutation_enabled"] != false {
t.Fatalf("body = %+v", body)
}
}
func TestProjectAdminRuntimeRejectsMutations(t *testing.T) {
router := chi.NewRouter()
module := &Module{}
router.Post("/clusters/{clusterID}/nodes/{nodeID}/admin-runtime/projection", module.projectAdminRuntime)
req := httptest.NewRequest(http.MethodPost, "/clusters/cluster-1/nodes/node-1/admin-runtime/projection", bytes.NewReader([]byte(`{
"schema_version":"rap.web_ingress.control_api_projection_request.v1",
"method":"POST",
"path":"/admin/nodes",
"scope":"platform",
"service_class":"admin-ingress"
}`)))
rec := httptest.NewRecorder()
router.ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("status = %d body=%s", rec.Code, rec.Body.String())
}
var response struct {
Status string `json:"status"`
Reason string `json:"reason"`
StatusCode int `json:"status_code"`
}
if err := json.Unmarshal(rec.Body.Bytes(), &response); err != nil {
t.Fatalf("decode response: %v", err)
}
if response.Status != "blocked" || response.Reason != "control_api_mutation_rejected" || response.StatusCode != http.StatusForbidden {
t.Fatalf("response = %+v", response)
}
}
func TestProjectAdminRuntimeReturnsHealthProjection(t *testing.T) {
router := chi.NewRouter()
module := &Module{}
router.Post("/clusters/{clusterID}/nodes/{nodeID}/admin-runtime/projection", module.projectAdminRuntime)
req := httptest.NewRequest(http.MethodPost, "/clusters/cluster-1/nodes/node-1/admin-runtime/projection", bytes.NewReader([]byte(`{
"schema_version":"rap.web_ingress.control_api_projection_request.v1",
"method":"GET",
"path":"/readyz",
"scope":"platform",
"service_class":"admin-ingress"
}`)))
rec := httptest.NewRecorder()
router.ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("status = %d body=%s", rec.Code, rec.Body.String())
}
var response struct {
Status string `json:"status"`
Reason string `json:"reason"`
StatusCode int `json:"status_code"`
Body json.RawMessage `json:"body"`
}
if err := json.Unmarshal(rec.Body.Bytes(), &response); err != nil {
t.Fatalf("decode response: %v", err)
}
if response.Status != "ready" || response.Reason != "admin_runtime_projection_ready" || response.StatusCode != http.StatusOK {
t.Fatalf("response = %+v", response)
}
var body struct {
Projection string `json:"projection"`
AuditRequired bool `json:"audit_required"`
}
if err := json.Unmarshal(response.Body, &body); err != nil {
t.Fatalf("decode body: %v", err)
}
if body.Projection != "read_only" || !body.AuditRequired {
t.Fatalf("body = %+v", body)
}
}
func TestProjectAdminRuntimeBlocksUnknownReadProjection(t *testing.T) {
router := chi.NewRouter()
module := &Module{}
router.Post("/clusters/{clusterID}/nodes/{nodeID}/admin-runtime/projection", module.projectAdminRuntime)
req := httptest.NewRequest(http.MethodPost, "/clusters/cluster-1/nodes/node-1/admin-runtime/projection", bytes.NewReader([]byte(`{
"schema_version":"rap.web_ingress.control_api_projection_request.v1",
"method":"GET",
"path":"/admin/nodes",
"scope":"platform",
"service_class":"admin-ingress"
}`)))
rec := httptest.NewRecorder()
router.ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("status = %d body=%s", rec.Code, rec.Body.String())
}
var response struct {
Status string `json:"status"`
Reason string `json:"reason"`
StatusCode int `json:"status_code"`
}
if err := json.Unmarshal(rec.Body.Bytes(), &response); err != nil {
t.Fatalf("decode response: %v", err)
}
if response.Status != "blocked" ||
response.Reason != "control_api_projection_not_implemented" ||
response.StatusCode != http.StatusNotImplemented {
t.Fatalf("response = %+v", response)
}
}
func TestProjectAdminRuntimeRejectsScopeClassMismatch(t *testing.T) {
router := chi.NewRouter()
module := &Module{}
router.Post("/clusters/{clusterID}/nodes/{nodeID}/admin-runtime/projection", module.projectAdminRuntime)
req := httptest.NewRequest(http.MethodPost, "/clusters/cluster-1/nodes/node-1/admin-runtime/projection", bytes.NewReader([]byte(`{
"schema_version":"rap.web_ingress.control_api_projection_request.v1",
"method":"GET",
"path":"/admin/ui-manifest",
"scope":"organization",
"service_class":"admin-ingress"
}`)))
rec := httptest.NewRecorder()
router.ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("status = %d body=%s", rec.Code, rec.Body.String())
}
var response struct {
Status string `json:"status"`
Reason string `json:"reason"`
StatusCode int `json:"status_code"`
}
if err := json.Unmarshal(rec.Body.Bytes(), &response); err != nil {
t.Fatalf("decode response: %v", err)
}
if response.Status != "blocked" ||
response.Reason != "control_api_projection_scope_rejected" ||
response.StatusCode != http.StatusForbidden {
t.Fatalf("response = %+v", response)
}
}
func TestProjectAdminRuntimeRejectsInvalidSchema(t *testing.T) {
router := chi.NewRouter()
module := &Module{}
router.Post("/clusters/{clusterID}/nodes/{nodeID}/admin-runtime/projection", module.projectAdminRuntime)
req := httptest.NewRequest(http.MethodPost, "/clusters/cluster-1/nodes/node-1/admin-runtime/projection", bytes.NewReader([]byte(`{
"schema_version":"wrong.schema",
"method":"GET",
"path":"/readyz",
"scope":"platform",
"service_class":"admin-ingress"
}`)))
rec := httptest.NewRecorder()
router.ServeHTTP(rec, req)
if rec.Code != http.StatusBadRequest {
t.Fatalf("status = %d body=%s", rec.Code, rec.Body.String())
}
}