187 lines
5.8 KiB
Go
187 lines
5.8 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"scm.bstein.dev/bstein/soteria/internal/api"
|
|
"scm.bstein.dev/bstein/soteria/internal/config"
|
|
)
|
|
|
|
func TestRefreshB2UsageRecordsCredentialResolutionErrors(t *testing.T) {
|
|
srv := &Server{
|
|
cfg: &config.Config{
|
|
B2Enabled: true,
|
|
B2ScanTimeout: time.Second,
|
|
},
|
|
client: &fakeKubeClient{},
|
|
metrics: newTelemetry(),
|
|
}
|
|
|
|
srv.refreshB2Usage(context.Background())
|
|
|
|
usage := srv.getB2Usage()
|
|
if !usage.Enabled || usage.Error == "" || !strings.Contains(usage.Error, "B2 endpoint is not configured") {
|
|
t.Fatalf("expected B2 credential resolution error snapshot, got %#v", usage)
|
|
}
|
|
if usage.ScannedAt == "" {
|
|
t.Fatalf("expected failed refresh to record scanned timestamp, got %#v", usage)
|
|
}
|
|
if srv.metrics.b2ScanSuccess != 0 || srv.metrics.b2ScanTimestamp == 0 {
|
|
t.Fatalf("expected failed B2 scan metrics to be recorded, got success=%f timestamp=%f", srv.metrics.b2ScanSuccess, srv.metrics.b2ScanTimestamp)
|
|
}
|
|
}
|
|
|
|
func TestRefreshB2UsageHandlesDisabledAndSuccessfulScans(t *testing.T) {
|
|
t.Run("disabled", func(t *testing.T) {
|
|
srv := &Server{
|
|
cfg: &config.Config{
|
|
B2Enabled: false,
|
|
B2Endpoint: "https://cached-endpoint",
|
|
B2Region: "us-west-001",
|
|
B2ScanTimeout: time.Second,
|
|
},
|
|
client: &fakeKubeClient{},
|
|
metrics: newTelemetry(),
|
|
}
|
|
|
|
srv.refreshB2Usage(context.Background())
|
|
|
|
usage := srv.getB2Usage()
|
|
if usage.Enabled || usage.Error != "" || usage.Endpoint != "https://cached-endpoint" {
|
|
t.Fatalf("expected disabled snapshot without scan error, got %#v", usage)
|
|
}
|
|
if srv.metrics.b2ScanSuccess != 0 || srv.metrics.b2AccountBytes != 0 {
|
|
t.Fatalf("expected disabled metrics snapshot, got success=%f bytes=%f", srv.metrics.b2ScanSuccess, srv.metrics.b2AccountBytes)
|
|
}
|
|
})
|
|
|
|
t.Run("successful scan", func(t *testing.T) {
|
|
now := time.Now().UTC()
|
|
server := newFakeS3Server(t,
|
|
[]string{"atlas"},
|
|
map[string][]fakeS3Object{
|
|
"atlas": {
|
|
{key: "fresh", size: 7, lastModified: now.Add(-1 * time.Hour)},
|
|
{key: "stale", size: 11, lastModified: now.Add(-48 * time.Hour)},
|
|
},
|
|
},
|
|
nil,
|
|
)
|
|
defer server.Close()
|
|
|
|
srv := &Server{
|
|
cfg: &config.Config{
|
|
B2Enabled: true,
|
|
B2Endpoint: server.URL,
|
|
B2Region: "us-west-001",
|
|
B2AccessKeyID: "atlas-key",
|
|
B2SecretAccessKey: "atlas-secret",
|
|
B2ScanTimeout: 2 * time.Second,
|
|
},
|
|
client: &fakeKubeClient{},
|
|
metrics: newTelemetry(),
|
|
}
|
|
|
|
srv.refreshB2Usage(context.Background())
|
|
|
|
usage := srv.getB2Usage()
|
|
if !usage.Enabled || !usage.Available || usage.Error != "" {
|
|
t.Fatalf("expected successful B2 scan snapshot, got %#v", usage)
|
|
}
|
|
if usage.Endpoint != server.URL || usage.Region != "us-west-001" || usage.TotalObjects != 2 || usage.RecentObjects24h != 1 {
|
|
t.Fatalf("expected successful usage totals, got %#v", usage)
|
|
}
|
|
if usage.ScannedAt == "" || usage.ScanDurationMS < 0 {
|
|
t.Fatalf("expected scan metadata, got %#v", usage)
|
|
}
|
|
if srv.metrics.b2ScanSuccess != 1 || srv.metrics.b2AccountBytes != 18 {
|
|
t.Fatalf("expected success metrics to be recorded, got success=%f bytes=%f", srv.metrics.b2ScanSuccess, srv.metrics.b2AccountBytes)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestRefreshB2UsageRecordsScanErrorsAfterCredentialsResolve(t *testing.T) {
|
|
srv := &Server{
|
|
cfg: &config.Config{
|
|
B2Enabled: true,
|
|
B2Endpoint: "https://",
|
|
B2AccessKeyID: "atlas-key",
|
|
B2SecretAccessKey: "atlas-secret",
|
|
B2ScanTimeout: time.Second,
|
|
},
|
|
client: &fakeKubeClient{},
|
|
metrics: newTelemetry(),
|
|
}
|
|
|
|
srv.refreshB2Usage(context.Background())
|
|
|
|
usage := srv.getB2Usage()
|
|
if usage.Endpoint != "https://" {
|
|
t.Fatalf("expected resolved endpoint to be preserved in failed snapshot, got %#v", usage)
|
|
}
|
|
if usage.Error == "" || !strings.Contains(usage.Error, "S3 endpoint host is empty") {
|
|
t.Fatalf("expected B2 scan error snapshot, got %#v", usage)
|
|
}
|
|
if usage.ScannedAt == "" || usage.ScanDurationMS < 0 {
|
|
t.Fatalf("expected scan metadata on failure, got %#v", usage)
|
|
}
|
|
if srv.metrics.b2ScanSuccess != 0 || srv.metrics.b2ScanDurationSeconds < 0 {
|
|
t.Fatalf("expected failure metrics after scan error, got success=%f duration=%f", srv.metrics.b2ScanSuccess, srv.metrics.b2ScanDurationSeconds)
|
|
}
|
|
}
|
|
|
|
func TestHandleB2UsageRefreshesWhenForcedAndQueryBoolRecognizesTruthyValues(t *testing.T) {
|
|
for _, raw := range []string{"1", "true", "yes", "y", "on", "TRUE"} {
|
|
if !queryBool(raw) {
|
|
t.Fatalf("expected %q to be treated as truthy", raw)
|
|
}
|
|
}
|
|
if queryBool("nope") {
|
|
t.Fatalf("expected invalid truthy value to be false")
|
|
}
|
|
|
|
srv := &Server{
|
|
cfg: &config.Config{
|
|
B2Enabled: true,
|
|
B2Endpoint: "https://",
|
|
B2AccessKeyID: "atlas-key",
|
|
B2SecretAccessKey: "atlas-secret",
|
|
B2ScanTimeout: time.Second,
|
|
},
|
|
client: &fakeKubeClient{},
|
|
metrics: newTelemetry(),
|
|
}
|
|
srv.handler = http.HandlerFunc(srv.route)
|
|
srv.setB2Usage(api.B2UsageResponse{
|
|
Enabled: true,
|
|
Available: true,
|
|
ScannedAt: time.Now().UTC().Add(-1 * time.Hour).Format(time.RFC3339),
|
|
Endpoint: "cached-endpoint",
|
|
})
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/v1/b2?refresh=yes", nil)
|
|
res := httptest.NewRecorder()
|
|
srv.Handler().ServeHTTP(res, req)
|
|
|
|
if res.Code != http.StatusOK {
|
|
t.Fatalf("expected forced refresh request to succeed, got %d: %s", res.Code, res.Body.String())
|
|
}
|
|
|
|
var payload api.B2UsageResponse
|
|
if err := json.Unmarshal(res.Body.Bytes(), &payload); err != nil {
|
|
t.Fatalf("decode forced refresh payload: %v", err)
|
|
}
|
|
if payload.Error == "" || !strings.Contains(payload.Error, "S3 endpoint host is empty") {
|
|
t.Fatalf("expected refreshed B2 failure payload, got %#v", payload)
|
|
}
|
|
if payload.Endpoint != "https://" {
|
|
t.Fatalf("expected refreshed endpoint to replace cached snapshot, got %#v", payload)
|
|
}
|
|
}
|