vxlan_handlers_test.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. package api
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "net/http"
  6. "net/http/httptest"
  7. "path/filepath"
  8. "testing"
  9. "debtik/internal/auth"
  10. "debtik/internal/vpn"
  11. )
  12. func setupTestVXLANServer(t *testing.T) (*Server, *vpn.Manager) {
  13. tmpDir := t.TempDir()
  14. authPath := filepath.Join(tmpDir, "users.json")
  15. authMgr := auth.NewManager(authPath)
  16. vpnMgr := &vpn.Manager{
  17. VXLAN: vpn.NewVXLANManager(filepath.Join(tmpDir, "vxlan.json")),
  18. }
  19. srv := &Server{
  20. vpnMgr: vpnMgr,
  21. authMgr: authMgr,
  22. mux: http.NewServeMux(),
  23. fsHandler: http.NotFoundHandler(),
  24. }
  25. srv.registerRoutes()
  26. return srv, vpnMgr
  27. }
  28. func TestVXLANAPIEndpoints(t *testing.T) {
  29. srv, _ := setupTestVXLANServer(t)
  30. // 1. GET /api/vpn/vxlan (empty initially)
  31. req := httptest.NewRequest(http.MethodGet, "/api/vpn/vxlan", nil)
  32. rec := httptest.NewRecorder()
  33. srv.mux.ServeHTTP(rec, req)
  34. if rec.Code != http.StatusOK {
  35. t.Fatalf("GET /api/vpn/vxlan code = %d; want 200", rec.Code)
  36. }
  37. var list []*vpn.VXLANInstance
  38. if err := json.NewDecoder(rec.Body).Decode(&list); err != nil {
  39. t.Fatalf("decode failed: %v", err)
  40. }
  41. if len(list) != 0 {
  42. t.Fatalf("expected 0 vxlan tunnels, got %d", len(list))
  43. }
  44. // 2. POST /api/vpn/vxlan (create disabled instance)
  45. payload := vpn.VXLANInstance{
  46. ID: "vxlan-unit-1",
  47. Name: "vxlan-test",
  48. VNI: 1050,
  49. Port: 4789,
  50. Disabled: true,
  51. Comment: "API test vxlan",
  52. }
  53. b, _ := json.Marshal(payload)
  54. req = httptest.NewRequest(http.MethodPost, "/api/vpn/vxlan", bytes.NewReader(b))
  55. rec = httptest.NewRecorder()
  56. srv.mux.ServeHTTP(rec, req)
  57. if rec.Code != http.StatusOK {
  58. t.Fatalf("POST /api/vpn/vxlan code = %d, body = %s; want 200", rec.Code, rec.Body.String())
  59. }
  60. // 3. GET /api/interface/vxlan alias
  61. req = httptest.NewRequest(http.MethodGet, "/api/interface/vxlan", nil)
  62. rec = httptest.NewRecorder()
  63. srv.mux.ServeHTTP(rec, req)
  64. if rec.Code != http.StatusOK {
  65. t.Fatalf("GET /api/interface/vxlan code = %d; want 200", rec.Code)
  66. }
  67. list = nil
  68. _ = json.NewDecoder(rec.Body).Decode(&list)
  69. if len(list) != 1 || list[0].Name != "vxlan-test" {
  70. t.Fatalf("expected 1 vxlan named vxlan-test, got %+v", list)
  71. }
  72. // 4. POST /api/vpn/vxlan/vteps
  73. vtepPayload := vpn.VXLANVtep{
  74. Interface: "vxlan-test",
  75. RemoteIP: "192.168.100.2",
  76. Comment: "Remote VTEP 1",
  77. }
  78. vb, _ := json.Marshal(vtepPayload)
  79. req = httptest.NewRequest(http.MethodPost, "/api/vpn/vxlan/vteps", bytes.NewReader(vb))
  80. rec = httptest.NewRecorder()
  81. srv.mux.ServeHTTP(rec, req)
  82. if rec.Code != http.StatusOK {
  83. t.Fatalf("POST /api/vpn/vxlan/vteps code = %d, body = %s; want 200", rec.Code, rec.Body.String())
  84. }
  85. // 5. GET /api/vpn/vxlan/vteps
  86. req = httptest.NewRequest(http.MethodGet, "/api/vpn/vxlan/vteps?interface=vxlan-test", nil)
  87. rec = httptest.NewRecorder()
  88. srv.mux.ServeHTTP(rec, req)
  89. if rec.Code != http.StatusOK {
  90. t.Fatalf("GET /api/vpn/vxlan/vteps code = %d; want 200", rec.Code)
  91. }
  92. var vteps []*vpn.VXLANVtep
  93. _ = json.NewDecoder(rec.Body).Decode(&vteps)
  94. if len(vteps) != 1 || vteps[0].RemoteIP != "192.168.100.2" {
  95. t.Fatalf("expected 1 vtep with remote-ip 192.168.100.2, got %+v", vteps)
  96. }
  97. // 6. DELETE /api/vpn/vxlan/{id}/vteps/{vtepid}
  98. req = httptest.NewRequest(http.MethodDelete, "/api/vpn/vxlan/vxlan-unit-1/vteps/192.168.100.2", nil)
  99. rec = httptest.NewRecorder()
  100. srv.mux.ServeHTTP(rec, req)
  101. if rec.Code != http.StatusOK {
  102. t.Fatalf("DELETE vtep code = %d, body = %s; want 200", rec.Code, rec.Body.String())
  103. }
  104. // 7. DELETE /api/vpn/vxlan/{id}
  105. req = httptest.NewRequest(http.MethodDelete, "/api/vpn/vxlan/vxlan-unit-1", nil)
  106. rec = httptest.NewRecorder()
  107. srv.mux.ServeHTTP(rec, req)
  108. if rec.Code != http.StatusOK {
  109. t.Fatalf("DELETE vxlan code = %d; want 200", rec.Code)
  110. }
  111. req = httptest.NewRequest(http.MethodGet, "/api/vpn/vxlan", nil)
  112. rec = httptest.NewRecorder()
  113. srv.mux.ServeHTTP(rec, req)
  114. list = nil
  115. _ = json.NewDecoder(rec.Body).Decode(&list)
  116. if len(list) != 0 {
  117. t.Fatalf("expected 0 vxlan tunnels after delete, got %d", len(list))
  118. }
  119. }