From 52ca6de22a71c3ca5bf8521c1ebc569f0ff63a28 Mon Sep 17 00:00:00 2001 From: Steven Zou Date: Thu, 11 Jul 2019 00:23:19 +0800 Subject: [PATCH] refactor the processor interface Signed-off-by: Steven Zou --- src/pkg/retention/policy/alg/index.go | 49 ++++++++++++++ src/pkg/retention/policy/alg/or/processor.go | 32 ++++++---- .../retention/policy/alg/or/processor_test.go | 26 ++++++-- src/pkg/retention/policy/alg/processor.go | 30 +++++---- src/pkg/retention/policy/builder.go | 64 ++++++++++--------- 5 files changed, 137 insertions(+), 64 deletions(-) create mode 100644 src/pkg/retention/policy/alg/index.go diff --git a/src/pkg/retention/policy/alg/index.go b/src/pkg/retention/policy/alg/index.go new file mode 100644 index 000000000..327e4e42e --- /dev/null +++ b/src/pkg/retention/policy/alg/index.go @@ -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) +} diff --git a/src/pkg/retention/policy/alg/or/processor.go b/src/pkg/retention/policy/alg/or/processor.go index 78ae32b92..cfbceb406 100644 --- a/src/pkg/retention/policy/alg/or/processor.go +++ b/src/pkg/retention/policy/alg/or/processor.go @@ -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[¶m.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 diff --git a/src/pkg/retention/policy/alg/or/processor_test.go b/src/pkg/retention/policy/alg/or/processor_test.go index d4c20c46f..bc5d29e29 100644 --- a/src/pkg/retention/policy/alg/or/processor_test.go +++ b/src/pkg/retention/policy/alg/or/processor_test.go @@ -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 } diff --git a/src/pkg/retention/policy/alg/processor.go b/src/pkg/retention/policy/alg/processor.go index af49f7c21..4f7103a5f 100644 --- a/src/pkg/retention/policy/alg/processor.go +++ b/src/pkg/retention/policy/alg/processor.go @@ -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 diff --git a/src/pkg/retention/policy/builder.go b/src/pkg/retention/policy/builder.go index 4d458175f..44461c87d 100644 --- a/src/pkg/retention/policy/builder.go +++ b/src/pkg/retention/policy/builder.go @@ -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 }