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

update router data envelope to use core

Matt Bolt 1 год назад
Родитель
Сommit
5167aef6de
1 измененных файлов с 36 добавлено и 158 удалено
  1. 36 158
      pkg/costmodel/router.go

+ 36 - 158
pkg/costmodel/router.go

@@ -13,6 +13,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/opencost/opencost/core/pkg/protocol"
 	"github.com/opencost/opencost/core/pkg/source"
 	"github.com/opencost/opencost/core/pkg/util/retry"
 	"github.com/opencost/opencost/core/pkg/util/timeutil"
@@ -59,6 +60,8 @@ const (
 var (
 	// gitCommit is set by the build system
 	gitCommit string
+
+	proto = protocol.HTTP()
 )
 
 // Accesses defines a singleton application instance, providing access to
@@ -107,14 +110,6 @@ func (a *Accesses) GetCacheRefresh(dur time.Duration) time.Duration {
 	return mins
 }
 
-type Response struct {
-	Code    int         `json:"code"`
-	Status  string      `json:"status"`
-	Data    interface{} `json:"data"`
-	Message string      `json:"message,omitempty"`
-	Warning string      `json:"warning,omitempty"`
-}
-
 // FilterFunc is a filter that returns true iff the given CostData should be filtered out, and the environment that was used as the filter criteria, if it was an aggregate
 type FilterFunc func(*CostData) (bool, string)
 
@@ -195,101 +190,13 @@ func ParsePercentString(percentStr string) (float64, error) {
 	return discount, nil
 }
 
-func WrapData(data interface{}, err error) []byte {
-	var resp []byte
-
-	if err != nil {
-		log.Errorf("Error returned to client: %s", err.Error())
-		resp, _ = json.Marshal(&Response{
-			Code:    http.StatusInternalServerError,
-			Status:  "error",
-			Message: err.Error(),
-			Data:    data,
-		})
-	} else {
-		resp, err = json.Marshal(&Response{
-			Code:   http.StatusOK,
-			Status: "success",
-			Data:   data,
-		})
-		if err != nil {
-			log.Errorf("error marshaling response json: %s", err.Error())
-		}
-	}
-
-	return resp
-}
-
-func WrapDataWithMessage(data interface{}, err error, message string) []byte {
-	var resp []byte
-
-	if err != nil {
-		log.Errorf("Error returned to client: %s", err.Error())
-		resp, _ = json.Marshal(&Response{
-			Code:    http.StatusInternalServerError,
-			Status:  "error",
-			Message: err.Error(),
-			Data:    data,
-		})
-	} else {
-		resp, _ = json.Marshal(&Response{
-			Code:    http.StatusOK,
-			Status:  "success",
-			Data:    data,
-			Message: message,
-		})
-	}
-
-	return resp
-}
-
-func WrapDataWithWarning(data interface{}, err error, warning string) []byte {
-	var resp []byte
-
-	if err != nil {
-		log.Errorf("Error returned to client: %s", err.Error())
-		resp, _ = json.Marshal(&Response{
-			Code:    http.StatusInternalServerError,
-			Status:  "error",
-			Message: err.Error(),
-			Warning: warning,
-			Data:    data,
-		})
-	} else {
-		resp, _ = json.Marshal(&Response{
-			Code:    http.StatusOK,
-			Status:  "success",
-			Data:    data,
-			Warning: warning,
-		})
-	}
-
-	return resp
-}
-
-func WrapDataWithMessageAndWarning(data interface{}, err error, message, warning string) []byte {
-	var resp []byte
-
+func WriteData(w http.ResponseWriter, data interface{}, err error) {
 	if err != nil {
-		log.Errorf("Error returned to client: %s", err.Error())
-		resp, _ = json.Marshal(&Response{
-			Code:    http.StatusInternalServerError,
-			Status:  "error",
-			Message: err.Error(),
-			Warning: warning,
-			Data:    data,
-		})
-	} else {
-		resp, _ = json.Marshal(&Response{
-			Code:    http.StatusOK,
-			Status:  "success",
-			Data:    data,
-			Message: message,
-			Warning: warning,
-		})
+		proto.WriteError(w, proto.InternalServerError(err.Error()))
+		return
 	}
 
-	return resp
+	proto.WriteData(w, data)
 }
 
 // RefreshPricingData needs to be called when a new node joins the fleet, since we cache the relevant subsets of pricing data to avoid storing the whole thing.
@@ -302,7 +209,7 @@ func (a *Accesses) RefreshPricingData(w http.ResponseWriter, r *http.Request, ps
 		log.Errorf("Error refreshing pricing data: %s", err.Error())
 	}
 
-	w.Write(WrapData(nil, err))
+	WriteData(w, nil, err)
 }
 
 func (a *Accesses) CostDataModel(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
@@ -316,7 +223,7 @@ func (a *Accesses) CostDataModel(w http.ResponseWriter, r *http.Request, ps http
 
 	duration, err := timeutil.ParseDuration(window)
 	if err != nil {
-		w.Write(WrapData(nil, fmt.Errorf("error parsing window (%s): %s", window, err)))
+		WriteData(w, nil, fmt.Errorf("error parsing window (%s): %s", window, err))
 		return
 	}
 
@@ -324,7 +231,7 @@ func (a *Accesses) CostDataModel(w http.ResponseWriter, r *http.Request, ps http
 	if offset != "" {
 		offsetDur, err := timeutil.ParseDuration(offset)
 		if err != nil {
-			w.Write(WrapData(nil, fmt.Errorf("error parsing offset (%s): %s", offset, err)))
+			WriteData(w, nil, fmt.Errorf("error parsing offset (%s): %s", offset, err))
 			return
 		}
 
@@ -346,9 +253,9 @@ func (a *Accesses) CostDataModel(w http.ResponseWriter, r *http.Request, ps http
 
 	if fields != "" {
 		filteredData := filterFields(fields, data)
-		w.Write(WrapData(filteredData, err))
+		WriteData(w, filteredData, err)
 	} else {
-		w.Write(WrapData(data, err))
+		WriteData(w, data, err)
 	}
 }
 
@@ -357,25 +264,24 @@ func (a *Accesses) GetAllNodePricing(w http.ResponseWriter, r *http.Request, ps
 	w.Header().Set("Access-Control-Allow-Origin", "*")
 
 	data, err := a.CloudProvider.AllNodePricing()
-	w.Write(WrapData(data, err))
+	WriteData(w, data, err)
 }
 
 func (a *Accesses) GetConfigs(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
 	w.Header().Set("Content-Type", "application/json")
 	w.Header().Set("Access-Control-Allow-Origin", "*")
+
 	data, err := a.CloudProvider.GetConfig()
-	w.Write(WrapData(data, err))
+	WriteData(w, data, err)
 }
 
 func (a *Accesses) UpdateSpotInfoConfigs(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
 	w.Header().Set("Content-Type", "application/json")
 	w.Header().Set("Access-Control-Allow-Origin", "*")
+
 	data, err := a.CloudProvider.UpdateConfig(r.Body, aws.SpotInfoUpdateType)
-	if err != nil {
-		w.Write(WrapData(data, err))
-		return
-	}
-	w.Write(WrapData(data, err))
+	WriteData(w, data, nil)
+
 	err = a.CloudProvider.DownloadPricingData()
 	if err != nil {
 		log.Errorf("Error redownloading data on config update: %s", err.Error())
@@ -385,23 +291,17 @@ func (a *Accesses) UpdateSpotInfoConfigs(w http.ResponseWriter, r *http.Request,
 func (a *Accesses) UpdateAthenaInfoConfigs(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
 	w.Header().Set("Content-Type", "application/json")
 	w.Header().Set("Access-Control-Allow-Origin", "*")
+
 	data, err := a.CloudProvider.UpdateConfig(r.Body, aws.AthenaInfoUpdateType)
-	if err != nil {
-		w.Write(WrapData(data, err))
-		return
-	}
-	w.Write(WrapData(data, err))
+	WriteData(w, data, err)
 }
 
 func (a *Accesses) UpdateBigQueryInfoConfigs(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
 	w.Header().Set("Content-Type", "application/json")
 	w.Header().Set("Access-Control-Allow-Origin", "*")
+
 	data, err := a.CloudProvider.UpdateConfig(r.Body, gcp.BigqueryUpdateType)
-	if err != nil {
-		w.Write(WrapData(data, err))
-		return
-	}
-	w.Write(WrapData(data, err))
+	WriteData(w, data, err)
 }
 
 func (a *Accesses) UpdateAzureStorageConfigs(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
@@ -409,21 +309,17 @@ func (a *Accesses) UpdateAzureStorageConfigs(w http.ResponseWriter, r *http.Requ
 	w.Header().Set("Access-Control-Allow-Origin", "*")
 	data, err := a.CloudProvider.UpdateConfig(r.Body, azure.AzureStorageUpdateType)
 	if err != nil {
-		w.Write(WrapData(data, err))
+		WriteData(w, nil, err)
 		return
 	}
-	w.Write(WrapData(data, err))
+	WriteData(w, data, err)
 }
 
 func (a *Accesses) UpdateConfigByKey(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
 	w.Header().Set("Content-Type", "application/json")
 	w.Header().Set("Access-Control-Allow-Origin", "*")
 	data, err := a.CloudProvider.UpdateConfig(r.Body, "")
-	if err != nil {
-		w.Write(WrapData(data, err))
-		return
-	}
-	w.Write(WrapData(data, err))
+	WriteData(w, data, err)
 }
 
 func (a *Accesses) ManagementPlatform(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
@@ -431,11 +327,7 @@ func (a *Accesses) ManagementPlatform(w http.ResponseWriter, r *http.Request, ps
 	w.Header().Set("Access-Control-Allow-Origin", "*")
 
 	data, err := a.CloudProvider.GetManagementPlatform()
-	if err != nil {
-		w.Write(WrapData(data, err))
-		return
-	}
-	w.Write(WrapData(data, err))
+	WriteData(w, data, err)
 }
 
 func (a *Accesses) ClusterInfo(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
@@ -444,7 +336,7 @@ func (a *Accesses) ClusterInfo(w http.ResponseWriter, r *http.Request, ps httpro
 
 	data := a.ClusterInfoProvider.GetClusterInfo()
 
-	w.Write(WrapData(data, nil))
+	WriteData(w, data, nil)
 }
 
 func (a *Accesses) GetClusterInfoMap(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
@@ -453,28 +345,30 @@ func (a *Accesses) GetClusterInfoMap(w http.ResponseWriter, r *http.Request, ps
 
 	data := a.ClusterMap.AsMap()
 
-	w.Write(WrapData(data, nil))
+	WriteData(w, data, nil)
 }
 
 func (a *Accesses) GetServiceAccountStatus(w http.ResponseWriter, _ *http.Request, _ httprouter.Params) {
 	w.Header().Set("Content-Type", "application/json")
 	w.Header().Set("Access-Control-Allow-Origin", "*")
 
-	w.Write(WrapData(a.CloudProvider.ServiceAccountStatus(), nil))
+	WriteData(w, a.CloudProvider.ServiceAccountStatus(), nil)
 }
 
 func (a *Accesses) GetPricingSourceStatus(w http.ResponseWriter, _ *http.Request, _ httprouter.Params) {
 	w.Header().Set("Content-Type", "application/json")
 	w.Header().Set("Access-Control-Allow-Origin", "*")
 
-	w.Write(WrapData(a.CloudProvider.PricingSourceStatus(), nil))
+	data := a.CloudProvider.PricingSourceStatus()
+	WriteData(w, data, nil)
 }
 
 func (a *Accesses) GetPricingSourceCounts(w http.ResponseWriter, _ *http.Request, _ httprouter.Params) {
 	w.Header().Set("Content-Type", "application/json")
 	w.Header().Set("Access-Control-Allow-Origin", "*")
 
-	w.Write(WrapData(a.Model.GetPricingSourceCounts()))
+	data, err := a.Model.GetPricingSourceCounts()
+	WriteData(w, data, err)
 }
 
 func (a *Accesses) GetPricingSourceSummary(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
@@ -482,7 +376,7 @@ func (a *Accesses) GetPricingSourceSummary(w http.ResponseWriter, r *http.Reques
 	w.Header().Set("Access-Control-Allow-Origin", "*")
 
 	data := a.CloudProvider.PricingSourceSummary()
-	w.Write(WrapData(data, nil))
+	WriteData(w, data, nil)
 }
 
 func (a *Accesses) GetOrphanedPods(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
@@ -532,7 +426,7 @@ func (a *Accesses) GetInstallInfo(w http.ResponseWriter, r *http.Request, _ http
 
 	containers, err := GetKubecostContainers(a.KubeClientSet)
 	if err != nil {
-		writeErrorResponse(w, 500, fmt.Sprintf("Unable to list pods: %s", err.Error()))
+		http.Error(w, fmt.Sprintf("Unable to list pods: %s", err.Error()), http.StatusInternalServerError)
 		return
 	}
 
@@ -550,7 +444,7 @@ func (a *Accesses) GetInstallInfo(w http.ResponseWriter, r *http.Request, _ http
 
 	body, err := json.Marshal(info)
 	if err != nil {
-		writeErrorResponse(w, 500, fmt.Sprintf("Error decoding pod: %s", err.Error()))
+		http.Error(w, fmt.Sprintf("Error decoding pod: %s", err.Error()), http.StatusInternalServerError)
 		return
 	}
 
@@ -812,19 +706,3 @@ func InitializeCustomCost(router *httprouter.Router) *customcost.PipelineService
 
 	return customCostPipelineService
 }
-
-func writeErrorResponse(w http.ResponseWriter, code int, message string) {
-	out := map[string]string{
-		"message": message,
-	}
-	bytes, err := json.Marshal(out)
-	if err != nil {
-		w.Header().Set("Content-Type", "text/plain")
-		w.WriteHeader(500)
-		fmt.Fprint(w, "unable to marshall json for error")
-		log.Warnf("Failed to marshall JSON for error response: %s", err.Error())
-		return
-	}
-	w.WriteHeader(code)
-	fmt.Fprint(w, string(bytes))
-}