This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
// Command integrationfixture is an isolated, deterministic external boundary
|
||||
// used only by the real-stack smoke gate. It behaves as a Prometheus-compatible
|
||||
// source and a webhook receiver; production images never include it.
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type counters struct {
|
||||
mu sync.Mutex
|
||||
prometheusRequests int
|
||||
webhookRequests int
|
||||
keys map[string]struct{}
|
||||
lastEvent string
|
||||
events map[string]int
|
||||
}
|
||||
|
||||
func main() {
|
||||
if len(os.Args) == 3 && (os.Args[1] == "health" || os.Args[1] == "get") {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||
defer cancel()
|
||||
request, _ := http.NewRequestWithContext(ctx, http.MethodGet, os.Args[2], nil)
|
||||
response, err := http.DefaultClient.Do(request)
|
||||
if err != nil || response.StatusCode != http.StatusOK {
|
||||
os.Exit(1)
|
||||
}
|
||||
defer response.Body.Close()
|
||||
if os.Args[1] == "get" {
|
||||
_, _ = io.CopyN(os.Stdout, response.Body, 64<<10)
|
||||
}
|
||||
return
|
||||
}
|
||||
listen := flag.String("listen", ":9090", "listen address")
|
||||
flag.Parse()
|
||||
state := &counters{keys: map[string]struct{}{}, events: map[string]int{}}
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/healthz", func(writer http.ResponseWriter, _ *http.Request) { writer.WriteHeader(http.StatusOK) })
|
||||
mux.HandleFunc("/api/v1/query", state.prometheus)
|
||||
mux.HandleFunc("/api/v1/query_range", state.prometheus)
|
||||
mux.HandleFunc("/webhook", state.webhook)
|
||||
mux.HandleFunc("/smoke/status", state.status)
|
||||
server := &http.Server{Addr: *listen, Handler: mux, ReadHeaderTimeout: 2 * time.Second, ReadTimeout: 5 * time.Second, WriteTimeout: 5 * time.Second, IdleTimeout: 15 * time.Second}
|
||||
if err := server.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func (state *counters) prometheus(writer http.ResponseWriter, request *http.Request) {
|
||||
if request.Method != http.MethodGet || strings.TrimSpace(request.URL.Query().Get("query")) == "" {
|
||||
http.Error(writer, "invalid query", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
state.mu.Lock()
|
||||
state.prometheusRequests++
|
||||
state.mu.Unlock()
|
||||
now := float64(time.Now().UTC().Unix())
|
||||
data := map[string]any{"resultType": "vector", "result": []any{map[string]any{"metric": map[string]string{"instance": "smoke-host"}, "value": []any{now, "95"}}}}
|
||||
if request.URL.Path == "/api/v1/query_range" {
|
||||
data = map[string]any{"resultType": "matrix", "result": []any{map[string]any{"metric": map[string]string{"instance": "smoke-host"}, "values": []any{[]any{now - 60, "90"}, []any{now, "95"}}}}}
|
||||
}
|
||||
writeJSON(writer, http.StatusOK, map[string]any{"status": "success", "data": data})
|
||||
}
|
||||
|
||||
func (state *counters) webhook(writer http.ResponseWriter, request *http.Request) {
|
||||
if request.Method != http.MethodPost {
|
||||
writer.WriteHeader(http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
expected := os.Getenv("PULSE_SMOKE_WEBHOOK_TOKEN")
|
||||
if expected == "" || request.Header.Get("Authorization") != "Bearer "+expected {
|
||||
writer.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
key := request.Header.Get("Idempotency-Key")
|
||||
var payload struct {
|
||||
EventType string `json:"eventType"`
|
||||
}
|
||||
if key == "" || json.NewDecoder(http.MaxBytesReader(writer, request.Body, 16<<10)).Decode(&payload) != nil {
|
||||
writer.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
state.mu.Lock()
|
||||
state.webhookRequests++
|
||||
state.keys[key] = struct{}{}
|
||||
state.lastEvent = payload.EventType
|
||||
state.events[payload.EventType]++
|
||||
state.mu.Unlock()
|
||||
writer.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
|
||||
func (state *counters) status(writer http.ResponseWriter, _ *http.Request) {
|
||||
state.mu.Lock()
|
||||
defer state.mu.Unlock()
|
||||
writeJSON(writer, http.StatusOK, map[string]any{"prometheusRequests": state.prometheusRequests, "webhookRequests": state.webhookRequests, "uniqueDeliveryKeys": len(state.keys), "lastEventType": state.lastEvent, "events": state.events})
|
||||
}
|
||||
|
||||
func writeJSON(writer http.ResponseWriter, status int, value any) {
|
||||
writer.Header().Set("Content-Type", "application/json")
|
||||
writer.WriteHeader(status)
|
||||
_ = json.NewEncoder(writer).Encode(value)
|
||||
}
|
||||
Reference in New Issue
Block a user