mirror of
https://github.com/goharbor/harbor.git
synced 2024-12-26 02:28:06 +01:00
Merge pull request #14023 from ywk253100/210115_scheduled
Fix the legacy scheduled job issue for GC/scan all
This commit is contained in:
commit
42559479e6
@ -312,7 +312,7 @@ BEGIN
|
|||||||
VALUES ('GARBAGE_COLLECTION', -1,
|
VALUES ('GARBAGE_COLLECTION', -1,
|
||||||
(SELECT schd.cron_str::json->>'cron'),
|
(SELECT schd.cron_str::json->>'cron'),
|
||||||
'GARBAGE_COLLECTION',
|
'GARBAGE_COLLECTION',
|
||||||
(SELECT json_build_object('trigger', null, 'deleteuntagged', schd.job_parameters::json->'delete_untagged', 'dryrun', false, 'job_parameters', schd.job_parameters)),
|
(SELECT json_build_object('trigger', null, 'deleteuntagged', schd.job_parameters::json->'delete_untagged', 'dryrun', false, 'extra_attrs', schd.job_parameters::json)),
|
||||||
(SELECT schd.cron_str::json->>'type'),
|
(SELECT schd.cron_str::json->>'type'),
|
||||||
(SELECT json_build_object('delete_untagged', schd.job_parameters::json->'delete_untagged')),
|
(SELECT json_build_object('delete_untagged', schd.job_parameters::json->'delete_untagged')),
|
||||||
schd.creation_time, schd.update_time) RETURNING id INTO new_schd_id;
|
schd.creation_time, schd.update_time) RETURNING id INTO new_schd_id;
|
||||||
@ -414,7 +414,7 @@ BEGIN
|
|||||||
LOOP
|
LOOP
|
||||||
INSERT INTO schedule (vendor_type, vendor_id, cron, callback_func_name,
|
INSERT INTO schedule (vendor_type, vendor_id, cron, callback_func_name,
|
||||||
cron_type, creation_time, update_time)
|
cron_type, creation_time, update_time)
|
||||||
VALUES ('IMAGE_SCAN_ALL', 0,
|
VALUES ('SCAN_ALL', 0,
|
||||||
(SELECT schd.cron_str::json->>'cron'),
|
(SELECT schd.cron_str::json->>'cron'),
|
||||||
'scanAll',
|
'scanAll',
|
||||||
(SELECT schd.cron_str::json->>'type'),
|
(SELECT schd.cron_str::json->>'type'),
|
||||||
|
@ -78,7 +78,7 @@ func (c *controller) Start(ctx context.Context, policy Policy, trigger string) (
|
|||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
_, err = c.taskMgr.Create(ctx, execID, &task.Job{
|
_, err = c.taskMgr.Create(ctx, execID, &task.Job{
|
||||||
Name: job.ImageGC,
|
Name: job.GarbageCollection,
|
||||||
Metadata: &job.Metadata{
|
Metadata: &job.Metadata{
|
||||||
JobKind: job.KindGeneric,
|
JobKind: job.KindGeneric,
|
||||||
},
|
},
|
||||||
|
@ -48,7 +48,10 @@ import (
|
|||||||
// DefaultController is a default singleton scan API controller.
|
// DefaultController is a default singleton scan API controller.
|
||||||
var DefaultController = NewController()
|
var DefaultController = NewController()
|
||||||
|
|
||||||
|
// const definitions
|
||||||
const (
|
const (
|
||||||
|
VendorTypeScanAll = "SCAN_ALL"
|
||||||
|
|
||||||
configRegistryEndpoint = "registryEndpoint"
|
configRegistryEndpoint = "registryEndpoint"
|
||||||
configCoreInternalAddr = "coreInternalAddr"
|
configCoreInternalAddr = "coreInternalAddr"
|
||||||
|
|
||||||
@ -62,7 +65,7 @@ const (
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
// keep only the latest created 5 scan all execution records
|
// keep only the latest created 5 scan all execution records
|
||||||
task.SetExecutionSweeperCount(job.ImageScanAllJob, 5)
|
task.SetExecutionSweeperCount(VendorTypeScanAll, 5)
|
||||||
}
|
}
|
||||||
|
|
||||||
// uuidGenerator is a func template which is for generating UUID.
|
// uuidGenerator is a func template which is for generating UUID.
|
||||||
@ -277,7 +280,7 @@ func (bc *basicController) Scan(ctx context.Context, artifact *ar.Artifact, opti
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (bc *basicController) ScanAll(ctx context.Context, trigger string, async bool) (int64, error) {
|
func (bc *basicController) ScanAll(ctx context.Context, trigger string, async bool) (int64, error) {
|
||||||
executionID, err := bc.execMgr.Create(ctx, job.ImageScanAllJob, 0, trigger)
|
executionID, err := bc.execMgr.Create(ctx, VendorTypeScanAll, 0, trigger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -479,7 +479,7 @@ func (suite *ControllerTestSuite) TestScanAll() {
|
|||||||
executionID := int64(1)
|
executionID := int64(1)
|
||||||
|
|
||||||
suite.execMgr.On(
|
suite.execMgr.On(
|
||||||
"Create", ctx, "IMAGE_SCAN_ALL", int64(0), "SCHEDULE",
|
"Create", ctx, "SCAN_ALL", int64(0), "SCHEDULE",
|
||||||
).Return(executionID, nil).Once()
|
).Return(executionID, nil).Once()
|
||||||
|
|
||||||
mock.OnAnything(suite.artifactCtl, "List").Return([]*artifact.Artifact{}, nil).Once()
|
mock.OnAnything(suite.artifactCtl, "List").Return([]*artifact.Artifact{}, nil).Once()
|
||||||
@ -501,7 +501,7 @@ func (suite *ControllerTestSuite) TestScanAll() {
|
|||||||
executionID := int64(1)
|
executionID := int64(1)
|
||||||
|
|
||||||
suite.execMgr.On(
|
suite.execMgr.On(
|
||||||
"Create", ctx, "IMAGE_SCAN_ALL", int64(0), "SCHEDULE",
|
"Create", ctx, "SCAN_ALL", int64(0), "SCHEDULE",
|
||||||
).Return(executionID, nil).Once()
|
).Return(executionID, nil).Once()
|
||||||
|
|
||||||
mock.OnAnything(suite.artifactCtl, "List").Return([]*artifact.Artifact{suite.artifact}, nil).Once()
|
mock.OnAnything(suite.artifactCtl, "List").Return([]*artifact.Artifact{suite.artifact}, nil).Once()
|
||||||
|
@ -47,7 +47,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: the vendor type of execution for the scan job trigger by the scan all is job.ImageScanAllJob
|
// NOTE: the vendor type of execution for the scan job trigger by the scan all is job.ImageScanAllJob
|
||||||
if err := task.RegisterCheckInProcessor(job.ImageScanAllJob, scanTaskCheckInProcessor); err != nil {
|
if err := task.RegisterCheckInProcessor(VendorTypeScanAll, scanTaskCheckInProcessor); err != nil {
|
||||||
log.Fatalf("failed to register the checkin processor for the scan all job, error %v", err)
|
log.Fatalf("failed to register the checkin processor for the scan all job, error %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,7 +164,7 @@ func (suite *CallbackTestSuite) TestScanAllCallback() {
|
|||||||
{
|
{
|
||||||
// create execution failed
|
// create execution failed
|
||||||
suite.execMgr.On(
|
suite.execMgr.On(
|
||||||
"Create", context.TODO(), "IMAGE_SCAN_ALL", int64(0), "SCHEDULE",
|
"Create", context.TODO(), "SCAN_ALL", int64(0), "SCHEDULE",
|
||||||
).Return(int64(0), fmt.Errorf("failed")).Once()
|
).Return(int64(0), fmt.Errorf("failed")).Once()
|
||||||
|
|
||||||
suite.Error(scanAllCallback(context.TODO(), ""))
|
suite.Error(scanAllCallback(context.TODO(), ""))
|
||||||
@ -174,7 +174,7 @@ func (suite *CallbackTestSuite) TestScanAllCallback() {
|
|||||||
executionID := int64(1)
|
executionID := int64(1)
|
||||||
|
|
||||||
suite.execMgr.On(
|
suite.execMgr.On(
|
||||||
"Create", context.TODO(), "IMAGE_SCAN_ALL", int64(0), "SCHEDULE",
|
"Create", context.TODO(), "SCAN_ALL", int64(0), "SCHEDULE",
|
||||||
).Return(executionID, nil).Once()
|
).Return(executionID, nil).Once()
|
||||||
|
|
||||||
suite.execMgr.On(
|
suite.execMgr.On(
|
||||||
|
36
src/jobservice/job/impl/legacy/legacy.go
Normal file
36
src/jobservice/job/impl/legacy/legacy.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// 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 legacy
|
||||||
|
|
||||||
|
import "github.com/goharbor/harbor/src/pkg/scheduler"
|
||||||
|
|
||||||
|
// As one job implementation can only be registered with one name. Define the following three
|
||||||
|
// schedulers which are wrapper of pkg/scheduler.PeriodicJob for the legacy periodical jobs
|
||||||
|
// They can be removed after several releases
|
||||||
|
|
||||||
|
// ReplicationScheduler is the legacy scheduler for replication
|
||||||
|
type ReplicationScheduler struct {
|
||||||
|
scheduler.PeriodicJob
|
||||||
|
}
|
||||||
|
|
||||||
|
// GarbageCollectionScheduler is the legacy scheduler for garbage collection
|
||||||
|
type GarbageCollectionScheduler struct {
|
||||||
|
scheduler.PeriodicJob
|
||||||
|
}
|
||||||
|
|
||||||
|
// ScanAllScheduler is the legacy scheduler for scan all
|
||||||
|
type ScanAllScheduler struct {
|
||||||
|
scheduler.PeriodicJob
|
||||||
|
}
|
@ -1,81 +0,0 @@
|
|||||||
// 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 replication
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/goharbor/harbor/src/common/api"
|
|
||||||
common_http "github.com/goharbor/harbor/src/common/http"
|
|
||||||
"github.com/goharbor/harbor/src/common/http/modifier/auth"
|
|
||||||
"github.com/goharbor/harbor/src/jobservice/job"
|
|
||||||
"github.com/goharbor/harbor/src/replication/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Scheduler is a job running in Jobservice which can be used as
|
|
||||||
// a scheduler when submitting it as a scheduled job. It receives
|
|
||||||
// a URL and data, and post the data to the URL when it is running
|
|
||||||
type Scheduler struct {
|
|
||||||
ctx job.Context
|
|
||||||
}
|
|
||||||
|
|
||||||
// ShouldRetry ...
|
|
||||||
func (s *Scheduler) ShouldRetry() bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// MaxFails ...
|
|
||||||
func (s *Scheduler) MaxFails() uint {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// MaxCurrency is implementation of same method in Interface.
|
|
||||||
func (s *Scheduler) MaxCurrency() uint {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate ....
|
|
||||||
func (s *Scheduler) Validate(params job.Parameters) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run ...
|
|
||||||
func (s *Scheduler) Run(ctx job.Context, params job.Parameters) error {
|
|
||||||
cmd, exist := ctx.OPCommand()
|
|
||||||
if exist && cmd == job.StopCommand {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
logger := ctx.GetLogger()
|
|
||||||
|
|
||||||
url := params["url"].(string)
|
|
||||||
url = fmt.Sprintf("%s/api/%s/replication/executions?trigger=%s", url, api.APIVersion, model.TriggerTypeScheduled)
|
|
||||||
policyID := (int64)(params["policy_id"].(float64))
|
|
||||||
cred := auth.NewSecretAuthorizer(os.Getenv("JOBSERVICE_SECRET"))
|
|
||||||
client := common_http.NewClient(&http.Client{
|
|
||||||
Transport: common_http.GetHTTPTransport(common_http.SecureTransport),
|
|
||||||
}, cred)
|
|
||||||
if err := client.Post(url, struct {
|
|
||||||
PolicyID int64 `json:"policy_id"`
|
|
||||||
}{
|
|
||||||
PolicyID: policyID,
|
|
||||||
}); err != nil {
|
|
||||||
logger.Errorf("failed to run the schedule job: %v", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
logger.Info("the schedule job finished")
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -22,16 +22,12 @@ const (
|
|||||||
|
|
||||||
// ImageScanJob is name of scan job it will be used as key to register to job service.
|
// ImageScanJob is name of scan job it will be used as key to register to job service.
|
||||||
ImageScanJob = "IMAGE_SCAN"
|
ImageScanJob = "IMAGE_SCAN"
|
||||||
// ImageScanAllJob is the name of "scanall" job in job service
|
// GarbageCollection job name
|
||||||
ImageScanAllJob = "IMAGE_SCAN_ALL"
|
GarbageCollection = "GARBAGE_COLLECTION"
|
||||||
// ImageGC the name of image garbage collection job in job service
|
|
||||||
ImageGC = "IMAGE_GC"
|
|
||||||
// ImageGCReadOnly the name of image garbage collection read only job in job service
|
// ImageGCReadOnly the name of image garbage collection read only job in job service
|
||||||
ImageGCReadOnly = "IMAGE_GC_READ_ONLY"
|
ImageGCReadOnly = "IMAGE_GC_READ_ONLY"
|
||||||
// Replication : the name of the replication job in job service
|
// Replication : the name of the replication job in job service
|
||||||
Replication = "REPLICATION"
|
Replication = "REPLICATION"
|
||||||
// ReplicationScheduler : the name of the replication scheduler job in job service
|
|
||||||
ReplicationScheduler = "IMAGE_REPLICATE"
|
|
||||||
// WebhookJob : the name of the webhook job in job service
|
// WebhookJob : the name of the webhook job in job service
|
||||||
WebhookJob = "WEBHOOK"
|
WebhookJob = "WEBHOOK"
|
||||||
// SlackJob : the name of the slack job in job service
|
// SlackJob : the name of the slack job in job service
|
||||||
|
@ -75,7 +75,7 @@ func (suite *ManagerTestSuite) SetupTest() {
|
|||||||
"id",
|
"id",
|
||||||
id,
|
id,
|
||||||
"name",
|
"name",
|
||||||
job.ImageGC,
|
jobNameGarbageCollection,
|
||||||
"kind",
|
"kind",
|
||||||
job.KindPeriodic,
|
job.KindPeriodic,
|
||||||
"unique",
|
"unique",
|
||||||
@ -104,7 +104,7 @@ func (suite *ManagerTestSuite) SetupTest() {
|
|||||||
params["redis_url_reg"] = "redis://redis:6379/1"
|
params["redis_url_reg"] = "redis://redis:6379/1"
|
||||||
|
|
||||||
policy := make(map[string]interface{})
|
policy := make(map[string]interface{})
|
||||||
policy["job_name"] = job.ImageGC
|
policy["job_name"] = jobNameGarbageCollection
|
||||||
policy["job_params"] = params
|
policy["job_params"] = params
|
||||||
policy["cron_spec"] = "0 0 17 * * *"
|
policy["cron_spec"] = "0 0 17 * * *"
|
||||||
|
|
||||||
|
@ -29,6 +29,12 @@ import (
|
|||||||
"github.com/gomodule/redigo/redis"
|
"github.com/gomodule/redigo/redis"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
jobNameGarbageCollection = "IMAGE_GC"
|
||||||
|
jobNameScanAll = "IMAGE_SCAN_ALL"
|
||||||
|
jobNameReplicationScheduler = "IMAGE_REPLICATE"
|
||||||
|
)
|
||||||
|
|
||||||
// PolicyMigrator migrate the cron job policy to new schema
|
// PolicyMigrator migrate the cron job policy to new schema
|
||||||
type PolicyMigrator struct {
|
type PolicyMigrator struct {
|
||||||
// namespace of rdb
|
// namespace of rdb
|
||||||
@ -299,9 +305,9 @@ func clearDuplicatedPolicies(conn redis.Conn, ns string) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.JobName == job.ImageScanAllJob ||
|
if p.JobName == jobNameScanAll ||
|
||||||
p.JobName == job.ImageGC ||
|
p.JobName == jobNameGarbageCollection ||
|
||||||
p.JobName == job.ReplicationScheduler {
|
p.JobName == jobNameReplicationScheduler {
|
||||||
score, _ := strconv.ParseInt(string(bytes[i+1].([]byte)), 10, 64)
|
score, _ := strconv.ParseInt(string(bytes[i+1].([]byte)), 10, 64)
|
||||||
|
|
||||||
key := hashKey(p)
|
key := hashKey(p)
|
||||||
|
@ -33,6 +33,7 @@ import (
|
|||||||
"github.com/goharbor/harbor/src/jobservice/job/impl"
|
"github.com/goharbor/harbor/src/jobservice/job/impl"
|
||||||
"github.com/goharbor/harbor/src/jobservice/job/impl/gc"
|
"github.com/goharbor/harbor/src/jobservice/job/impl/gc"
|
||||||
"github.com/goharbor/harbor/src/jobservice/job/impl/gcreadonly"
|
"github.com/goharbor/harbor/src/jobservice/job/impl/gcreadonly"
|
||||||
|
"github.com/goharbor/harbor/src/jobservice/job/impl/legacy"
|
||||||
"github.com/goharbor/harbor/src/jobservice/job/impl/notification"
|
"github.com/goharbor/harbor/src/jobservice/job/impl/notification"
|
||||||
"github.com/goharbor/harbor/src/jobservice/job/impl/replication"
|
"github.com/goharbor/harbor/src/jobservice/job/impl/replication"
|
||||||
"github.com/goharbor/harbor/src/jobservice/job/impl/sample"
|
"github.com/goharbor/harbor/src/jobservice/job/impl/sample"
|
||||||
@ -255,15 +256,20 @@ func (bs *Bootstrap) loadAndRunRedisWorkerPool(
|
|||||||
job.SampleJob: (*sample.Job)(nil),
|
job.SampleJob: (*sample.Job)(nil),
|
||||||
// Functional jobs
|
// Functional jobs
|
||||||
job.ImageScanJob: (*scan.Job)(nil),
|
job.ImageScanJob: (*scan.Job)(nil),
|
||||||
job.ImageGC: (*gc.GarbageCollector)(nil),
|
job.GarbageCollection: (*gc.GarbageCollector)(nil),
|
||||||
job.ImageGCReadOnly: (*gcreadonly.GarbageCollector)(nil),
|
job.ImageGCReadOnly: (*gcreadonly.GarbageCollector)(nil),
|
||||||
job.Replication: (*replication.Replication)(nil),
|
job.Replication: (*replication.Replication)(nil),
|
||||||
job.ReplicationScheduler: (*replication.Scheduler)(nil),
|
|
||||||
job.Retention: (*retention.Job)(nil),
|
job.Retention: (*retention.Job)(nil),
|
||||||
scheduler.JobNameScheduler: (*scheduler.PeriodicJob)(nil),
|
scheduler.JobNameScheduler: (*scheduler.PeriodicJob)(nil),
|
||||||
job.WebhookJob: (*notification.WebhookJob)(nil),
|
job.WebhookJob: (*notification.WebhookJob)(nil),
|
||||||
job.SlackJob: (*notification.SlackJob)(nil),
|
job.SlackJob: (*notification.SlackJob)(nil),
|
||||||
job.P2PPreheat: (*preheat.Job)(nil),
|
job.P2PPreheat: (*preheat.Job)(nil),
|
||||||
|
// In v2.2 we migrate the scheduled replication, garbage collection and scan all to
|
||||||
|
// the scheduler mechanism, the following three jobs are kept for the legacy jobs
|
||||||
|
// and they can be removed after several releases
|
||||||
|
"IMAGE_REPLICATE": (*legacy.ReplicationScheduler)(nil),
|
||||||
|
"IMAGE_GC": (*legacy.GarbageCollectionScheduler)(nil),
|
||||||
|
"IMAGE_SCAN_ALL": (*legacy.ScanAllScheduler)(nil),
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
// exit
|
// exit
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -176,11 +176,11 @@ func (s *scanAllAPI) createOrUpdateScanAllSchedule(ctx context.Context, cronType
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.scheduler.Schedule(ctx, job.ImageScanAllJob, 0, cronType, cron, scan.ScanAllCallback, nil, nil)
|
return s.scheduler.Schedule(ctx, scan.VendorTypeScanAll, 0, cronType, cron, scan.ScanAllCallback, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *scanAllAPI) getScanAllSchedule(ctx context.Context) (*scheduler.Schedule, error) {
|
func (s *scanAllAPI) getScanAllSchedule(ctx context.Context) (*scheduler.Schedule, error) {
|
||||||
query := q.New(q.KeyWords{"vendor_type": job.ImageScanAllJob})
|
query := q.New(q.KeyWords{"vendor_type": scan.VendorTypeScanAll})
|
||||||
schedules, err := s.scheduler.ListSchedules(ctx, query.First("-creation_time"))
|
schedules, err := s.scheduler.ListSchedules(ctx, query.First("-creation_time"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -235,7 +235,7 @@ func (s *scanAllAPI) getMetrics(ctx context.Context, trigger ...string) (*models
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *scanAllAPI) getLatestScanAllExecution(ctx context.Context, trigger ...string) (*task.Execution, error) {
|
func (s *scanAllAPI) getLatestScanAllExecution(ctx context.Context, trigger ...string) (*task.Execution, error) {
|
||||||
query := q.New(q.KeyWords{"vendor_type": job.ImageScanAllJob})
|
query := q.New(q.KeyWords{"vendor_type": scan.VendorTypeScanAll})
|
||||||
if len(trigger) > 0 {
|
if len(trigger) > 0 {
|
||||||
query.Keywords["trigger"] = trigger[0]
|
query.Keywords["trigger"] = trigger[0]
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user