mirror of
https://github.com/kubescape/kubescape.git
synced 2026-02-14 09:59:54 +00:00
update status busy to support more than one req
This commit is contained in:
@@ -15,24 +15,23 @@ import (
|
||||
|
||||
// Metrics http listener for prometheus support
|
||||
func (handler *HTTPHandler) Metrics(w http.ResponseWriter, r *http.Request) {
|
||||
if handler.state.isBusy() { // if already scanning the cluster
|
||||
message := fmt.Sprintf("scan '%s' in action", handler.state.getID())
|
||||
if handler.state.len() > 0 { // if already scanning the cluster
|
||||
message := fmt.Sprintf("scan '%s' in action", handler.state.getLatestID())
|
||||
logger.L().Info("server is busy", helpers.String("message", message), helpers.Time())
|
||||
w.WriteHeader(http.StatusServiceUnavailable)
|
||||
w.Write([]byte(message))
|
||||
return
|
||||
}
|
||||
|
||||
handler.state.setBusy()
|
||||
defer handler.state.setNotBusy()
|
||||
|
||||
scanID := uuid.NewString()
|
||||
handler.state.setID(scanID)
|
||||
handler.state.setBusy(scanID)
|
||||
defer handler.state.setNotBusy(scanID)
|
||||
|
||||
resultsFile := filepath.Join(OutputDir, scanID)
|
||||
|
||||
// trigger scanning
|
||||
logger.L().Info(handler.state.getID(), helpers.String("action", "triggering scan"), helpers.Time())
|
||||
logger.L().Info(scanID, helpers.String("action", "triggering scan"), helpers.Time())
|
||||
|
||||
ks := core.NewKubescape()
|
||||
results, err := ks.Scan(getPrometheusDefaultScanCommand(scanID, resultsFile))
|
||||
if err != nil {
|
||||
@@ -41,7 +40,7 @@ func (handler *HTTPHandler) Metrics(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
results.HandleResults()
|
||||
logger.L().Info(handler.state.getID(), helpers.String("action", "done scanning"), helpers.Time())
|
||||
logger.L().Info(scanID, helpers.String("action", "done scanning"), helpers.Time())
|
||||
|
||||
f, err := os.ReadFile(resultsFile)
|
||||
if err != nil {
|
||||
|
||||
@@ -47,7 +47,7 @@ func NewHTTPHandler() *HTTPHandler {
|
||||
// ============================================== STATUS ========================================================
|
||||
// Status API
|
||||
func (handler *HTTPHandler) Status(w http.ResponseWriter, r *http.Request) {
|
||||
defer handler.recover(w)
|
||||
defer handler.recover(w, "")
|
||||
|
||||
if r.Method != http.MethodGet {
|
||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||
@@ -59,25 +59,22 @@ func (handler *HTTPHandler) Status(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
statusQueryParams := &StatusQueryParams{}
|
||||
if err := schema.NewDecoder().Decode(statusQueryParams, r.URL.Query()); err != nil {
|
||||
handler.writeError(w, fmt.Errorf("failed to parse query params, reason: %s", err.Error()))
|
||||
handler.writeError(w, fmt.Errorf("failed to parse query params, reason: %s", err.Error()), "")
|
||||
return
|
||||
}
|
||||
|
||||
if !handler.state.isBusy() {
|
||||
if !handler.state.isBusy(statusQueryParams.ScanID) {
|
||||
response.Type = utilsapisv1.NotBusyScanResponseType
|
||||
w.Write(responseToBytes(&response))
|
||||
return
|
||||
}
|
||||
|
||||
currentScanID := handler.state.getID()
|
||||
if statusQueryParams.ScanID != "" && currentScanID != statusQueryParams.ScanID {
|
||||
response.Type = utilsapisv1.NotBusyScanResponseType
|
||||
w.Write(responseToBytes(&response))
|
||||
return
|
||||
if statusQueryParams.ScanID == "" {
|
||||
statusQueryParams.ScanID = handler.state.getLatestID()
|
||||
}
|
||||
|
||||
response.Response = currentScanID
|
||||
response.ID = currentScanID
|
||||
response.Response = statusQueryParams.ScanID
|
||||
response.ID = statusQueryParams.ScanID
|
||||
response.Type = utilsapisv1.BusyScanResponseType
|
||||
w.Write(responseToBytes(&response))
|
||||
}
|
||||
@@ -86,7 +83,10 @@ func (handler *HTTPHandler) Status(w http.ResponseWriter, r *http.Request) {
|
||||
// Scan API - TODO: break down to functions
|
||||
func (handler *HTTPHandler) Scan(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
defer handler.recover(w)
|
||||
// generate id
|
||||
scanID := uuid.NewString()
|
||||
|
||||
defer handler.recover(w, scanID)
|
||||
|
||||
defer r.Body.Close()
|
||||
|
||||
@@ -99,30 +99,20 @@ func (handler *HTTPHandler) Scan(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
scanQueryParams := &ScanQueryParams{}
|
||||
if err := schema.NewDecoder().Decode(scanQueryParams, r.URL.Query()); err != nil {
|
||||
handler.writeError(w, fmt.Errorf("failed to parse query params, reason: %s", err.Error()))
|
||||
return
|
||||
}
|
||||
if handler.state.isBusy() {
|
||||
// TODO - Add to queue
|
||||
w.WriteHeader(http.StatusOK)
|
||||
response.Response = handler.state.getID()
|
||||
response.ID = handler.state.getID()
|
||||
response.Type = utilsapisv1.IDScanResponseType
|
||||
w.Write(responseToBytes(&response))
|
||||
handler.writeError(w, fmt.Errorf("failed to parse query params, reason: %s", err.Error()), scanID)
|
||||
return
|
||||
}
|
||||
|
||||
handler.state.setBusy()
|
||||
handler.state.setBusy(scanID)
|
||||
|
||||
// Add to queue
|
||||
|
||||
// generate id
|
||||
scanID := uuid.NewString()
|
||||
handler.state.setID(scanID)
|
||||
response.ID = scanID
|
||||
response.Type = utilsapisv1.IDScanResponseType
|
||||
|
||||
readBuffer, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
handler.writeError(w, fmt.Errorf("failed to read request body, reason: %s", err.Error()))
|
||||
handler.writeError(w, fmt.Errorf("failed to read request body, reason: %s", err.Error()), scanID)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -130,7 +120,7 @@ func (handler *HTTPHandler) Scan(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
scanRequest := utilsmetav1.PostScanRequest{}
|
||||
if err := json.Unmarshal(readBuffer, &scanRequest); err != nil {
|
||||
handler.writeError(w, fmt.Errorf("failed to parse request payload, reason: %s", err.Error()))
|
||||
handler.writeError(w, fmt.Errorf("failed to parse request payload, reason: %s", err.Error()), scanID)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -166,7 +156,7 @@ func (handler *HTTPHandler) Scan(w http.ResponseWriter, r *http.Request) {
|
||||
logger.L().Debug("deleting results", helpers.String("ID", scanID))
|
||||
removeResultsFile(scanID)
|
||||
}
|
||||
handler.state.setNotBusy()
|
||||
handler.state.setNotBusy(scanID)
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
@@ -174,6 +164,11 @@ func (handler *HTTPHandler) Scan(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(statusCode)
|
||||
w.Write(responseToBytes(&response))
|
||||
}
|
||||
func (handler *HTTPHandler) scan() {
|
||||
for {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================== RESULTS ========================================================
|
||||
|
||||
@@ -182,13 +177,13 @@ func (handler *HTTPHandler) Results(w http.ResponseWriter, r *http.Request) {
|
||||
response := utilsmetav1.Response{}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
defer handler.recover(w)
|
||||
defer handler.recover(w, "")
|
||||
|
||||
defer r.Body.Close()
|
||||
|
||||
resultsQueryParams := &ResultsQueryParams{}
|
||||
if err := schema.NewDecoder().Decode(resultsQueryParams, r.URL.Query()); err != nil {
|
||||
handler.writeError(w, fmt.Errorf("failed to parse query params, reason: %s", err.Error()))
|
||||
handler.writeError(w, fmt.Errorf("failed to parse query params, reason: %s", err.Error()), "")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -206,14 +201,13 @@ func (handler *HTTPHandler) Results(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
response.ID = resultsQueryParams.ScanID
|
||||
|
||||
if handler.state.isBusy() { // if requested ID is still scanning
|
||||
if resultsQueryParams.ScanID == handler.state.getID() {
|
||||
logger.L().Info("scan in process", helpers.String("ID", resultsQueryParams.ScanID))
|
||||
w.WriteHeader(http.StatusOK)
|
||||
response.Response = "scanning in progress"
|
||||
w.Write(responseToBytes(&response))
|
||||
return
|
||||
}
|
||||
if handler.state.isBusy(resultsQueryParams.ScanID) { // if requested ID is still scanning
|
||||
logger.L().Info("scan in process", helpers.String("ID", resultsQueryParams.ScanID))
|
||||
w.WriteHeader(http.StatusOK)
|
||||
response.Response = fmt.Sprintf("scanning '%s' in progress", resultsQueryParams.ScanID)
|
||||
w.Write(responseToBytes(&response))
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
switch r.Method {
|
||||
@@ -264,10 +258,10 @@ func responseToBytes(res *utilsmetav1.Response) []byte {
|
||||
return b
|
||||
}
|
||||
|
||||
func (handler *HTTPHandler) recover(w http.ResponseWriter) {
|
||||
func (handler *HTTPHandler) recover(w http.ResponseWriter, scanID string) {
|
||||
response := utilsmetav1.Response{}
|
||||
if err := recover(); err != nil {
|
||||
handler.state.setNotBusy()
|
||||
handler.state.setNotBusy(scanID)
|
||||
logger.L().Error("recover", helpers.Error(fmt.Errorf("%v", err)))
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
response.Response = fmt.Sprintf("%v", err)
|
||||
@@ -276,11 +270,11 @@ func (handler *HTTPHandler) recover(w http.ResponseWriter) {
|
||||
}
|
||||
}
|
||||
|
||||
func (handler *HTTPHandler) writeError(w http.ResponseWriter, err error) {
|
||||
func (handler *HTTPHandler) writeError(w http.ResponseWriter, err error, scanID string) {
|
||||
response := utilsmetav1.Response{}
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
response.Response = err.Error()
|
||||
response.Type = utilsapisv1.ErrorScanResponseType
|
||||
w.Write(responseToBytes(&response))
|
||||
handler.state.setNotBusy()
|
||||
handler.state.setNotBusy(scanID)
|
||||
}
|
||||
|
||||
@@ -3,44 +3,32 @@ package v1
|
||||
import "sync"
|
||||
|
||||
type serverState struct {
|
||||
// response string
|
||||
busy bool
|
||||
id string
|
||||
statusID map[string]bool
|
||||
latestID string
|
||||
mtx sync.RWMutex
|
||||
}
|
||||
|
||||
func (s *serverState) isBusy() bool {
|
||||
// isBusy is server busy with ID, if id is empty will check for latest ID
|
||||
func (s *serverState) isBusy(id string) bool {
|
||||
s.mtx.RLock()
|
||||
busy := s.busy
|
||||
if id == "" {
|
||||
id = s.latestID
|
||||
}
|
||||
busy := s.statusID[id]
|
||||
s.mtx.RUnlock()
|
||||
return busy
|
||||
}
|
||||
|
||||
func (s *serverState) setBusy() {
|
||||
func (s *serverState) setBusy(id string) {
|
||||
s.mtx.Lock()
|
||||
s.busy = true
|
||||
s.statusID[id] = true
|
||||
s.latestID = id
|
||||
s.mtx.Unlock()
|
||||
}
|
||||
|
||||
func (s *serverState) setNotBusy() {
|
||||
func (s *serverState) setNotBusy(id string) {
|
||||
s.mtx.Lock()
|
||||
s.busy = false
|
||||
s.latestID = s.id
|
||||
s.id = ""
|
||||
s.mtx.Unlock()
|
||||
}
|
||||
|
||||
func (s *serverState) getID() string {
|
||||
s.mtx.RLock()
|
||||
id := s.id
|
||||
s.mtx.RUnlock()
|
||||
return id
|
||||
}
|
||||
|
||||
func (s *serverState) setID(id string) {
|
||||
s.mtx.Lock()
|
||||
s.id = id
|
||||
delete(s.statusID, id)
|
||||
s.mtx.Unlock()
|
||||
}
|
||||
|
||||
@@ -51,9 +39,16 @@ func (s *serverState) getLatestID() string {
|
||||
return id
|
||||
}
|
||||
|
||||
func (s *serverState) len() int {
|
||||
s.mtx.RLock()
|
||||
l := len(s.statusID)
|
||||
s.mtx.RUnlock()
|
||||
return l
|
||||
}
|
||||
|
||||
func newServerState() *serverState {
|
||||
return &serverState{
|
||||
busy: false,
|
||||
mtx: sync.RWMutex{},
|
||||
statusID: make(map[string]bool),
|
||||
mtx: sync.RWMutex{},
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user