forked from opencost/opencost
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
125 lines (102 loc) · 3.16 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package main
import (
"encoding/json"
"log"
"net/http"
"os"
"github.com/julienschmidt/httprouter"
costAnalyzerCloud "github.com/kubecost/cost-model/cloud"
costModel "github.com/kubecost/cost-model/costmodel"
prometheusClient "github.com/prometheus/client_golang/api"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
)
type Accesses struct {
PrometheusClient prometheusClient.Client
KubeClientSet *kubernetes.Clientset
Cloud costAnalyzerCloud.Provider
}
type DataEnvelope struct {
Code int `json:"code"`
Status string `json:"status"`
Data interface{} `json:"data"`
Message string `json:"message,omitempty"`
}
func wrapData(data interface{}, err error) []byte {
var resp []byte
if err != nil {
resp, _ = json.Marshal(&DataEnvelope{
Code: 500,
Status: "error",
Message: err.Error(),
Data: data,
})
} else {
resp, _ = json.Marshal(&DataEnvelope{
Code: 200,
Status: "success",
Data: data,
})
}
return resp
}
func (a *Accesses) RefreshPricingData(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Access-Control-Allow-Origin", "*")
err := a.Cloud.DownloadPricingData()
w.Write(wrapData(nil, err))
}
func (a *Accesses) CostDataModel(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Access-Control-Allow-Origin", "*")
window := r.URL.Query().Get("timeWindow")
data, err := costModel.ComputeCostData(a.PrometheusClient, a.KubeClientSet, a.Cloud, window)
w.Write(wrapData(data, err))
}
func (a *Accesses) CostDataModelRange(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Access-Control-Allow-Origin", "*")
start := r.URL.Query().Get("start")
end := r.URL.Query().Get("end")
window := r.URL.Query().Get("window")
data, err := costModel.ComputeCostDataRange(a.PrometheusClient, a.KubeClientSet, a.Cloud, start, end, window)
w.Write(wrapData(data, err))
}
func main() {
address := os.Getenv("PROMETHEUS_SERVER_ENDPOINT")
if address == "" {
log.Fatal("No address for prometheus set. Aborting.")
}
pc := prometheusClient.Config{
Address: address,
}
promCli, _ := prometheusClient.NewClient(pc)
// Kubernetes API setup
kc, err := rest.InClusterConfig()
if err != nil {
panic(err.Error())
}
kubeClientset, err := kubernetes.NewForConfig(kc)
if err != nil {
panic(err.Error())
}
cloudProviderKey := os.Getenv("CLOUD_PROVIDER_API_KEY")
cloudProvider, err := costAnalyzerCloud.NewProvider(kubeClientset, cloudProviderKey)
if err != nil {
panic(err.Error())
}
a := Accesses{
PrometheusClient: promCli,
KubeClientSet: kubeClientset,
Cloud: cloudProvider,
}
err = a.Cloud.DownloadPricingData()
if err != nil {
log.Printf("Failed to download pricing data: " + err.Error())
}
router := httprouter.New()
router.GET("/costDataModel", a.CostDataModel)
router.GET("/costDataModelRange", a.CostDataModelRange)
router.POST("/refreshPricing", a.RefreshPricingData)
log.Fatal(http.ListenAndServe(":9003", router))
}