/
allocation_json.go
191 lines (176 loc) · 9.38 KB
/
allocation_json.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
package kubecost
import (
"fmt"
"math"
"time"
"github.com/tkennes/openghg/pkg/util/json"
)
// AllocationJSON exists because there are expected JSON response fields
// that are calculated values from methods on an annotation
type AllocationJSON struct {
Name string `json:"name"`
Properties *AllocationProperties `json:"properties"`
Window Window `json:"window"`
Start string `json:"start"`
End string `json:"end"`
Minutes *float64 `json:"minutes"`
CPUCores *float64 `json:"cpuCores"`
CPUCoreRequestAverage *float64 `json:"cpuCoreRequestAverage"`
CPUCoreUsageAverage *float64 `json:"cpuCoreUsageAverage"`
CPUCoreHours *float64 `json:"cpuCoreHours"`
CPUCost *float64 `json:"cpuCost"`
CPUCostAdjustment *float64 `json:"cpuCostAdjustment"`
CPUEfficiency *float64 `json:"cpuEfficiency"`
GPUCount *float64 `json:"gpuCount"`
GPUHours *float64 `json:"gpuHours"`
GPUCost *float64 `json:"gpuCost"`
GPUCostAdjustment *float64 `json:"gpuCostAdjustment"`
NetworkTransferBytes *float64 `json:"networkTransferBytes"`
NetworkReceiveBytes *float64 `json:"networkReceiveBytes"`
NetworkCost *float64 `json:"networkCost"`
NetworkCrossZoneCost *float64 `json:"networkCrossZoneCost"`
NetworkCrossRegionCost *float64 `json:"networkCrossRegionCost"`
NetworkInternetCost *float64 `json:"networkInternetCost"`
NetworkCostAdjustment *float64 `json:"networkCostAdjustment"`
LoadBalancerCost *float64 `json:"loadBalancerCost"`
LoadBalancerCostAdjustment *float64 `json:"loadBalancerCostAdjustment"`
PVBytes *float64 `json:"pvBytes"`
PVByteHours *float64 `json:"pvByteHours"`
PVCost *float64 `json:"pvCost"`
PVs PVAllocations `json:"pvs"`
PVCostAdjustment *float64 `json:"pvCostAdjustment"`
RAMBytes *float64 `json:"ramBytes"`
RAMByteRequestAverage *float64 `json:"ramByteRequestAverage"`
RAMByteUsageAverage *float64 `json:"ramByteUsageAverage"`
RAMByteHours *float64 `json:"ramByteHours"`
RAMCost *float64 `json:"ramCost"`
RAMCostAdjustment *float64 `json:"ramCostAdjustment"`
RAMEfficiency *float64 `json:"ramEfficiency"`
ExternalCost *float64 `json:"externalCost"`
SharedCost *float64 `json:"sharedCost"`
TotalCost *float64 `json:"totalCost"`
TotalEfficiency *float64 `json:"totalEfficiency"`
RawAllocationOnly *RawAllocationOnlyData `json:"rawAllocationOnly,omitempty"`
ProportionalAssetResourceCosts *ProportionalAssetResourceCosts `json:"proportionalAssetResourceCosts,omitempty"`
LoadBalancers LbAllocations `json:"lbAllocations"`
SharedCostBreakdown *SharedCostBreakdowns `json:"sharedCostBreakdown,omitempty"`
}
func (aj *AllocationJSON) BuildFromAllocation(a *Allocation) {
if aj == nil {
return
}
aj.Name = a.Name
aj.Properties = a.Properties
aj.Window = a.Window
aj.Start = a.Start.UTC().Format(time.RFC3339)
aj.End = a.End.UTC().Format(time.RFC3339)
aj.Minutes = formatFloat64ForResponse(a.Minutes())
aj.CPUCores = formatFloat64ForResponse(a.CPUCores())
aj.CPUCoreRequestAverage = formatFloat64ForResponse(a.CPUCoreRequestAverage)
aj.CPUCoreUsageAverage = formatFloat64ForResponse(a.CPUCoreUsageAverage)
aj.CPUCoreHours = formatFloat64ForResponse(a.CPUCoreHours)
aj.CPUCost = formatFloat64ForResponse(a.CPUCost)
aj.CPUCostAdjustment = formatFloat64ForResponse(a.CPUCostAdjustment)
aj.CPUEfficiency = formatFloat64ForResponse(a.CPUEfficiency())
aj.GPUCount = formatFloat64ForResponse(a.GPUs())
aj.GPUHours = formatFloat64ForResponse(a.GPUHours)
aj.GPUCost = formatFloat64ForResponse(a.GPUCost)
aj.GPUCostAdjustment = formatFloat64ForResponse(a.GPUCostAdjustment)
aj.NetworkTransferBytes = formatFloat64ForResponse(a.NetworkTransferBytes)
aj.NetworkReceiveBytes = formatFloat64ForResponse(a.NetworkReceiveBytes)
aj.NetworkCost = formatFloat64ForResponse(a.NetworkCost)
aj.NetworkCrossZoneCost = formatFloat64ForResponse(a.NetworkCrossZoneCost)
aj.NetworkCrossRegionCost = formatFloat64ForResponse(a.NetworkCrossRegionCost)
aj.NetworkInternetCost = formatFloat64ForResponse(a.NetworkInternetCost)
aj.NetworkCostAdjustment = formatFloat64ForResponse(a.NetworkCostAdjustment)
aj.LoadBalancerCost = formatFloat64ForResponse(a.LoadBalancerCost)
aj.LoadBalancerCostAdjustment = formatFloat64ForResponse(a.LoadBalancerCostAdjustment)
aj.PVBytes = formatFloat64ForResponse(a.PVBytes())
aj.PVByteHours = formatFloat64ForResponse(a.PVByteHours())
aj.PVCost = formatFloat64ForResponse(a.PVCost())
aj.PVs = a.PVs
aj.PVCostAdjustment = formatFloat64ForResponse(a.PVCostAdjustment)
aj.RAMBytes = formatFloat64ForResponse(a.RAMBytes())
aj.RAMByteRequestAverage = formatFloat64ForResponse(a.RAMBytesRequestAverage)
aj.RAMByteUsageAverage = formatFloat64ForResponse(a.RAMBytesUsageAverage)
aj.RAMByteHours = formatFloat64ForResponse(a.RAMByteHours)
aj.RAMCost = formatFloat64ForResponse(a.RAMCost)
aj.RAMCostAdjustment = formatFloat64ForResponse(a.RAMCostAdjustment)
aj.RAMEfficiency = formatFloat64ForResponse(a.RAMEfficiency())
aj.SharedCost = formatFloat64ForResponse(a.SharedCost)
aj.ExternalCost = formatFloat64ForResponse(a.ExternalCost)
aj.TotalCost = formatFloat64ForResponse(a.TotalCost())
aj.TotalEfficiency = formatFloat64ForResponse(a.TotalEfficiency())
aj.RawAllocationOnly = a.RawAllocationOnly
aj.ProportionalAssetResourceCosts = &a.ProportionalAssetResourceCosts
aj.LoadBalancers = a.LoadBalancers
aj.SharedCostBreakdown = &a.SharedCostBreakdown
}
// formatFloat64ForResponse - take an existing float64, round it to 6 decimal places and return is possible, or return nil if invalid
func formatFloat64ForResponse(f float64) *float64 {
if math.IsNaN(f) || math.IsInf(f, 0) {
return nil
}
// 6 digits of precision is the maximum the API should return
result := math.Round(f*100000) / 100000.0
return &result
}
// MarshalJSON implements json.Marshaler interface
func (a *Allocation) MarshalJSON() ([]byte, error) {
aj := &AllocationJSON{}
aj.BuildFromAllocation(a)
buffer, err := json.Marshal(aj)
if err != nil {
return nil, fmt.Errorf("unable to marshal allocation %s to JSON: %s", aj.Name, err)
}
return buffer, nil
}
// UnmarshalJSON prevent nil pointer on PVAllocations
func (a *Allocation) UnmarshalJSON(b []byte) error {
// initialize PV to prevent nil panic
a.PVs = PVAllocations{}
// Aliasing Allocation and casting to alias gives access to the default unmarshaller
type alloc Allocation
err := json.Unmarshal(b, (*alloc)(a))
if err != nil {
return err
}
// clear PVs if they are empty, it is not initialized when empty
if len(a.PVs) == 0 {
a.PVs = nil
}
return nil
}
// MarshalJSON marshals PVAllocation as map[*PVKey]*PVAllocation this allows PVKey to retain its values through marshalling
func (pv PVAllocations) MarshalJSON() (b []byte, err error) {
pointerMap := make(map[*PVKey]*PVAllocation)
for pvKey, pvAlloc := range pv {
kp := pvKey
pointerMap[&kp] = pvAlloc
}
return json.Marshal(pointerMap)
}
// MarshalText converts PVKey to string to make it compatible with JSON Marshaller as an Object key
// this function is required to have a value caller for the actual values to be saved
func (pvk PVKey) MarshalText() (text []byte, err error) {
return []byte(pvk.String()), nil
}
// UnmarshalText converts JSON key string to PVKey it compatible with JSON Unmarshaller from an Object key
// this function is required to have a pointer caller for values to be pulled into marshalling struct
func (pvk *PVKey) UnmarshalText(text []byte) error {
return pvk.FromString(string(text))
}
// MarshalJSON JSON-encodes the AllocationSet
func (as *AllocationSet) MarshalJSON() ([]byte, error) {
if as == nil {
return json.Marshal(map[string]*Allocation{})
}
return json.Marshal(as.Allocations)
}
// MarshalJSON JSON-encodes the range
func (asr *AllocationSetRange) MarshalJSON() ([]byte, error) {
if asr == nil {
return json.Marshal([]*AllocationSet{})
}
return json.Marshal(asr.Allocations)
}