mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-20 10:52:08 +00:00
bd6f77e093
Tighten v5-to-v6 upgrade safety, release installability, provider MSP mode handling, AI cost accounting, metrics flushing, and frontend guardrails for the v6.0.0 GA candidate.
282 lines
7.6 KiB
Go
282 lines
7.6 KiB
Go
package proxmox
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
)
|
|
|
|
func TestGetCephStatus(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.URL.Path != "/cluster/ceph/status" {
|
|
http.NotFound(w, r)
|
|
return
|
|
}
|
|
resp := map[string]interface{}{
|
|
"data": map[string]interface{}{
|
|
"fsid": "fsid-1",
|
|
"health": map[string]interface{}{
|
|
"status": "HEALTH_OK",
|
|
"summary": []map[string]interface{}{
|
|
{"severity": "info", "summary": "ok"},
|
|
},
|
|
"checks": map[string]interface{}{},
|
|
},
|
|
"servicemap": map[string]interface{}{
|
|
"services": map[string]interface{}{},
|
|
},
|
|
"monmap": map[string]interface{}{
|
|
"num_mons": 3,
|
|
},
|
|
"mgrmap": map[string]interface{}{
|
|
"available": true,
|
|
"num_mgrs": 2,
|
|
"active_name": "mgr-a",
|
|
"standbys": []string{"mgr-b"},
|
|
},
|
|
"osdmap": map[string]interface{}{
|
|
"num_osds": 1,
|
|
"num_up_osds": 1,
|
|
"num_in_osds": 1,
|
|
},
|
|
"pgmap": map[string]interface{}{
|
|
"num_pgs": 5,
|
|
},
|
|
},
|
|
}
|
|
_ = json.NewEncoder(w).Encode(resp)
|
|
}))
|
|
defer server.Close()
|
|
|
|
client := &Client{baseURL: server.URL, httpClient: server.Client()}
|
|
status, err := client.GetCephStatus(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if status.FSID != "fsid-1" || status.Health.Status != "HEALTH_OK" {
|
|
t.Fatalf("unexpected status: %+v", status)
|
|
}
|
|
if status.MonMap.NumMons != 3 || status.MgrMap.NumMgrs != 2 || status.MgrMap.ActiveName != "mgr-a" {
|
|
t.Fatalf("expected monmap/mgrmap to decode, got %+v", status)
|
|
}
|
|
}
|
|
|
|
func TestGetCephStatusCountsMonitorArrayFallback(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.URL.Path != "/cluster/ceph/status" {
|
|
http.NotFound(w, r)
|
|
return
|
|
}
|
|
resp := map[string]interface{}{
|
|
"data": map[string]interface{}{
|
|
"fsid": "fsid-1",
|
|
"health": map[string]interface{}{
|
|
"status": "HEALTH_OK",
|
|
"summary": []map[string]interface{}{},
|
|
"checks": map[string]interface{}{},
|
|
},
|
|
"servicemap": map[string]interface{}{
|
|
"services": map[string]interface{}{},
|
|
},
|
|
"monmap": map[string]interface{}{
|
|
"mons": []map[string]interface{}{
|
|
{"name": "mon-a", "rank": 0},
|
|
{"name": "mon-b", "rank": 1},
|
|
{"name": "mon-c", "rank": 2},
|
|
},
|
|
},
|
|
"mgrmap": map[string]interface{}{
|
|
"available": true,
|
|
"num_mgrs": 3,
|
|
"active_name": "mgr-a",
|
|
"standbys": []string{"mgr-b", "mgr-c"},
|
|
},
|
|
"osdmap": map[string]interface{}{
|
|
"num_osds": 9,
|
|
"num_up_osds": 9,
|
|
"num_in_osds": 9,
|
|
},
|
|
"pgmap": map[string]interface{}{
|
|
"num_pgs": 129,
|
|
},
|
|
},
|
|
}
|
|
_ = json.NewEncoder(w).Encode(resp)
|
|
}))
|
|
defer server.Close()
|
|
|
|
client := &Client{baseURL: server.URL, httpClient: server.Client()}
|
|
status, err := client.GetCephStatus(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if status.MonMap.NumMons != 3 {
|
|
t.Fatalf("expected monmap.mons fallback to count 3 monitors, got %+v", status.MonMap)
|
|
}
|
|
}
|
|
|
|
func TestGetCephStatusCountsQuorumMonMapFallbacks(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.URL.Path != "/cluster/ceph/status" {
|
|
http.NotFound(w, r)
|
|
return
|
|
}
|
|
resp := map[string]interface{}{
|
|
"data": map[string]interface{}{
|
|
"fsid": "fsid-1",
|
|
"health": map[string]interface{}{
|
|
"status": "HEALTH_OK",
|
|
"summary": []map[string]interface{}{},
|
|
"checks": map[string]interface{}{},
|
|
},
|
|
"servicemap": map[string]interface{}{
|
|
"services": map[string]interface{}{},
|
|
},
|
|
"monmap": map[string]interface{}{
|
|
"monitors": []string{"mon-a", "mon-b"},
|
|
"quorum_names": []string{
|
|
"mon-a",
|
|
"mon-b",
|
|
"mon-c",
|
|
},
|
|
"quorum": []interface{}{0, 1, 2},
|
|
},
|
|
"mgrmap": map[string]interface{}{
|
|
"available": true,
|
|
"num_mgrs": 1,
|
|
"active_name": "mgr-a",
|
|
"standbys": []string{},
|
|
},
|
|
"osdmap": map[string]interface{}{},
|
|
"pgmap": map[string]interface{}{},
|
|
},
|
|
}
|
|
_ = json.NewEncoder(w).Encode(resp)
|
|
}))
|
|
defer server.Close()
|
|
|
|
client := &Client{baseURL: server.URL, httpClient: server.Client()}
|
|
status, err := client.GetCephStatus(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if status.MonMap.NumMons != 3 {
|
|
t.Fatalf("expected quorum fallback to count 3 monitors, got %+v", status.MonMap)
|
|
}
|
|
if len(status.MonMap.Monitors) != 2 || status.MonMap.Monitors[0].Name != "mon-a" {
|
|
t.Fatalf("expected monitor aliases to be preserved, got %+v", status.MonMap.Monitors)
|
|
}
|
|
if len(status.MonMap.QuorumNames) != 3 || len(status.MonMap.Quorum) != 3 {
|
|
t.Fatalf("expected quorum metadata to be preserved, got %+v", status.MonMap)
|
|
}
|
|
}
|
|
|
|
func TestGetCephStatusAcceptsStructuredManagerStandbys(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.URL.Path != "/cluster/ceph/status" {
|
|
http.NotFound(w, r)
|
|
return
|
|
}
|
|
resp := map[string]interface{}{
|
|
"data": map[string]interface{}{
|
|
"fsid": "fsid-1",
|
|
"health": map[string]interface{}{
|
|
"status": "HEALTH_OK",
|
|
"summary": []map[string]interface{}{},
|
|
"checks": map[string]interface{}{},
|
|
},
|
|
"servicemap": map[string]interface{}{
|
|
"services": map[string]interface{}{},
|
|
},
|
|
"monmap": map[string]interface{}{
|
|
"num_mons": 3,
|
|
},
|
|
"mgrmap": map[string]interface{}{
|
|
"available": true,
|
|
"num_mgrs": 3,
|
|
"active_name": "mgr-a",
|
|
"standbys": []map[string]interface{}{
|
|
{"name": "mgr-b"},
|
|
{"name": "mgr-c"},
|
|
},
|
|
},
|
|
"osdmap": map[string]interface{}{
|
|
"num_osds": 1,
|
|
"num_up_osds": 1,
|
|
"num_in_osds": 1,
|
|
},
|
|
"pgmap": map[string]interface{}{
|
|
"num_pgs": 5,
|
|
},
|
|
},
|
|
}
|
|
_ = json.NewEncoder(w).Encode(resp)
|
|
}))
|
|
defer server.Close()
|
|
|
|
client := &Client{baseURL: server.URL, httpClient: server.Client()}
|
|
status, err := client.GetCephStatus(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if len(status.MgrMap.Standbys) != 2 {
|
|
t.Fatalf("expected 2 standbys, got %+v", status.MgrMap.Standbys)
|
|
}
|
|
if status.MgrMap.Standbys[0] != "mgr-b" || status.MgrMap.Standbys[1] != "mgr-c" {
|
|
t.Fatalf("expected structured standbys to decode into names, got %+v", status.MgrMap.Standbys)
|
|
}
|
|
}
|
|
|
|
func TestGetCephDF(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.URL.Path != "/cluster/ceph/df" {
|
|
http.NotFound(w, r)
|
|
return
|
|
}
|
|
resp := map[string]interface{}{
|
|
"data": map[string]interface{}{
|
|
"data": map[string]interface{}{
|
|
"stats": map[string]interface{}{
|
|
"total_bytes": 100,
|
|
"total_used_bytes": 40,
|
|
"total_avail_bytes": 60,
|
|
"total_used_raw_bytes": 45,
|
|
"percent_used": 40.0,
|
|
},
|
|
"pools": []map[string]interface{}{
|
|
{
|
|
"id": 1,
|
|
"name": "pool1",
|
|
"stats": map[string]interface{}{
|
|
"bytes_used": 10,
|
|
"kb_used": 20,
|
|
"max_avail": 30,
|
|
"objects": 40,
|
|
"percent_used": 10.0,
|
|
"dirty": 0,
|
|
"stored_raw": 50,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
_ = json.NewEncoder(w).Encode(resp)
|
|
}))
|
|
defer server.Close()
|
|
|
|
client := &Client{baseURL: server.URL, httpClient: server.Client()}
|
|
df, err := client.GetCephDF(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if df.Data.Stats.TotalBytes != 100 || len(df.Data.Pools) != 1 {
|
|
t.Fatalf("unexpected df: %+v", df)
|
|
}
|
|
}
|