Merge pull request #8275 from steven-zou/feature/tag_retention_job

refactor the processor interface
This commit is contained in:
Steven Zou 2019-07-11 14:05:45 +08:00 committed by GitHub
commit 8a010ce3d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 137 additions and 64 deletions

View File

@ -0,0 +1,49 @@
// 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 alg
import (
"github.com/pkg/errors"
"sync"
)
const (
// AlgorithmOR for || algorithm
AlgorithmOR = "or"
)
// index for keeping the mapping between algorithm and its processor
var index sync.Map
// Register processor with the algorithm
func Register(algorithm string, processor Factory) {
if len(algorithm) > 0 && processor != nil {
index.Store(algorithm, processor)
}
}
// Get Processor
func Get(algorithm string, params []*Parameter) (Processor, error) {
v, ok := index.Load(algorithm)
if !ok {
return nil, errors.Errorf("no processor registered with algorithm: %s", algorithm)
}
if fac, ok := v.(Factory); ok {
return fac(params), nil
}
return nil, errors.Errorf("no valid processor registered for algorithm: %s", algorithm)
}

View File

@ -34,11 +34,27 @@ type processor struct {
}
// New processor
func New() alg.Processor {
return &processor{
func New(parameters []*alg.Parameter) alg.Processor {
p := &processor{
evaluators: make(map[*rule.Evaluator][]res.Selector),
performers: make(map[string]action.Performer),
}
if len(parameters) > 0 {
for _, param := range parameters {
if param.Evaluator != nil {
if len(param.Selectors) > 0 {
p.evaluators[&param.Evaluator] = param.Selectors
}
if param.Performer != nil {
p.performers[param.Evaluator.Action()] = param.Performer
}
}
}
}
return p
}
// Process the candidates with the rules
@ -188,16 +204,8 @@ func (p *processor) Process(artifacts []*res.Candidate) ([]*res.Result, error) {
return results, nil
}
// AddEvaluator appends a rule evaluator for processing
func (p *processor) AddEvaluator(evaluator rule.Evaluator, selectors []res.Selector) {
if evaluator != nil {
p.evaluators[&evaluator] = selectors
}
}
// SetPerformer sets a action performer to the processor
func (p *processor) AddActionPerformer(action string, performer action.Performer) {
p.performers[action] = performer
func init() {
alg.Register(alg.AlgorithmOR, New)
}
type cHash map[string]*res.Candidate

View File

@ -64,22 +64,34 @@ func (suite *ProcessorTestSuite) SetupSuite() {
},
}
p := New()
p.AddActionPerformer(action.Retain, action.NewRetainAction(suite.all))
params := make([]*alg.Parameter, 0)
perf := action.NewRetainAction(suite.all)
lastxParams := make(map[string]rule.Parameter)
lastxParams[lastx.ParameterX] = 10
p.AddEvaluator(lastx.New(lastxParams), []res.Selector{
regexp.New(regexp.Matches, "*dev*"),
label.New(label.With, "L1,L2"),
params = append(params, &alg.Parameter{
Evaluator: lastx.New(lastxParams),
Selectors: []res.Selector{
regexp.New(regexp.Matches, "*dev*"),
label.New(label.With, "L1,L2"),
},
Performer: perf,
})
latestKParams := make(map[string]rule.Parameter)
latestKParams[latestk.ParameterK] = 10
p.AddEvaluator(latestk.New(latestKParams), []res.Selector{
label.New(label.With, "L3"),
params = append(params, &alg.Parameter{
Evaluator: latestk.New(latestKParams),
Selectors: []res.Selector{
label.New(label.With, "L3"),
},
Performer: perf,
})
p, err := alg.Get(alg.AlgorithmOR, params)
require.NoError(suite.T(), err)
suite.p = p
}

View File

@ -33,18 +33,20 @@ type Processor interface {
// []*res.Result : the processed results
// error : common error object if any errors occurred
Process(artifacts []*res.Candidate) ([]*res.Result, error)
// Add a rule evaluator for the processor
//
// Arguments:
// evaluator rule.Evaluator : a rule evaluator
// selectors []res.Selector : selectors to narrow down the scope (&& adopted), optional
AddEvaluator(evaluator rule.Evaluator, selectors []res.Selector)
// Add performer for the related action to the processor
//
// Arguments:
// action string : action name
// performer action.Performer : a performer implementation
AddActionPerformer(action string, performer action.Performer)
}
// Parameter for constructing a processor
// Represents one rule
type Parameter struct {
// Evaluator for the rule
Evaluator rule.Evaluator
// Selectors for the rule
Selectors []res.Selector
// Performer for the rule evaluator
Performer action.Performer
}
// Factory for creating processor
type Factory func([]*Parameter) Processor

View File

@ -15,9 +15,9 @@
package policy
import (
"fmt"
"github.com/goharbor/harbor/src/pkg/retention/policy/action"
"github.com/goharbor/harbor/src/pkg/retention/policy/alg"
"github.com/goharbor/harbor/src/pkg/retention/policy/alg/or"
"github.com/goharbor/harbor/src/pkg/retention/policy/rule"
"github.com/goharbor/harbor/src/pkg/retention/res"
"github.com/goharbor/harbor/src/pkg/retention/res/selectors"
@ -55,38 +55,40 @@ func (bb *basicBuilder) Build(policy *LiteMeta) (alg.Processor, error) {
return nil, errors.New("nil policy to build processor")
}
switch policy.Algorithm {
case AlgorithmOR:
// New OR processor
p := or.New()
for _, r := range policy.Rules {
evaluator, err := rule.Get(r.Template, r.Parameters)
if err != nil {
return nil, err
}
params := make([]*alg.Parameter, 0)
perf, err := action.Get(r.Action, bb.allCandidates)
if err != nil {
return nil, errors.Wrap(err, "get action performer by metadata")
}
sl := make([]res.Selector, 0)
for _, s := range r.TagSelectors {
sel, err := selectors.Get(s.Kind, s.Decoration, s.Pattern)
if err != nil {
return nil, errors.Wrap(err, "get selector by metadata")
}
sl = append(sl, sel)
}
p.AddEvaluator(evaluator, sl)
p.AddActionPerformer(r.Action, perf)
return p, nil
for _, r := range policy.Rules {
evaluator, err := rule.Get(r.Template, r.Parameters)
if err != nil {
return nil, err
}
default:
perf, err := action.Get(r.Action, bb.allCandidates)
if err != nil {
return nil, errors.Wrap(err, "get action performer by metadata")
}
sl := make([]res.Selector, 0)
for _, s := range r.TagSelectors {
sel, err := selectors.Get(s.Kind, s.Decoration, s.Pattern)
if err != nil {
return nil, errors.Wrap(err, "get selector by metadata")
}
sl = append(sl, sel)
}
params = append(params, &alg.Parameter{
Evaluator: evaluator,
Selectors: sl,
Performer: perf,
})
}
return nil, errors.Errorf("algorithm %s is not supported", policy.Algorithm)
p, err := alg.Get(policy.Algorithm, params)
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf("get processor for algorithm: %s", policy.Algorithm))
}
return p, nil
}