feat(vulnerability): assemble vulnerabilities info for artifact (#10800)

1. Assemble scan overview to artifact when scanner enabled in the
project of the artifact.
2. Set addition link for vulnerabilities to artifact when scanner
enabled in the project of the artifact.

Signed-off-by: He Weiwei <hweiwei@vmware.com>
This commit is contained in:
He Weiwei 2020-02-22 13:29:58 +08:00 committed by GitHub
parent 1765abc985
commit f36152a560
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 891 additions and 53 deletions

View File

@ -135,31 +135,31 @@ paths:
required: false
- name: with_tag
in: query
description: Specify whether the tags are inclued inside the returning artifacts
description: Specify whether the tags are included inside the returning artifacts
type: boolean
required: false
default: true
- name: with_label
in: query
description: Specify whether the labels are inclued inside the returning artifacts
description: Specify whether the labels are included inside the returning artifacts
type: boolean
required: false
default: false
- name: with_scan_overview
in: query
description: Specify whether the scan overview is inclued inside the returning artifacts
description: Specify whether the scan overview is included inside the returning artifacts
type: boolean
required: false
default: false
- name: with_signature
in: query
description: Specify whether the signature is inclued inside the tags of the returning artifacts. Only works when setting "with_tag=true"
description: Specify whether the signature is included inside the tags of the returning artifacts. Only works when setting "with_tag=true"
type: boolean
required: false
default: false
- name: with_immutable_status
in: query
description: Specify whether the immutable status is inclued inside the tags of the returning artifacts. Only works when setting "with_tag=true"
description: Specify whether the immutable status is included inside the tags of the returning artifacts. Only works when setting "with_tag=true"
type: boolean
required: false
default: false
@ -372,7 +372,7 @@ paths:
in: path
description: The type of addition.
type: string
enum: [build_history, values.yaml, readme.md, dependencies]
enum: [build_history, values.yaml, readme.md, dependencies, vulnerabilities]
required: true
responses:
'200':
@ -670,6 +670,9 @@ definitions:
type: array
items:
$ref: '#/definitions/Label'
scan_overview:
$ref: '#/definitions/ScanOverview'
description: The overview of the scan result.
Tag:
type: object
properties:
@ -796,4 +799,66 @@ definitions:
deleted:
type: boolean
description: Whether the label is deleted or not
ScanOverview:
type: object
description: 'The scan overview attached in the metadata of tag'
additionalProperties:
$ref: '#/definitions/NativeReportSummary'
NativeReportSummary:
type: object
description: 'The summary for the native report'
properties:
report_id:
type: string
description: 'id of the native scan report'
example: '5f62c830-f996-11e9-957f-0242c0a89008'
scan_status:
type: string
description: 'The status of the report generating process'
example: 'Success'
severity:
type: string
description: 'The overall severity'
example: 'High'
duration:
type: integer
format: int64
description: 'The seconds spent for generating the report'
example: 300
summary:
$ref: '#/definitions/VulnerabilitySummary'
start_time:
type: string
format: date-time
description: 'The start time of the scan process that generating report'
example: '2006-01-02T14:04:05'
end_time:
type: string
format: date-time
description: 'The end time of the scan process that generating report'
example: '2006-01-02T15:04:05'
VulnerabilitySummary:
type: object
description: |
VulnerabilitySummary contains the total number of the foun d vulnerabilities number and numbers of each severity level.
properties:
total:
type: integer
format: int
description: 'The total number of the found vulnerabilities'
example: 500
fixable:
type: integer
format: int
description: 'The number of the fixable vulnerabilities'
example: 100
summary:
type: object
description: 'Numbers of the vulnerabilities with different severity'
additionalProperties:
type: integer
format: int
example: 10
example:
'Critical': 5
'High': 5

View File

@ -239,6 +239,11 @@ func (c *controller) List(ctx context.Context, query *q.Query, option *Option) (
if err != nil {
return nil, err
}
if err := c.populateRepositoryName(ctx, arts...); err != nil {
return nil, err
}
var artifacts []*Artifact
for _, art := range arts {
artifacts = append(artifacts, c.assembleArtifact(ctx, art, option))
@ -516,6 +521,17 @@ func (c *controller) assembleArtifact(ctx context.Context, art *artifact.Artifac
artifact := &Artifact{
Artifact: *art,
}
if artifact.RepositoryName == "" {
repo, err := c.repoMgr.Get(ctx, artifact.RepositoryID)
if err != nil {
log.Errorf("get repository %d failed, error: %v", artifact.RepositoryID, err)
return artifact
}
artifact.RepositoryName = repo.Name
}
// populate addition links
c.populateAdditionLinks(ctx, artifact)
if option == nil {
@ -532,6 +548,34 @@ func (c *controller) assembleArtifact(ctx context.Context, art *artifact.Artifac
return artifact
}
func (c *controller) populateRepositoryName(ctx context.Context, artifacts ...*artifact.Artifact) error {
var ids []int64
for _, artifact := range artifacts {
ids = append(ids, artifact.RepositoryID)
}
repositories, err := c.repoMgr.List(ctx, &q.Query{Keywords: map[string]interface{}{"repository_id__in": ids}})
if err != nil {
return err
}
mp := make(map[int64]string, len(repositories))
for _, repository := range repositories {
mp[repository.RepositoryID] = repository.Name
}
for _, artifact := range artifacts {
repositoryName, ok := mp[artifact.RepositoryID]
if !ok {
return ierror.NotFoundError(nil).WithMessage("repository %d not found", artifact.RepositoryID)
}
artifact.RepositoryName = repositoryName
}
return nil
}
func (c *controller) populateTags(ctx context.Context, art *Artifact, option *TagOption) {
tags, err := c.tagMgr.List(ctx, &q.Query{
Keywords: map[string]interface{}{
@ -619,25 +663,11 @@ func (c *controller) populateAdditionLinks(ctx context.Context, artifact *Artifa
log.Error(err.Error())
return
}
if len(types) == 0 {
return
}
repository, err := c.repoMgr.Get(ctx, artifact.RepositoryID)
if err != nil {
log.Error(err.Error())
return
}
pro, repo := utils.ParseRepository(repository.Name)
version := internal.GetAPIVersion(ctx)
if artifact.AdditionLinks == nil {
artifact.AdditionLinks = make(map[string]*AdditionLink)
}
for _, t := range types {
t = strings.ToLower(t)
artifact.AdditionLinks[t] = &AdditionLink{
HREF: fmt.Sprintf("/api/%s/projects/%s/repositories/%s/artifacts/%s/additions/%s",
version, pro, repo, artifact.Digest, t),
Absolute: false,
if len(types) > 0 {
version := internal.GetAPIVersion(ctx)
for _, t := range types {
artifact.SetAdditionLink(strings.ToLower(t), version)
}
}
}

View File

@ -134,8 +134,9 @@ func (c *controllerTestSuite) TestAssembleTag() {
func (c *controllerTestSuite) TestAssembleArtifact() {
art := &artifact.Artifact{
ID: 1,
Digest: "sha256:123",
ID: 1,
Digest: "sha256:123",
RepositoryName: "library/hello-world",
}
option := &Option{
WithTag: true,
@ -297,6 +298,9 @@ func (c *controllerTestSuite) TestList() {
c.repoMgr.On("Get").Return(&models.RepoRecord{
Name: "library/hello-world",
}, nil)
c.repoMgr.On("List").Return([]*models.RepoRecord{
{RepositoryID: 1, Name: "library/hello-world"},
}, nil)
artifacts, err := c.ctl.List(nil, query, option)
c.Require().Nil(err)
c.Require().Len(artifacts, 1)

View File

@ -15,7 +15,10 @@
package artifact
import (
"fmt"
cmodels "github.com/goharbor/harbor/src/common/models"
"github.com/goharbor/harbor/src/common/utils"
"github.com/goharbor/harbor/src/pkg/artifact"
"github.com/goharbor/harbor/src/pkg/signature"
"github.com/goharbor/harbor/src/pkg/tag/model/tag"
@ -29,6 +32,18 @@ type Artifact struct {
Labels []*cmodels.Label `json:"labels"`
}
// SetAdditionLink set a addition link
func (artifact *Artifact) SetAdditionLink(addition, version string) {
if artifact.AdditionLinks == nil {
artifact.AdditionLinks = make(map[string]*AdditionLink)
}
projectName, repo := utils.ParseRepository(artifact.RepositoryName)
href := fmt.Sprintf("/api/%s/projects/%s/repositories/%s/artifacts/%s/additions/%s", version, projectName, repo, artifact.Digest, addition)
artifact.AdditionLinks[addition] = &AdditionLink{HREF: href, Absolute: false}
}
// Tag is the overall view of tag
type Tag struct {
tag.Tag

View File

@ -24,6 +24,7 @@ import (
"github.com/goharbor/harbor/src/common/rbac"
"github.com/goharbor/harbor/src/common/utils/log"
"github.com/goharbor/harbor/src/core/config"
ierror "github.com/goharbor/harbor/src/internal/error"
"github.com/goharbor/harbor/src/jobservice/job"
"github.com/goharbor/harbor/src/jobservice/logger"
"github.com/goharbor/harbor/src/pkg/robot"
@ -261,7 +262,7 @@ func (bc *basicController) GetReport(artifact *v1.Artifact, mimeTypes []string)
}
if r == nil {
return nil, errs.WithCode(errs.PreconditionFailed, errs.Errorf("no scanner registration configured for project: %d", artifact.NamespaceID))
return nil, ierror.NotFoundError(nil).WithMessage("no scanner registration configured for project: %d", artifact.NamespaceID)
}
return bc.manager.GetBy(artifact.Digest, r.UUID, mimes)

View File

@ -40,6 +40,8 @@ type Artifact struct {
ExtraAttrs map[string]interface{} `json:"extra_attrs"` // only contains the simple attributes specific for the different artifact type, most of them should come from the config layer
Annotations map[string]string `json:"annotations"`
References []*Reference `json:"references"` // child artifacts referenced by the parent artifact if the artifact is an index
RepositoryName string `json:"-"` // repository name, eg: library/photon
}
// From converts the database level artifact to the business level object

View File

@ -17,22 +17,29 @@ package handler
import (
"context"
"fmt"
"net/http"
"strings"
"time"
"github.com/docker/distribution/reference"
"github.com/go-openapi/runtime"
"github.com/go-openapi/runtime/middleware"
"github.com/goharbor/harbor/src/api/artifact"
"github.com/goharbor/harbor/src/api/artifact/abstractor/resolver"
"github.com/goharbor/harbor/src/api/repository"
"github.com/goharbor/harbor/src/common/rbac"
"github.com/goharbor/harbor/src/common/utils"
ierror "github.com/goharbor/harbor/src/internal/error"
"github.com/goharbor/harbor/src/pkg/project"
"github.com/goharbor/harbor/src/pkg/q"
"github.com/goharbor/harbor/src/server/v2.0/handler/assembler"
"github.com/goharbor/harbor/src/server/v2.0/handler/model"
operation "github.com/goharbor/harbor/src/server/v2.0/restapi/operations/artifact"
"github.com/opencontainers/go-digest"
"net/http"
"strings"
"time"
)
const (
vulnerabilitiesAddition = "vulnerabilities"
)
func newArtifactAPI() *artifactAPI {
@ -95,10 +102,11 @@ func (a *artifactAPI) ListArtifacts(ctx context.Context, params operation.ListAr
for _, art := range arts {
artifact := &model.Artifact{}
artifact.Artifact = *art
a.assembleArtifact(ctx, artifact, params.WithScanOverview)
artifacts = append(artifacts, artifact)
}
assembler.NewVulAssembler(boolValue(params.WithScanOverview)).WithArtifacts(artifacts...).Assemble(ctx)
// TODO add link header
return operation.NewListArtifactsOK().WithXTotalCount(total).WithLink("").WithPayload(artifacts)
}
@ -118,7 +126,9 @@ func (a *artifactAPI) GetArtifact(ctx context.Context, params operation.GetArtif
}
art := &model.Artifact{}
art.Artifact = *artifact
a.assembleArtifact(ctx, art, params.WithScanOverview)
assembler.NewVulAssembler(boolValue(params.WithScanOverview)).WithArtifacts(art).Assemble(ctx)
return operation.NewGetArtifactOK().WithPayload(art)
}
@ -243,14 +253,23 @@ func (a *artifactAPI) GetAddition(ctx context.Context, params operation.GetAddit
if err := a.RequireProjectAccess(ctx, params.ProjectName, rbac.ActionRead, rbac.ResourceArtifactAddition); err != nil {
return a.SendError(ctx, err)
}
artifact, err := a.artCtl.GetByReference(ctx, fmt.Sprintf("%s/%s", params.ProjectName, params.RepositoryName), params.Reference, nil)
if err != nil {
return a.SendError(ctx, err)
}
addition, err := a.artCtl.GetAddition(ctx, artifact.ID, strings.ToUpper(params.Addition))
var addition *resolver.Addition
if params.Addition == vulnerabilitiesAddition {
addition, err = resolveVulnerabilitiesAddition(ctx, artifact)
} else {
addition, err = a.artCtl.GetAddition(ctx, artifact.ID, strings.ToUpper(params.Addition))
}
if err != nil {
return a.SendError(ctx, err)
}
return middleware.ResponderFunc(func(w http.ResponseWriter, p runtime.Producer) {
w.Header().Set("Content-Type", addition.ContentType)
w.Write(addition.Content)
@ -285,31 +304,22 @@ func (a *artifactAPI) RemoveLabel(ctx context.Context, params operation.RemoveLa
return operation.NewRemoveLabelOK()
}
func (a *artifactAPI) assembleArtifact(ctx context.Context, artifact *model.Artifact, withScanOverview *bool) {
if withScanOverview != nil && *withScanOverview {
// TODO populate scan result
}
// TODO populate vulnerability link
}
func option(withTag, withImmutableStatus, withLabel, withSignature *bool) *artifact.Option {
option := &artifact.Option{
WithTag: true, // return the tag by default
WithTag: true, // return the tag by default
WithLabel: boolValue(withLabel),
}
if withTag != nil {
option.WithTag = *(withTag)
}
if option.WithTag {
option.TagOption = &artifact.TagOption{}
if withImmutableStatus != nil {
option.TagOption.WithImmutableStatus = *(withImmutableStatus)
}
if withSignature != nil {
option.TagOption.WithSignature = *withSignature
option.TagOption = &artifact.TagOption{
WithImmutableStatus: boolValue(withImmutableStatus),
WithSignature: boolValue(withSignature),
}
}
if withLabel != nil {
option.WithLabel = *(withLabel)
}
return option
}

View File

@ -0,0 +1,107 @@
// 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 assembler
import (
"context"
"github.com/goharbor/harbor/src/api/scan"
"github.com/goharbor/harbor/src/api/scanner"
"github.com/goharbor/harbor/src/common/utils/log"
"github.com/goharbor/harbor/src/internal"
v1 "github.com/goharbor/harbor/src/pkg/scan/rest/v1"
"github.com/goharbor/harbor/src/server/v2.0/handler/model"
)
const (
vulnerabilitiesAddition = "vulnerabilities"
)
// NewVulAssembler returns vul assembler
func NewVulAssembler(withScanOverview bool) *VulAssembler {
return &VulAssembler{
withScanOverview: withScanOverview,
scanCtl: scan.DefaultController,
scannerCtl: scanner.DefaultController,
scanners: map[int64]bool{},
}
}
// VulAssembler vul assembler
type VulAssembler struct {
artifacts []*model.Artifact
scanCtl scan.Controller
scannerCtl scanner.Controller
scanners map[int64]bool
withScanOverview bool
}
func (assembler *VulAssembler) hasScanner(ctx context.Context, projectID int64) bool {
value, ok := assembler.scanners[projectID]
if !ok {
scanner, err := assembler.scannerCtl.GetRegistrationByProject(projectID)
if err != nil {
log.Warningf("get scanner for project %d failed, error: %v", projectID, err)
return false
}
value = scanner != nil
assembler.scanners[projectID] = value
}
return value
}
// WithArtifacts set artifacts for the assembler
func (assembler *VulAssembler) WithArtifacts(artifacts ...*model.Artifact) *VulAssembler {
assembler.artifacts = artifacts
return assembler
}
// Assemble assemble vul for the artifacts
func (assembler *VulAssembler) Assemble(ctx context.Context) error {
version := internal.GetAPIVersion(ctx)
for _, artifact := range assembler.artifacts {
hasScanner := assembler.hasScanner(ctx, artifact.ProjectID)
if !hasScanner {
continue
}
artifact.SetAdditionLink(vulnerabilitiesAddition, version)
if assembler.withScanOverview {
art := &v1.Artifact{
NamespaceID: artifact.ProjectID,
Repository: artifact.RepositoryName,
Digest: artifact.Digest,
MimeType: artifact.ManifestMediaType,
}
overview, err := assembler.scanCtl.GetSummary(art, []string{v1.MimeTypeNativeReport})
if err != nil {
log.Warningf("get scan summary of artifact %s failed, error:%v", artifact.Digest, err)
} else if len(overview) > 0 {
artifact.ScanOverview = overview
}
}
}
return nil
}

View File

@ -0,0 +1,107 @@
// 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 assembler
import (
"context"
"fmt"
"testing"
models "github.com/goharbor/harbor/src/pkg/scan/dao/scanner"
"github.com/goharbor/harbor/src/server/v2.0/handler/model"
"github.com/goharbor/harbor/src/testing/api/scan"
"github.com/goharbor/harbor/src/testing/api/scanner"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/suite"
)
type VulAssemblerTestSuite struct {
suite.Suite
}
func (suite *VulAssemblerTestSuite) newVulAssembler(withScanOverview bool) (*VulAssembler, *scan.Controller, *scanner.Controller) {
vulAssembler := NewVulAssembler(withScanOverview)
scanCtl := &scan.Controller{}
scannerCtl := &scanner.Controller{}
vulAssembler.scanCtl = scanCtl
vulAssembler.scannerCtl = scannerCtl
return vulAssembler, scanCtl, scannerCtl
}
func (suite *VulAssemblerTestSuite) TestNotHasScanner() {
{
assembler, _, scannerCtl := suite.newVulAssembler(true)
scannerCtl.On("GetRegistrationByProject", mock.AnythingOfType("int64")).Return(nil, nil)
var artifact model.Artifact
suite.Nil(assembler.WithArtifacts(&artifact).Assemble(context.TODO()))
suite.Len(artifact.AdditionLinks, 0)
}
{
assembler, _, scannerCtl := suite.newVulAssembler(true)
scannerCtl.On("GetRegistrationByProject", mock.AnythingOfType("int64")).Return(nil, fmt.Errorf("error"))
var artifact model.Artifact
suite.Nil(assembler.WithArtifacts(&artifact).Assemble(context.TODO()))
suite.Len(artifact.AdditionLinks, 0)
}
}
func (suite *VulAssemblerTestSuite) TestHasScanner() {
{
assembler, scanCtl, scannerCtl := suite.newVulAssembler(true)
scannerCtl.On("GetRegistrationByProject", mock.AnythingOfType("int64")).Return(&models.Registration{}, nil)
summary := map[string]interface{}{"key": "value"}
scanCtl.On("GetSummary", mock.AnythingOfType("*v1.Artifact"), mock.AnythingOfType("[]string")).Return(summary, nil)
var artifact model.Artifact
suite.Nil(assembler.WithArtifacts(&artifact).Assemble(context.TODO()))
suite.Len(artifact.AdditionLinks, 1)
suite.Equal(artifact.ScanOverview, summary)
}
{
assembler, scanCtl, scannerCtl := suite.newVulAssembler(false)
scannerCtl.On("GetRegistrationByProject", mock.AnythingOfType("int64")).Return(&models.Registration{}, nil)
summary := map[string]interface{}{"key": "value"}
scanCtl.On("GetSummary", mock.AnythingOfType("*v1.Artifact"), mock.AnythingOfType("[]string")).Return(summary, nil)
var artifact model.Artifact
suite.Nil(assembler.WithArtifacts(&artifact).Assemble(context.TODO()))
suite.Len(artifact.AdditionLinks, 1)
suite.Nil(artifact.ScanOverview)
}
{
assembler, scanCtl, scannerCtl := suite.newVulAssembler(true)
scannerCtl.On("GetRegistrationByProject", mock.AnythingOfType("int64")).Return(&models.Registration{}, nil)
scanCtl.On("GetSummary", mock.AnythingOfType("*v1.Artifact"), mock.AnythingOfType("[]string")).Return(nil, fmt.Errorf("error"))
var artifact model.Artifact
suite.Nil(assembler.WithArtifacts(&artifact).Assemble(context.TODO()))
suite.Len(artifact.AdditionLinks, 1)
suite.Nil(artifact.ScanOverview)
}
}
func TestVulAssemblerTestSuite(t *testing.T) {
suite.Run(t, &VulAssemblerTestSuite{})
}

View File

@ -19,5 +19,5 @@ import "github.com/goharbor/harbor/src/api/artifact"
// Artifact model
type Artifact struct {
artifact.Artifact
// TODO add other properties: scan result
ScanOverview map[string]interface{} `json:"scan_overview"`
}

View File

@ -0,0 +1,70 @@
// 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 handler
import (
"context"
"encoding/json"
"github.com/goharbor/harbor/src/api/artifact"
"github.com/goharbor/harbor/src/api/artifact/abstractor/resolver"
"github.com/goharbor/harbor/src/api/scan"
"github.com/goharbor/harbor/src/pkg/scan/report"
v1 "github.com/goharbor/harbor/src/pkg/scan/rest/v1"
)
func boolValue(v *bool) bool {
if v != nil {
return *v
}
return false
}
func resolveVulnerabilitiesAddition(ctx context.Context, artifact *artifact.Artifact) (*resolver.Addition, error) {
art := &v1.Artifact{
NamespaceID: artifact.ProjectID,
Repository: artifact.RepositoryName,
Digest: artifact.Digest,
MimeType: artifact.ManifestMediaType,
}
reports, err := scan.DefaultController.GetReport(art, []string{v1.MimeTypeNativeReport})
if err != nil {
return nil, err
}
vulnerabilities := make(map[string]interface{})
for _, rp := range reports {
// Resolve scan report data only when it is ready
if len(rp.Report) == 0 {
continue
}
vrp, err := report.ResolveData(rp.MimeType, []byte(rp.Report))
if err != nil {
return nil, err
}
vulnerabilities[rp.MimeType] = vrp
}
content, _ := json.Marshal(vulnerabilities)
return &resolver.Addition{
Content: content,
ContentType: "application/json",
}, nil
}

18
src/testing/api/api.go Normal file
View File

@ -0,0 +1,18 @@
// 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 api
//go:generate mockery -case snake -dir ../../api/scan -name Controller -output ./scan -outpkg scan
//go:generate mockery -case snake -dir ../../api/scanner -name Controller -output ./scanner -outpkg scanner

View File

@ -0,0 +1,177 @@
// Code generated by mockery v1.0.0. DO NOT EDIT.
package scan
import (
all "github.com/goharbor/harbor/src/pkg/scan/all"
daoscan "github.com/goharbor/harbor/src/pkg/scan/dao/scan"
job "github.com/goharbor/harbor/src/jobservice/job"
mock "github.com/stretchr/testify/mock"
report "github.com/goharbor/harbor/src/pkg/scan/report"
scan "github.com/goharbor/harbor/src/api/scan"
v1 "github.com/goharbor/harbor/src/pkg/scan/rest/v1"
)
// Controller is an autogenerated mock type for the Controller type
type Controller struct {
mock.Mock
}
// DeleteReports provides a mock function with given fields: digests
func (_m *Controller) DeleteReports(digests ...string) error {
_va := make([]interface{}, len(digests))
for _i := range digests {
_va[_i] = digests[_i]
}
var _ca []interface{}
_ca = append(_ca, _va...)
ret := _m.Called(_ca...)
var r0 error
if rf, ok := ret.Get(0).(func(...string) error); ok {
r0 = rf(digests...)
} else {
r0 = ret.Error(0)
}
return r0
}
// GetReport provides a mock function with given fields: artifact, mimeTypes
func (_m *Controller) GetReport(artifact *v1.Artifact, mimeTypes []string) ([]*daoscan.Report, error) {
ret := _m.Called(artifact, mimeTypes)
var r0 []*daoscan.Report
if rf, ok := ret.Get(0).(func(*v1.Artifact, []string) []*daoscan.Report); ok {
r0 = rf(artifact, mimeTypes)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]*daoscan.Report)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(*v1.Artifact, []string) error); ok {
r1 = rf(artifact, mimeTypes)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// GetScanLog provides a mock function with given fields: uuid
func (_m *Controller) GetScanLog(uuid string) ([]byte, error) {
ret := _m.Called(uuid)
var r0 []byte
if rf, ok := ret.Get(0).(func(string) []byte); ok {
r0 = rf(uuid)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]byte)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string) error); ok {
r1 = rf(uuid)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// GetStats provides a mock function with given fields: requester
func (_m *Controller) GetStats(requester string) (*all.Stats, error) {
ret := _m.Called(requester)
var r0 *all.Stats
if rf, ok := ret.Get(0).(func(string) *all.Stats); ok {
r0 = rf(requester)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*all.Stats)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string) error); ok {
r1 = rf(requester)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// GetSummary provides a mock function with given fields: artifact, mimeTypes, options
func (_m *Controller) GetSummary(artifact *v1.Artifact, mimeTypes []string, options ...report.Option) (map[string]interface{}, error) {
_va := make([]interface{}, len(options))
for _i := range options {
_va[_i] = options[_i]
}
var _ca []interface{}
_ca = append(_ca, artifact, mimeTypes)
_ca = append(_ca, _va...)
ret := _m.Called(_ca...)
var r0 map[string]interface{}
if rf, ok := ret.Get(0).(func(*v1.Artifact, []string, ...report.Option) map[string]interface{}); ok {
r0 = rf(artifact, mimeTypes, options...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(map[string]interface{})
}
}
var r1 error
if rf, ok := ret.Get(1).(func(*v1.Artifact, []string, ...report.Option) error); ok {
r1 = rf(artifact, mimeTypes, options...)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// HandleJobHooks provides a mock function with given fields: trackID, change
func (_m *Controller) HandleJobHooks(trackID string, change *job.StatusChange) error {
ret := _m.Called(trackID, change)
var r0 error
if rf, ok := ret.Get(0).(func(string, *job.StatusChange) error); ok {
r0 = rf(trackID, change)
} else {
r0 = ret.Error(0)
}
return r0
}
// Scan provides a mock function with given fields: artifact, options
func (_m *Controller) Scan(artifact *v1.Artifact, options ...scan.Option) error {
_va := make([]interface{}, len(options))
for _i := range options {
_va[_i] = options[_i]
}
var _ca []interface{}
_ca = append(_ca, artifact)
_ca = append(_ca, _va...)
ret := _m.Called(_ca...)
var r0 error
if rf, ok := ret.Get(0).(func(*v1.Artifact, ...scan.Option) error); ok {
r0 = rf(artifact, options...)
} else {
r0 = ret.Error(0)
}
return r0
}

View File

@ -0,0 +1,232 @@
// Code generated by mockery v1.0.0. DO NOT EDIT.
package scanner
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"
v1 "github.com/goharbor/harbor/src/pkg/scan/rest/v1"
)
// Controller is an autogenerated mock type for the Controller type
type Controller struct {
mock.Mock
}
// CreateRegistration provides a mock function with given fields: registration
func (_m *Controller) CreateRegistration(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
}
// DeleteRegistration provides a mock function with given fields: registrationUUID
func (_m *Controller) DeleteRegistration(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
}
// GetMetadata provides a mock function with given fields: registrationUUID
func (_m *Controller) GetMetadata(registrationUUID string) (*v1.ScannerAdapterMetadata, error) {
ret := _m.Called(registrationUUID)
var r0 *v1.ScannerAdapterMetadata
if rf, ok := ret.Get(0).(func(string) *v1.ScannerAdapterMetadata); ok {
r0 = rf(registrationUUID)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*v1.ScannerAdapterMetadata)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string) error); ok {
r1 = rf(registrationUUID)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// GetRegistration provides a mock function with given fields: registrationUUID
func (_m *Controller) GetRegistration(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
}
// GetRegistrationByProject provides a mock function with given fields: projectID
func (_m *Controller) GetRegistrationByProject(projectID int64) (*scanner.Registration, error) {
ret := _m.Called(projectID)
var r0 *scanner.Registration
if rf, ok := ret.Get(0).(func(int64) *scanner.Registration); ok {
r0 = rf(projectID)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*scanner.Registration)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(int64) error); ok {
r1 = rf(projectID)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// ListRegistrations provides a mock function with given fields: query
func (_m *Controller) ListRegistrations(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
}
// Ping provides a mock function with given fields: registration
func (_m *Controller) Ping(registration *scanner.Registration) (*v1.ScannerAdapterMetadata, error) {
ret := _m.Called(registration)
var r0 *v1.ScannerAdapterMetadata
if rf, ok := ret.Get(0).(func(*scanner.Registration) *v1.ScannerAdapterMetadata); ok {
r0 = rf(registration)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*v1.ScannerAdapterMetadata)
}
}
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
}
// RegistrationExists provides a mock function with given fields: registrationUUID
func (_m *Controller) RegistrationExists(registrationUUID string) bool {
ret := _m.Called(registrationUUID)
var r0 bool
if rf, ok := ret.Get(0).(func(string) bool); ok {
r0 = rf(registrationUUID)
} else {
r0 = ret.Get(0).(bool)
}
return r0
}
// SetDefaultRegistration provides a mock function with given fields: registrationUUID
func (_m *Controller) SetDefaultRegistration(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
}
// SetRegistrationByProject provides a mock function with given fields: projectID, scannerID
func (_m *Controller) SetRegistrationByProject(projectID int64, scannerID string) error {
ret := _m.Called(projectID, scannerID)
var r0 error
if rf, ok := ret.Get(0).(func(int64, string) error); ok {
r0 = rf(projectID, scannerID)
} else {
r0 = ret.Error(0)
}
return r0
}
// UpdateRegistration provides a mock function with given fields: registration
func (_m *Controller) UpdateRegistration(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
}