Skip to content

Commit 0204371

Browse files
committed
Feat: Add Meter And Event Calls to api-gateway
1 parent 4203ba4 commit 0204371

1 file changed

Lines changed: 165 additions & 0 deletions

File tree

persysctl/internal/client/client.go

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package client
22

33
import (
4+
"bufio"
45
"bytes"
56
"context"
67
"crypto/tls"
@@ -1011,6 +1012,170 @@ func (c *Client) GatewayClusters() (*GatewayClustersResponse, error) {
10111012
return &out, nil
10121013
}
10131014

1015+
func (c *Client) MeterListWorkloads(workloadType string) (map[string]any, error) {
1016+
if c.cfg.Transport != "http" {
1017+
return nil, fmt.Errorf("meter API is available only with http transport")
1018+
}
1019+
path := "/meter/v1/workloads"
1020+
q := url.Values{}
1021+
if trimmed := strings.TrimSpace(workloadType); trimmed != "" {
1022+
q.Set("workload_type", trimmed)
1023+
}
1024+
if encoded := q.Encode(); encoded != "" {
1025+
path += "?" + encoded
1026+
}
1027+
var out map[string]any
1028+
if err := c.httpJSONRequest("GET", path, nil, &out); err != nil {
1029+
return nil, err
1030+
}
1031+
return out, nil
1032+
}
1033+
1034+
func (c *Client) MeterGetWorkload(workloadID string) (map[string]any, error) {
1035+
if c.cfg.Transport != "http" {
1036+
return nil, fmt.Errorf("meter API is available only with http transport")
1037+
}
1038+
path := "/meter/v1/workloads/" + url.PathEscape(strings.TrimSpace(workloadID))
1039+
var out map[string]any
1040+
if err := c.httpJSONRequest("GET", path, nil, &out); err != nil {
1041+
return nil, err
1042+
}
1043+
return out, nil
1044+
}
1045+
1046+
func (c *Client) MeterHistory(workloadID string, from, to time.Time, limit int) (map[string]any, error) {
1047+
if c.cfg.Transport != "http" {
1048+
return nil, fmt.Errorf("meter API is available only with http transport")
1049+
}
1050+
path := "/meter/v1/workloads/" + url.PathEscape(strings.TrimSpace(workloadID)) + "/history"
1051+
q := url.Values{}
1052+
if !from.IsZero() {
1053+
q.Set("from", from.UTC().Format(time.RFC3339))
1054+
}
1055+
if !to.IsZero() {
1056+
q.Set("to", to.UTC().Format(time.RFC3339))
1057+
}
1058+
if limit > 0 {
1059+
q.Set("limit", strconv.Itoa(limit))
1060+
}
1061+
if encoded := q.Encode(); encoded != "" {
1062+
path += "?" + encoded
1063+
}
1064+
var out map[string]any
1065+
if err := c.httpJSONRequest("GET", path, nil, &out); err != nil {
1066+
return nil, err
1067+
}
1068+
return out, nil
1069+
}
1070+
1071+
func (c *Client) MeterSummary(workloadID string, from, to time.Time) (map[string]any, error) {
1072+
if c.cfg.Transport != "http" {
1073+
return nil, fmt.Errorf("meter API is available only with http transport")
1074+
}
1075+
path := "/meter/v1/workloads/" + url.PathEscape(strings.TrimSpace(workloadID)) + "/summary"
1076+
q := url.Values{}
1077+
if !from.IsZero() {
1078+
q.Set("from", from.UTC().Format(time.RFC3339))
1079+
}
1080+
if !to.IsZero() {
1081+
q.Set("to", to.UTC().Format(time.RFC3339))
1082+
}
1083+
if encoded := q.Encode(); encoded != "" {
1084+
path += "?" + encoded
1085+
}
1086+
var out map[string]any
1087+
if err := c.httpJSONRequest("GET", path, nil, &out); err != nil {
1088+
return nil, err
1089+
}
1090+
return out, nil
1091+
}
1092+
1093+
func (c *Client) WatchGatewayEvents(eventType, workloadID, nodeID string, limit int) ([]map[string]any, error) {
1094+
if c.cfg.Transport != "http" {
1095+
return nil, fmt.Errorf("gateway event stream is available only with http transport")
1096+
}
1097+
if limit <= 0 {
1098+
limit = 20
1099+
}
1100+
1101+
path := "/events/watch"
1102+
q := url.Values{}
1103+
if trimmed := strings.TrimSpace(eventType); trimmed != "" {
1104+
q.Set("type", trimmed)
1105+
}
1106+
if trimmed := strings.TrimSpace(workloadID); trimmed != "" {
1107+
q.Set("workload_id", trimmed)
1108+
}
1109+
if trimmed := strings.TrimSpace(nodeID); trimmed != "" {
1110+
q.Set("node_id", trimmed)
1111+
}
1112+
if encoded := q.Encode(); encoded != "" {
1113+
path += "?" + encoded
1114+
}
1115+
1116+
timeout := time.Duration(c.cfg.RPCTimeoutSeconds) * time.Second
1117+
if timeout <= 0 {
1118+
timeout = 15 * time.Second
1119+
}
1120+
ctx, cancel := context.WithTimeout(context.Background(), timeout)
1121+
defer cancel()
1122+
1123+
req, err := http.NewRequestWithContext(ctx, http.MethodGet, c.cfg.APIEndpoint+path, nil)
1124+
if err != nil {
1125+
return nil, fmt.Errorf("failed to create request: %w", err)
1126+
}
1127+
req.Header.Set("Accept", "text/event-stream")
1128+
resp, err := c.httpClient.Do(req)
1129+
if err != nil {
1130+
if ctx.Err() == context.DeadlineExceeded {
1131+
return nil, nil
1132+
}
1133+
return nil, fmt.Errorf("failed to send request: %w", err)
1134+
}
1135+
defer resp.Body.Close()
1136+
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
1137+
body, _ := io.ReadAll(resp.Body)
1138+
return nil, fmt.Errorf("API returned status %d: %s", resp.StatusCode, string(body))
1139+
}
1140+
1141+
scanner := bufio.NewScanner(resp.Body)
1142+
scanner.Buffer(make([]byte, 0, 64*1024), 1024*1024)
1143+
var (
1144+
events []map[string]any
1145+
dataLine string
1146+
)
1147+
for scanner.Scan() {
1148+
line := strings.TrimSpace(scanner.Text())
1149+
if strings.HasPrefix(line, "event:") {
1150+
continue
1151+
}
1152+
if strings.HasPrefix(line, "data:") {
1153+
dataLine = strings.TrimSpace(strings.TrimPrefix(line, "data:"))
1154+
continue
1155+
}
1156+
if line == "" && dataLine != "" {
1157+
var event map[string]any
1158+
if err := json.Unmarshal([]byte(dataLine), &event); err == nil {
1159+
events = append(events, event)
1160+
if len(events) >= limit {
1161+
return events, nil
1162+
}
1163+
}
1164+
dataLine = ""
1165+
}
1166+
if ctx.Err() != nil {
1167+
return events, nil
1168+
}
1169+
}
1170+
if err := scanner.Err(); err != nil {
1171+
if ctx.Err() == context.DeadlineExceeded {
1172+
return events, nil
1173+
}
1174+
return nil, fmt.Errorf("failed to read event stream: %w", err)
1175+
}
1176+
return events, nil
1177+
}
1178+
10141179
func (c *Client) TriggerForgeryBuild(req ForgeryBuildTriggerRequest) (map[string]interface{}, error) {
10151180
if c.cfg.Transport != "http" {
10161181
return nil, fmt.Errorf("forgery trigger-build is available only with http transport")

0 commit comments

Comments
 (0)