diff --git a/evidence/evidence_test.go b/evidence/evidence_test.go index b74083e2e..be92e94fd 100644 --- a/evidence/evidence_test.go +++ b/evidence/evidence_test.go @@ -186,3 +186,86 @@ func createErrorHandlerFuncVersion(t *testing.T) (http.HandlerFunc, *int) { w.WriteHeader(http.StatusNotFound) }, &requestNum } + +type DeleteEvidenceMockHandlerConfig struct { + StatusCode int + CapturedSubjectRepoPath *string + CapturedEvidenceName *string +} + +func createDeleteEvidenceMockHandler(t *testing.T, config *DeleteEvidenceMockHandlerConfig) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + switch { + case r.Method == http.MethodDelete && strings.HasPrefix(r.URL.Path, "/api/v1/evidence/"): + trimmed := strings.TrimPrefix(r.URL.Path, "/api/v1/evidence/") + lastSlash := strings.LastIndex(trimmed, "/") + if lastSlash < 0 { + t.Errorf("Unexpected delete path format: %s", r.URL.Path) + w.WriteHeader(http.StatusBadRequest) + return + } + subjectRepoPathEscaped := trimmed[:lastSlash] + evidenceNameEscaped := trimmed[lastSlash+1:] + + subjectRepoPath, err := url.PathUnescape(subjectRepoPathEscaped) + assert.NoError(t, err) + evidenceName, err := url.PathUnescape(evidenceNameEscaped) + assert.NoError(t, err) + + if config.CapturedSubjectRepoPath != nil { + *config.CapturedSubjectRepoPath = subjectRepoPath + } + if config.CapturedEvidenceName != nil { + *config.CapturedEvidenceName = evidenceName + } + + if config.StatusCode != 0 { + w.WriteHeader(config.StatusCode) + } else { + w.WriteHeader(http.StatusNoContent) + } + default: + t.Errorf("Unexpected request URI: %s", r.RequestURI) + w.WriteHeader(http.StatusNotFound) + } + } +} + +func TestDeleteEvidence_Success(t *testing.T) { + subjectRepoPath := "repo/path with space/a/b" + evidenceName := "evidence name.json" + + var capturedSubject string + var capturedName string + + handler := createDeleteEvidenceMockHandler(t, &DeleteEvidenceMockHandlerConfig{ + StatusCode: http.StatusNoContent, + CapturedSubjectRepoPath: &capturedSubject, + CapturedEvidenceName: &capturedName, + }) + mockServer, evdService := createMockServer(t, handler) + defer mockServer.Close() + + err := evdService.DeleteEvidence(subjectRepoPath, evidenceName) + assert.NoError(t, err) + assert.Equal(t, subjectRepoPath, capturedSubject) + assert.Equal(t, evidenceName, capturedName) +} + +func TestDeleteEvidence_NotFound(t *testing.T) { + handler := createDeleteEvidenceMockHandler(t, &DeleteEvidenceMockHandlerConfig{StatusCode: http.StatusNotFound}) + mockServer, evdService := createMockServer(t, handler) + defer mockServer.Close() + + err := evdService.DeleteEvidence("repo/a", "missing.json") + assert.Error(t, err) +} + +func TestDeleteEvidence_ServerError(t *testing.T) { + handler := createDeleteEvidenceMockHandler(t, &DeleteEvidenceMockHandlerConfig{StatusCode: http.StatusInternalServerError}) + mockServer, evdService := createMockServer(t, handler) + defer mockServer.Close() + + err := evdService.DeleteEvidence("repo/a", "boom.json") + assert.Error(t, err) +} diff --git a/evidence/manager.go b/evidence/manager.go index e4a8ce45c..3bc10e724 100644 --- a/evidence/manager.go +++ b/evidence/manager.go @@ -39,3 +39,8 @@ func (esm *EvidenceServicesManager) UploadEvidence(evidenceDetails services.Evid evidenceService := services.NewEvidenceService(esm.config.GetServiceDetails(), esm.client) return evidenceService.UploadEvidence(evidenceDetails) } + +func (esm *EvidenceServicesManager) DeleteEvidence(subjectRepoPath, evidenceName string) error { + evidenceService := services.NewEvidenceService(esm.config.GetServiceDetails(), esm.client) + return evidenceService.DeleteEvidence(subjectRepoPath, evidenceName) +} diff --git a/evidence/services/delete.go b/evidence/services/delete.go new file mode 100644 index 000000000..0a8bd7adb --- /dev/null +++ b/evidence/services/delete.go @@ -0,0 +1,35 @@ +package services + +import ( + "net/http" + "net/url" + "path" + + clientutils "github.com/jfrog/jfrog-client-go/utils" + "github.com/jfrog/jfrog-client-go/utils/errorutils" + "github.com/jfrog/jfrog-client-go/utils/log" +) + +const evidenceDeleteApi = "api/v1/evidence" + +func (es *EvidenceService) DeleteEvidence(subjectRepoPath, evidenceName string) error { + fullPath := path.Join(evidenceDeleteApi, subjectRepoPath, evidenceName) + u := url.URL{Path: fullPath} + + requestFullUrl, err := clientutils.BuildUrl(es.GetEvidenceDetails().GetUrl(), u.String(), nil) + if err != nil { + return errorutils.CheckError(err) + } + + httpClientDetails := es.GetEvidenceDetails().CreateHttpClientDetails() + httpClientDetails.SetContentTypeApplicationJson() + + log.Debug("Deleting evidence: ", requestFullUrl) + + resp, body, err := es.client.SendDelete(requestFullUrl, nil, &httpClientDetails) + if err != nil { + return err + } + + return errorutils.CheckResponseStatusWithBody(resp, body, http.StatusNoContent) +}