mirror of
https://github.com/kubescape/kubescape.git
synced 2026-04-15 06:58:11 +00:00
Implement unit-test for scan handler.
It plays wtih channels and goroutines, so having it behave correctly is not completely trivial and test worthy. Signed-off-by: ttimonen <toni.timonen@iki.fi>
This commit is contained in:
@@ -90,7 +90,6 @@ func (handler *HTTPHandler) Status(w http.ResponseWriter, r *http.Request) {
|
||||
// ============================================== SCAN ========================================================
|
||||
// Scan API
|
||||
func (handler *HTTPHandler) Scan(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// generate id
|
||||
scanID := uuid.NewString()
|
||||
|
||||
@@ -101,7 +100,6 @@ func (handler *HTTPHandler) Scan(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
scanRequestParams, err := getScanParamsFromRequest(r, scanID)
|
||||
if err != nil {
|
||||
handler.writeError(w, err, "")
|
||||
@@ -110,12 +108,6 @@ func (handler *HTTPHandler) Scan(w http.ResponseWriter, r *http.Request) {
|
||||
scanRequestParams.ctx = trace.ContextWithSpanContext(context.Background(), trace.SpanContextFromContext(r.Context()))
|
||||
|
||||
handler.state.setBusy(scanID)
|
||||
|
||||
response := &utilsmetav1.Response{}
|
||||
response.ID = scanID
|
||||
response.Type = utilsapisv1.BusyScanResponseType
|
||||
response.Response = fmt.Sprintf("scanning '%s' is in progress", scanID)
|
||||
|
||||
handler.scanResponseChan.set(scanID) // add channel
|
||||
defer handler.scanResponseChan.delete(scanID)
|
||||
|
||||
@@ -126,6 +118,11 @@ func (handler *HTTPHandler) Scan(w http.ResponseWriter, r *http.Request) {
|
||||
handler.scanRequestChan <- scanRequestParams
|
||||
}()
|
||||
|
||||
response := &utilsmetav1.Response{
|
||||
ID: scanID,
|
||||
Type: utilsapisv1.BusyScanResponseType,
|
||||
Response: fmt.Sprintf("scanning '%s' is in progress", scanID),
|
||||
}
|
||||
if scanRequestParams.scanQueryParams.ReturnResults {
|
||||
// wait for scan to complete
|
||||
response = <-handler.scanResponseChan.get(scanID)
|
||||
|
||||
@@ -1,5 +1,61 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
utilsmetav1 "github.com/kubescape/opa-utils/httpserver/meta/v1"
|
||||
reporthandlingv2 "github.com/kubescape/opa-utils/reporthandling/v2"
|
||||
)
|
||||
|
||||
func testBody(t *testing.T) io.Reader {
|
||||
t.Helper()
|
||||
b, err := json.Marshal(utilsmetav1.PostScanRequest{Account: "fakeFoobar"})
|
||||
if err != nil {
|
||||
t.Fatal("Can not marshal")
|
||||
}
|
||||
return bytes.NewReader(b)
|
||||
}
|
||||
|
||||
type scanner func(_ context.Context, _ *cautils.ScanInfo, _ string) (*reporthandlingv2.PostureReport, error)
|
||||
|
||||
// TestScan tests that the scan handler passes the scan requests correctly to the underlying scan engine.
|
||||
func TestScan(t *testing.T) {
|
||||
|
||||
// Our scanner is not setting up the k8s connection; the test is covering the rest of the wiring
|
||||
// that the signaling from the http handler goes all the way to the scanner implementation.
|
||||
defer func(o scanner) { scanImpl = o }(scanImpl)
|
||||
scanImpl = func(context.Context, *cautils.ScanInfo, string) (*reporthandlingv2.PostureReport, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var (
|
||||
h = NewHTTPHandler()
|
||||
rq = httptest.NewRequest("POST", "/scan?wait=true", testBody(t))
|
||||
w = httptest.NewRecorder()
|
||||
)
|
||||
h.Scan(w, rq)
|
||||
rs := w.Result()
|
||||
body, _ := io.ReadAll(rs.Body)
|
||||
|
||||
type out struct {
|
||||
code int
|
||||
ctype string
|
||||
body string
|
||||
}
|
||||
want := out{200, "application/json", `{"id":"","type":"v1results"}`}
|
||||
got := out{rs.StatusCode, rs.Header.Get("Content-type"), string(body)}
|
||||
|
||||
if got != want {
|
||||
t.Errorf("Scan result: %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================== STATUS ========================================================
|
||||
// Status API
|
||||
// func TestStatus(t *testing.T) {
|
||||
|
||||
@@ -25,11 +25,12 @@ import (
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
var scanImpl = scan // Override for testing
|
||||
func (handler *HTTPHandler) executeScan(scanReq *scanRequestParams) {
|
||||
response := &utilsmetav1.Response{}
|
||||
|
||||
logger.L().Info("scan triggered", helpers.String("ID", scanReq.scanID))
|
||||
_, err := scan(scanReq.ctx, scanReq.scanInfo, scanReq.scanID)
|
||||
_, err := scanImpl(scanReq.ctx, scanReq.scanInfo, scanReq.scanID)
|
||||
if err != nil {
|
||||
logger.L().Ctx(scanReq.ctx).Error("scanning failed", helpers.String("ID", scanReq.scanID), helpers.Error(err))
|
||||
if scanReq.scanQueryParams.ReturnResults {
|
||||
@@ -39,6 +40,7 @@ func (handler *HTTPHandler) executeScan(scanReq *scanRequestParams) {
|
||||
} else {
|
||||
logger.L().Ctx(scanReq.ctx).Success("done scanning", helpers.String("ID", scanReq.scanID))
|
||||
if scanReq.scanQueryParams.ReturnResults {
|
||||
//TODO(ttimonen) should we actually pass the PostureReport here somehow?
|
||||
response.Type = utilsapisv1.ResultsV1ScanResponseType
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user