Skip to content

Commit 7321b9a

Browse files
committed
wip remove phase hashing at CER applier
1 parent 55d9dfb commit 7321b9a

File tree

9 files changed

+358
-72
lines changed

9 files changed

+358
-72
lines changed

cmd/operator-controller/main.go

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,10 @@ type config struct {
106106
globalPullSecret string
107107
}
108108

109-
const authFilePrefix = "operator-controller-global-pull-secrets"
109+
const (
110+
authFilePrefix = "operator-controller-global-pull-secrets"
111+
fieldOwnerPrefix = "olm.operatorframework.io"
112+
)
110113

111114
// podNamespace checks whether the controller is running in a Pod vs.
112115
// being run locally by inspecting the namespace file that gets mounted
@@ -542,6 +545,7 @@ func setupBoxcutter(mgr manager.Manager, ceReconciler *controllers.ClusterExtens
542545
Scheme: mgr.GetScheme(),
543546
RevisionGenerator: rg,
544547
Preflights: preflights,
548+
FieldOwner: fmt.Sprintf("%s/clusterextension-controller", fieldOwnerPrefix),
545549
}
546550
ceReconciler.RevisionStatesGetter = &controllers.BoxcutterRevisionStatesGetter{Reader: mgr.GetClient()}
547551
ceReconciler.StorageMigrator = &applier.BoxcutterStorageMigrator{
@@ -550,11 +554,6 @@ func setupBoxcutter(mgr manager.Manager, ceReconciler *controllers.ClusterExtens
550554
RevisionGenerator: rg,
551555
}
552556

553-
// Boxcutter
554-
const (
555-
boxcutterSystemPrefixFieldOwner = "olm.operatorframework.io"
556-
)
557-
558557
discoveryClient, err := discovery.NewDiscoveryClientForConfig(mgr.GetConfig())
559558
if err != nil {
560559
return fmt.Errorf("unable to create discovery client: %w", err)
@@ -581,8 +580,8 @@ func setupBoxcutter(mgr manager.Manager, ceReconciler *controllers.ClusterExtens
581580
machinery.NewObjectEngine(
582581
mgr.GetScheme(), trackingCache, mgr.GetClient(),
583582
ownerhandling.NewNative(mgr.GetScheme()),
584-
machinery.NewComparator(ownerhandling.NewNative(mgr.GetScheme()), discoveryClient, mgr.GetScheme(), boxcutterSystemPrefixFieldOwner),
585-
boxcutterSystemPrefixFieldOwner, boxcutterSystemPrefixFieldOwner,
583+
machinery.NewComparator(ownerhandling.NewNative(mgr.GetScheme()), discoveryClient, mgr.GetScheme(), fieldOwnerPrefix),
584+
fieldOwnerPrefix, fieldOwnerPrefix,
586585
),
587586
validation.NewClusterPhaseValidator(mgr.GetRESTMapper(), mgr.GetClient()),
588587
),

internal/operator-controller/applier/boxcutter.go

Lines changed: 68 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import (
2929
"github.com/operator-framework/operator-controller/internal/operator-controller/labels"
3030
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/bundle/source"
3131
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/render"
32-
hashutil "github.com/operator-framework/operator-controller/internal/shared/util/hash"
3332
)
3433

3534
const (
@@ -202,6 +201,7 @@ type Boxcutter struct {
202201
Scheme *runtime.Scheme
203202
RevisionGenerator ClusterExtensionRevisionGenerator
204203
Preflights []Preflight
204+
FieldOwner string
205205
}
206206

207207
func (bc *Boxcutter) Apply(ctx context.Context, contentFS fs.FS, ext *ocv1.ClusterExtension, objectLabels, revisionAnnotations map[string]string) (bool, string, error) {
@@ -225,77 +225,98 @@ func (bc *Boxcutter) apply(ctx context.Context, contentFS fs.FS, ext *ocv1.Clust
225225
return false, "", err
226226
}
227227

228+
gvk, err := apiutil.GVKForObject(desiredRevision, bc.Scheme)
229+
if err != nil {
230+
return false, "", fmt.Errorf("getting GVK of ClusterExtensionRevision failed: %w", err)
231+
}
232+
233+
if err := controllerutil.SetControllerReference(ext, desiredRevision, bc.Scheme); err != nil {
234+
return false, "", fmt.Errorf("set ownerref: %w", err)
235+
}
236+
228237
// List all existing revisions
229238
existingRevisions, err := bc.getExistingRevisions(ctx, ext.GetName())
230239
if err != nil {
231240
return false, "", err
232241
}
233-
desiredHash := hashutil.DeepHashObject(desiredRevision.Spec.Phases)
234242

235-
// Sort into current and previous revisions.
236-
var (
237-
currentRevision *ocv1.ClusterExtensionRevision
238-
)
243+
currentRevision := &ocv1.ClusterExtensionRevision{}
239244
state := StateNeedsInstall
240-
if len(existingRevisions) > 0 {
241-
maybeCurrentRevision := existingRevisions[len(existingRevisions)-1]
242-
annotations := maybeCurrentRevision.GetAnnotations()
243-
if annotations != nil {
244-
if revisionHash, ok := annotations[RevisionHashAnnotation]; ok && revisionHash == desiredHash {
245-
currentRevision = &maybeCurrentRevision
245+
// check if we can update the current revision.
246+
if len(existingRevisions) > 0 { // nolint:nestif
247+
// try first to update the current revision.
248+
currentRevision = &existingRevisions[len(existingRevisions)-1]
249+
desiredRevision.Spec.Previous = currentRevision.Spec.Previous
250+
desiredRevision.Spec.Revision = currentRevision.Spec.Revision
251+
desiredRevision.Name = currentRevision.Name
252+
253+
obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(desiredRevision)
254+
if err != nil {
255+
return false, "", fmt.Errorf("converting ClusterExtensionRevision to unstructured failed: %w", err)
256+
}
257+
udr := &unstructured.Unstructured{Object: obj}
258+
udr.SetGroupVersionKind(gvk)
259+
if err = bc.Client.Patch(ctx, udr, client.Apply, client.FieldOwner(bc.FieldOwner), client.ForceOwnership); err != nil {
260+
if !apierrors.IsInvalid(err) {
261+
return false, "", fmt.Errorf("patching %s Revision: %w", desiredRevision.Name, err)
246262
}
263+
// We could not update the current revision due to trying to update an immutable field.
264+
// Therefore, we need to create a new revision.
265+
state = StateNeedsUpgrade
266+
} else {
267+
// inplace patch was successful, no changes in phases
268+
state = StateUnchanged
247269
}
248-
state = StateNeedsUpgrade
249270
}
250271

251-
// Preflights
252-
plainObjs := bc.getObjects(desiredRevision)
253-
for _, preflight := range bc.Preflights {
254-
if shouldSkipPreflight(ctx, preflight, ext, state) {
255-
continue
256-
}
257-
switch state {
258-
case StateNeedsInstall:
259-
err := preflight.Install(ctx, plainObjs)
260-
if err != nil {
261-
return false, "", err
272+
if state != StateUnchanged { // nolint:nestif
273+
// Preflights
274+
plainObjs := bc.getObjects(desiredRevision)
275+
for _, preflight := range bc.Preflights {
276+
if shouldSkipPreflight(ctx, preflight, ext, state) {
277+
continue
262278
}
263-
// TODO: jlanford's IDE says that "StateNeedsUpgrade" condition is always true, but
264-
// it isn't immediately obvious why that is. Perhaps len(existingRevisions) is
265-
// always greater than 0 (seems unlikely), or shouldSkipPreflight always returns
266-
// true (and we continue) when state == StateNeedsInstall?
267-
case StateNeedsUpgrade:
268-
err := preflight.Upgrade(ctx, plainObjs)
269-
if err != nil {
270-
return false, "", err
279+
switch state {
280+
case StateNeedsInstall:
281+
err := preflight.Install(ctx, plainObjs)
282+
if err != nil {
283+
return false, "", err
284+
}
285+
// TODO: jlanford's IDE says that "StateNeedsUpgrade" condition is always true, but
286+
// it isn't immediately obvious why that is. Perhaps len(existingRevisions) is
287+
// always greater than 0 (seems unlikely), or shouldSkipPreflight always returns
288+
// true (and we continue) when state == StateNeedsInstall?
289+
case StateNeedsUpgrade:
290+
err := preflight.Upgrade(ctx, plainObjs)
291+
if err != nil {
292+
return false, "", err
293+
}
271294
}
272295
}
273-
}
274296

275-
if currentRevision == nil {
276-
// all Revisions are outdated => create a new one.
297+
// need to create new revision
277298
prevRevisions := existingRevisions
278299
revisionNumber := latestRevisionNumber(prevRevisions) + 1
279300

280-
newRevision := desiredRevision
281-
newRevision.Name = fmt.Sprintf("%s-%d", ext.Name, revisionNumber)
282-
if newRevision.GetAnnotations() == nil {
283-
newRevision.Annotations = map[string]string{}
284-
}
285-
newRevision.Annotations[RevisionHashAnnotation] = desiredHash
286-
newRevision.Spec.Revision = revisionNumber
301+
desiredRevision.Name = fmt.Sprintf("%s-%d", ext.Name, revisionNumber)
302+
desiredRevision.Spec.Revision = revisionNumber
287303

288-
if err = bc.setPreviousRevisions(ctx, newRevision, prevRevisions); err != nil {
304+
if err = bc.setPreviousRevisions(ctx, desiredRevision, prevRevisions); err != nil {
289305
return false, "", fmt.Errorf("garbage collecting old Revisions: %w", err)
290306
}
291307

292-
if err := controllerutil.SetControllerReference(ext, newRevision, bc.Scheme); err != nil {
293-
return false, "", fmt.Errorf("set ownerref: %w", err)
308+
obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(desiredRevision)
309+
if err != nil {
310+
return false, "", fmt.Errorf("converting ClusterExtensionRevision to unstructured failed: %w", err)
294311
}
295-
if err := bc.Client.Create(ctx, newRevision); err != nil {
312+
udr := &unstructured.Unstructured{Object: obj}
313+
udr.SetGroupVersionKind(gvk)
314+
if err := bc.Client.Patch(ctx, udr, client.Apply, client.FieldOwner(bc.FieldOwner), client.ForceOwnership); err != nil {
296315
return false, "", fmt.Errorf("creating new Revision: %w", err)
297316
}
298-
currentRevision = newRevision
317+
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(udr.Object, currentRevision); err != nil {
318+
return false, "", fmt.Errorf("converting unstructured to ClusterExtensionRevision failed: %w", err)
319+
}
299320
}
300321

301322
progressingCondition := meta.FindStatusCondition(currentRevision.Status.Conditions, ocv1.TypeProgressing)

0 commit comments

Comments
 (0)