mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-02-19 07:50:43 +01:00
427 lines
14 KiB
Go
427 lines
14 KiB
Go
package proxmox
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestClusterClient_GetNodeStatus(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if r.URL.Path == "/api2/json/nodes" {
|
|
fmt.Fprint(w, `{"data":[{"node":"node1","status":"online"}]}`)
|
|
return
|
|
}
|
|
if r.URL.Path == "/api2/json/nodes/node1/status" {
|
|
fmt.Fprint(w, `{"data":{"cpu":0.25,"uptime":123}}`)
|
|
return
|
|
}
|
|
w.WriteHeader(http.StatusNotFound)
|
|
}))
|
|
defer server.Close()
|
|
|
|
cfg := ClientConfig{Host: server.URL, TokenName: "u@p!t", TokenValue: "v"}
|
|
cc := NewClusterClient("test", cfg, []string{server.URL}, nil)
|
|
|
|
status, err := cc.GetNodeStatus(context.Background(), "node1")
|
|
if err != nil {
|
|
t.Fatalf("GetNodeStatus failed: %v", err)
|
|
}
|
|
if status == nil || status.Uptime != 123 {
|
|
t.Fatalf("unexpected status: %+v", status)
|
|
}
|
|
}
|
|
|
|
func TestClusterClient_GetAllStorage(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if r.URL.Path == "/api2/json/nodes" {
|
|
fmt.Fprint(w, `{"data":[{"node":"node1","status":"online"}]}`)
|
|
return
|
|
}
|
|
if r.URL.Path == "/api2/json/storage" {
|
|
fmt.Fprint(w, `{"data":[{"storage":"local"}]}`)
|
|
return
|
|
}
|
|
w.WriteHeader(http.StatusNotFound)
|
|
}))
|
|
defer server.Close()
|
|
|
|
cfg := ClientConfig{Host: server.URL, TokenName: "u@p!t", TokenValue: "v"}
|
|
cc := NewClusterClient("test", cfg, []string{server.URL}, nil)
|
|
|
|
storage, err := cc.GetAllStorage(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("GetAllStorage failed: %v", err)
|
|
}
|
|
if len(storage) != 1 || storage[0].Storage != "local" {
|
|
t.Fatalf("unexpected storage result: %+v", storage)
|
|
}
|
|
}
|
|
|
|
func TestClusterClient_GetVMStatus(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if r.URL.Path == "/api2/json/nodes" {
|
|
fmt.Fprint(w, `{"data":[{"node":"node1","status":"online"}]}`)
|
|
return
|
|
}
|
|
if r.URL.Path == "/api2/json/nodes/node1/qemu/100/status/current" {
|
|
fmt.Fprint(w, `{"data":{"status":"running","cpu":0.5,"uptime":10,"agent":1}}`)
|
|
return
|
|
}
|
|
w.WriteHeader(http.StatusNotFound)
|
|
}))
|
|
defer server.Close()
|
|
|
|
cfg := ClientConfig{Host: server.URL, TokenName: "u@p!t", TokenValue: "v"}
|
|
cc := NewClusterClient("test", cfg, []string{server.URL}, nil)
|
|
|
|
status, err := cc.GetVMStatus(context.Background(), "node1", 100)
|
|
if err != nil {
|
|
t.Fatalf("GetVMStatus failed: %v", err)
|
|
}
|
|
if status == nil || status.Status != "running" {
|
|
t.Fatalf("unexpected VM status: %+v", status)
|
|
}
|
|
}
|
|
|
|
func TestClusterClient_GetContainerStatus(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if r.URL.Path == "/api2/json/nodes" {
|
|
fmt.Fprint(w, `{"data":[{"node":"node1","status":"online"}]}`)
|
|
return
|
|
}
|
|
if r.URL.Path == "/api2/json/nodes/node1/lxc/101/status/current" {
|
|
fmt.Fprint(w, `{"data":{"status":"running"}}`)
|
|
return
|
|
}
|
|
w.WriteHeader(http.StatusNotFound)
|
|
}))
|
|
defer server.Close()
|
|
|
|
cfg := ClientConfig{Host: server.URL, TokenName: "u@p!t", TokenValue: "v"}
|
|
cc := NewClusterClient("test", cfg, []string{server.URL}, nil)
|
|
|
|
status, err := cc.GetContainerStatus(context.Background(), "node1", 101)
|
|
if err != nil {
|
|
t.Fatalf("GetContainerStatus failed: %v", err)
|
|
}
|
|
if status == nil || status.Status != "running" {
|
|
t.Fatalf("unexpected container status: %+v", status)
|
|
}
|
|
}
|
|
|
|
func TestClusterClient_GetVMConfig(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if r.URL.Path == "/api2/json/nodes" {
|
|
fmt.Fprint(w, `{"data":[{"node":"node1","status":"online"}]}`)
|
|
return
|
|
}
|
|
if r.URL.Path == "/api2/json/nodes/node1/qemu/100/config" {
|
|
fmt.Fprint(w, `{"data":{"name":"vm-100"}}`)
|
|
return
|
|
}
|
|
w.WriteHeader(http.StatusNotFound)
|
|
}))
|
|
defer server.Close()
|
|
|
|
cfg := ClientConfig{Host: server.URL, TokenName: "u@p!t", TokenValue: "v"}
|
|
cc := NewClusterClient("test", cfg, []string{server.URL}, nil)
|
|
|
|
config, err := cc.GetVMConfig(context.Background(), "node1", 100)
|
|
if err != nil {
|
|
t.Fatalf("GetVMConfig failed: %v", err)
|
|
}
|
|
if config["name"] != "vm-100" {
|
|
t.Fatalf("unexpected VM config: %+v", config)
|
|
}
|
|
}
|
|
|
|
func TestClusterClient_GetVMAgentInfo(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if r.URL.Path == "/api2/json/nodes" {
|
|
fmt.Fprint(w, `{"data":[{"node":"node1","status":"online"}]}`)
|
|
return
|
|
}
|
|
if r.URL.Path == "/api2/json/nodes/node1/qemu/100/agent/get-osinfo" {
|
|
fmt.Fprint(w, `{"data":{"name":"debian"}}`)
|
|
return
|
|
}
|
|
w.WriteHeader(http.StatusNotFound)
|
|
}))
|
|
defer server.Close()
|
|
|
|
cfg := ClientConfig{Host: server.URL, TokenName: "u@p!t", TokenValue: "v"}
|
|
cc := NewClusterClient("test", cfg, []string{server.URL}, nil)
|
|
|
|
info, err := cc.GetVMAgentInfo(context.Background(), "node1", 100)
|
|
if err != nil {
|
|
t.Fatalf("GetVMAgentInfo failed: %v", err)
|
|
}
|
|
if info["name"] != "debian" {
|
|
t.Fatalf("unexpected agent info: %+v", info)
|
|
}
|
|
}
|
|
|
|
func TestClusterClient_GetVMAgentVersion(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if r.URL.Path == "/api2/json/nodes" {
|
|
fmt.Fprint(w, `{"data":[{"node":"node1","status":"online"}]}`)
|
|
return
|
|
}
|
|
if r.URL.Path == "/api2/json/nodes/node1/qemu/100/agent/info" {
|
|
fmt.Fprint(w, `{"data":{"result":{"version":"1.2.3"}}}`)
|
|
return
|
|
}
|
|
w.WriteHeader(http.StatusNotFound)
|
|
}))
|
|
defer server.Close()
|
|
|
|
cfg := ClientConfig{Host: server.URL, TokenName: "u@p!t", TokenValue: "v"}
|
|
cc := NewClusterClient("test", cfg, []string{server.URL}, nil)
|
|
|
|
version, err := cc.GetVMAgentVersion(context.Background(), "node1", 100)
|
|
if err != nil {
|
|
t.Fatalf("GetVMAgentVersion failed: %v", err)
|
|
}
|
|
if version != "1.2.3" {
|
|
t.Fatalf("unexpected version: %s", version)
|
|
}
|
|
}
|
|
|
|
func TestClusterClient_GetVMNetworkInterfaces(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if r.URL.Path == "/api2/json/nodes" {
|
|
fmt.Fprint(w, `{"data":[{"node":"node1","status":"online"}]}`)
|
|
return
|
|
}
|
|
if r.URL.Path == "/api2/json/nodes/node1/qemu/100/agent/network-get-interfaces" {
|
|
fmt.Fprint(w, `{"data":{"result":[{"name":"eth0"}]}}`)
|
|
return
|
|
}
|
|
w.WriteHeader(http.StatusNotFound)
|
|
}))
|
|
defer server.Close()
|
|
|
|
cfg := ClientConfig{Host: server.URL, TokenName: "u@p!t", TokenValue: "v"}
|
|
cc := NewClusterClient("test", cfg, []string{server.URL}, nil)
|
|
|
|
ifaces, err := cc.GetVMNetworkInterfaces(context.Background(), "node1", 100)
|
|
if err != nil {
|
|
t.Fatalf("GetVMNetworkInterfaces failed: %v", err)
|
|
}
|
|
if len(ifaces) != 1 || ifaces[0].Name != "eth0" {
|
|
t.Fatalf("unexpected interfaces: %+v", ifaces)
|
|
}
|
|
}
|
|
|
|
func TestClusterClient_GetContainerInterfaces(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if r.URL.Path == "/api2/json/nodes" {
|
|
fmt.Fprint(w, `{"data":[{"node":"node1","status":"online"}]}`)
|
|
return
|
|
}
|
|
if r.URL.Path == "/api2/json/nodes/node1/lxc/101/interfaces" {
|
|
fmt.Fprint(w, `{"data":[{"name":"eth0","ip":"10.0.0.2"}]}`)
|
|
return
|
|
}
|
|
w.WriteHeader(http.StatusNotFound)
|
|
}))
|
|
defer server.Close()
|
|
|
|
cfg := ClientConfig{Host: server.URL, TokenName: "u@p!t", TokenValue: "v"}
|
|
cc := NewClusterClient("test", cfg, []string{server.URL}, nil)
|
|
|
|
ifaces, err := cc.GetContainerInterfaces(context.Background(), "node1", 101)
|
|
if err != nil {
|
|
t.Fatalf("GetContainerInterfaces failed: %v", err)
|
|
}
|
|
if len(ifaces) != 1 || ifaces[0].Name != "eth0" {
|
|
t.Fatalf("unexpected interfaces: %+v", ifaces)
|
|
}
|
|
}
|
|
|
|
func TestClusterClient_GetClusterResources(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if r.URL.Path == "/api2/json/nodes" {
|
|
fmt.Fprint(w, `{"data":[{"node":"node1","status":"online"}]}`)
|
|
return
|
|
}
|
|
if strings.HasPrefix(r.URL.Path, "/api2/json/cluster/resources") {
|
|
fmt.Fprint(w, `{"data":[{"id":"qemu/100","type":"qemu","node":"node1"}]}`)
|
|
return
|
|
}
|
|
w.WriteHeader(http.StatusNotFound)
|
|
}))
|
|
defer server.Close()
|
|
|
|
cfg := ClientConfig{Host: server.URL, TokenName: "u@p!t", TokenValue: "v"}
|
|
cc := NewClusterClient("test", cfg, []string{server.URL}, nil)
|
|
|
|
resources, err := cc.GetClusterResources(context.Background(), "qemu")
|
|
if err != nil {
|
|
t.Fatalf("GetClusterResources failed: %v", err)
|
|
}
|
|
if len(resources) != 1 || resources[0].ID != "qemu/100" {
|
|
t.Fatalf("unexpected resources: %+v", resources)
|
|
}
|
|
}
|
|
|
|
func TestClusterClient_GetClusterResources_AllTypes(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if r.URL.Path == "/api2/json/nodes" {
|
|
fmt.Fprint(w, `{"data":[{"node":"node1","status":"online"}]}`)
|
|
return
|
|
}
|
|
if r.URL.Path == "/api2/json/cluster/resources" {
|
|
fmt.Fprint(w, `{"data":[{"id":"lxc/200","type":"lxc","node":"node1"}]}`)
|
|
return
|
|
}
|
|
w.WriteHeader(http.StatusNotFound)
|
|
}))
|
|
defer server.Close()
|
|
|
|
cfg := ClientConfig{Host: server.URL, TokenName: "u@p!t", TokenValue: "v"}
|
|
cc := NewClusterClient("test", cfg, []string{server.URL}, nil)
|
|
|
|
resources, err := cc.GetClusterResources(context.Background(), "")
|
|
if err != nil {
|
|
t.Fatalf("GetClusterResources failed: %v", err)
|
|
}
|
|
if len(resources) != 1 || resources[0].ID != "lxc/200" {
|
|
t.Fatalf("unexpected resources: %+v", resources)
|
|
}
|
|
}
|
|
|
|
func TestClusterClient_GetClusterStatusAndIsClusterMember(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if r.URL.Path == "/api2/json/nodes" {
|
|
fmt.Fprint(w, `{"data":[{"node":"node1","status":"online"}]}`)
|
|
return
|
|
}
|
|
if r.URL.Path == "/api2/json/cluster/status" {
|
|
fmt.Fprint(w, `{"data":[{"type":"cluster","name":"pve"},{"type":"node","name":"node1"}]}`)
|
|
return
|
|
}
|
|
w.WriteHeader(http.StatusNotFound)
|
|
}))
|
|
defer server.Close()
|
|
|
|
cfg := ClientConfig{Host: server.URL, TokenName: "u@p!t", TokenValue: "v"}
|
|
cc := NewClusterClient("test", cfg, []string{server.URL}, nil)
|
|
|
|
status, err := cc.GetClusterStatus(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("GetClusterStatus failed: %v", err)
|
|
}
|
|
if len(status) != 2 {
|
|
t.Fatalf("unexpected cluster status: %+v", status)
|
|
}
|
|
|
|
member, err := cc.IsClusterMember(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("IsClusterMember failed: %v", err)
|
|
}
|
|
if !member {
|
|
t.Fatal("expected cluster membership to be true")
|
|
}
|
|
}
|
|
|
|
func TestClusterClient_GetZFSPoolStatus(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if r.URL.Path == "/api2/json/nodes" {
|
|
fmt.Fprint(w, `{"data":[{"node":"node1","status":"online"}]}`)
|
|
return
|
|
}
|
|
if r.URL.Path == "/api2/json/nodes/node1/disks/zfs" {
|
|
fmt.Fprint(w, `{"data":[{"name":"rpool","health":"ONLINE"}]}`)
|
|
return
|
|
}
|
|
w.WriteHeader(http.StatusNotFound)
|
|
}))
|
|
defer server.Close()
|
|
|
|
cfg := ClientConfig{Host: server.URL, TokenName: "u@p!t", TokenValue: "v"}
|
|
cc := NewClusterClient("test", cfg, []string{server.URL}, nil)
|
|
|
|
pools, err := cc.GetZFSPoolStatus(context.Background(), "node1")
|
|
if err != nil {
|
|
t.Fatalf("GetZFSPoolStatus failed: %v", err)
|
|
}
|
|
if len(pools) != 1 || pools[0].Name != "rpool" {
|
|
t.Fatalf("unexpected pools: %+v", pools)
|
|
}
|
|
}
|
|
|
|
func TestClusterClient_GetDisks(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if r.URL.Path == "/api2/json/nodes" {
|
|
fmt.Fprint(w, `{"data":[{"node":"node1","status":"online"}]}`)
|
|
return
|
|
}
|
|
if r.URL.Path == "/api2/json/nodes/node1/disks/list" {
|
|
fmt.Fprint(w, `{"data":[{"devpath":"/dev/sda","model":"Samsung","wearout":"N/A"}]}`)
|
|
return
|
|
}
|
|
w.WriteHeader(http.StatusNotFound)
|
|
}))
|
|
defer server.Close()
|
|
|
|
cfg := ClientConfig{Host: server.URL, TokenName: "u@p!t", TokenValue: "v"}
|
|
cc := NewClusterClient("test", cfg, []string{server.URL}, nil)
|
|
|
|
disks, err := cc.GetDisks(context.Background(), "node1")
|
|
if err != nil {
|
|
t.Fatalf("GetDisks failed: %v", err)
|
|
}
|
|
if len(disks) != 1 || disks[0].DevPath != "/dev/sda" {
|
|
t.Fatalf("unexpected disks: %+v", disks)
|
|
}
|
|
if disks[0].Wearout != wearoutUnknown {
|
|
t.Fatalf("expected wearout unknown, got %d", disks[0].Wearout)
|
|
}
|
|
}
|
|
|
|
func TestClusterClient_GetNodePendingUpdates(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if r.URL.Path == "/api2/json/nodes" {
|
|
fmt.Fprint(w, `{"data":[{"node":"node1","status":"online"}]}`)
|
|
return
|
|
}
|
|
if r.URL.Path == "/api2/json/nodes/node1/apt/update" {
|
|
fmt.Fprint(w, `{"data":[{"Package":"vim","Version":"2"}]}`)
|
|
return
|
|
}
|
|
w.WriteHeader(http.StatusNotFound)
|
|
}))
|
|
defer server.Close()
|
|
|
|
cfg := ClientConfig{Host: server.URL, TokenName: "u@p!t", TokenValue: "v"}
|
|
cc := NewClusterClient("test", cfg, []string{server.URL}, nil)
|
|
|
|
updates, err := cc.GetNodePendingUpdates(context.Background(), "node1")
|
|
if err != nil {
|
|
t.Fatalf("GetNodePendingUpdates failed: %v", err)
|
|
}
|
|
if len(updates) != 1 || updates[0].Package != "vim" {
|
|
t.Fatalf("unexpected updates: %+v", updates)
|
|
}
|
|
}
|