Ver código fonte

Update pkg Kubecost types (#1354)

Signed-off-by: Matt Bolt <mbolt35@gmail.com>
Matt Bolt 3 anos atrás
pai
commit
d2f7b5855a

+ 1 - 1
go.mod

@@ -40,6 +40,7 @@ require (
 	github.com/prometheus/common v0.32.1
 	github.com/rs/cors v1.7.0
 	github.com/rs/zerolog v1.26.1
+	github.com/scaleway/scaleway-sdk-go v1.0.0-beta.9
 	github.com/spf13/cobra v1.2.1
 	github.com/spf13/viper v1.8.1
 	go.etcd.io/bbolt v1.3.5
@@ -110,7 +111,6 @@ require (
 	github.com/pelletier/go-toml v1.9.3 // indirect
 	github.com/prometheus/procfs v0.7.3 // indirect
 	github.com/rs/xid v1.3.0 // indirect
-	github.com/scaleway/scaleway-sdk-go v1.0.0-beta.9 // indirect
 	github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24 // indirect
 	github.com/sirupsen/logrus v1.8.1 // indirect
 	github.com/spf13/afero v1.6.0 // indirect

+ 1 - 0
go.sum

@@ -173,6 +173,7 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
 github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
 github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U=
 github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
+github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
 github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
 github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
 github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=

+ 12 - 12
pkg/costmodel/allocation.go

@@ -137,8 +137,8 @@ func (cm *CostModel) ComputeAllocation(start, end time.Time, resolution time.Dur
 	errors := []string{}
 	warnings := []string{}
 
-	asr.Each(func(i int, as *kubecost.AllocationSet) {
-		as.Each(func(k string, a *kubecost.Allocation) {
+	for _, as := range asr.Allocations {
+		for k, a := range as.Allocations {
 			if len(a.Properties.Annotations) > 0 {
 				if _, ok := allocationAnnotations[k]; !ok {
 					allocationAnnotations[k] = map[string]string{}
@@ -165,11 +165,11 @@ func (cm *CostModel) ComputeAllocation(start, end time.Time, resolution time.Dur
 					allocationServices[k][val] = true
 				}
 			}
-		})
+		}
 
 		errors = append(errors, as.Errors...)
 		warnings = append(warnings, as.Warnings...)
-	})
+	}
 
 	// Accumulate to yield the result AllocationSet. After this step, we will
 	// be nearly complete, but without the raw allocation data, which must be
@@ -181,7 +181,7 @@ func (cm *CostModel) ComputeAllocation(start, end time.Time, resolution time.Dur
 
 	// Apply the annotations, labels, and services to the post-accumulation
 	// results. (See above for why this is necessary.)
-	result.Each(func(k string, a *kubecost.Allocation) {
+	for k, a := range result.Allocations {
 		if annotations, ok := allocationAnnotations[k]; ok {
 			a.Properties.Annotations = annotations
 		}
@@ -201,15 +201,15 @@ func (cm *CostModel) ComputeAllocation(start, end time.Time, resolution time.Dur
 		// to match the Window of the AllocationSet, which gets expanded
 		// at the end of this function.
 		a.Window = a.Window.ExpandStart(start).ExpandEnd(end)
-	})
+	}
 
 	// Maintain RAM and CPU max usage values by iterating over the range,
 	// computing maximums on a rolling basis, and setting on the result set.
-	asr.Each(func(i int, as *kubecost.AllocationSet) {
-		as.Each(func(key string, alloc *kubecost.Allocation) {
+	for _, as := range asr.Allocations {
+		for key, alloc := range as.Allocations {
 			resultAlloc := result.Get(key)
 			if resultAlloc == nil {
-				return
+				continue
 			}
 
 			if resultAlloc.RawAllocationOnly == nil {
@@ -222,7 +222,7 @@ func (cm *CostModel) ComputeAllocation(start, end time.Time, resolution time.Dur
 				if !alloc.IsUnmounted() {
 					log.DedupedWarningf(10, "ComputeAllocation: raw allocation data missing for %s", key)
 				}
-				return
+				continue
 			}
 
 			if alloc.RawAllocationOnly.CPUCoreUsageMax > resultAlloc.RawAllocationOnly.CPUCoreUsageMax {
@@ -232,8 +232,8 @@ func (cm *CostModel) ComputeAllocation(start, end time.Time, resolution time.Dur
 			if alloc.RawAllocationOnly.RAMBytesUsageMax > resultAlloc.RawAllocationOnly.RAMBytesUsageMax {
 				resultAlloc.RawAllocationOnly.RAMBytesUsageMax = alloc.RawAllocationOnly.RAMBytesUsageMax
 			}
-		})
-	})
+		}
+	}
 
 	// Expand the window to match the queried time range.
 	result.Window = result.Window.ExpandStart(start).ExpandEnd(end)

Diferenças do arquivo suprimidas por serem muito extensas
+ 253 - 264
pkg/kubecost/allocation.go


+ 2 - 6
pkg/kubecost/allocation_json.go

@@ -97,9 +97,7 @@ func (as *AllocationSet) MarshalJSON() ([]byte, error) {
 	if as == nil {
 		return json.Marshal(map[string]*Allocation{})
 	}
-	as.RLock()
-	defer as.RUnlock()
-	return json.Marshal(as.allocations)
+	return json.Marshal(as.Allocations)
 }
 
 // MarshalJSON JSON-encodes the range
@@ -108,7 +106,5 @@ func (asr *AllocationSetRange) MarshalJSON() ([]byte, error) {
 		return json.Marshal([]*AllocationSet{})
 	}
 
-	asr.RLock()
-	defer asr.RUnlock()
-	return json.Marshal(asr.allocations)
+	return json.Marshal(asr.Allocations)
 }

+ 47 - 47
pkg/kubecost/allocation_test.go

@@ -510,7 +510,7 @@ func assertAllocationSetTotals(t *testing.T, as *AllocationSet, msg string, err
 }
 
 func assertAllocationTotals(t *testing.T, as *AllocationSet, msg string, exps map[string]float64) {
-	as.Each(func(k string, a *Allocation) {
+	for _, a := range as.Allocations {
 		if exp, ok := exps[a.Name]; ok {
 			if math.Round(a.TotalCost()*100) != math.Round(exp*100) {
 				t.Fatalf("AllocationSet.AggregateBy[%s]: expected total cost %f, actual %f", msg, exp, a.TotalCost())
@@ -518,11 +518,11 @@ func assertAllocationTotals(t *testing.T, as *AllocationSet, msg string, exps ma
 		} else {
 			t.Fatalf("AllocationSet.AggregateBy[%s]: unexpected allocation: %s", msg, a.Name)
 		}
-	})
+	}
 }
 
 func assertAllocationWindow(t *testing.T, as *AllocationSet, msg string, expStart, expEnd time.Time, expMinutes float64) {
-	as.Each(func(k string, a *Allocation) {
+	for _, a := range as.Allocations {
 		if !a.Start.Equal(expStart) {
 			t.Fatalf("AllocationSet.AggregateBy[%s]: expected start %s, actual %s", msg, expStart, a.Start)
 		}
@@ -532,14 +532,14 @@ func assertAllocationWindow(t *testing.T, as *AllocationSet, msg string, expStar
 		if a.Minutes() != expMinutes {
 			t.Fatalf("AllocationSet.AggregateBy[%s]: expected minutes %f, actual %f", msg, expMinutes, a.Minutes())
 		}
-	})
+	}
 }
 
 func printAllocationSet(msg string, as *AllocationSet) {
 	fmt.Printf("--- %s ---\n", msg)
-	as.Each(func(k string, a *Allocation) {
+	for _, a := range as.Allocations {
 		fmt.Printf(" > %s\n", a)
-	})
+	}
 }
 
 func TestAllocationSet_AggregateBy(t *testing.T) {
@@ -1567,21 +1567,21 @@ func TestAllocationSet_insertMatchingWindow(t *testing.T) {
 	}
 
 	as := NewAllocationSet(setStart, setEnd)
-	as.insert(a1)
-	as.insert(a2)
+	as.Insert(a1)
+	as.Insert(a2)
 
 	if as.Length() != 2 {
 		t.Errorf("AS length got %d, expected %d", as.Length(), 2)
 	}
 
-	as.Each(func(k string, a *Allocation) {
+	for _, a := range as.Allocations {
 		if !(*a.Window.Start()).Equal(setStart) {
 			t.Errorf("Allocation %s window start is %s, expected %s", a.Name, *a.Window.Start(), setStart)
 		}
 		if !(*a.Window.End()).Equal(setEnd) {
 			t.Errorf("Allocation %s window end is %s, expected %s", a.Name, *a.Window.End(), setEnd)
 		}
-	})
+	}
 }
 
 // TODO niko/etl
@@ -1704,7 +1704,7 @@ func TestAllocationSetRange_Accumulate(t *testing.T) {
 	if result.TotalCost() != 12.0 {
 		t.Fatalf("accumulating AllocationSetRange: expected total cost 12.0; actual %f", result.TotalCost())
 	}
-	allocMap := result.Map()
+	allocMap := result.Allocations
 	if len(allocMap) != 1 {
 		t.Fatalf("accumulating AllocationSetRange: expected length 1; actual length %d", len(allocMap))
 	}
@@ -1802,7 +1802,7 @@ func TestAllocationSetRange_AccumulateBy_Nils(t *testing.T) {
 
 	for _, c := range nilEmptycases {
 		result, err = c.asr.AccumulateBy(c.resolution)
-		for _, as := range result.allocations {
+		for _, as := range result.Allocations {
 			if !as.IsEmpty() {
 				t.Errorf("accumulating nil AllocationSetRange: expected empty; actual %s; TestId: %s", result, c.testId)
 			}
@@ -1855,7 +1855,7 @@ func TestAllocationSetRange_AccumulateBy_Nils(t *testing.T) {
 			t.Errorf("accumulating AllocationSetRange: expected AllocationSet; actual %s; TestId: %s", result, c.testId)
 		}
 
-		for _, as := range result.allocations {
+		for _, as := range result.Allocations {
 			sumCost += as.TotalCost()
 		}
 
@@ -2024,7 +2024,7 @@ func TestAllocationSetRange_AccumulateBy(t *testing.T) {
 			t.Errorf("accumulating AllocationSetRange: expected %v number of allocation sets; actual %v; TestId: %s", c.expectedSets, result.Length(), c.testId)
 		}
 
-		for _, as := range result.allocations {
+		for _, as := range result.Allocations {
 			sumCost += as.TotalCost()
 		}
 		if sumCost != c.expectedCost {
@@ -2046,11 +2046,11 @@ func TestAllocationSetRange_AccumulateBy(t *testing.T) {
 	}
 
 	sumCost = 0.0
-	for _, as := range result.allocations {
+	for _, as := range result.Allocations {
 		sumCost += as.TotalCost()
 	}
 
-	allocMap := result.allocations[0].Map()
+	allocMap := result.Allocations[0].Allocations
 	if len(allocMap) != 1 {
 		t.Errorf("accumulating AllocationSetRange: expected length 1; actual length %d", len(allocMap))
 	}
@@ -2164,8 +2164,8 @@ func TestAllocationSetRange_InsertRange(t *testing.T) {
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
-	thisASR.Each(func(i int, as *AllocationSet) {
-		as.Each(func(k string, a *Allocation) {
+	for _, as := range thisASR.Allocations {
+		for k, a := range as.Allocations {
 			if !util.IsApproximately(a.CPUCoreHours, unit.CPUCoreHours) {
 				t.Fatalf("allocation %s: expected %f; got %f", k, unit.CPUCoreHours, a.CPUCoreHours)
 			}
@@ -2199,8 +2199,8 @@ func TestAllocationSetRange_InsertRange(t *testing.T) {
 			if !util.IsApproximately(a.TotalCost(), unit.TotalCost()) {
 				t.Fatalf("allocation %s: expected %f; got %f", k, unit.TotalCost(), a.TotalCost())
 			}
-		})
-	})
+		}
+	}
 
 	// Expect an error calling InsertRange with a range exceeding the receiver
 	err = thisASR.InsertRange(longASR)
@@ -2216,7 +2216,7 @@ func TestAllocationSetRange_InsertRange(t *testing.T) {
 		t.Fatalf("unexpected error: %s", err)
 	}
 	yAS, err := thisASR.Get(0)
-	yAS.Each(func(k string, a *Allocation) {
+	for k, a := range yAS.Allocations {
 		if !util.IsApproximately(a.CPUCoreHours, 2*unit.CPUCoreHours) {
 			t.Fatalf("allocation %s: expected %f; got %f", k, unit.CPUCoreHours, a.CPUCoreHours)
 		}
@@ -2251,9 +2251,9 @@ func TestAllocationSetRange_InsertRange(t *testing.T) {
 		if !util.IsApproximately(a.TotalCost(), 2*unit.TotalCost()) {
 			t.Fatalf("allocation %s: expected %f; got %f", k, unit.TotalCost(), a.TotalCost())
 		}
-	})
+	}
 	tAS, err := thisASR.Get(1)
-	tAS.Each(func(k string, a *Allocation) {
+	for k, a := range tAS.Allocations {
 		if !util.IsApproximately(a.CPUCoreHours, unit.CPUCoreHours) {
 			t.Fatalf("allocation %s: expected %f; got %f", k, unit.CPUCoreHours, a.CPUCoreHours)
 		}
@@ -2287,7 +2287,7 @@ func TestAllocationSetRange_InsertRange(t *testing.T) {
 		if !util.IsApproximately(a.TotalCost(), unit.TotalCost()) {
 			t.Fatalf("allocation %s: expected %f; got %f", k, unit.TotalCost(), a.TotalCost())
 		}
-	})
+	}
 }
 
 // TODO niko/etl
@@ -2311,9 +2311,9 @@ func TestAllocationSetRange_MarshalJSON(t *testing.T) {
 		{
 			name: "Normal ASR",
 			arg: &AllocationSetRange{
-				allocations: []*AllocationSet{
+				Allocations: []*AllocationSet{
 					{
-						allocations: map[string]*Allocation{
+						Allocations: map[string]*Allocation{
 							"a": {
 								Start: time.Now().UTC().Truncate(day),
 							},
@@ -2371,9 +2371,9 @@ func TestAllocationSetRange_Start(t *testing.T) {
 		{
 			name: "Single allocation",
 			arg: &AllocationSetRange{
-				allocations: []*AllocationSet{
+				Allocations: []*AllocationSet{
 					{
-						allocations: map[string]*Allocation{
+						Allocations: map[string]*Allocation{
 							"a": {
 								Start: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
 							},
@@ -2387,9 +2387,9 @@ func TestAllocationSetRange_Start(t *testing.T) {
 		{
 			name: "Two allocations",
 			arg: &AllocationSetRange{
-				allocations: []*AllocationSet{
+				Allocations: []*AllocationSet{
 					{
-						allocations: map[string]*Allocation{
+						Allocations: map[string]*Allocation{
 							"a": {
 								Start: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
 							},
@@ -2406,16 +2406,16 @@ func TestAllocationSetRange_Start(t *testing.T) {
 		{
 			name: "Two AllocationSets",
 			arg: &AllocationSetRange{
-				allocations: []*AllocationSet{
+				Allocations: []*AllocationSet{
 					{
-						allocations: map[string]*Allocation{
+						Allocations: map[string]*Allocation{
 							"a": {
 								Start: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
 							},
 						},
 					},
 					{
-						allocations: map[string]*Allocation{
+						Allocations: map[string]*Allocation{
 							"b": {
 								Start: time.Date(1970, 1, 2, 0, 0, 0, 0, time.UTC),
 							},
@@ -2459,9 +2459,9 @@ func TestAllocationSetRange_End(t *testing.T) {
 		{
 			name: "Single allocation",
 			arg: &AllocationSetRange{
-				allocations: []*AllocationSet{
+				Allocations: []*AllocationSet{
 					{
-						allocations: map[string]*Allocation{
+						Allocations: map[string]*Allocation{
 							"a": {
 								End: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
 							},
@@ -2475,9 +2475,9 @@ func TestAllocationSetRange_End(t *testing.T) {
 		{
 			name: "Two allocations",
 			arg: &AllocationSetRange{
-				allocations: []*AllocationSet{
+				Allocations: []*AllocationSet{
 					{
-						allocations: map[string]*Allocation{
+						Allocations: map[string]*Allocation{
 							"a": {
 								End: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
 							},
@@ -2494,16 +2494,16 @@ func TestAllocationSetRange_End(t *testing.T) {
 		{
 			name: "Two AllocationSets",
 			arg: &AllocationSetRange{
-				allocations: []*AllocationSet{
+				Allocations: []*AllocationSet{
 					{
-						allocations: map[string]*Allocation{
+						Allocations: map[string]*Allocation{
 							"a": {
 								End: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
 							},
 						},
 					},
 					{
-						allocations: map[string]*Allocation{
+						Allocations: map[string]*Allocation{
 							"b": {
 								End: time.Date(1970, 1, 2, 0, 0, 0, 0, time.UTC),
 							},
@@ -2546,9 +2546,9 @@ func TestAllocationSetRange_Minutes(t *testing.T) {
 		{
 			name: "Single allocation",
 			arg: &AllocationSetRange{
-				allocations: []*AllocationSet{
+				Allocations: []*AllocationSet{
 					{
-						allocations: map[string]*Allocation{
+						Allocations: map[string]*Allocation{
 							"a": {
 								Start: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
 								End:   time.Date(1970, 1, 2, 0, 0, 0, 0, time.UTC),
@@ -2563,9 +2563,9 @@ func TestAllocationSetRange_Minutes(t *testing.T) {
 		{
 			name: "Two allocations",
 			arg: &AllocationSetRange{
-				allocations: []*AllocationSet{
+				Allocations: []*AllocationSet{
 					{
-						allocations: map[string]*Allocation{
+						Allocations: map[string]*Allocation{
 							"a": {
 								Start: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
 								End:   time.Date(1970, 1, 2, 0, 0, 0, 0, time.UTC),
@@ -2584,9 +2584,9 @@ func TestAllocationSetRange_Minutes(t *testing.T) {
 		{
 			name: "Two AllocationSets",
 			arg: &AllocationSetRange{
-				allocations: []*AllocationSet{
+				Allocations: []*AllocationSet{
 					{
-						allocations: map[string]*Allocation{
+						Allocations: map[string]*Allocation{
 							"a": {
 								Start: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
 								End:   time.Date(1970, 1, 2, 0, 0, 0, 0, time.UTC),
@@ -2594,7 +2594,7 @@ func TestAllocationSetRange_Minutes(t *testing.T) {
 						},
 					},
 					{
-						allocations: map[string]*Allocation{
+						Allocations: map[string]*Allocation{
 							"b": {
 								Start: time.Date(1970, 1, 2, 0, 0, 0, 0, time.UTC),
 								End:   time.Date(1970, 1, 3, 0, 0, 0, 0, time.UTC),

Diferenças do arquivo suprimidas por serem muito extensas
+ 268 - 255
pkg/kubecost/asset.go


+ 95 - 98
pkg/kubecost/asset_json.go

@@ -16,13 +16,13 @@ import (
 // MarshalJSON implements json.Marshaler
 func (a *Any) MarshalJSON() ([]byte, error) {
 	buffer := bytes.NewBufferString("{")
-	jsonEncode(buffer, "properties", a.Properties(), ",")
-	jsonEncode(buffer, "labels", a.Labels(), ",")
-	jsonEncode(buffer, "window", a.Window(), ",")
-	jsonEncodeString(buffer, "start", a.Start().Format(time.RFC3339), ",")
-	jsonEncodeString(buffer, "end", a.End().Format(time.RFC3339), ",")
+	jsonEncode(buffer, "properties", a.Properties, ",")
+	jsonEncode(buffer, "labels", a.Labels, ",")
+	jsonEncode(buffer, "window", a.Window, ",")
+	jsonEncodeString(buffer, "start", a.Start.Format(time.RFC3339), ",")
+	jsonEncodeString(buffer, "end", a.End.Format(time.RFC3339), ",")
 	jsonEncodeFloat64(buffer, "minutes", a.Minutes(), ",")
-	jsonEncodeFloat64(buffer, "adjustment", a.Adjustment(), ",")
+	jsonEncodeFloat64(buffer, "adjustment", a.Adjustment, ",")
 	jsonEncodeFloat64(buffer, "totalCost", a.TotalCost(), "")
 	buffer.WriteString("}")
 	return buffer.Bytes(), nil
@@ -70,20 +70,20 @@ func (a *Any) InterfaceToAny(itf interface{}) error {
 		return err
 	}
 
-	a.properties = &properties
-	a.labels = labels
-	a.start = start
-	a.end = end
-	a.window = Window{
+	a.Properties = &properties
+	a.Labels = labels
+	a.Start = start
+	a.End = end
+	a.Window = Window{
 		start: &start,
 		end:   &end,
 	}
 
 	if adjustment, err := getTypedVal(fmap["adjustment"]); err == nil {
-		a.adjustment = adjustment.(float64)
+		a.Adjustment = adjustment.(float64)
 	}
 	if Cost, err := getTypedVal(fmap["totalCost"]); err == nil {
-		a.Cost = Cost.(float64) - a.adjustment
+		a.Cost = Cost.(float64) - a.Adjustment
 	}
 
 	return nil
@@ -95,13 +95,13 @@ func (a *Any) InterfaceToAny(itf interface{}) error {
 func (ca *Cloud) MarshalJSON() ([]byte, error) {
 	buffer := bytes.NewBufferString("{")
 	jsonEncodeString(buffer, "type", ca.Type().String(), ",")
-	jsonEncode(buffer, "properties", ca.Properties(), ",")
-	jsonEncode(buffer, "labels", ca.Labels(), ",")
-	jsonEncode(buffer, "window", ca.Window(), ",")
-	jsonEncodeString(buffer, "start", ca.Start().Format(time.RFC3339), ",")
-	jsonEncodeString(buffer, "end", ca.End().Format(time.RFC3339), ",")
+	jsonEncode(buffer, "properties", ca.Properties, ",")
+	jsonEncode(buffer, "labels", ca.Labels, ",")
+	jsonEncode(buffer, "window", ca.Window, ",")
+	jsonEncodeString(buffer, "start", ca.Start.Format(time.RFC3339), ",")
+	jsonEncodeString(buffer, "end", ca.End.Format(time.RFC3339), ",")
 	jsonEncodeFloat64(buffer, "minutes", ca.Minutes(), ",")
-	jsonEncodeFloat64(buffer, "adjustment", ca.Adjustment(), ",")
+	jsonEncodeFloat64(buffer, "adjustment", ca.Adjustment, ",")
 	jsonEncodeFloat64(buffer, "credit", ca.Credit, ",")
 	jsonEncodeFloat64(buffer, "totalCost", ca.TotalCost(), "")
 	buffer.WriteString("}")
@@ -150,23 +150,23 @@ func (ca *Cloud) InterfaceToCloud(itf interface{}) error {
 		return err
 	}
 
-	ca.properties = &properties
-	ca.labels = labels
-	ca.start = start
-	ca.end = end
-	ca.window = Window{
+	ca.Properties = &properties
+	ca.Labels = labels
+	ca.Start = start
+	ca.End = end
+	ca.Window = Window{
 		start: &start,
 		end:   &end,
 	}
 
 	if adjustment, err := getTypedVal(fmap["adjustment"]); err == nil {
-		ca.adjustment = adjustment.(float64)
+		ca.Adjustment = adjustment.(float64)
 	}
 	if Credit, err := getTypedVal(fmap["credit"]); err == nil {
 		ca.Credit = Credit.(float64)
 	}
 	if Cost, err := getTypedVal(fmap["totalCost"]); err == nil {
-		ca.Cost = Cost.(float64) - ca.adjustment - ca.Credit
+		ca.Cost = Cost.(float64) - ca.Adjustment - ca.Credit
 	}
 
 	return nil
@@ -178,11 +178,11 @@ func (ca *Cloud) InterfaceToCloud(itf interface{}) error {
 func (cm *ClusterManagement) MarshalJSON() ([]byte, error) {
 	buffer := bytes.NewBufferString("{")
 	jsonEncodeString(buffer, "type", cm.Type().String(), ",")
-	jsonEncode(buffer, "properties", cm.Properties(), ",")
-	jsonEncode(buffer, "labels", cm.Labels(), ",")
-	jsonEncode(buffer, "window", cm.Window(), ",")
-	jsonEncodeString(buffer, "start", cm.Start().Format(time.RFC3339), ",")
-	jsonEncodeString(buffer, "end", cm.End().Format(time.RFC3339), ",")
+	jsonEncode(buffer, "properties", cm.Properties, ",")
+	jsonEncode(buffer, "labels", cm.Labels, ",")
+	jsonEncode(buffer, "window", cm.Window, ",")
+	jsonEncodeString(buffer, "start", cm.GetStart().Format(time.RFC3339), ",")
+	jsonEncodeString(buffer, "end", cm.GetEnd().Format(time.RFC3339), ",")
 	jsonEncodeFloat64(buffer, "minutes", cm.Minutes(), ",")
 	jsonEncodeFloat64(buffer, "totalCost", cm.TotalCost(), "")
 	buffer.WriteString("}")
@@ -231,9 +231,9 @@ func (cm *ClusterManagement) InterfaceToClusterManagement(itf interface{}) error
 		return err
 	}
 
-	cm.properties = &properties
-	cm.labels = labels
-	cm.window = Window{
+	cm.Properties = &properties
+	cm.Labels = labels
+	cm.Window = Window{
 		start: &start,
 		end:   &end,
 	}
@@ -251,16 +251,16 @@ func (cm *ClusterManagement) InterfaceToClusterManagement(itf interface{}) error
 func (d *Disk) MarshalJSON() ([]byte, error) {
 	buffer := bytes.NewBufferString("{")
 	jsonEncodeString(buffer, "type", d.Type().String(), ",")
-	jsonEncode(buffer, "properties", d.Properties(), ",")
-	jsonEncode(buffer, "labels", d.Labels(), ",")
-	jsonEncode(buffer, "window", d.Window(), ",")
-	jsonEncodeString(buffer, "start", d.Start().Format(time.RFC3339), ",")
-	jsonEncodeString(buffer, "end", d.End().Format(time.RFC3339), ",")
+	jsonEncode(buffer, "properties", d.Properties, ",")
+	jsonEncode(buffer, "labels", d.Labels, ",")
+	jsonEncode(buffer, "window", d.Window, ",")
+	jsonEncodeString(buffer, "start", d.Start.Format(time.RFC3339), ",")
+	jsonEncodeString(buffer, "end", d.End.Format(time.RFC3339), ",")
 	jsonEncodeFloat64(buffer, "minutes", d.Minutes(), ",")
 	jsonEncodeFloat64(buffer, "byteHours", d.ByteHours, ",")
 	jsonEncodeFloat64(buffer, "bytes", d.Bytes(), ",")
 	jsonEncode(buffer, "breakdown", d.Breakdown, ",")
-	jsonEncodeFloat64(buffer, "adjustment", d.Adjustment(), ",")
+	jsonEncodeFloat64(buffer, "adjustment", d.Adjustment, ",")
 	jsonEncodeFloat64(buffer, "totalCost", d.TotalCost(), "")
 	buffer.WriteString("}")
 	return buffer.Bytes(), nil
@@ -312,21 +312,21 @@ func (d *Disk) InterfaceToDisk(itf interface{}) error {
 
 	breakdown := toBreakdown(fbreakdown)
 
-	d.properties = &properties
-	d.labels = labels
-	d.start = start
-	d.end = end
-	d.window = Window{
+	d.Properties = &properties
+	d.Labels = labels
+	d.Start = start
+	d.End = end
+	d.Window = Window{
 		start: &start,
 		end:   &end,
 	}
 	d.Breakdown = &breakdown
 
 	if adjustment, err := getTypedVal(fmap["adjustment"]); err == nil {
-		d.adjustment = adjustment.(float64)
+		d.Adjustment = adjustment.(float64)
 	}
 	if Cost, err := getTypedVal(fmap["totalCost"]); err == nil {
-		d.Cost = Cost.(float64) - d.adjustment
+		d.Cost = Cost.(float64) - d.Adjustment
 	}
 	if ByteHours, err := getTypedVal(fmap["byteHours"]); err == nil {
 		d.ByteHours = ByteHours.(float64)
@@ -347,13 +347,13 @@ func (d *Disk) InterfaceToDisk(itf interface{}) error {
 func (n *Network) MarshalJSON() ([]byte, error) {
 	buffer := bytes.NewBufferString("{")
 	jsonEncodeString(buffer, "type", n.Type().String(), ",")
-	jsonEncode(buffer, "properties", n.Properties(), ",")
-	jsonEncode(buffer, "labels", n.Labels(), ",")
-	jsonEncode(buffer, "window", n.Window(), ",")
-	jsonEncodeString(buffer, "start", n.Start().Format(time.RFC3339), ",")
-	jsonEncodeString(buffer, "end", n.End().Format(time.RFC3339), ",")
+	jsonEncode(buffer, "properties", n.Properties, ",")
+	jsonEncode(buffer, "labels", n.Labels, ",")
+	jsonEncode(buffer, "window", n.Window, ",")
+	jsonEncodeString(buffer, "start", n.Start.Format(time.RFC3339), ",")
+	jsonEncodeString(buffer, "end", n.End.Format(time.RFC3339), ",")
 	jsonEncodeFloat64(buffer, "minutes", n.Minutes(), ",")
-	jsonEncodeFloat64(buffer, "adjustment", n.Adjustment(), ",")
+	jsonEncodeFloat64(buffer, "adjustment", n.Adjustment, ",")
 	jsonEncodeFloat64(buffer, "totalCost", n.TotalCost(), "")
 	buffer.WriteString("}")
 	return buffer.Bytes(), nil
@@ -401,20 +401,20 @@ func (n *Network) InterfaceToNetwork(itf interface{}) error {
 		return err
 	}
 
-	n.properties = &properties
-	n.labels = labels
-	n.start = start
-	n.end = end
-	n.window = Window{
+	n.Properties = &properties
+	n.Labels = labels
+	n.Start = start
+	n.End = end
+	n.Window = Window{
 		start: &start,
 		end:   &end,
 	}
 
 	if adjustment, err := getTypedVal(fmap["adjustment"]); err == nil {
-		n.adjustment = adjustment.(float64)
+		n.Adjustment = adjustment.(float64)
 	}
 	if Cost, err := getTypedVal(fmap["totalCost"]); err == nil {
-		n.Cost = Cost.(float64) - n.adjustment
+		n.Cost = Cost.(float64) - n.Adjustment
 	}
 
 	return nil
@@ -427,11 +427,11 @@ func (n *Network) InterfaceToNetwork(itf interface{}) error {
 func (n *Node) MarshalJSON() ([]byte, error) {
 	buffer := bytes.NewBufferString("{")
 	jsonEncodeString(buffer, "type", n.Type().String(), ",")
-	jsonEncode(buffer, "properties", n.Properties(), ",")
-	jsonEncode(buffer, "labels", n.Labels(), ",")
-	jsonEncode(buffer, "window", n.Window(), ",")
-	jsonEncodeString(buffer, "start", n.Start().Format(time.RFC3339), ",")
-	jsonEncodeString(buffer, "end", n.End().Format(time.RFC3339), ",")
+	jsonEncode(buffer, "properties", n.Properties, ",")
+	jsonEncode(buffer, "labels", n.Labels, ",")
+	jsonEncode(buffer, "window", n.Window, ",")
+	jsonEncodeString(buffer, "start", n.Start.Format(time.RFC3339), ",")
+	jsonEncodeString(buffer, "end", n.End.Format(time.RFC3339), ",")
 	jsonEncodeFloat64(buffer, "minutes", n.Minutes(), ",")
 	jsonEncodeString(buffer, "nodeType", n.NodeType, ",")
 	jsonEncodeFloat64(buffer, "cpuCores", n.CPUCores(), ",")
@@ -447,7 +447,7 @@ func (n *Node) MarshalJSON() ([]byte, error) {
 	jsonEncodeFloat64(buffer, "gpuCost", n.GPUCost, ",")
 	jsonEncodeFloat64(buffer, "gpuCount", n.GPUs(), ",")
 	jsonEncodeFloat64(buffer, "ramCost", n.RAMCost, ",")
-	jsonEncodeFloat64(buffer, "adjustment", n.Adjustment(), ",")
+	jsonEncodeFloat64(buffer, "adjustment", n.Adjustment, ",")
 	jsonEncodeFloat64(buffer, "totalCost", n.TotalCost(), "")
 	buffer.WriteString("}")
 	return buffer.Bytes(), nil
@@ -501,11 +501,11 @@ func (n *Node) InterfaceToNode(itf interface{}) error {
 	cpuBreakdown := toBreakdown(fcpuBreakdown)
 	ramBreakdown := toBreakdown(framBreakdown)
 
-	n.properties = &properties
-	n.labels = labels
-	n.start = start
-	n.end = end
-	n.window = Window{
+	n.Properties = &properties
+	n.Labels = labels
+	n.Start = start
+	n.End = end
+	n.Window = Window{
 		start: &start,
 		end:   &end,
 	}
@@ -513,7 +513,7 @@ func (n *Node) InterfaceToNode(itf interface{}) error {
 	n.RAMBreakdown = &ramBreakdown
 
 	if adjustment, err := getTypedVal(fmap["adjustment"]); err == nil {
-		n.adjustment = adjustment.(float64)
+		n.Adjustment = adjustment.(float64)
 	}
 	if NodeType, err := getTypedVal(fmap["nodeType"]); err == nil {
 		n.NodeType = NodeType.(string)
@@ -555,13 +555,13 @@ func (n *Node) InterfaceToNode(itf interface{}) error {
 func (lb *LoadBalancer) MarshalJSON() ([]byte, error) {
 	buffer := bytes.NewBufferString("{")
 	jsonEncodeString(buffer, "type", lb.Type().String(), ",")
-	jsonEncode(buffer, "properties", lb.Properties(), ",")
-	jsonEncode(buffer, "labels", lb.Labels(), ",")
-	jsonEncode(buffer, "window", lb.Window(), ",")
-	jsonEncodeString(buffer, "start", lb.Start().Format(time.RFC3339), ",")
-	jsonEncodeString(buffer, "end", lb.End().Format(time.RFC3339), ",")
+	jsonEncode(buffer, "properties", lb.Properties, ",")
+	jsonEncode(buffer, "labels", lb.Labels, ",")
+	jsonEncode(buffer, "window", lb.Window, ",")
+	jsonEncodeString(buffer, "start", lb.Start.Format(time.RFC3339), ",")
+	jsonEncodeString(buffer, "end", lb.End.Format(time.RFC3339), ",")
 	jsonEncodeFloat64(buffer, "minutes", lb.Minutes(), ",")
-	jsonEncodeFloat64(buffer, "adjustment", lb.Adjustment(), ",")
+	jsonEncodeFloat64(buffer, "adjustment", lb.Adjustment, ",")
 	jsonEncodeFloat64(buffer, "totalCost", lb.TotalCost(), "")
 	buffer.WriteString("}")
 	return buffer.Bytes(), nil
@@ -609,20 +609,20 @@ func (lb *LoadBalancer) InterfaceToLoadBalancer(itf interface{}) error {
 		return err
 	}
 
-	lb.properties = &properties
-	lb.labels = labels
-	lb.start = start
-	lb.end = end
-	lb.window = Window{
+	lb.Properties = &properties
+	lb.Labels = labels
+	lb.Start = start
+	lb.End = end
+	lb.Window = Window{
 		start: &start,
 		end:   &end,
 	}
 
 	if adjustment, err := getTypedVal(fmap["adjustment"]); err == nil {
-		lb.adjustment = adjustment.(float64)
+		lb.Adjustment = adjustment.(float64)
 	}
 	if Cost, err := getTypedVal(fmap["totalCost"]); err == nil {
-		lb.Cost = Cost.(float64) - lb.adjustment
+		lb.Cost = Cost.(float64) - lb.Adjustment
 	}
 
 	return nil
@@ -635,13 +635,11 @@ func (lb *LoadBalancer) InterfaceToLoadBalancer(itf interface{}) error {
 func (sa *SharedAsset) MarshalJSON() ([]byte, error) {
 	buffer := bytes.NewBufferString("{")
 	jsonEncodeString(buffer, "type", sa.Type().String(), ",")
-	jsonEncode(buffer, "properties", sa.Properties(), ",")
-	jsonEncode(buffer, "labels", sa.Labels(), ",")
-	jsonEncode(buffer, "properties", sa.Properties(), ",")
-	jsonEncode(buffer, "labels", sa.Labels(), ",")
-	jsonEncode(buffer, "window", sa.Window(), ",")
-	jsonEncodeString(buffer, "start", sa.Start().Format(time.RFC3339), ",")
-	jsonEncodeString(buffer, "end", sa.End().Format(time.RFC3339), ",")
+	jsonEncode(buffer, "properties", sa.Properties, ",")
+	jsonEncode(buffer, "labels", sa.Labels, ",")
+	jsonEncode(buffer, "window", sa.Window, ",")
+	jsonEncodeString(buffer, "start", sa.GetStart().Format(time.RFC3339), ",")
+	jsonEncodeString(buffer, "end", sa.GetEnd().Format(time.RFC3339), ",")
 	jsonEncodeFloat64(buffer, "minutes", sa.Minutes(), ",")
 	jsonEncodeFloat64(buffer, "totalCost", sa.TotalCost(), "")
 	buffer.WriteString("}")
@@ -690,9 +688,9 @@ func (sa *SharedAsset) InterfaceToSharedAsset(itf interface{}) error {
 		return err
 	}
 
-	sa.properties = &properties
-	sa.labels = labels
-	sa.window = Window{
+	sa.Properties = &properties
+	sa.Labels = labels
+	sa.Window = Window{
 		start: &start,
 		end:   &end,
 	}
@@ -712,9 +710,8 @@ func (as *AssetSet) MarshalJSON() ([]byte, error) {
 	if as == nil {
 		return json.Marshal(map[string]Asset{})
 	}
-	as.RLock()
-	defer as.RUnlock()
-	return json.Marshal(as.assets)
+
+	return json.Marshal(as.Assets)
 }
 
 // AssetSetResponse for unmarshaling of AssetSet.assets into AssetSet

+ 49 - 49
pkg/kubecost/asset_json_test.go

@@ -35,22 +35,22 @@ func TestAny_Unmarshal(t *testing.T) {
 	}
 
 	// Check if all fields in initial Any equal those in Any from unmarshal
-	if !any1.properties.Equal(any2.properties) {
+	if !any1.Properties.Equal(any2.Properties) {
 		t.Fatalf("Any Unmarshal: properties mutated in unmarshal")
 	}
-	if !any1.labels.Equal(any2.labels) {
+	if !any1.Labels.Equal(any2.Labels) {
 		t.Fatalf("Any Unmarshal: labels mutated in unmarshal")
 	}
-	if !any1.window.Equal(any2.window) {
+	if !any1.Window.Equal(any2.Window) {
 		t.Fatalf("Any Unmarshal: window mutated in unmarshal")
 	}
-	if !any1.start.Equal(any2.start) {
+	if !any1.Start.Equal(any2.Start) {
 		t.Fatalf("Any Unmarshal: start mutated in unmarshal")
 	}
-	if !any1.end.Equal(any2.end) {
+	if !any1.End.Equal(any2.End) {
 		t.Fatalf("Any Unmarshal: end mutated in unmarshal")
 	}
-	if any1.adjustment != any2.adjustment {
+	if any1.Adjustment != any2.Adjustment {
 		t.Fatalf("Any Unmarshal: adjustment mutated in unmarshal")
 	}
 	if any1.Cost != any2.Cost {
@@ -88,22 +88,22 @@ func TestCloud_Unmarshal(t *testing.T) {
 	}
 
 	// Check if all fields in initial Cloud equal those in Cloud from unmarshal
-	if !cloud1.properties.Equal(cloud2.properties) {
+	if !cloud1.Properties.Equal(cloud2.Properties) {
 		t.Fatalf("Cloud Unmarshal: properties mutated in unmarshal")
 	}
-	if !cloud1.labels.Equal(cloud2.labels) {
+	if !cloud1.Labels.Equal(cloud2.Labels) {
 		t.Fatalf("Cloud Unmarshal: labels mutated in unmarshal")
 	}
-	if !cloud1.window.Equal(cloud2.window) {
+	if !cloud1.Window.Equal(cloud2.Window) {
 		t.Fatalf("Cloud Unmarshal: window mutated in unmarshal")
 	}
-	if !cloud1.start.Equal(cloud2.start) {
+	if !cloud1.Start.Equal(cloud2.Start) {
 		t.Fatalf("Cloud Unmarshal: start mutated in unmarshal")
 	}
-	if !cloud1.end.Equal(cloud2.end) {
+	if !cloud1.End.Equal(cloud2.End) {
 		t.Fatalf("Cloud Unmarshal: end mutated in unmarshal")
 	}
-	if cloud1.adjustment != cloud2.adjustment {
+	if cloud1.Adjustment != cloud2.Adjustment {
 		t.Fatalf("Cloud Unmarshal: adjustment mutated in unmarshal")
 	}
 	if cloud1.Cost != cloud2.Cost {
@@ -138,13 +138,13 @@ func TestClusterManagement_Unmarshal(t *testing.T) {
 	}
 
 	// Check if all fields in initial ClusterManagement equal those in ClusterManagement from unmarshal
-	if !cm1.properties.Equal(cm2.properties) {
+	if !cm1.Properties.Equal(cm2.Properties) {
 		t.Fatalf("ClusterManagement Unmarshal: properties mutated in unmarshal")
 	}
-	if !cm1.labels.Equal(cm2.labels) {
+	if !cm1.Labels.Equal(cm2.Labels) {
 		t.Fatalf("ClusterManagement Unmarshal: labels mutated in unmarshal")
 	}
-	if !cm1.window.Equal(cm2.window) {
+	if !cm1.Window.Equal(cm2.Window) {
 		t.Fatalf("ClusterManagement Unmarshal: window mutated in unmarshal")
 	}
 	if cm1.Cost != cm2.Cost {
@@ -187,25 +187,25 @@ func TestDisk_Unmarshal(t *testing.T) {
 	}
 
 	// Check if all fields in initial Disk equal those in Disk from unmarshal
-	if !disk1.properties.Equal(disk2.properties) {
+	if !disk1.Properties.Equal(disk2.Properties) {
 		t.Fatalf("Disk Unmarshal: properties mutated in unmarshal")
 	}
-	if !disk1.labels.Equal(disk2.labels) {
+	if !disk1.Labels.Equal(disk2.Labels) {
 		t.Fatalf("Disk Unmarshal: labels mutated in unmarshal")
 	}
-	if !disk1.window.Equal(disk2.window) {
+	if !disk1.Window.Equal(disk2.Window) {
 		t.Fatalf("Disk Unmarshal: window mutated in unmarshal")
 	}
 	if !disk1.Breakdown.Equal(disk2.Breakdown) {
 		t.Fatalf("Disk Unmarshal: Breakdown mutated in unmarshal")
 	}
-	if !disk1.start.Equal(disk2.start) {
+	if !disk1.Start.Equal(disk2.Start) {
 		t.Fatalf("Disk Unmarshal: start mutated in unmarshal")
 	}
-	if !disk1.end.Equal(disk2.end) {
+	if !disk1.End.Equal(disk2.End) {
 		t.Fatalf("Disk Unmarshal: end mutated in unmarshal")
 	}
-	if disk1.adjustment != disk2.adjustment {
+	if disk1.Adjustment != disk2.Adjustment {
 		t.Fatalf("Disk Unmarshal: adjustment mutated in unmarshal")
 	}
 	if disk1.ByteHours != disk2.ByteHours {
@@ -241,22 +241,22 @@ func TestNetwork_Unmarshal(t *testing.T) {
 	}
 
 	// Check if all fields in initial Network equal those in Network from unmarshal
-	if !network1.properties.Equal(network2.properties) {
+	if !network1.Properties.Equal(network2.Properties) {
 		t.Fatalf("Network Unmarshal: properties mutated in unmarshal")
 	}
-	if !network1.labels.Equal(network2.labels) {
+	if !network1.Labels.Equal(network2.Labels) {
 		t.Fatalf("Network Unmarshal: labels mutated in unmarshal")
 	}
-	if !network1.window.Equal(network2.window) {
+	if !network1.Window.Equal(network2.Window) {
 		t.Fatalf("Network Unmarshal: window mutated in unmarshal")
 	}
-	if !network1.start.Equal(network2.start) {
+	if !network1.Start.Equal(network2.Start) {
 		t.Fatalf("Network Unmarshal: start mutated in unmarshal")
 	}
-	if !network1.end.Equal(network2.end) {
+	if !network1.End.Equal(network2.End) {
 		t.Fatalf("Network Unmarshal: end mutated in unmarshal")
 	}
-	if network1.adjustment != network2.adjustment {
+	if network1.Adjustment != network2.Adjustment {
 		t.Fatalf("Network Unmarshal: adjustment mutated in unmarshal")
 	}
 	if network1.Cost != network2.Cost {
@@ -309,13 +309,13 @@ func TestNode_Unmarshal(t *testing.T) {
 	}
 
 	// Check if all fields in initial Node equal those in Node from unmarshal
-	if !node1.properties.Equal(node2.properties) {
+	if !node1.Properties.Equal(node2.Properties) {
 		t.Fatalf("Node Unmarshal: properties mutated in unmarshal")
 	}
-	if !node1.labels.Equal(node2.labels) {
+	if !node1.Labels.Equal(node2.Labels) {
 		t.Fatalf("Node Unmarshal: labels mutated in unmarshal")
 	}
-	if !node1.window.Equal(node2.window) {
+	if !node1.Window.Equal(node2.Window) {
 		t.Fatalf("Node Unmarshal: window mutated in unmarshal")
 	}
 	if !node1.CPUBreakdown.Equal(node2.CPUBreakdown) {
@@ -324,13 +324,13 @@ func TestNode_Unmarshal(t *testing.T) {
 	if !node1.RAMBreakdown.Equal(node2.RAMBreakdown) {
 		t.Fatalf("Node Unmarshal: RAMBreakdown mutated in unmarshal")
 	}
-	if !node1.start.Equal(node2.start) {
+	if !node1.Start.Equal(node2.Start) {
 		t.Fatalf("Node Unmarshal: start mutated in unmarshal")
 	}
-	if !node1.end.Equal(node2.end) {
+	if !node1.End.Equal(node2.End) {
 		t.Fatalf("Node Unmarshal: end mutated in unmarshal")
 	}
-	if node1.adjustment != node2.adjustment {
+	if node1.Adjustment != node2.Adjustment {
 		t.Fatalf("Node Unmarshal: adjustment mutated in unmarshal")
 	}
 	if node1.NodeType != node2.NodeType {
@@ -390,22 +390,22 @@ func TestLoadBalancer_Unmarshal(t *testing.T) {
 	}
 
 	// Check if all fields in initial LoadBalancer equal those in LoadBalancer from unmarshal
-	if !lb1.properties.Equal(lb2.properties) {
+	if !lb1.Properties.Equal(lb2.Properties) {
 		t.Fatalf("LoadBalancer Unmarshal: properties mutated in unmarshal")
 	}
-	if !lb1.labels.Equal(lb2.labels) {
+	if !lb1.Labels.Equal(lb2.Labels) {
 		t.Fatalf("LoadBalancer Unmarshal: labels mutated in unmarshal")
 	}
-	if !lb1.window.Equal(lb2.window) {
+	if !lb1.Window.Equal(lb2.Window) {
 		t.Fatalf("LoadBalancer Unmarshal: window mutated in unmarshal")
 	}
-	if !lb1.start.Equal(lb2.start) {
+	if !lb1.Start.Equal(lb2.Start) {
 		t.Fatalf("LoadBalancer Unmarshal: start mutated in unmarshal")
 	}
-	if !lb1.end.Equal(lb2.end) {
+	if !lb1.End.Equal(lb2.End) {
 		t.Fatalf("LoadBalancer Unmarshal: end mutated in unmarshal")
 	}
-	if lb1.adjustment != lb2.adjustment {
+	if lb1.Adjustment != lb2.Adjustment {
 		t.Fatalf("LoadBalancer Unmarshal: adjustment mutated in unmarshal")
 	}
 	if lb1.Cost != lb2.Cost {
@@ -437,13 +437,13 @@ func TestSharedAsset_Unmarshal(t *testing.T) {
 	}
 
 	// Check if all fields in initial SharedAsset equal those in SharedAsset from unmarshal
-	if !sa1.properties.Equal(sa2.properties) {
+	if !sa1.Properties.Equal(sa2.Properties) {
 		t.Fatalf("SharedAsset Unmarshal: properties mutated in unmarshal")
 	}
-	if !sa1.labels.Equal(sa2.labels) {
+	if !sa1.Labels.Equal(sa2.Labels) {
 		t.Fatalf("SharedAsset Unmarshal: labels mutated in unmarshal")
 	}
-	if !sa1.window.Equal(sa2.window) {
+	if !sa1.Window.Equal(sa2.Window) {
 		t.Fatalf("SharedAsset Unmarshal: window mutated in unmarshal")
 	}
 	if sa1.Cost != sa2.Cost {
@@ -488,7 +488,7 @@ func TestAssetset_Unmarshal(t *testing.T) {
 	}
 
 	// For each asset in unmarshaled AssetSetResponse, check if it is equal to the corresponding AssetSet asset
-	for key, asset := range assetset.assets {
+	for key, asset := range assetset.Assets {
 
 		if unmarshaledAsset, exists := assetUnmarshalResponse.Assets[key]; exists {
 
@@ -500,23 +500,23 @@ func TestAssetset_Unmarshal(t *testing.T) {
 					asset, _ := asset.(*Disk)
 					unmarshaledAsset, _ := unmarshaledAsset.(*Disk)
 
-					if !asset.Labels().Equal(unmarshaledAsset.Labels()) {
+					if !asset.GetLabels().Equal(unmarshaledAsset.Labels) {
 						return false
 					}
-					if !asset.Properties().Equal(unmarshaledAsset.Properties()) {
+					if !asset.Properties.Equal(unmarshaledAsset.Properties) {
 						return false
 					}
 
-					if !asset.Start().Equal(unmarshaledAsset.Start()) {
+					if !asset.GetStart().Equal(unmarshaledAsset.Start) {
 						return false
 					}
-					if !asset.End().Equal(unmarshaledAsset.End()) {
+					if !asset.End.Equal(unmarshaledAsset.End) {
 						return false
 					}
-					if !asset.window.Equal(unmarshaledAsset.window) {
+					if !asset.Window.Equal(unmarshaledAsset.Window) {
 						return false
 					}
-					if asset.adjustment != unmarshaledAsset.adjustment {
+					if asset.Adjustment != unmarshaledAsset.Adjustment {
 						return false
 					}
 					if asset.Cost != unmarshaledAsset.Cost {

+ 148 - 148
pkg/kubecost/asset_test.go

@@ -31,25 +31,25 @@ func assertAssetSet(t *testing.T, as *AssetSet, msg string, window Window, exps
 	if !as.Window.Equal(window) {
 		t.Fatalf("AssetSet.AggregateBy[%s]: expected window %s, actual %s", msg, window, as.Window)
 	}
-	as.Each(func(key string, a Asset) {
+	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.Window().Equal(window) {
-				t.Fatalf("AssetSet.AggregateBy[%s]: key %s expected window %s, actual %s", msg, key, window, a.Window())
+			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)
-	as.Each(func(key string, a Asset) {
+	for key, a := range as.Assets {
 		fmt.Printf(" > %s: %s\n", key, a)
-	})
+	}
 }
 
 func TestAny_Add(t *testing.T) {
@@ -77,34 +77,34 @@ func TestAny_Add(t *testing.T) {
 	if any3.TotalCost() != 15.0 {
 		t.Fatalf("Any.Add: expected %f; got %f", 15.0, any3.TotalCost())
 	}
-	if any3.Adjustment() != 2.0 {
-		t.Fatalf("Any.Add: expected %f; got %f", 2.0, any3.Adjustment())
+	if any3.GetAdjustment() != 2.0 {
+		t.Fatalf("Any.Add: expected %f; got %f", 2.0, any3.GetAdjustment())
 	}
-	if any3.Properties().Cluster != "cluster1" {
-		t.Fatalf("Any.Add: expected %s; got %s", "cluster1", any3.Properties().Cluster)
+	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.Properties().ProviderID != "" {
-		t.Fatalf("Any.Add: expected %s; got %s", "", any3.Properties().ProviderID)
+	if any3.GetProperties().ProviderID != "" {
+		t.Fatalf("Any.Add: expected %s; got %s", "", any3.GetProperties().ProviderID)
 	}
-	if any3.Properties().Name != "" {
-		t.Fatalf("Any.Add: expected %s; got %s", "", any3.Properties().Name)
+	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 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())
+	if any2.Adjustment != 1.0 {
+		t.Fatalf("Any.Add: expected %f; got %f", 1.0, any2.Adjustment)
 	}
 }
 
@@ -127,8 +127,8 @@ func TestAny_Clone(t *testing.T) {
 	if any2.TotalCost() != 10.0 {
 		t.Fatalf("Any.Clone: expected %f; got %f", 10.0, any2.TotalCost())
 	}
-	if any2.Adjustment() != 1.0 {
-		t.Fatalf("Any.Clone: expected %f; got %f", 1.0, any2.Adjustment())
+	if any2.GetAdjustment() != 1.0 {
+		t.Fatalf("Any.Clone: expected %f; got %f", 1.0, any2.GetAdjustment())
 	}
 }
 
@@ -194,20 +194,20 @@ func TestDisk_Add(t *testing.T) {
 	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.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.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.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.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())
@@ -220,8 +220,8 @@ func TestDisk_Add(t *testing.T) {
 	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.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)
@@ -229,8 +229,8 @@ func TestDisk_Add(t *testing.T) {
 	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.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)
@@ -274,20 +274,20 @@ func TestDisk_Add(t *testing.T) {
 	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.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.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.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.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())
@@ -300,8 +300,8 @@ func TestDisk_Add(t *testing.T) {
 	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.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)
@@ -309,8 +309,8 @@ func TestDisk_Add(t *testing.T) {
 	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.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)
@@ -333,8 +333,8 @@ func TestDisk_Clone(t *testing.T) {
 	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.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)
@@ -412,20 +412,20 @@ func TestNode_Add(t *testing.T) {
 	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.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.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.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.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())
@@ -438,14 +438,14 @@ func TestNode_Add(t *testing.T) {
 	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 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())
+	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
@@ -506,20 +506,20 @@ func TestNode_Add(t *testing.T) {
 	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.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.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.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.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())
@@ -535,14 +535,14 @@ func TestNode_Add(t *testing.T) {
 	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 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())
+	if nodeA2.Adjustment != 1.0 {
+		t.Fatalf("Node.Add: expected %f; got %f", 1.0, nodeA2.Adjustment)
 	}
 }
 
@@ -582,8 +582,8 @@ func TestClusterManagement_Add(t *testing.T) {
 	if cm3.TotalCost() != 13.0 {
 		t.Fatalf("ClusterManagement.Add: expected %f; got %f", 13.0, cm3.TotalCost())
 	}
-	if cm3.Properties().Cluster != "cluster1" {
-		t.Fatalf("ClusterManagement.Add: expected %s; got %s", "cluster1", cm3.Properties().Cluster)
+	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())
@@ -617,8 +617,8 @@ func TestCloudAny_Add(t *testing.T) {
 	if ca3.TotalCost() != 15.0 {
 		t.Fatalf("Any.Add: expected %f; got %f", 15.0, ca3.TotalCost())
 	}
-	if ca3.Adjustment() != 2.0 {
-		t.Fatalf("Any.Add: expected %f; got %f", 2.0, ca3.Adjustment())
+	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())
@@ -628,14 +628,14 @@ func TestCloudAny_Add(t *testing.T) {
 	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 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())
+	if ca2.Adjustment != 1.0 {
+		t.Fatalf("Any.Add: expected %f; got %f", 1.0, ca2.Adjustment)
 	}
 }
 
@@ -824,13 +824,13 @@ func TestAssetSet_InsertMatchingWindow(t *testing.T) {
 	a1.SetProperties(&AssetProperties{
 		Name: "asset-1",
 	})
-	a1.window = NewClosedWindow(a1WindowStart, a1WindowEnd)
+	a1.Window = NewClosedWindow(a1WindowStart, a1WindowEnd)
 
 	a2 := &Disk{}
 	a2.SetProperties(&AssetProperties{
 		Name: "asset-2",
 	})
-	a2.window = NewClosedWindow(a2WindowStart, a2WindowEnd)
+	a2.Window = NewClosedWindow(a2WindowStart, a2WindowEnd)
 
 	as := NewAssetSet(setStart, setEnd)
 	as.Insert(a1)
@@ -840,14 +840,14 @@ func TestAssetSet_InsertMatchingWindow(t *testing.T) {
 		t.Errorf("AS length got %d, expected %d", as.Length(), 2)
 	}
 
-	as.Each(func(k string, a Asset) {
-		if !(*a.Window().Start()).Equal(setStart) {
-			t.Errorf("Asset %s window start is %s, expected %s", a.Properties().Name, *a.Window().Start(), setStart)
+	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.Window().End()).Equal(setEnd) {
-			t.Errorf("Asset %s window end is %s, expected %s", a.Properties().Name, *a.Window().End(), setEnd)
+		if !(*a.GetWindow().End()).Equal(setEnd) {
+			t.Errorf("Asset %s window end is %s, expected %s", a.GetProperties().Name, *a.GetWindow().End(), setEnd)
 		}
-	})
+	}
 }
 
 func TestAssetSet_ReconciliationMatchMap(t *testing.T) {
@@ -859,15 +859,15 @@ func TestAssetSet_ReconciliationMatchMap(t *testing.T) {
 
 	// Determine the number of assets by provider ID
 	assetCountByProviderId := make(map[string]int, len(matchMap))
-	as.Each(func(key string, a Asset) {
-		if a == nil || a.Properties() == nil || a.Properties().ProviderID == "" {
+	for _, a := range as.Assets {
+		if a == nil || a.GetProperties() == nil || a.GetProperties().ProviderID == "" {
 			return
 		}
-		if _, ok := assetCountByProviderId[a.Properties().ProviderID]; !ok {
-			assetCountByProviderId[a.Properties().ProviderID] = 0
+		if _, ok := assetCountByProviderId[a.GetProperties().ProviderID]; !ok {
+			assetCountByProviderId[a.GetProperties().ProviderID] = 0
 		}
-		assetCountByProviderId[a.Properties().ProviderID] += 1
-	})
+		assetCountByProviderId[a.GetProperties().ProviderID] += 1
+	}
 
 	for k, count := range assetCountByProviderId {
 		if len(matchMap[k]) != count {
@@ -1180,11 +1180,11 @@ func TestAssetSetRange_Start(t *testing.T) {
 		{
 			name: "Single asset",
 			arg: &AssetSetRange{
-				assets: []*AssetSet{
-					&AssetSet{
-						assets: map[string]Asset{
+				Assets: []*AssetSet{
+					{
+						Assets: map[string]Asset{
 							"a": &Node{
-								start: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
+								Start: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
 							},
 						},
 					},
@@ -1196,14 +1196,14 @@ func TestAssetSetRange_Start(t *testing.T) {
 		{
 			name: "Two assets",
 			arg: &AssetSetRange{
-				assets: []*AssetSet{
-					&AssetSet{
-						assets: map[string]Asset{
+				Assets: []*AssetSet{
+					{
+						Assets: map[string]Asset{
 							"a": &Node{
-								start: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
+								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),
+								Start: time.Date(1970, 1, 2, 0, 0, 0, 0, time.UTC),
 							},
 						},
 					},
@@ -1215,18 +1215,18 @@ func TestAssetSetRange_Start(t *testing.T) {
 		{
 			name: "Two AssetSets",
 			arg: &AssetSetRange{
-				assets: []*AssetSet{
-					&AssetSet{
-						assets: map[string]Asset{
+				Assets: []*AssetSet{
+					{
+						Assets: map[string]Asset{
 							"a": &Node{
-								start: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
+								Start: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
 							},
 						},
 					},
-					&AssetSet{
-						assets: map[string]Asset{
+					{
+						Assets: map[string]Asset{
 							"b": &Node{
-								start: time.Date(1970, 1, 2, 0, 0, 0, 0, time.UTC),
+								Start: time.Date(1970, 1, 2, 0, 0, 0, 0, time.UTC),
 							},
 						},
 					},
@@ -1268,11 +1268,11 @@ func TestAssetSetRange_End(t *testing.T) {
 		{
 			name: "Single asset",
 			arg: &AssetSetRange{
-				assets: []*AssetSet{
-					&AssetSet{
-						assets: map[string]Asset{
+				Assets: []*AssetSet{
+					{
+						Assets: map[string]Asset{
 							"a": &Node{
-								end: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
+								End: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
 							},
 						},
 					},
@@ -1284,14 +1284,14 @@ func TestAssetSetRange_End(t *testing.T) {
 		{
 			name: "Two assets",
 			arg: &AssetSetRange{
-				assets: []*AssetSet{
-					&AssetSet{
-						assets: map[string]Asset{
+				Assets: []*AssetSet{
+					{
+						Assets: map[string]Asset{
 							"a": &Node{
-								end: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
+								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),
+								End: time.Date(1970, 1, 2, 0, 0, 0, 0, time.UTC),
 							},
 						},
 					},
@@ -1303,18 +1303,18 @@ func TestAssetSetRange_End(t *testing.T) {
 		{
 			name: "Two AssetSets",
 			arg: &AssetSetRange{
-				assets: []*AssetSet{
-					&AssetSet{
-						assets: map[string]Asset{
+				Assets: []*AssetSet{
+					{
+						Assets: map[string]Asset{
 							"a": &Node{
-								end: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
+								End: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
 							},
 						},
 					},
-					&AssetSet{
-						assets: map[string]Asset{
+					{
+						Assets: map[string]Asset{
 							"b": &Node{
-								end: time.Date(1970, 1, 2, 0, 0, 0, 0, time.UTC),
+								End: time.Date(1970, 1, 2, 0, 0, 0, 0, time.UTC),
 							},
 						},
 					},
@@ -1355,12 +1355,12 @@ func TestAssetSetRange_Minutes(t *testing.T) {
 		{
 			name: "Single asset",
 			arg: &AssetSetRange{
-				assets: []*AssetSet{
-					&AssetSet{
-						assets: map[string]Asset{
+				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),
+								Start: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
+								End:   time.Date(1970, 1, 2, 0, 0, 0, 0, time.UTC),
 							},
 						},
 					},
@@ -1372,16 +1372,16 @@ func TestAssetSetRange_Minutes(t *testing.T) {
 		{
 			name: "Two assets",
 			arg: &AssetSetRange{
-				assets: []*AssetSet{
-					&AssetSet{
-						assets: map[string]Asset{
+				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),
+								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),
+								Start: time.Date(1970, 1, 2, 0, 0, 0, 0, time.UTC),
+								End:   time.Date(1970, 1, 3, 0, 0, 0, 0, time.UTC),
 							},
 						},
 					},
@@ -1393,20 +1393,20 @@ func TestAssetSetRange_Minutes(t *testing.T) {
 		{
 			name: "Two AssetSets",
 			arg: &AssetSetRange{
-				assets: []*AssetSet{
-					&AssetSet{
-						assets: map[string]Asset{
+				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),
+								Start: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
+								End:   time.Date(1970, 1, 2, 0, 0, 0, 0, time.UTC),
 							},
 						},
 					},
-					&AssetSet{
-						assets: map[string]Asset{
+					{
+						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),
+								Start: time.Date(1970, 1, 2, 0, 0, 0, 0, time.UTC),
+								End:   time.Date(1970, 1, 3, 0, 0, 0, 0, time.UTC),
 							},
 						},
 					},
@@ -1443,11 +1443,11 @@ func TestAssetSetRange_MarshalJSON(t *testing.T) {
 		{
 			name: "Normal ASR",
 			arg: &AssetSetRange{
-				assets: []*AssetSet{
+				Assets: []*AssetSet{
 					{
-						assets: map[string]Asset{
+						Assets: map[string]Asset{
 							"a": &Any{
-								start: time.Now().UTC().Truncate(day),
+								Start: time.Now().UTC().Truncate(day),
 							},
 						},
 					},

+ 2 - 2
pkg/kubecost/audit.go

@@ -1,9 +1,10 @@
 package kubecost
 
 import (
-	"golang.org/x/exp/slices"
 	"sync"
 	"time"
+
+	"golang.org/x/exp/slices"
 )
 
 // AuditType the types of Audits, each of which should be contained in an AuditSet
@@ -235,7 +236,6 @@ func (ea *EqualityAudit) Clone() *EqualityAudit {
 
 // AuditCoverage tracks coverage of each audit type
 type AuditCoverage struct {
-	sync.RWMutex
 	AllocationReconciliation Window `json:"allocationReconciliation"`
 	AllocationAgg            Window `json:"allocationAgg"`
 	AllocationTotal          Window `json:"allocationTotal"`

+ 1 - 1
pkg/kubecost/bingen.go

@@ -30,7 +30,7 @@ package kubecost
 // @bingen:generate:AssetLabels
 // @bingen:generate:AssetProperties
 // @bingen:generate:AssetProperty
-// @bingen:generate[stringtable]:AssetSet
+// @bingen:generate[stringtable,preprocess,postprocess]:AssetSet
 // @bingen:generate:AssetSetRange
 // @bingen:generate:Breakdown
 // @bingen:generate:Cloud

Diferenças do arquivo suprimidas por serem muito extensas
+ 383 - 604
pkg/kubecost/kubecost_codecs.go


+ 23 - 23
pkg/kubecost/kubecost_codecs_test.go

@@ -51,7 +51,7 @@ func BenchmarkAllocationSetRange_BinaryEncoding(b *testing.B) {
 			b.Fatalf("AllocationSetRange.Binary: expected %s; found %s", asr0.Window(), asr1.Window())
 		}
 
-		asr0.Each(func(i int, as0 *AllocationSet) {
+		for i, as0 := range asr0.Allocations {
 			as1, err := asr1.Get(i)
 			if err != nil {
 				b.Fatalf("AllocationSetRange.Binary: unexpected error: %s", err)
@@ -64,7 +64,7 @@ func BenchmarkAllocationSetRange_BinaryEncoding(b *testing.B) {
 				b.Fatalf("AllocationSetRange.Binary: expected %s; found %s", as0.Window, as1.Window)
 			}
 
-			as0.Each(func(k string, a0 *Allocation) {
+			for k, a0 := range as0.Allocations {
 				a1 := as1.Get(k)
 				if a1 == nil {
 					b.Fatalf("AllocationSetRange.Binary: missing Allocation: %s", a0)
@@ -73,8 +73,8 @@ func BenchmarkAllocationSetRange_BinaryEncoding(b *testing.B) {
 				if !a0.Equal(a1) {
 					b.Fatalf("AllocationSetRange.Binary: unequal Allocations \"%s\": expected %s; found %s", k, a0, a1)
 				}
-			})
-		})
+			}
+		}
 	}
 }
 
@@ -115,7 +115,7 @@ func TestAllocationSetRange_BinaryEncoding(t *testing.T) {
 		t.Fatalf("AllocationSetRange.Binary: expected %s; found %s", asr0.Window(), asr1.Window())
 	}
 
-	asr0.Each(func(i int, as0 *AllocationSet) {
+	for i, as0 := range asr0.Allocations {
 		as1, err := asr1.Get(i)
 		if err != nil {
 			t.Fatalf("AllocationSetRange.Binary: unexpected error: %s", err)
@@ -128,7 +128,7 @@ func TestAllocationSetRange_BinaryEncoding(t *testing.T) {
 			t.Fatalf("AllocationSetRange.Binary: expected %s; found %s", as0.Window, as1.Window)
 		}
 
-		as0.Each(func(k string, a0 *Allocation) {
+		for k, a0 := range as0.Allocations {
 			a1 := as1.Get(k)
 			if a1 == nil {
 				t.Fatalf("AllocationSetRange.Binary: missing Allocation: %s", a0)
@@ -137,10 +137,10 @@ func TestAllocationSetRange_BinaryEncoding(t *testing.T) {
 			// TODO Sean: fix JSON marshaling of PVs
 			a1.PVs = a0.PVs
 			if !a0.Equal(a1) {
-				t.Fatalf("AllocationSetRange.Binary: unequal Allocations \"%s\": expected %s; found %s", k, a0, a1)
+				t.Fatalf("AllocationSetRange.Binary: unequal Allocations \"%s\": expected \"%s\"; found \"%s\"", k, a0, a1)
 			}
-		})
-	})
+		}
+	}
 }
 
 func TestAny_BinaryEncoding(t *testing.T) {
@@ -172,23 +172,23 @@ func TestAny_BinaryEncoding(t *testing.T) {
 		t.Fatalf("Any.Binary: unexpected error: %s", err)
 	}
 
-	if a1.Properties().Name != a0.Properties().Name {
-		t.Fatalf("Any.Binary: expected %s, found %s", a0.Properties().Name, a1.Properties().Name)
+	if a1.Properties.Name != a0.Properties.Name {
+		t.Fatalf("Any.Binary: expected %s, found %s", a0.Properties.Name, a1.Properties.Name)
 	}
-	if a1.Properties().Cluster != a0.Properties().Cluster {
-		t.Fatalf("Any.Binary: expected %s, found %s", a0.Properties().Cluster, a1.Properties().Cluster)
+	if a1.Properties.Cluster != a0.Properties.Cluster {
+		t.Fatalf("Any.Binary: expected %s, found %s", a0.Properties.Cluster, a1.Properties.Cluster)
 	}
-	if a1.Properties().ProviderID != a0.Properties().ProviderID {
-		t.Fatalf("Any.Binary: expected %s, found %s", a0.Properties().ProviderID, a1.Properties().ProviderID)
+	if a1.Properties.ProviderID != a0.Properties.ProviderID {
+		t.Fatalf("Any.Binary: expected %s, found %s", a0.Properties.ProviderID, a1.Properties.ProviderID)
 	}
-	if a1.Adjustment() != a0.Adjustment() {
-		t.Fatalf("Any.Binary: expected %f, found %f", a0.Adjustment(), a1.Adjustment())
+	if a1.Adjustment != a0.Adjustment {
+		t.Fatalf("Any.Binary: expected %f, found %f", a0.Adjustment, a1.Adjustment)
 	}
 	if a1.TotalCost() != a0.TotalCost() {
 		t.Fatalf("Any.Binary: expected %f, found %f", a0.TotalCost(), a1.TotalCost())
 	}
-	if !a1.Window().Equal(a0.Window()) {
-		t.Fatalf("Any.Binary: expected %s, found %s", a0.Window(), a1.Window())
+	if !a1.Window.Equal(a0.Window) {
+		t.Fatalf("Any.Binary: expected %s, found %s", a0.Window, a1.Window)
 	}
 }
 
@@ -237,7 +237,7 @@ func TestAssetSetRange_BinaryEncoding(t *testing.T) {
 		t.Fatalf("AssetSetRange.Binary: expected %s; found %s", asr0.Window(), asr1.Window())
 	}
 
-	asr0.Each(func(i int, as0 *AssetSet) {
+	for i, as0 := range asr0.Assets {
 		as1, err := asr1.Get(i)
 		if err != nil {
 			t.Fatalf("AssetSetRange.Binary: unexpected error: %s", err)
@@ -250,7 +250,7 @@ func TestAssetSetRange_BinaryEncoding(t *testing.T) {
 			t.Fatalf("AssetSetRange.Binary: expected %s; found %s", as0.Window, as1.Window)
 		}
 
-		as0.Each(func(k string, a0 Asset) {
+		for k, a0 := range as0.Assets {
 			a1, ok := as1.Get(k)
 			if !ok {
 				t.Fatalf("AssetSetRange.Binary: missing Asset: %s", a0)
@@ -259,8 +259,8 @@ func TestAssetSetRange_BinaryEncoding(t *testing.T) {
 			if !a0.Equal(a1) {
 				t.Fatalf("AssetSetRange.Binary: unequal Assets \"%s\": expected %s; found %s", k, a0, a1)
 			}
-		})
-	})
+		}
+	}
 }
 
 func TestBreakdown_BinaryEncoding(t *testing.T) {

+ 7 - 7
pkg/kubecost/mock.go

@@ -331,7 +331,7 @@ func GenerateMockAllocationSetWithAssetProperties(start time.Time) *AllocationSe
 		Cluster: "cluster2",
 		Name:    "disk2",
 	}
-	for _, a := range as.allocations {
+	for _, a := range as.Allocations {
 		// add reconcilable pvs to pod-mno
 		if a.Properties.Pod == "pod-mno" {
 			a.PVs = a.PVs.Add(PVAllocations{
@@ -401,7 +401,7 @@ func GenerateMockAssetSets(start, end time.Time) []*AssetSet {
 	cluster1Nodes.CPUCost = 55.0
 	cluster1Nodes.RAMCost = 44.0
 	cluster1Nodes.GPUCost = 11.0
-	cluster1Nodes.adjustment = -10.00
+	cluster1Nodes.Adjustment = -10.00
 	cluster1Nodes.CPUCoreHours = 8
 	cluster1Nodes.RAMByteHours = 6
 	cluster1Nodes.GPUHours = 24
@@ -433,12 +433,12 @@ func GenerateMockAssetSets(start, end time.Time) []*AssetSet {
 	// Add PVs
 	cluster2Disk1 := NewDisk("disk1", "cluster2", "disk1", start, end, NewWindow(&start, &end))
 	cluster2Disk1.Cost = 5.0
-	cluster2Disk1.adjustment = 1.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.Adjustment = 3.0
 	cluster2Disk2.ByteHours = 10 * gb
 
 	cluster2Node1Disk := NewDisk("node1", "cluster2", "node1", start, end, NewWindow(&start, &end))
@@ -517,7 +517,7 @@ func GenerateMockAssetSets(start, end time.Time) []*AssetSet {
 	cluster1Nodes.CPUCost = 5.0
 	cluster1Nodes.RAMCost = 4.0
 	cluster1Nodes.GPUCost = 1.0
-	cluster1Nodes.adjustment = 90.00
+	cluster1Nodes.Adjustment = 90.00
 	cluster1Nodes.CPUCoreHours = 8
 	cluster1Nodes.RAMByteHours = 6
 	cluster1Nodes.GPUHours = 24
@@ -549,12 +549,12 @@ func GenerateMockAssetSets(start, end time.Time) []*AssetSet {
 	// Add PVs
 	cluster2Disk1 = NewDisk("disk1", "cluster2", "disk1", start, end, NewWindow(&start, &end))
 	cluster2Disk1.Cost = 5.0
-	cluster2Disk1.adjustment = 1.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.Adjustment = 4.0
 	cluster2Disk2.ByteHours = 20 * gb
 
 	assetSet2 := NewAssetSet(start, end, cluster1Nodes, cluster2Node1, cluster2Node2, cluster2Node3, cluster2Disk1,

+ 10 - 10
pkg/kubecost/summaryallocation.go

@@ -318,7 +318,7 @@ func NewSummaryAllocationSet(as *AllocationSet, filter AllocationFilter, kfs []A
 	if filter == nil && len(kfs) == 0 {
 		// No filters, so make the map of summary allocations exactly the size
 		// of the origin allocation set.
-		sasMap = make(map[string]*SummaryAllocation, len(as.allocations))
+		sasMap = make(map[string]*SummaryAllocation, len(as.Allocations))
 	} else {
 		// There are filters, so start with a standard map
 		sasMap = make(map[string]*SummaryAllocation)
@@ -329,7 +329,7 @@ func NewSummaryAllocationSet(as *AllocationSet, filter AllocationFilter, kfs []A
 		Window:             as.Window.Clone(),
 	}
 
-	for _, alloc := range as.allocations {
+	for _, alloc := range as.Allocations {
 		// First, detect if the allocation should be kept. If so, mark it as
 		// such, insert it, and continue.
 		shouldKeep := false
@@ -358,11 +358,11 @@ func NewSummaryAllocationSet(as *AllocationSet, filter AllocationFilter, kfs []A
 		}
 	}
 
-	for key := range as.externalKeys {
+	for key := range as.ExternalKeys {
 		sas.externalKeys[key] = true
 	}
 
-	for key := range as.idleKeys {
+	for key := range as.IdleKeys {
 		sas.idleKeys[key] = true
 	}
 
@@ -1313,27 +1313,27 @@ func (sasr *SummaryAllocationSetRange) InsertExternalAllocations(that *Allocatio
 	}
 
 	var err error
-	that.Each(func(j int, thatAS *AllocationSet) {
+	for _, thatAS := range that.Allocations {
 		if thatAS == nil || err != nil {
-			return
+			continue
 		}
 
 		// Find matching AllocationSet in asr
 		i, ok := keys[thatAS.Window.String()]
 		if !ok {
 			err = fmt.Errorf("cannot merge AllocationSet into window that does not exist: %s", thatAS.Window.String())
-			return
+			continue
 		}
 		sas := sasr.SummaryAllocationSets[i]
 
 		// Insert each Allocation from the given set
-		thatAS.Each(func(k string, alloc *Allocation) {
+		for _, alloc := range thatAS.Allocations {
 			externalSA := NewSummaryAllocation(alloc, true, true)
 			// This error will be returned below
 			// TODO:CLEANUP should Each have early-error-return functionality?
 			err = sas.Insert(externalSA)
-		})
-	})
+		}
+	}
 
 	// err might be nil
 	return err

+ 120 - 116
pkg/kubecost/totals.go

@@ -112,10 +112,10 @@ func (art *AllocationTotals) TotalCost() float64 {
 func ComputeAllocationTotals(as *AllocationSet, prop string) map[string]*AllocationTotals {
 	arts := map[string]*AllocationTotals{}
 
-	as.Each(func(name string, alloc *Allocation) {
+	for _, alloc := range as.Allocations {
 		// Do not count idle or unmounted allocations
 		if alloc.IsIdle() || alloc.IsUnmounted() {
-			return
+			continue
 		}
 
 		// Default to computing totals by Cluster, but allow override to use Node.
@@ -163,7 +163,7 @@ func ComputeAllocationTotals(as *AllocationSet, prop string) map[string]*Allocat
 
 		arts[key].RAMCost += alloc.RAMCost
 		arts[key].RAMCostAdjustment += alloc.RAMCostAdjustment
-	})
+	}
 
 	return arts
 }
@@ -303,139 +303,143 @@ func ComputeAssetTotals(as *AssetSet, prop AssetProperty) map[string]*AssetTotal
 	nodeNames := map[string]bool{}
 	disks := map[string]*Disk{}
 
-	as.Each(func(name string, asset Asset) {
-		if node, ok := asset.(*Node); ok {
-			// Default to computing totals by Cluster, but allow override to use Node.
-			key := node.Properties().Cluster
-			if prop == AssetNodeProp {
-				key = fmt.Sprintf("%s/%s", node.Properties().Cluster, node.Properties().Name)
-			}
+	for _, node := range as.Nodes {
+		// Default to computing totals by Cluster, but allow override to use Node.
+		key := node.Properties.Cluster
+		if prop == AssetNodeProp {
+			key = fmt.Sprintf("%s/%s", node.Properties.Cluster, node.Properties.Name)
+		}
 
-			// Add node name to list of node names. (These are to be used later
-			// for attached volumes.)
-			nodeNames[fmt.Sprintf("%s/%s", node.Properties().Cluster, node.Properties().Name)] = true
-
-			// adjustmentRate is used to scale resource costs proportionally
-			// by the adjustment. This is necessary because we only get one
-			// adjustment per Node, not one per-resource-per-Node.
-			//
-			// e.g. total cost =  $90 (cost = $100, adjustment = -$10)  => 0.9000 ( 90 / 100)
-			// e.g. total cost = $150 (cost = $450, adjustment = -$300) => 0.3333 (150 / 450)
-			// e.g. total cost = $150 (cost = $100, adjustment = $50)   => 1.5000 (150 / 100)
-			adjustmentRate := 1.0
-			if node.TotalCost()-node.Adjustment() == 0 {
-				// If (totalCost - adjustment) is 0.0 then adjustment cancels
-				// the entire node cost and we should make everything 0
-				// without dividing by 0.
-				adjustmentRate = 0.0
-				log.DedupedWarningf(5, "ComputeTotals: node cost adjusted to $0.00 for %s", node.Properties().Name)
-			} else if node.Adjustment() != 0.0 {
-				// adjustmentRate is the ratio of cost-with-adjustment (i.e. TotalCost)
-				// to cost-without-adjustment (i.e. TotalCost - Adjustment).
-				adjustmentRate = node.TotalCost() / (node.TotalCost() - node.Adjustment())
-			}
+		// Add node name to list of node names. (These are to be used later
+		// for attached volumes.)
+		nodeNames[fmt.Sprintf("%s/%s", node.Properties.Cluster, node.Properties.Name)] = true
+
+		// adjustmentRate is used to scale resource costs proportionally
+		// by the adjustment. This is necessary because we only get one
+		// adjustment per Node, not one per-resource-per-Node.
+		//
+		// e.g. total cost =  $90 (cost = $100, adjustment = -$10)  => 0.9000 ( 90 / 100)
+		// e.g. total cost = $150 (cost = $450, adjustment = -$300) => 0.3333 (150 / 450)
+		// e.g. total cost = $150 (cost = $100, adjustment = $50)   => 1.5000 (150 / 100)
+		adjustmentRate := 1.0
+		if node.TotalCost()-node.Adjustment == 0 {
+			// If (totalCost - adjustment) is 0.0 then adjustment cancels
+			// the entire node cost and we should make everything 0
+			// without dividing by 0.
+			adjustmentRate = 0.0
+			log.DedupedWarningf(5, "ComputeTotals: node cost adjusted to $0.00 for %s", node.Properties.Name)
+		} else if node.Adjustment != 0.0 {
+			// adjustmentRate is the ratio of cost-with-adjustment (i.e. TotalCost)
+			// to cost-without-adjustment (i.e. TotalCost - Adjustment).
+			adjustmentRate = node.TotalCost() / (node.TotalCost() - node.Adjustment)
+		}
 
-			// 1. Start with raw, measured resource cost
-			// 2. Apply discount to get discounted resource cost
-			// 3. Apply adjustment to get final "adjusted" resource cost
-			// 4. Subtract (3 - 2) to get adjustment in doller-terms
-			// 5. Use (2 + 4) as total cost, so (2) is "cost" and (4) is "adjustment"
-
-			// Example:
-			// - node.CPUCost   = 10.00
-			// - node.Discount  =  0.20  // We assume a 20% discount
-			// - adjustmentRate =  0.75  // CUR says we need to reduce to 75% of our post-discount node cost
-			//
-			// 1. See above
-			// 2. discountedCPUCost = 10.00 * (1.0 - 0.2) =  8.00
-			// 3. adjustedCPUCost   =  8.00 * 0.75        =  6.00  // this is the actual cost according to the CUR
-			// 4. adjustment        =  6.00 - 8.00        = -2.00
-			// 5. totalCost = 6.00, which is the sum of (2) cost = 8.00 and (4) adjustment = -2.00
-
-			discountedCPUCost := node.CPUCost * (1.0 - node.Discount)
-			adjustedCPUCost := discountedCPUCost * adjustmentRate
-			cpuCostAdjustment := adjustedCPUCost - discountedCPUCost
-
-			discountedRAMCost := node.RAMCost * (1.0 - node.Discount)
-			adjustedRAMCost := discountedRAMCost * adjustmentRate
-			ramCostAdjustment := adjustedRAMCost - discountedRAMCost
-
-			adjustedGPUCost := node.GPUCost * adjustmentRate
-			gpuCostAdjustment := adjustedGPUCost - node.GPUCost
+		// 1. Start with raw, measured resource cost
+		// 2. Apply discount to get discounted resource cost
+		// 3. Apply adjustment to get final "adjusted" resource cost
+		// 4. Subtract (3 - 2) to get adjustment in doller-terms
+		// 5. Use (2 + 4) as total cost, so (2) is "cost" and (4) is "adjustment"
+
+		// Example:
+		// - node.CPUCost   = 10.00
+		// - node.Discount  =  0.20  // We assume a 20% discount
+		// - adjustmentRate =  0.75  // CUR says we need to reduce to 75% of our post-discount node cost
+		//
+		// 1. See above
+		// 2. discountedCPUCost = 10.00 * (1.0 - 0.2) =  8.00
+		// 3. adjustedCPUCost   =  8.00 * 0.75        =  6.00  // this is the actual cost according to the CUR
+		// 4. adjustment        =  6.00 - 8.00        = -2.00
+		// 5. totalCost = 6.00, which is the sum of (2) cost = 8.00 and (4) adjustment = -2.00
+
+		discountedCPUCost := node.CPUCost * (1.0 - node.Discount)
+		adjustedCPUCost := discountedCPUCost * adjustmentRate
+		cpuCostAdjustment := adjustedCPUCost - discountedCPUCost
+
+		discountedRAMCost := node.RAMCost * (1.0 - node.Discount)
+		adjustedRAMCost := discountedRAMCost * adjustmentRate
+		ramCostAdjustment := adjustedRAMCost - discountedRAMCost
+
+		adjustedGPUCost := node.GPUCost * adjustmentRate
+		gpuCostAdjustment := adjustedGPUCost - node.GPUCost
 
-			if _, ok := arts[key]; !ok {
-				arts[key] = &AssetTotals{
-					Start:   node.Start(),
-					End:     node.End(),
-					Cluster: node.Properties().Cluster,
-					Node:    node.Properties().Name,
-				}
+		if _, ok := arts[key]; !ok {
+			arts[key] = &AssetTotals{
+				Start:   node.Start,
+				End:     node.End,
+				Cluster: node.Properties.Cluster,
+				Node:    node.Properties.Name,
 			}
+		}
 
-			if arts[key].Start.After(node.Start()) {
-				arts[key].Start = node.Start()
-			}
-			if arts[key].End.Before(node.End()) {
-				arts[key].End = node.End()
-			}
+		if arts[key].Start.After(node.Start) {
+			arts[key].Start = node.Start
+		}
+		if arts[key].End.Before(node.End) {
+			arts[key].End = node.End
+		}
 
-			if arts[key].Node != node.Properties().Name {
-				arts[key].Node = ""
-			}
+		if arts[key].Node != node.Properties.Name {
+			arts[key].Node = ""
+		}
 
-			arts[key].Count++
+		arts[key].Count++
 
-			// TotalCPUCost will be discounted cost + adjustment
-			arts[key].CPUCost += discountedCPUCost
-			arts[key].CPUCostAdjustment += cpuCostAdjustment
+		// TotalCPUCost will be discounted cost + adjustment
+		arts[key].CPUCost += discountedCPUCost
+		arts[key].CPUCostAdjustment += cpuCostAdjustment
 
-			// TotalRAMCost will be discounted cost + adjustment
-			arts[key].RAMCost += discountedRAMCost
-			arts[key].RAMCostAdjustment += ramCostAdjustment
+		// TotalRAMCost will be discounted cost + adjustment
+		arts[key].RAMCost += discountedRAMCost
+		arts[key].RAMCostAdjustment += ramCostAdjustment
+
+		// TotalGPUCost will be discounted cost + adjustment
+		arts[key].GPUCost += node.GPUCost
+		arts[key].GPUCostAdjustment += gpuCostAdjustment
+	}
 
-			// TotalGPUCost will be discounted cost + adjustment
-			arts[key].GPUCost += node.GPUCost
-			arts[key].GPUCostAdjustment += gpuCostAdjustment
-		} else if lb, ok := asset.(*LoadBalancer); ok && prop == AssetClusterProp {
-			// Only record load balancers when prop is Cluster because we
-			// can't break down LoadBalancer by node.
-			key := lb.Properties().Cluster
+	// Only record LoadBalancer and ClusterManagement when prop
+	// is cluster. We can't breakdown these types by Node.
+	if prop == AssetClusterProp {
+		for _, lb := range as.LoadBalancers {
+			key := lb.Properties.Cluster
 
 			if _, ok := arts[key]; !ok {
 				arts[key] = &AssetTotals{
-					Start:   lb.Start(),
-					End:     lb.End(),
-					Cluster: lb.Properties().Cluster,
+					Start:   lb.Start,
+					End:     lb.End,
+					Cluster: lb.Properties.Cluster,
 				}
 			}
 
 			arts[key].Count++
 			arts[key].LoadBalancerCost += lb.Cost
-			arts[key].LoadBalancerCostAdjustment += lb.adjustment
-		} else if cm, ok := asset.(*ClusterManagement); ok && prop == AssetClusterProp {
-			// Only record cluster management when prop is Cluster because we
-			// can't break down ClusterManagement by node.
-			key := cm.Properties().Cluster
+			arts[key].LoadBalancerCostAdjustment += lb.Adjustment
+		}
+
+		for _, cm := range as.ClusterManagement {
+			key := cm.Properties.Cluster
 
 			if _, ok := arts[key]; !ok {
 				arts[key] = &AssetTotals{
-					Start:   cm.Start(),
-					End:     cm.End(),
-					Cluster: cm.Properties().Cluster,
+					Start:   cm.GetStart(),
+					End:     cm.GetEnd(),
+					Cluster: cm.Properties.Cluster,
 				}
 			}
 
 			arts[key].Count++
 			arts[key].ClusterManagementCost += cm.Cost
-			arts[key].ClusterManagementCostAdjustment += cm.adjustment
-		} else if disk, ok := asset.(*Disk); ok {
-			// Record disks in an intermediate structure, which will be
-			// processed after all assets have been seen.
-			key := fmt.Sprintf("%s/%s", disk.Properties().Cluster, disk.Properties().Name)
-
-			disks[key] = disk
+			arts[key].ClusterManagementCostAdjustment += cm.Adjustment
 		}
-	})
+	}
+
+	// Record disks in an intermediate structure, which will be
+	// processed after all assets have been seen.
+	for _, disk := range as.Disks {
+		key := fmt.Sprintf("%s/%s", disk.Properties.Cluster, disk.Properties.Name)
+
+		disks[key] = disk
+	}
 
 	// Record all disks as either attached volumes or persistent volumes.
 	for name, disk := range disks {
@@ -444,18 +448,18 @@ func ComputeAssetTotals(as *AssetSet, prop AssetProperty) map[string]*AssetTotal
 		// reset the key to just the cluster.
 		key := name
 		if prop == AssetClusterProp {
-			key = disk.Properties().Cluster
+			key = disk.Properties.Cluster
 		}
 
 		if _, ok := arts[key]; !ok {
 			arts[key] = &AssetTotals{
-				Start:   disk.Start(),
-				End:     disk.End(),
-				Cluster: disk.Properties().Cluster,
+				Start:   disk.Start,
+				End:     disk.End,
+				Cluster: disk.Properties.Cluster,
 			}
 
 			if prop == AssetNodeProp {
-				arts[key].Node = disk.Properties().Name
+				arts[key].Node = disk.Properties.Name
 			}
 		}
 
@@ -466,14 +470,14 @@ func ComputeAssetTotals(as *AssetSet, prop AssetProperty) map[string]*AssetTotal
 			// TODO can we make a stronger match at the underlying ETL layer?
 			arts[key].Count++
 			arts[key].AttachedVolumeCost += disk.Cost
-			arts[key].AttachedVolumeCostAdjustment += disk.adjustment
+			arts[key].AttachedVolumeCostAdjustment += disk.Adjustment
 		} else if prop == AssetClusterProp {
 			// Here, we're looking at a PersistentVolume because we're not
 			// looking at an AttachedVolume. Only record PersistentVolume data
 			// at the cluster level (i.e. prop == AssetClusterProp).
 			arts[key].Count++
 			arts[key].PersistentVolumeCost += disk.Cost
-			arts[key].PersistentVolumeCostAdjustment += disk.adjustment
+			arts[key].PersistentVolumeCostAdjustment += disk.Adjustment
 		}
 	}
 

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff