Skip to content

Commit ed1ef13

Browse files
committed
update the revision controller to use the type moved latestrevision
1 parent 0a97fe4 commit ed1ef13

File tree

9 files changed

+244
-103
lines changed

9 files changed

+244
-103
lines changed

pkg/operator/apiserver/controllerset/apiservercontrollerset.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@ func (cs *APIServerControllerSet) WithRevisionController(
315315
secretGetter corev1client.SecretsGetter,
316316
) *APIServerControllerSet {
317317
cs.revisionController.controller = revisioncontroller.NewRevisionController(
318+
cs.name,
318319
targetNamespace,
319320
configMaps,
320321
secrets,

pkg/operator/configobserver/node/suppress_config_updates_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,10 @@ func TestSuppressConfigUpdateUntilSameProfileFunc(t *testing.T) {
212212
}
213213
}
214214
staticPodOperatorStatus := operatorv1.StaticPodOperatorStatus{
215-
LatestAvailableRevision: int32(len(testCase.observedConfigRevisions) + 1),
216-
NodeStatuses: nodesStatuses,
215+
OperatorStatus: operatorv1.OperatorStatus{
216+
LatestAvailableRevision: int32(len(testCase.observedConfigRevisions) + 1),
217+
},
218+
NodeStatuses: nodesStatuses,
217219
}
218220

219221
operatorObservedConfig, err := json.Marshal(testCase.operatorSpecObservedConfig)

pkg/operator/revisioncontroller/revision_controller.go

Lines changed: 79 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,25 @@ import (
77
"strings"
88
"time"
99

10-
"k8s.io/klog/v2"
11-
1210
operatorv1 "github.com/openshift/api/operator/v1"
13-
corev1 "k8s.io/api/core/v1"
14-
"k8s.io/apimachinery/pkg/api/equality"
15-
apierrors "k8s.io/apimachinery/pkg/api/errors"
16-
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
17-
"k8s.io/client-go/informers"
18-
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
19-
11+
applyoperatorv1 "github.com/openshift/client-go/operator/applyconfigurations/operator/v1"
2012
"github.com/openshift/library-go/pkg/controller/factory"
2113
"github.com/openshift/library-go/pkg/operator/condition"
2214
"github.com/openshift/library-go/pkg/operator/events"
2315
"github.com/openshift/library-go/pkg/operator/management"
2416
"github.com/openshift/library-go/pkg/operator/resource/resourceapply"
2517
"github.com/openshift/library-go/pkg/operator/v1helpers"
18+
corev1 "k8s.io/api/core/v1"
19+
"k8s.io/apimachinery/pkg/api/equality"
20+
apierrors "k8s.io/apimachinery/pkg/api/errors"
21+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
22+
"k8s.io/client-go/informers"
23+
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
24+
"k8s.io/klog/v2"
2625
)
2726

2827
// LatestRevisionClient is an operator client for an operator status with a latest revision field.
28+
// Deprecated
2929
type LatestRevisionClient interface {
3030
v1helpers.OperatorClient
3131

@@ -39,14 +39,16 @@ type LatestRevisionClient interface {
3939
// of them. If the original resources changes, the revision counter is increased, stored in LatestAvailableRevision
4040
// field of the operator config and new snapshots suffixed by the revision are created.
4141
type RevisionController struct {
42+
controllerInstanceName string
43+
4244
targetNamespace string
4345
// configMaps is the list of configmaps that are directly copied.A different actor/controller modifies these.
4446
// the first element should be the configmap that contains the static pod manifest
4547
configMaps []RevisionResource
4648
// secrets is a list of secrets that are directly copied for the current values. A different actor/controller modifies these.
4749
secrets []RevisionResource
4850

49-
operatorClient LatestRevisionClient
51+
operatorClient v1helpers.OperatorClient
5052
configMapGetter corev1client.ConfigMapsGetter
5153
secretGetter corev1client.SecretsGetter
5254

@@ -63,11 +65,12 @@ type PreconditionFunc func(ctx context.Context) (bool, error)
6365

6466
// NewRevisionController create a new revision controller.
6567
func NewRevisionController(
68+
instanceName string,
6669
targetNamespace string,
6770
configMaps []RevisionResource,
6871
secrets []RevisionResource,
6972
kubeInformersForTargetNamespace informers.SharedInformerFactory,
70-
operatorClient LatestRevisionClient,
73+
operatorClient v1helpers.OperatorClient,
7174
configMapGetter corev1client.ConfigMapsGetter,
7275
secretGetter corev1client.SecretsGetter,
7376
eventRecorder events.Recorder,
@@ -80,9 +83,10 @@ func NewRevisionController(
8083
}
8184

8285
c := &RevisionController{
83-
targetNamespace: targetNamespace,
84-
configMaps: configMaps,
85-
secrets: secrets,
86+
controllerInstanceName: factory.ControllerInstanceName(instanceName, "RevisionController"),
87+
targetNamespace: targetNamespace,
88+
configMaps: configMaps,
89+
secrets: secrets,
8690

8791
operatorClient: operatorClient,
8892
configMapGetter: configMapGetter,
@@ -106,18 +110,17 @@ func NewRevisionController(
106110

107111
// createRevisionIfNeeded takes care of creating content for the static pods to use.
108112
// returns whether or not requeue and if an error happened when updating status. Normally it updates status itself.
109-
func (c RevisionController) createRevisionIfNeeded(ctx context.Context, recorder events.Recorder, latestAvailableRevision int32, resourceVersion string) (bool, error) {
110-
isLatestRevisionCurrent, requiredIsNotFound, reason := c.isLatestRevisionCurrent(ctx, latestAvailableRevision)
113+
func (c RevisionController) createRevisionIfNeeded(ctx context.Context, recorder events.Recorder, currentLastAvailableRevision int32) (wroteStatus bool, requeue bool, err error) {
114+
isLatestRevisionCurrent, requiredIsNotFound, reason := c.isLatestRevisionCurrent(ctx, currentLastAvailableRevision)
111115

112116
// check to make sure that the latestRevision has the exact content we expect. No mutation here, so we start creating the next Revision only when it is required
113117
if isLatestRevisionCurrent {
114-
klog.V(4).Infof("Returning early, %d triggered and up to date", latestAvailableRevision)
115-
return false, nil
118+
klog.V(4).Infof("Returning early, %d triggered and up to date", currentLastAvailableRevision)
119+
return false, false, nil
116120
}
117121

118-
nextRevision := latestAvailableRevision + 1
122+
nextRevision := currentLastAvailableRevision + 1
119123
var createdNewRevision bool
120-
var err error
121124
// check to make sure no new revision is created when a required object is missing
122125
if requiredIsNotFound {
123126
err = fmt.Errorf("%v", reason)
@@ -127,36 +130,43 @@ func (c RevisionController) createRevisionIfNeeded(ctx context.Context, recorder
127130
}
128131

129132
if err != nil {
130-
cond := operatorv1.OperatorCondition{
131-
Type: "RevisionControllerDegraded",
132-
Status: operatorv1.ConditionTrue,
133-
Reason: "ContentCreationError",
134-
Message: err.Error(),
135-
}
136-
if _, _, updateError := v1helpers.UpdateStatus(ctx, c.operatorClient, v1helpers.UpdateConditionFn(cond)); updateError != nil {
133+
status := applyoperatorv1.OperatorStatus().
134+
WithConditions(applyoperatorv1.OperatorCondition().
135+
WithType(condition.RevisionControllerDegradedConditionType).
136+
WithStatus(operatorv1.ConditionTrue).
137+
WithReason("ContentCreationError").
138+
WithMessage(err.Error()),
139+
).
140+
WithLatestAvailableRevision(currentLastAvailableRevision)
141+
// different fieldmanager is used to conflict. We could also choose to *always* set the lastavailablerevision
142+
// update this tomorrow, that's probably better.
143+
updateError := c.operatorClient.ApplyOperatorStatus(ctx, c.controllerInstanceName, status)
144+
if updateError != nil {
137145
recorder.Warningf("RevisionCreateFailed", "Failed to create revision %d: %v", nextRevision, err.Error())
138-
return true, updateError
146+
return true, true, updateError
139147
}
140-
return true, nil
148+
return true, true, nil
141149
}
142150

143151
if !createdNewRevision {
144152
klog.V(4).Infof("Revision %v not created", nextRevision)
145-
return false, nil
153+
return false, false, nil
146154
}
155+
147156
recorder.Eventf("RevisionTriggered", "new revision %d triggered by %q", nextRevision, reason)
148157

149-
cond := operatorv1.OperatorCondition{
150-
Type: "RevisionControllerDegraded",
151-
Status: operatorv1.ConditionFalse,
152-
}
153-
if _, updated, updateError := c.operatorClient.UpdateLatestRevisionOperatorStatus(ctx, nextRevision, v1helpers.UpdateConditionFn(cond)); updateError != nil {
154-
return true, updateError
155-
} else if updated {
156-
recorder.Eventf("RevisionCreate", "Revision %d created because %s", nextRevision, reason)
158+
status := applyoperatorv1.OperatorStatus().
159+
WithConditions(applyoperatorv1.OperatorCondition().
160+
WithType(condition.RevisionControllerDegradedConditionType).
161+
WithStatus(operatorv1.ConditionFalse),
162+
).
163+
WithLatestAvailableRevision(nextRevision)
164+
updateError := c.operatorClient.ApplyOperatorStatus(ctx, c.controllerInstanceName, status)
165+
if updateError != nil {
166+
return true, true, updateError
157167
}
158168

159-
return false, nil
169+
return true, false, nil
160170
}
161171

162172
func nameFor(name string, revision int32) string {
@@ -344,7 +354,8 @@ func (c RevisionController) getLatestAvailableRevision(ctx context.Context) (int
344354
}
345355

346356
func (c RevisionController) sync(ctx context.Context, syncCtx factory.SyncContext) error {
347-
operatorSpec, _, latestAvailableRevisionSeenByOperator, resourceVersion, err := c.operatorClient.GetLatestRevisionState()
357+
//operatorSpec, _, latestAvailableRevisionSeenByOperator, resourceVersion, err := c.operatorClient.GetLatestRevisionState()
358+
operatorSpec, operatorStatus, _, err := c.operatorClient.GetOperatorState()
348359
if err != nil {
349360
return err
350361
}
@@ -362,33 +373,47 @@ func (c RevisionController) sync(ctx context.Context, syncCtx factory.SyncContex
362373
if err != nil {
363374
return err
364375
}
365-
if latestObservedRevision != 0 && latestAvailableRevisionSeenByOperator != latestObservedRevision {
376+
if latestObservedRevision != 0 && operatorStatus.LatestAvailableRevision != latestObservedRevision {
366377
// Then make sure that revision number is what's in the operator status
367-
_, _, err := c.operatorClient.UpdateLatestRevisionOperatorStatus(ctx, latestObservedRevision)
378+
status := applyoperatorv1.OperatorStatus().
379+
WithConditions(applyoperatorv1.OperatorCondition().
380+
WithType(condition.RevisionControllerDegradedConditionType).
381+
WithStatus(operatorv1.ConditionFalse),
382+
).
383+
WithLatestAvailableRevision(latestObservedRevision)
384+
err := c.operatorClient.ApplyOperatorStatus(ctx, c.controllerInstanceName, status)
368385
if err != nil {
369386
return err
370387
}
371388
// regardless of whether we made a change, requeue to rerun the sync with updated status
372389
return factory.SyntheticRequeueError
373390
}
374391

375-
requeue, syncErr := c.createRevisionIfNeeded(ctx, syncCtx.Recorder(), latestAvailableRevisionSeenByOperator, resourceVersion)
392+
wroteStatus, requeue, syncErr := c.createRevisionIfNeeded(ctx, syncCtx.Recorder(), operatorStatus.LatestAvailableRevision)
393+
switch {
394+
case requeue && syncErr == nil:
395+
return factory.SyntheticRequeueError
396+
case syncErr != nil:
397+
// this is updated in status inside of createRevisionIfNeeded
398+
return syncErr
399+
400+
}
376401
if requeue && syncErr == nil {
377402
return factory.SyntheticRequeueError
378403
}
379-
err = syncErr
404+
if wroteStatus {
405+
return syncErr
406+
}
380407

381408
// update failing condition
382-
cond := operatorv1.OperatorCondition{
383-
Type: condition.RevisionControllerDegradedConditionType,
384-
Status: operatorv1.ConditionFalse,
385-
}
386-
if err != nil {
387-
cond.Status = operatorv1.ConditionTrue
388-
cond.Reason = "Error"
389-
cond.Message = err.Error()
390-
}
391-
if _, _, updateError := v1helpers.UpdateStatus(ctx, c.operatorClient, v1helpers.UpdateConditionFn(cond)); updateError != nil {
409+
status := applyoperatorv1.OperatorStatus().
410+
WithConditions(applyoperatorv1.OperatorCondition().
411+
WithType(condition.RevisionControllerDegradedConditionType).
412+
WithStatus(operatorv1.ConditionFalse),
413+
).
414+
WithLatestAvailableRevision(operatorStatus.LatestAvailableRevision)
415+
updateError := c.operatorClient.ApplyOperatorStatus(ctx, c.controllerInstanceName, status)
416+
if updateError != nil {
392417
if err == nil {
393418
return updateError
394419
}

0 commit comments

Comments
 (0)