mirror of
https://github.com/goharbor/harbor.git
synced 2025-02-20 22:02:32 +01:00
fix: supply the latest tag of artifact to scan request
Closes #14416 #14299 Signed-off-by: He Weiwei <hweiwei@vmware.com>
This commit is contained in:
parent
1f9ab2b735
commit
1b955cd28e
@ -91,7 +91,7 @@ func (a *Handler) addPullCount(ctx context.Context, event *event.ArtifactEvent)
|
|||||||
|
|
||||||
func (a *Handler) onPush(ctx context.Context, event *event.ArtifactEvent) error {
|
func (a *Handler) onPush(ctx context.Context, event *event.ArtifactEvent) error {
|
||||||
go func() {
|
go func() {
|
||||||
if err := autoScan(ctx, &artifact.Artifact{Artifact: *event.Artifact}); err != nil {
|
if err := autoScan(ctx, &artifact.Artifact{Artifact: *event.Artifact}, event.Tags...); err != nil {
|
||||||
log.Errorf("scan artifact %s@%s failed, error: %v", event.Artifact.RepositoryName, event.Artifact.Digest, err)
|
log.Errorf("scan artifact %s@%s failed, error: %v", event.Artifact.RepositoryName, event.Artifact.Digest, err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
@ -24,7 +24,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// autoScan scan artifact when the project of the artifact enable auto scan
|
// autoScan scan artifact when the project of the artifact enable auto scan
|
||||||
func autoScan(ctx context.Context, a *artifact.Artifact) error {
|
func autoScan(ctx context.Context, a *artifact.Artifact, tags ...string) error {
|
||||||
proj, err := project.Ctl.Get(ctx, a.ProjectID)
|
proj, err := project.Ctl.Get(ctx, a.ProjectID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -35,6 +35,11 @@ func autoScan(ctx context.Context, a *artifact.Artifact) error {
|
|||||||
|
|
||||||
// transaction here to work with the image index
|
// transaction here to work with the image index
|
||||||
return orm.WithTransaction(func(ctx context.Context) error {
|
return orm.WithTransaction(func(ctx context.Context) error {
|
||||||
return scan.DefaultController.Scan(ctx, a)
|
options := []scan.Option{}
|
||||||
|
if len(tags) > 0 {
|
||||||
|
options = append(options, scan.WithTag(tags[0]))
|
||||||
|
}
|
||||||
|
|
||||||
|
return scan.DefaultController.Scan(ctx, a, options...)
|
||||||
})(ctx)
|
})(ctx)
|
||||||
}
|
}
|
||||||
|
@ -18,10 +18,12 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/goharbor/harbor/src/controller/artifact"
|
"github.com/goharbor/harbor/src/controller/artifact"
|
||||||
|
"github.com/goharbor/harbor/src/controller/event"
|
||||||
"github.com/goharbor/harbor/src/controller/project"
|
"github.com/goharbor/harbor/src/controller/project"
|
||||||
"github.com/goharbor/harbor/src/controller/scan"
|
"github.com/goharbor/harbor/src/controller/scan"
|
||||||
"github.com/goharbor/harbor/src/lib/errors"
|
"github.com/goharbor/harbor/src/lib/errors"
|
||||||
"github.com/goharbor/harbor/src/lib/orm"
|
"github.com/goharbor/harbor/src/lib/orm"
|
||||||
|
pkg "github.com/goharbor/harbor/src/pkg/artifact"
|
||||||
proModels "github.com/goharbor/harbor/src/pkg/project/models"
|
proModels "github.com/goharbor/harbor/src/pkg/project/models"
|
||||||
projecttesting "github.com/goharbor/harbor/src/testing/controller/project"
|
projecttesting "github.com/goharbor/harbor/src/testing/controller/project"
|
||||||
scantesting "github.com/goharbor/harbor/src/testing/controller/scan"
|
scantesting "github.com/goharbor/harbor/src/testing/controller/scan"
|
||||||
@ -107,6 +109,23 @@ func (suite *AutoScanTestSuite) TestAutoScanFailed() {
|
|||||||
suite.Error(autoScan(ctx, art))
|
suite.Error(autoScan(ctx, art))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (suite *AutoScanTestSuite) TestWithArtifactEvent() {
|
||||||
|
mock.OnAnything(suite.projectController, "Get").Return(&proModels.Project{
|
||||||
|
Metadata: map[string]string{
|
||||||
|
proModels.ProMetaAutoScan: "true",
|
||||||
|
},
|
||||||
|
}, nil)
|
||||||
|
|
||||||
|
mock.OnAnything(suite.scanController, "Scan").Return(nil)
|
||||||
|
|
||||||
|
event := &event.ArtifactEvent{
|
||||||
|
Artifact: &pkg.Artifact{},
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := orm.NewContext(nil, &ormtesting.FakeOrmer{})
|
||||||
|
suite.Nil(autoScan(ctx, &artifact.Artifact{Artifact: *event.Artifact}, event.Tags...))
|
||||||
|
}
|
||||||
|
|
||||||
func TestAutoScanTestSuite(t *testing.T) {
|
func TestAutoScanTestSuite(t *testing.T) {
|
||||||
suite.Run(t, &AutoScanTestSuite{})
|
suite.Run(t, &AutoScanTestSuite{})
|
||||||
}
|
}
|
||||||
|
@ -110,9 +110,9 @@ func constructScanImagePayload(event *event.ScanImageEvent, project *proModels.P
|
|||||||
Operator: event.Operator,
|
Operator: event.Operator,
|
||||||
}
|
}
|
||||||
|
|
||||||
reference := event.Artifact.Digest
|
reference := event.Artifact.Tag
|
||||||
if reference == "" {
|
if reference == "" {
|
||||||
reference = event.Artifact.Tag
|
reference = event.Artifact.Digest
|
||||||
}
|
}
|
||||||
|
|
||||||
resURL, err := util.BuildImageResourceURL(event.Artifact.Repository, reference)
|
resURL, err := util.BuildImageResourceURL(event.Artifact.Repository, reference)
|
||||||
|
@ -26,6 +26,7 @@ import (
|
|||||||
ar "github.com/goharbor/harbor/src/controller/artifact"
|
ar "github.com/goharbor/harbor/src/controller/artifact"
|
||||||
"github.com/goharbor/harbor/src/controller/robot"
|
"github.com/goharbor/harbor/src/controller/robot"
|
||||||
sc "github.com/goharbor/harbor/src/controller/scanner"
|
sc "github.com/goharbor/harbor/src/controller/scanner"
|
||||||
|
"github.com/goharbor/harbor/src/controller/tag"
|
||||||
"github.com/goharbor/harbor/src/jobservice/job"
|
"github.com/goharbor/harbor/src/jobservice/job"
|
||||||
"github.com/goharbor/harbor/src/lib"
|
"github.com/goharbor/harbor/src/lib"
|
||||||
"github.com/goharbor/harbor/src/lib/config"
|
"github.com/goharbor/harbor/src/lib/config"
|
||||||
@ -61,6 +62,7 @@ const (
|
|||||||
registrationKey = "registration"
|
registrationKey = "registration"
|
||||||
|
|
||||||
artifactIDKey = "artifact_id"
|
artifactIDKey = "artifact_id"
|
||||||
|
artifactTagKey = "artifact_tag"
|
||||||
reportUUIDsKey = "report_uuids"
|
reportUUIDsKey = "report_uuids"
|
||||||
robotIDKey = "robot_id"
|
robotIDKey = "robot_id"
|
||||||
)
|
)
|
||||||
@ -77,6 +79,15 @@ type uuidGenerator func() (string, error)
|
|||||||
// utility methods.
|
// utility methods.
|
||||||
type configGetter func(cfg string) (string, error)
|
type configGetter func(cfg string) (string, error)
|
||||||
|
|
||||||
|
// launchScanJobParam is a param to launch scan job.
|
||||||
|
type launchScanJobParam struct {
|
||||||
|
ExecutionID int64
|
||||||
|
Registration *scanner.Registration
|
||||||
|
Artifact *ar.Artifact
|
||||||
|
Tag string
|
||||||
|
Reports []*scan.Report
|
||||||
|
}
|
||||||
|
|
||||||
// basicController is default implementation of api.Controller interface
|
// basicController is default implementation of api.Controller interface
|
||||||
type basicController struct {
|
type basicController struct {
|
||||||
// Manage the scan report records
|
// Manage the scan report records
|
||||||
@ -87,6 +98,8 @@ type basicController struct {
|
|||||||
sc sc.Controller
|
sc sc.Controller
|
||||||
// Robot account controller
|
// Robot account controller
|
||||||
rc robot.Controller
|
rc robot.Controller
|
||||||
|
// Tag controller
|
||||||
|
tagCtl tag.Controller
|
||||||
// UUID generator
|
// UUID generator
|
||||||
uuid uuidGenerator
|
uuid uuidGenerator
|
||||||
// Configuration getter func
|
// Configuration getter func
|
||||||
@ -112,6 +125,8 @@ func NewController() Controller {
|
|||||||
sc: sc.DefaultController,
|
sc: sc.DefaultController,
|
||||||
// Refer to the default robot account controller
|
// Refer to the default robot account controller
|
||||||
rc: robot.Ctl,
|
rc: robot.Ctl,
|
||||||
|
// Refer to the default tag controller
|
||||||
|
tagCtl: tag.Ctl,
|
||||||
// Generate UUID with uuid lib
|
// Generate UUID with uuid lib
|
||||||
uuid: func() (string, error) {
|
uuid: func() (string, error) {
|
||||||
aUUID, err := uuid.NewUUID()
|
aUUID, err := uuid.NewUUID()
|
||||||
@ -210,14 +225,16 @@ func (bc *basicController) Scan(ctx context.Context, artifact *ar.Artifact, opti
|
|||||||
return errors.BadRequestError(nil).WithMessage("the configured scanner %s does not support scanning artifact with mime type %s", r.Name, artifact.ManifestMediaType)
|
return errors.BadRequestError(nil).WithMessage("the configured scanner %s does not support scanning artifact with mime type %s", r.Name, artifact.ManifestMediaType)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Param struct {
|
// Parse options
|
||||||
Artifact *ar.Artifact
|
opts, err := parseOptions(options...)
|
||||||
Reports []*scan.Report
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "scan controller: scan")
|
||||||
}
|
}
|
||||||
|
|
||||||
params := []*Param{}
|
var (
|
||||||
|
errs []error
|
||||||
var errs []error
|
launchScanJobParams []*launchScanJobParam
|
||||||
|
)
|
||||||
for _, art := range artifacts {
|
for _, art := range artifacts {
|
||||||
reports, err := bc.makeReportPlaceholder(ctx, r, art)
|
reports, err := bc.makeReportPlaceholder(ctx, r, art)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -228,8 +245,27 @@ func (bc *basicController) Scan(ctx context.Context, artifact *ar.Artifact, opti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var tag string
|
||||||
|
if art.Digest == artifact.Digest {
|
||||||
|
tag = opts.Tag
|
||||||
|
}
|
||||||
|
|
||||||
|
if tag == "" {
|
||||||
|
latestTag, err := bc.getLatestTagOfArtifact(ctx, art.ID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = latestTag
|
||||||
|
}
|
||||||
|
|
||||||
if len(reports) > 0 {
|
if len(reports) > 0 {
|
||||||
params = append(params, &Param{Artifact: art, Reports: reports})
|
launchScanJobParams = append(launchScanJobParams, &launchScanJobParam{
|
||||||
|
Registration: r,
|
||||||
|
Artifact: art,
|
||||||
|
Tag: tag,
|
||||||
|
Reports: reports,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,12 +274,6 @@ func (bc *basicController) Scan(ctx context.Context, artifact *ar.Artifact, opti
|
|||||||
return errs[0]
|
return errs[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse options
|
|
||||||
opts, err := parseOptions(options...)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "scan controller: scan")
|
|
||||||
}
|
|
||||||
|
|
||||||
if opts.ExecutionID == 0 {
|
if opts.ExecutionID == 0 {
|
||||||
extraAttrs := map[string]interface{}{
|
extraAttrs := map[string]interface{}{
|
||||||
artfiactKey: map[string]interface{}{
|
artfiactKey: map[string]interface{}{
|
||||||
@ -266,15 +296,17 @@ func (bc *basicController) Scan(ctx context.Context, artifact *ar.Artifact, opti
|
|||||||
}
|
}
|
||||||
|
|
||||||
errs = errs[:0]
|
errs = errs[:0]
|
||||||
for _, param := range params {
|
for _, launchScanJobParam := range launchScanJobParams {
|
||||||
if err := bc.launchScanJob(ctx, opts.ExecutionID, param.Artifact, r, param.Reports); err != nil {
|
launchScanJobParam.ExecutionID = opts.ExecutionID
|
||||||
|
|
||||||
|
if err := bc.launchScanJob(ctx, launchScanJobParam); err != nil {
|
||||||
log.G(ctx).Warningf("scan artifact %s@%s failed, error: %v", artifact.RepositoryName, artifact.Digest, err)
|
log.G(ctx).Warningf("scan artifact %s@%s failed, error: %v", artifact.RepositoryName, artifact.Digest, err)
|
||||||
errs = append(errs, err)
|
errs = append(errs, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// all scanning of the artifacts failed
|
// all scanning of the artifacts failed
|
||||||
if len(errs) == len(params) {
|
if len(errs) == len(launchScanJobParams) {
|
||||||
return fmt.Errorf("scan artifact %s@%s failed", artifact.RepositoryName, artifact.Digest)
|
return fmt.Errorf("scan artifact %s@%s failed", artifact.RepositoryName, artifact.Digest)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -795,14 +827,14 @@ func (bc *basicController) makeRobotAccount(ctx context.Context, projectID int64
|
|||||||
}
|
}
|
||||||
|
|
||||||
// launchScanJob launches a job to run scan
|
// launchScanJob launches a job to run scan
|
||||||
func (bc *basicController) launchScanJob(ctx context.Context, executionID int64, artifact *ar.Artifact, registration *scanner.Registration, reports []*scan.Report) error {
|
func (bc *basicController) launchScanJob(ctx context.Context, param *launchScanJobParam) error {
|
||||||
// don't launch scan job for the artifact which is not supported by the scanner
|
// don't launch scan job for the artifact which is not supported by the scanner
|
||||||
if !hasCapability(registration, artifact) {
|
if !hasCapability(param.Registration, param.Artifact) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var ck string
|
var ck string
|
||||||
if registration.UseInternalAddr {
|
if param.Registration.UseInternalAddr {
|
||||||
ck = configCoreInternalAddr
|
ck = configCoreInternalAddr
|
||||||
} else {
|
} else {
|
||||||
ck = configRegistryEndpoint
|
ck = configRegistryEndpoint
|
||||||
@ -813,7 +845,7 @@ func (bc *basicController) launchScanJob(ctx context.Context, executionID int64,
|
|||||||
return errors.Wrap(err, "scan controller: launch scan job")
|
return errors.Wrap(err, "scan controller: launch scan job")
|
||||||
}
|
}
|
||||||
|
|
||||||
robot, err := bc.makeRobotAccount(ctx, artifact.ProjectID, artifact.RepositoryName, registration)
|
robot, err := bc.makeRobotAccount(ctx, param.Artifact.ProjectID, param.Artifact.RepositoryName, param.Registration)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "scan controller: launch scan job")
|
return errors.Wrap(err, "scan controller: launch scan job")
|
||||||
}
|
}
|
||||||
@ -824,14 +856,15 @@ func (bc *basicController) launchScanJob(ctx context.Context, executionID int64,
|
|||||||
URL: registryAddr,
|
URL: registryAddr,
|
||||||
},
|
},
|
||||||
Artifact: &v1.Artifact{
|
Artifact: &v1.Artifact{
|
||||||
NamespaceID: artifact.ProjectID,
|
NamespaceID: param.Artifact.ProjectID,
|
||||||
Repository: artifact.RepositoryName,
|
Repository: param.Artifact.RepositoryName,
|
||||||
Digest: artifact.Digest,
|
Digest: param.Artifact.Digest,
|
||||||
MimeType: artifact.ManifestMediaType,
|
Tag: param.Tag,
|
||||||
|
MimeType: param.Artifact.ManifestMediaType,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
rJSON, err := registration.ToJSON()
|
rJSON, err := param.Registration.ToJSON()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "scan controller: launch scan job")
|
return errors.Wrap(err, "scan controller: launch scan job")
|
||||||
}
|
}
|
||||||
@ -846,16 +879,16 @@ func (bc *basicController) launchScanJob(ctx context.Context, executionID int64,
|
|||||||
return errors.Wrap(err, "launch scan job")
|
return errors.Wrap(err, "launch scan job")
|
||||||
}
|
}
|
||||||
|
|
||||||
mimes := make([]string, len(reports))
|
mimes := make([]string, len(param.Reports))
|
||||||
reportUUIDs := make([]string, len(reports))
|
reportUUIDs := make([]string, len(param.Reports))
|
||||||
for i, report := range reports {
|
for i, report := range param.Reports {
|
||||||
mimes[i] = report.MimeType
|
mimes[i] = report.MimeType
|
||||||
reportUUIDs[i] = report.UUID
|
reportUUIDs[i] = report.UUID
|
||||||
}
|
}
|
||||||
|
|
||||||
params := make(map[string]interface{})
|
params := make(map[string]interface{})
|
||||||
params[sca.JobParamRegistration] = rJSON
|
params[sca.JobParamRegistration] = rJSON
|
||||||
params[sca.JobParameterAuthType] = registration.GetRegistryAuthorizationType()
|
params[sca.JobParameterAuthType] = param.Registration.GetRegistryAuthorizationType()
|
||||||
params[sca.JobParameterRequest] = sJSON
|
params[sca.JobParameterRequest] = sJSON
|
||||||
params[sca.JobParameterMimes] = mimes
|
params[sca.JobParameterMimes] = mimes
|
||||||
params[sca.JobParameterRobot] = robotJSON
|
params[sca.JobParameterRobot] = robotJSON
|
||||||
@ -871,7 +904,8 @@ func (bc *basicController) launchScanJob(ctx context.Context, executionID int64,
|
|||||||
// keep the report uuids in array so that when ?| operator support by the FilterRaw method of beego's orm
|
// keep the report uuids in array so that when ?| operator support by the FilterRaw method of beego's orm
|
||||||
// we can list the tasks of the scan reports by one SQL
|
// we can list the tasks of the scan reports by one SQL
|
||||||
extraAttrs := map[string]interface{}{
|
extraAttrs := map[string]interface{}{
|
||||||
artifactIDKey: artifact.ID,
|
artifactIDKey: param.Artifact.ID,
|
||||||
|
artifactTagKey: param.Tag,
|
||||||
robotIDKey: robot.ID,
|
robotIDKey: robot.ID,
|
||||||
reportUUIDsKey: reportUUIDs,
|
reportUUIDsKey: reportUUIDs,
|
||||||
}
|
}
|
||||||
@ -885,7 +919,7 @@ func (bc *basicController) launchScanJob(ctx context.Context, executionID int64,
|
|||||||
extraAttrs["report:"+reportUUID] = "1"
|
extraAttrs["report:"+reportUUID] = "1"
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = bc.taskMgr.Create(ctx, executionID, j, extraAttrs)
|
_, err = bc.taskMgr.Create(ctx, param.ExecutionID, j, extraAttrs)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -983,6 +1017,20 @@ func (bc *basicController) assembleReports(ctx context.Context, reports ...*scan
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (bc *basicController) getLatestTagOfArtifact(ctx context.Context, artifactID int64) (string, error) {
|
||||||
|
query := q.New(q.KeyWords{"artifact_id": artifactID})
|
||||||
|
tags, err := bc.tagCtl.List(ctx, query.First(q.NewSort("push_time", true)), nil)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(tags) == 0 {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return tags[0].Name, nil
|
||||||
|
}
|
||||||
|
|
||||||
func getArtifactID(extraAttrs map[string]interface{}) int64 {
|
func getArtifactID(extraAttrs map[string]interface{}) int64 {
|
||||||
var artifactID float64
|
var artifactID float64
|
||||||
if extraAttrs != nil {
|
if extraAttrs != nil {
|
||||||
@ -994,6 +1042,17 @@ func getArtifactID(extraAttrs map[string]interface{}) int64 {
|
|||||||
return int64(artifactID)
|
return int64(artifactID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getArtifactTag(extraAttrs map[string]interface{}) string {
|
||||||
|
var tag string
|
||||||
|
if extraAttrs != nil {
|
||||||
|
if v, ok := extraAttrs[artifactTagKey]; ok {
|
||||||
|
tag, _ = v.(string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tag
|
||||||
|
}
|
||||||
|
|
||||||
func getReportUUIDs(extraAttrs map[string]interface{}) []string {
|
func getReportUUIDs(extraAttrs map[string]interface{}) []string {
|
||||||
var reportUUIDs []string
|
var reportUUIDs []string
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ import (
|
|||||||
artifacttesting "github.com/goharbor/harbor/src/testing/controller/artifact"
|
artifacttesting "github.com/goharbor/harbor/src/testing/controller/artifact"
|
||||||
robottesting "github.com/goharbor/harbor/src/testing/controller/robot"
|
robottesting "github.com/goharbor/harbor/src/testing/controller/robot"
|
||||||
scannertesting "github.com/goharbor/harbor/src/testing/controller/scanner"
|
scannertesting "github.com/goharbor/harbor/src/testing/controller/scanner"
|
||||||
|
tagtesting "github.com/goharbor/harbor/src/testing/controller/tag"
|
||||||
ormtesting "github.com/goharbor/harbor/src/testing/lib/orm"
|
ormtesting "github.com/goharbor/harbor/src/testing/lib/orm"
|
||||||
"github.com/goharbor/harbor/src/testing/mock"
|
"github.com/goharbor/harbor/src/testing/mock"
|
||||||
postprocessorstesting "github.com/goharbor/harbor/src/testing/pkg/scan/postprocessors"
|
postprocessorstesting "github.com/goharbor/harbor/src/testing/pkg/scan/postprocessors"
|
||||||
@ -59,6 +60,8 @@ type ControllerTestSuite struct {
|
|||||||
artifactCtl *artifacttesting.Controller
|
artifactCtl *artifacttesting.Controller
|
||||||
originalArtifactCtl artifact.Controller
|
originalArtifactCtl artifact.Controller
|
||||||
|
|
||||||
|
tagCtl *tagtesting.FakeController
|
||||||
|
|
||||||
registration *scanner.Registration
|
registration *scanner.Registration
|
||||||
artifact *artifact.Artifact
|
artifact *artifact.Artifact
|
||||||
rawReport string
|
rawReport string
|
||||||
@ -255,6 +258,9 @@ func (suite *ControllerTestSuite) SetupSuite() {
|
|||||||
|
|
||||||
suite.ar = &artifacttesting.Controller{}
|
suite.ar = &artifacttesting.Controller{}
|
||||||
|
|
||||||
|
suite.tagCtl = &tagtesting.FakeController{}
|
||||||
|
suite.tagCtl.On("List", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil)
|
||||||
|
|
||||||
suite.execMgr = &tasktesting.ExecutionManager{}
|
suite.execMgr = &tasktesting.ExecutionManager{}
|
||||||
|
|
||||||
suite.taskMgr = &tasktesting.Manager{}
|
suite.taskMgr = &tasktesting.Manager{}
|
||||||
@ -264,6 +270,7 @@ func (suite *ControllerTestSuite) SetupSuite() {
|
|||||||
ar: suite.ar,
|
ar: suite.ar,
|
||||||
sc: sc,
|
sc: sc,
|
||||||
rc: rc,
|
rc: rc,
|
||||||
|
tagCtl: suite.tagCtl,
|
||||||
uuid: func() (string, error) {
|
uuid: func() (string, error) {
|
||||||
return "the-uuid-123", nil
|
return "the-uuid-123", nil
|
||||||
},
|
},
|
||||||
|
@ -92,6 +92,7 @@ func scanTaskStatusChange(ctx context.Context, taskID int64, status string) (err
|
|||||||
NamespaceID: art.ProjectID,
|
NamespaceID: art.ProjectID,
|
||||||
Repository: art.RepositoryName,
|
Repository: art.RepositoryName,
|
||||||
Digest: art.Digest,
|
Digest: art.Digest,
|
||||||
|
Tag: getArtifactTag(t.ExtraAttrs),
|
||||||
MimeType: art.ManifestMediaType,
|
MimeType: art.ManifestMediaType,
|
||||||
},
|
},
|
||||||
Status: status,
|
Status: status,
|
||||||
|
@ -17,6 +17,7 @@ package scan
|
|||||||
// Options keep the settings/configurations for scanning.
|
// Options keep the settings/configurations for scanning.
|
||||||
type Options struct {
|
type Options struct {
|
||||||
ExecutionID int64 // The execution id to scan artifact
|
ExecutionID int64 // The execution id to scan artifact
|
||||||
|
Tag string // The tag of the artifact to scan
|
||||||
}
|
}
|
||||||
|
|
||||||
// Option represents an option item by func template.
|
// Option represents an option item by func template.
|
||||||
@ -34,3 +35,12 @@ func WithExecutionID(executionID int64) Option {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithTag sets the tag option.
|
||||||
|
func WithTag(tag string) Option {
|
||||||
|
return func(options *Options) error {
|
||||||
|
options.Tag = tag
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -23,6 +23,7 @@ import (
|
|||||||
"github.com/goharbor/harbor/src/controller/artifact"
|
"github.com/goharbor/harbor/src/controller/artifact"
|
||||||
"github.com/goharbor/harbor/src/controller/scan"
|
"github.com/goharbor/harbor/src/controller/scan"
|
||||||
"github.com/goharbor/harbor/src/lib/errors"
|
"github.com/goharbor/harbor/src/lib/errors"
|
||||||
|
"github.com/goharbor/harbor/src/pkg/distribution"
|
||||||
operation "github.com/goharbor/harbor/src/server/v2.0/restapi/operations/scan"
|
operation "github.com/goharbor/harbor/src/server/v2.0/restapi/operations/scan"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -58,7 +59,12 @@ func (s *scanAPI) ScanArtifact(ctx context.Context, params operation.ScanArtifac
|
|||||||
return s.SendError(ctx, err)
|
return s.SendError(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.scanCtl.Scan(ctx, artifact); err != nil {
|
options := []scan.Option{}
|
||||||
|
if !distribution.IsDigest(params.Reference) {
|
||||||
|
options = append(options, scan.WithTag(params.Reference))
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.scanCtl.Scan(ctx, artifact, options...); err != nil {
|
||||||
return s.SendError(ctx, err)
|
return s.SendError(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user