Parcourir la source

interfaces in cloudcost item and kubecost assetset and asset needed for matching billed vs monitored resources

Signed-off-by: Alan Rodrigues <alanr5691@yahoo.com>
Signed-off-by: Logan Ballard <loganballard@gmail.com>
Alan Rodrigues il y a 3 ans
Parent
commit
15afae3d69
2 fichiers modifiés avec 90 ajouts et 0 suppressions
  1. 30 0
      pkg/kubecost/asset.go
  2. 60 0
      pkg/kubecost/cloudcostitem.go

+ 30 - 0
pkg/kubecost/asset.go

@@ -2157,6 +2157,22 @@ func (n *Node) GPUs() float64 {
 	return n.GPUHours * (60.0 / n.Minutes())
 }
 
+func (n *Node) MonitoringKey() string {
+	nodeProps := n.GetProperties()
+	if nodeProps == nil {
+		return ""
+	}
+	//TO-DO: For Alibaba investigate why cloudCost ProviderID doesnt match Kubecost ProviderID via Kubernetes API
+	if nodeProps.Provider == AlibabaProvider {
+		aliProviderID := strings.Split(nodeProps.ProviderID, ".")
+		if len(aliProviderID) != 2 {
+			return ""
+		}
+		return nodeProps.Provider + "/" + nodeProps.Account + "/" + aliProviderID[1]
+	}
+	return nodeProps.Provider + "/" + nodeProps.Account + "/" + nodeProps.ProviderID
+}
+
 // LoadBalancer is an Asset representing a single load balancer in a cluster
 // TODO: add GB of ingress processed, numForwardingRules once we start recording those to prometheus metric
 type LoadBalancer struct {
@@ -3163,6 +3179,20 @@ func (as *AssetSet) accumulate(that *AssetSet) (*AssetSet, error) {
 	return acc, nil
 }
 
+func (as *AssetSet) MonitoredPropsOfCloudCostItem(cci *CloudCostItem) (time.Time, string, string) {
+	for _, node := range as.Nodes {
+		if node.MonitoringKey() == cci.MonitoringKey() {
+			props := node.GetProperties()
+			if props == nil {
+				continue
+			}
+			// To-DO: No match between cluster ID and Node here?
+			return node.End, props.Cluster, ""
+		}
+	}
+	return time.Time{}, "", ""
+}
+
 type DiffKind string
 
 const (

+ 60 - 0
pkg/kubecost/cloudcostitem.go

@@ -70,6 +70,10 @@ func (ccip CloudCostItemProperties) Key() string {
 	return fmt.Sprintf("%s/%s/%s/%s/%s/%s", ccip.Provider, ccip.BillingID, ccip.WorkGroupID, ccip.Category, ccip.Service, ccip.ProviderID)
 }
 
+func (ccip CloudCostItemProperties) MonitoringKey() string {
+	return fmt.Sprintf("%s/%s/%s", ccip.Provider, ccip.WorkGroupID, ccip.ProviderID)
+}
+
 // CloudCostItem represents a CUR line item, identifying a cloud resource and
 // its cost over some period of time.
 type CloudCostItem struct {
@@ -128,6 +132,10 @@ func (cci *CloudCostItem) add(that *CloudCostItem) {
 	cci.Window = cci.Window.Expand(that.Window)
 }
 
+func (cci *CloudCostItem) MonitoringKey() string {
+	return cci.Properties.MonitoringKey()
+}
+
 type CloudCostItemSet struct {
 	CloudCostItems map[string]*CloudCostItem `json:"items"`
 	Window         Window                    `json:"window"`
@@ -149,6 +157,42 @@ func NewCloudCostItemSet(start, end time.Time, cloudCostItems ...*CloudCostItem)
 	return ccis
 }
 
+func (ccis *CloudCostItemSet) Accumulate(that *CloudCostItemSet) (*CloudCostItemSet, error) {
+	if ccis.IsEmpty() {
+		return that.Clone(), nil
+	}
+
+	if that.IsEmpty() {
+		return ccis.Clone(), nil
+	}
+	// Set start, end to min(start), max(end)
+	start := ccis.Window.Start()
+	end := ccis.Window.End()
+	if that.Window.Start().Before(*start) {
+		start = that.Window.Start()
+	}
+	if that.Window.End().After(*end) {
+		end = that.Window.End()
+	}
+
+	acc := NewCloudCostItemSet(*start, *end)
+
+	for _, cci := range ccis.CloudCostItems {
+		err := acc.Insert(cci)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	for _, cci := range that.CloudCostItems {
+		err := acc.Insert(cci)
+		if err != nil {
+			return nil, err
+		}
+	}
+	return acc, nil
+}
+
 func (ccis *CloudCostItemSet) Equal(that *CloudCostItemSet) bool {
 	if ccis.Integration != that.Integration {
 		return false
@@ -319,6 +363,22 @@ func (ccisr *CloudCostItemSetRange) Clone() *CloudCostItemSetRange {
 	}
 }
 
+// Accumulate sums each CloudCostItemSet in the given range, returning a single cumulative
+// CloudCostItemSet for the entire range.
+func (ccisr *CloudCostItemSetRange) Accumulate() (*CloudCostItemSet, error) {
+	var cloudCostItemSet *CloudCostItemSet
+	var err error
+
+	for _, ccis := range ccisr.CloudCostItemSets {
+		cloudCostItemSet, err = cloudCostItemSet.Accumulate(ccis)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	return cloudCostItemSet, nil
+}
+
 // LoadCloudCostItem loads CloudCostItems into existing CloudCostItemSets of the CloudCostItemSetRange.
 // This function service to aggregate and distribute costs over predefined windows
 // are accumulated here so that the resulting CloudCostItem with the 1d window has the correct price for the entire day.