Просмотр исходного кода

Merge pull request #241 from kubecost/kubecon-demo

Adding in the stubs for GCP Reserved Instances. This is tested to be …
Ajay Tripathy 6 лет назад
Родитель
Сommit
bfddb82557
2 измененных файлов с 159 добавлено и 0 удалено
  1. 39 0
      cloud/awsprovider.go
  2. 120 0
      cloud/gcpprovider.go

+ 39 - 0
cloud/awsprovider.go

@@ -1401,3 +1401,42 @@ func parseSpotData(bucket string, prefix string, projectID string, region string
 	}
 	return spots, nil
 }
+
+/*
+func (aws *AWS) getReservedInstances() ([]interface{}, error) {
+	customPricing, err := a.GetConfig()
+	if err != nil {
+		return nil, err
+	}
+	if customPricing.ServiceKeyName != "" {
+		err = os.Setenv(awsAccessKeyIDEnvVar, customPricing.ServiceKeyName)
+		if err != nil {
+			return nil, err
+		}
+		err = os.Setenv(awsAccessKeySecretEnvVar, customPricing.ServiceKeySecret)
+		if err != nil {
+			return nil, err
+		}
+	}
+	athenaConfigs, err := os.Open("/var/configs/athena.json")
+	if err != nil {
+		return nil, err
+	}
+	defer athenaConfigs.Close()
+	b, err := ioutil.ReadAll(athenaConfigs)
+	if err != nil {
+		return nil, err
+	}
+	var athenaConf map[string]string
+	json.Unmarshal([]byte(b), &athenaConf)
+	region := aws.String(customPricing.AthenaRegion)
+
+	c := &aws.Config{
+		Region: region,
+	}
+	s := session.Must(session.NewSession(c))
+	svc := ec2.New(s)
+
+	svc.DescribeReservedInstances()
+}
+*/

+ 120 - 0
cloud/gcpprovider.go

@@ -14,6 +14,7 @@ import (
 	"strconv"
 	"strings"
 	"sync"
+	"time"
 
 	"k8s.io/klog"
 
@@ -704,6 +705,16 @@ func (gcp *GCP) DownloadPricingData() error {
 		pvkeys[key.Features()] = key
 	}
 
+	reserved, err := gcp.getReservedInstances()
+	if err != nil {
+		klog.V(1).Infof("Failed to lookup reserved instance data: %s", err.Error())
+	} else {
+		klog.V(1).Infof("Found %d reserved instances", len(reserved))
+		for _, r := range reserved {
+			klog.V(1).Infof("Reserved: CPU: %d, RAM: %d", r.ReservedCPU, r.ReservedRAM)
+		}
+	}
+
 	pages, err := gcp.parsePages(inputkeys, pvkeys)
 
 	if err != nil {
@@ -750,6 +761,115 @@ func (c *GCP) NetworkPricing() (*Network, error) {
 	}, nil
 }
 
+const (
+	GCPReservedInstanceResourceTypeRAM string = "MEMORY"
+	GCPReservedInstanceResourceTypeCPU string = "VCPU"
+	GCPReservedInstanceStatusActive    string = "ACTIVE"
+	GCPReservedInstancePlanOneYear     string = "TWELVE_MONTH"
+	GCPReservedInstancePlanThreeYear   string = "THIRTY_SIX_MONTH"
+)
+
+type GCPReservedInstancePlan struct {
+	Name    string
+	CPUCost float64
+	RAMCost float64
+}
+
+type GCPReservedInstance struct {
+	ReservedRAM int64
+	ReservedCPU int64
+	Plan        *GCPReservedInstancePlan
+	StartDate   time.Time
+	EndDate     time.Time
+	Region      string
+}
+
+// Two available Reservation plans for GCP, 1-year and 3-year
+var gcpReservedInstancePlans map[string]*GCPReservedInstancePlan = map[string]*GCPReservedInstancePlan{
+	GCPReservedInstancePlanOneYear: &GCPReservedInstancePlan{
+		Name:    GCPReservedInstancePlanOneYear,
+		CPUCost: 0.019915,
+		RAMCost: 0.002669,
+	},
+	GCPReservedInstancePlanThreeYear: &GCPReservedInstancePlan{
+		Name:    GCPReservedInstancePlanThreeYear,
+		CPUCost: 0.014225,
+		RAMCost: 0.001907,
+	},
+}
+
+func (gcp *GCP) getReservedInstances() ([]*GCPReservedInstance, error) {
+	var results []*GCPReservedInstance
+
+	ctx := context.Background()
+	computeService, err := compute.NewService(ctx)
+	if err != nil {
+		return nil, err
+	}
+
+	commitments, err := computeService.RegionCommitments.AggregatedList(gcp.ProjectID).Do()
+	if err != nil {
+		return nil, err
+	}
+
+	for regionKey, commitList := range commitments.Items {
+		for _, commit := range commitList.Commitments {
+			if commit.Status != GCPReservedInstanceStatusActive {
+				continue
+			}
+
+			var vcpu int64 = 0
+			var ram int64 = 0
+			for _, resource := range commit.Resources {
+				switch resource.Type {
+				case GCPReservedInstanceResourceTypeRAM:
+					ram = resource.Amount
+				case GCPReservedInstanceResourceTypeCPU:
+					vcpu = resource.Amount
+				default:
+					klog.V(4).Infof("Failed to handle resource type: %s", resource.Type)
+				}
+			}
+
+			var region string
+			regionStr := strings.Split(regionKey, "/")
+			if len(regionStr) == 2 {
+				region = regionStr[1]
+			}
+
+			timeLayout := "2006-01-02T15:04:05Z07:00"
+			startTime, err := time.Parse(timeLayout, commit.StartTimestamp)
+			if err != nil {
+				klog.V(1).Infof("Failed to parse start date: %s", commit.StartTimestamp)
+				continue
+			}
+
+			endTime, err := time.Parse(timeLayout, commit.EndTimestamp)
+			if err != nil {
+				klog.V(1).Infof("Failed to parse end date: %s", commit.EndTimestamp)
+				continue
+			}
+
+			// Look for a plan based on the name. Default to One Year if it fails
+			plan, ok := gcpReservedInstancePlans[commit.Plan]
+			if !ok {
+				plan = gcpReservedInstancePlans[GCPReservedInstancePlanOneYear]
+			}
+
+			results = append(results, &GCPReservedInstance{
+				Region:      region,
+				ReservedRAM: ram,
+				ReservedCPU: vcpu,
+				Plan:        plan,
+				StartDate:   startTime,
+				EndDate:     endTime,
+			})
+		}
+	}
+
+	return results, nil
+}
+
 type pvKey struct {
 	Labels                 map[string]string
 	StorageClass           string