| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005 |
- package opencost
- import (
- "bytes"
- "fmt"
- "reflect"
- "time"
- "github.com/opencost/opencost/core/pkg/util/json"
- )
- // Encoding and decoding logic for Asset types
- // Any marshal and unmarshal
- // MarshalJSON implements json.Marshaler
- func (a *Any) MarshalJSON() ([]byte, error) {
- buffer := bytes.NewBufferString("{")
- jsonEncode(buffer, "properties", a.Properties, ",")
- jsonEncode(buffer, "labels", a.Labels, ",")
- jsonEncode(buffer, "window", a.Window, ",")
- jsonEncodeString(buffer, "start", a.Start.Format(time.RFC3339), ",")
- jsonEncodeString(buffer, "end", a.End.Format(time.RFC3339), ",")
- jsonEncodeFloat64(buffer, "minutes", a.Minutes(), ",")
- jsonEncodeFloat64(buffer, "adjustment", a.Adjustment, ",")
- jsonEncodeFloat64(buffer, "totalCost", a.TotalCost(), "")
- buffer.WriteString("}")
- return buffer.Bytes(), nil
- }
- func (a *Any) UnmarshalJSON(b []byte) error {
- var f interface{}
- err := json.Unmarshal(b, &f)
- if err != nil {
- return err
- }
- err = a.InterfaceToAny(f)
- if err != nil {
- return err
- }
- return nil
- }
- // Converts interface{} to Any, carrying over relevant fields
- func (a *Any) InterfaceToAny(itf interface{}) error {
- fmap := itf.(map[string]interface{})
- // parse properties map to AssetProperties
- fproperties := fmap["properties"].(map[string]interface{})
- properties := toAssetProp(fproperties)
- // parse labels map to AssetLabels
- labels := make(map[string]string)
- for k, v := range fmap["labels"].(map[string]interface{}) {
- labels[k] = v.(string)
- }
- // parse start and end strings to time.Time
- start, err := time.Parse(time.RFC3339, fmap["start"].(string))
- if err != nil {
- return err
- }
- end, err := time.Parse(time.RFC3339, fmap["end"].(string))
- if err != nil {
- return err
- }
- a.Properties = &properties
- a.Labels = labels
- a.Start = start
- a.End = end
- a.Window = Window{
- start: &start,
- end: &end,
- }
- if adjustment, err := getTypedVal(fmap["adjustment"]); err == nil {
- a.Adjustment = adjustment.(float64)
- }
- if Cost, err := getTypedVal(fmap["totalCost"]); err == nil {
- a.Cost = Cost.(float64) - a.Adjustment
- }
- return nil
- }
- // Cloud marshal and unmarshal
- // MarshalJSON implements json.Marshaler
- func (ca *Cloud) MarshalJSON() ([]byte, error) {
- buffer := bytes.NewBufferString("{")
- jsonEncodeString(buffer, "type", ca.Type().String(), ",")
- jsonEncode(buffer, "properties", ca.Properties, ",")
- jsonEncode(buffer, "labels", ca.Labels, ",")
- jsonEncode(buffer, "window", ca.Window, ",")
- jsonEncodeString(buffer, "start", ca.Start.Format(time.RFC3339), ",")
- jsonEncodeString(buffer, "end", ca.End.Format(time.RFC3339), ",")
- jsonEncodeFloat64(buffer, "minutes", ca.Minutes(), ",")
- jsonEncodeFloat64(buffer, "adjustment", ca.Adjustment, ",")
- jsonEncodeFloat64(buffer, "credit", ca.Credit, ",")
- jsonEncodeFloat64(buffer, "totalCost", ca.TotalCost(), "")
- buffer.WriteString("}")
- return buffer.Bytes(), nil
- }
- func (ca *Cloud) UnmarshalJSON(b []byte) error {
- var f interface{}
- err := json.Unmarshal(b, &f)
- if err != nil {
- return err
- }
- err = ca.InterfaceToCloud(f)
- if err != nil {
- return err
- }
- return nil
- }
- // Converts interface{} to Cloud, carrying over relevant fields
- func (ca *Cloud) InterfaceToCloud(itf interface{}) error {
- fmap := itf.(map[string]interface{})
- // parse properties map to AssetProperties
- fproperties := fmap["properties"].(map[string]interface{})
- properties := toAssetProp(fproperties)
- // parse labels map to AssetLabels
- labels := make(map[string]string)
- for k, v := range fmap["labels"].(map[string]interface{}) {
- labels[k] = v.(string)
- }
- // parse start and end strings to time.Time
- start, err := time.Parse(time.RFC3339, fmap["start"].(string))
- if err != nil {
- return err
- }
- end, err := time.Parse(time.RFC3339, fmap["end"].(string))
- if err != nil {
- return err
- }
- ca.Properties = &properties
- ca.Labels = labels
- ca.Start = start
- ca.End = end
- ca.Window = Window{
- start: &start,
- end: &end,
- }
- if adjustment, err := getTypedVal(fmap["adjustment"]); err == nil {
- ca.Adjustment = adjustment.(float64)
- }
- if Credit, err := getTypedVal(fmap["credit"]); err == nil {
- ca.Credit = Credit.(float64)
- }
- if Cost, err := getTypedVal(fmap["totalCost"]); err == nil {
- ca.Cost = Cost.(float64) - ca.Adjustment - ca.Credit
- }
- return nil
- }
- // ClusterManagement marshal and unmarshal
- // MarshalJSON implements json.Marshler
- func (cm *ClusterManagement) MarshalJSON() ([]byte, error) {
- buffer := bytes.NewBufferString("{")
- jsonEncodeString(buffer, "type", cm.Type().String(), ",")
- jsonEncode(buffer, "properties", cm.Properties, ",")
- jsonEncode(buffer, "labels", cm.Labels, ",")
- jsonEncode(buffer, "window", cm.Window, ",")
- jsonEncodeString(buffer, "start", cm.GetStart().Format(time.RFC3339), ",")
- jsonEncodeString(buffer, "end", cm.GetEnd().Format(time.RFC3339), ",")
- jsonEncodeFloat64(buffer, "minutes", cm.Minutes(), ",")
- jsonEncodeFloat64(buffer, "totalCost", cm.TotalCost(), "")
- buffer.WriteString("}")
- return buffer.Bytes(), nil
- }
- func (cm *ClusterManagement) UnmarshalJSON(b []byte) error {
- var f interface{}
- err := json.Unmarshal(b, &f)
- if err != nil {
- return err
- }
- err = cm.InterfaceToClusterManagement(f)
- if err != nil {
- return err
- }
- return nil
- }
- // Converts interface{} to ClusterManagement, carrying over relevant fields
- func (cm *ClusterManagement) InterfaceToClusterManagement(itf interface{}) error {
- fmap := itf.(map[string]interface{})
- // parse properties map to AssetProperties
- fproperties := fmap["properties"].(map[string]interface{})
- properties := toAssetProp(fproperties)
- // parse labels map to AssetLabels
- labels := make(map[string]string)
- for k, v := range fmap["labels"].(map[string]interface{}) {
- labels[k] = v.(string)
- }
- // parse start and end strings to time.Time
- start, err := time.Parse(time.RFC3339, fmap["start"].(string))
- if err != nil {
- return err
- }
- end, err := time.Parse(time.RFC3339, fmap["end"].(string))
- if err != nil {
- return err
- }
- cm.Properties = &properties
- cm.Labels = labels
- cm.Window = Window{
- start: &start,
- end: &end,
- }
- if Cost, err := getTypedVal(fmap["totalCost"]); err == nil {
- cm.Cost = Cost.(float64)
- }
- return nil
- }
- // Disk marshal and unmarshal
- // MarshalJSON implements the json.Marshaler interface
- func (d *Disk) MarshalJSON() ([]byte, error) {
- buffer := bytes.NewBufferString("{")
- jsonEncodeString(buffer, "type", d.Type().String(), ",")
- jsonEncode(buffer, "properties", d.Properties, ",")
- jsonEncode(buffer, "labels", d.Labels, ",")
- jsonEncode(buffer, "window", d.Window, ",")
- jsonEncodeString(buffer, "start", d.Start.Format(time.RFC3339), ",")
- jsonEncodeString(buffer, "end", d.End.Format(time.RFC3339), ",")
- jsonEncodeFloat64(buffer, "minutes", d.Minutes(), ",")
- jsonEncodeFloat64(buffer, "byteHours", d.ByteHours, ",")
- jsonEncodeFloat64(buffer, "bytes", d.Bytes(), ",")
- if d.ByteHoursUsed == nil {
- jsonEncode(buffer, "byteHoursUsed", nil, ",")
- } else {
- jsonEncodeFloat64(buffer, "byteHoursUsed", *d.ByteHoursUsed, ",")
- }
- if d.ByteUsageMax == nil {
- jsonEncode(buffer, "byteUsageMax", nil, ",")
- } else {
- jsonEncodeFloat64(buffer, "byteUsageMax", *d.ByteUsageMax, ",")
- }
- jsonEncode(buffer, "breakdown", d.Breakdown, ",")
- jsonEncodeFloat64(buffer, "adjustment", d.Adjustment, ",")
- jsonEncodeFloat64(buffer, "totalCost", d.TotalCost(), ",")
- jsonEncodeString(buffer, "storageClass", d.StorageClass, ",")
- jsonEncodeString(buffer, "volumeName", d.VolumeName, ",")
- jsonEncodeString(buffer, "claimName", d.ClaimName, ",")
- jsonEncodeString(buffer, "claimNamespace", d.ClaimNamespace, "")
- buffer.WriteString("}")
- return buffer.Bytes(), nil
- }
- func (d *Disk) UnmarshalJSON(b []byte) error {
- var f interface{}
- err := json.Unmarshal(b, &f)
- if err != nil {
- return err
- }
- err = d.InterfaceToDisk(f)
- if err != nil {
- return err
- }
- return nil
- }
- // Converts interface{} to Disk, carrying over relevant fields
- func (d *Disk) InterfaceToDisk(itf interface{}) error {
- fmap := itf.(map[string]interface{})
- // parse properties map to AssetProperties
- fproperties := fmap["properties"].(map[string]interface{})
- properties := toAssetProp(fproperties)
- // parse labels map to AssetLabels
- labels := make(map[string]string)
- for k, v := range fmap["labels"].(map[string]interface{}) {
- labels[k] = v.(string)
- }
- // parse start and end strings to time.Time
- start, err := time.Parse(time.RFC3339, fmap["start"].(string))
- if err != nil {
- return err
- }
- end, err := time.Parse(time.RFC3339, fmap["end"].(string))
- if err != nil {
- return err
- }
- fbreakdown := fmap["breakdown"].(map[string]interface{})
- breakdown := toBreakdown(fbreakdown)
- d.Properties = &properties
- d.Labels = labels
- d.Start = start
- d.End = end
- d.Window = Window{
- start: &start,
- end: &end,
- }
- d.Breakdown = &breakdown
- if adjustment, err := getTypedVal(fmap["adjustment"]); err == nil {
- d.Adjustment = adjustment.(float64)
- }
- if Cost, err := getTypedVal(fmap["totalCost"]); err == nil {
- d.Cost = Cost.(float64) - d.Adjustment
- }
- if ByteHours, err := getTypedVal(fmap["byteHours"]); err == nil {
- d.ByteHours = ByteHours.(float64)
- }
- if ByteHoursUsed, err := getTypedVal(fmap["byteHoursUsed"]); err == nil {
- if ByteHoursUsed == nil {
- d.ByteHoursUsed = nil
- } else {
- byteHours := ByteHoursUsed.(float64)
- d.ByteHoursUsed = &byteHours
- }
- }
- if ByteUsageMax, err := getTypedVal(fmap["byteUsageMax"]); err == nil {
- if ByteUsageMax == nil {
- d.ByteUsageMax = nil
- } else {
- max := ByteUsageMax.(float64)
- d.ByteUsageMax = &max
- }
- }
- if StorageClass, err := getTypedVal(fmap["storageClass"]); err == nil {
- d.StorageClass = StorageClass.(string)
- }
- if VolumeName, err := getTypedVal(fmap["volumeName"]); err == nil {
- d.VolumeName = VolumeName.(string)
- }
- if ClaimName, err := getTypedVal(fmap["claimName"]); err == nil {
- d.ClaimName = ClaimName.(string)
- }
- if ClaimNamespace, err := getTypedVal(fmap["claimNamespace"]); err == nil {
- d.ClaimNamespace = ClaimNamespace.(string)
- }
- // d.Local is not marhsaled, and cannot be calculated from marshaled values.
- // Currently, it is just ignored and not set in the resulting unmarshal to Disk
- // be aware that this means a resulting Disk from an unmarshal is therefore NOT
- // equal to the originally marshaled Disk.
- return nil
- }
- // Network marshal and unmarshal
- // MarshalJSON implements json.Marshal interface
- func (n *Network) MarshalJSON() ([]byte, error) {
- buffer := bytes.NewBufferString("{")
- jsonEncodeString(buffer, "type", n.Type().String(), ",")
- jsonEncode(buffer, "properties", n.Properties, ",")
- jsonEncode(buffer, "labels", n.Labels, ",")
- jsonEncode(buffer, "window", n.Window, ",")
- jsonEncodeString(buffer, "start", n.Start.Format(time.RFC3339), ",")
- jsonEncodeString(buffer, "end", n.End.Format(time.RFC3339), ",")
- jsonEncodeFloat64(buffer, "minutes", n.Minutes(), ",")
- jsonEncodeFloat64(buffer, "adjustment", n.Adjustment, ",")
- jsonEncodeFloat64(buffer, "totalCost", n.TotalCost(), "")
- buffer.WriteString("}")
- return buffer.Bytes(), nil
- }
- func (n *Network) UnmarshalJSON(b []byte) error {
- var f interface{}
- err := json.Unmarshal(b, &f)
- if err != nil {
- return err
- }
- err = n.InterfaceToNetwork(f)
- if err != nil {
- return err
- }
- return nil
- }
- // Converts interface{} to Network, carrying over relevant fields
- func (n *Network) InterfaceToNetwork(itf interface{}) error {
- fmap := itf.(map[string]interface{})
- // parse properties map to AssetProperties
- fproperties := fmap["properties"].(map[string]interface{})
- properties := toAssetProp(fproperties)
- // parse labels map to AssetLabels
- labels := make(map[string]string)
- for k, v := range fmap["labels"].(map[string]interface{}) {
- labels[k] = v.(string)
- }
- // parse start and end strings to time.Time
- start, err := time.Parse(time.RFC3339, fmap["start"].(string))
- if err != nil {
- return err
- }
- end, err := time.Parse(time.RFC3339, fmap["end"].(string))
- if err != nil {
- return err
- }
- n.Properties = &properties
- n.Labels = labels
- n.Start = start
- n.End = end
- n.Window = Window{
- start: &start,
- end: &end,
- }
- if adjustment, err := getTypedVal(fmap["adjustment"]); err == nil {
- n.Adjustment = adjustment.(float64)
- }
- if Cost, err := getTypedVal(fmap["totalCost"]); err == nil {
- n.Cost = Cost.(float64) - n.Adjustment
- }
- return nil
- }
- // Node marshal and unmarshal
- // MarshalJSON implements json.Marshal interface
- func (n *Node) MarshalJSON() ([]byte, error) {
- buffer := bytes.NewBufferString("{")
- jsonEncodeString(buffer, "type", n.Type().String(), ",")
- jsonEncode(buffer, "properties", n.Properties, ",")
- jsonEncode(buffer, "labels", n.Labels, ",")
- jsonEncode(buffer, "window", n.Window, ",")
- jsonEncodeString(buffer, "start", n.Start.Format(time.RFC3339), ",")
- jsonEncodeString(buffer, "end", n.End.Format(time.RFC3339), ",")
- jsonEncodeFloat64(buffer, "minutes", n.Minutes(), ",")
- jsonEncodeString(buffer, "nodeType", n.NodeType, ",")
- if poolName := GetNodePoolName(n.Properties.Provider, n.Labels); poolName != "" {
- jsonEncodeString(buffer, "pool", poolName, ",")
- }
- jsonEncodeFloat64(buffer, "cpuCores", n.CPUCores(), ",")
- jsonEncodeFloat64(buffer, "ramBytes", n.RAMBytes(), ",")
- jsonEncodeFloat64(buffer, "cpuCoreHours", n.CPUCoreHours, ",")
- jsonEncodeFloat64(buffer, "ramByteHours", n.RAMByteHours, ",")
- jsonEncodeFloat64(buffer, "GPUHours", n.GPUHours, ",")
- jsonEncode(buffer, "cpuBreakdown", n.CPUBreakdown, ",")
- jsonEncode(buffer, "ramBreakdown", n.RAMBreakdown, ",")
- jsonEncodeFloat64(buffer, "preemptible", n.Preemptible, ",")
- jsonEncodeFloat64(buffer, "discount", n.Discount, ",")
- jsonEncodeFloat64(buffer, "cpuCost", n.CPUCost, ",")
- jsonEncodeFloat64(buffer, "gpuCost", n.GPUCost, ",")
- jsonEncodeFloat64(buffer, "gpuCount", n.GPUs(), ",")
- jsonEncodeFloat64(buffer, "ramCost", n.RAMCost, ",")
- jsonEncodeFloat64(buffer, "adjustment", n.Adjustment, ",")
- if n.Overhead != nil {
- jsonEncode(buffer, "overhead", n.Overhead, ",")
- }
- jsonEncodeFloat64(buffer, "totalCost", n.TotalCost(), "")
- buffer.WriteString("}")
- return buffer.Bytes(), nil
- }
- func (n *Node) UnmarshalJSON(b []byte) error {
- var f interface{}
- err := json.Unmarshal(b, &f)
- if err != nil {
- return err
- }
- err = n.InterfaceToNode(f)
- if err != nil {
- return err
- }
- return nil
- }
- // Converts interface{} to Node, carrying over relevant fields
- func (n *Node) InterfaceToNode(itf interface{}) error {
- fmap := itf.(map[string]interface{})
- // parse properties map to AssetProperties
- fproperties := fmap["properties"].(map[string]interface{})
- properties := toAssetProp(fproperties)
- // parse labels map to AssetLabels
- labels := make(map[string]string)
- for k, v := range fmap["labels"].(map[string]interface{}) {
- labels[k] = v.(string)
- }
- // parse start and end strings to time.Time
- start, err := time.Parse(time.RFC3339, fmap["start"].(string))
- if err != nil {
- return err
- }
- end, err := time.Parse(time.RFC3339, fmap["end"].(string))
- if err != nil {
- return err
- }
- fcpuBreakdown := fmap["cpuBreakdown"].(map[string]interface{})
- framBreakdown := fmap["ramBreakdown"].(map[string]interface{})
- cpuBreakdown := toBreakdown(fcpuBreakdown)
- ramBreakdown := toBreakdown(framBreakdown)
- n.Properties = &properties
- n.Labels = labels
- n.Start = start
- n.End = end
- n.Window = Window{
- start: &start,
- end: &end,
- }
- n.CPUBreakdown = &cpuBreakdown
- n.RAMBreakdown = &ramBreakdown
- if adjustment, err := getTypedVal(fmap["adjustment"]); err == nil {
- n.Adjustment = adjustment.(float64)
- }
- if NodeType, err := getTypedVal(fmap["nodeType"]); err == nil {
- n.NodeType = NodeType.(string)
- }
- if CPUCoreHours, err := getTypedVal(fmap["cpuCoreHours"]); err == nil {
- n.CPUCoreHours = CPUCoreHours.(float64)
- }
- if RAMByteHours, err := getTypedVal(fmap["ramByteHours"]); err == nil {
- n.RAMByteHours = RAMByteHours.(float64)
- }
- if GPUHours, err := getTypedVal(fmap["GPUHours"]); err == nil {
- n.GPUHours = GPUHours.(float64)
- }
- if CPUCost, err := getTypedVal(fmap["cpuCost"]); err == nil {
- n.CPUCost = CPUCost.(float64)
- }
- if GPUCost, err := getTypedVal(fmap["gpuCost"]); err == nil {
- n.GPUCost = GPUCost.(float64)
- }
- if GPUCount, err := getTypedVal(fmap["gpuCount"]); err == nil {
- n.GPUCount = GPUCount.(float64)
- }
- if RAMCost, err := getTypedVal(fmap["ramCost"]); err == nil {
- n.RAMCost = RAMCost.(float64)
- }
- if Discount, err := getTypedVal(fmap["discount"]); err == nil {
- n.Discount = Discount.(float64)
- }
- if Preemptible, err := getTypedVal(fmap["preemptible"]); err == nil {
- n.Preemptible = Preemptible.(float64)
- }
- return nil
- }
- // Loadbalancer marshal and unmarshal
- // MarshalJSON implements json.Marshal
- func (lb *LoadBalancer) MarshalJSON() ([]byte, error) {
- buffer := bytes.NewBufferString("{")
- jsonEncodeString(buffer, "type", lb.Type().String(), ",")
- jsonEncode(buffer, "properties", lb.Properties, ",")
- jsonEncode(buffer, "labels", lb.Labels, ",")
- jsonEncode(buffer, "window", lb.Window, ",")
- jsonEncodeString(buffer, "start", lb.Start.Format(time.RFC3339), ",")
- jsonEncodeString(buffer, "end", lb.End.Format(time.RFC3339), ",")
- jsonEncodeFloat64(buffer, "minutes", lb.Minutes(), ",")
- jsonEncodeFloat64(buffer, "adjustment", lb.Adjustment, ",")
- jsonEncodeFloat64(buffer, "totalCost", lb.TotalCost(), ",")
- jsonEncode(buffer, "private", lb.Private, ",")
- jsonEncodeString(buffer, "ip", lb.Ip, "")
- buffer.WriteString("}")
- return buffer.Bytes(), nil
- }
- func (lb *LoadBalancer) UnmarshalJSON(b []byte) error {
- var f interface{}
- err := json.Unmarshal(b, &f)
- if err != nil {
- return err
- }
- err = lb.InterfaceToLoadBalancer(f)
- if err != nil {
- return err
- }
- return nil
- }
- // Converts interface{} to LoadBalancer, carrying over relevant fields
- func (lb *LoadBalancer) InterfaceToLoadBalancer(itf interface{}) error {
- fmap := itf.(map[string]interface{})
- // parse properties map to AssetProperties
- fproperties := fmap["properties"].(map[string]interface{})
- properties := toAssetProp(fproperties)
- // parse labels map to AssetLabels
- labels := make(map[string]string)
- for k, v := range fmap["labels"].(map[string]interface{}) {
- labels[k] = v.(string)
- }
- // parse start and end strings to time.Time
- start, err := time.Parse(time.RFC3339, fmap["start"].(string))
- if err != nil {
- return err
- }
- end, err := time.Parse(time.RFC3339, fmap["end"].(string))
- if err != nil {
- return err
- }
- lb.Properties = &properties
- lb.Labels = labels
- lb.Start = start
- lb.End = end
- lb.Window = Window{
- start: &start,
- end: &end,
- }
- if adjustment, err := getTypedVal(fmap["adjustment"]); err == nil {
- lb.Adjustment = adjustment.(float64)
- }
- if Cost, err := getTypedVal(fmap["totalCost"]); err == nil {
- lb.Cost = Cost.(float64) - lb.Adjustment
- }
- if private, err := getTypedVal(fmap["private"]); err == nil {
- lb.Private = private.(bool)
- }
- if ip, err := getTypedVal(fmap["ip"]); err == nil {
- lb.Ip = ip.(string)
- }
- return nil
- }
- // SharedAsset marshal and unmarshal
- // MarshalJSON implements json.Marshaler
- func (sa *SharedAsset) MarshalJSON() ([]byte, error) {
- buffer := bytes.NewBufferString("{")
- jsonEncodeString(buffer, "type", sa.Type().String(), ",")
- jsonEncode(buffer, "properties", sa.Properties, ",")
- jsonEncode(buffer, "labels", sa.Labels, ",")
- jsonEncode(buffer, "window", sa.Window, ",")
- jsonEncodeString(buffer, "start", sa.GetStart().Format(time.RFC3339), ",")
- jsonEncodeString(buffer, "end", sa.GetEnd().Format(time.RFC3339), ",")
- jsonEncodeFloat64(buffer, "minutes", sa.Minutes(), ",")
- jsonEncodeFloat64(buffer, "totalCost", sa.TotalCost(), "")
- buffer.WriteString("}")
- return buffer.Bytes(), nil
- }
- func (sa *SharedAsset) UnmarshalJSON(b []byte) error {
- var f interface{}
- err := json.Unmarshal(b, &f)
- if err != nil {
- return err
- }
- err = sa.InterfaceToSharedAsset(f)
- if err != nil {
- return err
- }
- return nil
- }
- // Converts interface{} to SharedAsset, carrying over relevant fields
- func (sa *SharedAsset) InterfaceToSharedAsset(itf interface{}) error {
- fmap := itf.(map[string]interface{})
- // parse properties map to AssetProperties
- fproperties := fmap["properties"].(map[string]interface{})
- properties := toAssetProp(fproperties)
- // parse labels map to AssetLabels
- labels := make(map[string]string)
- for k, v := range fmap["labels"].(map[string]interface{}) {
- labels[k] = v.(string)
- }
- // parse start and end strings to time.Time
- start, err := time.Parse(time.RFC3339, fmap["start"].(string))
- if err != nil {
- return err
- }
- end, err := time.Parse(time.RFC3339, fmap["end"].(string))
- if err != nil {
- return err
- }
- sa.Properties = &properties
- sa.Labels = labels
- sa.Window = Window{
- start: &start,
- end: &end,
- }
- if Cost, err := getTypedVal(fmap["totalCost"]); err == nil {
- sa.Cost = Cost.(float64)
- }
- return nil
- }
- // AssetSet marshal
- // MarshalJSON JSON-encodes the AssetSet
- func (as *AssetSet) MarshalJSON() ([]byte, error) {
- if as == nil {
- return json.Marshal(map[string]Asset{})
- }
- return json.Marshal(as.Assets)
- }
- // AssetSetResponse for unmarshaling of AssetSet.assets into AssetSet
- // Unmarshals a marshaled AssetSet json into AssetSetResponse
- func (asr *AssetSetResponse) UnmarshalJSON(b []byte) error {
- var assetMap map[string]*json.RawMessage
- // Partial unmarshal to map of json RawMessage
- err := json.Unmarshal(b, &assetMap)
- if err != nil {
- return err
- }
- err = asr.RawMessageToAssetSetResponse(assetMap)
- if err != nil {
- return err
- }
- return nil
- }
- func (asr *AssetSetResponse) RawMessageToAssetSetResponse(assetMap map[string]*json.RawMessage) error {
- newAssetMap := make(map[string]Asset)
- // For each item in asset map, unmarshal to appropriate type
- for key, rawMessage := range assetMap {
- var f interface{}
- err := json.Unmarshal(*rawMessage, &f)
- if err != nil {
- return err
- }
- fmap := f.(map[string]interface{})
- switch t := fmap["type"]; t {
- case "Cloud":
- var ca Cloud
- err := ca.InterfaceToCloud(f)
- if err != nil {
- return err
- }
- newAssetMap[key] = &ca
- case "ClusterManagement":
- var cm ClusterManagement
- err := cm.InterfaceToClusterManagement(f)
- if err != nil {
- return err
- }
- newAssetMap[key] = &cm
- case "Disk":
- var d Disk
- err := d.InterfaceToDisk(f)
- if err != nil {
- return err
- }
- newAssetMap[key] = &d
- case "Network":
- var nw Network
- err := nw.InterfaceToNetwork(f)
- if err != nil {
- return err
- }
- newAssetMap[key] = &nw
- case "Node":
- var n Node
- err := n.InterfaceToNode(f)
- if err != nil {
- return err
- }
- newAssetMap[key] = &n
- case "LoadBalancer":
- var lb LoadBalancer
- err := lb.InterfaceToLoadBalancer(f)
- if err != nil {
- return err
- }
- newAssetMap[key] = &lb
- case "Shared":
- var sa SharedAsset
- err := sa.InterfaceToSharedAsset(f)
- if err != nil {
- return err
- }
- newAssetMap[key] = &sa
- default:
- var a Any
- err := a.InterfaceToAny(f)
- if err != nil {
- return err
- }
- newAssetMap[key] = &a
- }
- }
- asr.Assets = newAssetMap
- return nil
- }
- func (asrr *AssetSetRangeResponse) UnmarshalJSON(b []byte) error {
- var assetMapList []map[string]*json.RawMessage
- // Partial unmarshal to map of json RawMessage
- err := json.Unmarshal(b, &assetMapList)
- if err != nil {
- return err
- }
- var assetSetList []*AssetSetResponse
- for _, rawm := range assetMapList {
- var asresp AssetSetResponse
- err = asresp.RawMessageToAssetSetResponse(rawm)
- if err != nil {
- return err
- }
- assetSetList = append(assetSetList, &asresp)
- }
- asrr.Assets = assetSetList
- return nil
- }
- // Extra decoding util functions, for clarity
- // Creates an AssetProperties directly from map[string]interface{}
- func toAssetProp(fproperties map[string]interface{}) AssetProperties {
- var properties AssetProperties
- if category, v := fproperties["category"].(string); v {
- properties.Category = category
- }
- if provider, v := fproperties["provider"].(string); v {
- properties.Provider = provider
- }
- if account, v := fproperties["account"].(string); v {
- properties.Account = account
- }
- if project, v := fproperties["project"].(string); v {
- properties.Project = project
- }
- if service, v := fproperties["service"].(string); v {
- properties.Service = service
- }
- if cluster, v := fproperties["cluster"].(string); v {
- properties.Cluster = cluster
- }
- if name, v := fproperties["name"].(string); v {
- properties.Name = name
- }
- if providerID, v := fproperties["providerID"].(string); v {
- properties.ProviderID = providerID
- }
- return properties
- }
- // Creates an Breakdown directly from map[string]interface{}
- func toBreakdown(fproperties map[string]interface{}) Breakdown {
- var breakdown Breakdown
- if idle, v := fproperties["idle"].(float64); v {
- breakdown.Idle = idle
- }
- if other, v := fproperties["other"].(float64); v {
- breakdown.Other = other
- }
- if system, v := fproperties["system"].(float64); v {
- breakdown.System = system
- }
- if user, v := fproperties["user"].(float64); v {
- breakdown.User = user
- }
- return breakdown
- }
- // Not strictly nessesary, but cleans up the code and is a secondary check
- // for correct types
- func getTypedVal(itf interface{}) (interface{}, error) {
- switch itf := itf.(type) {
- case float64:
- return float64(itf), nil
- case string:
- return string(itf), nil
- default:
- unktype := reflect.ValueOf(itf)
- return nil, fmt.Errorf("Type %v is an invalid type", unktype)
- }
- }
|