From 8cc16de180c342928a9b56d5f5d814073089470c Mon Sep 17 00:00:00 2001 From: little_an <anyiwei123@sina.com> Date: Tue, 6 Dec 2022 16:12:21 +0800 Subject: [PATCH] fix dragonfly response when p2p preheat (#15916) * fix dragonfly response when p2p preheat Signed-off-by: anyiwei <anyiwei@didichuxing.com> --- src/pkg/p2p/preheat/provider/dragonfly.go | 67 ++++++++++++++----- .../p2p/preheat/provider/dragonfly_test.go | 26 +++++++ src/pkg/p2p/preheat/provider/mock.go | 55 +++++++++++++++ 3 files changed, 130 insertions(+), 18 deletions(-) diff --git a/src/pkg/p2p/preheat/provider/dragonfly.go b/src/pkg/p2p/preheat/provider/dragonfly.go index 82b17125b..c0b873733 100644 --- a/src/pkg/p2p/preheat/provider/dragonfly.go +++ b/src/pkg/p2p/preheat/provider/dragonfly.go @@ -2,13 +2,13 @@ package provider import ( "encoding/json" - "errors" "fmt" "net/http" "strings" common_http "github.com/goharbor/harbor/src/common/http" "github.com/goharbor/harbor/src/lib" + "github.com/goharbor/harbor/src/lib/errors" "github.com/goharbor/harbor/src/pkg/p2p/preheat/models/provider" "github.com/goharbor/harbor/src/pkg/p2p/preheat/provider/auth" "github.com/goharbor/harbor/src/pkg/p2p/preheat/provider/client" @@ -19,6 +19,7 @@ const ( preheatEndpoint = "/preheats" preheatTaskEndpoint = "/preheats/{task_id}" dragonflyPending = "WAITING" + dragonflyFailed = "FAILED" ) type dragonflyPreheatCreateResp struct { @@ -29,6 +30,7 @@ type dragonflyPreheatInfo struct { ID string `json:"ID"` StartTime string `json:"startTime,omitempty"` FinishTime string `json:"finishTime,omitempty"` + ErrorMsg string `json:"errorMsg"` Status string } @@ -109,6 +111,51 @@ func (dd *DragonflyDriver) Preheat(preheatingImage *PreheatImage) (*PreheatingSt // CheckProgress implements @Driver.CheckProgress. func (dd *DragonflyDriver) CheckProgress(taskID string) (*PreheatingStatus, error) { + status, err := dd.getProgressStatus(taskID) + if err != nil { + return nil, err + } + + // If preheat job already exists + if strings.Index(status.ErrorMsg, "preheat task already exists, id:") >= 0 { + if taskID, err = getTaskExistedFromErrMsg(status.ErrorMsg); err != nil { + return nil, err + } + if status, err = dd.getProgressStatus(taskID); err != nil { + return nil, err + } + } + + if status.Status == dragonflyPending { + status.Status = provider.PreheatingStatusPending + } else if status.Status == dragonflyFailed { + status.Status = provider.PreheatingStatusFail + } + + res := &PreheatingStatus{ + Status: status.Status, + TaskID: taskID, + } + if status.StartTime != "" { + res.StartTime = status.StartTime + } + if status.FinishTime != "" { + res.FinishTime = status.FinishTime + } + + return res, nil +} + +func getTaskExistedFromErrMsg(msg string) (string, error) { + begin := strings.Index(msg, "preheat task already exists, id:") + 32 + end := strings.LastIndex(msg, "\"}") + if end-begin <= 0 { + return "", errors.Errorf("can't find existed task id by error msg:%s", msg) + } + return msg[begin:end], nil +} + +func (dd *DragonflyDriver) getProgressStatus(taskID string) (*dragonflyPreheatInfo, error) { if dd.instance == nil { return nil, errors.New("missing instance metadata") } @@ -128,23 +175,7 @@ func (dd *DragonflyDriver) CheckProgress(taskID string) (*PreheatingStatus, erro if err := json.Unmarshal(bytes, status); err != nil { return nil, err } - - if status.Status == dragonflyPending { - status.Status = provider.PreheatingStatusPending - } - - res := &PreheatingStatus{ - Status: status.Status, - TaskID: taskID, - } - if status.StartTime != "" { - res.StartTime = status.StartTime - } - if status.FinishTime != "" { - res.FinishTime = status.FinishTime - } - - return res, nil + return status, nil } func (dd *DragonflyDriver) getCred() *auth.Credential { diff --git a/src/pkg/p2p/preheat/provider/dragonfly_test.go b/src/pkg/p2p/preheat/provider/dragonfly_test.go index 6d555635c..e7bfa658f 100644 --- a/src/pkg/p2p/preheat/provider/dragonfly_test.go +++ b/src/pkg/p2p/preheat/provider/dragonfly_test.go @@ -113,4 +113,30 @@ func (suite *DragonflyTestSuite) TestCheckProgress() { st, err := suite.driver.CheckProgress("dragonfly-id") require.NoError(suite.T(), err, "get preheat status") suite.Equal(provider.PreheatingStatusSuccess, st.Status, "preheat status") + + // preheat job exit but returns no id + st, err = suite.driver.CheckProgress("preheat-job-exist-with-no-id") + require.Error(suite.T(), err, "get preheat status") + + // preheat job exit returns id but get info with that failed + st, err = suite.driver.CheckProgress("preheat-job-exist-with-id-1") + require.Error(suite.T(), err, "get preheat status") + + // preheat job normal failed + st, err = suite.driver.CheckProgress("preheat-job-normal-failed") + require.NoError(suite.T(), err, "get preheat status") + suite.Equal(provider.PreheatingStatusFail, st.Status, "preheat status") + + // instance is empty + testDriver := &DragonflyDriver{} + st, err = testDriver.CheckProgress("") + require.Error(suite.T(), err, "get preheat status") + + // preheat job with no task id + st, err = suite.driver.CheckProgress("") + require.Error(suite.T(), err, "get preheat status") + + // preheat job with err json response + st, err = suite.driver.CheckProgress("preheat-job-err-body-json") + require.Error(suite.T(), err, "get preheat status") } diff --git a/src/pkg/p2p/preheat/provider/mock.go b/src/pkg/p2p/preheat/provider/mock.go index 21bd02386..3ff3973bb 100644 --- a/src/pkg/p2p/preheat/provider/mock.go +++ b/src/pkg/p2p/preheat/provider/mock.go @@ -95,6 +95,61 @@ func MockDragonflyProvider() *httptest.Server { } bytes, _ := json.Marshal(status) _, _ = w.Write(bytes) + case strings.Replace(preheatTaskEndpoint, "{task_id}", "preheat-job-exist-with-no-id", 1): + if r.Method != http.MethodGet { + w.WriteHeader(http.StatusNotImplemented) + return + } + status := &dragonflyPreheatInfo{ + ID: "preheat-exist-with-no-id", + StartTime: time.Now().UTC().String(), + FinishTime: time.Now().Add(5 * time.Minute).UTC().String(), + Status: "FAILED", + ErrorMsg: "{\"Code\":208,\"Msg\":\"preheat task already exists, id:\"}", + } + bytes, _ := json.Marshal(status) + _, _ = w.Write(bytes) + case strings.Replace(preheatTaskEndpoint, "{task_id}", "preheat-job-normal-failed", 1): + if r.Method != http.MethodGet { + w.WriteHeader(http.StatusNotImplemented) + return + } + status := &dragonflyPreheatInfo{ + ID: "preheat-job-exist-with-id-1", + StartTime: time.Now().UTC().String(), + FinishTime: time.Now().Add(5 * time.Minute).UTC().String(), + Status: "FAILED", + ErrorMsg: "{\"Code\":208,\"Msg\":\"some msg\"}", + } + bytes, _ := json.Marshal(status) + _, _ = w.Write(bytes) + case strings.Replace(preheatTaskEndpoint, "{task_id}", "preheat-job-exist-with-id-1", 1): + if r.Method != http.MethodGet { + w.WriteHeader(http.StatusNotImplemented) + return + } + status := &dragonflyPreheatInfo{ + ID: "preheat-job-exist-with-id-1", + StartTime: time.Now().UTC().String(), + FinishTime: time.Now().Add(5 * time.Minute).UTC().String(), + Status: "FAILED", + ErrorMsg: "{\"Code\":208,\"Msg\":\"preheat task already exists, id:preheat-job-exist-with-id-1-1\"}", + } + bytes, _ := json.Marshal(status) + _, _ = w.Write(bytes) + case strings.Replace(preheatTaskEndpoint, "{task_id}", "preheat-job-exist-with-id-1-1", 1): + if r.Method != http.MethodGet { + w.WriteHeader(http.StatusNotImplemented) + return + } + w.WriteHeader(http.StatusInternalServerError) + case strings.Replace(preheatTaskEndpoint, "{task_id}", "preheat-job-err-body-json", 1): + if r.Method != http.MethodGet { + w.WriteHeader(http.StatusNotImplemented) + return + } + bodyStr := "\"err body\"" + _, _ = w.Write([]byte(bodyStr)) default: w.WriteHeader(http.StatusNotImplemented) }