mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-18 08:15:16 +01:00
fix(scanner): process scenario reinstall without clair flag
1. Fix name conflict when install internal clair adapter. 2. Remove all internal adapters when reinstall harbor without --with-clair flag Signed-off-by: He Weiwei <hweiwei@vmware.com>
This commit is contained in:
parent
7b12ed14a1
commit
0246ca7aa4
@ -226,9 +226,13 @@ func main() {
|
||||
Immutable: true,
|
||||
}
|
||||
|
||||
if err := scan.EnsureScanner(reg); err != nil {
|
||||
if err := scan.EnsureScanner(reg, true); err != nil {
|
||||
log.Fatalf("failed to initialize clair scanner: %v", err)
|
||||
}
|
||||
} else {
|
||||
if err := scan.RemoveImmutableScanners(); err != nil {
|
||||
log.Warningf("failed to remove immutable scanners: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
closing := make(chan struct{})
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
"github.com/astaxie/beego/orm"
|
||||
"github.com/goharbor/harbor/src/common/dao"
|
||||
"github.com/goharbor/harbor/src/pkg/q"
|
||||
"github.com/goharbor/harbor/src/pkg/types"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@ -31,7 +32,16 @@ func init() {
|
||||
// AddRegistration adds a new registration
|
||||
func AddRegistration(r *Registration) (int64, error) {
|
||||
o := dao.GetOrmer()
|
||||
return o.Insert(r)
|
||||
|
||||
id, err := o.Insert(r)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "duplicate key value violates unique constraint") {
|
||||
return 0, types.ErrDupRows
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return id, nil
|
||||
}
|
||||
|
||||
// GetRegistration gets the specified registration
|
||||
|
@ -21,14 +21,17 @@ import (
|
||||
"github.com/goharbor/harbor/src/pkg/q"
|
||||
"github.com/goharbor/harbor/src/pkg/scan/dao/scanner"
|
||||
sc "github.com/goharbor/harbor/src/pkg/scan/scanner"
|
||||
"github.com/goharbor/harbor/src/pkg/types"
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
scannerManager = sc.New()
|
||||
)
|
||||
|
||||
// EnsureScanner ensure the scanner which specially name exists in the system
|
||||
func EnsureScanner(registration *scanner.Registration) error {
|
||||
// EnsureScanner ensure the scanner which specially endpoint exists in the system
|
||||
func EnsureScanner(registration *scanner.Registration, resolveConflicts ...bool) error {
|
||||
q := &q.Query{
|
||||
Keywords: map[string]interface{}{"url": registration.URL},
|
||||
}
|
||||
@ -39,20 +42,65 @@ func EnsureScanner(registration *scanner.Registration) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(registrations) == 0 {
|
||||
defaultReg, err := scannerManager.GetDefault()
|
||||
if len(registrations) > 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var resolveConflict bool
|
||||
if len(resolveConflicts) > 0 {
|
||||
resolveConflict = resolveConflicts[0]
|
||||
}
|
||||
|
||||
var defaultReg *scanner.Registration
|
||||
defaultReg, err = scannerManager.GetDefault()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get the default scanner, error: %v", err)
|
||||
}
|
||||
|
||||
// Set the registration to be default one when no default registration exist in the system
|
||||
registration.IsDefault = defaultReg == nil
|
||||
|
||||
for {
|
||||
_, err = scannerManager.Create(registration)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get the default scanner, error: %v", err)
|
||||
if resolveConflict && errors.Cause(err) == types.ErrDupRows {
|
||||
var id uuid.UUID
|
||||
id, err = uuid.NewUUID()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
registration.Name = registration.Name + "-" + id.String()
|
||||
resolveConflict = false
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Set the registration to be default one when no default registration exist in the system
|
||||
registration.IsDefault = defaultReg == nil
|
||||
break
|
||||
}
|
||||
|
||||
if _, err := scannerManager.Create(registration); err != nil {
|
||||
if err == nil {
|
||||
log.Infof("initialized scanner named %s", registration.Name)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// RemoveImmutableScanners remove all immutable scanners in the system
|
||||
func RemoveImmutableScanners() error {
|
||||
q := &q.Query{
|
||||
Keywords: map[string]interface{}{"immutable": true},
|
||||
}
|
||||
|
||||
registrations, err := scannerManager.List(q)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, reg := range registrations {
|
||||
if err := scannerManager.Delete(reg.UUID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infof("initialized scanner named %s", registration.Name)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
"github.com/goharbor/harbor/src/pkg/scan/dao/scanner"
|
||||
sc "github.com/goharbor/harbor/src/pkg/scan/scanner"
|
||||
"github.com/goharbor/harbor/src/pkg/scan/scanner/mocks"
|
||||
"github.com/goharbor/harbor/src/pkg/types"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
@ -32,6 +33,7 @@ type managerOptions struct {
|
||||
getError error
|
||||
getDefaultError error
|
||||
createError error
|
||||
createErrorFn func(*scanner.Registration) error
|
||||
}
|
||||
|
||||
func newManager(opts *managerOptions) sc.Manager {
|
||||
@ -95,10 +97,18 @@ func newManager(opts *managerOptions) sc.Manager {
|
||||
return reg.URL
|
||||
}
|
||||
|
||||
createError := func(reg *scanner.Registration) error {
|
||||
if opts.createErrorFn != nil {
|
||||
return opts.createErrorFn(reg)
|
||||
}
|
||||
|
||||
return opts.createError
|
||||
}
|
||||
|
||||
mgr.On("List", mock.AnythingOfType("*q.Query")).Return(listFn, opts.listError)
|
||||
mgr.On("Get", mock.AnythingOfType("string")).Return(getFn, opts.getError)
|
||||
mgr.On("GetDefault").Return(getDefaultFn, opts.getDefaultError)
|
||||
mgr.On("Create", mock.AnythingOfType("*scanner.Registration")).Return(createFn, opts.createError)
|
||||
mgr.On("Create", mock.AnythingOfType("*scanner.Registration")).Return(createFn, createError)
|
||||
|
||||
return mgr
|
||||
}
|
||||
@ -176,3 +186,30 @@ func TestEnsureScanner(t *testing.T) {
|
||||
assert.NotNil(reg3)
|
||||
assert.False(reg3.IsDefault)
|
||||
}
|
||||
|
||||
func TestEnsureScannerWithResolveConflict(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
registrations := []*scanner.Registration{
|
||||
{URL: "reg1"},
|
||||
}
|
||||
|
||||
// create registration got ErrDupRows when its name is Clair
|
||||
scannerManager = newManager(
|
||||
&managerOptions{
|
||||
registrations: registrations,
|
||||
|
||||
createErrorFn: func(reg *scanner.Registration) error {
|
||||
if reg.Name == "Clair" {
|
||||
return errors.Wrap(types.ErrDupRows, "failed to create reg")
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
assert.Nil(EnsureScanner(&scanner.Registration{Name: "Clair", URL: "reg1"}))
|
||||
assert.Error(EnsureScanner(&scanner.Registration{Name: "Clair", URL: "reg2"}))
|
||||
assert.Nil(EnsureScanner(&scanner.Registration{Name: "Clair", URL: "reg2"}, true))
|
||||
}
|
||||
|
24
src/pkg/types/error.go
Normal file
24
src/pkg/types/error.go
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright Project Harbor Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrDupRows is returned by DAO when inserting failed with error "duplicate key value violates unique constraint"
|
||||
ErrDupRows = errors.New("sql: duplicate row in DB")
|
||||
)
|
Loading…
Reference in New Issue
Block a user