mirror of
https://github.com/DeBrosOfficial/orama.git
synced 2026-03-17 13:06:56 +00:00
- Introduced `secrets` command for managing function secrets, including set, list, and delete operations. - Added `triggers` command for managing PubSub triggers associated with functions, allowing addition, listing, and deletion of triggers. - Implemented API handlers for secrets management, including setting, listing, and deleting secrets. - Updated serverless handlers to support new secrets and triggers functionalities. - Enhanced tests for the new features, ensuring proper functionality and error handling.
340 lines
8.7 KiB
Go
340 lines
8.7 KiB
Go
package serverless
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/DeBrosOfficial/network/pkg/serverless"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Mock SecretsManager
|
|
// ---------------------------------------------------------------------------
|
|
|
|
type mockSecretsManager struct {
|
|
secrets map[string]map[string]string // namespace -> name -> value
|
|
setErr error
|
|
getErr error
|
|
listErr error
|
|
delErr error
|
|
}
|
|
|
|
func newMockSecretsManager() *mockSecretsManager {
|
|
return &mockSecretsManager{
|
|
secrets: make(map[string]map[string]string),
|
|
}
|
|
}
|
|
|
|
func (m *mockSecretsManager) Set(_ context.Context, namespace, name, value string) error {
|
|
if m.setErr != nil {
|
|
return m.setErr
|
|
}
|
|
if m.secrets[namespace] == nil {
|
|
m.secrets[namespace] = make(map[string]string)
|
|
}
|
|
m.secrets[namespace][name] = value
|
|
return nil
|
|
}
|
|
|
|
func (m *mockSecretsManager) Get(_ context.Context, namespace, name string) (string, error) {
|
|
if m.getErr != nil {
|
|
return "", m.getErr
|
|
}
|
|
ns, ok := m.secrets[namespace]
|
|
if !ok {
|
|
return "", serverless.ErrSecretNotFound
|
|
}
|
|
v, ok := ns[name]
|
|
if !ok {
|
|
return "", serverless.ErrSecretNotFound
|
|
}
|
|
return v, nil
|
|
}
|
|
|
|
func (m *mockSecretsManager) List(_ context.Context, namespace string) ([]string, error) {
|
|
if m.listErr != nil {
|
|
return nil, m.listErr
|
|
}
|
|
ns := m.secrets[namespace]
|
|
names := make([]string, 0, len(ns))
|
|
for k := range ns {
|
|
names = append(names, k)
|
|
}
|
|
return names, nil
|
|
}
|
|
|
|
func (m *mockSecretsManager) Delete(_ context.Context, namespace, name string) error {
|
|
if m.delErr != nil {
|
|
return m.delErr
|
|
}
|
|
ns, ok := m.secrets[namespace]
|
|
if !ok {
|
|
return serverless.ErrSecretNotFound
|
|
}
|
|
if _, ok := ns[name]; !ok {
|
|
return serverless.ErrSecretNotFound
|
|
}
|
|
delete(ns, name)
|
|
return nil
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Helpers
|
|
// ---------------------------------------------------------------------------
|
|
|
|
func newSecretsTestHandlers(sm serverless.SecretsManager) *ServerlessHandlers {
|
|
logger := zap.NewNop()
|
|
wsManager := serverless.NewWSManager(logger)
|
|
return NewServerlessHandlers(
|
|
nil,
|
|
newMockRegistry(),
|
|
wsManager,
|
|
nil,
|
|
nil,
|
|
sm,
|
|
logger,
|
|
)
|
|
}
|
|
|
|
func decodeJSON(t *testing.T, rec *httptest.ResponseRecorder) map[string]interface{} {
|
|
t.Helper()
|
|
var result map[string]interface{}
|
|
if err := json.Unmarshal(rec.Body.Bytes(), &result); err != nil {
|
|
t.Fatalf("failed to decode response: %v", err)
|
|
}
|
|
return result
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Tests
|
|
// ---------------------------------------------------------------------------
|
|
|
|
func TestHandleSetSecret_Success(t *testing.T) {
|
|
sm := newMockSecretsManager()
|
|
h := newSecretsTestHandlers(sm)
|
|
|
|
body := `{"name":"API_KEY","value":"secret123"}`
|
|
req := httptest.NewRequest(http.MethodPut, "/v1/functions/secrets?namespace=myns", strings.NewReader(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
rec := httptest.NewRecorder()
|
|
|
|
h.HandleSetSecret(rec, req)
|
|
|
|
if rec.Code != http.StatusOK {
|
|
t.Errorf("expected 200, got %d: %s", rec.Code, rec.Body.String())
|
|
}
|
|
|
|
resp := decodeJSON(t, rec)
|
|
if resp["name"] != "API_KEY" {
|
|
t.Errorf("expected name API_KEY, got %v", resp["name"])
|
|
}
|
|
|
|
// Verify stored
|
|
if sm.secrets["myns"]["API_KEY"] != "secret123" {
|
|
t.Errorf("secret not stored correctly")
|
|
}
|
|
}
|
|
|
|
func TestHandleSetSecret_MissingName(t *testing.T) {
|
|
h := newSecretsTestHandlers(newMockSecretsManager())
|
|
|
|
body := `{"value":"secret123"}`
|
|
req := httptest.NewRequest(http.MethodPut, "/v1/functions/secrets?namespace=myns", strings.NewReader(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
rec := httptest.NewRecorder()
|
|
|
|
h.HandleSetSecret(rec, req)
|
|
|
|
if rec.Code != http.StatusBadRequest {
|
|
t.Errorf("expected 400, got %d", rec.Code)
|
|
}
|
|
}
|
|
|
|
func TestHandleSetSecret_MissingValue(t *testing.T) {
|
|
h := newSecretsTestHandlers(newMockSecretsManager())
|
|
|
|
body := `{"name":"API_KEY"}`
|
|
req := httptest.NewRequest(http.MethodPut, "/v1/functions/secrets?namespace=myns", strings.NewReader(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
rec := httptest.NewRecorder()
|
|
|
|
h.HandleSetSecret(rec, req)
|
|
|
|
if rec.Code != http.StatusBadRequest {
|
|
t.Errorf("expected 400, got %d", rec.Code)
|
|
}
|
|
}
|
|
|
|
func TestHandleSetSecret_NilManager(t *testing.T) {
|
|
h := newSecretsTestHandlers(nil)
|
|
|
|
body := `{"name":"API_KEY","value":"secret123"}`
|
|
req := httptest.NewRequest(http.MethodPut, "/v1/functions/secrets?namespace=myns", strings.NewReader(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
rec := httptest.NewRecorder()
|
|
|
|
h.HandleSetSecret(rec, req)
|
|
|
|
if rec.Code != http.StatusNotImplemented {
|
|
t.Errorf("expected 501, got %d", rec.Code)
|
|
}
|
|
}
|
|
|
|
func TestHandleListSecrets_Empty(t *testing.T) {
|
|
h := newSecretsTestHandlers(newMockSecretsManager())
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/v1/functions/secrets?namespace=myns", nil)
|
|
rec := httptest.NewRecorder()
|
|
|
|
h.HandleListSecrets(rec, req)
|
|
|
|
if rec.Code != http.StatusOK {
|
|
t.Errorf("expected 200, got %d", rec.Code)
|
|
}
|
|
|
|
resp := decodeJSON(t, rec)
|
|
if resp["count"].(float64) != 0 {
|
|
t.Errorf("expected count 0, got %v", resp["count"])
|
|
}
|
|
}
|
|
|
|
func TestHandleListSecrets_Populated(t *testing.T) {
|
|
sm := newMockSecretsManager()
|
|
sm.secrets["myns"] = map[string]string{
|
|
"KEY_A": "val_a",
|
|
"KEY_B": "val_b",
|
|
}
|
|
h := newSecretsTestHandlers(sm)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/v1/functions/secrets?namespace=myns", nil)
|
|
rec := httptest.NewRecorder()
|
|
|
|
h.HandleListSecrets(rec, req)
|
|
|
|
if rec.Code != http.StatusOK {
|
|
t.Errorf("expected 200, got %d", rec.Code)
|
|
}
|
|
|
|
resp := decodeJSON(t, rec)
|
|
if resp["count"].(float64) != 2 {
|
|
t.Errorf("expected count 2, got %v", resp["count"])
|
|
}
|
|
}
|
|
|
|
func TestHandleListSecrets_NilManager(t *testing.T) {
|
|
h := newSecretsTestHandlers(nil)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/v1/functions/secrets?namespace=myns", nil)
|
|
rec := httptest.NewRecorder()
|
|
|
|
h.HandleListSecrets(rec, req)
|
|
|
|
if rec.Code != http.StatusNotImplemented {
|
|
t.Errorf("expected 501, got %d", rec.Code)
|
|
}
|
|
}
|
|
|
|
func TestHandleDeleteSecret_Success(t *testing.T) {
|
|
sm := newMockSecretsManager()
|
|
sm.secrets["myns"] = map[string]string{"API_KEY": "val"}
|
|
h := newSecretsTestHandlers(sm)
|
|
|
|
req := httptest.NewRequest(http.MethodDelete, "/v1/functions/secrets/API_KEY?namespace=myns", nil)
|
|
rec := httptest.NewRecorder()
|
|
|
|
h.HandleDeleteSecret(rec, req, "API_KEY")
|
|
|
|
if rec.Code != http.StatusOK {
|
|
t.Errorf("expected 200, got %d", rec.Code)
|
|
}
|
|
|
|
if _, exists := sm.secrets["myns"]["API_KEY"]; exists {
|
|
t.Error("secret should have been deleted")
|
|
}
|
|
}
|
|
|
|
func TestHandleDeleteSecret_NotFound(t *testing.T) {
|
|
h := newSecretsTestHandlers(newMockSecretsManager())
|
|
|
|
req := httptest.NewRequest(http.MethodDelete, "/v1/functions/secrets/MISSING?namespace=myns", nil)
|
|
rec := httptest.NewRecorder()
|
|
|
|
h.HandleDeleteSecret(rec, req, "MISSING")
|
|
|
|
if rec.Code != http.StatusNotFound {
|
|
t.Errorf("expected 404, got %d", rec.Code)
|
|
}
|
|
}
|
|
|
|
func TestHandleDeleteSecret_NilManager(t *testing.T) {
|
|
h := newSecretsTestHandlers(nil)
|
|
|
|
req := httptest.NewRequest(http.MethodDelete, "/v1/functions/secrets/KEY?namespace=myns", nil)
|
|
rec := httptest.NewRecorder()
|
|
|
|
h.HandleDeleteSecret(rec, req, "KEY")
|
|
|
|
if rec.Code != http.StatusNotImplemented {
|
|
t.Errorf("expected 501, got %d", rec.Code)
|
|
}
|
|
}
|
|
|
|
// Test routing through handleFunctionByName
|
|
func TestRouting_SecretsSet(t *testing.T) {
|
|
sm := newMockSecretsManager()
|
|
h := newSecretsTestHandlers(sm)
|
|
|
|
mux := http.NewServeMux()
|
|
h.RegisterRoutes(mux)
|
|
|
|
body := `{"name":"MY_SECRET","value":"myval"}`
|
|
req := httptest.NewRequest(http.MethodPut, "/v1/functions/secrets?namespace=test", strings.NewReader(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
rec := httptest.NewRecorder()
|
|
|
|
mux.ServeHTTP(rec, req)
|
|
|
|
if rec.Code != http.StatusOK {
|
|
t.Errorf("expected 200, got %d: %s", rec.Code, rec.Body.String())
|
|
}
|
|
}
|
|
|
|
func TestRouting_SecretsList(t *testing.T) {
|
|
h := newSecretsTestHandlers(newMockSecretsManager())
|
|
|
|
mux := http.NewServeMux()
|
|
h.RegisterRoutes(mux)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/v1/functions/secrets?namespace=test", nil)
|
|
rec := httptest.NewRecorder()
|
|
|
|
mux.ServeHTTP(rec, req)
|
|
|
|
if rec.Code != http.StatusOK {
|
|
t.Errorf("expected 200, got %d: %s", rec.Code, rec.Body.String())
|
|
}
|
|
}
|
|
|
|
func TestRouting_SecretsDelete(t *testing.T) {
|
|
sm := newMockSecretsManager()
|
|
sm.secrets["test"] = map[string]string{"KEY": "val"}
|
|
h := newSecretsTestHandlers(sm)
|
|
|
|
mux := http.NewServeMux()
|
|
h.RegisterRoutes(mux)
|
|
|
|
req := httptest.NewRequest(http.MethodDelete, "/v1/functions/secrets/KEY?namespace=test", nil)
|
|
rec := httptest.NewRecorder()
|
|
|
|
mux.ServeHTTP(rec, req)
|
|
|
|
if rec.Code != http.StatusOK {
|
|
t.Errorf("expected 200, got %d: %s", rec.Code, rec.Body.String())
|
|
}
|
|
}
|