allocation_consistency_test.go 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996
  1. package costmodel
  2. // F-19u / OC-04 repro (invariant E3: one consistent data view per computation).
  3. //
  4. // computeAllocation queries the data source in two phases: buildPodMap runs
  5. // QueryPods/QueryPodsUID in its own QueryGroup, then computeAllocation calls
  6. // DataSource.Metrics() again and issues the resource queries. A data source
  7. // that swaps in-memory snapshots between (or during) those phases yields a pod
  8. // map from one state and resource series from another; series for pods not in
  9. // the map are silently dropped.
  10. //
  11. // swapQuerier models such a source: it holds two immutable states (A and B)
  12. // and serves query number < flipAfter from A and every later query from B,
  13. // counting across all Metrics() calls. It implements source.PinnableMetricsQuerier:
  14. // a pinned view serves every query from the state current at pin time, as an
  15. // adapter over immutable snapshots would.
  16. import (
  17. "sort"
  18. "strings"
  19. "sync"
  20. "testing"
  21. "time"
  22. "github.com/julienschmidt/httprouter"
  23. "github.com/opencost/opencost/core/pkg/clusters"
  24. "github.com/opencost/opencost/core/pkg/diagnostics"
  25. "github.com/opencost/opencost/core/pkg/source"
  26. "github.com/opencost/opencost/core/pkg/storage"
  27. "github.com/opencost/opencost/core/pkg/util"
  28. "github.com/opencost/opencost/pkg/cloud/provider"
  29. "github.com/opencost/opencost/pkg/config"
  30. "github.com/stretchr/testify/require"
  31. )
  32. const (
  33. swapStateA = 0
  34. swapStateB = 1
  35. )
  36. var swapStateNames = [2]string{"A", "B"}
  37. type servedQuery struct {
  38. method string
  39. state int
  40. // pinned is true when the query was issued through a pinned view
  41. pinned bool
  42. }
  43. // swapQuerier is a MetricsQuerier over two snapshots that flips from state A
  44. // to state B once flipAfter queries have been served.
  45. type swapQuerier struct {
  46. states [2]source.MetricsQuerier
  47. flipAfter int
  48. // parent and pinnedState are set on a pinned view; queries are recorded on the parent
  49. parent *swapQuerier
  50. pinnedState int
  51. mu sync.Mutex
  52. served []servedQuery
  53. pins int
  54. releases int
  55. }
  56. var _ source.PinnableMetricsQuerier = (*swapQuerier)(nil)
  57. // currentState returns the state an unpinned query would be served from; q.mu must be held
  58. func (q *swapQuerier) currentState() int {
  59. if len(q.served) >= q.flipAfter {
  60. return swapStateB
  61. }
  62. return swapStateA
  63. }
  64. func (q *swapQuerier) serve(method string) source.MetricsQuerier {
  65. root := q
  66. if q.parent != nil {
  67. root = q.parent
  68. }
  69. root.mu.Lock()
  70. defer root.mu.Unlock()
  71. state := q.pinnedState
  72. if q.parent == nil {
  73. state = root.currentState()
  74. }
  75. root.served = append(root.served, servedQuery{method: method, state: state, pinned: q.parent != nil})
  76. return q.states[state]
  77. }
  78. func (q *swapQuerier) Pin() (source.MetricsQuerier, func()) {
  79. q.mu.Lock()
  80. defer q.mu.Unlock()
  81. q.pins++
  82. pinned := &swapQuerier{states: q.states, parent: q, pinnedState: q.currentState()}
  83. return pinned, func() {
  84. q.mu.Lock()
  85. defer q.mu.Unlock()
  86. q.releases++
  87. }
  88. }
  89. func (q *swapQuerier) servedQueries() []servedQuery {
  90. q.mu.Lock()
  91. defer q.mu.Unlock()
  92. return append([]servedQuery(nil), q.served...)
  93. }
  94. // swapDataSource returns the same swapQuerier from every Metrics() call, so
  95. // the query count (and hence the flip) spans all Metrics() calls.
  96. type swapDataSource struct {
  97. querier *swapQuerier
  98. resolution time.Duration
  99. metricsCallsN int
  100. mu sync.Mutex
  101. }
  102. var _ source.OpenCostDataSource = (*swapDataSource)(nil)
  103. func (d *swapDataSource) RegisterEndPoints(_ *httprouter.Router) {}
  104. func (d *swapDataSource) RegisterDiagnostics(_ diagnostics.DiagnosticService) {}
  105. func (d *swapDataSource) ClusterMap() clusters.ClusterMap { return nil }
  106. func (d *swapDataSource) ClusterInfo() clusters.ClusterInfoProvider { return nil }
  107. func (d *swapDataSource) BatchDuration() time.Duration { return 0 }
  108. func (d *swapDataSource) Resolution() time.Duration { return d.resolution }
  109. func (d *swapDataSource) Metrics() source.MetricsQuerier {
  110. d.mu.Lock()
  111. d.metricsCallsN++
  112. d.mu.Unlock()
  113. return d.querier
  114. }
  115. func swapTestSnapshot(cluster, node string, pods []string, start, end time.Time) *source.MockMetricsQuerier {
  116. q := source.NewMockMetricsQuerier()
  117. var running []*util.Vector
  118. for ts := start; !ts.After(end); ts = ts.Add(10 * time.Minute) {
  119. running = append(running, &util.Vector{Timestamp: float64(ts.Unix()), Value: 1})
  120. }
  121. var podsRes []*source.PodsResult
  122. var ram, cpu []*source.ContainerMetricResult
  123. for _, p := range pods {
  124. podsRes = append(podsRes, &source.PodsResult{
  125. UID: "uid-" + p, Cluster: cluster, Namespace: "ns", Pod: p, Data: running,
  126. })
  127. ram = append(ram, &source.ContainerMetricResult{
  128. Cluster: cluster, Node: node, Namespace: "ns", Pod: p, Container: "app",
  129. Data: []*util.Vector{{Timestamp: float64(end.Unix()), Value: 1024 * 1024 * 1024}},
  130. })
  131. cpu = append(cpu, &source.ContainerMetricResult{
  132. Cluster: cluster, Node: node, Namespace: "ns", Pod: p, Container: "app",
  133. Data: []*util.Vector{{Timestamp: float64(end.Unix()), Value: 1}},
  134. })
  135. }
  136. q.SetOverride(source.QueryPods, podsRes)
  137. q.SetOverride(source.QueryPodsUID, podsRes)
  138. q.SetOverride(source.QueryRAMBytesAllocated, ram)
  139. q.SetOverride(source.QueryRAMRequests, ram)
  140. q.SetOverride(source.QueryCPUCoresAllocated, cpu)
  141. q.SetOverride(source.QueryCPURequests, cpu)
  142. return q
  143. }
  144. func TestComputeAllocation_ConsistentDataView(t *testing.T) {
  145. // the data source swaps its snapshot after the first query (the pod query): computeAllocation must
  146. // still see only state A, so pod-b is absent and none of its data is used
  147. t.Run("swap after pod query", func(t *testing.T) { checkConsistentDataView(t, 1, false) })
  148. // the swap happens before the computation starts: everything comes from state B, including pod-b
  149. t.Run("swap before computation", func(t *testing.T) { checkConsistentDataView(t, 0, true) })
  150. }
  151. func checkConsistentDataView(t *testing.T, flipAfter int, wantPodB bool) {
  152. const cluster, node = "cluster-one", "node-1"
  153. end := time.Now().UTC().Truncate(time.Hour)
  154. start := end.Add(-time.Hour)
  155. stateA := swapTestSnapshot(cluster, node, []string{"pod-a"}, start, end)
  156. stateB := swapTestSnapshot(cluster, node, []string{"pod-a", "pod-b"}, start, end)
  157. // Flip after the first query: the pod query (buildPodMap's first call)
  158. // is served from A, every subsequent query from B, i.e. the adapter
  159. // swapped its snapshot between the pod phase and the resource phase.
  160. querier := &swapQuerier{states: [2]source.MetricsQuerier{stateA, stateB}, flipAfter: flipAfter}
  161. ds := &swapDataSource{querier: querier, resolution: time.Minute}
  162. confMan := config.NewConfigFileManager(storage.NewFileStorage("../../"))
  163. customProvider := &provider.CSVProvider{
  164. CSVLocation: "../../configs/pricing_schema_pv.csv",
  165. CustomProvider: &provider.CustomProvider{
  166. Config: provider.NewProviderConfig(confMan, "../../configs/default.json"),
  167. },
  168. }
  169. require.NoError(t, customProvider.DownloadPricingData())
  170. cm := &CostModel{DataSource: ds, Provider: customProvider}
  171. allocSet, _, err := cm.computeAllocation(start, end)
  172. require.NoError(t, err)
  173. require.NotNil(t, allocSet)
  174. served := querier.servedQueries()
  175. require.NotEmpty(t, served, "fake served no queries; computeAllocation did not use the data source")
  176. byState := map[int][]string{}
  177. for _, s := range served {
  178. byState[s.state] = append(byState[s.state], s.method)
  179. }
  180. podPresent := map[string]bool{}
  181. var podBRAM, podBCPU float64
  182. for _, alloc := range allocSet.Allocations {
  183. p := alloc.Properties.Pod
  184. for _, name := range []string{"pod-a", "pod-b"} {
  185. if p == name || strings.HasPrefix(p, name+" ") {
  186. podPresent[name] = true
  187. if name == "pod-b" {
  188. podBRAM += alloc.RAMByteHours
  189. podBCPU += alloc.CPUCoreHours
  190. }
  191. }
  192. }
  193. }
  194. // E3 (direct): every query in one computeAllocation call must be served
  195. // from the same data-source state.
  196. if len(byState) > 1 {
  197. for _, st := range []int{swapStateA, swapStateB} {
  198. methods := append([]string(nil), byState[st]...)
  199. sort.Strings(methods)
  200. t.Logf("state %s served %d queries, e.g. %v", swapStateNames[st], len(methods), head(methods, 6))
  201. }
  202. t.Errorf("E3 violated: one computeAllocation call was served from %d data-source states (A=%d queries, B=%d queries, %d Metrics() calls); the pod map and the resource series come from different snapshots",
  203. len(byState), len(byState[swapStateA]), len(byState[swapStateB]), ds.metricsCallsN)
  204. }
  205. // Diagnostic consequence: state B carried RAM/CPU series for pod-b, but
  206. // pod-b was not in state A's pod map, so those series were dropped.
  207. fromB := len(byState[swapStateB]) > 0
  208. if fromB && !podPresent["pod-b"] {
  209. t.Logf("consequence: pod-b RAM/CPU series were fetched from state B but pod-b is absent from the AllocationSet (silently dropped); pods present: %v", podPresent)
  210. }
  211. // E3 (outcome): pod-b is either absent with none of its data used, or
  212. // fully present with its allocation.
  213. if podPresent["pod-b"] {
  214. if podBRAM <= 0 || podBCPU <= 0 {
  215. t.Errorf("E3 violated: pod-b present but incomplete (RAMByteHours=%v CPUCoreHours=%v)", podBRAM, podBCPU)
  216. }
  217. }
  218. if !podPresent["pod-a"] {
  219. t.Errorf("pod-a missing from AllocationSet; test setup is not driving computeAllocation end to end")
  220. }
  221. if podPresent["pod-b"] != wantPodB {
  222. t.Errorf("pod-b present = %v, want %v", podPresent["pod-b"], wantPodB)
  223. }
  224. requireAllPinned(t, querier)
  225. }
  226. // requireAllPinned fails if any query bypassed the pinned view, or the querier was not pinned and
  227. // released exactly once. A bypassing query can be served from a different state than the pinned view
  228. // whenever the data source swaps between Pin() and that query.
  229. func requireAllPinned(t *testing.T, querier *swapQuerier) {
  230. t.Helper()
  231. var bypassed []string
  232. for _, s := range querier.servedQueries() {
  233. if !s.pinned {
  234. bypassed = append(bypassed, s.method)
  235. }
  236. }
  237. if len(bypassed) > 0 {
  238. t.Errorf("E3 violated: %d queries bypassed the pinned querier: %v", len(bypassed), head(bypassed, 6))
  239. }
  240. querier.mu.Lock()
  241. defer querier.mu.Unlock()
  242. if querier.pins != 1 || querier.releases != 1 {
  243. t.Errorf("expected the querier to be pinned and released once per computation, got pins=%d releases=%d", querier.pins, querier.releases)
  244. }
  245. }
  246. func head(s []string, n int) []string {
  247. if len(s) <= n {
  248. return s
  249. }
  250. return s[:n]
  251. }
  252. // ---- swapQuerier: MetricsQuerier forwarding (generated from source.RecordMetricsQuerier) ----
  253. func (q *swapQuerier) QueryLocalStorageActiveMinutes(start, end time.Time) *source.Future[source.LocalStorageActiveMinutesResult] {
  254. return q.serve(source.QueryLocalStorageActiveMinutes).QueryLocalStorageActiveMinutes(start, end)
  255. }
  256. func (q *swapQuerier) QueryLocalStorageUsedAvg(start, end time.Time) *source.Future[source.LocalStorageUsedAvgResult] {
  257. return q.serve(source.QueryLocalStorageUsedAvg).QueryLocalStorageUsedAvg(start, end)
  258. }
  259. func (q *swapQuerier) QueryLocalStorageUsedMax(start, end time.Time) *source.Future[source.LocalStorageUsedMaxResult] {
  260. return q.serve(source.QueryLocalStorageUsedMax).QueryLocalStorageUsedMax(start, end)
  261. }
  262. func (q *swapQuerier) QueryLocalStorageBytes(start, end time.Time) *source.Future[source.LocalStorageBytesResult] {
  263. return q.serve(source.QueryLocalStorageBytes).QueryLocalStorageBytes(start, end)
  264. }
  265. func (q *swapQuerier) QueryKMLocalStorageUsedAvg(start, end time.Time) *source.Future[source.NodeUIDValueResult] {
  266. return q.serve(source.QueryKMLocalStorageUsedAvg).QueryKMLocalStorageUsedAvg(start, end)
  267. }
  268. func (q *swapQuerier) QueryKMLocalStorageUsedMax(start, end time.Time) *source.Future[source.NodeUIDValueResult] {
  269. return q.serve(source.QueryKMLocalStorageUsedMax).QueryKMLocalStorageUsedMax(start, end)
  270. }
  271. func (q *swapQuerier) QueryKMLocalStorageBytes(start, end time.Time) *source.Future[source.UIDValueResult] {
  272. return q.serve(source.QueryKMLocalStorageBytes).QueryKMLocalStorageBytes(start, end)
  273. }
  274. func (q *swapQuerier) QueryNodeInfo(start, end time.Time) *source.Future[source.NodeInfoResult] {
  275. return q.serve(source.QueryNodeInfo).QueryNodeInfo(start, end)
  276. }
  277. func (q *swapQuerier) QueryNodeUptime(start, end time.Time) *source.Future[source.UptimeResult] {
  278. return q.serve(source.QueryNodeUptime).QueryNodeUptime(start, end)
  279. }
  280. func (q *swapQuerier) QueryNodeActiveMinutes(start, end time.Time) *source.Future[source.NodeActiveMinutesResult] {
  281. return q.serve(source.QueryNodeActiveMinutes).QueryNodeActiveMinutes(start, end)
  282. }
  283. func (q *swapQuerier) QueryNodeCPUCoresCapacity(start, end time.Time) *source.Future[source.NodeCPUCoresCapacityResult] {
  284. return q.serve(source.QueryNodeCPUCoresCapacity).QueryNodeCPUCoresCapacity(start, end)
  285. }
  286. func (q *swapQuerier) QueryNodeCPUCoresAllocatable(start, end time.Time) *source.Future[source.NodeCPUCoresAllocatableResult] {
  287. return q.serve(source.QueryNodeCPUCoresAllocatable).QueryNodeCPUCoresAllocatable(start, end)
  288. }
  289. func (q *swapQuerier) QueryNodeRAMBytesCapacity(start, end time.Time) *source.Future[source.NodeRAMBytesCapacityResult] {
  290. return q.serve(source.QueryNodeRAMBytesCapacity).QueryNodeRAMBytesCapacity(start, end)
  291. }
  292. func (q *swapQuerier) QueryNodeRAMBytesAllocatable(start, end time.Time) *source.Future[source.NodeRAMBytesAllocatableResult] {
  293. return q.serve(source.QueryNodeRAMBytesAllocatable).QueryNodeRAMBytesAllocatable(start, end)
  294. }
  295. func (q *swapQuerier) QueryNodeGPUCount(start, end time.Time) *source.Future[source.NodeGPUCountResult] {
  296. return q.serve(source.QueryNodeGPUCount).QueryNodeGPUCount(start, end)
  297. }
  298. func (q *swapQuerier) QueryNodeCPUModeTotal(start, end time.Time) *source.Future[source.NodeCPUModeTotalResult] {
  299. return q.serve(source.QueryNodeCPUModeTotal).QueryNodeCPUModeTotal(start, end)
  300. }
  301. func (q *swapQuerier) QueryNodeIsSpot(start, end time.Time) *source.Future[source.NodeIsSpotResult] {
  302. return q.serve(source.QueryNodeIsSpot).QueryNodeIsSpot(start, end)
  303. }
  304. func (q *swapQuerier) QueryNodeRAMSystemPercent(start, end time.Time) *source.Future[source.NodeRAMSystemPercentResult] {
  305. return q.serve(source.QueryNodeRAMSystemPercent).QueryNodeRAMSystemPercent(start, end)
  306. }
  307. func (q *swapQuerier) QueryNodeRAMUserPercent(start, end time.Time) *source.Future[source.NodeRAMUserPercentResult] {
  308. return q.serve(source.QueryNodeRAMUserPercent).QueryNodeRAMUserPercent(start, end)
  309. }
  310. func (q *swapQuerier) QueryNodeResourceCapacities(start, end time.Time) *source.Future[source.ResourceResult] {
  311. return q.serve(source.QueryNodeResourceCapacities).QueryNodeResourceCapacities(start, end)
  312. }
  313. func (q *swapQuerier) QueryNodeResourcesAllocatable(start, end time.Time) *source.Future[source.ResourceResult] {
  314. return q.serve(source.QueryNodeResourcesAllocatable).QueryNodeResourcesAllocatable(start, end)
  315. }
  316. func (q *swapQuerier) QueryLBActiveMinutes(start, end time.Time) *source.Future[source.LBActiveMinutesResult] {
  317. return q.serve(source.QueryLBActiveMinutes).QueryLBActiveMinutes(start, end)
  318. }
  319. func (q *swapQuerier) QueryLBPricePerHr(start, end time.Time) *source.Future[source.LBPricePerHrResult] {
  320. return q.serve(source.QueryLBPricePerHr).QueryLBPricePerHr(start, end)
  321. }
  322. func (q *swapQuerier) QueryClusterInfo(start, end time.Time) *source.Future[source.ClusterInfoResult] {
  323. return q.serve(source.QueryClusterInfo).QueryClusterInfo(start, end)
  324. }
  325. func (q *swapQuerier) QueryClusterKubeModelVersion(start, end time.Time) *source.Future[source.ClusterKubeModelVersionResult] {
  326. return q.serve(source.QueryClusterKubeModelVersion).QueryClusterKubeModelVersion(start, end)
  327. }
  328. func (q *swapQuerier) QueryClusterUptime(start, end time.Time) *source.Future[source.UptimeResult] {
  329. return q.serve(source.QueryClusterUptime).QueryClusterUptime(start, end)
  330. }
  331. func (q *swapQuerier) QueryClusterManagementDuration(start, end time.Time) *source.Future[source.ClusterManagementDurationResult] {
  332. return q.serve(source.QueryClusterManagementDuration).QueryClusterManagementDuration(start, end)
  333. }
  334. func (q *swapQuerier) QueryClusterManagementPricePerHr(start, end time.Time) *source.Future[source.ClusterManagementPricePerHrResult] {
  335. return q.serve(source.QueryClusterManagementPricePerHr).QueryClusterManagementPricePerHr(start, end)
  336. }
  337. func (q *swapQuerier) QueryPods(start, end time.Time) *source.Future[source.PodsResult] {
  338. return q.serve(source.QueryPods).QueryPods(start, end)
  339. }
  340. func (q *swapQuerier) QueryPodsUID(start, end time.Time) *source.Future[source.PodsResult] {
  341. return q.serve(source.QueryPodsUID).QueryPodsUID(start, end)
  342. }
  343. func (q *swapQuerier) QueryPodInfo(start, end time.Time) *source.Future[source.PodInfoResult] {
  344. return q.serve(source.QueryPodInfo).QueryPodInfo(start, end)
  345. }
  346. func (q *swapQuerier) QueryPodUptime(start, end time.Time) *source.Future[source.UptimeResult] {
  347. return q.serve(source.QueryPodUptime).QueryPodUptime(start, end)
  348. }
  349. func (q *swapQuerier) QueryPodOwners(start, end time.Time) *source.Future[source.OwnerResult] {
  350. return q.serve(source.QueryPodOwners).QueryPodOwners(start, end)
  351. }
  352. func (q *swapQuerier) QueryPodPVCVolumes(start, end time.Time) *source.Future[source.PodPVCVolumeResult] {
  353. return q.serve(source.QueryPodPVCVolumes).QueryPodPVCVolumes(start, end)
  354. }
  355. func (q *swapQuerier) QueryPodNetworkEgressBytes(start, end time.Time) *source.Future[source.PodNetworkBytesResult] {
  356. return q.serve(source.QueryPodNetworkEgressBytes).QueryPodNetworkEgressBytes(start, end)
  357. }
  358. func (q *swapQuerier) QueryPodNetworkIngressBytes(start, end time.Time) *source.Future[source.PodNetworkBytesResult] {
  359. return q.serve(source.QueryPodNetworkIngressBytes).QueryPodNetworkIngressBytes(start, end)
  360. }
  361. func (q *swapQuerier) QueryContainerUptime(start, end time.Time) *source.Future[source.ContainerUptimeResult] {
  362. return q.serve(source.QueryContainerUptime).QueryContainerUptime(start, end)
  363. }
  364. func (q *swapQuerier) QueryContainerResourceRequests(start, end time.Time) *source.Future[source.ContainerResourceResult] {
  365. return q.serve(source.QueryContainerResourceRequests).QueryContainerResourceRequests(start, end)
  366. }
  367. func (q *swapQuerier) QueryContainerResourceLimits(start, end time.Time) *source.Future[source.ContainerResourceResult] {
  368. return q.serve(source.QueryContainerResourceLimits).QueryContainerResourceLimits(start, end)
  369. }
  370. func (q *swapQuerier) QueryRAMBytesAllocated(start, end time.Time) *source.Future[source.RAMBytesAllocatedResult] {
  371. return q.serve(source.QueryRAMBytesAllocated).QueryRAMBytesAllocated(start, end)
  372. }
  373. func (q *swapQuerier) QueryRAMRequests(start, end time.Time) *source.Future[source.RAMRequestsResult] {
  374. return q.serve(source.QueryRAMRequests).QueryRAMRequests(start, end)
  375. }
  376. func (q *swapQuerier) QueryRAMLimits(start, end time.Time) *source.Future[source.RAMLimitsResult] {
  377. return q.serve(source.QueryRAMLimits).QueryRAMLimits(start, end)
  378. }
  379. func (q *swapQuerier) QueryRAMUsageAvg(start, end time.Time) *source.Future[source.RAMUsageAvgResult] {
  380. return q.serve(source.QueryRAMUsageAvg).QueryRAMUsageAvg(start, end)
  381. }
  382. func (q *swapQuerier) QueryRAMUsageMax(start, end time.Time) *source.Future[source.RAMUsageMaxResult] {
  383. return q.serve(source.QueryRAMUsageMax).QueryRAMUsageMax(start, end)
  384. }
  385. func (q *swapQuerier) QueryNodeRAMPricePerGiBHr(start, end time.Time) *source.Future[source.NodeRAMPricePerGiBHrResult] {
  386. return q.serve(source.QueryNodeRAMPricePerGiBHr).QueryNodeRAMPricePerGiBHr(start, end)
  387. }
  388. func (q *swapQuerier) QueryCPUCoresAllocated(start, end time.Time) *source.Future[source.CPUCoresAllocatedResult] {
  389. return q.serve(source.QueryCPUCoresAllocated).QueryCPUCoresAllocated(start, end)
  390. }
  391. func (q *swapQuerier) QueryCPURequests(start, end time.Time) *source.Future[source.CPURequestsResult] {
  392. return q.serve(source.QueryCPURequests).QueryCPURequests(start, end)
  393. }
  394. func (q *swapQuerier) QueryCPULimits(start, end time.Time) *source.Future[source.CPULimitsResult] {
  395. return q.serve(source.QueryCPULimits).QueryCPULimits(start, end)
  396. }
  397. func (q *swapQuerier) QueryCPUUsageAvg(start, end time.Time) *source.Future[source.CPUUsageAvgResult] {
  398. return q.serve(source.QueryCPUUsageAvg).QueryCPUUsageAvg(start, end)
  399. }
  400. func (q *swapQuerier) QueryCPUUsageMax(start, end time.Time) *source.Future[source.CPUUsageMaxResult] {
  401. return q.serve(source.QueryCPUUsageMax).QueryCPUUsageMax(start, end)
  402. }
  403. func (q *swapQuerier) QueryNodeCPUPricePerHr(start, end time.Time) *source.Future[source.NodeCPUPricePerHrResult] {
  404. return q.serve(source.QueryNodeCPUPricePerHr).QueryNodeCPUPricePerHr(start, end)
  405. }
  406. func (q *swapQuerier) QueryGPUsAllocated(start, end time.Time) *source.Future[source.GPUsAllocatedResult] {
  407. return q.serve(source.QueryGPUsAllocated).QueryGPUsAllocated(start, end)
  408. }
  409. func (q *swapQuerier) QueryGPUsRequested(start, end time.Time) *source.Future[source.GPUsRequestedResult] {
  410. return q.serve(source.QueryGPUsRequested).QueryGPUsRequested(start, end)
  411. }
  412. func (q *swapQuerier) QueryGPUsUsageAvg(start, end time.Time) *source.Future[source.GPUsUsageAvgResult] {
  413. return q.serve(source.QueryGPUsUsageAvg).QueryGPUsUsageAvg(start, end)
  414. }
  415. func (q *swapQuerier) QueryGPUsUsageMax(start, end time.Time) *source.Future[source.GPUsUsageMaxResult] {
  416. return q.serve(source.QueryGPUsUsageMax).QueryGPUsUsageMax(start, end)
  417. }
  418. func (q *swapQuerier) QueryNodeGPUPricePerHr(start, end time.Time) *source.Future[source.NodeGPUPricePerHrResult] {
  419. return q.serve(source.QueryNodeGPUPricePerHr).QueryNodeGPUPricePerHr(start, end)
  420. }
  421. func (q *swapQuerier) QueryGPUInfo(start, end time.Time) *source.Future[source.GPUInfoResult] {
  422. return q.serve(source.QueryGPUInfo).QueryGPUInfo(start, end)
  423. }
  424. func (q *swapQuerier) QueryIsGPUShared(start, end time.Time) *source.Future[source.IsGPUSharedResult] {
  425. return q.serve(source.QueryIsGPUShared).QueryIsGPUShared(start, end)
  426. }
  427. func (q *swapQuerier) QueryDCGMDeviceInfo(start, end time.Time) *source.Future[source.DCGMDeviceInfoResult] {
  428. return q.serve(source.QueryDCGMDeviceInfo).QueryDCGMDeviceInfo(start, end)
  429. }
  430. func (q *swapQuerier) QueryDCGMDeviceUptime(start, end time.Time) *source.Future[source.DCGMDeviceUptimeResult] {
  431. return q.serve(source.QueryDCGMDeviceUptime).QueryDCGMDeviceUptime(start, end)
  432. }
  433. func (q *swapQuerier) QueryDCGMContainerUsageAvg(start, end time.Time) *source.Future[source.DCGMDeviceContainerUsageResult] {
  434. return q.serve(source.QueryDCGMContainerUsageAvg).QueryDCGMContainerUsageAvg(start, end)
  435. }
  436. func (q *swapQuerier) QueryDCGMContainerUsageMax(start, end time.Time) *source.Future[source.DCGMDeviceContainerUsageResult] {
  437. return q.serve(source.QueryDCGMContainerUsageMax).QueryDCGMContainerUsageMax(start, end)
  438. }
  439. func (q *swapQuerier) QueryPodPVCAllocation(start, end time.Time) *source.Future[source.PodPVCAllocationResult] {
  440. return q.serve(source.QueryPodPVCAllocation).QueryPodPVCAllocation(start, end)
  441. }
  442. func (q *swapQuerier) QueryPVCBytesRequested(start, end time.Time) *source.Future[source.PVCBytesRequestedResult] {
  443. return q.serve(source.QueryPVCBytesRequested).QueryPVCBytesRequested(start, end)
  444. }
  445. func (q *swapQuerier) QueryPVCInfo(start, end time.Time) *source.Future[source.PVCInfoResult] {
  446. return q.serve(source.QueryPVCInfo).QueryPVCInfo(start, end)
  447. }
  448. func (q *swapQuerier) QueryKMPVCInfo(start, end time.Time) *source.Future[source.PVCInfoResult] {
  449. return q.serve(source.QueryKMPVCInfo).QueryKMPVCInfo(start, end)
  450. }
  451. func (q *swapQuerier) QueryPVCUptime(start, end time.Time) *source.Future[source.UptimeResult] {
  452. return q.serve(source.QueryPVCUptime).QueryPVCUptime(start, end)
  453. }
  454. func (q *swapQuerier) QueryPVCBytesUsedAverage(start, end time.Time) *source.Future[source.PVCUIDValueResult] {
  455. return q.serve(source.QueryPVCBytesUsedAverage).QueryPVCBytesUsedAverage(start, end)
  456. }
  457. func (q *swapQuerier) QueryPVCBytesUsedMax(start, end time.Time) *source.Future[source.PVCUIDValueResult] {
  458. return q.serve(source.QueryPVCBytesUsedMax).QueryPVCBytesUsedMax(start, end)
  459. }
  460. func (q *swapQuerier) QueryPVBytes(start, end time.Time) *source.Future[source.PVBytesResult] {
  461. return q.serve(source.QueryPVBytes).QueryPVBytes(start, end)
  462. }
  463. func (q *swapQuerier) QueryPVPricePerGiBHour(start, end time.Time) *source.Future[source.PVPricePerGiBHourResult] {
  464. return q.serve(source.QueryPVPricePerGiBHour).QueryPVPricePerGiBHour(start, end)
  465. }
  466. func (q *swapQuerier) QueryPVInfo(start, end time.Time) *source.Future[source.PVInfoResult] {
  467. return q.serve(source.QueryPVInfo).QueryPVInfo(start, end)
  468. }
  469. func (q *swapQuerier) QueryPVActiveMinutes(start, end time.Time) *source.Future[source.PVActiveMinutesResult] {
  470. return q.serve(source.QueryPVActiveMinutes).QueryPVActiveMinutes(start, end)
  471. }
  472. func (q *swapQuerier) QueryPVUsedAverage(start, end time.Time) *source.Future[source.PVUsedAvgResult] {
  473. return q.serve(source.QueryPVUsedAverage).QueryPVUsedAverage(start, end)
  474. }
  475. func (q *swapQuerier) QueryPVUsedMax(start, end time.Time) *source.Future[source.PVUsedMaxResult] {
  476. return q.serve(source.QueryPVUsedMax).QueryPVUsedMax(start, end)
  477. }
  478. func (q *swapQuerier) QueryKMPVInfo(start, end time.Time) *source.Future[source.PVInfoResult] {
  479. return q.serve(source.QueryKMPVInfo).QueryKMPVInfo(start, end)
  480. }
  481. func (q *swapQuerier) QueryPVUptime(start, end time.Time) *source.Future[source.UptimeResult] {
  482. return q.serve(source.QueryPVUptime).QueryPVUptime(start, end)
  483. }
  484. func (q *swapQuerier) QueryDeploymentInfo(start, end time.Time) *source.Future[source.DeploymentInfoResult] {
  485. return q.serve(source.QueryDeploymentInfo).QueryDeploymentInfo(start, end)
  486. }
  487. func (q *swapQuerier) QueryDeploymentUptime(start, end time.Time) *source.Future[source.UptimeResult] {
  488. return q.serve(source.QueryDeploymentUptime).QueryDeploymentUptime(start, end)
  489. }
  490. func (q *swapQuerier) QueryDeploymentLabels(start, end time.Time) *source.Future[source.LabelsResult] {
  491. return q.serve(source.QueryDeploymentLabels).QueryDeploymentLabels(start, end)
  492. }
  493. func (q *swapQuerier) QueryDeploymentAnnotations(start, end time.Time) *source.Future[source.AnnotationsResult] {
  494. return q.serve(source.QueryDeploymentAnnotations).QueryDeploymentAnnotations(start, end)
  495. }
  496. func (q *swapQuerier) QueryDeploymentMatchLabels(start, end time.Time) *source.Future[source.DeploymentLabelsResult] {
  497. return q.serve(source.QueryDeploymentMatchLabels).QueryDeploymentMatchLabels(start, end)
  498. }
  499. func (q *swapQuerier) QueryStatefulSetInfo(start, end time.Time) *source.Future[source.StatefulSetInfoResult] {
  500. return q.serve(source.QueryStatefulSetInfo).QueryStatefulSetInfo(start, end)
  501. }
  502. func (q *swapQuerier) QueryStatefulSetUptime(start, end time.Time) *source.Future[source.UptimeResult] {
  503. return q.serve(source.QueryStatefulSetUptime).QueryStatefulSetUptime(start, end)
  504. }
  505. func (q *swapQuerier) QueryStatefulSetLabels(start, end time.Time) *source.Future[source.LabelsResult] {
  506. return q.serve(source.QueryStatefulSetLabels).QueryStatefulSetLabels(start, end)
  507. }
  508. func (q *swapQuerier) QueryStatefulSetAnnotations(start, end time.Time) *source.Future[source.AnnotationsResult] {
  509. return q.serve(source.QueryStatefulSetAnnotations).QueryStatefulSetAnnotations(start, end)
  510. }
  511. func (q *swapQuerier) QueryStatefulSetMatchLabels(start, end time.Time) *source.Future[source.StatefulSetLabelsResult] {
  512. return q.serve(source.QueryStatefulSetMatchLabels).QueryStatefulSetMatchLabels(start, end)
  513. }
  514. func (q *swapQuerier) QueryDaemonSetInfo(start, end time.Time) *source.Future[source.DaemonSetInfoResult] {
  515. return q.serve(source.QueryDaemonSetInfo).QueryDaemonSetInfo(start, end)
  516. }
  517. func (q *swapQuerier) QueryDaemonSetUptime(start, end time.Time) *source.Future[source.UptimeResult] {
  518. return q.serve(source.QueryDaemonSetUptime).QueryDaemonSetUptime(start, end)
  519. }
  520. func (q *swapQuerier) QueryDaemonSetLabels(start, end time.Time) *source.Future[source.LabelsResult] {
  521. return q.serve(source.QueryDaemonSetLabels).QueryDaemonSetLabels(start, end)
  522. }
  523. func (q *swapQuerier) QueryDaemonSetAnnotations(start, end time.Time) *source.Future[source.AnnotationsResult] {
  524. return q.serve(source.QueryDaemonSetAnnotations).QueryDaemonSetAnnotations(start, end)
  525. }
  526. func (q *swapQuerier) QueryDaemonSetArguments(start, end time.Time) *source.Future[source.DaemonSetArgumentResult] {
  527. return q.serve(source.QueryDaemonSetArguments).QueryDaemonSetArguments(start, end)
  528. }
  529. func (q *swapQuerier) QueryJobInfo(start, end time.Time) *source.Future[source.JobInfoResult] {
  530. return q.serve(source.QueryJobInfo).QueryJobInfo(start, end)
  531. }
  532. func (q *swapQuerier) QueryJobUptime(start, end time.Time) *source.Future[source.UptimeResult] {
  533. return q.serve(source.QueryJobUptime).QueryJobUptime(start, end)
  534. }
  535. func (q *swapQuerier) QueryJobLabels(start, end time.Time) *source.Future[source.LabelsResult] {
  536. return q.serve(source.QueryJobLabels).QueryJobLabels(start, end)
  537. }
  538. func (q *swapQuerier) QueryJobAnnotations(start, end time.Time) *source.Future[source.AnnotationsResult] {
  539. return q.serve(source.QueryJobAnnotations).QueryJobAnnotations(start, end)
  540. }
  541. func (q *swapQuerier) QueryCronJobInfo(start, end time.Time) *source.Future[source.CronJobInfoResult] {
  542. return q.serve(source.QueryCronJobInfo).QueryCronJobInfo(start, end)
  543. }
  544. func (q *swapQuerier) QueryCronJobUptime(start, end time.Time) *source.Future[source.UptimeResult] {
  545. return q.serve(source.QueryCronJobUptime).QueryCronJobUptime(start, end)
  546. }
  547. func (q *swapQuerier) QueryCronJobLabels(start, end time.Time) *source.Future[source.LabelsResult] {
  548. return q.serve(source.QueryCronJobLabels).QueryCronJobLabels(start, end)
  549. }
  550. func (q *swapQuerier) QueryCronJobAnnotations(start, end time.Time) *source.Future[source.AnnotationsResult] {
  551. return q.serve(source.QueryCronJobAnnotations).QueryCronJobAnnotations(start, end)
  552. }
  553. func (q *swapQuerier) QueryReplicaSetInfo(start, end time.Time) *source.Future[source.ReplicaSetInfoResult] {
  554. return q.serve(source.QueryReplicaSetInfo).QueryReplicaSetInfo(start, end)
  555. }
  556. func (q *swapQuerier) QueryReplicaSetUptime(start, end time.Time) *source.Future[source.UptimeResult] {
  557. return q.serve(source.QueryReplicaSetUptime).QueryReplicaSetUptime(start, end)
  558. }
  559. func (q *swapQuerier) QueryReplicaSetLabels(start, end time.Time) *source.Future[source.LabelsResult] {
  560. return q.serve(source.QueryReplicaSetLabels).QueryReplicaSetLabels(start, end)
  561. }
  562. func (q *swapQuerier) QueryReplicaSetAnnotations(start, end time.Time) *source.Future[source.AnnotationsResult] {
  563. return q.serve(source.QueryReplicaSetAnnotations).QueryReplicaSetAnnotations(start, end)
  564. }
  565. func (q *swapQuerier) QueryReplicaSetOwners(start, end time.Time) *source.Future[source.OwnerResult] {
  566. return q.serve(source.QueryReplicaSetOwners).QueryReplicaSetOwners(start, end)
  567. }
  568. func (q *swapQuerier) QueryNamespaceInfo(start, end time.Time) *source.Future[source.NamespaceInfoResult] {
  569. return q.serve(source.QueryNamespaceInfo).QueryNamespaceInfo(start, end)
  570. }
  571. func (q *swapQuerier) QueryNamespaceUptime(start, end time.Time) *source.Future[source.UptimeResult] {
  572. return q.serve(source.QueryNamespaceUptime).QueryNamespaceUptime(start, end)
  573. }
  574. func (q *swapQuerier) QueryServiceInfo(start, end time.Time) *source.Future[source.ServiceInfoResult] {
  575. return q.serve(source.QueryServiceInfo).QueryServiceInfo(start, end)
  576. }
  577. func (q *swapQuerier) QueryServiceUptime(start, end time.Time) *source.Future[source.UptimeResult] {
  578. return q.serve(source.QueryServiceUptime).QueryServiceUptime(start, end)
  579. }
  580. func (q *swapQuerier) QueryServiceSelectorLabels(start, end time.Time) *source.Future[source.ServiceLabelsResult] {
  581. return q.serve(source.QueryServiceSelectorLabels).QueryServiceSelectorLabels(start, end)
  582. }
  583. func (q *swapQuerier) QueryNetZoneGiB(start, end time.Time) *source.Future[source.NetZoneGiBResult] {
  584. return q.serve(source.QueryNetZoneGiB).QueryNetZoneGiB(start, end)
  585. }
  586. func (q *swapQuerier) QueryNetZonePricePerGiB(start, end time.Time) *source.Future[source.NetZonePricePerGiBResult] {
  587. return q.serve(source.QueryNetZonePricePerGiB).QueryNetZonePricePerGiB(start, end)
  588. }
  589. func (q *swapQuerier) QueryNetRegionGiB(start, end time.Time) *source.Future[source.NetRegionGiBResult] {
  590. return q.serve(source.QueryNetRegionGiB).QueryNetRegionGiB(start, end)
  591. }
  592. func (q *swapQuerier) QueryNetRegionPricePerGiB(start, end time.Time) *source.Future[source.NetRegionPricePerGiBResult] {
  593. return q.serve(source.QueryNetRegionPricePerGiB).QueryNetRegionPricePerGiB(start, end)
  594. }
  595. func (q *swapQuerier) QueryNetInternetGiB(start, end time.Time) *source.Future[source.NetInternetGiBResult] {
  596. return q.serve(source.QueryNetInternetGiB).QueryNetInternetGiB(start, end)
  597. }
  598. func (q *swapQuerier) QueryNetInternetPricePerGiB(start, end time.Time) *source.Future[source.NetInternetPricePerGiBResult] {
  599. return q.serve(source.QueryNetInternetPricePerGiB).QueryNetInternetPricePerGiB(start, end)
  600. }
  601. func (q *swapQuerier) QueryNetInternetServiceGiB(start, end time.Time) *source.Future[source.NetInternetServiceGiBResult] {
  602. return q.serve(source.QueryNetInternetServiceGiB).QueryNetInternetServiceGiB(start, end)
  603. }
  604. func (q *swapQuerier) QueryNetNatGatewayPricePerGiB(start, end time.Time) *source.Future[source.NetNatGatewayPricePerGiBResult] {
  605. return q.serve(source.QueryNetNatGatewayPricePerGiB).QueryNetNatGatewayPricePerGiB(start, end)
  606. }
  607. func (q *swapQuerier) QueryNetNatGatewayGiB(start, end time.Time) *source.Future[source.NetNatGatewayGiBResult] {
  608. return q.serve(source.QueryNetNatGatewayGiB).QueryNetNatGatewayGiB(start, end)
  609. }
  610. func (q *swapQuerier) QueryNetTransferBytes(start, end time.Time) *source.Future[source.NetTransferBytesResult] {
  611. return q.serve(source.QueryNetTransferBytes).QueryNetTransferBytes(start, end)
  612. }
  613. func (q *swapQuerier) QueryNetZoneIngressGiB(start, end time.Time) *source.Future[source.NetZoneIngressGiBResult] {
  614. return q.serve(source.QueryNetZoneIngressGiB).QueryNetZoneIngressGiB(start, end)
  615. }
  616. func (q *swapQuerier) QueryNetRegionIngressGiB(start, end time.Time) *source.Future[source.NetRegionIngressGiBResult] {
  617. return q.serve(source.QueryNetRegionIngressGiB).QueryNetRegionIngressGiB(start, end)
  618. }
  619. func (q *swapQuerier) QueryNetInternetIngressGiB(start, end time.Time) *source.Future[source.NetInternetIngressGiBResult] {
  620. return q.serve(source.QueryNetInternetIngressGiB).QueryNetInternetIngressGiB(start, end)
  621. }
  622. func (q *swapQuerier) QueryNetInternetServiceIngressGiB(start, end time.Time) *source.Future[source.NetInternetServiceIngressGiBResult] {
  623. return q.serve(source.QueryNetInternetServiceIngressGiB).QueryNetInternetServiceIngressGiB(start, end)
  624. }
  625. func (q *swapQuerier) QueryNetNatGatewayIngressPricePerGiB(start, end time.Time) *source.Future[source.NetNatGatewayPricePerGiBResult] {
  626. return q.serve(source.QueryNetNatGatewayIngressPricePerGiB).QueryNetNatGatewayIngressPricePerGiB(start, end)
  627. }
  628. func (q *swapQuerier) QueryNetNatGatewayIngressGiB(start, end time.Time) *source.Future[source.NetNatGatewayIngressGiBResult] {
  629. return q.serve(source.QueryNetNatGatewayIngressGiB).QueryNetNatGatewayIngressGiB(start, end)
  630. }
  631. func (q *swapQuerier) QueryNetReceiveBytes(start, end time.Time) *source.Future[source.NetReceiveBytesResult] {
  632. return q.serve(source.QueryNetReceiveBytes).QueryNetReceiveBytes(start, end)
  633. }
  634. func (q *swapQuerier) QueryNamespaceAnnotations(start, end time.Time) *source.Future[source.NamespaceAnnotationsResult] {
  635. return q.serve(source.QueryNamespaceAnnotations).QueryNamespaceAnnotations(start, end)
  636. }
  637. func (q *swapQuerier) QueryPodAnnotations(start, end time.Time) *source.Future[source.PodAnnotationsResult] {
  638. return q.serve(source.QueryPodAnnotations).QueryPodAnnotations(start, end)
  639. }
  640. func (q *swapQuerier) QueryNodeLabels(start, end time.Time) *source.Future[source.NodeLabelsResult] {
  641. return q.serve(source.QueryNodeLabels).QueryNodeLabels(start, end)
  642. }
  643. func (q *swapQuerier) QueryNamespaceLabels(start, end time.Time) *source.Future[source.NamespaceLabelsResult] {
  644. return q.serve(source.QueryNamespaceLabels).QueryNamespaceLabels(start, end)
  645. }
  646. func (q *swapQuerier) QueryPodLabels(start, end time.Time) *source.Future[source.PodLabelsResult] {
  647. return q.serve(source.QueryPodLabels).QueryPodLabels(start, end)
  648. }
  649. func (q *swapQuerier) QueryPodsWithDaemonSetOwner(start, end time.Time) *source.Future[source.PodsWithDaemonSetOwnerResult] {
  650. return q.serve(source.QueryPodsWithDaemonSetOwner).QueryPodsWithDaemonSetOwner(start, end)
  651. }
  652. func (q *swapQuerier) QueryPodsWithJobOwner(start, end time.Time) *source.Future[source.PodsWithJobOwnerResult] {
  653. return q.serve(source.QueryPodsWithJobOwner).QueryPodsWithJobOwner(start, end)
  654. }
  655. func (q *swapQuerier) QueryPodsWithReplicaSetOwner(start, end time.Time) *source.Future[source.PodsWithReplicaSetOwnerResult] {
  656. return q.serve(source.QueryPodsWithReplicaSetOwner).QueryPodsWithReplicaSetOwner(start, end)
  657. }
  658. func (q *swapQuerier) QueryReplicaSetsWithoutOwners(start, end time.Time) *source.Future[source.ReplicaSetsWithoutOwnersResult] {
  659. return q.serve(source.QueryReplicaSetsWithoutOwners).QueryReplicaSetsWithoutOwners(start, end)
  660. }
  661. func (q *swapQuerier) QueryReplicaSetsWithRollout(start, end time.Time) *source.Future[source.ReplicaSetsWithRolloutResult] {
  662. return q.serve(source.QueryReplicaSetsWithRollout).QueryReplicaSetsWithRollout(start, end)
  663. }
  664. func (q *swapQuerier) QueryResourceQuotaInfo(start, end time.Time) *source.Future[source.ResourceQuotaInfoResult] {
  665. return q.serve(source.QueryResourceQuotaInfo).QueryResourceQuotaInfo(start, end)
  666. }
  667. func (q *swapQuerier) QueryResourceQuotaUptime(start, end time.Time) *source.Future[source.UptimeResult] {
  668. return q.serve(source.QueryResourceQuotaUptime).QueryResourceQuotaUptime(start, end)
  669. }
  670. func (q *swapQuerier) QueryResourceQuotaSpecCPURequestAverage(start, end time.Time) *source.Future[source.ResourceResult] {
  671. return q.serve(source.QueryResourceQuotaSpecCPURequestAverage).QueryResourceQuotaSpecCPURequestAverage(start, end)
  672. }
  673. func (q *swapQuerier) QueryResourceQuotaSpecCPURequestMax(start, end time.Time) *source.Future[source.ResourceResult] {
  674. return q.serve(source.QueryResourceQuotaSpecCPURequestMax).QueryResourceQuotaSpecCPURequestMax(start, end)
  675. }
  676. func (q *swapQuerier) QueryResourceQuotaSpecRAMRequestAverage(start, end time.Time) *source.Future[source.ResourceResult] {
  677. return q.serve(source.QueryResourceQuotaSpecRAMRequestAverage).QueryResourceQuotaSpecRAMRequestAverage(start, end)
  678. }
  679. func (q *swapQuerier) QueryResourceQuotaSpecRAMRequestMax(start, end time.Time) *source.Future[source.ResourceResult] {
  680. return q.serve(source.QueryResourceQuotaSpecRAMRequestMax).QueryResourceQuotaSpecRAMRequestMax(start, end)
  681. }
  682. func (q *swapQuerier) QueryResourceQuotaSpecCPULimitAverage(start, end time.Time) *source.Future[source.ResourceResult] {
  683. return q.serve(source.QueryResourceQuotaSpecCPULimitAverage).QueryResourceQuotaSpecCPULimitAverage(start, end)
  684. }
  685. func (q *swapQuerier) QueryResourceQuotaSpecCPULimitMax(start, end time.Time) *source.Future[source.ResourceResult] {
  686. return q.serve(source.QueryResourceQuotaSpecCPULimitMax).QueryResourceQuotaSpecCPULimitMax(start, end)
  687. }
  688. func (q *swapQuerier) QueryResourceQuotaSpecRAMLimitAverage(start, end time.Time) *source.Future[source.ResourceResult] {
  689. return q.serve(source.QueryResourceQuotaSpecRAMLimitAverage).QueryResourceQuotaSpecRAMLimitAverage(start, end)
  690. }
  691. func (q *swapQuerier) QueryResourceQuotaSpecRAMLimitMax(start, end time.Time) *source.Future[source.ResourceResult] {
  692. return q.serve(source.QueryResourceQuotaSpecRAMLimitMax).QueryResourceQuotaSpecRAMLimitMax(start, end)
  693. }
  694. func (q *swapQuerier) QueryResourceQuotaStatusUsedCPURequestAverage(start, end time.Time) *source.Future[source.ResourceResult] {
  695. return q.serve(source.QueryResourceQuotaStatusUsedCPURequestAverage).QueryResourceQuotaStatusUsedCPURequestAverage(start, end)
  696. }
  697. func (q *swapQuerier) QueryResourceQuotaStatusUsedCPURequestMax(start, end time.Time) *source.Future[source.ResourceResult] {
  698. return q.serve(source.QueryResourceQuotaStatusUsedCPURequestMax).QueryResourceQuotaStatusUsedCPURequestMax(start, end)
  699. }
  700. func (q *swapQuerier) QueryResourceQuotaStatusUsedRAMRequestAverage(start, end time.Time) *source.Future[source.ResourceResult] {
  701. return q.serve(source.QueryResourceQuotaStatusUsedRAMRequestAverage).QueryResourceQuotaStatusUsedRAMRequestAverage(start, end)
  702. }
  703. func (q *swapQuerier) QueryResourceQuotaStatusUsedRAMRequestMax(start, end time.Time) *source.Future[source.ResourceResult] {
  704. return q.serve(source.QueryResourceQuotaStatusUsedRAMRequestMax).QueryResourceQuotaStatusUsedRAMRequestMax(start, end)
  705. }
  706. func (q *swapQuerier) QueryResourceQuotaStatusUsedCPULimitAverage(start, end time.Time) *source.Future[source.ResourceResult] {
  707. return q.serve(source.QueryResourceQuotaStatusUsedCPULimitAverage).QueryResourceQuotaStatusUsedCPULimitAverage(start, end)
  708. }
  709. func (q *swapQuerier) QueryResourceQuotaStatusUsedCPULimitMax(start, end time.Time) *source.Future[source.ResourceResult] {
  710. return q.serve(source.QueryResourceQuotaStatusUsedCPULimitMax).QueryResourceQuotaStatusUsedCPULimitMax(start, end)
  711. }
  712. func (q *swapQuerier) QueryResourceQuotaStatusUsedRAMLimitAverage(start, end time.Time) *source.Future[source.ResourceResult] {
  713. return q.serve(source.QueryResourceQuotaStatusUsedRAMLimitAverage).QueryResourceQuotaStatusUsedRAMLimitAverage(start, end)
  714. }
  715. func (q *swapQuerier) QueryResourceQuotaStatusUsedRAMLimitMax(start, end time.Time) *source.Future[source.ResourceResult] {
  716. return q.serve(source.QueryResourceQuotaStatusUsedRAMLimitMax).QueryResourceQuotaStatusUsedRAMLimitMax(start, end)
  717. }
  718. func (q *swapQuerier) QueryInferencePromptTokens(start, end time.Time) *source.Future[source.InferenceTokensResult] {
  719. return q.serve(source.QueryInferencePromptTokens).QueryInferencePromptTokens(start, end)
  720. }
  721. func (q *swapQuerier) QueryInferenceGenerationTokens(start, end time.Time) *source.Future[source.InferenceTokensResult] {
  722. return q.serve(source.QueryInferenceGenerationTokens).QueryInferenceGenerationTokens(start, end)
  723. }
  724. func (q *swapQuerier) QueryInferenceInputProcessingTime(start, end time.Time) *source.Future[source.InferenceProcessingTimeResult] {
  725. return q.serve(source.QueryInferenceInputProcessingTime).QueryInferenceInputProcessingTime(start, end)
  726. }
  727. func (q *swapQuerier) QueryInferenceOutputProcessingTime(start, end time.Time) *source.Future[source.InferenceProcessingTimeResult] {
  728. return q.serve(source.QueryInferenceOutputProcessingTime).QueryInferenceOutputProcessingTime(start, end)
  729. }
  730. func (q *swapQuerier) QueryInferenceCachedTokens(start, end time.Time) *source.Future[source.InferenceTokensResult] {
  731. return q.serve(source.QueryInferenceCachedTokens).QueryInferenceCachedTokens(start, end)
  732. }
  733. func (q *swapQuerier) QueryInferenceCacheConfig(t time.Time) *source.Future[source.InferenceCacheConfigResult] {
  734. return q.serve(source.QueryInferenceCacheConfig).QueryInferenceCacheConfig(t)
  735. }
  736. func (q *swapQuerier) QueryDataCoverage(limitDays int) (time.Time, time.Time, error) {
  737. return q.serve(source.QueryDataCoverage).QueryDataCoverage(limitDays)
  738. }
  739. // newSwapCostModel returns a CostModel over a swapQuerier that swaps from state A to state B after the
  740. // first query.
  741. func newSwapCostModel(t *testing.T, start, end time.Time) (*CostModel, *swapQuerier) {
  742. t.Helper()
  743. const cluster, node = "cluster-one", "node-1"
  744. stateA := swapTestSnapshot(cluster, node, []string{"pod-a"}, start, end)
  745. stateB := swapTestSnapshot(cluster, node, []string{"pod-a", "pod-b"}, start, end)
  746. querier := &swapQuerier{states: [2]source.MetricsQuerier{stateA, stateB}, flipAfter: 1}
  747. confMan := config.NewConfigFileManager(storage.NewFileStorage("../../"))
  748. customProvider := &provider.CSVProvider{
  749. CSVLocation: "../../configs/pricing_schema_pv.csv",
  750. CustomProvider: &provider.CustomProvider{
  751. Config: provider.NewProviderConfig(confMan, "../../configs/default.json"),
  752. },
  753. }
  754. require.NoError(t, customProvider.DownloadPricingData())
  755. return &CostModel{DataSource: &swapDataSource{querier: querier, resolution: time.Minute}, Provider: customProvider}, querier
  756. }
  757. // requireSingleState fails if the querier served queries from more than one state, or was not pinned
  758. // and released exactly once.
  759. func requireSingleState(t *testing.T, querier *swapQuerier) {
  760. t.Helper()
  761. states := map[int]int{}
  762. for _, s := range querier.servedQueries() {
  763. states[s.state]++
  764. }
  765. require.NotEmpty(t, states, "no queries were served")
  766. if len(states) > 1 {
  767. t.Errorf("E3 violated: queries served from %d states (A=%d, B=%d)", len(states), states[swapStateA], states[swapStateB])
  768. }
  769. requireAllPinned(t, querier)
  770. }
  771. func TestComputeAssets_ConsistentDataView(t *testing.T) {
  772. end := time.Now().UTC().Truncate(time.Hour)
  773. start := end.Add(-time.Hour)
  774. cm, querier := newSwapCostModel(t, start, end)
  775. _, err := cm.ComputeAssets(start, end)
  776. require.NoError(t, err)
  777. requireSingleState(t, querier)
  778. }
  779. func TestGetNetworkInsightSet_ConsistentDataView(t *testing.T) {
  780. end := time.Now().UTC().Truncate(time.Hour)
  781. start := end.Add(-time.Hour)
  782. cm, querier := newSwapCostModel(t, start, end)
  783. _, err := cm.GetNetworkInsightSet(start, end)
  784. require.NoError(t, err)
  785. requireSingleState(t, querier)
  786. }