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
|
||||
}
|
||||
|
||||
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 {
|
||||
Address string `json:"ip-address"`
|
||||
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) {
|
||||
t.Run("nil receiver returns zero", func(t *testing.T) {
|
||||
var status *MemoryStatus
|
||||
|
|
|
|||
Loading…
Reference in a new issue