| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813 |
- package opencost
- import (
- "encoding/json"
- "fmt"
- "math"
- "reflect"
- "testing"
- "time"
- "github.com/opencost/opencost/core/pkg/util"
- )
- var start1 = time.Date(2020, time.January, 1, 0, 0, 0, 0, time.UTC)
- var start2 = start1.Add(day)
- var start3 = start2.Add(day)
- var start4 = start2.Add(day)
- var windows = []Window{
- NewWindow(&start1, &start2),
- NewWindow(&start2, &start3),
- NewWindow(&start3, &start4),
- }
- func assertAssetSet(t *testing.T, as *AssetSet, msg string, window Window, exps map[string]float64, err error) {
- if err != nil {
- t.Fatalf("AssetSet.AggregateBy[%s]: unexpected error: %s", msg, err)
- }
- if as.Length() != len(exps) {
- t.Fatalf("AssetSet.AggregateBy[%s]: expected set of length %d, actual %d", msg, len(exps), as.Length())
- }
- if !as.Window.Equal(window) {
- t.Fatalf("AssetSet.AggregateBy[%s]: expected window %s, actual %s", msg, window, as.Window)
- }
- for key, a := range as.Assets {
- if exp, ok := exps[key]; ok {
- if math.Round(a.TotalCost()*100) != math.Round(exp*100) {
- t.Fatalf("AssetSet.AggregateBy[%s]: key %s expected total cost %.2f, actual %.2f", msg, key, exp, a.TotalCost())
- }
- if !a.GetWindow().Equal(window) {
- t.Fatalf("AssetSet.AggregateBy[%s]: key %s expected window %s, actual %s", msg, key, window, a.GetWindow())
- }
- } else {
- t.Fatalf("AssetSet.AggregateBy[%s]: unexpected asset: %s", msg, key)
- }
- }
- }
- func printAssetSet(msg string, as *AssetSet) {
- fmt.Printf("--- %s ---\n", msg)
- for key, a := range as.Assets {
- fmt.Printf(" > %s: %s\n", key, a)
- }
- }
- func TestAny_Add(t *testing.T) {
- any1 := NewAsset(*windows[0].start, *windows[0].end, windows[0])
- any1.SetProperties(&AssetProperties{
- Name: "any1",
- Cluster: "cluster1",
- ProviderID: "any1",
- })
- any1.Cost = 9.0
- any1.SetAdjustment(1.0)
- any2 := NewAsset(*windows[0].start, *windows[0].end, windows[0])
- any2.SetProperties(&AssetProperties{
- Name: "any2",
- Cluster: "cluster1",
- ProviderID: "any2",
- })
- any2.Cost = 4.0
- any2.SetAdjustment(1.0)
- any3 := any1.Add(any2)
- // Check that the sums and properties are correct
- if any3.TotalCost() != 15.0 {
- t.Fatalf("Any.Add: expected %f; got %f", 15.0, any3.TotalCost())
- }
- if any3.GetAdjustment() != 2.0 {
- t.Fatalf("Any.Add: expected %f; got %f", 2.0, any3.GetAdjustment())
- }
- if any3.GetProperties().Cluster != "cluster1" {
- t.Fatalf("Any.Add: expected %s; got %s", "cluster1", any3.GetProperties().Cluster)
- }
- if any3.Type() != AnyAssetType {
- t.Fatalf("Any.Add: expected %s; got %s", AnyAssetType, any3.Type())
- }
- if any3.GetProperties().ProviderID != "" {
- t.Fatalf("Any.Add: expected %s; got %s", "", any3.GetProperties().ProviderID)
- }
- if any3.GetProperties().Name != "" {
- t.Fatalf("Any.Add: expected %s; got %s", "", any3.GetProperties().Name)
- }
- // Check that the original assets are unchanged
- if any1.TotalCost() != 10.0 {
- t.Fatalf("Any.Add: expected %f; got %f", 10.0, any1.TotalCost())
- }
- if any1.Adjustment != 1.0 {
- t.Fatalf("Any.Add: expected %f; got %f", 1.0, any1.Adjustment)
- }
- if any2.TotalCost() != 5.0 {
- t.Fatalf("Any.Add: expected %f; got %f", 5.0, any2.TotalCost())
- }
- if any2.Adjustment != 1.0 {
- t.Fatalf("Any.Add: expected %f; got %f", 1.0, any2.Adjustment)
- }
- }
- func TestAny_Clone(t *testing.T) {
- any1 := NewAsset(*windows[0].start, *windows[0].end, windows[0])
- any1.SetProperties(&AssetProperties{
- Name: "any1",
- Cluster: "cluster1",
- ProviderID: "any1",
- })
- any1.Cost = 9.0
- any1.SetAdjustment(1.0)
- any2 := any1.Clone()
- any1.Cost = 18.0
- any1.SetAdjustment(2.0)
- // any2 should match any1, even after mutating any1
- if any2.TotalCost() != 10.0 {
- t.Fatalf("Any.Clone: expected %f; got %f", 10.0, any2.TotalCost())
- }
- if any2.GetAdjustment() != 1.0 {
- t.Fatalf("Any.Clone: expected %f; got %f", 1.0, any2.GetAdjustment())
- }
- }
- func TestAny_MarshalJSON(t *testing.T) {
- any1 := NewAsset(*windows[0].start, *windows[0].end, windows[0])
- any1.SetProperties(&AssetProperties{
- Name: "any1",
- Cluster: "cluster1",
- ProviderID: "any1",
- })
- any1.Cost = 9.0
- any1.SetAdjustment(1.0)
- _, err := json.Marshal(any1)
- if err != nil {
- t.Fatalf("Any.MarshalJSON: unexpected error: %s", err)
- }
- any2 := NewAsset(*windows[0].start, *windows[0].end, windows[0])
- any2.SetProperties(&AssetProperties{
- Name: "any2",
- Cluster: "cluster1",
- ProviderID: "any2",
- })
- any2.Cost = math.NaN()
- any2.SetAdjustment(1.0)
- _, err = json.Marshal(any2)
- if err != nil {
- t.Fatalf("Any.MarshalJSON: unexpected error: %s", err)
- }
- }
- func TestDisk_Add(t *testing.T) {
- // 1. aggregate: add size, local
- // 2. accumulate: don't add size, local
- hours := windows[0].Duration().Hours()
- // Aggregate: two disks, one window
- disk1 := NewDisk("disk1", "cluster1", "disk1", *windows[0].start, *windows[0].end, windows[0])
- disk1.ByteHours = 100.0 * gb * hours
- disk1.Cost = 9.0
- disk1.SetAdjustment(1.0)
- if disk1.Bytes() != 100.0*gb {
- t.Fatalf("Disk.Add: expected %f; got %f", 100.0*gb, disk1.Bytes())
- }
- disk2 := NewDisk("disk2", "cluster1", "disk2", *windows[0].start, *windows[0].end, windows[0])
- disk2.ByteHours = 60.0 * gb * hours
- disk2.Cost = 4.0
- disk2.Local = 1.0
- disk2.SetAdjustment(1.0)
- if disk2.Bytes() != 60.0*gb {
- t.Fatalf("Disk.Add: expected %f; got %f", 60.0*gb, disk2.Bytes())
- }
- diskT := disk1.Add(disk2).(*Disk)
- // Check that the sums and properties are correct
- if diskT.TotalCost() != 15.0 {
- t.Fatalf("Disk.Add: expected %f; got %f", 15.0, diskT.TotalCost())
- }
- if diskT.Adjustment != 2.0 {
- t.Fatalf("Disk.Add: expected %f; got %f", 2.0, diskT.Adjustment)
- }
- if diskT.Properties.Cluster != "cluster1" {
- t.Fatalf("Disk.Add: expected %s; got %s", "cluster1", diskT.Properties.Cluster)
- }
- if diskT.Type() != DiskAssetType {
- t.Fatalf("Disk.Add: expected %s; got %s", AnyAssetType, diskT.Type())
- }
- if diskT.Properties.ProviderID != "" {
- t.Fatalf("Disk.Add: expected %s; got %s", "", diskT.Properties.ProviderID)
- }
- if diskT.Properties.Name != "" {
- t.Fatalf("Disk.Add: expected %s; got %s", "", diskT.Properties.Name)
- }
- if diskT.Bytes() != 160.0*gb {
- t.Fatalf("Disk.Add: expected %f; got %f", 160.0*gb, diskT.Bytes())
- }
- if !util.IsApproximately(diskT.Local, 0.333333) {
- t.Fatalf("Disk.Add: expected %f; got %f", 0.333333, diskT.Local)
- }
- // Check that the original assets are unchanged
- if disk1.TotalCost() != 10.0 {
- t.Fatalf("Disk.Add: expected %f; got %f", 10.0, disk1.TotalCost())
- }
- if disk1.Adjustment != 1.0 {
- t.Fatalf("Disk.Add: expected %f; got %f", 1.0, disk1.Adjustment)
- }
- if disk1.Local != 0.0 {
- t.Fatalf("Disk.Add: expected %f; got %f", 0.0, disk1.Local)
- }
- if disk2.TotalCost() != 5.0 {
- t.Fatalf("Disk.Add: expected %f; got %f", 5.0, disk2.TotalCost())
- }
- if disk2.Adjustment != 1.0 {
- t.Fatalf("Disk.Add: expected %f; got %f", 1.0, disk2.Adjustment)
- }
- if disk2.Local != 1.0 {
- t.Fatalf("Disk.Add: expected %f; got %f", 1.0, disk2.Local)
- }
- disk3 := NewDisk("disk3", "cluster1", "disk3", *windows[0].start, *windows[0].end, windows[0])
- disk3.ByteHours = 0.0 * hours
- disk3.Cost = 0.0
- disk3.Local = 0.0
- disk3.SetAdjustment(0.0)
- disk4 := NewDisk("disk4", "cluster1", "disk4", *windows[0].start, *windows[0].end, windows[0])
- disk4.ByteHours = 0.0 * hours
- disk4.Cost = 0.0
- disk4.Local = 1.0
- disk4.SetAdjustment(0.0)
- diskT = disk3.Add(disk4).(*Disk)
- if diskT.TotalCost() != 0.0 {
- t.Fatalf("Disk.Add: expected %f; got %f", 0.0, diskT.TotalCost())
- }
- if diskT.Local != 0.5 {
- t.Fatalf("Disk.Add: expected %f; got %f", 0.5, diskT.Local)
- }
- // Accumulate: one disks, two windows
- diskA1 := NewDisk("diskA1", "cluster1", "diskA1", *windows[0].start, *windows[0].end, windows[0])
- diskA1.ByteHours = 100 * gb * hours
- diskA1.Cost = 9.0
- diskA1.SetAdjustment(1.0)
- diskA2 := NewDisk("diskA2", "cluster1", "diskA2", *windows[1].start, *windows[1].end, windows[1])
- diskA2.ByteHours = 100 * gb * hours
- diskA2.Cost = 9.0
- diskA2.SetAdjustment(1.0)
- diskAT := diskA1.Add(diskA2).(*Disk)
- // Check that the sums and properties are correct
- if diskAT.TotalCost() != 20.0 {
- t.Fatalf("Disk.Add: expected %f; got %f", 20.0, diskAT.TotalCost())
- }
- if diskAT.Adjustment != 2.0 {
- t.Fatalf("Disk.Add: expected %f; got %f", 2.0, diskAT.Adjustment)
- }
- if diskAT.Properties.Cluster != "cluster1" {
- t.Fatalf("Disk.Add: expected %s; got %s", "cluster1", diskAT.Properties.Cluster)
- }
- if diskAT.Type() != DiskAssetType {
- t.Fatalf("Disk.Add: expected %s; got %s", AnyAssetType, diskAT.Type())
- }
- if diskAT.Properties.ProviderID != "" {
- t.Fatalf("Disk.Add: expected %s; got %s", "", diskAT.Properties.ProviderID)
- }
- if diskAT.Properties.Name != "" {
- t.Fatalf("Disk.Add: expected %s; got %s", "", diskAT.Properties.Name)
- }
- if diskAT.Bytes() != 100.0*gb {
- t.Fatalf("Disk.Add: expected %f; got %f", 100.0*gb, diskT.Bytes())
- }
- if diskAT.Local != 0.0 {
- t.Fatalf("Disk.Add: expected %f; got %f", 0.0, diskAT.Local)
- }
- // Check that the original assets are unchanged
- if diskA1.TotalCost() != 10.0 {
- t.Fatalf("Disk.Add: expected %f; got %f", 10.0, diskA1.TotalCost())
- }
- if diskA1.Adjustment != 1.0 {
- t.Fatalf("Disk.Add: expected %f; got %f", 1.0, diskA1.Adjustment)
- }
- if diskA1.Local != 0.0 {
- t.Fatalf("Disk.Add: expected %f; got %f", 0.0, diskA1.Local)
- }
- if diskA2.TotalCost() != 10.0 {
- t.Fatalf("Disk.Add: expected %f; got %f", 10.0, diskA2.TotalCost())
- }
- if diskA2.Adjustment != 1.0 {
- t.Fatalf("Disk.Add: expected %f; got %f", 1.0, diskA2.Adjustment)
- }
- if diskA2.Local != 0.0 {
- t.Fatalf("Disk.Add: expected %f; got %f", 0.0, diskA2.Local)
- }
- }
- func TestDisk_Clone(t *testing.T) {
- disk1 := NewDisk("disk1", "cluster1", "disk1", *windows[0].start, *windows[0].end, windows[0])
- disk1.Local = 0.0
- disk1.Cost = 9.0
- disk1.SetAdjustment(1.0)
- disk2 := disk1.Clone().(*Disk)
- disk2.Local = 1.0
- disk1.Cost = 18.0
- disk1.SetAdjustment(2.0)
- // disk2 should match disk1, even after mutating disk1
- if disk2.TotalCost() != 10.0 {
- t.Fatalf("Any.Clone: expected %f; got %f", 10.0, disk2.TotalCost())
- }
- if disk2.Adjustment != 1.0 {
- t.Fatalf("Any.Clone: expected %f; got %f", 1.0, disk2.Adjustment)
- }
- if disk2.Local != 1.0 {
- t.Fatalf("Disk.Add: expected %f; got %f", 1.0, disk2.Local)
- }
- }
- func TestDisk_MarshalJSON(t *testing.T) {
- disk := NewDisk("disk", "cluster", "providerID", *windows[0].start, *windows[0].end, windows[0])
- disk.SetLabels(AssetLabels{
- "label": "value",
- })
- disk.Cost = 9.0
- disk.SetAdjustment(1.0)
- _, err := json.Marshal(disk)
- if err != nil {
- t.Fatalf("Disk.MarshalJSON: unexpected error: %s", err)
- }
- }
- func TestNode_Add(t *testing.T) {
- // 1. aggregate: add size, local
- // 2. accumulate: don't add size, local
- hours := windows[0].Duration().Hours()
- // Aggregate: two nodes, one window
- node1 := NewNode("node1", "cluster1", "node1", *windows[0].start, *windows[0].end, windows[0])
- node1.CPUCoreHours = 1.0 * hours
- node1.RAMByteHours = 2.0 * gb * hours
- node1.GPUHours = 0.0 * hours
- node1.GPUCost = 0.0
- node1.CPUCost = 8.0
- node1.RAMCost = 4.0
- node1.Discount = 0.3
- node1.CPUBreakdown = &Breakdown{
- Idle: 0.6,
- System: 0.2,
- User: 0.2,
- Other: 0.0,
- }
- node1.RAMBreakdown = &Breakdown{
- Idle: 0.6,
- System: 0.2,
- User: 0.2,
- Other: 0.0,
- }
- node1.SetAdjustment(1.6)
- node1.Overhead = &NodeOverhead{
- CpuOverheadFraction: 1,
- RamOverheadFraction: 1,
- OverheadCostFraction: 1,
- }
- node2 := NewNode("node2", "cluster1", "node2", *windows[0].start, *windows[0].end, windows[0])
- node2.CPUCoreHours = 1.0 * hours
- node2.RAMByteHours = 2.0 * gb * hours
- node2.GPUHours = 0.0 * hours
- node2.GPUCost = 0.0
- node2.CPUCost = 3.0
- node2.RAMCost = 1.0
- node2.Discount = 0.0
- node1.CPUBreakdown = &Breakdown{
- Idle: 0.9,
- System: 0.05,
- User: 0.0,
- Other: 0.05,
- }
- node1.RAMBreakdown = &Breakdown{
- Idle: 0.9,
- System: 0.05,
- User: 0.0,
- Other: 0.05,
- }
- node2.SetAdjustment(1.0)
- node2.Overhead = &NodeOverhead{
- CpuOverheadFraction: 0.6,
- RamOverheadFraction: 0.75,
- OverheadCostFraction: 0.7,
- }
- nodeT := node1.Add(node2).(*Node)
- // Check that the sums and properties are correct
- if !util.IsApproximately(nodeT.TotalCost(), 15.0) {
- t.Fatalf("Node.Add: expected %f; got %f", 15.0, nodeT.TotalCost())
- }
- if nodeT.Adjustment != 2.6 {
- t.Fatalf("Node.Add: expected %f; got %f", 2.6, nodeT.Adjustment)
- }
- if nodeT.Properties.Cluster != "cluster1" {
- t.Fatalf("Node.Add: expected %s; got %s", "cluster1", nodeT.Properties.Cluster)
- }
- if nodeT.Type() != NodeAssetType {
- t.Fatalf("Node.Add: expected %s; got %s", AnyAssetType, nodeT.Type())
- }
- if nodeT.Properties.ProviderID != "" {
- t.Fatalf("Node.Add: expected %s; got %s", "", nodeT.Properties.ProviderID)
- }
- if nodeT.Properties.Name != "" {
- t.Fatalf("Node.Add: expected %s; got %s", "", nodeT.Properties.Name)
- }
- if nodeT.CPUCores() != 2.0 {
- t.Fatalf("Node.Add: expected %f; got %f", 2.0, nodeT.CPUCores())
- }
- if nodeT.RAMBytes() != 4.0*gb {
- t.Fatalf("Node.Add: expected %f; got %f", 4.0*gb, nodeT.RAMBytes())
- }
- if o := nodeT.Overhead; o == nil {
- t.Errorf("Node.Add (1 + 2): expected overhead to be non-nil")
- } else {
- if o.CpuOverheadFraction < 0 || o.CpuOverheadFraction > 1 {
- t.Errorf("CPU overhead must be within [0, 1], is: %f", o.CpuOverheadFraction)
- }
- if o.RamOverheadFraction < 0 || o.RamOverheadFraction > 1 {
- t.Errorf("RAM overhead must be within [0, 1], is: %f", o.RamOverheadFraction)
- }
- if o.OverheadCostFraction < 0 || o.OverheadCostFraction > 1 {
- t.Errorf("Cost-weighted overhead must be within [0, 1], is: %f", o.OverheadCostFraction)
- }
- }
- // Check that the original assets are unchanged
- if !util.IsApproximately(node1.TotalCost(), 10.0) {
- t.Fatalf("Node.Add: expected %f; got %f", 10.0, node1.TotalCost())
- }
- if node1.Adjustment != 1.6 {
- t.Fatalf("Node.Add: expected %f; got %f", 1.0, node1.Adjustment)
- }
- if !util.IsApproximately(node2.TotalCost(), 5.0) {
- t.Fatalf("Node.Add: expected %f; got %f", 5.0, node2.TotalCost())
- }
- if node2.Adjustment != 1.0 {
- t.Fatalf("Node.Add: expected %f; got %f", 1.0, node2.Adjustment)
- }
- // Check that we don't divide by zero computing Local
- node3 := NewNode("node3", "cluster1", "node3", *windows[0].start, *windows[0].end, windows[0])
- node3.CPUCoreHours = 0 * hours
- node3.RAMByteHours = 0 * hours
- node3.GPUHours = 0.0 * hours
- node3.GPUCost = 0
- node3.CPUCost = 0.0
- node3.RAMCost = 0.0
- node3.Discount = 0.3
- node3.SetAdjustment(0.0)
- node3.Overhead = &NodeOverhead{
- CpuOverheadFraction: 0.6,
- RamOverheadFraction: 0.75,
- OverheadCostFraction: 0.7,
- }
- node4 := NewNode("node4", "cluster1", "node4", *windows[0].start, *windows[0].end, windows[0])
- node4.CPUCoreHours = 0 * hours
- node4.RAMByteHours = 0 * hours
- node4.GPUHours = 0.0 * hours
- node4.GPUCost = 0
- node4.CPUCost = 0.0
- node4.RAMCost = 0.0
- node4.Discount = 0.1
- node4.SetAdjustment(0.0)
- node4.Overhead = nil
- nodeT = node3.Add(node4).(*Node)
- // Check that the sums and properties are correct and without NaNs
- if nodeT.TotalCost() != 0.0 {
- t.Fatalf("Node.Add: expected %f; got %f", 0.0, nodeT.TotalCost())
- }
- if nodeT.Discount != 0.2 {
- t.Fatalf("Node.Add: expected %f; got %f", 0.2, nodeT.Discount)
- }
- if nodeT.Overhead != nil {
- t.Errorf("Node.Add: adding a node with nil overhead should nil the resulting overhead")
- }
- // Accumulate: one nodes, two window
- nodeA1 := NewNode("nodeA1", "cluster1", "nodeA1", *windows[0].start, *windows[0].end, windows[0])
- nodeA1.CPUCoreHours = 1.0 * hours
- nodeA1.RAMByteHours = 2.0 * gb * hours
- nodeA1.GPUHours = 0.0 * hours
- nodeA1.GPUCost = 0.0
- nodeA1.CPUCost = 8.0
- nodeA1.RAMCost = 4.0
- nodeA1.Discount = 0.3
- nodeA1.SetAdjustment(1.6)
- nodeA2 := NewNode("nodeA2", "cluster1", "nodeA2", *windows[1].start, *windows[1].end, windows[1])
- nodeA2.CPUCoreHours = 1.0 * hours
- nodeA2.RAMByteHours = 2.0 * gb * hours
- nodeA2.GPUHours = 0.0 * hours
- nodeA2.GPUCost = 0.0
- nodeA2.CPUCost = 3.0
- nodeA2.RAMCost = 1.0
- nodeA2.Discount = 0.0
- nodeA2.SetAdjustment(1.0)
- nodeAT := nodeA1.Add(nodeA2).(*Node)
- // Check that the sums and properties are correct
- if !util.IsApproximately(nodeAT.TotalCost(), 15.0) {
- t.Fatalf("Node.Add: expected %f; got %f", 15.0, nodeAT.TotalCost())
- }
- if nodeAT.Adjustment != 2.6 {
- t.Fatalf("Node.Add: expected %f; got %f", 2.6, nodeAT.Adjustment)
- }
- if nodeAT.Properties.Cluster != "cluster1" {
- t.Fatalf("Node.Add: expected %s; got %s", "cluster1", nodeAT.Properties.Cluster)
- }
- if nodeAT.Type() != NodeAssetType {
- t.Fatalf("Node.Add: expected %s; got %s", AnyAssetType, nodeAT.Type())
- }
- if nodeAT.Properties.ProviderID != "" {
- t.Fatalf("Node.Add: expected %s; got %s", "", nodeAT.Properties.ProviderID)
- }
- if nodeAT.Properties.Name != "" {
- t.Fatalf("Node.Add: expected %s; got %s", "", nodeAT.Properties.Name)
- }
- if nodeAT.CPUCores() != 1.0 {
- t.Fatalf("Node.Add: expected %f; got %f", 1.0, nodeAT.CPUCores())
- }
- if nodeAT.RAMBytes() != 2.0*gb {
- t.Fatalf("Node.Add: expected %f; got %f", 2.0*gb, nodeAT.RAMBytes())
- }
- if nodeAT.GPUs() != 0.0 {
- t.Fatalf("Node.Add: expected %f; got %f", 0.0, nodeAT.GPUs())
- }
- // Check that the original assets are unchanged
- if !util.IsApproximately(nodeA1.TotalCost(), 10.0) {
- t.Fatalf("Node.Add: expected %f; got %f", 10.0, nodeA1.TotalCost())
- }
- if nodeA1.Adjustment != 1.6 {
- t.Fatalf("Node.Add: expected %f; got %f", 1.0, nodeA1.Adjustment)
- }
- if !util.IsApproximately(nodeA2.TotalCost(), 5.0) {
- t.Fatalf("Node.Add: expected %f; got %f", 5.0, nodeA2.TotalCost())
- }
- if nodeA2.Adjustment != 1.0 {
- t.Fatalf("Node.Add: expected %f; got %f", 1.0, nodeA2.Adjustment)
- }
- }
- func TestNode_Clone(t *testing.T) {
- cases := []struct {
- name string
- input *Node
- }{
- {
- name: "overhead nil",
- input: &Node{
- Overhead: nil,
- },
- },
- {
- name: "overhead non-nil",
- input: &Node{
- Overhead: &NodeOverhead{
- CpuOverheadFraction: 3,
- RamOverheadFraction: 7,
- OverheadCostFraction: 6,
- },
- },
- },
- }
- for _, c := range cases {
- t.Run(c.name, func(t *testing.T) {
- result := c.input.Clone()
- if !result.Equal(c.input) {
- t.Errorf("clone result doesn't equal input")
- }
- })
- }
- }
- func TestNode_MarshalJSON(t *testing.T) {
- node := NewNode("node", "cluster", "providerID", *windows[0].start, *windows[0].end, windows[0])
- node.SetLabels(AssetLabels{
- "label": "value",
- })
- node.CPUCost = 9.0
- node.RAMCost = 0.0
- node.RAMCost = 21.0
- node.CPUCoreHours = 123.0
- node.RAMByteHours = 13323.0
- node.GPUHours = 123.0
- node.SetAdjustment(1.0)
- _, err := json.Marshal(node)
- if err != nil {
- t.Fatalf("Node.MarshalJSON: unexpected error: %s", err)
- }
- }
- func TestClusterManagement_Add(t *testing.T) {
- cm1 := NewClusterManagement(GCPProvider, "cluster1", windows[0])
- cm1.Cost = 9.0
- cm2 := NewClusterManagement(GCPProvider, "cluster1", windows[0])
- cm2.Cost = 4.0
- cm3 := cm1.Add(cm2)
- // Check that the sums and properties are correct
- if cm3.TotalCost() != 13.0 {
- t.Fatalf("ClusterManagement.Add: expected %f; got %f", 13.0, cm3.TotalCost())
- }
- if cm3.GetProperties().Cluster != "cluster1" {
- t.Fatalf("ClusterManagement.Add: expected %s; got %s", "cluster1", cm3.GetProperties().Cluster)
- }
- if cm3.Type() != ClusterManagementAssetType {
- t.Fatalf("ClusterManagement.Add: expected %s; got %s", ClusterManagementAssetType, cm3.Type())
- }
- // Check that the original assets are unchanged
- if cm1.TotalCost() != 9.0 {
- t.Fatalf("ClusterManagement.Add: expected %f; got %f", 9.0, cm1.TotalCost())
- }
- if cm2.TotalCost() != 4.0 {
- t.Fatalf("ClusterManagement.Add: expected %f; got %f", 4.0, cm2.TotalCost())
- }
- }
- func TestClusterManagement_Clone(t *testing.T) {
- // TODO
- }
- func TestCloudAny_Add(t *testing.T) {
- ca1 := NewCloud(ComputeCategory, "ca1", *windows[0].start, *windows[0].end, windows[0])
- ca1.Cost = 9.0
- ca1.SetAdjustment(1.0)
- ca2 := NewCloud(StorageCategory, "ca2", *windows[0].start, *windows[0].end, windows[0])
- ca2.Cost = 4.0
- ca2.SetAdjustment(1.0)
- ca3 := ca1.Add(ca2)
- // Check that the sums and properties are correct
- if ca3.TotalCost() != 15.0 {
- t.Fatalf("Any.Add: expected %f; got %f", 15.0, ca3.TotalCost())
- }
- if ca3.GetAdjustment() != 2.0 {
- t.Fatalf("Any.Add: expected %f; got %f", 2.0, ca3.GetAdjustment())
- }
- if ca3.Type() != CloudAssetType {
- t.Fatalf("Any.Add: expected %s; got %s", CloudAssetType, ca3.Type())
- }
- // Check that the original assets are unchanged
- if ca1.TotalCost() != 10.0 {
- t.Fatalf("Any.Add: expected %f; got %f", 10.0, ca1.TotalCost())
- }
- if ca1.Adjustment != 1.0 {
- t.Fatalf("Any.Add: expected %f; got %f", 1.0, ca1.Adjustment)
- }
- if ca2.TotalCost() != 5.0 {
- t.Fatalf("Any.Add: expected %f; got %f", 5.0, ca2.TotalCost())
- }
- if ca2.Adjustment != 1.0 {
- t.Fatalf("Any.Add: expected %f; got %f", 1.0, ca2.Adjustment)
- }
- }
- func TestCloudAny_Clone(t *testing.T) {
- // TODO
- }
- func TestAssetSet_AggregateBy(t *testing.T) {
- endYesterday := time.Now().UTC().Truncate(day)
- startYesterday := endYesterday.Add(-day)
- window := NewWindow(&startYesterday, &endYesterday)
- // Scenarios to test:
- // 1 Single-aggregation
- // 1a []AssetProperty=[Cluster]
- // 1b []AssetProperty=[Type]
- // 1c []AssetProperty=[Nil]
- // 1d []AssetProperty=nil
- // 1e aggregateBy []string=["label:test"]
- // 2 Multi-aggregation
- // 2a []AssetProperty=[Cluster,Type]
- // 3 Share resources
- // 3a Shared hourly cost > 0.0
- // Definitions and set-up:
- var as *AssetSet
- var err error
- // Tests:
- // 1 Single-aggregation
- // 1a []AssetProperty=[Cluster]
- as = GenerateMockAssetSet(startYesterday, day)
- err = as.AggregateBy([]string{string(AssetClusterProp)}, nil)
- if err != nil {
- t.Fatalf("AssetSet.AggregateBy: unexpected error: %s", err)
- }
- assertAssetSet(t, as, "1a", window, map[string]float64{
- "cluster1": 26.0,
- "cluster2": 15.0,
- "cluster3": 19.0,
- }, nil)
- // 1b []AssetProperty=[Type]
- as = GenerateMockAssetSet(startYesterday, day)
- err = as.AggregateBy([]string{string(AssetTypeProp)}, nil)
- if err != nil {
- t.Fatalf("AssetSet.AggregateBy: unexpected error: %s", err)
- }
- assertAssetSet(t, as, "1b", window, map[string]float64{
- "Node": 49.0,
- "Disk": 8.0,
- "ClusterManagement": 3.0,
- }, nil)
- // 1c []AssetProperty=[Nil]
- as = GenerateMockAssetSet(startYesterday, day)
- err = as.AggregateBy([]string{}, nil)
- if err != nil {
- t.Fatalf("AssetSet.AggregateBy: unexpected error: %s", err)
- }
- assertAssetSet(t, as, "1c", window, map[string]float64{
- "": 60.0,
- }, nil)
- // 1d []AssetProperty=nil
- as = GenerateMockAssetSet(startYesterday, day)
- err = as.AggregateBy(nil, nil)
- if err != nil {
- t.Fatalf("AssetSet.AggregateBy: unexpected error: %s", err)
- }
- assertAssetSet(t, as, "1d", window, map[string]float64{
- "__undefined__/__undefined__/__undefined__/Compute/cluster1/Node/Kubernetes/gcp-node1/node1": 7.00,
- "__undefined__/__undefined__/__undefined__/Compute/cluster1/Node/Kubernetes/gcp-node2/node2": 5.50,
- "__undefined__/__undefined__/__undefined__/Compute/cluster1/Node/Kubernetes/gcp-node3/node3": 6.50,
- "__undefined__/__undefined__/__undefined__/Storage/cluster1/Disk/Kubernetes/gcp-disk1/disk1": 2.50,
- "__undefined__/__undefined__/__undefined__/Storage/cluster1/Disk/Kubernetes/gcp-disk2/disk2": 1.50,
- "GCP/__undefined__/__undefined__/Management/cluster1/ClusterManagement/Kubernetes/__undefined__/__undefined__": 3.00,
- "__undefined__/__undefined__/__undefined__/Compute/cluster2/Node/Kubernetes/gcp-node4/node4": 11.00,
- "__undefined__/__undefined__/__undefined__/Storage/cluster2/Disk/Kubernetes/gcp-disk3/disk3": 2.50,
- "__undefined__/__undefined__/__undefined__/Storage/cluster2/Disk/Kubernetes/gcp-disk4/disk4": 1.50,
- "GCP/__undefined__/__undefined__/Management/cluster2/ClusterManagement/Kubernetes/__undefined__/__undefined__": 0.00,
- "__undefined__/__undefined__/__undefined__/Compute/cluster3/Node/Kubernetes/aws-node5/node5": 19.00,
- }, nil)
- // 1e aggregateBy []string=["label:test"]
- as = GenerateMockAssetSet(startYesterday, day)
- err = as.AggregateBy([]string{"label:test"}, nil)
- if err != nil {
- t.Fatalf("AssetSet.AggregateBy: unexpected error: %s", err)
- }
- assertAssetSet(t, as, "1e", window, map[string]float64{
- "__undefined__": 53.00,
- "test=test": 7.00,
- }, nil)
- // 2 Multi-aggregation
- // 2a []AssetProperty=[Cluster,Type]
- as = GenerateMockAssetSet(startYesterday, day)
- err = as.AggregateBy([]string{string(AssetClusterProp), string(AssetTypeProp)}, nil)
- if err != nil {
- t.Fatalf("AssetSet.AggregateBy: unexpected error: %s", err)
- }
- assertAssetSet(t, as, "2a", window, map[string]float64{
- "cluster1/Node": 19.0,
- "cluster1/Disk": 4.0,
- "cluster1/ClusterManagement": 3.0,
- "cluster2/Node": 11.0,
- "cluster2/Disk": 4.0,
- "cluster2/ClusterManagement": 0.0,
- "cluster3/Node": 19.0,
- }, nil)
- // 3 Share resources
- // 3a Shared hourly cost > 0.0
- as = GenerateMockAssetSet(startYesterday, day)
- err = as.AggregateBy([]string{string(AssetTypeProp)}, &AssetAggregationOptions{
- SharedHourlyCosts: map[string]float64{"shared1": 0.5},
- })
- if err != nil {
- t.Fatalf("AssetSet.AggregateBy: unexpected error: %s", err)
- }
- assertAssetSet(t, as, "1a", window, map[string]float64{
- "Node": 49.0,
- "Disk": 8.0,
- "ClusterManagement": 3.0,
- "Shared": 12.0,
- }, nil)
- }
- func TestAssetSet_FindMatch(t *testing.T) {
- endYesterday := time.Now().UTC().Truncate(day)
- startYesterday := endYesterday.Add(-day)
- s, e := startYesterday, endYesterday
- w := NewWindow(&s, &e)
- var query, match Asset
- var as *AssetSet
- var err error
- // Assert success of a simple match of Type and ProviderID
- as = GenerateMockAssetSet(startYesterday, day)
- query = NewNode("", "", "gcp-node3", s, e, w)
- match, err = as.FindMatch(query, []string{string(AssetTypeProp), string(AssetProviderIDProp)}, nil)
- if err != nil {
- t.Fatalf("AssetSet.FindMatch: unexpected error: %s", err)
- }
- // Assert error of a simple non-match of Type and ProviderID
- as = GenerateMockAssetSet(startYesterday, day)
- query = NewNode("", "", "aws-node3", s, e, w)
- match, err = as.FindMatch(query, []string{string(AssetTypeProp), string(AssetProviderIDProp)}, nil)
- if err == nil {
- t.Fatalf("AssetSet.FindMatch: expected error (no match); found %s", match)
- }
- // Assert error of matching ProviderID, but not Type
- as = GenerateMockAssetSet(startYesterday, day)
- query = NewCloud(ComputeCategory, "gcp-node3", s, e, w)
- match, err = as.FindMatch(query, []string{string(AssetTypeProp), string(AssetProviderIDProp)}, nil)
- if err == nil {
- t.Fatalf("AssetSet.FindMatch: expected error (no match); found %s", match)
- }
- }
- // Asserts that all Assets within an AssetSet have a Window that
- // matches that of the AssetSet.
- func TestAssetSet_InsertMatchingWindow(t *testing.T) {
- setStart := time.Now().Round(time.Hour)
- setEnd := setStart.Add(1 * time.Hour)
- a1WindowStart := setStart.Add(5 * time.Minute)
- a1WindowEnd := setStart.Add(50 * time.Minute)
- a2WindowStart := setStart.Add(17 * time.Minute)
- a2WindowEnd := setStart.Add(34 * time.Minute)
- a1 := &Node{}
- a1.SetProperties(&AssetProperties{
- Name: "asset-1",
- })
- a1.Window = NewClosedWindow(a1WindowStart, a1WindowEnd)
- a2 := &Disk{}
- a2.SetProperties(&AssetProperties{
- Name: "asset-2",
- })
- a2.Window = NewClosedWindow(a2WindowStart, a2WindowEnd)
- as := NewAssetSet(setStart, setEnd)
- as.Insert(a1, nil)
- as.Insert(a2, nil)
- if as.Length() != 2 {
- t.Errorf("AS length got %d, expected %d", as.Length(), 2)
- }
- for _, a := range as.Assets {
- if !(*a.GetWindow().Start()).Equal(setStart) {
- t.Errorf("Asset %s window start is %s, expected %s", a.GetProperties().Name, *a.GetWindow().Start(), setStart)
- }
- if !(*a.GetWindow().End()).Equal(setEnd) {
- t.Errorf("Asset %s window end is %s, expected %s", a.GetProperties().Name, *a.GetWindow().End(), setEnd)
- }
- }
- }
- func TestAssetSetRange_AccumulateToAssetSet(t *testing.T) {
- endYesterday := time.Now().UTC().Truncate(day)
- startYesterday := endYesterday.Add(-day)
- startD2 := startYesterday
- startD1 := startD2.Add(-day)
- startD0 := startD1.Add(-day)
- window := NewWindow(&startD0, &endYesterday)
- var asr *AssetSetRange
- var as *AssetSet
- var err error
- asr = NewAssetSetRange(
- GenerateMockAssetSet(startD0, day),
- GenerateMockAssetSet(startD1, day),
- GenerateMockAssetSet(startD2, day),
- )
- err = asr.AggregateBy(nil, nil)
- if err != nil {
- t.Fatalf("AssetSetRange.AggregateBy: unexpected error: %s", err)
- }
- as, err = asr.AccumulateToAssetSet()
- if err != nil {
- t.Fatalf("AssetSetRange.AccumulateToAssetSet: unexpected error: %s", err)
- }
- assertAssetSet(t, as, "1a", window, map[string]float64{
- "__undefined__/__undefined__/__undefined__/Compute/cluster1/Node/Kubernetes/gcp-node1/node1": 21.00,
- "__undefined__/__undefined__/__undefined__/Compute/cluster1/Node/Kubernetes/gcp-node2/node2": 16.50,
- "__undefined__/__undefined__/__undefined__/Compute/cluster1/Node/Kubernetes/gcp-node3/node3": 19.50,
- "__undefined__/__undefined__/__undefined__/Storage/cluster1/Disk/Kubernetes/gcp-disk1/disk1": 7.50,
- "__undefined__/__undefined__/__undefined__/Storage/cluster1/Disk/Kubernetes/gcp-disk2/disk2": 4.50,
- "GCP/__undefined__/__undefined__/Management/cluster1/ClusterManagement/Kubernetes/__undefined__/__undefined__": 9.00,
- "__undefined__/__undefined__/__undefined__/Compute/cluster2/Node/Kubernetes/gcp-node4/node4": 33.00,
- "__undefined__/__undefined__/__undefined__/Storage/cluster2/Disk/Kubernetes/gcp-disk3/disk3": 7.50,
- "__undefined__/__undefined__/__undefined__/Storage/cluster2/Disk/Kubernetes/gcp-disk4/disk4": 4.50,
- "GCP/__undefined__/__undefined__/Management/cluster2/ClusterManagement/Kubernetes/__undefined__/__undefined__": 0.00,
- "__undefined__/__undefined__/__undefined__/Compute/cluster3/Node/Kubernetes/aws-node5/node5": 57.00,
- }, nil)
- asr = NewAssetSetRange(
- GenerateMockAssetSet(startD0, day),
- GenerateMockAssetSet(startD1, day),
- GenerateMockAssetSet(startD2, day),
- )
- err = asr.AggregateBy([]string{}, nil)
- if err != nil {
- t.Fatalf("AssetSetRange.AggregateBy: unexpected error: %s", err)
- }
- as, err = asr.AccumulateToAssetSet()
- if err != nil {
- t.Fatalf("AssetSetRange.AccumulateToAssetSet: unexpected error: %s", err)
- }
- assertAssetSet(t, as, "1b", window, map[string]float64{
- "": 180.00,
- }, nil)
- asr = NewAssetSetRange(
- GenerateMockAssetSet(startD0, day),
- GenerateMockAssetSet(startD1, day),
- GenerateMockAssetSet(startD2, day),
- )
- err = asr.AggregateBy([]string{string(AssetTypeProp)}, nil)
- if err != nil {
- t.Fatalf("AssetSetRange.AggregateBy: unexpected error: %s", err)
- }
- as, err = asr.AccumulateToAssetSet()
- if err != nil {
- t.Fatalf("AssetSetRange.AggregateBy: unexpected error: %s", err)
- }
- assertAssetSet(t, as, "1c", window, map[string]float64{
- "Node": 147.0,
- "Disk": 24.0,
- "ClusterManagement": 9.0,
- }, nil)
- asr = NewAssetSetRange(
- GenerateMockAssetSet(startD0, day),
- GenerateMockAssetSet(startD1, day),
- GenerateMockAssetSet(startD2, day),
- )
- err = asr.AggregateBy([]string{string(AssetClusterProp)}, nil)
- if err != nil {
- t.Fatalf("AssetSetRange.AggregateBy: unexpected error: %s", err)
- }
- as, err = asr.AccumulateToAssetSet()
- if err != nil {
- t.Fatalf("AssetSetRange.AggregateBy: unexpected error: %s", err)
- }
- assertAssetSet(t, as, "1c", window, map[string]float64{
- "cluster1": 78.0,
- "cluster2": 45.0,
- "cluster3": 57.0,
- }, nil)
- // Accumulation with aggregation should work, even when the first AssetSet
- // is empty (this was previously an issue)
- asr = NewAssetSetRange(
- NewAssetSet(startD0, startD1),
- GenerateMockAssetSet(startD1, day),
- GenerateMockAssetSet(startD2, day),
- )
- err = asr.AggregateBy([]string{string(AssetTypeProp)}, nil)
- if err != nil {
- t.Fatalf("AssetSetRange.AggregateBy: unexpected error: %s", err)
- }
- as, err = asr.AccumulateToAssetSet()
- if err != nil {
- t.Fatalf("AssetSetRange.AggregateBy: unexpected error: %s", err)
- }
- assertAssetSet(t, as, "1d", window, map[string]float64{
- "Node": 98.00,
- "Disk": 16.00,
- "ClusterManagement": 6.00,
- }, nil)
- }
- func TestAssetSetRange_Start(t *testing.T) {
- tests := []struct {
- name string
- arg *AssetSetRange
- expectError bool
- expected time.Time
- }{
- {
- name: "Empty ASR",
- arg: nil,
- expectError: true,
- },
- {
- name: "Single asset",
- arg: &AssetSetRange{
- Assets: []*AssetSet{
- {
- Assets: map[string]Asset{
- "a": &Node{
- Start: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
- },
- },
- },
- },
- },
- expected: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
- },
- {
- name: "Two assets",
- arg: &AssetSetRange{
- Assets: []*AssetSet{
- {
- Assets: map[string]Asset{
- "a": &Node{
- Start: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
- },
- "b": &Node{
- Start: time.Date(1970, 1, 2, 0, 0, 0, 0, time.UTC),
- },
- },
- },
- },
- },
- expected: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
- },
- {
- name: "Two AssetSets",
- arg: &AssetSetRange{
- Assets: []*AssetSet{
- {
- Assets: map[string]Asset{
- "a": &Node{
- Start: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
- },
- },
- },
- {
- Assets: map[string]Asset{
- "b": &Node{
- Start: time.Date(1970, 1, 2, 0, 0, 0, 0, time.UTC),
- },
- },
- },
- },
- },
- expected: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
- },
- }
- for _, test := range tests {
- result, err := test.arg.Start()
- if test.expectError && err != nil {
- continue
- }
- if test.expectError && err == nil {
- t.Errorf("%s: expected error and got none", test.name)
- } else if result != test.expected {
- t.Errorf("%s: expected %s but got %s", test.name, test.expected, result)
- }
- }
- }
- func TestAssetSetRange_End(t *testing.T) {
- tests := []struct {
- name string
- arg *AssetSetRange
- expectError bool
- expected time.Time
- }{
- {
- name: "Empty ASR",
- arg: nil,
- expectError: true,
- },
- {
- name: "Single asset",
- arg: &AssetSetRange{
- Assets: []*AssetSet{
- {
- Assets: map[string]Asset{
- "a": &Node{
- End: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
- },
- },
- },
- },
- },
- expected: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
- },
- {
- name: "Two assets",
- arg: &AssetSetRange{
- Assets: []*AssetSet{
- {
- Assets: map[string]Asset{
- "a": &Node{
- End: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
- },
- "b": &Node{
- End: time.Date(1970, 1, 2, 0, 0, 0, 0, time.UTC),
- },
- },
- },
- },
- },
- expected: time.Date(1970, 1, 2, 0, 0, 0, 0, time.UTC),
- },
- {
- name: "Two AssetSets",
- arg: &AssetSetRange{
- Assets: []*AssetSet{
- {
- Assets: map[string]Asset{
- "a": &Node{
- End: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
- },
- },
- },
- {
- Assets: map[string]Asset{
- "b": &Node{
- End: time.Date(1970, 1, 2, 0, 0, 0, 0, time.UTC),
- },
- },
- },
- },
- },
- expected: time.Date(1970, 1, 2, 0, 0, 0, 0, time.UTC),
- },
- }
- for _, test := range tests {
- result, err := test.arg.End()
- if test.expectError && err != nil {
- continue
- }
- if test.expectError && err == nil {
- t.Errorf("%s: expected error and got none", test.name)
- } else if result != test.expected {
- t.Errorf("%s: expected %s but got %s", test.name, test.expected, result)
- }
- }
- }
- func TestAssetSetRange_Minutes(t *testing.T) {
- tests := []struct {
- name string
- arg *AssetSetRange
- expected float64
- }{
- {
- name: "Empty ASR",
- arg: nil,
- expected: 0,
- },
- {
- name: "Single asset",
- arg: &AssetSetRange{
- Assets: []*AssetSet{
- {
- Assets: map[string]Asset{
- "a": &Node{
- Start: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
- End: time.Date(1970, 1, 2, 0, 0, 0, 0, time.UTC),
- },
- },
- },
- },
- },
- expected: 24 * 60,
- },
- {
- name: "Two assets",
- arg: &AssetSetRange{
- Assets: []*AssetSet{
- {
- Assets: map[string]Asset{
- "a": &Node{
- Start: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
- End: time.Date(1970, 1, 2, 0, 0, 0, 0, time.UTC),
- },
- "b": &Node{
- Start: time.Date(1970, 1, 2, 0, 0, 0, 0, time.UTC),
- End: time.Date(1970, 1, 3, 0, 0, 0, 0, time.UTC),
- },
- },
- },
- },
- },
- expected: 2 * 24 * 60,
- },
- {
- name: "Two AssetSets",
- arg: &AssetSetRange{
- Assets: []*AssetSet{
- {
- Assets: map[string]Asset{
- "a": &Node{
- Start: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
- End: time.Date(1970, 1, 2, 0, 0, 0, 0, time.UTC),
- },
- },
- },
- {
- Assets: map[string]Asset{
- "b": &Node{
- Start: time.Date(1970, 1, 2, 0, 0, 0, 0, time.UTC),
- End: time.Date(1970, 1, 3, 0, 0, 0, 0, time.UTC),
- },
- },
- },
- },
- },
- expected: 2 * 24 * 60,
- },
- }
- for _, test := range tests {
- result := test.arg.Minutes()
- if result != test.expected {
- t.Errorf("%s: expected %f but got %f", test.name, test.expected, result)
- }
- }
- }
- func TestAssetSetRange_MarshalJSON(t *testing.T) {
- tests := []struct {
- name string
- arg *AssetSetRange
- expected *AssetSetRange
- }{
- {
- name: "Nil ASR",
- arg: nil,
- },
- {
- name: "Nil AS in ASR",
- arg: NewAssetSetRange(nil),
- },
- {
- name: "Normal ASR",
- arg: &AssetSetRange{
- Assets: []*AssetSet{
- {
- Assets: map[string]Asset{
- "a": &Any{
- Start: time.Now().UTC().Truncate(day),
- },
- },
- },
- },
- },
- },
- }
- for _, test := range tests {
- bytes, err := json.Marshal(test.arg)
- if err != nil {
- t.Fatalf("ASR Marshal: test %s, unexpected error: %s", test.name, err)
- }
- var testASR []*AssetSet
- marshaled := &testASR
- err = json.Unmarshal(bytes, marshaled)
- if err != nil {
- t.Fatalf("ASR Unmarshal: test %s: unexpected error: %s", test.name, err)
- }
- if test.arg.Length() != len(testASR) {
- t.Fatalf("ASR Unmarshal: test %s: length mutated in encoding: expected %d but got %d", test.name, test.arg.Length(), len(testASR))
- }
- // asset don't unmarshal back from json
- }
- }
- func TestAssetSetRange_AccumulateBy_None(t *testing.T) {
- ago4d := time.Now().UTC().Truncate(day).Add(-4 * day)
- ago3d := time.Now().UTC().Truncate(day).Add(-3 * day)
- ago2d := time.Now().UTC().Truncate(day).Add(-2 * day)
- yesterday := time.Now().UTC().Truncate(day).Add(-day)
- today := time.Now().UTC().Truncate(day)
- ago4dAS := GenerateMockAssetSet(ago4d, day)
- ago3dAS := GenerateMockAssetSet(ago3d, day)
- ago2dAS := GenerateMockAssetSet(ago2d, day)
- yesterdayAS := GenerateMockAssetSet(yesterday, day)
- todayAS := GenerateMockAssetSet(today, day)
- asr := NewAssetSetRange(ago4dAS, ago3dAS, ago2dAS, yesterdayAS, todayAS)
- asr, err := asr.Accumulate(AccumulateOptionNone)
- if err != nil {
- t.Fatalf("unexpected error calling accumulateBy: %s", err)
- }
- if len(asr.Assets) != 5 {
- t.Fatalf("expected 5 asset sets, got:%d", len(asr.Assets))
- }
- }
- func TestAssetSetRange_AccumulateBy_All(t *testing.T) {
- ago4d := time.Now().UTC().Truncate(day).Add(-4 * day)
- ago3d := time.Now().UTC().Truncate(day).Add(-3 * day)
- ago2d := time.Now().UTC().Truncate(day).Add(-2 * day)
- yesterday := time.Now().UTC().Truncate(day).Add(-day)
- today := time.Now().UTC().Truncate(day)
- ago4dAS := GenerateMockAssetSet(ago4d, day)
- ago3dAS := GenerateMockAssetSet(ago3d, day)
- ago2dAS := GenerateMockAssetSet(ago2d, day)
- yesterdayAS := GenerateMockAssetSet(yesterday, day)
- todayAS := GenerateMockAssetSet(today, day)
- asr := NewAssetSetRange(ago4dAS, ago3dAS, ago2dAS, yesterdayAS, todayAS)
- asr, err := asr.Accumulate(AccumulateOptionAll)
- if err != nil {
- t.Fatalf("unexpected error calling accumulateBy: %s", err)
- }
- if len(asr.Assets) != 1 {
- t.Fatalf("expected 1 asset set, got:%d", len(asr.Assets))
- }
- }
- func TestAssetSetRange_AccumulateBy_Hour(t *testing.T) {
- ago4h := time.Now().UTC().Truncate(time.Hour).Add(-4 * time.Hour)
- ago3h := time.Now().UTC().Truncate(time.Hour).Add(-3 * time.Hour)
- ago2h := time.Now().UTC().Truncate(time.Hour).Add(-2 * time.Hour)
- ago1h := time.Now().UTC().Truncate(time.Hour).Add(-time.Hour)
- currentHour := time.Now().UTC().Truncate(time.Hour)
- ago4hAS := GenerateMockAssetSet(ago4h, time.Hour)
- ago3hAS := GenerateMockAssetSet(ago3h, time.Hour)
- ago2hAS := GenerateMockAssetSet(ago2h, time.Hour)
- ago1hAS := GenerateMockAssetSet(ago1h, time.Hour)
- currentHourAS := GenerateMockAssetSet(currentHour, time.Hour)
- asr := NewAssetSetRange(ago4hAS, ago3hAS, ago2hAS, ago1hAS, currentHourAS)
- asr, err := asr.Accumulate(AccumulateOptionHour)
- if err != nil {
- t.Fatalf("unexpected error calling accumulateBy: %s", err)
- }
- if len(asr.Assets) != 5 {
- t.Fatalf("expected 5 asset sets, got:%d", len(asr.Assets))
- }
- allocMap := asr.Assets[0].Assets
- alloc := allocMap["__undefined__/__undefined__/__undefined__/Storage/cluster2/Disk/Kubernetes/gcp-disk4/disk4"]
- if alloc.Minutes() != 60.0 {
- t.Errorf("accumulating asset set range: expected %f minutes; actual %f", 60.0, alloc.Minutes())
- }
- }
- func TestAssetSetRange_AccumulateBy_Day_From_Day(t *testing.T) {
- ago4d := time.Now().UTC().Truncate(day).Add(-4 * day)
- ago3d := time.Now().UTC().Truncate(day).Add(-3 * day)
- ago2d := time.Now().UTC().Truncate(day).Add(-2 * day)
- yesterday := time.Now().UTC().Truncate(day).Add(-day)
- today := time.Now().UTC().Truncate(day)
- ago4dAS := GenerateMockAssetSet(ago4d, day)
- ago3dAS := GenerateMockAssetSet(ago3d, day)
- ago2dAS := GenerateMockAssetSet(ago2d, day)
- yesterdayAS := GenerateMockAssetSet(yesterday, day)
- todayAS := GenerateMockAssetSet(today, day)
- asr := NewAssetSetRange(ago4dAS, ago3dAS, ago2dAS, yesterdayAS, todayAS)
- asr, err := asr.Accumulate(AccumulateOptionDay)
- if err != nil {
- t.Fatalf("unexpected error calling accumulateBy: %s", err)
- }
- if len(asr.Assets) != 5 {
- t.Fatalf("expected 5 asset sets, got:%d", len(asr.Assets))
- }
- allocMap := asr.Assets[0].Assets
- alloc := allocMap["__undefined__/__undefined__/__undefined__/Storage/cluster2/Disk/Kubernetes/gcp-disk4/disk4"]
- if alloc.Minutes() != 1440.0 {
- t.Errorf("accumulating asset set range: expected %f minutes; actual %f", 1440.0, alloc.Minutes())
- }
- }
- func TestAssetSetRange_AccumulateBy_Day_From_Hours(t *testing.T) {
- ago4h := time.Now().UTC().Truncate(time.Hour).Add(-4 * time.Hour)
- ago3h := time.Now().UTC().Truncate(time.Hour).Add(-3 * time.Hour)
- ago2h := time.Now().UTC().Truncate(time.Hour).Add(-2 * time.Hour)
- ago1h := time.Now().UTC().Truncate(time.Hour).Add(-time.Hour)
- currentHour := time.Now().UTC().Truncate(time.Hour)
- ago4hAS := GenerateMockAssetSet(ago4h, time.Hour)
- ago3hAS := GenerateMockAssetSet(ago3h, time.Hour)
- ago2hAS := GenerateMockAssetSet(ago2h, time.Hour)
- ago1hAS := GenerateMockAssetSet(ago1h, time.Hour)
- currentHourAS := GenerateMockAssetSet(currentHour, time.Hour)
- asr := NewAssetSetRange(ago4hAS, ago3hAS, ago2hAS, ago1hAS, currentHourAS)
- asr, err := asr.Accumulate(AccumulateOptionDay)
- if err != nil {
- t.Fatalf("unexpected error calling accumulateBy: %s", err)
- }
- if len(asr.Assets) != 1 && len(asr.Assets) != 2 {
- t.Fatalf("expected 1 allocation set, got:%d", len(asr.Assets))
- }
- allocMap := asr.Assets[0].Assets
- alloc := allocMap["__undefined__/__undefined__/__undefined__/Storage/cluster2/Disk/Kubernetes/gcp-disk4/disk4"]
- if alloc.Minutes() > 300.0 {
- t.Errorf("accumulating AllocationSetRange: expected %f or less minutes; actual %f", 300.0, alloc.Minutes())
- }
- }
- func TestAssetSetRange_AccumulateBy_Week(t *testing.T) {
- ago9d := time.Now().UTC().Truncate(day).Add(-9 * day)
- ago8d := time.Now().UTC().Truncate(day).Add(-8 * day)
- ago7d := time.Now().UTC().Truncate(day).Add(-7 * day)
- ago6d := time.Now().UTC().Truncate(day).Add(-6 * day)
- ago5d := time.Now().UTC().Truncate(day).Add(-5 * day)
- ago4d := time.Now().UTC().Truncate(day).Add(-4 * day)
- ago3d := time.Now().UTC().Truncate(day).Add(-3 * day)
- ago2d := time.Now().UTC().Truncate(day).Add(-2 * day)
- yesterday := time.Now().UTC().Truncate(day).Add(-day)
- today := time.Now().UTC().Truncate(day)
- ago9dAS := GenerateMockAssetSet(ago9d, day)
- ago8dAS := GenerateMockAssetSet(ago8d, day)
- ago7dAS := GenerateMockAssetSet(ago7d, day)
- ago6dAS := GenerateMockAssetSet(ago6d, day)
- ago5dAS := GenerateMockAssetSet(ago5d, day)
- ago4dAS := GenerateMockAssetSet(ago4d, day)
- ago3dAS := GenerateMockAssetSet(ago3d, day)
- ago2dAS := GenerateMockAssetSet(ago2d, day)
- yesterdayAS := GenerateMockAssetSet(yesterday, day)
- todayAS := GenerateMockAssetSet(today, day)
- asr := NewAssetSetRange(ago9dAS, ago8dAS, ago7dAS, ago6dAS, ago5dAS, ago4dAS, ago3dAS, ago2dAS, yesterdayAS, todayAS)
- asr, err := asr.Accumulate(AccumulateOptionWeek)
- if err != nil {
- t.Fatalf("unexpected error calling accumulateBy: %s", err)
- }
- if len(asr.Assets) != 2 && len(asr.Assets) != 3 {
- t.Fatalf("expected 2 or 3 asset sets, got:%d", len(asr.Assets))
- }
- for _, as := range asr.Assets {
- if as.Window.Duration() < time.Hour*24 || as.Window.Duration() > time.Hour*24*7 {
- t.Fatalf("expected window duration to be between 1 and 7 days, got:%s", as.Window.Duration().String())
- }
- }
- }
- func TestAssetSetRange_AccumulateBy_Month(t *testing.T) {
- prevMonth1stDay := time.Date(2020, 01, 29, 0, 0, 0, 0, time.UTC)
- prevMonth2ndDay := time.Date(2020, 01, 30, 0, 0, 0, 0, time.UTC)
- prevMonth3ndDay := time.Date(2020, 01, 31, 0, 0, 0, 0, time.UTC)
- nextMonth1stDay := time.Date(2020, 02, 01, 0, 0, 0, 0, time.UTC)
- prev1AS := GenerateMockAssetSet(prevMonth1stDay, day)
- prev2AS := GenerateMockAssetSet(prevMonth2ndDay, day)
- prev3AS := GenerateMockAssetSet(prevMonth3ndDay, day)
- nextAS := GenerateMockAssetSet(nextMonth1stDay, day)
- asr := NewAssetSetRange(prev1AS, prev2AS, prev3AS, nextAS)
- asr, err := asr.Accumulate(AccumulateOptionMonth)
- if err != nil {
- t.Fatalf("unexpected error calling accumulateBy: %s", err)
- }
- if len(asr.Assets) != 2 {
- t.Fatalf("expected 2 assets sets, got:%d", len(asr.Assets))
- }
- for _, as := range asr.Assets {
- if as.Window.Duration() < time.Hour*24 || as.Window.Duration() > time.Hour*24*31 {
- t.Fatalf("expected window duration to be between 1 and 31 days, got:%s", as.Window.Duration().String())
- }
- }
- }
- func TestAny_SanitizeNaN(t *testing.T) {
- any := getMockAny(math.NaN())
- any.SanitizeNaN()
- v := reflect.ValueOf(any)
- checkAllFloat64sForNaN(t, v, "TestAny_SanitizeNaN")
- }
- func getMockAny(f float64) Any {
- return Any{
- Adjustment: f,
- Cost: f,
- }
- }
- func TestCloud_SanitizeNaN(t *testing.T) {
- cloud := getMockCloud(math.NaN())
- cloud.SanitizeNaN()
- v := reflect.ValueOf(cloud)
- checkAllFloat64sForNaN(t, v, "TestCloud_SanitizeNaN")
- }
- func getMockCloud(f float64) Cloud {
- return Cloud{
- Adjustment: f,
- Cost: f,
- Credit: f,
- }
- }
- func TestClusterManagement_SanitizeNaN(t *testing.T) {
- cm := getMockClusterManagement(math.NaN())
- cm.SanitizeNaN()
- v := reflect.ValueOf(cm)
- checkAllFloat64sForNaN(t, v, "TestClusterManagement_SanitizeNaN")
- }
- func getMockClusterManagement(f float64) ClusterManagement {
- return ClusterManagement{
- Cost: f,
- Adjustment: f,
- }
- }
- func TestDisk_SanitizeNaN(t *testing.T) {
- disk := getMockDisk(math.NaN())
- disk.SanitizeNaN()
- v := reflect.ValueOf(disk)
- checkAllFloat64sForNaN(t, v, "TestDisk_SanitizeNaN")
- vBreakdown := reflect.ValueOf(*disk.Breakdown)
- checkAllFloat64sForNaN(t, vBreakdown, "TestDisk_SanitizeNaN")
- }
- func getMockDisk(f float64) Disk {
- bhu := f
- bum := f
- breakdown := getMockBreakdown(f)
- return Disk{
- Adjustment: f,
- Cost: f,
- ByteHours: f,
- Local: f,
- Breakdown: &breakdown,
- ByteHoursUsed: &bhu,
- ByteUsageMax: &bum,
- }
- }
- func TestBreakdown_SanitizeNaN(t *testing.T) {
- b := getMockBreakdown(math.NaN())
- b.SanitizeNaN()
- v := reflect.ValueOf(b)
- checkAllFloat64sForNaN(t, v, "TestBreakdown_SanitizeNaN")
- }
- func getMockBreakdown(f float64) Breakdown {
- return Breakdown{
- Idle: f,
- Other: f,
- System: f,
- User: f,
- }
- }
- func TestNetwork_SanitizeNaN(t *testing.T) {
- n := getMockNetwork(math.NaN())
- n.SanitizeNaN()
- v := reflect.ValueOf(n)
- checkAllFloat64sForNaN(t, v, "TestNetwork_SanitizeNaN")
- }
- func getMockNetwork(f float64) Network {
- return Network{
- Adjustment: f,
- Cost: f,
- }
- }
- func TestNodeOverhead_SanitizeNaN(t *testing.T) {
- n := getMockNodeOverhead(math.NaN())
- n.SanitizeNaN()
- v := reflect.ValueOf(n)
- checkAllFloat64sForNaN(t, v, "TestNodeOverhead_SanitizeNaN")
- }
- func getMockNodeOverhead(f float64) NodeOverhead {
- return NodeOverhead{
- CpuOverheadFraction: f,
- RamOverheadFraction: f,
- OverheadCostFraction: f,
- }
- }
- func TestNode_SanitizeNaN(t *testing.T) {
- n := getMockNode(math.NaN())
- n.SanitizeNaN()
- v := reflect.ValueOf(n)
- checkAllFloat64sForNaN(t, v, "TestNode_SanitizeNaN")
- vCpu := reflect.ValueOf(*n.CPUBreakdown)
- checkAllFloat64sForNaN(t, vCpu, "TestNode_SanitizeNaN")
- vRam := reflect.ValueOf(*n.RAMBreakdown)
- checkAllFloat64sForNaN(t, vRam, "TestNode_SanitizeNaN")
- vOverhead := reflect.ValueOf(*n.Overhead)
- checkAllFloat64sForNaN(t, vOverhead, "TestNode_SanitizeNaN")
- }
- func getMockNode(f float64) Node {
- cpuBreakdown := getMockBreakdown(f)
- ramBreakdown := getMockBreakdown(f)
- overhead := getMockNodeOverhead(f)
- return Node{
- Adjustment: f,
- CPUCoreHours: f,
- RAMByteHours: f,
- GPUHours: f,
- CPUBreakdown: &cpuBreakdown,
- RAMBreakdown: &ramBreakdown,
- CPUCost: f,
- GPUCost: f,
- GPUCount: f,
- RAMCost: f,
- Discount: f,
- Preemptible: f,
- Overhead: &overhead,
- }
- }
- func TestLoadBalancer_SanitizeNaN(t *testing.T) {
- lb := getMockLoadBalancer(math.NaN())
- lb.SanitizeNaN()
- v := reflect.ValueOf(lb)
- checkAllFloat64sForNaN(t, v, "TestLoadBalancer_SanitizeNaN")
- }
- func getMockLoadBalancer(f float64) LoadBalancer {
- return LoadBalancer{
- Adjustment: f,
- Cost: f,
- }
- }
- func TestSharedAsset_SanitizeNaN(t *testing.T) {
- sa := getMockSharedAsset(math.NaN())
- sa.SanitizeNaN()
- v := reflect.ValueOf(sa)
- checkAllFloat64sForNaN(t, v, "TestSharedAsset_SanitizeNaN")
- }
- func getMockSharedAsset(f float64) SharedAsset {
- return SharedAsset{
- Cost: f,
- }
- }
- func TestAssetSet_SanitizeNaN(t *testing.T) {
- testCaseName := "TestAssetSet_SanitizeNaN"
- as := getMockAssetSet(math.NaN())
- as.SanitizeNaN()
- v := reflect.ValueOf(as)
- checkAllFloat64sForNaN(t, v, testCaseName)
- for _, a := range as.Assets {
- if math.IsNaN(a.TotalCost()) {
- t.Fatalf("TestAssetSet_SanitizeNaN: Asset: expected not NaN for TotalCost(): expected NaN, got:%f", a.TotalCost())
- }
- if math.IsNaN(a.GetAdjustment()) {
- t.Fatalf("TestAssetSet_SanitizeNaN: Asset: expected not NaN for GetAdjustment(): expected NaN, got:%f", a.GetAdjustment())
- }
- }
- for _, any := range as.Any {
- vAny := reflect.ValueOf(*any)
- checkAllFloat64sForNaN(t, vAny, testCaseName)
- }
- for _, cloud := range as.Cloud {
- vCloud := reflect.ValueOf(*cloud)
- checkAllFloat64sForNaN(t, vCloud, testCaseName)
- }
- for _, cm := range as.ClusterManagement {
- vCM := reflect.ValueOf(*cm)
- checkAllFloat64sForNaN(t, vCM, testCaseName)
- }
- for _, disk := range as.Disks {
- vDisk := reflect.ValueOf(*disk)
- checkAllFloat64sForNaN(t, vDisk, testCaseName)
- }
- for _, network := range as.Network {
- vNetwork := reflect.ValueOf(*network)
- checkAllFloat64sForNaN(t, vNetwork, testCaseName)
- }
- for _, node := range as.Nodes {
- vNode := reflect.ValueOf(*node)
- checkAllFloat64sForNaN(t, vNode, testCaseName)
- }
- for _, sa := range as.SharedAssets {
- vSA := reflect.ValueOf(*sa)
- checkAllFloat64sForNaN(t, vSA, testCaseName)
- }
- }
- func getMockAssetSet(f float64) AssetSet {
- any := getMockAny(f)
- cloud := getMockCloud(f)
- cm := getMockClusterManagement(f)
- disk := getMockDisk(f)
- network := getMockNetwork(f)
- node := getMockNode(f)
- lb := getMockLoadBalancer(f)
- sa := getMockSharedAsset(f)
- assets := map[string]Asset{"any": &any, "cloud": &cloud}
- as := AssetSet{
- Assets: assets,
- Any: map[string]*Any{"NaN": &any},
- Cloud: map[string]*Cloud{"NaN": &cloud},
- ClusterManagement: map[string]*ClusterManagement{"NaN": &cm},
- Disks: map[string]*Disk{"NaN": &disk},
- Network: map[string]*Network{"NaN": &network},
- Nodes: map[string]*Node{"NaN": &node},
- LoadBalancers: map[string]*LoadBalancer{"NaN": &lb},
- SharedAssets: map[string]*SharedAsset{"NaN": &sa},
- }
- return as
- }
|