Skip to content

Commit

Permalink
🌱 Refactor filter package (#1734)
Browse files Browse the repository at this point in the history
* Move filter code to util/slices

Signed-off-by: Per Goncalves da Silva <[email protected]>

* Rename Filter to RemoveInPlace

Signed-off-by: Per Goncalves da Silva <[email protected]>

* Add Filter function and update unit tests

Signed-off-by: Per Goncalves da Silva <[email protected]>

* Refactor slice utils package structure

Signed-off-by: Per Goncalves da Silva <[email protected]>

* Address reviewer comments

Signed-off-by: Per Goncalves da Silva <[email protected]>

---------

Signed-off-by: Per Goncalves da Silva <[email protected]>
Co-authored-by: Per Goncalves da Silva <[email protected]>
  • Loading branch information
perdasilva and Per Goncalves da Silva authored Feb 11, 2025
1 parent c0a2964 commit 9864ba7
Show file tree
Hide file tree
Showing 7 changed files with 271 additions and 96 deletions.
5 changes: 3 additions & 2 deletions internal/catalogmetadata/filter/bundle_predicates.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import (
"github.com/operator-framework/operator-registry/alpha/declcfg"

"github.com/operator-framework/operator-controller/internal/bundleutil"
"github.com/operator-framework/operator-controller/internal/util/filter"
)

func InMastermindsSemverRange(semverRange *mmsemver.Constraints) Predicate[declcfg.Bundle] {
func InMastermindsSemverRange(semverRange *mmsemver.Constraints) filter.Predicate[declcfg.Bundle] {
return func(b declcfg.Bundle) bool {
bVersion, err := bundleutil.GetVersion(b)
if err != nil {
Expand All @@ -26,7 +27,7 @@ func InMastermindsSemverRange(semverRange *mmsemver.Constraints) Predicate[declc
}
}

func InAnyChannel(channels ...declcfg.Channel) Predicate[declcfg.Bundle] {
func InAnyChannel(channels ...declcfg.Channel) filter.Predicate[declcfg.Bundle] {
return func(bundle declcfg.Bundle) bool {
for _, ch := range channels {
for _, entry := range ch.Entries {
Expand Down
79 changes: 0 additions & 79 deletions internal/catalogmetadata/filter/filter_test.go

This file was deleted.

7 changes: 4 additions & 3 deletions internal/catalogmetadata/filter/successors.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ import (
"github.com/operator-framework/operator-registry/alpha/declcfg"

ocv1 "github.com/operator-framework/operator-controller/api/v1"
"github.com/operator-framework/operator-controller/internal/util/filter"
)

func SuccessorsOf(installedBundle ocv1.BundleMetadata, channels ...declcfg.Channel) (Predicate[declcfg.Bundle], error) {
func SuccessorsOf(installedBundle ocv1.BundleMetadata, channels ...declcfg.Channel) (filter.Predicate[declcfg.Bundle], error) {
installedBundleVersion, err := mmsemver.NewVersion(installedBundle.Version)
if err != nil {
return nil, fmt.Errorf("parsing installed bundle %q version %q: %w", installedBundle.Name, installedBundle.Version, err)
Expand All @@ -28,13 +29,13 @@ func SuccessorsOf(installedBundle ocv1.BundleMetadata, channels ...declcfg.Chann
}

// We need either successors or current version (no upgrade)
return Or(
return filter.Or(
successorsPredicate,
InMastermindsSemverRange(installedVersionConstraint),
), nil
}

func legacySuccessor(installedBundle ocv1.BundleMetadata, channels ...declcfg.Channel) (Predicate[declcfg.Bundle], error) {
func legacySuccessor(installedBundle ocv1.BundleMetadata, channels ...declcfg.Channel) (filter.Predicate[declcfg.Bundle], error) {
installedBundleVersion, err := bsemver.Parse(installedBundle.Version)
if err != nil {
return nil, fmt.Errorf("error parsing installed bundle version: %w", err)
Expand Down
3 changes: 2 additions & 1 deletion internal/catalogmetadata/filter/successors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
ocv1 "github.com/operator-framework/operator-controller/api/v1"
"github.com/operator-framework/operator-controller/internal/bundleutil"
"github.com/operator-framework/operator-controller/internal/catalogmetadata/compare"
"github.com/operator-framework/operator-controller/internal/util/filter"
)

func TestSuccessorsPredicate(t *testing.T) {
Expand Down Expand Up @@ -160,7 +161,7 @@ func TestSuccessorsPredicate(t *testing.T) {
for _, bundle := range bundleSet {
allBundles = append(allBundles, bundle)
}
result := Filter(allBundles, successors)
result := filter.InPlace(allBundles, successors)

// sort before comparison for stable order
slices.SortFunc(result, compare.ByVersion)
Expand Down
7 changes: 4 additions & 3 deletions internal/resolve/catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/operator-framework/operator-controller/internal/bundleutil"
"github.com/operator-framework/operator-controller/internal/catalogmetadata/compare"
"github.com/operator-framework/operator-controller/internal/catalogmetadata/filter"
filterutil "github.com/operator-framework/operator-controller/internal/util/filter"
)

type ValidationFunc func(*declcfg.Bundle) error
Expand Down Expand Up @@ -75,7 +76,7 @@ func (r *CatalogResolver) Resolve(ctx context.Context, ext *ocv1.ClusterExtensio

var catStats []*catStat

resolvedBundles := []foundBundle{}
var resolvedBundles []foundBundle
var priorDeprecation *declcfg.Deprecation

listOptions := []client.ListOption{
Expand All @@ -96,7 +97,7 @@ func (r *CatalogResolver) Resolve(ctx context.Context, ext *ocv1.ClusterExtensio
cs.PackageFound = true
cs.TotalBundles = len(packageFBC.Bundles)

var predicates []filter.Predicate[declcfg.Bundle]
var predicates []filterutil.Predicate[declcfg.Bundle]
if len(channels) > 0 {
channelSet := sets.New(channels...)
filteredChannels := slices.DeleteFunc(packageFBC.Channels, func(c declcfg.Channel) bool {
Expand All @@ -118,7 +119,7 @@ func (r *CatalogResolver) Resolve(ctx context.Context, ext *ocv1.ClusterExtensio
}

// Apply the predicates to get the candidate bundles
packageFBC.Bundles = filter.Filter(packageFBC.Bundles, filter.And(predicates...))
packageFBC.Bundles = filterutil.InPlace(packageFBC.Bundles, filterutil.And(predicates...))
cs.MatchedBundles = len(packageFBC.Bundles)
if len(packageFBC.Bundles) == 0 {
return nil
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
package filter

import (
"slices"
)
import "slices"

// Predicate returns true if the object should be kept when filtering
type Predicate[T any] func(entity T) bool

// Filter filters a slice accordingly to
func Filter[T any](in []T, test Predicate[T]) []T {
return slices.DeleteFunc(in, Not(test))
}

func And[T any](predicates ...Predicate[T]) Predicate[T] {
return func(obj T) bool {
for _, predicate := range predicates {
Expand Down Expand Up @@ -39,3 +32,21 @@ func Not[T any](predicate Predicate[T]) Predicate[T] {
return !predicate(obj)
}
}

// Filter creates a new slice with all elements from s for which the test returns true
func Filter[T any](s []T, test Predicate[T]) []T {
var out []T
for i := 0; i < len(s); i++ {
if test(s[i]) {
out = append(out, s[i])
}
}
return slices.Clip(out)
}

// InPlace modifies s by removing any element for which test returns false.
// InPlace zeroes the elements between the new length and the original length in s.
// The returned slice is of the new length.
func InPlace[T any](s []T, test Predicate[T]) []T {
return slices.DeleteFunc(s, Not(test))
}
Loading

0 comments on commit 9864ba7

Please sign in to comment.