Skip to content

Commit be8bd26

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 be8bd26

File tree

223 files changed

+16099
-8522
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

+16099
-8522
lines changed

go.mod

Lines changed: 3 additions & 1 deletion
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.20211013175853-311a12e3f5fc

go.sum

Lines changed: 25 additions & 77 deletions
Large diffs are not rendered by default.

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

Lines changed: 26 additions & 0 deletions
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

Lines changed: 88 additions & 4 deletions
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,19 @@ func sortChannel(bundles []*cache.Entry) ([]*cache.Entry, error) {
733736
return chains[0], nil
734737
}
735738

739+
var propertyFeatureGates = map[string]featuregate.Feature{
740+
property.TypeAllRequired: feature.CompoundConstraintsV1Alpha1,
741+
property.TypeAnyRequired: feature.CompoundConstraintsV1Alpha1,
742+
property.TypeNoneRequired: feature.CompoundConstraintsV1Alpha1,
743+
}
744+
736745
func DependencyPredicates(properties []*api.Property) ([]cache.Predicate, error) {
737746
var predicates []cache.Predicate
738747
for _, property := range properties {
748+
if gate, hasGate := propertyFeatureGates[property.Type]; hasGate && !feature.Gate.Enabled(gate) {
749+
return nil, fmt.Errorf("feature gate %q must be enabled for property %q", gate, property.Type)
750+
}
751+
739752
predicate, err := predicateForProperty(property)
740753
if err != nil {
741754
return nil, err
@@ -752,17 +765,22 @@ func predicateForProperty(property *api.Property) (cache.Predicate, error) {
752765
if property == nil {
753766
return nil, nil
754767
}
755-
p, ok := predicates[property.Type]
768+
p, ok := predicateParsers[property.Type]
756769
if !ok {
757770
return nil, nil
758771
}
759772
return p(property.Value)
760773
}
761774

762-
var predicates = map[string]func(string) (cache.Predicate, error){
775+
var predicateParsers = map[string]func(string) (cache.Predicate, error){
763776
"olm.gvk.required": predicateForRequiredGVKProperty,
764777
"olm.package.required": predicateForRequiredPackageProperty,
765778
"olm.label.required": predicateForRequiredLabelProperty,
779+
780+
// Feature gate CompoundConstraintsV1Alpha1.
781+
property.TypeAllRequired: compoundPredicateFuncForOp(cache.And),
782+
property.TypeAnyRequired: compoundPredicateFuncForOp(cache.Or),
783+
property.TypeNoneRequired: compoundPredicateFuncForOp(cache.Not),
766784
}
767785

768786
func predicateForRequiredGVKProperty(value string) (cache.Predicate, error) {
@@ -789,11 +807,15 @@ func predicateForRequiredPackageProperty(value string) (cache.Predicate, error)
789807
if err := json.Unmarshal([]byte(value), &pkg); err != nil {
790808
return nil, err
791809
}
792-
ver, err := semver.ParseRange(pkg.VersionRange)
810+
return newPackageRequiredPredicate(pkg.PackageName, pkg.VersionRange)
811+
}
812+
813+
func newPackageRequiredPredicate(name, verRange string) (cache.Predicate, error) {
814+
ver, err := semver.ParseRange(verRange)
793815
if err != nil {
794816
return nil, err
795817
}
796-
return cache.And(cache.PkgPredicate(pkg.PackageName), cache.VersionInRangePredicate(ver, pkg.VersionRange)), nil
818+
return cache.And(cache.PkgPredicate(name), cache.VersionInRangePredicate(ver, verRange)), nil
797819
}
798820

799821
func predicateForRequiredLabelProperty(value string) (cache.Predicate, error) {
@@ -806,6 +828,68 @@ func predicateForRequiredLabelProperty(value string) (cache.Predicate, error) {
806828
return cache.LabelPredicate(label.Label), nil
807829
}
808830

831+
func compoundPredicateFuncForOp(op func(p ...cache.Predicate) cache.Predicate) func(string) (cache.Predicate, error) {
832+
return func(value string) (cache.Predicate, error) {
833+
c, err := property.ParseCompound(property.Property{Value: json.RawMessage(value)})
834+
if err != nil {
835+
return nil, err
836+
}
837+
838+
preds, err := requiredGroupToPredicate(c, 0)
839+
if err != nil {
840+
return nil, err
841+
}
842+
843+
return op(preds...), nil
844+
}
845+
}
846+
847+
func requiredGroupToPredicate(c property.Constraints, iteration int) (preds []cache.Predicate, err error) {
848+
849+
if err := property.ValidateMaxDepth(iteration); err != nil {
850+
return nil, err
851+
}
852+
853+
for _, gvk := range c.GVKs {
854+
preds = append(preds, cache.ProvidingAPIPredicate(opregistry.APIKey{
855+
Group: gvk.Group,
856+
Version: gvk.Version,
857+
Kind: gvk.Kind,
858+
}))
859+
}
860+
for _, pkg := range c.Packages {
861+
pred, err := newPackageRequiredPredicate(pkg.PackageName, pkg.VersionRange)
862+
if err != nil {
863+
return nil, err
864+
}
865+
preds = append(preds, pred)
866+
}
867+
868+
for _, all := range c.All {
869+
sub, err := requiredGroupToPredicate(all, iteration+1)
870+
if err != nil {
871+
return nil, err
872+
}
873+
preds = append(preds, cache.And(sub...))
874+
}
875+
for _, any := range c.Any {
876+
sub, err := requiredGroupToPredicate(any, iteration+1)
877+
if err != nil {
878+
return nil, err
879+
}
880+
preds = append(preds, cache.Or(sub...))
881+
}
882+
for _, none := range c.None {
883+
sub, err := requiredGroupToPredicate(none, iteration+1)
884+
if err != nil {
885+
return nil, err
886+
}
887+
preds = append(preds, cache.Not(sub...))
888+
}
889+
890+
return preds, nil
891+
}
892+
809893
func newOperatorFromV1Alpha1CSV(csv *v1alpha1.ClusterServiceVersion) (*cache.Entry, error) {
810894
providedAPIs := cache.EmptyAPISet()
811895
for _, crdDef := range csv.Spec.CustomResourceDefinitions.Owned {

pkg/feature/feature.go

Lines changed: 10 additions & 6 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 3 additions & 3 deletions
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

Lines changed: 7 additions & 0 deletions
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

Lines changed: 6 additions & 2 deletions
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

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)