Skip to content

Commit 77d4bae

Browse files
authored
Fixes 4346: return task for introspect and snapshot APIs (#736)
* Fixes 4346: return task for introspect and snapshot APIs * update api docs
1 parent 3d65fdc commit 77d4bae

File tree

4 files changed

+79
-29
lines changed

4 files changed

+79
-29
lines changed

api/docs.go

+10-4
Original file line numberDiff line numberDiff line change
@@ -1002,8 +1002,11 @@ const docTemplate = `{
10021002
}
10031003
],
10041004
"responses": {
1005-
"204": {
1006-
"description": "Introspection was successfully queued"
1005+
"200": {
1006+
"description": "OK",
1007+
"schema": {
1008+
"$ref": "#/definitions/api.TaskInfoResponse"
1009+
}
10071010
},
10081011
"400": {
10091012
"description": "Bad Request",
@@ -1206,8 +1209,11 @@ const docTemplate = `{
12061209
}
12071210
],
12081211
"responses": {
1209-
"204": {
1210-
"description": "Snapshot was successfully queued"
1212+
"200": {
1213+
"description": "OK",
1214+
"schema": {
1215+
"$ref": "#/definitions/api.TaskInfoResponse"
1216+
}
12111217
},
12121218
"400": {
12131219
"description": "Bad Request",

api/openapi.json

+18-4
Original file line numberDiff line numberDiff line change
@@ -2534,8 +2534,15 @@
25342534
"x-originalParamName": "body"
25352535
},
25362536
"responses": {
2537-
"204": {
2538-
"description": "Introspection was successfully queued"
2537+
"200": {
2538+
"content": {
2539+
"application/json": {
2540+
"schema": {
2541+
"$ref": "#/components/schemas/api.TaskInfoResponse"
2542+
}
2543+
}
2544+
},
2545+
"description": "OK"
25392546
},
25402547
"400": {
25412548
"content": {
@@ -2800,8 +2807,15 @@
28002807
}
28012808
],
28022809
"responses": {
2803-
"204": {
2804-
"description": "Snapshot was successfully queued"
2810+
"200": {
2811+
"content": {
2812+
"application/json": {
2813+
"schema": {
2814+
"$ref": "#/components/schemas/api.TaskInfoResponse"
2815+
}
2816+
}
2817+
},
2818+
"description": "OK"
28052819
},
28062820
"400": {
28072821
"content": {

pkg/handler/repositories.go

+21-8
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ func (rh *RepositoryHandler) bulkDeleteRepositories(c echo.Context) error {
436436
// @Description Snapshot a repository if not already snapshotting
437437
// @Tags repositories
438438
// @Param uuid path string true "Repository ID."
439-
// @Success 204 "Snapshot was successfully queued"
439+
// @Success 200 {object} api.TaskInfoResponse
440440
// @Failure 400 {object} ce.ErrorResponse
441441
// @Failure 404 {object} ce.ErrorResponse
442442
// @Failure 500 {object} ce.ErrorResponse
@@ -465,9 +465,14 @@ func (rh *RepositoryHandler) createSnapshot(c echo.Context) error {
465465
return ce.NewErrorResponse(http.StatusBadRequest, "Error snapshotting repository", "Snapshotting not yet enabled for this repository.")
466466
}
467467

468-
rh.enqueueSnapshotEvent(c, &response)
468+
taskID := rh.enqueueSnapshotEvent(c, &response)
469469

470-
return c.NoContent(http.StatusNoContent)
470+
var resp api.TaskInfoResponse
471+
if resp, err = rh.DaoRegistry.TaskInfo.Fetch(c.Request().Context(), orgID, taskID); err != nil {
472+
return ce.NewErrorResponse(ce.HttpCodeForDaoError(err), "Error fetching task info", err.Error())
473+
}
474+
475+
return c.JSON(http.StatusOK, resp)
471476
}
472477

473478
// IntrospectRepository godoc
@@ -477,7 +482,7 @@ func (rh *RepositoryHandler) createSnapshot(c echo.Context) error {
477482
// @Tags repositories
478483
// @Param uuid path string true "Repository ID."
479484
// @Param body body api.RepositoryIntrospectRequest false "request body"
480-
// @Success 204 "Introspection was successfully queued"
485+
// @Success 200 {object} api.TaskInfoResponse
481486
// @Failure 400 {object} ce.ErrorResponse
482487
// @Failure 404 {object} ce.ErrorResponse
483488
// @Failure 500 {object} ce.ErrorResponse
@@ -536,9 +541,14 @@ func (rh *RepositoryHandler) introspect(c echo.Context) error {
536541
return ce.NewErrorResponse(ce.HttpCodeForDaoError(err), "Error resetting failed introspections count", err.Error())
537542
}
538543

539-
rh.enqueueIntrospectEvent(c, response, orgID)
544+
taskID := rh.enqueueIntrospectEvent(c, response, orgID)
540545

541-
return c.NoContent(http.StatusNoContent)
546+
var resp api.TaskInfoResponse
547+
if resp, err = rh.DaoRegistry.TaskInfo.Fetch(c.Request().Context(), orgID, taskID); err != nil {
548+
return ce.NewErrorResponse(ce.HttpCodeForDaoError(err), "error fetching task info", err.Error())
549+
}
550+
551+
return c.JSON(http.StatusOK, resp)
542552
}
543553

544554
// Update godoc
@@ -571,7 +581,7 @@ func (rh *RepositoryHandler) getGpgKeyFile(c echo.Context) error {
571581
}
572582

573583
// enqueueSnapshotEvent queues up a snapshot for a given repository uuid (not repository config) and org.
574-
func (rh *RepositoryHandler) enqueueSnapshotEvent(c echo.Context, response *api.RepositoryResponse) {
584+
func (rh *RepositoryHandler) enqueueSnapshotEvent(c echo.Context, response *api.RepositoryResponse) string {
575585
if config.PulpConfigured() {
576586
task := queue.Task{
577587
Typename: config.RepositorySnapshotTask,
@@ -593,7 +603,9 @@ func (rh *RepositoryHandler) enqueueSnapshotEvent(c echo.Context, response *api.
593603
response.LastSnapshotTaskUUID = taskID.String()
594604
}
595605
}
606+
return taskID.String()
596607
}
608+
return ""
597609
}
598610

599611
func (rh *RepositoryHandler) enqueueSnapshotDeleteEvent(c echo.Context, orgID string, repo api.RepositoryResponse) {
@@ -613,7 +625,7 @@ func (rh *RepositoryHandler) enqueueSnapshotDeleteEvent(c echo.Context, orgID st
613625
}
614626
}
615627

616-
func (rh *RepositoryHandler) enqueueIntrospectEvent(c echo.Context, response api.RepositoryResponse, orgID string) {
628+
func (rh *RepositoryHandler) enqueueIntrospectEvent(c echo.Context, response api.RepositoryResponse, orgID string) string {
617629
var err error
618630
task := queue.Task{
619631
Typename: payloads.Introspect,
@@ -628,6 +640,7 @@ func (rh *RepositoryHandler) enqueueIntrospectEvent(c echo.Context, response api
628640
logger := tasks.LogForTask(taskID.String(), task.Typename, task.RequestID)
629641
logger.Error().Msg("error enqueuing task")
630642
}
643+
return taskID.String()
631644
}
632645

633646
func (rh *RepositoryHandler) cancelIntrospectAndSnapshot(c echo.Context, orgID string, repoConfig api.RepositoryResponse) error {

pkg/handler/repositories_test.go

+30-13
Original file line numberDiff line numberDiff line change
@@ -981,40 +981,49 @@ func (suite *ReposSuite) TestIntrospectRepository() {
981981
t.Setenv("OPTIONS_INTROSPECT_API_TIME_LIMIT_SEC", "0")
982982
config.Load()
983983

984-
uuid := "abcadaba"
984+
repoConfigUUID := "abcadaba"
985985
repoUuid := "repoUuid"
986986
intReq := api.RepositoryIntrospectRequest{ResetCount: true}
987987
repoResp := api.RepositoryResponse{
988988
Name: "my repo",
989989
URL: "https://example.com",
990-
UUID: uuid,
990+
UUID: repoConfigUUID,
991991
RepositoryUUID: repoUuid,
992992
}
993993
repoUpdate := dao.RepositoryUpdate{UUID: "12345", FailedIntrospectionsCount: pointy.Int(0), LastIntrospectionStatus: pointy.String("Pending")}
994994
now := time.Now()
995995
repo := dao.Repository{UUID: "12345", LastIntrospectionTime: &now}
996+
expectedTaskInfo := api.TaskInfoResponse{OrgId: test_handler.MockOrgId}
996997

997998
mockTaskClientEnqueueIntrospect(suite.tcMock, "https://example.com", repoUuid)
998999

9991000
// Fetch will filter the request by Org ID before updating
10001001
suite.reg.Repository.On("Update", test.MockCtx(), repoUpdate).Return(nil).NotBefore(
10011002
suite.reg.Repository.On("FetchForUrl", test.MockCtx(), repoResp.URL).Return(repo, nil).NotBefore(
1002-
suite.reg.RepositoryConfig.WithContextMock().On("Fetch", test.MockCtx(), test_handler.MockOrgId, uuid).Return(repoResp, nil),
1003+
suite.reg.RepositoryConfig.WithContextMock().On("Fetch", test.MockCtx(), test_handler.MockOrgId, repoConfigUUID).Return(repoResp, nil),
10031004
),
10041005
)
1006+
suite.reg.TaskInfo.On("Fetch", test.MockCtx(), test_handler.MockOrgId, uuid.Nil.String()).Return(expectedTaskInfo, nil)
1007+
10051008
body, err := json.Marshal(intReq)
10061009
if err != nil {
10071010
t.Error("Could not marshal JSON")
10081011
}
10091012

1010-
req := httptest.NewRequest(http.MethodPost, api.FullRootPath()+"/repositories/"+uuid+"/introspect/",
1013+
req := httptest.NewRequest(http.MethodPost, api.FullRootPath()+"/repositories/"+repoConfigUUID+"/introspect/",
10111014
bytes.NewReader(body))
10121015
req.Header.Set("Content-Type", "application/json")
10131016
req.Header.Set(api.IdentityHeader, test_handler.EncodedIdentity(t))
10141017

1015-
code, _, err := suite.serveRepositoriesRouter(req)
1018+
code, body, err := suite.serveRepositoriesRouter(req)
10161019
assert.Nil(t, err)
1017-
assert.Equal(t, http.StatusNoContent, code)
1020+
1021+
var actualTaskInfo api.TaskInfoResponse
1022+
err = json.Unmarshal(body, &actualTaskInfo)
1023+
assert.Nil(t, err)
1024+
1025+
assert.Equal(t, actualTaskInfo, expectedTaskInfo)
1026+
assert.Equal(t, http.StatusOK, code)
10181027
}
10191028
func (suite *ReposSuite) TestIntrospectRepositoryFailedLimit() {
10201029
t := suite.T()
@@ -1052,41 +1061,49 @@ func (suite *ReposSuite) TestCreateSnapshot() {
10521061
config.Get().Features.Snapshots.Accounts = &[]string{test_handler.MockAccountNumber}
10531062
defer resetFeatures()
10541063

1055-
uuid := "abcadaba"
1064+
repoConfigUUID := "abcadaba"
10561065
repoUuid := "repoUuid"
10571066
repoResp := api.RepositoryResponse{
10581067
Name: "my repo",
10591068
URL: "https://example.com",
1060-
UUID: uuid,
1069+
UUID: repoConfigUUID,
10611070
RepositoryUUID: repoUuid,
10621071
Snapshot: true,
10631072
}
10641073

10651074
repoUpdate := dao.RepositoryUpdate{UUID: repoUuid, LastIntrospectionStatus: pointy.String(config.StatusPending)}
10661075
repo := dao.Repository{UUID: repoUuid}
1076+
expectedTaskInfo := api.TaskInfoResponse{OrgId: test_handler.MockOrgId}
10671077

10681078
mockTaskClientEnqueueSnapshot(suite, &repoResp)
10691079

10701080
// Fetch will filter the request by Org ID before updating
10711081
suite.reg.Repository.On("Update", test.MockCtx(), repoUpdate).Return(nil).NotBefore(
10721082
suite.reg.TaskInfo.On("IsTaskInProgress", test.MockCtx(), test_handler.MockOrgId, repo.UUID, config.RepositorySnapshotTask).Return(false, "", nil).
1073-
NotBefore(suite.reg.RepositoryConfig.On("Fetch", test.MockCtx(), test_handler.MockOrgId, uuid).Return(repoResp, nil)),
1083+
NotBefore(suite.reg.RepositoryConfig.On("Fetch", test.MockCtx(), test_handler.MockOrgId, repoConfigUUID).Return(repoResp, nil)),
10741084
suite.reg.TaskInfo.On("IsTaskInProgress", test.MockCtx(), test_handler.MockOrgId, repo.UUID, config.IntrospectTask).Return(false, "", nil).
1075-
NotBefore(suite.reg.RepositoryConfig.On("Fetch", test.MockCtx(), test_handler.MockOrgId, uuid).Return(repoResp, nil)),
1085+
NotBefore(suite.reg.RepositoryConfig.On("Fetch", test.MockCtx(), test_handler.MockOrgId, repoConfigUUID).Return(repoResp, nil)),
10761086
)
10771087

1088+
suite.reg.TaskInfo.On("Fetch", test.MockCtx(), test_handler.MockOrgId, uuid.Nil.String()).Return(expectedTaskInfo, nil)
1089+
10781090
body, err := json.Marshal("")
10791091
if err != nil {
10801092
t.Error("Could not marshal JSON")
10811093
}
10821094

1083-
req := httptest.NewRequest(http.MethodPost, api.FullRootPath()+"/repositories/"+uuid+"/snapshot/", bytes.NewReader(body))
1095+
req := httptest.NewRequest(http.MethodPost, api.FullRootPath()+"/repositories/"+repoConfigUUID+"/snapshot/", bytes.NewReader(body))
10841096
req.Header.Set("Content-Type", "application/json")
10851097
req.Header.Set(api.IdentityHeader, test_handler.EncodedIdentity(t))
10861098

1087-
code, _, err := suite.serveRepositoriesRouter(req)
1099+
code, body, err := suite.serveRepositoriesRouter(req)
10881100
assert.Nil(t, err)
1089-
assert.Equal(t, http.StatusNoContent, code)
1101+
1102+
var actualTaskInfo api.TaskInfoResponse
1103+
err = json.Unmarshal(body, &actualTaskInfo)
1104+
assert.Nil(t, err)
1105+
1106+
assert.Equal(t, http.StatusOK, code)
10901107
}
10911108

10921109
func (suite *ReposSuite) TestCreateSnapshotError() {

0 commit comments

Comments
 (0)