mock.go 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037
  1. package opencost
  2. import (
  3. "fmt"
  4. "time"
  5. "github.com/opencost/opencost/core/pkg/model/kubemodel"
  6. )
  7. const gb = 1024 * 1024 * 1024
  8. const day = 24 * time.Hour
  9. var disk = PVKey{
  10. Cluster: "cluster1",
  11. Name: "pv1",
  12. }
  13. // NewMockUnitAllocation creates an *Allocation with all of its float64 values set to 1 and generic properties if not provided in arg
  14. func NewMockUnitAllocation(name string, start time.Time, resolution time.Duration, props *AllocationProperties) *Allocation {
  15. if name == "" {
  16. name = "cluster1/namespace1/pod1/container1"
  17. }
  18. properties := &AllocationProperties{}
  19. if props == nil {
  20. properties.Cluster = "cluster1"
  21. properties.Node = "node1"
  22. properties.Namespace = "namespace1"
  23. properties.ControllerKind = "deployment"
  24. properties.Controller = "deployment1"
  25. properties.Pod = "pod1"
  26. properties.Container = "container1"
  27. } else {
  28. properties = props
  29. }
  30. end := start.Add(resolution)
  31. alloc := &Allocation{
  32. Name: name,
  33. Properties: properties,
  34. Window: NewWindow(&start, &end).Clone(),
  35. Start: start,
  36. End: end,
  37. CPUCoreHours: 1,
  38. CPUCost: 1,
  39. CPUCoreRequestAverage: 1,
  40. CPUCoreUsageAverage: 1,
  41. GPUHours: 1,
  42. GPUCost: 1,
  43. NetworkCost: 1,
  44. LoadBalancerCost: 1,
  45. PVs: PVAllocations{
  46. disk: {
  47. ByteHours: 1,
  48. Cost: 1,
  49. },
  50. },
  51. RAMByteHours: 1,
  52. RAMCost: 1,
  53. RAMBytesRequestAverage: 1,
  54. RAMBytesUsageAverage: 1,
  55. RawAllocationOnly: &RawAllocationOnlyData{
  56. CPUCoreUsageMax: 1,
  57. RAMBytesUsageMax: 1,
  58. },
  59. ProportionalAssetResourceCosts: nil,
  60. }
  61. // If idle allocation, remove non-idle costs, but maintain total cost
  62. if alloc.IsIdle() {
  63. alloc.PVs = nil
  64. alloc.NetworkCost = 0.0
  65. alloc.LoadBalancerCost = 0.0
  66. alloc.CPUCoreHours += 1.0
  67. alloc.CPUCost += 1.0
  68. alloc.RAMByteHours += 1.0
  69. alloc.RAMCost += 1.0
  70. }
  71. return alloc
  72. }
  73. // GenerateMockAllocationSetClusterIdle creates generic allocation set which includes an idle set broken down by cluster
  74. func GenerateMockAllocationSetClusterIdle(start time.Time) *AllocationSet {
  75. // Cluster Idle allocations
  76. a1i := NewMockUnitAllocation(fmt.Sprintf("cluster1/%s", IdleSuffix), start, day, &AllocationProperties{
  77. Cluster: "cluster1",
  78. })
  79. a1i.CPUCost = 5.0
  80. a1i.RAMCost = 15.0
  81. a1i.GPUCost = 0.0
  82. a2i := NewMockUnitAllocation(fmt.Sprintf("cluster2/%s", IdleSuffix), start, day, &AllocationProperties{
  83. Cluster: "cluster2",
  84. })
  85. a2i.CPUCost = 5.0
  86. a2i.RAMCost = 5.0
  87. a2i.GPUCost = 0.0
  88. as := GenerateMockAllocationSet(start)
  89. as.Insert(a1i)
  90. as.Insert(a2i)
  91. return as
  92. }
  93. // GenerateMockAllocationSetNodeIdle creates generic allocation set which includes an idle set broken down by node
  94. func GenerateMockAllocationSetNodeIdle(start time.Time) *AllocationSet {
  95. // Node Idle allocations
  96. a11i := NewMockUnitAllocation(fmt.Sprintf("c1nodes/%s", IdleSuffix), start, day, &AllocationProperties{
  97. Cluster: "cluster1",
  98. Node: "c1nodes",
  99. ProviderID: "c1nodes",
  100. })
  101. a11i.CPUCost = 5.0
  102. a11i.RAMCost = 15.0
  103. a11i.GPUCost = 0.0
  104. a21i := NewMockUnitAllocation(fmt.Sprintf("node1/%s", IdleSuffix), start, day, &AllocationProperties{
  105. Cluster: "cluster2",
  106. Node: "node1",
  107. ProviderID: "node1",
  108. })
  109. a21i.CPUCost = 1.666667
  110. a21i.RAMCost = 1.666667
  111. a21i.GPUCost = 0.0
  112. a22i := NewMockUnitAllocation(fmt.Sprintf("node2/%s", IdleSuffix), start, day, &AllocationProperties{
  113. Cluster: "cluster2",
  114. Node: "node2",
  115. ProviderID: "node2",
  116. })
  117. a22i.CPUCost = 1.666667
  118. a22i.RAMCost = 1.666667
  119. a22i.GPUCost = 0.0
  120. a23i := NewMockUnitAllocation(fmt.Sprintf("node3/%s", IdleSuffix), start, day, &AllocationProperties{
  121. Cluster: "cluster2",
  122. Node: "node3",
  123. ProviderID: "node3",
  124. Namespace: "",
  125. })
  126. a23i.CPUCost = 1.666667
  127. a23i.RAMCost = 1.666667
  128. a23i.GPUCost = 0.0
  129. as := GenerateMockAllocationSet(start)
  130. as.Insert(a11i)
  131. as.Insert(a21i)
  132. as.Insert(a22i)
  133. as.Insert(a23i)
  134. return as
  135. }
  136. // GenerateMockAllocationSet creates generic allocation set without idle allocations
  137. func GenerateMockAllocationSet(start time.Time) *AllocationSet {
  138. // Active allocations
  139. a1111 := NewMockUnitAllocation("cluster1/namespace1/pod1/container1", start, day, &AllocationProperties{
  140. Cluster: "cluster1",
  141. Namespace: "namespace1",
  142. Pod: "pod1",
  143. Container: "container1",
  144. ProviderID: "c1nodes",
  145. Node: "c1nodes",
  146. })
  147. a1111.RAMCost = 11.00
  148. a1111.PVs = PVAllocations{
  149. PVKey{Cluster: "cluster1", Name: "pv-a1111"}: {
  150. ByteHours: 1,
  151. Cost: 1,
  152. },
  153. }
  154. a11abc2 := NewMockUnitAllocation("cluster1/namespace1/pod-abc/container2", start, day, &AllocationProperties{
  155. Cluster: "cluster1",
  156. Namespace: "namespace1",
  157. Pod: "pod-abc",
  158. Container: "container2",
  159. ProviderID: "c1nodes",
  160. Node: "c1nodes",
  161. })
  162. a11abc2.PVs = PVAllocations{
  163. PVKey{Cluster: "cluster1", Name: "pv-a11abc2"}: {
  164. ByteHours: 1,
  165. Cost: 1,
  166. },
  167. }
  168. a11def3 := NewMockUnitAllocation("cluster1/namespace1/pod-def/container3", start, day, &AllocationProperties{
  169. Cluster: "cluster1",
  170. Namespace: "namespace1",
  171. Pod: "pod-def",
  172. Container: "container3",
  173. ProviderID: "c1nodes",
  174. Node: "c1nodes",
  175. })
  176. a11def3.PVs = PVAllocations{
  177. PVKey{Cluster: "cluster1", Name: "pv-a11def3"}: {
  178. ByteHours: 1,
  179. Cost: 1,
  180. },
  181. }
  182. a12ghi4 := NewMockUnitAllocation("cluster1/namespace2/pod-ghi/container4", start, day, &AllocationProperties{
  183. Cluster: "cluster1",
  184. Namespace: "namespace2",
  185. Pod: "pod-ghi",
  186. Container: "container4",
  187. ProviderID: "c1nodes",
  188. Node: "c1nodes",
  189. })
  190. a12ghi4.PVs = PVAllocations{
  191. PVKey{Cluster: "cluster1", Name: "pv-a12ghi4"}: {
  192. ByteHours: 1,
  193. Cost: 1,
  194. },
  195. }
  196. a12ghi5 := NewMockUnitAllocation("cluster1/namespace2/pod-ghi/container5", start, day, &AllocationProperties{
  197. Cluster: "cluster1",
  198. Namespace: "namespace2",
  199. Pod: "pod-ghi",
  200. Container: "container5",
  201. ProviderID: "c1nodes",
  202. Node: "c1nodes",
  203. })
  204. a12ghi5.PVs = PVAllocations{
  205. PVKey{Cluster: "cluster1", Name: "pv-a12ghi5"}: {
  206. ByteHours: 1,
  207. Cost: 1,
  208. },
  209. }
  210. a12jkl6 := NewMockUnitAllocation("cluster1/namespace2/pod-jkl/container6", start, day, &AllocationProperties{
  211. Cluster: "cluster1",
  212. Namespace: "namespace2",
  213. Pod: "pod-jkl",
  214. Container: "container6",
  215. ProviderID: "c1nodes",
  216. Node: "c1nodes",
  217. })
  218. a12jkl6.PVs = PVAllocations{
  219. PVKey{Cluster: "cluster1", Name: "pv-a12jkl6"}: {
  220. ByteHours: 1,
  221. Cost: 1,
  222. },
  223. }
  224. a22mno4 := NewMockUnitAllocation("cluster2/namespace2/pod-mno/container4", start, day, &AllocationProperties{
  225. Cluster: "cluster2",
  226. Namespace: "namespace2",
  227. Pod: "pod-mno",
  228. Container: "container4",
  229. ProviderID: "node1",
  230. Node: "node1",
  231. })
  232. a22mno4.PVs = PVAllocations{
  233. PVKey{Cluster: "cluster2", Name: "pv-a22mno4"}: {
  234. ByteHours: 1,
  235. Cost: 1,
  236. },
  237. }
  238. a22mno5 := NewMockUnitAllocation("cluster2/namespace2/pod-mno/container5", start, day, &AllocationProperties{
  239. Cluster: "cluster2",
  240. Namespace: "namespace2",
  241. Pod: "pod-mno",
  242. Container: "container5",
  243. ProviderID: "node1",
  244. Node: "node1",
  245. })
  246. a22mno5.PVs = PVAllocations{
  247. PVKey{Cluster: "cluster2", Name: "pv-a22mno5"}: {
  248. ByteHours: 1,
  249. Cost: 1,
  250. },
  251. }
  252. a22pqr6 := NewMockUnitAllocation("cluster2/namespace2/pod-pqr/container6", start, day, &AllocationProperties{
  253. Cluster: "cluster2",
  254. Namespace: "namespace2",
  255. Pod: "pod-pqr",
  256. Container: "container6",
  257. ProviderID: "node2",
  258. Node: "node2",
  259. })
  260. a22pqr6.PVs = PVAllocations{
  261. PVKey{Cluster: "cluster2", Name: "pv-a22pqr6"}: {
  262. ByteHours: 1,
  263. Cost: 1,
  264. },
  265. }
  266. a23stu7 := NewMockUnitAllocation("cluster2/namespace3/pod-stu/container7", start, day, &AllocationProperties{
  267. Cluster: "cluster2",
  268. Namespace: "namespace3",
  269. Pod: "pod-stu",
  270. Container: "container7",
  271. ProviderID: "node2",
  272. Node: "node2",
  273. })
  274. a23stu7.PVs = PVAllocations{
  275. PVKey{Cluster: "cluster2", Name: "pv-a23stu7"}: {
  276. ByteHours: 1,
  277. Cost: 1,
  278. },
  279. }
  280. a23vwx8 := NewMockUnitAllocation("cluster2/namespace3/pod-vwx/container8", start, day, &AllocationProperties{
  281. Cluster: "cluster2",
  282. Namespace: "namespace3",
  283. Pod: "pod-vwx",
  284. Container: "container8",
  285. ProviderID: "node3",
  286. Node: "node3",
  287. })
  288. a23vwx8.PVs = PVAllocations{
  289. PVKey{Cluster: "cluster2", Name: "pv-a23vwx8"}: {
  290. ByteHours: 1,
  291. Cost: 1,
  292. },
  293. }
  294. a23vwx9 := NewMockUnitAllocation("cluster2/namespace3/pod-vwx/container9", start, day, &AllocationProperties{
  295. Cluster: "cluster2",
  296. Namespace: "namespace3",
  297. Pod: "pod-vwx",
  298. Container: "container9",
  299. ProviderID: "node3",
  300. Node: "node3",
  301. })
  302. a23vwx9.PVs = PVAllocations{
  303. PVKey{Cluster: "cluster2", Name: "pv-a23vwx9"}: {
  304. ByteHours: 1,
  305. Cost: 1,
  306. },
  307. }
  308. // Controllers
  309. a11abc2.Properties.ControllerKind = "deployment"
  310. a11abc2.Properties.Controller = "deployment1"
  311. a11def3.Properties.ControllerKind = "deployment"
  312. a11def3.Properties.Controller = "deployment1"
  313. a12ghi4.Properties.ControllerKind = "deployment"
  314. a12ghi4.Properties.Controller = "deployment2"
  315. a12ghi5.Properties.ControllerKind = "deployment"
  316. a12ghi5.Properties.Controller = "deployment2"
  317. a22mno4.Properties.ControllerKind = "deployment"
  318. a22mno4.Properties.Controller = "deployment2"
  319. a22mno5.Properties.ControllerKind = "deployment"
  320. a22mno5.Properties.Controller = "deployment2"
  321. a23stu7.Properties.ControllerKind = "deployment"
  322. a23stu7.Properties.Controller = "deployment3"
  323. a12jkl6.Properties.ControllerKind = "daemonset"
  324. a12jkl6.Properties.Controller = "daemonset1"
  325. a22pqr6.Properties.ControllerKind = "daemonset"
  326. a22pqr6.Properties.Controller = "daemonset1"
  327. a23vwx8.Properties.ControllerKind = "statefulset"
  328. a23vwx8.Properties.Controller = "statefulset1"
  329. a23vwx9.Properties.ControllerKind = "statefulset"
  330. a23vwx9.Properties.Controller = "statefulset1"
  331. // Labels
  332. a1111.Properties.Labels = map[string]string{"app": "app1", "env": "env1"}
  333. a12ghi4.Properties.Labels = map[string]string{"app": "app2", "env": "env2"}
  334. a12ghi5.Properties.Labels = map[string]string{"app": "app2", "env": "env2"}
  335. a22mno4.Properties.Labels = map[string]string{"app": "app2"}
  336. a22mno5.Properties.Labels = map[string]string{"app": "app2"}
  337. //Annotations
  338. a23stu7.Properties.Annotations = map[string]string{"team": "team1"}
  339. a23vwx8.Properties.Annotations = map[string]string{"team": "team2"}
  340. a23vwx9.Properties.Annotations = map[string]string{"team": "team1"}
  341. // Services
  342. a12jkl6.Properties.Services = []string{"service1"}
  343. a22pqr6.Properties.Services = []string{"service1"}
  344. return NewAllocationSet(start, start.Add(day),
  345. // cluster 1, namespace1
  346. a1111, a11abc2, a11def3,
  347. // cluster 1, namespace 2
  348. a12ghi4, a12ghi5, a12jkl6,
  349. // cluster 2, namespace 2
  350. a22mno4, a22mno5, a22pqr6,
  351. // cluster 2, namespace 3
  352. a23stu7, a23vwx8, a23vwx9,
  353. )
  354. }
  355. // GenerateMockAllocationSetWithAssetProperties with no idle and connections to Assets in properties
  356. func GenerateMockAllocationSetWithAssetProperties(start time.Time) *AllocationSet {
  357. as := GenerateMockAllocationSet(start)
  358. disk1 := PVKey{
  359. Cluster: "cluster2",
  360. Name: "disk1",
  361. }
  362. disk2 := PVKey{
  363. Cluster: "cluster2",
  364. Name: "disk2",
  365. }
  366. for _, a := range as.Allocations {
  367. // add reconcilable pvs to pod-mno
  368. if a.Properties.Pod == "pod-mno" {
  369. a.PVs = a.PVs.Add(PVAllocations{
  370. disk1: {
  371. Cost: 2.5,
  372. ByteHours: 2.5 * gb,
  373. },
  374. disk2: {
  375. Cost: 5,
  376. ByteHours: 5 * gb,
  377. },
  378. })
  379. }
  380. // add loadBalancer service to allocations
  381. if a.Name == "cluster2/namespace2/pod-mno/container4" {
  382. a.Properties.Services = append(a.Properties.Services, "loadBalancer1")
  383. }
  384. if a.Name == "cluster2/namespace2/pod-mno/container5" {
  385. a.Properties.Services = append(a.Properties.Services, "loadBalancer2")
  386. }
  387. if a.Name == "cluster2/namespace2/pod-pqr/container6" {
  388. a.Properties.Services = append(a.Properties.Services, "loadBalancer1")
  389. a.Properties.Services = append(a.Properties.Services, "loadBalancer2")
  390. }
  391. }
  392. return as
  393. }
  394. // GenerateMockAssetSets creates generic AssetSets
  395. func GenerateMockAssetSets(start, end time.Time) []*AssetSet {
  396. var assetSets []*AssetSet
  397. // Create an AssetSet representing cluster costs for two clusters (cluster1
  398. // and cluster2). Include Nodes and Disks for both, even though only
  399. // Nodes will be counted. Whereas in practice, Assets should be aggregated
  400. // by type, here we will provide multiple Nodes for one of the clusters to
  401. // make sure the function still holds.
  402. // NOTE: we're re-using GenerateMockAllocationSet so this has to line up with
  403. // the allocated node costs from that function. See table above.
  404. // | Hierarchy | Cost | CPU | RAM | GPU | Adjustment |
  405. // +-----------------------------------------+------+------+------+------+------------+
  406. // cluster1:
  407. // nodes 100.00 55.00 44.00 11.00 -10.00
  408. // +-----------------------------------------+------+------+------+------+------------+
  409. // cluster1 subtotal (adjusted) 100.00 50.00 40.00 10.00 0.00
  410. // +-----------------------------------------+------+------+------+------+------------+
  411. // cluster1 allocated 48.00 6.00 16.00 6.00 0.00
  412. // +-----------------------------------------+------+------+------+------+------------+
  413. // cluster1 idle 72.00 44.00 24.00 4.00 0.00
  414. // +-----------------------------------------+------+------+------+------+------------+
  415. // cluster2:
  416. // node1 35.00 20.00 15.00 0.00 0.00
  417. // node2 35.00 20.00 15.00 0.00 0.00
  418. // node3 30.00 10.00 10.00 10.00 0.00
  419. // (disks should not matter for idle)
  420. // +-----------------------------------------+------+------+------+------+------------+
  421. // cluster2 subtotal 100.00 50.00 40.00 10.00 0.00
  422. // +-----------------------------------------+------+------+------+------+------------+
  423. // cluster2 allocated 28.00 6.00 6.00 6.00 0.00
  424. // +-----------------------------------------+------+------+------+------+------------+
  425. // cluster2 idle 82.00 44.00 34.00 4.00 0.00
  426. // +-----------------------------------------+------+------+------+------+------------+
  427. cluster1Nodes := NewNode("c1nodes", "cluster1", "c1nodes", start, end, NewWindow(&start, &end))
  428. cluster1Nodes.CPUCost = 55.0
  429. cluster1Nodes.RAMCost = 44.0
  430. cluster1Nodes.GPUCost = 11.0
  431. cluster1Nodes.Adjustment = -10.00
  432. cluster1Nodes.CPUCoreHours = 8
  433. cluster1Nodes.RAMByteHours = 6
  434. cluster1Nodes.GPUHours = 24
  435. cluster2Node1 := NewNode("node1", "cluster2", "node1", start, end, NewWindow(&start, &end))
  436. cluster2Node1.CPUCost = 20.0
  437. cluster2Node1.RAMCost = 15.0
  438. cluster2Node1.GPUCost = 0.0
  439. cluster2Node1.CPUCoreHours = 4
  440. cluster2Node1.RAMByteHours = 3
  441. cluster2Node1.GPUHours = 0
  442. cluster2Node2 := NewNode("node2", "cluster2", "node2", start, end, NewWindow(&start, &end))
  443. cluster2Node2.CPUCost = 20.0
  444. cluster2Node2.RAMCost = 15.0
  445. cluster2Node2.GPUCost = 0.0
  446. cluster2Node2.CPUCoreHours = 3
  447. cluster2Node2.RAMByteHours = 2
  448. cluster2Node2.GPUHours = 0
  449. cluster2Node3 := NewNode("node3", "cluster2", "node3", start, end, NewWindow(&start, &end))
  450. cluster2Node3.CPUCost = 10.0
  451. cluster2Node3.RAMCost = 10.0
  452. cluster2Node3.GPUCost = 10.0
  453. cluster2Node3.CPUCoreHours = 2
  454. cluster2Node3.RAMByteHours = 2
  455. cluster2Node3.GPUHours = 24
  456. // Add PVs
  457. cluster2Disk1 := NewDisk("disk1", "cluster2", "disk1", start, end, NewWindow(&start, &end))
  458. cluster2Disk1.Cost = 5.0
  459. cluster2Disk1.Adjustment = 1.0
  460. cluster2Disk1.ByteHours = 5 * gb
  461. cluster2Disk2 := NewDisk("disk2", "cluster2", "disk2", start, end, NewWindow(&start, &end))
  462. cluster2Disk2.Cost = 10.0
  463. cluster2Disk2.Adjustment = 3.0
  464. cluster2Disk2.ByteHours = 10 * gb
  465. cluster2Node1Disk := NewDisk("node1", "cluster2", "node1", start, end, NewWindow(&start, &end))
  466. cluster2Node1Disk.Cost = 1.0
  467. cluster2Node1Disk.ByteHours = 5 * gb
  468. // Add Attached Disks
  469. cluster2Node2Disk := NewDisk("node2", "cluster2", "node2", start, end, NewWindow(&start, &end))
  470. cluster2Node2Disk.Cost = 2.0
  471. cluster2Node2Disk.ByteHours = 5 * gb
  472. cluster2Node3Disk := NewDisk("node3", "cluster2", "node3", start, end, NewWindow(&start, &end))
  473. cluster2Node3Disk.Cost = 3.0
  474. cluster2Node3Disk.ByteHours = 5 * gb
  475. // Add Cluster Management
  476. cluster1ClusterManagement := NewClusterManagement("", "cluster1", NewWindow(&start, &end))
  477. cluster1ClusterManagement.Cost = 2.0
  478. cluster2ClusterManagement := NewClusterManagement("", "cluster2", NewWindow(&start, &end))
  479. cluster2ClusterManagement.Cost = 2.0
  480. // Add Networks
  481. c1Network := NewNetwork("", "cluster1", "c1nodes", start, end, NewWindow(&start, &end))
  482. c1Network.Cost = 3.0
  483. node1Network := NewNetwork("node1", "cluster2", "node1", start, end, NewWindow(&start, &end))
  484. node1Network.Cost = 4.0
  485. node2Network := NewNetwork("node2", "cluster2", "node2", start, end, NewWindow(&start, &end))
  486. node2Network.Cost = 5.0
  487. node3Network := NewNetwork("node3", "cluster2", "node3", start, end, NewWindow(&start, &end))
  488. node3Network.Cost = 2.0
  489. // Add LoadBalancers
  490. cluster2LoadBalancer1 := NewLoadBalancer("namespace2/loadBalancer1", "cluster2", "lb1", start, end, NewWindow(&start, &end), false, "127.0.0.1")
  491. cluster2LoadBalancer1.Cost = 10.0
  492. cluster2LoadBalancer2 := NewLoadBalancer("namespace2/loadBalancer2", "cluster2", "lb2", start, end, NewWindow(&start, &end), false, "127.0.0.1")
  493. cluster2LoadBalancer2.Cost = 15.0
  494. assetSet1 := NewAssetSet(start, end, cluster1Nodes, cluster2Node1, cluster2Node2, cluster2Node3, cluster2Disk1,
  495. cluster2Disk2, cluster2Node1Disk, cluster2Node2Disk, cluster2Node3Disk, cluster1ClusterManagement,
  496. cluster2ClusterManagement, c1Network, node1Network, node2Network, node3Network, cluster2LoadBalancer1, cluster2LoadBalancer2)
  497. assetSets = append(assetSets, assetSet1)
  498. // NOTE: we're re-using GenerateMockAllocationSet so this has to line up with
  499. // the allocated node costs from that function. See table above.
  500. // | Hierarchy | Cost | CPU | RAM | GPU | Adjustment |
  501. // +-----------------------------------------+------+------+------+------+------------+
  502. // cluster1:
  503. // nodes 100.00 5.00 4.00 1.00 90.00
  504. // +-----------------------------------------+------+------+------+------+------------+
  505. // cluster1 subtotal (adjusted) 100.00 50.00 40.00 10.00 0.00
  506. // +-----------------------------------------+------+------+------+------+------------+
  507. // cluster1 allocated 48.00 6.00 16.00 6.00 0.00
  508. // +-----------------------------------------+------+------+------+------+------------+
  509. // cluster1 idle 72.00 44.00 24.00 4.00 0.00
  510. // +-----------------------------------------+------+------+------+------+------------+
  511. // cluster2:
  512. // node1 35.00 20.00 15.00 0.00 0.00
  513. // node2 35.00 20.00 15.00 0.00 0.00
  514. // node3 30.00 10.00 10.00 10.00 0.00
  515. // (disks should not matter for idle)
  516. // +-----------------------------------------+------+------+------+------+------------+
  517. // cluster2 subtotal 100.00 50.00 40.00 10.00 0.00
  518. // +-----------------------------------------+------+------+------+------+------------+
  519. // cluster2 allocated 28.00 6.00 6.00 6.00 0.00
  520. // +-----------------------------------------+------+------+------+------+------------+
  521. // cluster2 idle 82.00 44.00 34.00 4.00 0.00
  522. // +-----------------------------------------+------+------+------+------+------------+
  523. cluster1Nodes = NewNode("", "cluster1", "c1nodes", start, end, NewWindow(&start, &end))
  524. cluster1Nodes.CPUCost = 5.0
  525. cluster1Nodes.RAMCost = 4.0
  526. cluster1Nodes.GPUCost = 1.0
  527. cluster1Nodes.Adjustment = 90.00
  528. cluster1Nodes.CPUCoreHours = 8
  529. cluster1Nodes.RAMByteHours = 6
  530. cluster1Nodes.GPUHours = 24
  531. cluster2Node1 = NewNode("node1", "cluster2", "node1", start, end, NewWindow(&start, &end))
  532. cluster2Node1.CPUCost = 20.0
  533. cluster2Node1.RAMCost = 15.0
  534. cluster2Node1.GPUCost = 0.0
  535. cluster2Node1.CPUCoreHours = 4
  536. cluster2Node1.RAMByteHours = 3
  537. cluster2Node1.GPUHours = 0
  538. cluster2Node2 = NewNode("node2", "cluster2", "node2", start, end, NewWindow(&start, &end))
  539. cluster2Node2.CPUCost = 20.0
  540. cluster2Node2.RAMCost = 15.0
  541. cluster2Node2.GPUCost = 0.0
  542. cluster2Node2.CPUCoreHours = 3
  543. cluster2Node2.RAMByteHours = 2
  544. cluster2Node2.GPUHours = 0
  545. cluster2Node3 = NewNode("node3", "cluster2", "node3", start, end, NewWindow(&start, &end))
  546. cluster2Node3.CPUCost = 10.0
  547. cluster2Node3.RAMCost = 10.0
  548. cluster2Node3.GPUCost = 10.0
  549. cluster2Node3.CPUCoreHours = 2
  550. cluster2Node3.RAMByteHours = 2
  551. cluster2Node3.GPUHours = 24
  552. // Add PVs
  553. cluster2Disk1 = NewDisk("disk1", "cluster2", "disk1", start, end, NewWindow(&start, &end))
  554. cluster2Disk1.Cost = 5.0
  555. cluster2Disk1.Adjustment = 1.0
  556. cluster2Disk1.ByteHours = 5 * gb
  557. cluster2Disk2 = NewDisk("disk2", "cluster2", "disk2", start, end, NewWindow(&start, &end))
  558. cluster2Disk2.Cost = 12.0
  559. cluster2Disk2.Adjustment = 4.0
  560. cluster2Disk2.ByteHours = 20 * gb
  561. assetSet2 := NewAssetSet(start, end, cluster1Nodes, cluster2Node1, cluster2Node2, cluster2Node3, cluster2Disk1,
  562. cluster2Disk2, cluster2Node1Disk, cluster2Node2Disk, cluster2Node3Disk, cluster1ClusterManagement,
  563. cluster2ClusterManagement, c1Network, node1Network, node2Network, node3Network, cluster2LoadBalancer1, cluster2LoadBalancer2)
  564. assetSets = append(assetSets, assetSet2)
  565. return assetSets
  566. }
  567. // GenerateMockAssetSet generates the following topology:
  568. //
  569. // | Asset | Cost | Adj |
  570. // +------------------------------+------+------+
  571. //
  572. // cluster1:
  573. // node1: 6.00 1.00
  574. // node2: 4.00 1.50
  575. // node3: 7.00 -0.50
  576. // disk1: 2.50 0.00
  577. // disk2: 1.50 0.00
  578. // clusterManagement1: 3.00 0.00
  579. //
  580. // +------------------------------+------+------+
  581. //
  582. // cluster1 subtotal 24.00 2.00
  583. //
  584. // +------------------------------+------+------+
  585. //
  586. // cluster2:
  587. // node4: 12.00 -1.00
  588. // disk3: 2.50 0.00
  589. // disk4: 1.50 0.00
  590. // clusterManagement2: 0.00 0.00
  591. //
  592. // +------------------------------+------+------+
  593. //
  594. // cluster2 subtotal 16.00 -1.00
  595. //
  596. // +------------------------------+------+------+
  597. //
  598. // cluster3:
  599. // node5: 17.00 2.00
  600. //
  601. // +------------------------------+------+------+
  602. //
  603. // cluster3 subtotal 17.00 2.00
  604. //
  605. // +------------------------------+------+------+
  606. //
  607. // total 57.00 3.00
  608. //
  609. // +------------------------------+------+------+
  610. func GenerateMockAssetSet(start time.Time, duration time.Duration) *AssetSet {
  611. end := start.Add(duration)
  612. window := NewWindow(&start, &end)
  613. hours := window.Duration().Hours()
  614. node1 := NewNode("node1", "cluster1", "gcp-node1", *window.Clone().start, *window.Clone().end, window.Clone())
  615. node1.CPUCost = 4.0
  616. node1.RAMCost = 4.0
  617. node1.GPUCost = 2.0
  618. node1.Discount = 0.5
  619. node1.CPUCoreHours = 2.0 * hours
  620. node1.RAMByteHours = 4.0 * gb * hours
  621. node1.GPUHours = 1.0 * hours
  622. node1.SetAdjustment(1.0)
  623. node1.SetLabels(map[string]string{"test": "test"})
  624. node2 := NewNode("node2", "cluster1", "gcp-node2", *window.Clone().start, *window.Clone().end, window.Clone())
  625. node2.CPUCost = 4.0
  626. node2.RAMCost = 4.0
  627. node2.GPUCost = 0.0
  628. node2.Discount = 0.5
  629. node2.CPUCoreHours = 2.0 * hours
  630. node2.RAMByteHours = 4.0 * gb * hours
  631. node2.GPUHours = 0.0 * hours
  632. node2.SetAdjustment(1.5)
  633. node3 := NewNode("node3", "cluster1", "gcp-node3", *window.Clone().start, *window.Clone().end, window.Clone())
  634. node3.CPUCost = 4.0
  635. node3.RAMCost = 4.0
  636. node3.GPUCost = 3.0
  637. node3.Discount = 0.5
  638. node3.CPUCoreHours = 2.0 * hours
  639. node3.RAMByteHours = 4.0 * gb * hours
  640. node3.GPUHours = 2.0 * hours
  641. node3.SetAdjustment(-0.5)
  642. node4 := NewNode("node4", "cluster2", "gcp-node4", *window.Clone().start, *window.Clone().end, window.Clone())
  643. node4.CPUCost = 10.0
  644. node4.RAMCost = 6.0
  645. node4.GPUCost = 0.0
  646. node4.Discount = 0.25
  647. node4.CPUCoreHours = 4.0 * hours
  648. node4.RAMByteHours = 12.0 * gb * hours
  649. node4.GPUHours = 0.0 * hours
  650. node4.SetAdjustment(-1.0)
  651. node5 := NewNode("node5", "cluster3", "aws-node5", *window.Clone().start, *window.Clone().end, window.Clone())
  652. node5.CPUCost = 10.0
  653. node5.RAMCost = 7.0
  654. node5.GPUCost = 0.0
  655. node5.Discount = 0.0
  656. node5.CPUCoreHours = 8.0 * hours
  657. node5.RAMByteHours = 24.0 * gb * hours
  658. node5.GPUHours = 0.0 * hours
  659. node5.SetAdjustment(2.0)
  660. disk1 := NewDisk("disk1", "cluster1", "gcp-disk1", *window.Clone().start, *window.Clone().end, window.Clone())
  661. disk1.Cost = 2.5
  662. disk1.ByteHours = 100 * gb * hours
  663. disk2 := NewDisk("disk2", "cluster1", "gcp-disk2", *window.Clone().start, *window.Clone().end, window.Clone())
  664. disk2.Cost = 1.5
  665. disk2.ByteHours = 60 * gb * hours
  666. disk3 := NewDisk("disk3", "cluster2", "gcp-disk3", *window.Clone().start, *window.Clone().end, window.Clone())
  667. disk3.Cost = 2.5
  668. disk3.ByteHours = 100 * gb * hours
  669. disk4 := NewDisk("disk4", "cluster2", "gcp-disk4", *window.Clone().start, *window.Clone().end, window.Clone())
  670. disk4.Cost = 1.5
  671. disk4.ByteHours = 100 * gb * hours
  672. cm1 := NewClusterManagement(GCPProvider, "cluster1", window.Clone())
  673. cm1.Cost = 3.0
  674. cm2 := NewClusterManagement(GCPProvider, "cluster2", window.Clone())
  675. cm2.Cost = 0.0
  676. return NewAssetSet(
  677. start, end,
  678. // cluster 1
  679. node1, node2, node3, disk1, disk2, cm1,
  680. // cluster 2
  681. node4, disk3, disk4, cm2,
  682. // cluster 3
  683. node5,
  684. )
  685. }
  686. // NewMockUnitSummaryAllocation creates an *SummaryAllocation with all of its float64 values set to 1 and generic properties if not provided in arg
  687. func NewMockUnitSummaryAllocation(name string, start time.Time, resolution time.Duration, props *AllocationProperties) *SummaryAllocation {
  688. if name == "" {
  689. name = "cluster1/namespace1/pod1/container1"
  690. }
  691. properties := &AllocationProperties{}
  692. if props == nil {
  693. properties.Cluster = "cluster1"
  694. properties.Node = "node1"
  695. properties.Namespace = "namespace1"
  696. properties.ControllerKind = "deployment"
  697. properties.Controller = "deployment1"
  698. properties.Pod = "pod1"
  699. properties.Container = "container1"
  700. } else {
  701. properties = props
  702. }
  703. end := start.Add(resolution)
  704. alloc := &SummaryAllocation{
  705. Name: name,
  706. Properties: properties,
  707. Start: start,
  708. End: end,
  709. CPUCost: 1,
  710. CPUCoreRequestAverage: 1,
  711. CPUCoreUsageAverage: 1,
  712. GPUCost: 1,
  713. NetworkCost: 1,
  714. LoadBalancerCost: 1,
  715. RAMCost: 1,
  716. RAMBytesRequestAverage: 1,
  717. RAMBytesUsageAverage: 1,
  718. }
  719. // If idle allocation, remove non-idle costs, but maintain total cost
  720. if alloc.IsIdle() {
  721. alloc.NetworkCost = 0.0
  722. alloc.LoadBalancerCost = 0.0
  723. alloc.CPUCost += 1.0
  724. alloc.RAMCost += 1.0
  725. }
  726. return alloc
  727. }
  728. // NewMockUnitSummaryAllocationSet creates an *SummaryAllocationSet
  729. func NewMockUnitSummaryAllocationSet(start time.Time, resolution time.Duration) *SummaryAllocationSet {
  730. end := start.Add(resolution)
  731. sas := &SummaryAllocationSet{
  732. Window: NewWindow(&start, &end),
  733. }
  734. return sas
  735. }
  736. const (
  737. mockCloudService1 = "MockCloudService1"
  738. mockCloudService2 = "MockCloudService2"
  739. mockCloudService3 = "MockCloudService3"
  740. mockCloudServiceName = "MockCloudService"
  741. )
  742. type MockNetworkInsightImportantKeys struct {
  743. Cluster string
  744. Namespace string
  745. Controller string
  746. Pod string
  747. Node string
  748. Labels map[string]string
  749. Region string
  750. Zone string
  751. }
  752. func createMockNetworkDetail(cost, bytes float64, endPoint string, trafficDirection NetworkTrafficDirection, trafficType NetworkTrafficType) (*NetworkDetail, error) {
  753. return &NetworkDetail{
  754. Cost: cost,
  755. Bytes: bytes,
  756. EndPoint: endPoint,
  757. TrafficDirection: trafficDirection,
  758. TrafficType: trafficType,
  759. }, nil
  760. }
  761. func createMockNetworkInsight(mockInsight MockNetworkInsightImportantKeys, detailsSet NetworkDetailsSet) *NetworkInsight {
  762. // Ingress isnt charges at the moment
  763. internetCost := detailsSet.GetTotalInternetCost()
  764. crossZoneCost := detailsSet.GetCrossZoneCost()
  765. crossRegionCost := detailsSet.GetCrossRegionCost()
  766. totalCost := internetCost + crossZoneCost + crossRegionCost
  767. return NewNetworkInsight(
  768. mockInsight.Cluster, mockInsight.Namespace, mockInsight.Controller,
  769. mockInsight.Pod, mockInsight.Node, mockInsight.Labels, mockInsight.Region,
  770. mockInsight.Zone, totalCost, crossZoneCost, crossRegionCost, internetCost, detailsSet)
  771. }
  772. func GenerateMockNetworkInsightSet(start time.Time, end time.Time) *NetworkInsightSet {
  773. mockInsight1 := MockNetworkInsightImportantKeys{
  774. Cluster: "mockCluster1",
  775. Namespace: "mockNamespace1",
  776. Controller: "",
  777. Pod: "mockPod1",
  778. Node: "",
  779. Labels: map[string]string{},
  780. Region: "",
  781. Zone: "",
  782. }
  783. mockInsight2 := MockNetworkInsightImportantKeys{
  784. Cluster: "mockCluster1",
  785. Namespace: "mockNamespace2",
  786. Controller: "",
  787. Pod: "mockPod2",
  788. Node: "",
  789. Labels: map[string]string{},
  790. Region: "",
  791. Zone: "",
  792. }
  793. mcs1inIngress, _ := createMockNetworkDetail(0, 200000, mockCloudService1, NetworkTrafficDirectionIngress, NetworkTrafficTypeInternet)
  794. mcs2inIngress, _ := createMockNetworkDetail(0, 400000, mockCloudService2, NetworkTrafficDirectionIngress, NetworkTrafficTypeInternet)
  795. mcs3inIngress, _ := createMockNetworkDetail(0, 800000, mockCloudService2, NetworkTrafficDirectionIngress, NetworkTrafficTypeInternet)
  796. mcs1inEgress, _ := createMockNetworkDetail(0.16, 300000, mockCloudService1, NetworkTrafficDirectionEgress, NetworkTrafficTypeInternet)
  797. mcs2inEgress, _ := createMockNetworkDetail(0.24, 300000, mockCloudService2, NetworkTrafficDirectionEgress, NetworkTrafficTypeInternet)
  798. mcs3inEgress, _ := createMockNetworkDetail(0.35, 300000, mockCloudService3, NetworkTrafficDirectionEgress, NetworkTrafficTypeInternet)
  799. set1 := make(NetworkDetailsSet, 0)
  800. set1[mcs1inIngress.Key()] = mcs1inIngress
  801. set1[mcs2inIngress.Key()] = mcs2inIngress
  802. set1[mcs3inIngress.Key()] = mcs3inIngress
  803. set1[mcs1inEgress.Key()] = mcs1inEgress
  804. set1[mcs2inEgress.Key()] = mcs2inEgress
  805. set1[mcs3inEgress.Key()] = mcs3inEgress
  806. set2 := make(NetworkDetailsSet, 0)
  807. set2[mcs1inIngress.Key()] = mcs1inIngress.Clone()
  808. set2[mcs2inIngress.Key()] = mcs2inIngress.Clone()
  809. set2[mcs3inIngress.Key()] = mcs3inIngress.Clone()
  810. set2[mcs1inEgress.Key()] = mcs1inEgress.Clone()
  811. set2[mcs2inEgress.Key()] = mcs2inEgress.Clone()
  812. set2[mcs3inEgress.Key()] = mcs3inEgress.Clone()
  813. ni1 := createMockNetworkInsight(mockInsight1, set1)
  814. ni2 := createMockNetworkInsight(mockInsight1, set2)
  815. ni3 := createMockNetworkInsight(mockInsight2, set1.Clone())
  816. nis := &NetworkInsightSet{
  817. NetworkInsights: make(map[string]*NetworkInsight, 0),
  818. Window: NewClosedWindow(start, end),
  819. }
  820. nis.Insert(ni1, []NetworkInsightProperty{NetworkInsightsPod})
  821. nis.Insert(ni2, []NetworkInsightProperty{NetworkInsightsPod})
  822. nis.Insert(ni3, []NetworkInsightProperty{NetworkInsightsPod})
  823. return nis
  824. }
  825. func GenerateMockCloudCostSet(start, end time.Time, provider, integration string) *CloudCostSet {
  826. ccs := NewCloudCostSet(start, end)
  827. ccs.Integration = integration
  828. ccs.Insert(&CloudCost{
  829. Window: ccs.Window,
  830. Properties: &CloudCostProperties{
  831. Provider: provider,
  832. AccountID: "account1",
  833. InvoiceEntityID: "invoiceEntity1",
  834. Service: provider + "-storage",
  835. Category: StorageCategory,
  836. Labels: CloudCostLabels{
  837. "label1": "value1",
  838. "label2": "value2",
  839. "label3": "value3",
  840. },
  841. ProviderID: "id1",
  842. },
  843. ListCost: CostMetric{
  844. Cost: 100,
  845. KubernetesPercent: 0,
  846. },
  847. NetCost: CostMetric{
  848. Cost: 100,
  849. KubernetesPercent: 0,
  850. },
  851. })
  852. ccs.Insert(&CloudCost{
  853. Window: ccs.Window,
  854. Properties: &CloudCostProperties{
  855. Provider: provider,
  856. AccountID: "account1",
  857. InvoiceEntityID: "invoiceEntity1",
  858. Service: provider + "-compute",
  859. Category: ComputeCategory,
  860. Labels: CloudCostLabels{
  861. "label1": "value1",
  862. "label2": "value2",
  863. "label3": "value3",
  864. },
  865. ProviderID: "id2",
  866. },
  867. ListCost: CostMetric{
  868. Cost: 2000,
  869. KubernetesPercent: 1,
  870. },
  871. NetCost: CostMetric{
  872. Cost: 1800,
  873. KubernetesPercent: 1,
  874. },
  875. })
  876. ccs.Insert(&CloudCost{
  877. Window: ccs.Window,
  878. Properties: &CloudCostProperties{
  879. Provider: provider,
  880. AccountID: "account2",
  881. InvoiceEntityID: "invoiceEntity2",
  882. Service: provider + "-compute",
  883. Category: ComputeCategory,
  884. Labels: CloudCostLabels{
  885. "label1": "value1",
  886. "label2": "value2",
  887. "label3": "value3",
  888. },
  889. ProviderID: "id3",
  890. },
  891. ListCost: CostMetric{
  892. Cost: 8000,
  893. KubernetesPercent: 1,
  894. },
  895. NetCost: CostMetric{
  896. Cost: 8000,
  897. KubernetesPercent: 1,
  898. },
  899. })
  900. return ccs
  901. }
  902. // GenerateMockKubeModelSet creates generic KubeModel set
  903. func GenerateMockKubeModelSet(start, end time.Time) *kubemodel.KubeModelSet {
  904. kms := kubemodel.NewKubeModelSet(start, end)
  905. kms.Cluster = &kubemodel.Cluster{
  906. UID: "clusterUID",
  907. Name: "cluster",
  908. }
  909. kms.RegisterNamespace("namespace-1", "namespace-1")
  910. kms.RegisterNamespace("namespace-2", "namespace-2")
  911. kms.RegisterResourceQuota("resourcequota-1", "resourcequota-1", "namespace-1")
  912. kms.RegisterResourceQuota("resourcequota-2", "resourcequota-2", "namespace-1")
  913. kms.RegisterResourceQuota("resourcequota-3", "resourcequota-3", "namespace-2")
  914. kms.RegisterResourceQuota("resourcequota-4", "resourcequota-4", "namespace-2")
  915. return kms
  916. }