fix(scanner): imporve clair adapter initializing

1. Remove ping action when initialize clair adapter installed by harbor.
2. Remvoe the `IsDefault` property when initialize clair adapter that
make it switch to auto detecting.

Signed-off-by: He Weiwei <hweiwei@vmware.com>
This commit is contained in:
He Weiwei 2019-10-31 08:03:37 +00:00
parent 86312d722e
commit 7170485a9b
4 changed files with 343 additions and 5 deletions

View File

@ -217,12 +217,10 @@ func main() {
log.Fatalf("failed to initialize clair database: %v", err)
}
// TODO: change to be internal adapter
reg := &scanner.Registration{
Name: "Clair",
Description: "The clair scanner adapter",
URL: config.ClairAdapterEndpoint(),
IsDefault: true,
UseInternalAddr: true,
Immutable: true,
}

View File

@ -15,10 +15,16 @@
package scan
import (
"fmt"
"github.com/goharbor/harbor/src/common/utils/log"
"github.com/goharbor/harbor/src/pkg/q"
sc "github.com/goharbor/harbor/src/pkg/scan/api/scanner"
"github.com/goharbor/harbor/src/pkg/scan/dao/scanner"
sc "github.com/goharbor/harbor/src/pkg/scan/scanner"
)
var (
scannerManager = sc.New()
)
// EnsureScanner ensure the scanner which specially name exists in the system
@ -27,13 +33,22 @@ func EnsureScanner(registration *scanner.Registration) error {
Keywords: map[string]interface{}{"url": registration.URL},
}
registrations, err := sc.DefaultController.ListRegistrations(q)
// Check if the registration with the url already existing.
registrations, err := scannerManager.List(q)
if err != nil {
return err
}
if len(registrations) == 0 {
if _, err := sc.DefaultController.CreateRegistration(registration); err != nil {
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
if _, err := scannerManager.Create(registration); err != nil {
return err
}

178
src/pkg/scan/init_test.go Normal file
View File

@ -0,0 +1,178 @@
// 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 scan
import (
"testing"
"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/scan/scanner/mocks"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
type managerOptions struct {
registrations []*scanner.Registration
listError error
getError error
getDefaultError error
createError error
}
func newManager(opts *managerOptions) sc.Manager {
if opts == nil {
opts = &managerOptions{}
}
data := map[string]*scanner.Registration{}
for _, reg := range opts.registrations {
data[reg.URL] = reg
}
mgr := &mocks.Manager{}
listFn := func(query *q.Query) []*scanner.Registration {
if opts.listError != nil {
return nil
}
url := query.Keywords["url"]
var results []*scanner.Registration
for key, reg := range data {
if url == key {
results = append(results, reg)
}
}
return results
}
getFn := func(url string) *scanner.Registration {
if opts.getError != nil {
return nil
}
return data[url]
}
getDefaultFn := func() *scanner.Registration {
if opts.getDefaultError != nil {
return nil
}
for _, reg := range data {
if reg.IsDefault {
return reg
}
}
return nil
}
createFn := func(reg *scanner.Registration) string {
if opts.createError != nil {
return ""
}
data[reg.URL] = reg
return reg.URL
}
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)
return mgr
}
func TestEnsureScanner(t *testing.T) {
assert := assert.New(t)
registrations := []*scanner.Registration{
{URL: "reg1"},
}
// registration with the url exist in the system
scannerManager = newManager(
&managerOptions{
registrations: registrations,
},
)
assert.Nil(EnsureScanner(&scanner.Registration{URL: "reg1"}))
// list registrations got error
scannerManager = newManager(
&managerOptions{
listError: errors.New("list registrations internal error"),
},
)
assert.Error(EnsureScanner(&scanner.Registration{URL: "reg1"}))
// create registration got error
scannerManager = newManager(
&managerOptions{
createError: errors.New("create registration internal error"),
},
)
assert.Error(EnsureScanner(&scanner.Registration{URL: "reg1"}))
// get default registration got error
scannerManager = newManager(
&managerOptions{
getDefaultError: errors.New("get default registration internal error"),
},
)
assert.Error(EnsureScanner(&scanner.Registration{URL: "reg1"}))
// create registration when no registrations in the system
scannerManager = newManager(nil)
assert.Nil(EnsureScanner(&scanner.Registration{URL: "reg1"}))
reg1, err := scannerManager.Get("reg1")
assert.Nil(err)
assert.NotNil(reg1)
assert.True(reg1.IsDefault)
// create registration when there are registrations in the system
scannerManager = newManager(
&managerOptions{
registrations: registrations,
},
)
assert.Nil(EnsureScanner(&scanner.Registration{URL: "reg2"}))
reg2, err := scannerManager.Get("reg2")
assert.Nil(err)
assert.NotNil(reg2)
assert.True(reg2.IsDefault)
// create registration when there are registrations in the system and the default registration exist
scannerManager = newManager(
&managerOptions{
registrations: []*scanner.Registration{
{URL: "reg1", IsDefault: true},
},
},
)
assert.Nil(EnsureScanner(&scanner.Registration{URL: "reg3"}))
reg3, err := scannerManager.Get("reg3")
assert.Nil(err)
assert.NotNil(reg3)
assert.False(reg3.IsDefault)
}

View File

@ -0,0 +1,147 @@
// Code generated by mockery v1.0.0. DO NOT EDIT.
package mocks
import (
q "github.com/goharbor/harbor/src/pkg/q"
mock "github.com/stretchr/testify/mock"
scanner "github.com/goharbor/harbor/src/pkg/scan/dao/scanner"
)
// Manager is an autogenerated mock type for the Manager type
type Manager struct {
mock.Mock
}
// Create provides a mock function with given fields: registration
func (_m *Manager) Create(registration *scanner.Registration) (string, error) {
ret := _m.Called(registration)
var r0 string
if rf, ok := ret.Get(0).(func(*scanner.Registration) string); ok {
r0 = rf(registration)
} else {
r0 = ret.Get(0).(string)
}
var r1 error
if rf, ok := ret.Get(1).(func(*scanner.Registration) error); ok {
r1 = rf(registration)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Delete provides a mock function with given fields: registrationUUID
func (_m *Manager) Delete(registrationUUID string) error {
ret := _m.Called(registrationUUID)
var r0 error
if rf, ok := ret.Get(0).(func(string) error); ok {
r0 = rf(registrationUUID)
} else {
r0 = ret.Error(0)
}
return r0
}
// Get provides a mock function with given fields: registrationUUID
func (_m *Manager) Get(registrationUUID string) (*scanner.Registration, error) {
ret := _m.Called(registrationUUID)
var r0 *scanner.Registration
if rf, ok := ret.Get(0).(func(string) *scanner.Registration); ok {
r0 = rf(registrationUUID)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*scanner.Registration)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string) error); ok {
r1 = rf(registrationUUID)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// GetDefault provides a mock function with given fields:
func (_m *Manager) GetDefault() (*scanner.Registration, error) {
ret := _m.Called()
var r0 *scanner.Registration
if rf, ok := ret.Get(0).(func() *scanner.Registration); ok {
r0 = rf()
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*scanner.Registration)
}
}
var r1 error
if rf, ok := ret.Get(1).(func() error); ok {
r1 = rf()
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// List provides a mock function with given fields: query
func (_m *Manager) List(query *q.Query) ([]*scanner.Registration, error) {
ret := _m.Called(query)
var r0 []*scanner.Registration
if rf, ok := ret.Get(0).(func(*q.Query) []*scanner.Registration); ok {
r0 = rf(query)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]*scanner.Registration)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(*q.Query) error); ok {
r1 = rf(query)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// SetAsDefault provides a mock function with given fields: registrationUUID
func (_m *Manager) SetAsDefault(registrationUUID string) error {
ret := _m.Called(registrationUUID)
var r0 error
if rf, ok := ret.Get(0).(func(string) error); ok {
r0 = rf(registrationUUID)
} else {
r0 = ret.Error(0)
}
return r0
}
// Update provides a mock function with given fields: registration
func (_m *Manager) Update(registration *scanner.Registration) error {
ret := _m.Called(registration)
var r0 error
if rf, ok := ret.Get(0).(func(*scanner.Registration) error); ok {
r0 = rf(registration)
} else {
r0 = ret.Error(0)
}
return r0
}