diff --git a/pkg/reconciler/configuration/configuration.go b/pkg/reconciler/configuration/configuration.go index 5405c9a6f38d..decce9eb764d 100644 --- a/pkg/reconciler/configuration/configuration.go +++ b/pkg/reconciler/configuration/configuration.go @@ -127,7 +127,7 @@ func (c *Reconciler) ReconcileKind(ctx context.Context, config *v1.Configuration // findAndSetLatestReadyRevision finds the last ready revision and sets LatestReadyRevisionName to it. func (c *Reconciler) findAndSetLatestReadyRevision(ctx context.Context, config *v1.Configuration) error { - sortedRevisions, err := c.getSortedCreatedRevisions(config) + sortedRevisions, err := c.getSortedCreatedRevisions(ctx, config) if err != nil { return err } @@ -148,33 +148,38 @@ func (c *Reconciler) findAndSetLatestReadyRevision(ctx context.Context, config * // getSortedCreatedRevisions returns the list of created revisions sorted in descending // generation order between the generation of the latest ready revision and config's generation (both inclusive). -func (c *Reconciler) getSortedCreatedRevisions(config *v1.Configuration) ([]*v1.Revision, error) { +func (c *Reconciler) getSortedCreatedRevisions(ctx context.Context, config *v1.Configuration) ([]*v1.Revision, error) { + logger := logging.FromContext(ctx) lister := c.revisionLister.Revisions(config.Namespace) configSelector := labels.SelectorFromSet(labels.Set{ serving.ConfigurationLabelKey: config.Name, }) if config.Status.LatestReadyRevisionName != "" { lrr, err := lister.Get(config.Status.LatestReadyRevisionName) + // Record the error and continue because we still want to set the LRR to the correct revision. if err != nil { - return nil, err - } - start := lrr.Generation - var generations []string - for i := start; i <= int64(config.Generation); i++ { - generations = append(generations, strconv.FormatInt(i, 10)) - } + // If the user deletes the LatestReadyRevision then this may return an error due to the + // dangling reference. Proceed to calculate the next-latest ready revision so that the + // caller can synthesize a new Revision at the current generation to replace the one deleted. + logger.Errorf("Error getting latest ready revision %q: %v", config.Status.LatestReadyRevisionName, err) + } else { + start := lrr.Generation + var generations []string + for i := start; i <= int64(config.Generation); i++ { + generations = append(generations, strconv.FormatInt(i, 10)) + } - // Add an "In" filter so that the configurations we get back from List have generation - // in range (config's latest ready generation, config's generation] - generationKey := serving.ConfigurationGenerationLabelKey - inReq, err := labels.NewRequirement(generationKey, - selection.In, - generations, - ) - if err != nil { - return nil, err + // Add an "In" filter so that the configurations we get back from List have generation + // in range (config's latest ready generation, config's generation] + generationKey := serving.ConfigurationGenerationLabelKey + inReq, err := labels.NewRequirement(generationKey, + selection.In, + generations, + ) + if err == nil { + configSelector = configSelector.Add(*inReq) + } } - configSelector = configSelector.Add(*inReq) } list, err := lister.List(configSelector) diff --git a/pkg/reconciler/configuration/configuration_test.go b/pkg/reconciler/configuration/configuration_test.go index 7a2f2f8de0c1..7bd8575a0762 100644 --- a/pkg/reconciler/configuration/configuration_test.go +++ b/pkg/reconciler/configuration/configuration_test.go @@ -468,6 +468,35 @@ func TestReconcile(t *testing.T) { Eventf(corev1.EventTypeNormal, "LatestReadyUpdate", "LatestReadyRevisionName updated to %q", "revnotready-00002"), }, Key: "foo/revnotready", + }, { + Name: "current LRR doesn't exist, LCR is ready", + Objects: []runtime.Object{ + cfg("lrrnotexist", "foo", 2, + WithLatestCreated("lrrnotexist-00002"), + WithLatestReady("lrrnotexist-00001"), WithObservedGen, func(cfg *v1.Configuration) { + cfg.Spec.GetTemplate().Name = "lrrnotexist-00002" + }, + ), + rev("lrrnotexist", "foo", 1, + WithRevName("lrrnotexist-00000"), + WithCreationTimestamp(now), MarkRevisionReady), + rev("lrrnotexist", "foo", 2, + WithRevName("lrrnotexist-00002"), + WithCreationTimestamp(now), MarkRevisionReady), + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: cfg("lrrnotexist", "foo", 2, + WithLatestCreated("lrrnotexist-00002"), + WithLatestReady("lrrnotexist-00002"), + WithObservedGen, func(cfg *v1.Configuration) { + cfg.Spec.GetTemplate().Name = "lrrnotexist-00002" + }, + ), + }}, + WantEvents: []string{ + Eventf(corev1.EventTypeNormal, "LatestReadyUpdate", "LatestReadyRevisionName updated to %q", "lrrnotexist-00002"), + }, + Key: "foo/lrrnotexist", }} table.Test(t, MakeFactory(func(ctx context.Context, listers *Listers, cmw configmap.Watcher) controller.Reconciler {