Skip to content

Commit 9eaf91f

Browse files
committed
resolve operators on catalog availability change
Signed-off-by: Ankita Thomas <[email protected]>
1 parent 4ea83e6 commit 9eaf91f

File tree

4 files changed

+132
-3
lines changed

4 files changed

+132
-3
lines changed

config/rbac/role.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ rules:
1212
verbs:
1313
- list
1414
- watch
15+
- apiGroups:
16+
- catalogd.operatorframework.io
17+
resources:
18+
- catalogsources
19+
verbs:
20+
- list
21+
- watch
1522
- apiGroups:
1623
- catalogd.operatorframework.io
1724
resources:

controllers/catalog_predicates.go

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package controllers
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/go-logr/logr"
8+
catalogd "github.com/operator-framework/catalogd/pkg/apis/core/v1beta1"
9+
operatorv1alpha1 "github.com/operator-framework/operator-controller/api/v1alpha1"
10+
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
11+
"k8s.io/apimachinery/pkg/types"
12+
"sigs.k8s.io/controller-runtime/pkg/client"
13+
"sigs.k8s.io/controller-runtime/pkg/event"
14+
"sigs.k8s.io/controller-runtime/pkg/handler"
15+
"sigs.k8s.io/controller-runtime/pkg/predicate"
16+
"sigs.k8s.io/controller-runtime/pkg/reconcile"
17+
)
18+
19+
// Predicate for reconciling operators when available (i.e. ready) catalogsources on cluster change
20+
type catalogReadyTransitionPredicate struct {
21+
predicate.Funcs
22+
catalogReady map[string]bool
23+
}
24+
25+
func newCatalogReadyTransitionPredicate() *catalogReadyTransitionPredicate {
26+
return &catalogReadyTransitionPredicate{
27+
catalogReady: map[string]bool{},
28+
}
29+
}
30+
31+
func (c *catalogReadyTransitionPredicate) Create(e event.CreateEvent) bool {
32+
fmt.Println("CreateEvent CatalogSource", e.Object.GetName())
33+
catalogReady, err := isCatalogReady(e.Object)
34+
if err != nil {
35+
fmt.Println(err)
36+
return false
37+
}
38+
c.catalogReady[e.Object.GetName()] = catalogReady
39+
return catalogReady
40+
}
41+
42+
func (c *catalogReadyTransitionPredicate) Update(e event.UpdateEvent) bool {
43+
fmt.Println("UpdateEvent CatalogSource", e.ObjectOld.GetName(), e.ObjectNew.GetName())
44+
oldCatalogReady, err := isCatalogReady(e.ObjectOld)
45+
if err != nil {
46+
fmt.Println(err)
47+
return false
48+
}
49+
50+
newCatalogReady, err := isCatalogReady(e.ObjectNew)
51+
if err != nil {
52+
fmt.Println(err)
53+
return false
54+
}
55+
56+
c.catalogReady[e.ObjectNew.GetName()] = newCatalogReady
57+
// TODO: determine if ready -> non-ready transition triggers reconcile with stale catalog contents
58+
return oldCatalogReady != newCatalogReady
59+
}
60+
61+
func (c *catalogReadyTransitionPredicate) Delete(e event.DeleteEvent) bool {
62+
fmt.Println("DeleteEvent CatalogSource", e.Object.GetName())
63+
delete(c.catalogReady, e.Object.GetName())
64+
return true
65+
}
66+
67+
func (c *catalogReadyTransitionPredicate) Generic(e event.GenericEvent) bool {
68+
fmt.Println("GenericEvent CatalogSource", e.Object.GetName())
69+
catalogReady, err := isCatalogReady(e.Object)
70+
if err != nil {
71+
fmt.Println(err)
72+
return false
73+
}
74+
predicateState := c.catalogReady[e.Object.GetName()] != catalogReady
75+
c.catalogReady[e.Object.GetName()] = catalogReady
76+
return predicateState
77+
}
78+
79+
func isCatalogReady(o client.Object) (bool, error) {
80+
catalog, ok := o.(*catalogd.CatalogSource)
81+
if !ok {
82+
return false, fmt.Errorf("wrong object type: not a catalogsource: %+v", o)
83+
}
84+
if len(catalog.Status.Conditions) > 0 {
85+
for _, cond := range catalog.Status.Conditions {
86+
if cond.Type == catalogd.TypeReady && cond.Status == v1.ConditionTrue {
87+
return true, nil
88+
}
89+
}
90+
}
91+
return false, nil
92+
}
93+
94+
// Generate reconcile requests for all operators affected by a catalog change
95+
func operatorRequestsForCatalog(ctx context.Context, c client.Client, logger logr.Logger) handler.MapFunc {
96+
return func(object client.Object) []reconcile.Request {
97+
// no way of associating an operator to a catalog so create reconcile requests for everything
98+
operators := operatorv1alpha1.OperatorList{}
99+
err := c.List(ctx, &operators)
100+
if err != nil {
101+
logger.Error(err, "unable to enqueue operators for catalog reconcile")
102+
return nil
103+
}
104+
var requests []reconcile.Request
105+
for _, op := range operators.Items {
106+
requests = append(requests, reconcile.Request{
107+
NamespacedName: types.NamespacedName{
108+
Namespace: op.GetNamespace(),
109+
Name: op.GetName(),
110+
},
111+
})
112+
}
113+
return requests
114+
}
115+
}

controllers/operator_controller.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ import (
2020
"context"
2121
"fmt"
2222

23+
catalogd "github.com/operator-framework/catalogd/pkg/apis/core/v1beta1"
2324
"github.com/operator-framework/deppy/pkg/deppy/solver"
25+
"github.com/operator-framework/operator-controller/controllers/validators"
2426
rukpakv1alpha1 "github.com/operator-framework/rukpak/api/v1alpha1"
2527
"k8s.io/apimachinery/pkg/api/equality"
2628
apimeta "k8s.io/apimachinery/pkg/api/meta"
@@ -31,10 +33,11 @@ import (
3133
utilerrors "k8s.io/apimachinery/pkg/util/errors"
3234
"k8s.io/utils/pointer"
3335
ctrl "sigs.k8s.io/controller-runtime"
36+
"sigs.k8s.io/controller-runtime/pkg/builder"
3437
"sigs.k8s.io/controller-runtime/pkg/client"
38+
"sigs.k8s.io/controller-runtime/pkg/handler"
3539
"sigs.k8s.io/controller-runtime/pkg/log"
36-
37-
"github.com/operator-framework/operator-controller/controllers/validators"
40+
"sigs.k8s.io/controller-runtime/pkg/source"
3841

3942
operatorsv1alpha1 "github.com/operator-framework/operator-controller/api/v1alpha1"
4043
"github.com/operator-framework/operator-controller/internal/resolution"
@@ -57,6 +60,7 @@ type OperatorReconciler struct {
5760

5861
//+kubebuilder:rbac:groups=catalogd.operatorframework.io,resources=bundlemetadata,verbs=list;watch
5962
//+kubebuilder:rbac:groups=catalogd.operatorframework.io,resources=packages,verbs=list;watch
63+
//+kubebuilder:rbac:groups=catalogd.operatorframework.io,resources=catalogsources,verbs=list;watch
6064

6165
func (r *OperatorReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
6266
l := log.FromContext(ctx).WithName("operator-controller")
@@ -294,6 +298,9 @@ func (r *OperatorReconciler) generateExpectedBundleDeployment(o operatorsv1alpha
294298
func (r *OperatorReconciler) SetupWithManager(mgr ctrl.Manager) error {
295299
err := ctrl.NewControllerManagedBy(mgr).
296300
For(&operatorsv1alpha1.Operator{}).
301+
Watches(source.NewKindWithCache(&catalogd.CatalogSource{}, mgr.GetCache()),
302+
handler.EnqueueRequestsFromMapFunc(operatorRequestsForCatalog(context.TODO(), mgr.GetClient(), mgr.GetLogger())),
303+
builder.WithPredicates(newCatalogReadyTransitionPredicate())).
297304
Owns(&rukpakv1alpha1.BundleDeployment{}).
298305
Complete(r)
299306

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ go 1.19
44

55
require (
66
github.com/blang/semver/v4 v4.0.0
7+
github.com/go-logr/logr v1.2.3
78
github.com/onsi/ginkgo/v2 v2.8.3
89
github.com/onsi/gomega v1.27.1
910
github.com/operator-framework/catalogd v0.1.3
@@ -26,7 +27,6 @@ require (
2627
github.com/evanphx/json-patch/v5 v5.6.0 // indirect
2728
github.com/fsnotify/fsnotify v1.6.0 // indirect
2829
github.com/go-air/gini v1.0.4 // indirect
29-
github.com/go-logr/logr v1.2.3 // indirect
3030
github.com/go-logr/zapr v1.2.3 // indirect
3131
github.com/go-openapi/jsonpointer v0.19.5 // indirect
3232
github.com/go-openapi/jsonreference v0.20.0 // indirect

0 commit comments

Comments
 (0)