Skip to content

Commit

Permalink
restructures the code to fix cycle dependencies
Browse files Browse the repository at this point in the history
Signed-off-by: Maksym Trofimenko <maksym@container-registry.com>
  • Loading branch information
Maksym Trofimenko committed Jan 19, 2025
1 parent e350a10 commit cf1d1fa
Show file tree
Hide file tree
Showing 20 changed files with 136 additions and 171 deletions.
3 changes: 1 addition & 2 deletions src/controller/artifact/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (
"context"
stderrors "errors"
"fmt"
policyindex "github.com/goharbor/harbor/src/pkg/retention/policy/rule/index"
"os"
"strings"
"time"
Expand Down Expand Up @@ -132,7 +131,7 @@ func NewController() Controller {
artrashMgr: artifactrash.Mgr,
blobMgr: blob.Mgr,
labelMgr: label.Mgr,
immutableMtr: rule.NewRuleMatcher(policyindex.Get),
immutableMtr: rule.NewRuleMatcher(),
regCli: registry.Cli,
abstractor: NewAbstractor(),
accessoryMgr: accessory.Mgr,
Expand Down
3 changes: 1 addition & 2 deletions src/controller/tag/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import (
"github.com/goharbor/harbor/src/pkg/artifact"
"github.com/goharbor/harbor/src/pkg/immutable/match"
"github.com/goharbor/harbor/src/pkg/immutable/match/rule"
policyindex "github.com/goharbor/harbor/src/pkg/retention/policy/rule/index"
"github.com/goharbor/harbor/src/pkg/tag"
model_tag "github.com/goharbor/harbor/src/pkg/tag/model/tag"
)
Expand Down Expand Up @@ -64,7 +63,7 @@ func NewController() Controller {
return &controller{
tagMgr: tag.Mgr,
artMgr: pkg.ArtifactMgr,
immutableMtr: rule.NewRuleMatcher(policyindex.Get),
immutableMtr: rule.NewRuleMatcher(),
}
}

Expand Down
34 changes: 0 additions & 34 deletions src/pkg/clients/core/artifact.go

This file was deleted.

3 changes: 2 additions & 1 deletion src/pkg/clients/core/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (

chttp "github.com/goharbor/harbor/src/common/http"
"github.com/goharbor/harbor/src/common/http/modifier"
modelsv2 "github.com/goharbor/harbor/src/controller/artifact"
)

// Client defines the methods that a core client should implement
Expand All @@ -31,7 +32,7 @@ type Client interface {

// ArtifactClient defines the methods that an image client should implement
type ArtifactClient interface {
ListAllArtifacts(project, repository string) ([]*Artifact, error)
ListAllArtifacts(project, repository string) ([]*modelsv2.Artifact, error)
DeleteArtifact(project, repository, digest string) error
DeleteArtifactRepository(project, repository string) error
}
Expand Down
5 changes: 3 additions & 2 deletions src/pkg/clients/core/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ package core
import (
"fmt"

modelsv2 "github.com/goharbor/harbor/src/controller/artifact"
"github.com/goharbor/harbor/src/lib/encode/repository"
)

func (c *client) ListAllArtifacts(project, repo string) ([]*Artifact, error) {
func (c *client) ListAllArtifacts(project, repo string) ([]*modelsv2.Artifact, error) {
repo = repository.Encode(repo)
url := c.buildURL(fmt.Sprintf("/api/v2.0/projects/%s/repositories/%s/artifacts", project, repo))
var arts []*Artifact
var arts []*modelsv2.Artifact
if err := c.httpclient.GetAndIteratePagination(url, &arts); err != nil {
return nil, err
}
Expand Down
13 changes: 5 additions & 8 deletions src/pkg/immutable/match/rule/match.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,12 @@ import (
"github.com/goharbor/harbor/src/pkg/immutable/match"
"github.com/goharbor/harbor/src/pkg/immutable/model"
"github.com/goharbor/harbor/src/pkg/retention/policy/rule"
policyindex "github.com/goharbor/harbor/src/pkg/retention/policy/rule/index"
)

// EvaluatorGetter functions that gets evaluator from index based on templateID
type EvaluatorGetter func(templateID string, parameters rule.Parameters) (rule.Evaluator, error)

// Matcher ...
type Matcher struct {
rules []*model.Metadata
evaluatorGetter EvaluatorGetter
rules []*model.Metadata
}

// Match ...
Expand Down Expand Up @@ -91,7 +88,7 @@ func (rm *Matcher) Match(ctx context.Context, pid int64, c iselector.Candidate)
params[k] = v
}

evaluator, err := rm.evaluatorGetter(r.Template, params)
evaluator, err := policyindex.Get(r.Template, params)
if err != nil {
return false, err
}
Expand All @@ -118,6 +115,6 @@ func (rm *Matcher) getImmutableRules(ctx context.Context, pid int64) error {
}

// NewRuleMatcher ...
func NewRuleMatcher(eg EvaluatorGetter) match.ImmutableTagMatcher {
return &Matcher{evaluatorGetter: eg}
func NewRuleMatcher() match.ImmutableTagMatcher {
return &Matcher{}
}
3 changes: 1 addition & 2 deletions src/pkg/immutable/match/rule/match_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"github.com/goharbor/harbor/src/lib/orm"
"github.com/goharbor/harbor/src/lib/selector"
"github.com/goharbor/harbor/src/pkg/immutable/model"
policyindex "github.com/goharbor/harbor/src/pkg/retention/policy/rule/index"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
Expand Down Expand Up @@ -149,7 +148,7 @@ func (s *MatchTestSuite) TestImmuMatch() {
s.ruleIDs = append(s.ruleIDs, id)
s.require.Nil(err)

match := NewRuleMatcher(policyindex.Get)
match := NewRuleMatcher()

c1 := selector.Candidate{
NamespaceID: 1,
Expand Down
5 changes: 2 additions & 3 deletions src/pkg/retention/policy/action/index/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ package index

import (
"github.com/goharbor/harbor/src/lib/errors"
"github.com/goharbor/harbor/src/pkg/immutable/match/rule"
"github.com/goharbor/harbor/src/pkg/retention/policy/action"
policyindex "github.com/goharbor/harbor/src/pkg/retention/policy/rule/index"
"github.com/goharbor/harbor/src/pkg/retention/policy/action/performer"
"sync"
)

Expand All @@ -27,7 +26,7 @@ var index sync.Map

func init() {
// Register retain action
Register(action.Retain, action.NewRetainAction(rule.NewRuleMatcher(policyindex.Get)))
Register(action.Retain, performer.NewRetainAction)
}

// Register the performer with the corresponding action
Expand Down
94 changes: 0 additions & 94 deletions src/pkg/retention/policy/action/performer.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,7 @@ package action

import (
"context"
"github.com/goharbor/harbor/src/pkg/immutable/match"

"github.com/goharbor/harbor/src/common/utils"
"github.com/goharbor/harbor/src/lib/log"
"github.com/goharbor/harbor/src/lib/selector"
"github.com/goharbor/harbor/src/pkg/retention/dep"
)

const (
Expand All @@ -44,92 +39,3 @@ type Performer interface {

// PerformerFactory is factory method for creating Performer
type PerformerFactory func(params interface{}, isDryRun bool) Performer

// retainAction make sure all the candidates will be retained and others will be cleared
type retainAction struct {
all []*selector.Candidate
// Indicate if it is a dry run
isDryRun bool

immutableTagMatcher match.ImmutableTagMatcher
}

// Perform the action
func (ra *retainAction) Perform(ctx context.Context, candidates []*selector.Candidate) (results []*selector.Result, err error) {
retainedShare := make(map[string]bool)
immutableShare := make(map[string]bool)
for _, c := range candidates {
retainedShare[c.Hash()] = true
}

for _, c := range ra.all {
if _, ok := retainedShare[c.Hash()]; ok {
continue
}
if ra.isImmutable(ctx, c) {
immutableShare[c.Hash()] = true
}
}

// start to delete
if len(ra.all) > 0 {
for _, c := range ra.all {
if _, ok := retainedShare[c.Hash()]; !ok {
result := &selector.Result{
Target: c,
}
if _, ok = immutableShare[c.Hash()]; ok {
result.Error = &selector.ImmutableError{}
} else {
if !ra.isDryRun {
if err := dep.DefaultClient.Delete(c); err != nil {
result.Error = err
}
}
}
results = append(results, result)
}
}
}

return
}

func (ra *retainAction) isImmutable(ctx context.Context, c *selector.Candidate) bool {
projectID := c.NamespaceID
repo := c.Repository
_, repoName := utils.ParseRepository(repo)
matched, err := ra.immutableTagMatcher.Match(ctx, projectID, selector.Candidate{
Repository: repoName,
Tags: c.Tags,
NamespaceID: projectID,
PulledTime: c.PulledTime,
PushedTime: c.PushedTime,
})
if err != nil {
log.Error(err)
return false
}
return matched
}

// NewRetainAction returns factory method for RetainAction
func NewRetainAction(m match.ImmutableTagMatcher) PerformerFactory {
return func(params interface{}, isDryRun bool) Performer {
if params != nil {
if all, ok := params.([]*selector.Candidate); ok {
ra := &retainAction{
all: all,
isDryRun: isDryRun,
immutableTagMatcher: m,
}
return ra
}
}
return &retainAction{
all: make([]*selector.Candidate, 0),
isDryRun: isDryRun,
immutableTagMatcher: m,
}
}
}
107 changes: 107 additions & 0 deletions src/pkg/retention/policy/action/performer/performer.go
Original file line number Diff line number Diff line change
@@ -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 performer

import (
"context"
"github.com/goharbor/harbor/src/common/utils"
"github.com/goharbor/harbor/src/lib/log"
"github.com/goharbor/harbor/src/lib/selector"
rule2 "github.com/goharbor/harbor/src/pkg/immutable/match/rule"
"github.com/goharbor/harbor/src/pkg/retention/dep"
"github.com/goharbor/harbor/src/pkg/retention/policy/action"
)

// retainAction make sure all the candidates will be retained and others will be cleared
type retainAction struct {
all []*selector.Candidate
// Indicate if it is a dry run
isDryRun bool
}

// Perform the action
func (ra *retainAction) Perform(ctx context.Context, candidates []*selector.Candidate) (results []*selector.Result, err error) {
retainedShare := make(map[string]bool)
immutableShare := make(map[string]bool)
for _, c := range candidates {
retainedShare[c.Hash()] = true
}

for _, c := range ra.all {
if _, ok := retainedShare[c.Hash()]; ok {
continue
}
if isImmutable(ctx, c) {
immutableShare[c.Hash()] = true
}
}

// start to delete
if len(ra.all) > 0 {
for _, c := range ra.all {
if _, ok := retainedShare[c.Hash()]; !ok {
result := &selector.Result{
Target: c,
}
if _, ok = immutableShare[c.Hash()]; ok {
result.Error = &selector.ImmutableError{}
} else {
if !ra.isDryRun {
if err := dep.DefaultClient.Delete(c); err != nil {
result.Error = err
}
}
}
results = append(results, result)
}
}
}

return
}

func isImmutable(ctx context.Context, c *selector.Candidate) bool {
projectID := c.NamespaceID
repo := c.Repository
_, repoName := utils.ParseRepository(repo)
matched, err := rule2.NewRuleMatcher().Match(ctx, projectID, selector.Candidate{
Repository: repoName,
Tags: c.Tags,
NamespaceID: projectID,
PulledTime: c.PulledTime,
PushedTime: c.PushedTime,
})
if err != nil {
log.Error(err)
return false
}
return matched
}

// NewRetainAction returns performer for RetainAction
func NewRetainAction(params interface{}, isDryRun bool) action.Performer {
if params != nil {
if all, ok := params.([]*selector.Candidate); ok {
return &retainAction{
all: all,
isDryRun: isDryRun,
}
}
}
return &retainAction{
all: make([]*selector.Candidate, 0),
isDryRun: isDryRun,
}
}
Loading

0 comments on commit cf1d1fa

Please sign in to comment.