mirror of
https://github.com/goharbor/harbor
synced 2025-04-12 23:24:59 +00:00
Merge pull request #3101 from ywk253100/170822_replica
Convert 500 error returned by Admiral to duplicate project error when creating duplicate project
This commit is contained in:
commit
f41d2ff436
|
@ -15,9 +15,13 @@
|
||||||
package error
|
package error
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ErrDupProject is the error returned when creating a duplicate project
|
||||||
|
var ErrDupProject = errors.New("duplicate project")
|
||||||
|
|
||||||
// HTTPError : if response is returned but the status code is not 200, an Error instance will be returned
|
// HTTPError : if response is returned but the status code is not 200, an Error instance will be returned
|
||||||
type HTTPError struct {
|
type HTTPError struct {
|
||||||
StatusCode int
|
StatusCode int
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"github.com/vmware/harbor/src/common/dao"
|
"github.com/vmware/harbor/src/common/dao"
|
||||||
"github.com/vmware/harbor/src/common/models"
|
"github.com/vmware/harbor/src/common/models"
|
||||||
"github.com/vmware/harbor/src/common/utils"
|
"github.com/vmware/harbor/src/common/utils"
|
||||||
|
errutil "github.com/vmware/harbor/src/common/utils/error"
|
||||||
"github.com/vmware/harbor/src/common/utils/log"
|
"github.com/vmware/harbor/src/common/utils/log"
|
||||||
"github.com/vmware/harbor/src/ui/config"
|
"github.com/vmware/harbor/src/ui/config"
|
||||||
|
|
||||||
|
@ -44,7 +45,6 @@ type ProjectAPI struct {
|
||||||
const projectNameMaxLen int = 30
|
const projectNameMaxLen int = 30
|
||||||
const projectNameMinLen int = 2
|
const projectNameMinLen int = 2
|
||||||
const restrictedNameChars = `[a-z0-9]+(?:[._-][a-z0-9]+)*`
|
const restrictedNameChars = `[a-z0-9]+(?:[._-][a-z0-9]+)*`
|
||||||
const dupProjectPattern = `Duplicate entry '\w+' for key 'name'`
|
|
||||||
|
|
||||||
// Prepare validates the URL and the user
|
// Prepare validates the URL and the user
|
||||||
func (p *ProjectAPI) Prepare() {
|
func (p *ProjectAPI) Prepare() {
|
||||||
|
@ -130,8 +130,7 @@ func (p *ProjectAPI) Post() {
|
||||||
AutomaticallyScanImagesOnPush: pro.AutomaticallyScanImagesOnPush,
|
AutomaticallyScanImagesOnPush: pro.AutomaticallyScanImagesOnPush,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
dup, _ := regexp.MatchString(dupProjectPattern, err.Error())
|
if err == errutil.ErrDupProject {
|
||||||
if dup {
|
|
||||||
log.Debugf("conflict %s", pro.Name)
|
log.Debugf("conflict %s", pro.Name)
|
||||||
p.RenderError(http.StatusConflict, "")
|
p.RenderError(http.StatusConflict, "")
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -16,12 +16,17 @@ package db
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"regexp"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/vmware/harbor/src/common/dao"
|
"github.com/vmware/harbor/src/common/dao"
|
||||||
"github.com/vmware/harbor/src/common/models"
|
"github.com/vmware/harbor/src/common/models"
|
||||||
|
errutil "github.com/vmware/harbor/src/common/utils/error"
|
||||||
|
"github.com/vmware/harbor/src/common/utils/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const dupProjectPattern = `Duplicate entry '\w+' for key 'name'`
|
||||||
|
|
||||||
// ProjectManager implements pm.PM interface based on database
|
// ProjectManager implements pm.PM interface based on database
|
||||||
type ProjectManager struct{}
|
type ProjectManager struct{}
|
||||||
|
|
||||||
|
@ -105,7 +110,21 @@ func (p *ProjectManager) Create(project *models.Project) (int64, error) {
|
||||||
UpdateTime: t,
|
UpdateTime: t,
|
||||||
}
|
}
|
||||||
|
|
||||||
return dao.AddProject(*pro)
|
id, err := dao.AddProject(*pro)
|
||||||
|
if err != nil {
|
||||||
|
dup, e := regexp.MatchString(dupProjectPattern, err.Error())
|
||||||
|
if e != nil {
|
||||||
|
log.Errorf("failed to match duplicate project pattern: %v", e)
|
||||||
|
}
|
||||||
|
|
||||||
|
if dup {
|
||||||
|
err = errutil.ErrDupProject
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return id, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete ...
|
// Delete ...
|
||||||
|
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/vmware/harbor/src/common/dao"
|
"github.com/vmware/harbor/src/common/dao"
|
||||||
"github.com/vmware/harbor/src/common/models"
|
"github.com/vmware/harbor/src/common/models"
|
||||||
|
errutil "github.com/vmware/harbor/src/common/utils/error"
|
||||||
"github.com/vmware/harbor/src/common/utils/log"
|
"github.com/vmware/harbor/src/common/utils/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -166,6 +167,19 @@ func TestCreateAndDelete(t *testing.T) {
|
||||||
})
|
})
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Nil(t, pm.Delete(id))
|
assert.Nil(t, pm.Delete(id))
|
||||||
|
|
||||||
|
// duplicate project name
|
||||||
|
id, err = pm.Create(&models.Project{
|
||||||
|
Name: "test",
|
||||||
|
OwnerName: "admin",
|
||||||
|
})
|
||||||
|
assert.Nil(t, err)
|
||||||
|
defer pm.Delete(id)
|
||||||
|
_, err = pm.Create(&models.Project{
|
||||||
|
Name: "test",
|
||||||
|
OwnerName: "admin",
|
||||||
|
})
|
||||||
|
assert.Equal(t, errutil.ErrDupProject, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUpdate(t *testing.T) {
|
func TestUpdate(t *testing.T) {
|
||||||
|
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -31,6 +32,8 @@ import (
|
||||||
"github.com/vmware/harbor/src/common/utils/log"
|
"github.com/vmware/harbor/src/common/utils/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const dupProjectPattern = `Project name '\w+' is already used`
|
||||||
|
|
||||||
// ProjectManager implements projectmanager.ProjecdtManager interface
|
// ProjectManager implements projectmanager.ProjecdtManager interface
|
||||||
// base on project management service
|
// base on project management service
|
||||||
type ProjectManager struct {
|
type ProjectManager struct {
|
||||||
|
@ -366,6 +369,33 @@ func (p *ProjectManager) Create(pro *models.Project) (int64, error) {
|
||||||
|
|
||||||
b, err := p.send(http.MethodPost, "/projects", bytes.NewBuffer(data))
|
b, err := p.send(http.MethodPost, "/projects", bytes.NewBuffer(data))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// when creating a project with a duplicate name in Admiral, a 500 error
|
||||||
|
// with a specific message will be returned for now.
|
||||||
|
// Maybe a 409 error will be returned if Admiral team finds the way to
|
||||||
|
// return a specific code in Xenon.
|
||||||
|
// The following codes convert both those two errors to DupProjectErr
|
||||||
|
httpErr, ok := err.(*er.HTTPError)
|
||||||
|
if !ok {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if httpErr.StatusCode == http.StatusConflict {
|
||||||
|
return 0, er.ErrDupProject
|
||||||
|
}
|
||||||
|
|
||||||
|
if httpErr.StatusCode != http.StatusInternalServerError {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
match, e := regexp.MatchString(dupProjectPattern, httpErr.Detail)
|
||||||
|
if e != nil {
|
||||||
|
log.Errorf("failed to match duplicate project mattern: %v", e)
|
||||||
|
}
|
||||||
|
|
||||||
|
if match {
|
||||||
|
err = er.ErrDupProject
|
||||||
|
}
|
||||||
|
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/vmware/harbor/src/common/models"
|
"github.com/vmware/harbor/src/common/models"
|
||||||
|
errutil "github.com/vmware/harbor/src/common/utils/error"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -344,6 +345,12 @@ func TestCreate(t *testing.T) {
|
||||||
assert.True(t, project.PreventVulnerableImagesFromRunning)
|
assert.True(t, project.PreventVulnerableImagesFromRunning)
|
||||||
assert.Equal(t, "medium", project.PreventVulnerableImagesFromRunningSeverity)
|
assert.Equal(t, "medium", project.PreventVulnerableImagesFromRunningSeverity)
|
||||||
assert.True(t, project.AutomaticallyScanImagesOnPush)
|
assert.True(t, project.AutomaticallyScanImagesOnPush)
|
||||||
|
|
||||||
|
// duplicate project name
|
||||||
|
_, err = pm.Create(&models.Project{
|
||||||
|
Name: name,
|
||||||
|
})
|
||||||
|
assert.Equal(t, errutil.ErrDupProject, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDelete(t *testing.T) {
|
func TestDelete(t *testing.T) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user