Skip to content

Commit

Permalink
feat(resolver): Move all predicates to its own file
Browse files Browse the repository at this point in the history
Signed-off-by: Anik Bhattacharjee <anikbhattacharya93@gmail.com>
  • Loading branch information
anik120 committed Jul 15, 2021
1 parent f87b076 commit 86998b0
Show file tree
Hide file tree
Showing 5 changed files with 303 additions and 286 deletions.
182 changes: 0 additions & 182 deletions pkg/controller/registry/resolver/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"sync"
"time"

"github.com/blang/semver/v4"
"github.com/sirupsen/logrus"

"github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/listers/operators/v1alpha1"
Expand Down Expand Up @@ -387,16 +386,6 @@ func (s SortableSnapshots) Swap(i, j int) {
s.snapshots[i], s.snapshots[j] = s.snapshots[j], s.snapshots[i]
}

type OperatorPredicateFunc func(*Operator) bool

func (opf OperatorPredicateFunc) Test(o *Operator) bool {
return opf(o)
}

type OperatorPredicate interface {
Test(*Operator) bool
}

func (s *CatalogSnapshot) Find(p ...OperatorPredicate) []*Operator {
s.m.RLock()
defer s.m.RUnlock()
Expand All @@ -420,155 +409,6 @@ func (f EmptyOperatorFinder) Find(...OperatorPredicate) []*Operator {
return nil
}

func WithCSVName(name string) OperatorPredicate {
return OperatorPredicateFunc(func(o *Operator) bool {
return o.name == name
})
}

func WithChannel(channel string) OperatorPredicate {
return OperatorPredicateFunc(func(o *Operator) bool {
// all operators match the empty channel
if channel == "" {
return true
}
if o.bundle == nil {
return false
}
return o.bundle.ChannelName == channel
})
}

func WithPackage(pkg string) OperatorPredicate {
return OperatorPredicateFunc(func(o *Operator) bool {
for _, p := range o.Properties() {
if p.Type != opregistry.PackageType {
continue
}
var prop opregistry.PackageProperty
err := json.Unmarshal([]byte(p.Value), &prop)
if err != nil {
continue
}
if prop.PackageName == pkg {
return true
}
}
return o.Package() == pkg
})
}

func WithVersionInRange(r semver.Range) OperatorPredicate {
return OperatorPredicateFunc(func(o *Operator) bool {
for _, p := range o.Properties() {
if p.Type != opregistry.PackageType {
continue
}
var prop opregistry.PackageProperty
err := json.Unmarshal([]byte(p.Value), &prop)
if err != nil {
continue
}
ver, err := semver.Parse(prop.Version)
if err != nil {
continue
}
if r(ver) {
return true
}
}
return o.version != nil && r(*o.version)
})
}

func WithLabel(label string) OperatorPredicate {
return OperatorPredicateFunc(func(o *Operator) bool {
for _, p := range o.Properties() {
if p.Type != opregistry.LabelType {
continue
}
var prop opregistry.LabelProperty
err := json.Unmarshal([]byte(p.Value), &prop)
if err != nil {
continue
}
if prop.Label == label {
return true
}
}
return false
})
}

func WithCatalog(key registry.CatalogKey) OperatorPredicate {
return OperatorPredicateFunc(func(o *Operator) bool {
return key.Equal(o.SourceInfo().Catalog)
})
}

func ProvidingAPI(api opregistry.APIKey) OperatorPredicate {
return OperatorPredicateFunc(func(o *Operator) bool {
for _, p := range o.Properties() {
if p.Type != opregistry.GVKType {
continue
}
var prop opregistry.GVKProperty
err := json.Unmarshal([]byte(p.Value), &prop)
if err != nil {
continue
}
if prop.Kind == api.Kind && prop.Version == api.Version && prop.Group == api.Group {
return true
}
}
return false
})
}

func SkipRangeIncludes(version semver.Version) OperatorPredicate {
return OperatorPredicateFunc(func(o *Operator) bool {
// TODO: lift range parsing to OperatorSurface
semverRange, err := semver.ParseRange(o.bundle.SkipRange)
return err == nil && semverRange(version)
})
}

func Replaces(name string) OperatorPredicate {
return OperatorPredicateFunc(func(o *Operator) bool {
if o.Replaces() == name {
return true
}
for _, s := range o.bundle.Skips {
if s == name {
return true
}
}
return false
})
}

func And(p ...OperatorPredicate) OperatorPredicate {
return OperatorPredicateFunc(func(o *Operator) bool {
for _, l := range p {
if l.Test(o) == false {
return false
}
}
return true
})
}

func Or(p ...OperatorPredicate) OperatorPredicate {
return OperatorPredicateFunc(func(o *Operator) bool {
for _, l := range p {
if l.Test(o) == true {
return true
}
}
return false
})
}

func AtLeast(n int, operators []*Operator) ([]*Operator, error) {
if len(operators) < n {
return nil, fmt.Errorf("expected at least %d operator(s), got %d", n, len(operators))
Expand Down Expand Up @@ -596,25 +436,3 @@ func Filter(operators []*Operator, p ...OperatorPredicate) []*Operator {
func Matches(o *Operator, p ...OperatorPredicate) bool {
return And(p...).Test(o)
}

func True() OperatorPredicate {
return OperatorPredicateFunc(func(*Operator) bool {
return true
})
}

func False() OperatorPredicate {
return OperatorPredicateFunc(func(*Operator) bool {
return false
})
}

func CountingPredicate(p OperatorPredicate, n *int) OperatorPredicate {
return OperatorPredicateFunc(func(o *Operator) bool {
if p.Test(o) {
*n++
return true
}
return false
})
}
46 changes: 0 additions & 46 deletions pkg/controller/registry/resolver/cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -339,49 +339,3 @@ func TestStripPluralRequiredAndProvidedAPIKeys(t *testing.T) {
assert.Equal(t, "K.v1.g", result[0].providedAPIs.String())
assert.Equal(t, "K2.v2.g2", result[0].requiredAPIs.String())
}

func TestCountingPredicate(t *testing.T) {
for _, tc := range []struct {
Name string
TestResults []bool
Expected int
}{
{
Name: "no increment on failure",
TestResults: []bool{false},
Expected: 0,
},
{
Name: "increment on success",
TestResults: []bool{true},
Expected: 1,
},
{
Name: "multiple increments",
TestResults: []bool{true, true},
Expected: 2,
},
{
Name: "no increment without test",
TestResults: nil,
Expected: 0,
},
} {
t.Run(tc.Name, func(t *testing.T) {
var (
n int
result bool
)

p := CountingPredicate(OperatorPredicateFunc(func(*Operator) bool {
return result
}), &n)

for _, result = range tc.TestResults {
p.Test(nil)
}

assert.Equal(t, tc.Expected, n)
})
}
}
58 changes: 0 additions & 58 deletions pkg/controller/registry/resolver/operators.go
Original file line number Diff line number Diff line change
Expand Up @@ -434,64 +434,6 @@ func (o *Operator) DependencyPredicates() (predicates []OperatorPredicate, err e
return
}

func PredicateForProperty(property *api.Property) (OperatorPredicate, error) {
if property == nil {
return nil, nil
}
p, ok := predicates[property.Type]
if !ok {
return nil, nil
}
return p(property.Value)
}

var predicates = map[string]func(string) (OperatorPredicate, error){
"olm.gvk.required": predicateForRequiredGVKProperty,
"olm.package.required": predicateForRequiredPackageProperty,
"olm.label.required": predicateForRequiredLabelProperty,
}

func predicateForRequiredGVKProperty(value string) (OperatorPredicate, error) {
var gvk struct {
Group string `json:"group"`
Version string `json:"version"`
Kind string `json:"kind"`
}
if err := json.Unmarshal([]byte(value), &gvk); err != nil {
return nil, err
}
return ProvidingAPI(opregistry.APIKey{
Group: gvk.Group,
Version: gvk.Version,
Kind: gvk.Kind,
}), nil
}

func predicateForRequiredPackageProperty(value string) (OperatorPredicate, error) {
var pkg struct {
PackageName string `json:"packageName"`
VersionRange string `json:"versionRange"`
}
if err := json.Unmarshal([]byte(value), &pkg); err != nil {
return nil, err
}
ver, err := semver.ParseRange(pkg.VersionRange)
if err != nil {
return nil, err
}
return And(WithPackage(pkg.PackageName), WithVersionInRange(ver)), nil
}

func predicateForRequiredLabelProperty(value string) (OperatorPredicate, error) {
var label struct {
Label string `json:"label"`
}
if err := json.Unmarshal([]byte(value), &label); err != nil {
return nil, err
}
return WithLabel(label.Label), nil
}

func requiredAPIsToProperties(apis APISet) (out []*api.Property, err error) {
if len(apis) == 0 {
return
Expand Down
Loading

0 comments on commit 86998b0

Please sign in to comment.