diff --git a/go.mod b/go.mod index d80d95a..f260518 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,8 @@ go 1.21.5 require ( cloud.google.com/go/compute v1.25.1 + cloud.google.com/go/monitoring v1.18.0 + github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.38.6 github.com/google/uuid v1.6.0 github.com/kaytu-io/kaytu v0.10.5 golang.org/x/oauth2 v0.21.0 @@ -13,6 +15,7 @@ require ( require ( cloud.google.com/go/compute/metadata v0.3.0 // indirect + github.com/aws/smithy-go v1.20.2 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect @@ -25,14 +28,17 @@ require ( github.com/spf13/cobra v1.8.0 // indirect github.com/spf13/pflag v1.0.5 // indirect go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect golang.org/x/crypto v0.24.0 // indirect golang.org/x/net v0.26.0 // indirect + golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.21.0 // indirect golang.org/x/text v0.16.0 // indirect + golang.org/x/time v0.5.0 // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240610135401-a8a62080eff3 // indirect diff --git a/go.sum b/go.sum index bf21b3b..66df2df 100644 --- a/go.sum +++ b/go.sum @@ -5,7 +5,13 @@ cloud.google.com/go/compute v1.25.1 h1:ZRpHJedLtTpKgr3RV1Fx23NuaAEN1Zfx9hw1u4aJd cloud.google.com/go/compute v1.25.1/go.mod h1:oopOIR53ly6viBYxaDhBfJwzUAxf1zE//uf3IB011ls= cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/monitoring v1.18.0 h1:NfkDLQDG2UR3WYZVQE8kwSbUIEyIqJUPl+aOQdFH1T4= +cloud.google.com/go/monitoring v1.18.0/go.mod h1:c92vVBCeq/OB4Ioyo+NbN2U7tlg5ZH41PZcdvfc+Lcg= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.38.6 h1:UVjxYe8VGpwXYcmBcciBHlQrNssdEvntXCPWmnRR15U= +github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.38.6/go.mod h1:4V6VDA0kZavRn71+sLpVna75oobnlG+gwtnNcBwZhu4= +github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q= +github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= @@ -79,6 +85,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= @@ -123,6 +131,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= diff --git a/plugin/kaytu/compute_instance.go b/plugin/kaytu/compute_instance.go new file mode 100644 index 0000000..b71a2b3 --- /dev/null +++ b/plugin/kaytu/compute_instance.go @@ -0,0 +1,52 @@ +package kaytu + +import ( + "cloud.google.com/go/monitoring/apiv3/v2/monitoringpb" +) + +type GcpComputeInstance struct { + HashedInstanceId string `json:"hashedInstanceId"` + Zone string `json:"zone"` + MachineType string `json:"machineType"` +} + +type RightsizingGcpComputeInstance struct { + Zone string `json:"zone"` + MachineType string `json:"machineType"` + MachineFamily string `json:"machineFamily"` + CPU int64 `json:"cpu"` + MemoryMb int64 `json:"memoryMb"` + + Cost float64 `json:"cost"` +} + +type GcpComputeInstanceRightsizingRecommendation struct { + Current RightsizingGcpComputeInstance `json:"current"` + Recommended *RightsizingGcpComputeInstance `json:"recommended"` + + CPU Usage `json:"cpu"` + Memory Usage `json:"memory"` + + Description string `json:"description"` +} + +type GcpComputeInstanceWastageRequest struct { + RequestId *string `json:"requestId"` + CliVersion *string `json:"cliVersion"` + Identification map[string]string `json:"identification"` + Instance GcpComputeInstance `json:"instance"` + Metrics map[string][]*monitoringpb.Point `json:"metrics"` + Region string `json:"region"` + Preferences map[string]*string `json:"preferences"` + Loading bool `json:"loading"` +} + +type GcpComputeInstanceWastageResponse struct { + RightSizing GcpComputeInstanceRightsizingRecommendation `json:"rightSizing"` +} + +type Usage struct { + Avg *float64 + Min *float64 + Max *float64 +} diff --git a/plugin/kaytu/request.go b/plugin/kaytu/request.go new file mode 100644 index 0000000..c117f22 --- /dev/null +++ b/plugin/kaytu/request.go @@ -0,0 +1,56 @@ +package kaytu + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" +) + +var ErrLogin = errors.New("your session is expired, please login") + +func Ec2InstanceWastageRequest(reqBody GcpComputeInstanceWastageRequest, token string) (*GcpComputeInstanceWastageResponse, error) { + payloadEncoded, err := json.Marshal(reqBody) + if err != nil { + return nil, err + } + req, err := http.NewRequest("POST", "https://api.kaytu.io/kaytu/wastage/api/v1/wastage/gcp-compute", bytes.NewBuffer(payloadEncoded)) + //req, err := http.NewRequest("POST", "http://localhost:8000/api/v1/wastage/ec2-instance", bytes.NewBuffer(payloadEncoded)) + if err != nil { + return nil, fmt.Errorf("[ec2-instance]: %v", err) + } + req.Header.Add("content-type", "application/json") + if len(token) > 0 { + req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token)) + } + res, err := http.DefaultClient.Do(req) + if err != nil { + return nil, fmt.Errorf("[gcp-compute]: %v", err) + } + + body, err := io.ReadAll(res.Body) + if err != nil { + return nil, fmt.Errorf("[gcp-compute]: %v", err) + } + err = res.Body.Close() + if err != nil { + return nil, fmt.Errorf("[gcp-compute]: %v", err) + } + + if res.StatusCode == 401 { + return nil, ErrLogin + } + + if res.StatusCode >= 300 || res.StatusCode < 200 { + return nil, fmt.Errorf("server returned status code %d, [requestAbout] : %s", res.StatusCode, string(body)) + } + + response := GcpComputeInstanceWastageResponse{} + err = json.Unmarshal(body, &response) + if err != nil { + return nil, fmt.Errorf("[requestAbout] : %v", err) + } + return &response, nil +}