parent
cdf80dbab5
commit
13e2577c57
2 changed files with 124 additions and 0 deletions
|
|
@ -1050,6 +1050,95 @@ type VMFileSystem struct {
|
||||||
DiskRaw []interface{} `json:"disk"` // Raw disk device info from API
|
DiskRaw []interface{} `json:"disk"` // Raw disk device info from API
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (fs *VMFileSystem) UnmarshalJSON(data []byte) error {
|
||||||
|
type rawVMFileSystem struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Mountpoint string `json:"mountpoint"`
|
||||||
|
TotalBytes interface{} `json:"total-bytes"`
|
||||||
|
UsedBytes interface{} `json:"used-bytes"`
|
||||||
|
DiskRaw []interface{} `json:"disk"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var raw rawVMFileSystem
|
||||||
|
if err := json.Unmarshal(data, &raw); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
total, err := parseUint64Flexible(raw.TotalBytes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
used, err := parseUint64Flexible(raw.UsedBytes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.Name = raw.Name
|
||||||
|
fs.Type = raw.Type
|
||||||
|
fs.Mountpoint = raw.Mountpoint
|
||||||
|
fs.TotalBytes = total
|
||||||
|
fs.UsedBytes = used
|
||||||
|
fs.DiskRaw = raw.DiskRaw
|
||||||
|
fs.Disk = ""
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseUint64Flexible(value interface{}) (uint64, error) {
|
||||||
|
switch v := value.(type) {
|
||||||
|
case nil:
|
||||||
|
return 0, nil
|
||||||
|
case uint64:
|
||||||
|
return v, nil
|
||||||
|
case int:
|
||||||
|
if v < 0 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
return uint64(v), nil
|
||||||
|
case int64:
|
||||||
|
if v < 0 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
return uint64(v), nil
|
||||||
|
case float64:
|
||||||
|
if v < 0 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
return uint64(v), nil
|
||||||
|
case json.Number:
|
||||||
|
return parseUint64Flexible(v.String())
|
||||||
|
case string:
|
||||||
|
s := strings.TrimSpace(v)
|
||||||
|
if s == "" {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(s, "0x") || strings.HasPrefix(s, "0X") {
|
||||||
|
u, err := strconv.ParseUint(s[2:], 16, 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return u, nil
|
||||||
|
}
|
||||||
|
if strings.ContainsAny(s, ".eE") {
|
||||||
|
f, err := strconv.ParseFloat(s, 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if f < 0 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
return uint64(f), nil
|
||||||
|
}
|
||||||
|
u, err := strconv.ParseUint(s, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return u, nil
|
||||||
|
default:
|
||||||
|
return 0, fmt.Errorf("unsupported type %T for uint64 conversion", value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type VMIpAddress struct {
|
type VMIpAddress struct {
|
||||||
Address string `json:"ip-address"`
|
Address string `json:"ip-address"`
|
||||||
Prefix int `json:"prefix"`
|
Prefix int `json:"prefix"`
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,41 @@ func TestDiskUnmarshalWearout(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestVMFileSystemUnmarshalFlexibleNumbers(t *testing.T) {
|
||||||
|
t.Run("accepts numeric values", func(t *testing.T) {
|
||||||
|
payload := `{"name":"rootfs","type":"zfs","mountpoint":"/","total-bytes":8589934592,"used-bytes":3221225472,"disk":[{"dev":"/dev/vtbd0p2"}]}`
|
||||||
|
var fs VMFileSystem
|
||||||
|
if err := json.Unmarshal([]byte(payload), &fs); err != nil {
|
||||||
|
t.Fatalf("unexpected error unmarshalling numeric fields: %v", err)
|
||||||
|
}
|
||||||
|
if fs.TotalBytes != 8589934592 || fs.UsedBytes != 3221225472 {
|
||||||
|
t.Fatalf("unexpected numeric values: got total=%d used=%d", fs.TotalBytes, fs.UsedBytes)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("accepts numeric strings", func(t *testing.T) {
|
||||||
|
payload := `{"name":"rootfs","type":"ufs","mountpoint":"/","total-bytes":"5368709120","used-bytes":"2147483648","disk":[{"dev":"/dev/vtbd0p3"}]}`
|
||||||
|
var fs VMFileSystem
|
||||||
|
if err := json.Unmarshal([]byte(payload), &fs); err != nil {
|
||||||
|
t.Fatalf("unexpected error unmarshalling string fields: %v", err)
|
||||||
|
}
|
||||||
|
if fs.TotalBytes != 5368709120 || fs.UsedBytes != 2147483648 {
|
||||||
|
t.Fatalf("unexpected string values: got total=%d used=%d", fs.TotalBytes, fs.UsedBytes)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("accepts float-like strings", func(t *testing.T) {
|
||||||
|
payload := `{"name":"rootfs","type":"ufs","mountpoint":"/","total-bytes":"1073741824.0","used-bytes":"536870912.0","disk":[{"dev":"/dev/vtbd0p4"}]}`
|
||||||
|
var fs VMFileSystem
|
||||||
|
if err := json.Unmarshal([]byte(payload), &fs); err != nil {
|
||||||
|
t.Fatalf("unexpected error unmarshalling float-like strings: %v", err)
|
||||||
|
}
|
||||||
|
if fs.TotalBytes != 1073741824 || fs.UsedBytes != 536870912 {
|
||||||
|
t.Fatalf("unexpected float string values: got total=%d used=%d", fs.TotalBytes, fs.UsedBytes)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestMemoryStatusEffectiveAvailable(t *testing.T) {
|
func TestMemoryStatusEffectiveAvailable(t *testing.T) {
|
||||||
t.Run("nil receiver returns zero", func(t *testing.T) {
|
t.Run("nil receiver returns zero", func(t *testing.T) {
|
||||||
var status *MemoryStatus
|
var status *MemoryStatus
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue