Skip to content

Commit e12a395

Browse files
committed
feat(resolver): resolve compound dep constraints from bundle properties
This is an alpha-gated feature. Signed-off-by: Eric Stroczynski <[email protected]>
1 parent 23d84fa commit e12a395

File tree

223 files changed

+16043
-8516
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

223 files changed

+16043
-8516
lines changed

go.mod

+3-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ require (
2525
github.com/onsi/gomega v1.13.0
2626
github.com/openshift/api v0.0.0-20200331152225-585af27e34fd
2727
github.com/openshift/client-go v0.0.0-20200326155132-2a6cd50aedd0
28-
github.com/operator-framework/api v0.10.3
28+
github.com/operator-framework/api v0.10.5
2929
github.com/operator-framework/operator-registry v1.17.5
3030
github.com/otiai10/copy v1.2.0
3131
github.com/pkg/errors v0.9.1
@@ -66,3 +66,5 @@ replace (
6666
// informers until it can be resolved upstream:
6767
sigs.k8s.io/controller-runtime v0.9.2 => github.com/benluddy/controller-runtime v0.9.3-0.20210720171926-9bcb99bd9bd3
6868
)
69+
70+
replace github.com/operator-framework/operator-registry => github.com/estroz/operator-registry v1.3.1-0.20211011195013-5ccff2185310

go.sum

+25-77
Large diffs are not rendered by default.

pkg/controller/registry/resolver/cache/predicates.go

+26
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,32 @@ func (p orPredicate) String() string {
282282
return b.String()
283283
}
284284

285+
func Not(p ...Predicate) Predicate {
286+
return notPredicate{
287+
predicates: p,
288+
}
289+
}
290+
291+
type notPredicate struct {
292+
predicates []Predicate
293+
}
294+
295+
func (p notPredicate) Test(o *Entry) bool {
296+
// !pred && !pred is equivalent to !(pred || pred).
297+
return !orPredicate{p.predicates}.Test(o)
298+
}
299+
300+
func (p notPredicate) String() string {
301+
var b bytes.Buffer
302+
for i, predicate := range p.predicates {
303+
b.WriteString(predicate.String())
304+
if i != len(p.predicates)-1 {
305+
b.WriteString(" and not ")
306+
}
307+
}
308+
return b.String()
309+
}
310+
285311
type booleanPredicate struct {
286312
result bool
287313
}

pkg/controller/registry/resolver/resolver.go

+83-2
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,15 @@ import (
1010
"github.com/blang/semver/v4"
1111
"github.com/sirupsen/logrus"
1212
utilerrors "k8s.io/apimachinery/pkg/util/errors"
13+
"k8s.io/component-base/featuregate"
1314

1415
"github.com/operator-framework/api/pkg/operators/v1alpha1"
1516
v1alpha1listers "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/listers/operators/v1alpha1"
1617
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/cache"
1718
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/projection"
1819
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/solver"
20+
"github.com/operator-framework/operator-lifecycle-manager/pkg/feature"
21+
"github.com/operator-framework/operator-registry/alpha/property"
1922
"github.com/operator-framework/operator-registry/pkg/api"
2023
opregistry "github.com/operator-framework/operator-registry/pkg/registry"
2124
)
@@ -733,9 +736,17 @@ func sortChannel(bundles []*cache.Entry) ([]*cache.Entry, error) {
733736
return chains[0], nil
734737
}
735738

739+
var propertyFeatureGates = map[string]featuregate.Feature{
740+
"olm.group.required": feature.CompoundConstraintsV1Alpha1,
741+
}
742+
736743
func DependencyPredicates(properties []*api.Property) ([]cache.Predicate, error) {
737744
var predicates []cache.Predicate
738745
for _, property := range properties {
746+
if gate, hasGate := propertyFeatureGates[property.Type]; hasGate && !feature.Gate.Enabled(gate) {
747+
return nil, fmt.Errorf("feature gate %q must be enabled for property %q", gate, property.Type)
748+
}
749+
739750
predicate, err := predicateForProperty(property)
740751
if err != nil {
741752
return nil, err
@@ -752,17 +763,19 @@ func predicateForProperty(property *api.Property) (cache.Predicate, error) {
752763
if property == nil {
753764
return nil, nil
754765
}
755-
p, ok := predicates[property.Type]
766+
p, ok := predicateParsers[property.Type]
756767
if !ok {
757768
return nil, nil
758769
}
759770
return p(property.Value)
760771
}
761772

762-
var predicates = map[string]func(string) (cache.Predicate, error){
773+
var predicateParsers = map[string]func(string) (cache.Predicate, error){
763774
"olm.gvk.required": predicateForRequiredGVKProperty,
764775
"olm.package.required": predicateForRequiredPackageProperty,
765776
"olm.label.required": predicateForRequiredLabelProperty,
777+
// Feature gate CompoundConstraintsV1Alpha1.
778+
"olm.group.required": predicateForRequiredGroupProperty,
766779
}
767780

768781
func predicateForRequiredGVKProperty(value string) (cache.Predicate, error) {
@@ -806,6 +819,74 @@ func predicateForRequiredLabelProperty(value string) (cache.Predicate, error) {
806819
return cache.LabelPredicate(label.Label), nil
807820
}
808821

822+
func predicateForRequiredGroupProperty(value string) (cache.Predicate, error) {
823+
gr, err := property.ParseGroupRequired(json.RawMessage(value))
824+
if err != nil {
825+
return nil, err
826+
}
827+
return requiredGroupToPredicate(gr, 0)
828+
}
829+
830+
func requiredGroupToPredicate(gr property.GroupRequired, iteration int) (sourcePredicate cache.Predicate, err error) {
831+
if err := property.ValidateMaxDepth(iteration); err != nil {
832+
return nil, err
833+
}
834+
835+
sourcePredicate = cache.True()
836+
837+
for _, and := range gr.And {
838+
sourcePredicate, err = logicalToPredicate(sourcePredicate, groupLogical(and), cache.And, iteration)
839+
if err != nil {
840+
return nil, err
841+
}
842+
}
843+
for _, or := range gr.Or {
844+
sourcePredicate, err = logicalToPredicate(sourcePredicate, groupLogical(or), cache.Or, iteration)
845+
if err != nil {
846+
return nil, err
847+
}
848+
}
849+
for _, not := range gr.Not {
850+
sourcePredicate, err = logicalToPredicate(sourcePredicate, groupLogical(not), cache.Not, iteration)
851+
if err != nil {
852+
return nil, err
853+
}
854+
}
855+
856+
return sourcePredicate, nil
857+
}
858+
859+
type groupLogical struct {
860+
Packages []property.PackageRequired
861+
GVKs []property.GVKRequired
862+
Groups []property.GroupRequired
863+
}
864+
865+
func logicalToPredicate(src cache.Predicate, gl groupLogical, op func(p ...cache.Predicate) cache.Predicate, iteration int) (cache.Predicate, error) {
866+
for _, gvk := range gl.GVKs {
867+
src = op(src, cache.ProvidingAPIPredicate(opregistry.APIKey{
868+
Group: gvk.Group,
869+
Version: gvk.Version,
870+
Kind: gvk.Kind,
871+
}))
872+
}
873+
for _, pkg := range gl.Packages {
874+
ver, err := semver.ParseRange(pkg.VersionRange)
875+
if err != nil {
876+
return nil, err
877+
}
878+
src = op(src, cache.PkgPredicate(pkg.PackageName), cache.VersionInRangePredicate(ver, pkg.VersionRange))
879+
}
880+
for _, g := range gl.Groups {
881+
pred, err := requiredGroupToPredicate(g, iteration+1)
882+
if err != nil {
883+
return nil, err
884+
}
885+
src = op(src, pred)
886+
}
887+
return src, nil
888+
}
889+
809890
func newOperatorFromV1Alpha1CSV(csv *v1alpha1.ClusterServiceVersion) (*cache.Entry, error) {
810891
providedAPIs := cache.EmptyAPISet()
811892
for _, crdDef := range csv.Spec.CustomResourceDefinitions.Owned {

pkg/feature/feature.go

+10-6
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,19 @@ import (
66
"k8s.io/component-base/featuregate"
77
)
88

9+
// MyFeature featuregate.Feature = "MyFeature"
10+
// owner: @username
11+
// alpha: v1.X
12+
// (see https://github.com/kubernetes/kubernetes/blob/master/pkg/features/kube_features.go)
913
const (
10-
// MyFeature featuregate.Feature = "MyFeature"
11-
// owner: @username
12-
// alpha: v1.X
13-
// (see https://github.com/kubernetes/kubernetes/blob/master/pkg/features/kube_features.go)
14-
1514
// OperatorLifecycleManagerV1 enables OLM's v1 APIs.
1615
// owner: @njhale
1716
// alpha: v0.15.0
1817
OperatorLifecycleManagerV1 featuregate.Feature = "OperatorLifecycleManagerV1"
18+
// CompoundConstraintsV1Alpha1 enables executing compound dependency constraints specified in operator bundles.
19+
// owner: @estroz
20+
// alpha: v0.20.0
21+
CompoundConstraintsV1Alpha1 featuregate.Feature = "CompoundConstraintsV1Alpha1"
1922
)
2023

2124
var (
@@ -35,5 +38,6 @@ func AddFlag(fs *pflag.FlagSet) {
3538
}
3639

3740
var featureGates = map[featuregate.Feature]featuregate.FeatureSpec{
38-
OperatorLifecycleManagerV1: {Default: true, LockToDefault: true, PreRelease: featuregate.GA},
41+
OperatorLifecycleManagerV1: {Default: true, LockToDefault: true, PreRelease: featuregate.GA},
42+
CompoundConstraintsV1Alpha1: {Default: false, LockToDefault: false, PreRelease: featuregate.Alpha},
3943
}

vendor/github.com/containerd/containerd/archive/tar_unix.go

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/containerd/containerd/content/local/store.go

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/containerd/containerd/metadata/containers.go

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/containerd/containerd/metadata/content.go

+3-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/containerd/containerd/remotes/docker/authorizer.go

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/containerd/containerd/remotes/docker/fetcher.go

+6-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/containerd/containerd/remotes/docker/pusher.go

+5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/containerd/containerd/remotes/docker/resolver.go

+17-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/containerd/containerd/version/version.go

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)