Files
garage-ui/backend/internal/services/admin_factory_test.go
T

150 lines
4.4 KiB
Go

package services
import (
"errors"
"net/http"
"net/http/httptest"
"testing"
"Noooste/garage-ui/internal/config"
)
func TestErrUnsupportedIsSentinel(t *testing.T) {
err := ErrUnsupported
if !errors.Is(err, ErrUnsupported) {
t.Fatal("ErrUnsupported should match itself via errors.Is")
}
}
func TestCapabilitiesV2AllTrue(t *testing.T) {
caps := CapabilitiesV2()
if !caps.ClusterStatistics || !caps.NodeInfo || !caps.NodeStatistics {
t.Fatalf("v2 capabilities should all be true, got %+v", caps)
}
}
func TestCapabilitiesV1AllFalse(t *testing.T) {
caps := CapabilitiesV1()
if caps.ClusterStatistics || caps.NodeInfo || caps.NodeStatistics {
t.Fatalf("v1 capabilities should all be false, got %+v", caps)
}
}
func TestDetectVersion_V2(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/v2/GetClusterHealth" {
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(`{"status":"healthy"}`))
return
}
w.WriteHeader(404)
}))
t.Cleanup(srv.Close)
cfg := &config.GarageConfig{AdminEndpoint: srv.URL, AdminToken: "tok"}
result, err := NewAdminService(cfg, "")
if err != nil {
t.Fatal(err)
}
if result.APIVersion != "v2" {
t.Fatalf("expected v2, got %s", result.APIVersion)
}
if !result.Capabilities.ClusterStatistics {
t.Fatal("v2 should have ClusterStatistics capability")
}
}
func TestDetectVersion_V1(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/v2/GetClusterHealth" {
w.WriteHeader(404)
return
}
if r.URL.Path == "/v1/health" {
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(`{"status":"healthy"}`))
return
}
w.WriteHeader(404)
}))
t.Cleanup(srv.Close)
cfg := &config.GarageConfig{AdminEndpoint: srv.URL, AdminToken: "tok"}
result, err := NewAdminService(cfg, "")
if err != nil {
t.Fatal(err)
}
if result.APIVersion != "v1" {
t.Fatalf("expected v1, got %s", result.APIVersion)
}
if result.Capabilities.ClusterStatistics {
t.Fatal("v1 should not have ClusterStatistics capability")
}
}
func TestDetectVersion_Unreachable(t *testing.T) {
cfg := &config.GarageConfig{AdminEndpoint: "http://127.0.0.1:1", AdminToken: "tok"}
_, err := NewAdminService(cfg, "")
if err == nil {
t.Fatal("expected error for unreachable server")
}
}
// Garage v2.x serves /v1/health too, so a transient failure of the /v2 probe
// must not cause a permanent downgrade to the (broken on v2.x) v1 client.
// Regression test for https://github.com/Noooste/garage-ui/issues/78
func TestDetectVersion_V2_TransientProbeFailure(t *testing.T) {
var v2Hits int
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/v2/GetClusterHealth":
v2Hits++
if v2Hits < 3 { // fail the first two attempts, then recover
w.WriteHeader(http.StatusServiceUnavailable)
return
}
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(`{"status":"healthy"}`))
case "/v1/health": // v2.x still answers this
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(`{"status":"healthy"}`))
default:
w.WriteHeader(http.StatusNotFound)
}
}))
t.Cleanup(srv.Close)
cfg := &config.GarageConfig{AdminEndpoint: srv.URL, AdminToken: "tok"}
result, err := NewAdminService(cfg, "")
if err != nil {
t.Fatal(err)
}
if result.APIVersion != "v2" {
t.Fatalf("expected v2 after transient probe failure, got %s", result.APIVersion)
}
}
// A server that answers /v1/health but returns a server error (not 404) for
// /v2/GetClusterHealth must NOT be detected as v1, because v2.x servers also
// answer /v1/health. Falling through to v1 here is the issue #78 misdetection.
func TestDetectVersion_DoesNotDowngradeOnV2ServerError(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/v2/GetClusterHealth":
w.WriteHeader(http.StatusServiceUnavailable)
case "/v1/health":
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(`{"status":"healthy"}`))
default:
w.WriteHeader(http.StatusNotFound)
}
}))
t.Cleanup(srv.Close)
cfg := &config.GarageConfig{AdminEndpoint: srv.URL, AdminToken: "tok"}
result, err := NewAdminService(cfg, "")
if err == nil && result.APIVersion == "v1" {
t.Fatal("must not downgrade to v1 when /v2 returns a server error; v2.x also serves /v1/health")
}
}