mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-23 10:45:45 +01:00
Merge pull request #2725 from ywk253100/170707_status_code
Return real status code returned by admiral APIs
This commit is contained in:
commit
0b282039e9
@ -23,6 +23,7 @@ import (
|
||||
"github.com/astaxie/beego/validation"
|
||||
"github.com/vmware/harbor/src/common/dao"
|
||||
"github.com/vmware/harbor/src/common/models"
|
||||
http_error "github.com/vmware/harbor/src/common/utils/error"
|
||||
"github.com/vmware/harbor/src/common/utils/log"
|
||||
"github.com/vmware/harbor/src/ui/auth"
|
||||
|
||||
@ -80,6 +81,21 @@ func (b *BaseAPI) HandleInternalServerError(text string) {
|
||||
b.RenderError(http.StatusInternalServerError, "")
|
||||
}
|
||||
|
||||
// ParseAndHandleError : if the err is an instance of utils/error.Error,
|
||||
// return the status code and the detail message contained in err, otherwise
|
||||
// return 500
|
||||
func (b *BaseAPI) ParseAndHandleError(text string, err error) {
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
log.Errorf("%s: %v", text, err)
|
||||
if e, ok := err.(*http_error.HTTPError); ok {
|
||||
b.RenderError(e.StatusCode, e.Detail)
|
||||
return
|
||||
}
|
||||
b.RenderError(http.StatusInternalServerError, "")
|
||||
}
|
||||
|
||||
// Render returns nil as it won't render template
|
||||
func (b *BaseAPI) Render() error {
|
||||
return nil
|
||||
|
@ -26,6 +26,7 @@ import (
|
||||
"github.com/vmware/harbor/src/common"
|
||||
"github.com/vmware/harbor/src/common/models"
|
||||
"github.com/vmware/harbor/src/common/utils"
|
||||
http_error "github.com/vmware/harbor/src/common/utils/error"
|
||||
"github.com/vmware/harbor/src/common/utils/log"
|
||||
)
|
||||
|
||||
@ -202,7 +203,10 @@ func send(client *http.Client, req *http.Request) (*AuthContext, error) {
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("unexpected status code: %d %s", resp.StatusCode, string(data))
|
||||
return nil, &http_error.HTTPError{
|
||||
StatusCode: resp.StatusCode,
|
||||
Detail: string(data),
|
||||
}
|
||||
}
|
||||
|
||||
ctx := &AuthContext{}
|
||||
|
@ -18,13 +18,13 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Error : if response is returned but the status code is not 200, an Error instance will be returned
|
||||
type Error struct {
|
||||
// HTTPError : if response is returned but the status code is not 200, an Error instance will be returned
|
||||
type HTTPError struct {
|
||||
StatusCode int
|
||||
Detail string
|
||||
}
|
||||
|
||||
// Error returns the details as string
|
||||
func (e *Error) Error() string {
|
||||
func (e *HTTPError) Error() string {
|
||||
return fmt.Sprintf("%d %s", e.StatusCode, e.Detail)
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ import (
|
||||
)
|
||||
|
||||
func TestError(t *testing.T) {
|
||||
err := &Error{
|
||||
err := &HTTPError{
|
||||
StatusCode: 404,
|
||||
Detail: "not found",
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ func getToken(client *http.Client, credential Credential, realm, service string,
|
||||
return nil, err
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, ®istry_error.Error{
|
||||
return nil, ®istry_error.HTTPError{
|
||||
StatusCode: resp.StatusCode,
|
||||
Detail: string(data),
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ func (r *Registry) Catalog() ([]string, error) {
|
||||
suffix = ""
|
||||
}
|
||||
} else {
|
||||
return repos, ®istry_error.Error{
|
||||
return repos, ®istry_error.HTTPError{
|
||||
StatusCode: resp.StatusCode,
|
||||
Detail: string(b),
|
||||
}
|
||||
@ -157,7 +157,7 @@ func (r *Registry) Ping() error {
|
||||
return err
|
||||
}
|
||||
|
||||
return ®istry_error.Error{
|
||||
return ®istry_error.HTTPError{
|
||||
StatusCode: resp.StatusCode,
|
||||
Detail: string(b),
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ func NewRepositoryWithModifiers(name, endpoint string, insecure bool, modifiers
|
||||
|
||||
func parseError(err error) error {
|
||||
if urlErr, ok := err.(*url.Error); ok {
|
||||
if regErr, ok := urlErr.Err.(*registry_error.Error); ok {
|
||||
if regErr, ok := urlErr.Err.(*registry_error.HTTPError); ok {
|
||||
return regErr
|
||||
}
|
||||
}
|
||||
@ -120,7 +120,7 @@ func (r *Repository) ListTag() ([]string, error) {
|
||||
return tags, nil
|
||||
}
|
||||
|
||||
return tags, ®istry_error.Error{
|
||||
return tags, ®istry_error.HTTPError{
|
||||
StatusCode: resp.StatusCode,
|
||||
Detail: string(b),
|
||||
}
|
||||
@ -160,7 +160,7 @@ func (r *Repository) ManifestExist(reference string) (digest string, exist bool,
|
||||
return
|
||||
}
|
||||
|
||||
err = ®istry_error.Error{
|
||||
err = ®istry_error.HTTPError{
|
||||
StatusCode: resp.StatusCode,
|
||||
Detail: string(b),
|
||||
}
|
||||
@ -197,7 +197,7 @@ func (r *Repository) PullManifest(reference string, acceptMediaTypes []string) (
|
||||
return
|
||||
}
|
||||
|
||||
err = ®istry_error.Error{
|
||||
err = ®istry_error.HTTPError{
|
||||
StatusCode: resp.StatusCode,
|
||||
Detail: string(b),
|
||||
}
|
||||
@ -232,7 +232,7 @@ func (r *Repository) PushManifest(reference, mediaType string, payload []byte) (
|
||||
return
|
||||
}
|
||||
|
||||
err = ®istry_error.Error{
|
||||
err = ®istry_error.HTTPError{
|
||||
StatusCode: resp.StatusCode,
|
||||
Detail: string(b),
|
||||
}
|
||||
@ -263,7 +263,7 @@ func (r *Repository) DeleteManifest(digest string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return ®istry_error.Error{
|
||||
return ®istry_error.HTTPError{
|
||||
StatusCode: resp.StatusCode,
|
||||
Detail: string(b),
|
||||
}
|
||||
@ -277,7 +277,7 @@ func (r *Repository) DeleteTag(tag string) error {
|
||||
}
|
||||
|
||||
if !exist {
|
||||
return ®istry_error.Error{
|
||||
return ®istry_error.HTTPError{
|
||||
StatusCode: http.StatusNotFound,
|
||||
}
|
||||
}
|
||||
@ -312,7 +312,7 @@ func (r *Repository) BlobExist(digest string) (bool, error) {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return false, ®istry_error.Error{
|
||||
return false, ®istry_error.HTTPError{
|
||||
StatusCode: resp.StatusCode,
|
||||
Detail: string(b),
|
||||
}
|
||||
@ -348,7 +348,7 @@ func (r *Repository) PullBlob(digest string) (size int64, data io.ReadCloser, er
|
||||
return
|
||||
}
|
||||
|
||||
err = ®istry_error.Error{
|
||||
err = ®istry_error.HTTPError{
|
||||
StatusCode: resp.StatusCode,
|
||||
Detail: string(b),
|
||||
}
|
||||
@ -379,7 +379,7 @@ func (r *Repository) initiateBlobUpload(name string) (location, uploadUUID strin
|
||||
return
|
||||
}
|
||||
|
||||
err = ®istry_error.Error{
|
||||
err = ®istry_error.HTTPError{
|
||||
StatusCode: resp.StatusCode,
|
||||
Detail: string(b),
|
||||
}
|
||||
@ -409,7 +409,7 @@ func (r *Repository) monolithicBlobUpload(location, digest string, size int64, d
|
||||
return err
|
||||
}
|
||||
|
||||
return ®istry_error.Error{
|
||||
return ®istry_error.HTTPError{
|
||||
StatusCode: resp.StatusCode,
|
||||
Detail: string(b),
|
||||
}
|
||||
@ -447,7 +447,7 @@ func (r *Repository) DeleteBlob(digest string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return ®istry_error.Error{
|
||||
return ®istry_error.HTTPError{
|
||||
StatusCode: resp.StatusCode,
|
||||
Detail: string(b),
|
||||
}
|
||||
|
@ -396,10 +396,10 @@ func TestListTag(t *testing.T) {
|
||||
|
||||
func TestParseError(t *testing.T) {
|
||||
err := &url.Error{
|
||||
Err: ®istry_error.Error{},
|
||||
Err: ®istry_error.HTTPError{},
|
||||
}
|
||||
e := parseError(err)
|
||||
if _, ok := e.(*registry_error.Error); !ok {
|
||||
if _, ok := e.(*registry_error.HTTPError); !ok {
|
||||
t.Errorf("error type does not match registry error")
|
||||
}
|
||||
}
|
||||
|
@ -67,8 +67,7 @@ func (pma *ProjectMemberAPI) Prepare() {
|
||||
}
|
||||
project, err := pma.ProjectMgr.Get(pid)
|
||||
if err != nil {
|
||||
pma.HandleInternalServerError(
|
||||
fmt.Sprintf("failed to get project %d: %v", pid, err))
|
||||
pma.ParseAndHandleError(fmt.Sprintf("failed to get project %d", pid), err)
|
||||
return
|
||||
}
|
||||
if project == nil {
|
||||
|
@ -59,8 +59,7 @@ func (p *ProjectAPI) Prepare() {
|
||||
|
||||
project, err := p.ProjectMgr.Get(id)
|
||||
if err != nil {
|
||||
p.HandleInternalServerError(fmt.Sprintf("failed to get project %d: %v",
|
||||
id, err))
|
||||
p.ParseAndHandleError(fmt.Sprintf("failed to get project %d", id), err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -107,8 +106,8 @@ func (p *ProjectAPI) Post() {
|
||||
|
||||
exist, err := p.ProjectMgr.Exist(pro.Name)
|
||||
if err != nil {
|
||||
p.HandleInternalServerError(fmt.Sprintf("failed to check the existence of project %s: %v",
|
||||
pro.Name, err))
|
||||
p.ParseAndHandleError(fmt.Sprintf("failed to check the existence of project %s",
|
||||
pro.Name), err)
|
||||
return
|
||||
}
|
||||
if exist {
|
||||
@ -126,12 +125,12 @@ func (p *ProjectAPI) Post() {
|
||||
AutomaticallyScanImagesOnPush: pro.AutomaticallyScanImagesOnPush,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("Failed to add project, error: %v", err)
|
||||
dup, _ := regexp.MatchString(dupProjectPattern, err.Error())
|
||||
if dup {
|
||||
log.Debugf("conflict %s", pro.Name)
|
||||
p.RenderError(http.StatusConflict, "")
|
||||
} else {
|
||||
p.RenderError(http.StatusInternalServerError, "Failed to add project")
|
||||
p.ParseAndHandleError("failed to add project", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -163,8 +162,7 @@ func (p *ProjectAPI) Head() {
|
||||
|
||||
project, err := p.ProjectMgr.Get(name)
|
||||
if err != nil {
|
||||
p.HandleInternalServerError(fmt.Sprintf("failed to get project %s: %v",
|
||||
name, err))
|
||||
p.ParseAndHandleError(fmt.Sprintf("failed to get project %s", name), err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -223,8 +221,7 @@ func (p *ProjectAPI) Delete() {
|
||||
}
|
||||
|
||||
if err = p.ProjectMgr.Delete(p.project.ProjectID); err != nil {
|
||||
p.HandleInternalServerError(
|
||||
fmt.Sprintf("failed to delete project %d: %v", p.project.ProjectID, err))
|
||||
p.ParseAndHandleError(fmt.Sprintf("failed to delete project %d", p.project.ProjectID), err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -299,13 +296,13 @@ func (p *ProjectAPI) List() {
|
||||
|
||||
total, err := p.ProjectMgr.GetTotal(query, base)
|
||||
if err != nil {
|
||||
p.HandleInternalServerError(fmt.Sprintf("failed to get total of projects: %v", err))
|
||||
p.ParseAndHandleError("failed to get total of projects", err)
|
||||
return
|
||||
}
|
||||
|
||||
projects, err := p.ProjectMgr.GetAll(query, base)
|
||||
if err != nil {
|
||||
p.HandleInternalServerError(fmt.Sprintf("failed to get projects: %v", err))
|
||||
p.ParseAndHandleError("failed to get projects", err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -359,8 +356,8 @@ func (p *ProjectAPI) ToggleProjectPublic() {
|
||||
&models.Project{
|
||||
Public: req.Public,
|
||||
}); err != nil {
|
||||
p.HandleInternalServerError(fmt.Sprintf("failed to update project %d: %v",
|
||||
p.project.ProjectID, err))
|
||||
p.ParseAndHandleError(fmt.Sprintf("failed to update project %d",
|
||||
p.project.ProjectID), err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -86,8 +86,8 @@ func (pa *RepPolicyAPI) List() {
|
||||
for _, policy := range policies {
|
||||
project, err := pa.ProjectMgr.Get(policy.ProjectID)
|
||||
if err != nil {
|
||||
pa.HandleInternalServerError(fmt.Sprintf(
|
||||
"failed to get project %d: %v", policy.ProjectID, err))
|
||||
pa.ParseAndHandleError(fmt.Sprintf(
|
||||
"failed to get project %d", policy.ProjectID), err)
|
||||
return
|
||||
}
|
||||
if project != nil {
|
||||
@ -118,8 +118,8 @@ func (pa *RepPolicyAPI) Post() {
|
||||
|
||||
project, err := pa.ProjectMgr.Get(policy.ProjectID)
|
||||
if err != nil {
|
||||
log.Errorf("failed to get project %d: %v", policy.ProjectID, err)
|
||||
pa.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
|
||||
pa.ParseAndHandleError(fmt.Sprintf("failed to get project %d", policy.ProjectID), err)
|
||||
return
|
||||
}
|
||||
|
||||
if project == nil {
|
||||
|
@ -84,8 +84,8 @@ func (ra *RepositoryAPI) Get() {
|
||||
|
||||
exist, err := ra.ProjectMgr.Exist(projectID)
|
||||
if err != nil {
|
||||
ra.HandleInternalServerError(fmt.Sprintf("failed to check the existence of project %d: %v",
|
||||
projectID, err))
|
||||
ra.ParseAndHandleError(fmt.Sprintf("failed to check the existence of project %d",
|
||||
projectID), err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -169,8 +169,8 @@ func (ra *RepositoryAPI) Delete() {
|
||||
projectName, _ := utils.ParseRepository(repoName)
|
||||
project, err := ra.ProjectMgr.Get(projectName)
|
||||
if err != nil {
|
||||
ra.HandleInternalServerError(fmt.Sprintf("failed to get the project %s: %v",
|
||||
projectName, err))
|
||||
ra.ParseAndHandleError(fmt.Sprintf("failed to get the project %s",
|
||||
projectName), err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -200,7 +200,7 @@ func (ra *RepositoryAPI) Delete() {
|
||||
if len(tag) == 0 {
|
||||
tagList, err := rc.ListTag()
|
||||
if err != nil {
|
||||
if regErr, ok := err.(*registry_error.Error); ok {
|
||||
if regErr, ok := err.(*registry_error.HTTPError); ok {
|
||||
ra.CustomAbort(regErr.StatusCode, regErr.Detail)
|
||||
}
|
||||
|
||||
@ -242,7 +242,7 @@ func (ra *RepositoryAPI) Delete() {
|
||||
|
||||
for _, t := range tags {
|
||||
if err = rc.DeleteTag(t); err != nil {
|
||||
if regErr, ok := err.(*registry_error.Error); ok {
|
||||
if regErr, ok := err.(*registry_error.HTTPError); ok {
|
||||
if regErr.StatusCode == http.StatusNotFound {
|
||||
continue
|
||||
}
|
||||
@ -335,8 +335,8 @@ func (ra *RepositoryAPI) GetTags() {
|
||||
projectName, _ := utils.ParseRepository(repoName)
|
||||
exist, err := ra.ProjectMgr.Exist(projectName)
|
||||
if err != nil {
|
||||
ra.HandleInternalServerError(fmt.Sprintf("failed to check the existence of project %s: %v",
|
||||
projectName, err))
|
||||
ra.ParseAndHandleError(fmt.Sprintf("failed to check the existence of project %s",
|
||||
projectName), err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -475,8 +475,8 @@ func (ra *RepositoryAPI) GetManifests() {
|
||||
projectName, _ := utils.ParseRepository(repoName)
|
||||
exist, err := ra.ProjectMgr.Exist(projectName)
|
||||
if err != nil {
|
||||
ra.HandleInternalServerError(fmt.Sprintf("failed to check the existence of project %s: %v",
|
||||
projectName, err))
|
||||
ra.ParseAndHandleError(fmt.Sprintf("failed to check the existence of project %s",
|
||||
projectName), err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -503,7 +503,7 @@ func (ra *RepositoryAPI) GetManifests() {
|
||||
|
||||
manifest, err := getManifest(rc, tag, version)
|
||||
if err != nil {
|
||||
if regErr, ok := err.(*registry_error.Error); ok {
|
||||
if regErr, ok := err.(*registry_error.HTTPError); ok {
|
||||
ra.CustomAbort(regErr.StatusCode, regErr.Detail)
|
||||
}
|
||||
|
||||
@ -577,7 +577,7 @@ func (ra *RepositoryAPI) GetTopRepos() {
|
||||
projectIDs := []int64{}
|
||||
projects, err := ra.ProjectMgr.GetPublic()
|
||||
if err != nil {
|
||||
ra.HandleInternalServerError(fmt.Sprintf("failed to get public projects: %v", err))
|
||||
ra.ParseAndHandleError("failed to get public projects", err)
|
||||
return
|
||||
}
|
||||
if ra.SecurityCtx.IsAuthenticated() {
|
||||
@ -617,8 +617,8 @@ func (ra *RepositoryAPI) GetSignatures() {
|
||||
projectName, _ := utils.ParseRepository(repoName)
|
||||
exist, err := ra.ProjectMgr.Exist(projectName)
|
||||
if err != nil {
|
||||
ra.HandleInternalServerError(fmt.Sprintf("failed to check the existence of project %s: %v",
|
||||
projectName, err))
|
||||
ra.ParseAndHandleError(fmt.Sprintf("failed to check the existence of project %s",
|
||||
projectName), err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -658,8 +658,8 @@ func (ra *RepositoryAPI) ScanImage() {
|
||||
projectName, _ := utils.ParseRepository(repoName)
|
||||
exist, err := ra.ProjectMgr.Exist(projectName)
|
||||
if err != nil {
|
||||
ra.HandleInternalServerError(fmt.Sprintf("failed to check the existence of project %s: %v",
|
||||
projectName, err))
|
||||
ra.ParseAndHandleError(fmt.Sprintf("failed to check the existence of project %s",
|
||||
projectName), err)
|
||||
return
|
||||
}
|
||||
if !exist {
|
||||
@ -776,7 +776,7 @@ func (ra *RepositoryAPI) checkExistence(repository, tag string) (bool, string, e
|
||||
project, _ := utils.ParseRepository(repository)
|
||||
exist, err := ra.ProjectMgr.Exist(project)
|
||||
if err != nil {
|
||||
return false, "", fmt.Errorf("failed to check the existence of project %s: %v", project, err)
|
||||
return false, "", err
|
||||
}
|
||||
if !exist {
|
||||
log.Errorf("project %s not found", project)
|
||||
|
@ -51,15 +51,13 @@ func (s *SearchAPI) Get() {
|
||||
if isSysAdmin {
|
||||
projects, err = s.ProjectMgr.GetAll(nil)
|
||||
if err != nil {
|
||||
s.HandleInternalServerError(fmt.Sprintf(
|
||||
"failed to get projects: %v", err))
|
||||
s.ParseAndHandleError("failed to get projects", err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
projects, err = s.ProjectMgr.GetPublic()
|
||||
if err != nil {
|
||||
s.HandleInternalServerError(fmt.Sprintf(
|
||||
"failed to get projects: %v", err))
|
||||
s.ParseAndHandleError("failed to get projects", err)
|
||||
return
|
||||
}
|
||||
if isAuthenticated {
|
||||
|
@ -59,8 +59,7 @@ func (s *StatisticAPI) Get() {
|
||||
statistic := map[string]int64{}
|
||||
pubProjs, err := s.ProjectMgr.GetPublic()
|
||||
if err != nil {
|
||||
s.HandleInternalServerError(fmt.Sprintf(
|
||||
"failed to get public projects: %v", err))
|
||||
s.ParseAndHandleError("failed to get public projects", err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -102,8 +101,8 @@ func (s *StatisticAPI) Get() {
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
s.HandleInternalServerError(fmt.Sprintf(
|
||||
"failed to get projects of user %s: %v", s.username, err))
|
||||
s.ParseAndHandleError(fmt.Sprintf(
|
||||
"failed to get projects of user %s", s.username), err)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,7 @@ func (t *TargetAPI) ping(endpoint, username, password string) {
|
||||
}
|
||||
|
||||
if err = registry.Ping(); err != nil {
|
||||
if regErr, ok := err.(*registry_error.Error); ok {
|
||||
if regErr, ok := err.(*registry_error.HTTPError); ok {
|
||||
t.CustomAbort(regErr.StatusCode, regErr.Detail)
|
||||
}
|
||||
|
||||
|
@ -440,7 +440,7 @@ func getReposByProject(name string, keyword ...string) ([]string, error) {
|
||||
func repositoryExist(name string, client *registry.Repository) (bool, error) {
|
||||
tags, err := client.ListTag()
|
||||
if err != nil {
|
||||
if regErr, ok := err.(*registry_error.Error); ok && regErr.StatusCode == http.StatusNotFound {
|
||||
if regErr, ok := err.(*registry_error.HTTPError); ok && regErr.StatusCode == http.StatusNotFound {
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
|
@ -412,7 +412,7 @@ func (p *ProjectManager) send(method, path string, body io.Reader) ([]byte, erro
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, &er.Error{
|
||||
return nil, &er.HTTPError{
|
||||
StatusCode: resp.StatusCode,
|
||||
Detail: string(b),
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user