| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037 |
- package opencost
- import (
- "fmt"
- "time"
- "github.com/opencost/opencost/core/pkg/model/kubemodel"
- )
- const gb = 1024 * 1024 * 1024
- const day = 24 * time.Hour
- var disk = PVKey{
- Cluster: "cluster1",
- Name: "pv1",
- }
- // NewMockUnitAllocation creates an *Allocation with all of its float64 values set to 1 and generic properties if not provided in arg
- func NewMockUnitAllocation(name string, start time.Time, resolution time.Duration, props *AllocationProperties) *Allocation {
- if name == "" {
- name = "cluster1/namespace1/pod1/container1"
- }
- properties := &AllocationProperties{}
- if props == nil {
- properties.Cluster = "cluster1"
- properties.Node = "node1"
- properties.Namespace = "namespace1"
- properties.ControllerKind = "deployment"
- properties.Controller = "deployment1"
- properties.Pod = "pod1"
- properties.Container = "container1"
- } else {
- properties = props
- }
- end := start.Add(resolution)
- alloc := &Allocation{
- Name: name,
- Properties: properties,
- Window: NewWindow(&start, &end).Clone(),
- Start: start,
- End: end,
- CPUCoreHours: 1,
- CPUCost: 1,
- CPUCoreRequestAverage: 1,
- CPUCoreUsageAverage: 1,
- GPUHours: 1,
- GPUCost: 1,
- NetworkCost: 1,
- LoadBalancerCost: 1,
- PVs: PVAllocations{
- disk: {
- ByteHours: 1,
- Cost: 1,
- },
- },
- RAMByteHours: 1,
- RAMCost: 1,
- RAMBytesRequestAverage: 1,
- RAMBytesUsageAverage: 1,
- RawAllocationOnly: &RawAllocationOnlyData{
- CPUCoreUsageMax: 1,
- RAMBytesUsageMax: 1,
- },
- ProportionalAssetResourceCosts: nil,
- }
- // If idle allocation, remove non-idle costs, but maintain total cost
- if alloc.IsIdle() {
- alloc.PVs = nil
- alloc.NetworkCost = 0.0
- alloc.LoadBalancerCost = 0.0
- alloc.CPUCoreHours += 1.0
- alloc.CPUCost += 1.0
- alloc.RAMByteHours += 1.0
- alloc.RAMCost += 1.0
- }
- return alloc
- }
- // GenerateMockAllocationSetClusterIdle creates generic allocation set which includes an idle set broken down by cluster
- func GenerateMockAllocationSetClusterIdle(start time.Time) *AllocationSet {
- // Cluster Idle allocations
- a1i := NewMockUnitAllocation(fmt.Sprintf("cluster1/%s", IdleSuffix), start, day, &AllocationProperties{
- Cluster: "cluster1",
- })
- a1i.CPUCost = 5.0
- a1i.RAMCost = 15.0
- a1i.GPUCost = 0.0
- a2i := NewMockUnitAllocation(fmt.Sprintf("cluster2/%s", IdleSuffix), start, day, &AllocationProperties{
- Cluster: "cluster2",
- })
- a2i.CPUCost = 5.0
- a2i.RAMCost = 5.0
- a2i.GPUCost = 0.0
- as := GenerateMockAllocationSet(start)
- as.Insert(a1i)
- as.Insert(a2i)
- return as
- }
- // GenerateMockAllocationSetNodeIdle creates generic allocation set which includes an idle set broken down by node
- func GenerateMockAllocationSetNodeIdle(start time.Time) *AllocationSet {
- // Node Idle allocations
- a11i := NewMockUnitAllocation(fmt.Sprintf("c1nodes/%s", IdleSuffix), start, day, &AllocationProperties{
- Cluster: "cluster1",
- Node: "c1nodes",
- ProviderID: "c1nodes",
- })
- a11i.CPUCost = 5.0
- a11i.RAMCost = 15.0
- a11i.GPUCost = 0.0
- a21i := NewMockUnitAllocation(fmt.Sprintf("node1/%s", IdleSuffix), start, day, &AllocationProperties{
- Cluster: "cluster2",
- Node: "node1",
- ProviderID: "node1",
- })
- a21i.CPUCost = 1.666667
- a21i.RAMCost = 1.666667
- a21i.GPUCost = 0.0
- a22i := NewMockUnitAllocation(fmt.Sprintf("node2/%s", IdleSuffix), start, day, &AllocationProperties{
- Cluster: "cluster2",
- Node: "node2",
- ProviderID: "node2",
- })
- a22i.CPUCost = 1.666667
- a22i.RAMCost = 1.666667
- a22i.GPUCost = 0.0
- a23i := NewMockUnitAllocation(fmt.Sprintf("node3/%s", IdleSuffix), start, day, &AllocationProperties{
- Cluster: "cluster2",
- Node: "node3",
- ProviderID: "node3",
- Namespace: "",
- })
- a23i.CPUCost = 1.666667
- a23i.RAMCost = 1.666667
- a23i.GPUCost = 0.0
- as := GenerateMockAllocationSet(start)
- as.Insert(a11i)
- as.Insert(a21i)
- as.Insert(a22i)
- as.Insert(a23i)
- return as
- }
- // GenerateMockAllocationSet creates generic allocation set without idle allocations
- func GenerateMockAllocationSet(start time.Time) *AllocationSet {
- // Active allocations
- a1111 := NewMockUnitAllocation("cluster1/namespace1/pod1/container1", start, day, &AllocationProperties{
- Cluster: "cluster1",
- Namespace: "namespace1",
- Pod: "pod1",
- Container: "container1",
- ProviderID: "c1nodes",
- Node: "c1nodes",
- })
- a1111.RAMCost = 11.00
- a1111.PVs = PVAllocations{
- PVKey{Cluster: "cluster1", Name: "pv-a1111"}: {
- ByteHours: 1,
- Cost: 1,
- },
- }
- a11abc2 := NewMockUnitAllocation("cluster1/namespace1/pod-abc/container2", start, day, &AllocationProperties{
- Cluster: "cluster1",
- Namespace: "namespace1",
- Pod: "pod-abc",
- Container: "container2",
- ProviderID: "c1nodes",
- Node: "c1nodes",
- })
- a11abc2.PVs = PVAllocations{
- PVKey{Cluster: "cluster1", Name: "pv-a11abc2"}: {
- ByteHours: 1,
- Cost: 1,
- },
- }
- a11def3 := NewMockUnitAllocation("cluster1/namespace1/pod-def/container3", start, day, &AllocationProperties{
- Cluster: "cluster1",
- Namespace: "namespace1",
- Pod: "pod-def",
- Container: "container3",
- ProviderID: "c1nodes",
- Node: "c1nodes",
- })
- a11def3.PVs = PVAllocations{
- PVKey{Cluster: "cluster1", Name: "pv-a11def3"}: {
- ByteHours: 1,
- Cost: 1,
- },
- }
- a12ghi4 := NewMockUnitAllocation("cluster1/namespace2/pod-ghi/container4", start, day, &AllocationProperties{
- Cluster: "cluster1",
- Namespace: "namespace2",
- Pod: "pod-ghi",
- Container: "container4",
- ProviderID: "c1nodes",
- Node: "c1nodes",
- })
- a12ghi4.PVs = PVAllocations{
- PVKey{Cluster: "cluster1", Name: "pv-a12ghi4"}: {
- ByteHours: 1,
- Cost: 1,
- },
- }
- a12ghi5 := NewMockUnitAllocation("cluster1/namespace2/pod-ghi/container5", start, day, &AllocationProperties{
- Cluster: "cluster1",
- Namespace: "namespace2",
- Pod: "pod-ghi",
- Container: "container5",
- ProviderID: "c1nodes",
- Node: "c1nodes",
- })
- a12ghi5.PVs = PVAllocations{
- PVKey{Cluster: "cluster1", Name: "pv-a12ghi5"}: {
- ByteHours: 1,
- Cost: 1,
- },
- }
- a12jkl6 := NewMockUnitAllocation("cluster1/namespace2/pod-jkl/container6", start, day, &AllocationProperties{
- Cluster: "cluster1",
- Namespace: "namespace2",
- Pod: "pod-jkl",
- Container: "container6",
- ProviderID: "c1nodes",
- Node: "c1nodes",
- })
- a12jkl6.PVs = PVAllocations{
- PVKey{Cluster: "cluster1", Name: "pv-a12jkl6"}: {
- ByteHours: 1,
- Cost: 1,
- },
- }
- a22mno4 := NewMockUnitAllocation("cluster2/namespace2/pod-mno/container4", start, day, &AllocationProperties{
- Cluster: "cluster2",
- Namespace: "namespace2",
- Pod: "pod-mno",
- Container: "container4",
- ProviderID: "node1",
- Node: "node1",
- })
- a22mno4.PVs = PVAllocations{
- PVKey{Cluster: "cluster2", Name: "pv-a22mno4"}: {
- ByteHours: 1,
- Cost: 1,
- },
- }
- a22mno5 := NewMockUnitAllocation("cluster2/namespace2/pod-mno/container5", start, day, &AllocationProperties{
- Cluster: "cluster2",
- Namespace: "namespace2",
- Pod: "pod-mno",
- Container: "container5",
- ProviderID: "node1",
- Node: "node1",
- })
- a22mno5.PVs = PVAllocations{
- PVKey{Cluster: "cluster2", Name: "pv-a22mno5"}: {
- ByteHours: 1,
- Cost: 1,
- },
- }
- a22pqr6 := NewMockUnitAllocation("cluster2/namespace2/pod-pqr/container6", start, day, &AllocationProperties{
- Cluster: "cluster2",
- Namespace: "namespace2",
- Pod: "pod-pqr",
- Container: "container6",
- ProviderID: "node2",
- Node: "node2",
- })
- a22pqr6.PVs = PVAllocations{
- PVKey{Cluster: "cluster2", Name: "pv-a22pqr6"}: {
- ByteHours: 1,
- Cost: 1,
- },
- }
- a23stu7 := NewMockUnitAllocation("cluster2/namespace3/pod-stu/container7", start, day, &AllocationProperties{
- Cluster: "cluster2",
- Namespace: "namespace3",
- Pod: "pod-stu",
- Container: "container7",
- ProviderID: "node2",
- Node: "node2",
- })
- a23stu7.PVs = PVAllocations{
- PVKey{Cluster: "cluster2", Name: "pv-a23stu7"}: {
- ByteHours: 1,
- Cost: 1,
- },
- }
- a23vwx8 := NewMockUnitAllocation("cluster2/namespace3/pod-vwx/container8", start, day, &AllocationProperties{
- Cluster: "cluster2",
- Namespace: "namespace3",
- Pod: "pod-vwx",
- Container: "container8",
- ProviderID: "node3",
- Node: "node3",
- })
- a23vwx8.PVs = PVAllocations{
- PVKey{Cluster: "cluster2", Name: "pv-a23vwx8"}: {
- ByteHours: 1,
- Cost: 1,
- },
- }
- a23vwx9 := NewMockUnitAllocation("cluster2/namespace3/pod-vwx/container9", start, day, &AllocationProperties{
- Cluster: "cluster2",
- Namespace: "namespace3",
- Pod: "pod-vwx",
- Container: "container9",
- ProviderID: "node3",
- Node: "node3",
- })
- a23vwx9.PVs = PVAllocations{
- PVKey{Cluster: "cluster2", Name: "pv-a23vwx9"}: {
- ByteHours: 1,
- Cost: 1,
- },
- }
- // Controllers
- a11abc2.Properties.ControllerKind = "deployment"
- a11abc2.Properties.Controller = "deployment1"
- a11def3.Properties.ControllerKind = "deployment"
- a11def3.Properties.Controller = "deployment1"
- a12ghi4.Properties.ControllerKind = "deployment"
- a12ghi4.Properties.Controller = "deployment2"
- a12ghi5.Properties.ControllerKind = "deployment"
- a12ghi5.Properties.Controller = "deployment2"
- a22mno4.Properties.ControllerKind = "deployment"
- a22mno4.Properties.Controller = "deployment2"
- a22mno5.Properties.ControllerKind = "deployment"
- a22mno5.Properties.Controller = "deployment2"
- a23stu7.Properties.ControllerKind = "deployment"
- a23stu7.Properties.Controller = "deployment3"
- a12jkl6.Properties.ControllerKind = "daemonset"
- a12jkl6.Properties.Controller = "daemonset1"
- a22pqr6.Properties.ControllerKind = "daemonset"
- a22pqr6.Properties.Controller = "daemonset1"
- a23vwx8.Properties.ControllerKind = "statefulset"
- a23vwx8.Properties.Controller = "statefulset1"
- a23vwx9.Properties.ControllerKind = "statefulset"
- a23vwx9.Properties.Controller = "statefulset1"
- // Labels
- a1111.Properties.Labels = map[string]string{"app": "app1", "env": "env1"}
- a12ghi4.Properties.Labels = map[string]string{"app": "app2", "env": "env2"}
- a12ghi5.Properties.Labels = map[string]string{"app": "app2", "env": "env2"}
- a22mno4.Properties.Labels = map[string]string{"app": "app2"}
- a22mno5.Properties.Labels = map[string]string{"app": "app2"}
- //Annotations
- a23stu7.Properties.Annotations = map[string]string{"team": "team1"}
- a23vwx8.Properties.Annotations = map[string]string{"team": "team2"}
- a23vwx9.Properties.Annotations = map[string]string{"team": "team1"}
- // Services
- a12jkl6.Properties.Services = []string{"service1"}
- a22pqr6.Properties.Services = []string{"service1"}
- return NewAllocationSet(start, start.Add(day),
- // cluster 1, namespace1
- a1111, a11abc2, a11def3,
- // cluster 1, namespace 2
- a12ghi4, a12ghi5, a12jkl6,
- // cluster 2, namespace 2
- a22mno4, a22mno5, a22pqr6,
- // cluster 2, namespace 3
- a23stu7, a23vwx8, a23vwx9,
- )
- }
- // GenerateMockAllocationSetWithAssetProperties with no idle and connections to Assets in properties
- func GenerateMockAllocationSetWithAssetProperties(start time.Time) *AllocationSet {
- as := GenerateMockAllocationSet(start)
- disk1 := PVKey{
- Cluster: "cluster2",
- Name: "disk1",
- }
- disk2 := PVKey{
- Cluster: "cluster2",
- Name: "disk2",
- }
- for _, a := range as.Allocations {
- // add reconcilable pvs to pod-mno
- if a.Properties.Pod == "pod-mno" {
- a.PVs = a.PVs.Add(PVAllocations{
- disk1: {
- Cost: 2.5,
- ByteHours: 2.5 * gb,
- },
- disk2: {
- Cost: 5,
- ByteHours: 5 * gb,
- },
- })
- }
- // add loadBalancer service to allocations
- if a.Name == "cluster2/namespace2/pod-mno/container4" {
- a.Properties.Services = append(a.Properties.Services, "loadBalancer1")
- }
- if a.Name == "cluster2/namespace2/pod-mno/container5" {
- a.Properties.Services = append(a.Properties.Services, "loadBalancer2")
- }
- if a.Name == "cluster2/namespace2/pod-pqr/container6" {
- a.Properties.Services = append(a.Properties.Services, "loadBalancer1")
- a.Properties.Services = append(a.Properties.Services, "loadBalancer2")
- }
- }
- return as
- }
- // GenerateMockAssetSets creates generic AssetSets
- func GenerateMockAssetSets(start, end time.Time) []*AssetSet {
- var assetSets []*AssetSet
- // Create an AssetSet representing cluster costs for two clusters (cluster1
- // and cluster2). Include Nodes and Disks for both, even though only
- // Nodes will be counted. Whereas in practice, Assets should be aggregated
- // by type, here we will provide multiple Nodes for one of the clusters to
- // make sure the function still holds.
- // NOTE: we're re-using GenerateMockAllocationSet so this has to line up with
- // the allocated node costs from that function. See table above.
- // | Hierarchy | Cost | CPU | RAM | GPU | Adjustment |
- // +-----------------------------------------+------+------+------+------+------------+
- // cluster1:
- // nodes 100.00 55.00 44.00 11.00 -10.00
- // +-----------------------------------------+------+------+------+------+------------+
- // cluster1 subtotal (adjusted) 100.00 50.00 40.00 10.00 0.00
- // +-----------------------------------------+------+------+------+------+------------+
- // cluster1 allocated 48.00 6.00 16.00 6.00 0.00
- // +-----------------------------------------+------+------+------+------+------------+
- // cluster1 idle 72.00 44.00 24.00 4.00 0.00
- // +-----------------------------------------+------+------+------+------+------------+
- // cluster2:
- // node1 35.00 20.00 15.00 0.00 0.00
- // node2 35.00 20.00 15.00 0.00 0.00
- // node3 30.00 10.00 10.00 10.00 0.00
- // (disks should not matter for idle)
- // +-----------------------------------------+------+------+------+------+------------+
- // cluster2 subtotal 100.00 50.00 40.00 10.00 0.00
- // +-----------------------------------------+------+------+------+------+------------+
- // cluster2 allocated 28.00 6.00 6.00 6.00 0.00
- // +-----------------------------------------+------+------+------+------+------------+
- // cluster2 idle 82.00 44.00 34.00 4.00 0.00
- // +-----------------------------------------+------+------+------+------+------------+
- cluster1Nodes := NewNode("c1nodes", "cluster1", "c1nodes", start, end, NewWindow(&start, &end))
- cluster1Nodes.CPUCost = 55.0
- cluster1Nodes.RAMCost = 44.0
- cluster1Nodes.GPUCost = 11.0
- cluster1Nodes.Adjustment = -10.00
- cluster1Nodes.CPUCoreHours = 8
- cluster1Nodes.RAMByteHours = 6
- cluster1Nodes.GPUHours = 24
- cluster2Node1 := NewNode("node1", "cluster2", "node1", start, end, NewWindow(&start, &end))
- cluster2Node1.CPUCost = 20.0
- cluster2Node1.RAMCost = 15.0
- cluster2Node1.GPUCost = 0.0
- cluster2Node1.CPUCoreHours = 4
- cluster2Node1.RAMByteHours = 3
- cluster2Node1.GPUHours = 0
- cluster2Node2 := NewNode("node2", "cluster2", "node2", start, end, NewWindow(&start, &end))
- cluster2Node2.CPUCost = 20.0
- cluster2Node2.RAMCost = 15.0
- cluster2Node2.GPUCost = 0.0
- cluster2Node2.CPUCoreHours = 3
- cluster2Node2.RAMByteHours = 2
- cluster2Node2.GPUHours = 0
- cluster2Node3 := NewNode("node3", "cluster2", "node3", start, end, NewWindow(&start, &end))
- cluster2Node3.CPUCost = 10.0
- cluster2Node3.RAMCost = 10.0
- cluster2Node3.GPUCost = 10.0
- cluster2Node3.CPUCoreHours = 2
- cluster2Node3.RAMByteHours = 2
- cluster2Node3.GPUHours = 24
- // Add PVs
- cluster2Disk1 := NewDisk("disk1", "cluster2", "disk1", start, end, NewWindow(&start, &end))
- cluster2Disk1.Cost = 5.0
- cluster2Disk1.Adjustment = 1.0
- cluster2Disk1.ByteHours = 5 * gb
- cluster2Disk2 := NewDisk("disk2", "cluster2", "disk2", start, end, NewWindow(&start, &end))
- cluster2Disk2.Cost = 10.0
- cluster2Disk2.Adjustment = 3.0
- cluster2Disk2.ByteHours = 10 * gb
- cluster2Node1Disk := NewDisk("node1", "cluster2", "node1", start, end, NewWindow(&start, &end))
- cluster2Node1Disk.Cost = 1.0
- cluster2Node1Disk.ByteHours = 5 * gb
- // Add Attached Disks
- cluster2Node2Disk := NewDisk("node2", "cluster2", "node2", start, end, NewWindow(&start, &end))
- cluster2Node2Disk.Cost = 2.0
- cluster2Node2Disk.ByteHours = 5 * gb
- cluster2Node3Disk := NewDisk("node3", "cluster2", "node3", start, end, NewWindow(&start, &end))
- cluster2Node3Disk.Cost = 3.0
- cluster2Node3Disk.ByteHours = 5 * gb
- // Add Cluster Management
- cluster1ClusterManagement := NewClusterManagement("", "cluster1", NewWindow(&start, &end))
- cluster1ClusterManagement.Cost = 2.0
- cluster2ClusterManagement := NewClusterManagement("", "cluster2", NewWindow(&start, &end))
- cluster2ClusterManagement.Cost = 2.0
- // Add Networks
- c1Network := NewNetwork("", "cluster1", "c1nodes", start, end, NewWindow(&start, &end))
- c1Network.Cost = 3.0
- node1Network := NewNetwork("node1", "cluster2", "node1", start, end, NewWindow(&start, &end))
- node1Network.Cost = 4.0
- node2Network := NewNetwork("node2", "cluster2", "node2", start, end, NewWindow(&start, &end))
- node2Network.Cost = 5.0
- node3Network := NewNetwork("node3", "cluster2", "node3", start, end, NewWindow(&start, &end))
- node3Network.Cost = 2.0
- // Add LoadBalancers
- cluster2LoadBalancer1 := NewLoadBalancer("namespace2/loadBalancer1", "cluster2", "lb1", start, end, NewWindow(&start, &end), false, "127.0.0.1")
- cluster2LoadBalancer1.Cost = 10.0
- cluster2LoadBalancer2 := NewLoadBalancer("namespace2/loadBalancer2", "cluster2", "lb2", start, end, NewWindow(&start, &end), false, "127.0.0.1")
- cluster2LoadBalancer2.Cost = 15.0
- assetSet1 := NewAssetSet(start, end, cluster1Nodes, cluster2Node1, cluster2Node2, cluster2Node3, cluster2Disk1,
- cluster2Disk2, cluster2Node1Disk, cluster2Node2Disk, cluster2Node3Disk, cluster1ClusterManagement,
- cluster2ClusterManagement, c1Network, node1Network, node2Network, node3Network, cluster2LoadBalancer1, cluster2LoadBalancer2)
- assetSets = append(assetSets, assetSet1)
- // NOTE: we're re-using GenerateMockAllocationSet so this has to line up with
- // the allocated node costs from that function. See table above.
- // | Hierarchy | Cost | CPU | RAM | GPU | Adjustment |
- // +-----------------------------------------+------+------+------+------+------------+
- // cluster1:
- // nodes 100.00 5.00 4.00 1.00 90.00
- // +-----------------------------------------+------+------+------+------+------------+
- // cluster1 subtotal (adjusted) 100.00 50.00 40.00 10.00 0.00
- // +-----------------------------------------+------+------+------+------+------------+
- // cluster1 allocated 48.00 6.00 16.00 6.00 0.00
- // +-----------------------------------------+------+------+------+------+------------+
- // cluster1 idle 72.00 44.00 24.00 4.00 0.00
- // +-----------------------------------------+------+------+------+------+------------+
- // cluster2:
- // node1 35.00 20.00 15.00 0.00 0.00
- // node2 35.00 20.00 15.00 0.00 0.00
- // node3 30.00 10.00 10.00 10.00 0.00
- // (disks should not matter for idle)
- // +-----------------------------------------+------+------+------+------+------------+
- // cluster2 subtotal 100.00 50.00 40.00 10.00 0.00
- // +-----------------------------------------+------+------+------+------+------------+
- // cluster2 allocated 28.00 6.00 6.00 6.00 0.00
- // +-----------------------------------------+------+------+------+------+------------+
- // cluster2 idle 82.00 44.00 34.00 4.00 0.00
- // +-----------------------------------------+------+------+------+------+------------+
- cluster1Nodes = NewNode("", "cluster1", "c1nodes", start, end, NewWindow(&start, &end))
- cluster1Nodes.CPUCost = 5.0
- cluster1Nodes.RAMCost = 4.0
- cluster1Nodes.GPUCost = 1.0
- cluster1Nodes.Adjustment = 90.00
- cluster1Nodes.CPUCoreHours = 8
- cluster1Nodes.RAMByteHours = 6
- cluster1Nodes.GPUHours = 24
- cluster2Node1 = NewNode("node1", "cluster2", "node1", start, end, NewWindow(&start, &end))
- cluster2Node1.CPUCost = 20.0
- cluster2Node1.RAMCost = 15.0
- cluster2Node1.GPUCost = 0.0
- cluster2Node1.CPUCoreHours = 4
- cluster2Node1.RAMByteHours = 3
- cluster2Node1.GPUHours = 0
- cluster2Node2 = NewNode("node2", "cluster2", "node2", start, end, NewWindow(&start, &end))
- cluster2Node2.CPUCost = 20.0
- cluster2Node2.RAMCost = 15.0
- cluster2Node2.GPUCost = 0.0
- cluster2Node2.CPUCoreHours = 3
- cluster2Node2.RAMByteHours = 2
- cluster2Node2.GPUHours = 0
- cluster2Node3 = NewNode("node3", "cluster2", "node3", start, end, NewWindow(&start, &end))
- cluster2Node3.CPUCost = 10.0
- cluster2Node3.RAMCost = 10.0
- cluster2Node3.GPUCost = 10.0
- cluster2Node3.CPUCoreHours = 2
- cluster2Node3.RAMByteHours = 2
- cluster2Node3.GPUHours = 24
- // Add PVs
- cluster2Disk1 = NewDisk("disk1", "cluster2", "disk1", start, end, NewWindow(&start, &end))
- cluster2Disk1.Cost = 5.0
- cluster2Disk1.Adjustment = 1.0
- cluster2Disk1.ByteHours = 5 * gb
- cluster2Disk2 = NewDisk("disk2", "cluster2", "disk2", start, end, NewWindow(&start, &end))
- cluster2Disk2.Cost = 12.0
- cluster2Disk2.Adjustment = 4.0
- cluster2Disk2.ByteHours = 20 * gb
- assetSet2 := NewAssetSet(start, end, cluster1Nodes, cluster2Node1, cluster2Node2, cluster2Node3, cluster2Disk1,
- cluster2Disk2, cluster2Node1Disk, cluster2Node2Disk, cluster2Node3Disk, cluster1ClusterManagement,
- cluster2ClusterManagement, c1Network, node1Network, node2Network, node3Network, cluster2LoadBalancer1, cluster2LoadBalancer2)
- assetSets = append(assetSets, assetSet2)
- return assetSets
- }
- // GenerateMockAssetSet generates the following topology:
- //
- // | Asset | Cost | Adj |
- // +------------------------------+------+------+
- //
- // cluster1:
- // node1: 6.00 1.00
- // node2: 4.00 1.50
- // node3: 7.00 -0.50
- // disk1: 2.50 0.00
- // disk2: 1.50 0.00
- // clusterManagement1: 3.00 0.00
- //
- // +------------------------------+------+------+
- //
- // cluster1 subtotal 24.00 2.00
- //
- // +------------------------------+------+------+
- //
- // cluster2:
- // node4: 12.00 -1.00
- // disk3: 2.50 0.00
- // disk4: 1.50 0.00
- // clusterManagement2: 0.00 0.00
- //
- // +------------------------------+------+------+
- //
- // cluster2 subtotal 16.00 -1.00
- //
- // +------------------------------+------+------+
- //
- // cluster3:
- // node5: 17.00 2.00
- //
- // +------------------------------+------+------+
- //
- // cluster3 subtotal 17.00 2.00
- //
- // +------------------------------+------+------+
- //
- // total 57.00 3.00
- //
- // +------------------------------+------+------+
- func GenerateMockAssetSet(start time.Time, duration time.Duration) *AssetSet {
- end := start.Add(duration)
- window := NewWindow(&start, &end)
- hours := window.Duration().Hours()
- node1 := NewNode("node1", "cluster1", "gcp-node1", *window.Clone().start, *window.Clone().end, window.Clone())
- node1.CPUCost = 4.0
- node1.RAMCost = 4.0
- node1.GPUCost = 2.0
- node1.Discount = 0.5
- node1.CPUCoreHours = 2.0 * hours
- node1.RAMByteHours = 4.0 * gb * hours
- node1.GPUHours = 1.0 * hours
- node1.SetAdjustment(1.0)
- node1.SetLabels(map[string]string{"test": "test"})
- node2 := NewNode("node2", "cluster1", "gcp-node2", *window.Clone().start, *window.Clone().end, window.Clone())
- node2.CPUCost = 4.0
- node2.RAMCost = 4.0
- node2.GPUCost = 0.0
- node2.Discount = 0.5
- node2.CPUCoreHours = 2.0 * hours
- node2.RAMByteHours = 4.0 * gb * hours
- node2.GPUHours = 0.0 * hours
- node2.SetAdjustment(1.5)
- node3 := NewNode("node3", "cluster1", "gcp-node3", *window.Clone().start, *window.Clone().end, window.Clone())
- node3.CPUCost = 4.0
- node3.RAMCost = 4.0
- node3.GPUCost = 3.0
- node3.Discount = 0.5
- node3.CPUCoreHours = 2.0 * hours
- node3.RAMByteHours = 4.0 * gb * hours
- node3.GPUHours = 2.0 * hours
- node3.SetAdjustment(-0.5)
- node4 := NewNode("node4", "cluster2", "gcp-node4", *window.Clone().start, *window.Clone().end, window.Clone())
- node4.CPUCost = 10.0
- node4.RAMCost = 6.0
- node4.GPUCost = 0.0
- node4.Discount = 0.25
- node4.CPUCoreHours = 4.0 * hours
- node4.RAMByteHours = 12.0 * gb * hours
- node4.GPUHours = 0.0 * hours
- node4.SetAdjustment(-1.0)
- node5 := NewNode("node5", "cluster3", "aws-node5", *window.Clone().start, *window.Clone().end, window.Clone())
- node5.CPUCost = 10.0
- node5.RAMCost = 7.0
- node5.GPUCost = 0.0
- node5.Discount = 0.0
- node5.CPUCoreHours = 8.0 * hours
- node5.RAMByteHours = 24.0 * gb * hours
- node5.GPUHours = 0.0 * hours
- node5.SetAdjustment(2.0)
- disk1 := NewDisk("disk1", "cluster1", "gcp-disk1", *window.Clone().start, *window.Clone().end, window.Clone())
- disk1.Cost = 2.5
- disk1.ByteHours = 100 * gb * hours
- disk2 := NewDisk("disk2", "cluster1", "gcp-disk2", *window.Clone().start, *window.Clone().end, window.Clone())
- disk2.Cost = 1.5
- disk2.ByteHours = 60 * gb * hours
- disk3 := NewDisk("disk3", "cluster2", "gcp-disk3", *window.Clone().start, *window.Clone().end, window.Clone())
- disk3.Cost = 2.5
- disk3.ByteHours = 100 * gb * hours
- disk4 := NewDisk("disk4", "cluster2", "gcp-disk4", *window.Clone().start, *window.Clone().end, window.Clone())
- disk4.Cost = 1.5
- disk4.ByteHours = 100 * gb * hours
- cm1 := NewClusterManagement(GCPProvider, "cluster1", window.Clone())
- cm1.Cost = 3.0
- cm2 := NewClusterManagement(GCPProvider, "cluster2", window.Clone())
- cm2.Cost = 0.0
- return NewAssetSet(
- start, end,
- // cluster 1
- node1, node2, node3, disk1, disk2, cm1,
- // cluster 2
- node4, disk3, disk4, cm2,
- // cluster 3
- node5,
- )
- }
- // NewMockUnitSummaryAllocation creates an *SummaryAllocation with all of its float64 values set to 1 and generic properties if not provided in arg
- func NewMockUnitSummaryAllocation(name string, start time.Time, resolution time.Duration, props *AllocationProperties) *SummaryAllocation {
- if name == "" {
- name = "cluster1/namespace1/pod1/container1"
- }
- properties := &AllocationProperties{}
- if props == nil {
- properties.Cluster = "cluster1"
- properties.Node = "node1"
- properties.Namespace = "namespace1"
- properties.ControllerKind = "deployment"
- properties.Controller = "deployment1"
- properties.Pod = "pod1"
- properties.Container = "container1"
- } else {
- properties = props
- }
- end := start.Add(resolution)
- alloc := &SummaryAllocation{
- Name: name,
- Properties: properties,
- Start: start,
- End: end,
- CPUCost: 1,
- CPUCoreRequestAverage: 1,
- CPUCoreUsageAverage: 1,
- GPUCost: 1,
- NetworkCost: 1,
- LoadBalancerCost: 1,
- RAMCost: 1,
- RAMBytesRequestAverage: 1,
- RAMBytesUsageAverage: 1,
- }
- // If idle allocation, remove non-idle costs, but maintain total cost
- if alloc.IsIdle() {
- alloc.NetworkCost = 0.0
- alloc.LoadBalancerCost = 0.0
- alloc.CPUCost += 1.0
- alloc.RAMCost += 1.0
- }
- return alloc
- }
- // NewMockUnitSummaryAllocationSet creates an *SummaryAllocationSet
- func NewMockUnitSummaryAllocationSet(start time.Time, resolution time.Duration) *SummaryAllocationSet {
- end := start.Add(resolution)
- sas := &SummaryAllocationSet{
- Window: NewWindow(&start, &end),
- }
- return sas
- }
- const (
- mockCloudService1 = "MockCloudService1"
- mockCloudService2 = "MockCloudService2"
- mockCloudService3 = "MockCloudService3"
- mockCloudServiceName = "MockCloudService"
- )
- type MockNetworkInsightImportantKeys struct {
- Cluster string
- Namespace string
- Controller string
- Pod string
- Node string
- Labels map[string]string
- Region string
- Zone string
- }
- func createMockNetworkDetail(cost, bytes float64, endPoint string, trafficDirection NetworkTrafficDirection, trafficType NetworkTrafficType) (*NetworkDetail, error) {
- return &NetworkDetail{
- Cost: cost,
- Bytes: bytes,
- EndPoint: endPoint,
- TrafficDirection: trafficDirection,
- TrafficType: trafficType,
- }, nil
- }
- func createMockNetworkInsight(mockInsight MockNetworkInsightImportantKeys, detailsSet NetworkDetailsSet) *NetworkInsight {
- // Ingress isnt charges at the moment
- internetCost := detailsSet.GetTotalInternetCost()
- crossZoneCost := detailsSet.GetCrossZoneCost()
- crossRegionCost := detailsSet.GetCrossRegionCost()
- totalCost := internetCost + crossZoneCost + crossRegionCost
- return NewNetworkInsight(
- mockInsight.Cluster, mockInsight.Namespace, mockInsight.Controller,
- mockInsight.Pod, mockInsight.Node, mockInsight.Labels, mockInsight.Region,
- mockInsight.Zone, totalCost, crossZoneCost, crossRegionCost, internetCost, detailsSet)
- }
- func GenerateMockNetworkInsightSet(start time.Time, end time.Time) *NetworkInsightSet {
- mockInsight1 := MockNetworkInsightImportantKeys{
- Cluster: "mockCluster1",
- Namespace: "mockNamespace1",
- Controller: "",
- Pod: "mockPod1",
- Node: "",
- Labels: map[string]string{},
- Region: "",
- Zone: "",
- }
- mockInsight2 := MockNetworkInsightImportantKeys{
- Cluster: "mockCluster1",
- Namespace: "mockNamespace2",
- Controller: "",
- Pod: "mockPod2",
- Node: "",
- Labels: map[string]string{},
- Region: "",
- Zone: "",
- }
- mcs1inIngress, _ := createMockNetworkDetail(0, 200000, mockCloudService1, NetworkTrafficDirectionIngress, NetworkTrafficTypeInternet)
- mcs2inIngress, _ := createMockNetworkDetail(0, 400000, mockCloudService2, NetworkTrafficDirectionIngress, NetworkTrafficTypeInternet)
- mcs3inIngress, _ := createMockNetworkDetail(0, 800000, mockCloudService2, NetworkTrafficDirectionIngress, NetworkTrafficTypeInternet)
- mcs1inEgress, _ := createMockNetworkDetail(0.16, 300000, mockCloudService1, NetworkTrafficDirectionEgress, NetworkTrafficTypeInternet)
- mcs2inEgress, _ := createMockNetworkDetail(0.24, 300000, mockCloudService2, NetworkTrafficDirectionEgress, NetworkTrafficTypeInternet)
- mcs3inEgress, _ := createMockNetworkDetail(0.35, 300000, mockCloudService3, NetworkTrafficDirectionEgress, NetworkTrafficTypeInternet)
- set1 := make(NetworkDetailsSet, 0)
- set1[mcs1inIngress.Key()] = mcs1inIngress
- set1[mcs2inIngress.Key()] = mcs2inIngress
- set1[mcs3inIngress.Key()] = mcs3inIngress
- set1[mcs1inEgress.Key()] = mcs1inEgress
- set1[mcs2inEgress.Key()] = mcs2inEgress
- set1[mcs3inEgress.Key()] = mcs3inEgress
- set2 := make(NetworkDetailsSet, 0)
- set2[mcs1inIngress.Key()] = mcs1inIngress.Clone()
- set2[mcs2inIngress.Key()] = mcs2inIngress.Clone()
- set2[mcs3inIngress.Key()] = mcs3inIngress.Clone()
- set2[mcs1inEgress.Key()] = mcs1inEgress.Clone()
- set2[mcs2inEgress.Key()] = mcs2inEgress.Clone()
- set2[mcs3inEgress.Key()] = mcs3inEgress.Clone()
- ni1 := createMockNetworkInsight(mockInsight1, set1)
- ni2 := createMockNetworkInsight(mockInsight1, set2)
- ni3 := createMockNetworkInsight(mockInsight2, set1.Clone())
- nis := &NetworkInsightSet{
- NetworkInsights: make(map[string]*NetworkInsight, 0),
- Window: NewClosedWindow(start, end),
- }
- nis.Insert(ni1, []NetworkInsightProperty{NetworkInsightsPod})
- nis.Insert(ni2, []NetworkInsightProperty{NetworkInsightsPod})
- nis.Insert(ni3, []NetworkInsightProperty{NetworkInsightsPod})
- return nis
- }
- func GenerateMockCloudCostSet(start, end time.Time, provider, integration string) *CloudCostSet {
- ccs := NewCloudCostSet(start, end)
- ccs.Integration = integration
- ccs.Insert(&CloudCost{
- Window: ccs.Window,
- Properties: &CloudCostProperties{
- Provider: provider,
- AccountID: "account1",
- InvoiceEntityID: "invoiceEntity1",
- Service: provider + "-storage",
- Category: StorageCategory,
- Labels: CloudCostLabels{
- "label1": "value1",
- "label2": "value2",
- "label3": "value3",
- },
- ProviderID: "id1",
- },
- ListCost: CostMetric{
- Cost: 100,
- KubernetesPercent: 0,
- },
- NetCost: CostMetric{
- Cost: 100,
- KubernetesPercent: 0,
- },
- })
- ccs.Insert(&CloudCost{
- Window: ccs.Window,
- Properties: &CloudCostProperties{
- Provider: provider,
- AccountID: "account1",
- InvoiceEntityID: "invoiceEntity1",
- Service: provider + "-compute",
- Category: ComputeCategory,
- Labels: CloudCostLabels{
- "label1": "value1",
- "label2": "value2",
- "label3": "value3",
- },
- ProviderID: "id2",
- },
- ListCost: CostMetric{
- Cost: 2000,
- KubernetesPercent: 1,
- },
- NetCost: CostMetric{
- Cost: 1800,
- KubernetesPercent: 1,
- },
- })
- ccs.Insert(&CloudCost{
- Window: ccs.Window,
- Properties: &CloudCostProperties{
- Provider: provider,
- AccountID: "account2",
- InvoiceEntityID: "invoiceEntity2",
- Service: provider + "-compute",
- Category: ComputeCategory,
- Labels: CloudCostLabels{
- "label1": "value1",
- "label2": "value2",
- "label3": "value3",
- },
- ProviderID: "id3",
- },
- ListCost: CostMetric{
- Cost: 8000,
- KubernetesPercent: 1,
- },
- NetCost: CostMetric{
- Cost: 8000,
- KubernetesPercent: 1,
- },
- })
- return ccs
- }
- // GenerateMockKubeModelSet creates generic KubeModel set
- func GenerateMockKubeModelSet(start, end time.Time) *kubemodel.KubeModelSet {
- kms := kubemodel.NewKubeModelSet(start, end)
- kms.Cluster = &kubemodel.Cluster{
- UID: "clusterUID",
- Name: "cluster",
- }
- kms.RegisterNamespace("namespace-1", "namespace-1")
- kms.RegisterNamespace("namespace-2", "namespace-2")
- kms.RegisterResourceQuota("resourcequota-1", "resourcequota-1", "namespace-1")
- kms.RegisterResourceQuota("resourcequota-2", "resourcequota-2", "namespace-1")
- kms.RegisterResourceQuota("resourcequota-3", "resourcequota-3", "namespace-2")
- kms.RegisterResourceQuota("resourcequota-4", "resourcequota-4", "namespace-2")
- return kms
- }
|