141 lines
5.2 KiB
Go
141 lines
5.2 KiB
Go
package api
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"fission-console/internal/fission"
|
|
|
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
dynamicfake "k8s.io/client-go/dynamic/fake"
|
|
)
|
|
|
|
func TestHandleTimeTriggersRootCreateListGetUpdateDelete(t *testing.T) {
|
|
ctx := context.Background()
|
|
scheme := runtime.NewScheme()
|
|
client := dynamicfake.NewSimpleDynamicClientWithCustomListKinds(
|
|
scheme,
|
|
map[schema.GroupVersionResource]string{
|
|
fission.TimeTrigGVR: "TimeTriggerList",
|
|
},
|
|
functionObject("fission-test", "hello"),
|
|
)
|
|
s := &Server{dyn: client, ns: "fission-test"}
|
|
|
|
createReq := httptest.NewRequest(http.MethodPost, "/console/api/timetriggers", strings.NewReader(`{"name":"cron-job","functionName":"hello","cron":"*/5 * * * *","method":"get","subpath":"logs"}`))
|
|
createRec := httptest.NewRecorder()
|
|
s.handleTimeTriggersRoot(createRec, createReq)
|
|
if createRec.Code != http.StatusCreated {
|
|
t.Fatalf("create status = %d, want %d body=%s", createRec.Code, http.StatusCreated, createRec.Body.String())
|
|
}
|
|
created := decodeMap(t, createRec.Body.Bytes())
|
|
if created["name"] != "cron-job" {
|
|
t.Fatalf("create name = %v", created["name"])
|
|
}
|
|
if created["cron"] != "*/5 * * * *" {
|
|
t.Fatalf("create cron = %v", created["cron"])
|
|
}
|
|
if created["method"] != http.MethodGet {
|
|
t.Fatalf("create method = %v", created["method"])
|
|
}
|
|
if created["subpath"] != "/logs" {
|
|
t.Fatalf("create subpath = %v", created["subpath"])
|
|
}
|
|
|
|
createdObj, err := client.Resource(fission.TimeTrigGVR).Namespace("fission-test").Get(ctx, "cron-job", metav1.GetOptions{})
|
|
if err != nil {
|
|
t.Fatalf("get created timetrigger: %v", err)
|
|
}
|
|
if cron, _, _ := unstructured.NestedString(createdObj.Object, "spec", "cron"); cron != "*/5 * * * *" {
|
|
t.Fatalf("stored cron = %q", cron)
|
|
}
|
|
|
|
listReq := httptest.NewRequest(http.MethodGet, "/console/api/timetriggers", nil)
|
|
listRec := httptest.NewRecorder()
|
|
s.handleTimeTriggersRoot(listRec, listReq)
|
|
if listRec.Code != http.StatusOK {
|
|
t.Fatalf("list status = %d body=%s", listRec.Code, listRec.Body.String())
|
|
}
|
|
if !strings.Contains(listRec.Body.String(), "cron-job") {
|
|
t.Fatalf("list body does not contain created trigger: %s", listRec.Body.String())
|
|
}
|
|
|
|
getReq := httptest.NewRequest(http.MethodGet, "/console/api/timetriggers/cron-job", nil)
|
|
getRec := httptest.NewRecorder()
|
|
s.handleTimeTriggersAction(getRec, getReq)
|
|
if getRec.Code != http.StatusOK {
|
|
t.Fatalf("get status = %d body=%s", getRec.Code, getRec.Body.String())
|
|
}
|
|
got := decodeMap(t, getRec.Body.Bytes())
|
|
if got["function"] != "hello" {
|
|
t.Fatalf("get function = %v", got["function"])
|
|
}
|
|
|
|
updateReq := httptest.NewRequest(http.MethodPut, "/console/api/timetriggers/cron-job", strings.NewReader(`{"name":"cron-job","functionName":"hello","cron":"@hourly","method":"post","subpath":"/"}`))
|
|
updateRec := httptest.NewRecorder()
|
|
s.handleTimeTriggersAction(updateRec, updateReq)
|
|
if updateRec.Code != http.StatusOK {
|
|
t.Fatalf("update status = %d body=%s", updateRec.Code, updateRec.Body.String())
|
|
}
|
|
updated, err := client.Resource(fission.TimeTrigGVR).Namespace("fission-test").Get(ctx, "cron-job", metav1.GetOptions{})
|
|
if err != nil {
|
|
t.Fatalf("get updated timetrigger: %v", err)
|
|
}
|
|
if cron, _, _ := unstructured.NestedString(updated.Object, "spec", "cron"); cron != "@hourly" {
|
|
t.Fatalf("updated cron = %q", cron)
|
|
}
|
|
|
|
deleteReq := httptest.NewRequest(http.MethodDelete, "/console/api/timetriggers/cron-job", nil)
|
|
deleteRec := httptest.NewRecorder()
|
|
s.handleTimeTriggersAction(deleteRec, deleteReq)
|
|
if deleteRec.Code != http.StatusOK {
|
|
t.Fatalf("delete status = %d body=%s", deleteRec.Code, deleteRec.Body.String())
|
|
}
|
|
if _, err := client.Resource(fission.TimeTrigGVR).Namespace("fission-test").Get(ctx, "cron-job", metav1.GetOptions{}); !apierrors.IsNotFound(err) {
|
|
t.Fatalf("expected timetrigger to be deleted, got err=%v", err)
|
|
}
|
|
}
|
|
|
|
func TestHandleCreateTimeTriggerRejectsMissingFunction(t *testing.T) {
|
|
client := dynamicfake.NewSimpleDynamicClient(runtime.NewScheme())
|
|
s := &Server{dyn: client, ns: "fission-test"}
|
|
|
|
req := httptest.NewRequest(http.MethodPost, "/console/api/timetriggers", strings.NewReader(`{"name":"cron-job","functionName":"missing","cron":"*/5 * * * *"}`))
|
|
rec := httptest.NewRecorder()
|
|
s.handleTimeTriggersRoot(rec, req)
|
|
if rec.Code != http.StatusBadRequest {
|
|
t.Fatalf("status = %d, want %d body=%s", rec.Code, http.StatusBadRequest, rec.Body.String())
|
|
}
|
|
if !strings.Contains(rec.Body.String(), "not found") {
|
|
t.Fatalf("expected not found error, got %s", rec.Body.String())
|
|
}
|
|
}
|
|
|
|
func decodeMap(t *testing.T, data []byte) map[string]any {
|
|
t.Helper()
|
|
var result map[string]any
|
|
if err := json.Unmarshal(data, &result); err != nil {
|
|
t.Fatalf("decode json: %v body=%s", err, string(data))
|
|
}
|
|
return result
|
|
}
|
|
|
|
func functionObject(namespace, name string) *unstructured.Unstructured {
|
|
return &unstructured.Unstructured{Object: map[string]any{
|
|
"apiVersion": "fission.io/v1",
|
|
"kind": "Function",
|
|
"metadata": map[string]any{
|
|
"name": name,
|
|
"namespace": namespace,
|
|
},
|
|
}}
|
|
}
|