Skip to content

Commit 17e48e7

Browse files
njhaleopenshift-cherrypick-robot
authored andcommitted
fix(operator): remove broken thread-safety (#2697)
The thread-safety logic is flawed and can prevent Operator resources from being reconciled when component resources are updated. It also ensures idempotence when enqueuing a resource for reconciliation; In other words, enqueuing no-ops if the given resource is already in the queue. The underlying queue will ensure a reconciler never races itself when processing a given resource event. Signed-off-by: Nick Hale <[email protected]> Upstream-repository: operator-lifecycle-manager Upstream-commit: 3807cc1a01619ddf857009c72ca1712746e8fc01
1 parent 0a0de85 commit 17e48e7

File tree

3 files changed

+5
-106
lines changed

3 files changed

+5
-106
lines changed

staging/operator-lifecycle-manager/pkg/controller/operators/operator_controller.go

Lines changed: 2 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package operators
33
import (
44
"context"
55
"fmt"
6-
"sync"
76

87
"github.com/go-logr/logr"
98
appsv1 "k8s.io/api/apps/v1"
@@ -14,7 +13,6 @@ import (
1413
"k8s.io/apimachinery/pkg/api/meta"
1514
"k8s.io/apimachinery/pkg/labels"
1615
"k8s.io/apimachinery/pkg/runtime"
17-
"k8s.io/apimachinery/pkg/types"
1816
kscheme "k8s.io/client-go/kubernetes/scheme"
1917
apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
2018
ctrl "sigs.k8s.io/controller-runtime"
@@ -50,10 +48,6 @@ type OperatorReconciler struct {
5048

5149
log logr.Logger
5250
factory decorators.OperatorFactory
53-
54-
// last observed resourceVersion for known Operators
55-
lastResourceVersion map[types.NamespacedName]string
56-
mu sync.RWMutex
5751
}
5852

5953
// +kubebuilder:rbac:groups=operators.coreos.com,resources=operators,verbs=create;update;patch;delete
@@ -105,9 +99,8 @@ func NewOperatorReconciler(cli client.Client, log logr.Logger, scheme *runtime.S
10599
return &OperatorReconciler{
106100
Client: cli,
107101

108-
log: log,
109-
factory: factory,
110-
lastResourceVersion: map[types.NamespacedName]string{},
102+
log: log,
103+
factory: factory,
111104
}, nil
112105
}
113106

@@ -139,16 +132,6 @@ func (r *OperatorReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
139132
}
140133
}
141134

142-
rv, ok := r.getLastResourceVersion(req.NamespacedName)
143-
if !create && ok && rv == in.ResourceVersion {
144-
log.V(1).Info("Operator is already up-to-date")
145-
return reconcile.Result{}, nil
146-
}
147-
148-
// Set the cached resource version to 0 so we can handle
149-
// the race with requests enqueuing via mapComponentRequests
150-
r.setLastResourceVersion(req.NamespacedName, "0")
151-
152135
// Wrap with convenience decorator
153136
operator, err := r.factory.NewOperator(in)
154137
if err != nil {
@@ -174,11 +157,6 @@ func (r *OperatorReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
174157
}
175158
}
176159

177-
// Only set the resource version if it already exists.
178-
// If it does not exist, it means mapComponentRequests was called
179-
// while we were reconciling and we need to reconcile again
180-
r.setLastResourceVersionIfExists(req.NamespacedName, operator.GetResourceVersion())
181-
182160
return ctrl.Result{}, nil
183161
}
184162

@@ -242,33 +220,6 @@ func (r *OperatorReconciler) hasExistingComponents(ctx context.Context, name str
242220
return false, nil
243221
}
244222

245-
func (r *OperatorReconciler) getLastResourceVersion(name types.NamespacedName) (string, bool) {
246-
r.mu.RLock()
247-
defer r.mu.RUnlock()
248-
rv, ok := r.lastResourceVersion[name]
249-
return rv, ok
250-
}
251-
252-
func (r *OperatorReconciler) setLastResourceVersion(name types.NamespacedName, rv string) {
253-
r.mu.Lock()
254-
defer r.mu.Unlock()
255-
r.lastResourceVersion[name] = rv
256-
}
257-
258-
func (r *OperatorReconciler) setLastResourceVersionIfExists(name types.NamespacedName, rv string) {
259-
r.mu.Lock()
260-
defer r.mu.Unlock()
261-
if _, ok := r.lastResourceVersion[name]; ok {
262-
r.lastResourceVersion[name] = rv
263-
}
264-
}
265-
266-
func (r *OperatorReconciler) unsetLastResourceVersion(name types.NamespacedName) {
267-
r.mu.Lock()
268-
defer r.mu.Unlock()
269-
delete(r.lastResourceVersion, name)
270-
}
271-
272223
func (r *OperatorReconciler) mapComponentRequests(obj client.Object) []reconcile.Request {
273224
var requests []reconcile.Request
274225
if obj == nil {
@@ -277,8 +228,6 @@ func (r *OperatorReconciler) mapComponentRequests(obj client.Object) []reconcile
277228

278229
labels := decorators.OperatorNames(obj.GetLabels())
279230
for _, name := range labels {
280-
// unset the last recorded resource version so the Operator will reconcile
281-
r.unsetLastResourceVersion(name)
282231
requests = append(requests, reconcile.Request{NamespacedName: name})
283232
}
284233

staging/operator-lifecycle-manager/test/e2e/operator_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ var _ = Describe("Operator API", func() {
7070
// 14. Ensure the reference to ns-a is eventually removed from o's status.components.refs field
7171
// 15. Delete o
7272
// 16. Ensure o is not re-created
73+
// issue: https://github.com/operator-framework/operator-lifecycle-manager/issues/2628
7374
It("should surface components in its status", func() {
7475
o := &operatorsv1.Operator{}
7576
o.SetName(genName("o-"))

vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/operators/operator_controller.go

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

0 commit comments

Comments
 (0)