Add HostConfig + Cluster fields to models and update docs
This commit is contained in:
parent
960ef62342
commit
00c4472d6c
9 changed files with 1805 additions and 9 deletions
|
|
@ -14,15 +14,18 @@ var CLUSTERSTAT = map[string]int{
|
|||
var JSONBCLFields = []string{"resources", "host_types", "host_models", "cluster_admins"}
|
||||
|
||||
type ClusterInfo struct {
|
||||
ClusterName string `json:"cluster_name"`
|
||||
Version string `json:"version"`
|
||||
Status int `json:"status"`
|
||||
ControllerName string `json:"controller_name"`
|
||||
NumServers int `json:"num_servers"`
|
||||
Resources string `json:"resources"`
|
||||
HostTypes string `json:"host_types"`
|
||||
HostModels string `json:"host_models"`
|
||||
ClusterAdmins string `json:"cluster_admins"`
|
||||
ClusterName string `json:"cluster_name"`
|
||||
Version string `json:"version"`
|
||||
Status int `json:"status"`
|
||||
ControllerName string `json:"controller_name"`
|
||||
NumServers int `json:"num_servers"`
|
||||
Resources string `json:"resources"`
|
||||
HostTypes string `json:"host_types"`
|
||||
HostModels string `json:"host_models"`
|
||||
ClusterAdmins string `json:"cluster_admins"`
|
||||
HeartbeatInterval int `json:"heartbeat_interval"`
|
||||
Vcpus int `json:"vcpus"`
|
||||
InactiveHeartbeatCount int `json:"inactive_heartbeat_count"`
|
||||
}
|
||||
|
||||
var CLUSTER_SUPPORT_FILTERS = []string{
|
||||
|
|
|
|||
125
src/frontend/apiserver/models/clusters_test.go
Normal file
125
src/frontend/apiserver/models/clusters_test.go
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestClusterInfo_NewFields(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
cluster ClusterInfo
|
||||
field string
|
||||
want interface{}
|
||||
}{
|
||||
{
|
||||
name: "HeartbeatInterval field exists and serializes",
|
||||
cluster: ClusterInfo{ClusterName: "test", HeartbeatInterval: 30},
|
||||
field: "heartbeat_interval",
|
||||
want: float64(30),
|
||||
},
|
||||
{
|
||||
name: "Vcpus field exists and serializes",
|
||||
cluster: ClusterInfo{ClusterName: "test", Vcpus: 16},
|
||||
field: "vcpus",
|
||||
want: float64(16),
|
||||
},
|
||||
{
|
||||
name: "InactiveHeartbeatCount field exists and serializes",
|
||||
cluster: ClusterInfo{ClusterName: "test", InactiveHeartbeatCount: 3},
|
||||
field: "inactive_heartbeat_count",
|
||||
want: float64(3),
|
||||
},
|
||||
{
|
||||
name: "HeartbeatInterval zero value serializes as 0 not omitted",
|
||||
cluster: ClusterInfo{ClusterName: "test", HeartbeatInterval: 0, Vcpus: 0, InactiveHeartbeatCount: 0},
|
||||
field: "heartbeat_interval",
|
||||
want: float64(0),
|
||||
},
|
||||
{
|
||||
name: "Vcpus zero value serializes as 0 not omitted",
|
||||
cluster: ClusterInfo{ClusterName: "test", HeartbeatInterval: 0, Vcpus: 0, InactiveHeartbeatCount: 0},
|
||||
field: "vcpus",
|
||||
want: float64(0),
|
||||
},
|
||||
{
|
||||
name: "InactiveHeartbeatCount zero value serializes as 0 not omitted",
|
||||
cluster: ClusterInfo{ClusterName: "test", HeartbeatInterval: 0, Vcpus: 0, InactiveHeartbeatCount: 0},
|
||||
field: "inactive_heartbeat_count",
|
||||
want: float64(0),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
data, err := json.Marshal(tt.cluster)
|
||||
if err != nil {
|
||||
t.Fatalf("json.Marshal failed: %v", err)
|
||||
}
|
||||
var m map[string]interface{}
|
||||
if err := json.Unmarshal(data, &m); err != nil {
|
||||
t.Fatalf("json.Unmarshal failed: %v", err)
|
||||
}
|
||||
got, ok := m[tt.field]
|
||||
if !ok {
|
||||
t.Errorf("field %q not found in JSON output; available keys: %v", tt.field, mapKeys(m))
|
||||
} else if got != tt.want {
|
||||
t.Errorf("field %q = %v, want %v", tt.field, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestClusterInfo_ExistingFieldsUnchanged(t *testing.T) {
|
||||
c := ClusterInfo{
|
||||
ClusterName: "mycluster",
|
||||
Version: "1.0",
|
||||
Status: 1,
|
||||
ControllerName: "ctrl1",
|
||||
NumServers: 5,
|
||||
Resources: `{"res1":"val1"}`,
|
||||
HostTypes: "LINUX64",
|
||||
HostModels: "modelA",
|
||||
ClusterAdmins: "admin1,admin2",
|
||||
}
|
||||
|
||||
data, err := json.Marshal(c)
|
||||
if err != nil {
|
||||
t.Fatalf("json.Marshal failed: %v", err)
|
||||
}
|
||||
var m map[string]interface{}
|
||||
if err := json.Unmarshal(data, &m); err != nil {
|
||||
t.Fatalf("json.Unmarshal failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify all existing fields still serialize correctly
|
||||
existing := map[string]string{
|
||||
"cluster_name": c.ClusterName,
|
||||
"version": c.Version,
|
||||
"controller_name": c.ControllerName,
|
||||
"resources": c.Resources,
|
||||
"host_types": c.HostTypes,
|
||||
"host_models": c.HostModels,
|
||||
"cluster_admins": c.ClusterAdmins,
|
||||
}
|
||||
for jsonKey, wantVal := range existing {
|
||||
got, _ := m[jsonKey].(string)
|
||||
if got != wantVal {
|
||||
t.Errorf("existing field %q = %q, want %q", jsonKey, got, wantVal)
|
||||
}
|
||||
}
|
||||
if got, _ := m["status"].(float64); int(got) != c.Status {
|
||||
t.Errorf("existing field status = %v, want %d", got, c.Status)
|
||||
}
|
||||
if got, _ := m["num_servers"].(float64); int(got) != c.NumServers {
|
||||
t.Errorf("existing field num_servers = %v, want %d", got, c.NumServers)
|
||||
}
|
||||
}
|
||||
|
||||
func mapKeys(m map[string]interface{}) []string {
|
||||
keys := make([]string, 0, len(m))
|
||||
for k := range m {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
|
@ -18,6 +18,9 @@ var HOSTSTAT = map[string]int{
|
|||
}
|
||||
|
||||
func HostStateStr(state int) string {
|
||||
if state == 0 {
|
||||
return "UNKNOWN"
|
||||
}
|
||||
if (state & HOSTSTAT["UNAVAIL"]) != 0 {
|
||||
return "UNAVAIL"
|
||||
} else if (state & HOSTSTAT["CLOSED"]) != 0 {
|
||||
|
|
|
|||
61
src/frontend/apiserver/models/hosts_test.go
Normal file
61
src/frontend/apiserver/models/hosts_test.go
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
package models
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestHostStateStr(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
state int
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "zero value returns UNKNOWN when no worker has reported",
|
||||
state: 0,
|
||||
want: "UNKNOWN",
|
||||
},
|
||||
{
|
||||
name: "UNAVAIL flag",
|
||||
state: HOSTSTAT["UNAVAIL"],
|
||||
want: "UNAVAIL",
|
||||
},
|
||||
{
|
||||
name: "CLOSED flag",
|
||||
state: HOSTSTAT["CLOSED"],
|
||||
want: "CLOSED",
|
||||
},
|
||||
{
|
||||
name: "BUSY flag",
|
||||
state: HOSTSTAT["BUSY"],
|
||||
want: "BUSY",
|
||||
},
|
||||
{
|
||||
name: "LOCKEDU flag",
|
||||
state: HOSTSTAT["LOCKEDU"],
|
||||
want: "LOCKU",
|
||||
},
|
||||
{
|
||||
name: "LOCKEDW flag",
|
||||
state: HOSTSTAT["LOCKEDW"],
|
||||
want: "LOCKW",
|
||||
},
|
||||
{
|
||||
name: "no flags set returns OK for real host status",
|
||||
state: 0x00000001, // some non-zero, non-flag value
|
||||
want: "OK",
|
||||
},
|
||||
{
|
||||
name: "combined UNAVAIL+CLOSED flags",
|
||||
state: HOSTSTAT["UNAVAIL"] | HOSTSTAT["CLOSED"],
|
||||
want: "UNAVAIL", // UNAVAIL takes priority
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := HostStateStr(tt.state)
|
||||
if got != tt.want {
|
||||
t.Errorf("HostStateStr(%d) = %q, want %q", tt.state, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue