diff --git a/pkg/apis/serving/v1/revision_helpers.go b/pkg/apis/serving/v1/revision_helpers.go index effc224459c1..e561c7ae6495 100644 --- a/pkg/apis/serving/v1/revision_helpers.go +++ b/pkg/apis/serving/v1/revision_helpers.go @@ -128,11 +128,6 @@ func (r *Revision) GetRoutingStateModified() time.Time { return parsed } -// IsReachable returns whether or not the revision can be reached by a route. -func (r *Revision) IsReachable() bool { - return RoutingState(r.Labels[serving.RoutingStateLabelKey]) == RoutingStateActive -} - // GetProtocol returns the app level network protocol. func (r *Revision) GetProtocol() net.ProtocolType { ports := r.Spec.GetContainer().Ports diff --git a/pkg/apis/serving/v1/revision_helpers_test.go b/pkg/apis/serving/v1/revision_helpers_test.go index e176d67c1cb7..65feea02ed5f 100644 --- a/pkg/apis/serving/v1/revision_helpers_test.go +++ b/pkg/apis/serving/v1/revision_helpers_test.go @@ -22,7 +22,6 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/equality" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" net "knative.dev/networking/pkg/apis/networking" duckv1 "knative.dev/pkg/apis/duck/v1" @@ -106,38 +105,6 @@ func TestIsActivationRequired(t *testing.T) { } } -func TestRevisionIsReachable(t *testing.T) { - tests := []struct { - name string - labels map[string]string - want bool - }{{ - name: "has serving state label", - labels: map[string]string{serving.RoutingStateLabelKey: "active"}, - want: true, - }, { - name: "empty route annotation", - labels: map[string]string{serving.RoutingStateLabelKey: ""}, - want: false, - }, { - name: "no route annotation", - labels: nil, - want: false, - }} - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - rev := Revision{ObjectMeta: metav1.ObjectMeta{Labels: tt.labels}} - - got := rev.IsReachable() - - if got != tt.want { - t.Errorf("IsReachable = %t, want: %t", got, tt.want) - } - }) - } -} - func TestRevisionGetProtocol(t *testing.T) { containerWithPortName := func(name string) corev1.Container { return corev1.Container{Ports: []corev1.ContainerPort{{Name: name}}} diff --git a/pkg/reconciler/revision/resources/pa.go b/pkg/reconciler/revision/resources/pa.go index 1a51f3f9bbcb..e51f4e8553f7 100644 --- a/pkg/reconciler/revision/resources/pa.go +++ b/pkg/reconciler/revision/resources/pa.go @@ -20,6 +20,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "knative.dev/pkg/apis" "knative.dev/pkg/kmeta" autoscalingv1alpha1 "knative.dev/serving/pkg/apis/autoscaling/v1alpha1" v1 "knative.dev/serving/pkg/apis/serving/v1" @@ -44,27 +45,30 @@ func MakePA(rev *v1.Revision) *autoscalingv1alpha1.PodAutoscaler { Name: names.Deployment(rev), }, ProtocolType: rev.GetProtocol(), - Reachability: func() autoscalingv1alpha1.ReachabilityType { - // If the Revision has failed to become Ready, then mark the PodAutoscaler as unreachable. - if rev.Status.GetCondition(v1.RevisionConditionReady).IsFalse() { - // Make sure that we don't do this when a newly failing revision is - // marked reachable by outside forces. - if !rev.IsReachable() { - return autoscalingv1alpha1.ReachabilityUnreachable - } - } + Reachability: reachability(rev), + }, + } +} - // We don't know the reachability if the revision has just been created - // or it is activating. - if rev.Status.GetCondition(v1.RevisionConditionActive).IsUnknown() { - return autoscalingv1alpha1.ReachabilityUnknown - } +func reachability(rev *v1.Revision) autoscalingv1alpha1.ReachabilityType { + // check infra failures + conds := []apis.ConditionType{ + v1.RevisionConditionResourcesAvailable, + v1.RevisionConditionContainerHealthy, + } - if rev.IsReachable() { - return autoscalingv1alpha1.ReachabilityReachable - } - return autoscalingv1alpha1.ReachabilityUnreachable - }(), - }, + for _, cond := range conds { + if c := rev.Status.GetCondition(cond); c != nil && c.IsFalse() { + return autoscalingv1alpha1.ReachabilityUnreachable + } + } + + switch rev.GetRoutingState() { + case v1.RoutingStateActive: + return autoscalingv1alpha1.ReachabilityReachable + case v1.RoutingStateReserve: + return autoscalingv1alpha1.ReachabilityUnreachable + default: + return autoscalingv1alpha1.ReachabilityUnknown } } diff --git a/pkg/reconciler/revision/resources/pa_test.go b/pkg/reconciler/revision/resources/pa_test.go index be1edf6691eb..dbc1dc7e2dc5 100644 --- a/pkg/reconciler/revision/resources/pa_test.go +++ b/pkg/reconciler/revision/resources/pa_test.go @@ -22,6 +22,7 @@ import ( "github.com/google/go-cmp/cmp" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + duckv1 "knative.dev/pkg/apis/duck/v1" "knative.dev/networking/pkg/apis/networking" "knative.dev/pkg/ptr" @@ -37,26 +38,22 @@ func TestMakePA(t *testing.T) { want *autoscalingv1alpha1.PodAutoscaler }{{ name: "name is bar (Concurrency=1, Reachable=true)", - rev: func() *v1.Revision { - rev := v1.Revision{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "foo", - Name: "bar", - UID: "1234", - Labels: map[string]string{ - serving.RoutingStateLabelKey: "active", - }, - Annotations: map[string]string{ - "a": "b", - }, + rev: &v1.Revision{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "foo", + Name: "bar", + UID: "1234", + Labels: map[string]string{ + serving.RoutingStateLabelKey: string(v1.RoutingStateActive), }, - Spec: v1.RevisionSpec{ - ContainerConcurrency: ptr.Int64(1), + Annotations: map[string]string{ + "a": "b", }, - } - rev.Status.MarkActiveTrue() - return &rev - }(), + }, + Spec: v1.RevisionSpec{ + ContainerConcurrency: ptr.Int64(1), + }, + }, want: &autoscalingv1alpha1.PodAutoscaler{ ObjectMeta: metav1.ObjectMeta{ Namespace: "foo", @@ -91,28 +88,27 @@ func TestMakePA(t *testing.T) { }, }, { name: "name is baz (Concurrency=0, Reachable=false)", - rev: func() *v1.Revision { - rev := v1.Revision{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "blah", - Name: "baz", - UID: "4321", + rev: &v1.Revision{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "blah", + Name: "baz", + UID: "4321", + Labels: map[string]string{ + serving.RoutingStateLabelKey: string(v1.RoutingStateReserve), }, - Spec: v1.RevisionSpec{ - ContainerConcurrency: ptr.Int64(0), - PodSpec: corev1.PodSpec{ - Containers: []corev1.Container{{ - Ports: []corev1.ContainerPort{{ - Name: "h2c", - HostPort: int32(443), - }}, + }, + Spec: v1.RevisionSpec{ + ContainerConcurrency: ptr.Int64(0), + PodSpec: corev1.PodSpec{ + Containers: []corev1.Container{{ + Ports: []corev1.ContainerPort{{ + Name: "h2c", + HostPort: int32(443), }}, - }, + }}, }, - } - rev.Status.MarkActiveTrue() - return &rev - }(), + }, + }, want: &autoscalingv1alpha1.PodAutoscaler{ ObjectMeta: metav1.ObjectMeta{ Namespace: "blah", @@ -143,43 +139,39 @@ func TestMakePA(t *testing.T) { Reachability: autoscalingv1alpha1.ReachabilityUnreachable, }}, }, { - name: "name is baz (Concurrency=0, Reachable=false, Activating)", - rev: func() *v1.Revision { - rev := v1.Revision{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "blah", - Name: "baz", - UID: "4321", - }, - Spec: v1.RevisionSpec{ - ContainerConcurrency: ptr.Int64(0), - PodSpec: corev1.PodSpec{ - Containers: []corev1.Container{{ - Ports: []corev1.ContainerPort{{ - Name: "h2c", - HostPort: int32(443), - }}, + name: "unknown routing state", + rev: &v1.Revision{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "blah", + Name: "batman", + UID: "4321", + }, + Spec: v1.RevisionSpec{ + ContainerConcurrency: ptr.Int64(0), + PodSpec: corev1.PodSpec{ + Containers: []corev1.Container{{ + Ports: []corev1.ContainerPort{{ + Name: "h2c", + HostPort: int32(443), }}, - }, + }}, }, - } - rev.Status.MarkActiveUnknown("reasons", "because") - return &rev - }(), + }, + }, want: &autoscalingv1alpha1.PodAutoscaler{ ObjectMeta: metav1.ObjectMeta{ Namespace: "blah", - Name: "baz", + Name: "batman", Labels: map[string]string{ - serving.RevisionLabelKey: "baz", + serving.RevisionLabelKey: "batman", serving.RevisionUID: "4321", - AppLabelKey: "baz", + AppLabelKey: "batman", }, Annotations: map[string]string{}, OwnerReferences: []metav1.OwnerReference{{ APIVersion: v1.SchemeGroupVersion.String(), Kind: "Revision", - Name: "baz", + Name: "batman", UID: "4321", Controller: ptr.Bool(true), BlockOwnerDeletion: ptr.Bool(true), @@ -190,36 +182,35 @@ func TestMakePA(t *testing.T) { ScaleTargetRef: corev1.ObjectReference{ APIVersion: "apps/v1", Kind: "Deployment", - Name: "baz-deployment", + Name: "batman-deployment", }, ProtocolType: networking.ProtocolH2C, + // When the Revision has failed, we mark the PA as unreachable. Reachability: autoscalingv1alpha1.ReachabilityUnknown, }}, }, { - name: "name is batman (Activating, Revision failed)", - rev: func() *v1.Revision { - rev := v1.Revision{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "blah", - Name: "batman", - UID: "4321", + name: "pending routing state", + rev: &v1.Revision{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "blah", + Name: "batman", + UID: "4321", + Labels: map[string]string{ + serving.RoutingStateLabelKey: string(v1.RoutingStatePending), }, - Spec: v1.RevisionSpec{ - ContainerConcurrency: ptr.Int64(0), - PodSpec: corev1.PodSpec{ - Containers: []corev1.Container{{ - Ports: []corev1.ContainerPort{{ - Name: "h2c", - HostPort: int32(443), - }}, + }, + Spec: v1.RevisionSpec{ + ContainerConcurrency: ptr.Int64(0), + PodSpec: corev1.PodSpec{ + Containers: []corev1.Container{{ + Ports: []corev1.ContainerPort{{ + Name: "h2c", + HostPort: int32(443), }}, - }, + }}, }, - } - rev.Status.MarkActiveUnknown("reasons", "because") - rev.Status.MarkResourcesAvailableFalse("foo", "bar") - return &rev - }(), + }, + }, want: &autoscalingv1alpha1.PodAutoscaler{ ObjectMeta: metav1.ObjectMeta{ Namespace: "blah", @@ -248,50 +239,115 @@ func TestMakePA(t *testing.T) { }, ProtocolType: networking.ProtocolH2C, // When the Revision has failed, we mark the PA as unreachable. - Reachability: autoscalingv1alpha1.ReachabilityUnreachable, + Reachability: autoscalingv1alpha1.ReachabilityUnknown, }}, }, { - name: "name is robin (Activating, Revision routable but failed)", - rev: func() *v1.Revision { - rev := v1.Revision{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "blah", - Name: "robin", - UID: "4321", - Labels: map[string]string{ - serving.RoutingStateLabelKey: "active", - }, + name: "failed deployment", + rev: &v1.Revision{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "blah", + Name: "batman", + UID: "4321", + Labels: map[string]string{ + serving.RoutingStateLabelKey: string(v1.RoutingStateActive), }, - Spec: v1.RevisionSpec{ - ContainerConcurrency: ptr.Int64(0), - PodSpec: corev1.PodSpec{ - Containers: []corev1.Container{{ - Ports: []corev1.ContainerPort{{ - Name: "h2c", - HostPort: int32(443), - }}, + }, + Spec: v1.RevisionSpec{ + ContainerConcurrency: ptr.Int64(0), + PodSpec: corev1.PodSpec{ + Containers: []corev1.Container{{ + Ports: []corev1.ContainerPort{{ + Name: "h2c", + HostPort: int32(443), }}, - }, + }}, }, - } - rev.Status.MarkActiveUnknown("reasons", "because") - rev.Status.MarkResourcesAvailableFalse("foo", "bar") - return &rev - }(), + }, + Status: v1.RevisionStatus{ + Status: duckv1.Status{ + Conditions: duckv1.Conditions{{ + Type: v1.RevisionConditionResourcesAvailable, + Status: corev1.ConditionFalse, + }}, + }, + }, + }, want: &autoscalingv1alpha1.PodAutoscaler{ ObjectMeta: metav1.ObjectMeta{ - Namespace: "blah", - Name: "robin", + Namespace: "blah", + Name: "batman", + Annotations: map[string]string{}, Labels: map[string]string{ - serving.RevisionLabelKey: "robin", + serving.RevisionLabelKey: "batman", serving.RevisionUID: "4321", - AppLabelKey: "robin", + AppLabelKey: "batman", + }, + OwnerReferences: []metav1.OwnerReference{{ + APIVersion: v1.SchemeGroupVersion.String(), + Kind: "Revision", + Name: "batman", + UID: "4321", + Controller: ptr.Bool(true), + BlockOwnerDeletion: ptr.Bool(true), + }}, + }, + Spec: autoscalingv1alpha1.PodAutoscalerSpec{ + ContainerConcurrency: 0, + ScaleTargetRef: corev1.ObjectReference{ + APIVersion: "apps/v1", + Kind: "Deployment", + Name: "batman-deployment", + }, + ProtocolType: networking.ProtocolH2C, + Reachability: autoscalingv1alpha1.ReachabilityUnreachable, + }, + }, + }, { + // Crashlooping container that never starts + name: "failed container", + rev: &v1.Revision{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "blah", + Name: "batman", + UID: "4321", + Labels: map[string]string{ + serving.RoutingStateLabelKey: string(v1.RoutingStateActive), + }, + }, + Spec: v1.RevisionSpec{ + ContainerConcurrency: ptr.Int64(0), + PodSpec: corev1.PodSpec{ + Containers: []corev1.Container{{ + Ports: []corev1.ContainerPort{{ + Name: "h2c", + HostPort: int32(443), + }}, + }}, + }, + }, + Status: v1.RevisionStatus{ + Status: duckv1.Status{ + Conditions: duckv1.Conditions{{ + Type: v1.RevisionConditionContainerHealthy, + Status: corev1.ConditionFalse, + }}, }, + }, + }, + want: &autoscalingv1alpha1.PodAutoscaler{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "blah", + Name: "batman", Annotations: map[string]string{}, + Labels: map[string]string{ + serving.RevisionLabelKey: "batman", + serving.RevisionUID: "4321", + AppLabelKey: "batman", + }, OwnerReferences: []metav1.OwnerReference{{ APIVersion: v1.SchemeGroupVersion.String(), Kind: "Revision", - Name: "robin", + Name: "batman", UID: "4321", Controller: ptr.Bool(true), BlockOwnerDeletion: ptr.Bool(true), @@ -302,12 +358,12 @@ func TestMakePA(t *testing.T) { ScaleTargetRef: corev1.ObjectReference{ APIVersion: "apps/v1", Kind: "Deployment", - Name: "robin-deployment", + Name: "batman-deployment", }, ProtocolType: networking.ProtocolH2C, - // Reachability trumps failure of Revisions. - Reachability: autoscalingv1alpha1.ReachabilityUnknown, - }}, + Reachability: autoscalingv1alpha1.ReachabilityUnreachable, + }, + }, }} for _, test := range tests { diff --git a/pkg/reconciler/revision/table_test.go b/pkg/reconciler/revision/table_test.go index 026854c90267..a31ffe122087 100644 --- a/pkg/reconciler/revision/table_test.go +++ b/pkg/reconciler/revision/table_test.go @@ -241,6 +241,7 @@ func TestReconcile(t *testing.T) { Revision("foo", "stable-deactivation", WithLogURL, MarkRevisionReady, MarkInactive("NoTraffic", "This thing is inactive."), + WithRoutingState(v1.RoutingStateReserve, fc), withDefaultContainerStatuses(), WithRevisionObservedGeneration(1)), pa("foo", "stable-deactivation", WithNoTraffic("NoTraffic", "This thing is inactive."), WithReachabilityUnreachable, @@ -276,6 +277,7 @@ func TestReconcile(t *testing.T) { Objects: []runtime.Object{ Revision("foo", "pa-not-ready", WithLogURL, + WithRoutingState(v1.RoutingStateReserve, fc), MarkRevisionReady, WithRevisionObservedGeneration(1)), pa("foo", "pa-not-ready", WithPAStatusService("its-not-confidential"), @@ -287,7 +289,7 @@ func TestReconcile(t *testing.T) { WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ Object: Revision("foo", "pa-not-ready", WithLogURL, MarkRevisionReady, withDefaultContainerStatuses(), - + WithRoutingState(v1.RoutingStateReserve, fc), // When we reconcile a ready state and our pa is in an activating // state, we should see the following mutation. MarkActivating("Queued", "Requests to the target are being buffered as resources are provisioned."), @@ -301,6 +303,7 @@ func TestReconcile(t *testing.T) { Objects: []runtime.Object{ Revision("foo", "pa-inactive", WithLogURL, + WithRoutingState(v1.RoutingStateReserve, fc), MarkRevisionReady, WithRevisionObservedGeneration(1)), pa("foo", "pa-inactive", WithNoTraffic("NoTraffic", "This thing is inactive."), @@ -312,6 +315,7 @@ func TestReconcile(t *testing.T) { WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ Object: Revision("foo", "pa-inactive", WithLogURL, MarkRevisionReady, withDefaultContainerStatuses(), + WithRoutingState(v1.RoutingStateReserve, fc), // When we reconcile an "all ready" revision when the PA // is inactive, we should see the following change. @@ -367,6 +371,7 @@ func TestReconcile(t *testing.T) { Objects: []runtime.Object{ Revision("foo", "pa-inactive", WithLogURL, MarkRevisionReady, + WithRoutingState(v1.RoutingStateReserve, fc), WithRevisionObservedGeneration(1)), pa("foo", "pa-inactive", WithNoTraffic("NoTraffic", "This thing is inactive."), @@ -379,6 +384,7 @@ func TestReconcile(t *testing.T) { WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ Object: Revision("foo", "pa-inactive", WithLogURL, MarkRevisionReady, + WithRoutingState(v1.RoutingStateReserve, fc), // When we reconcile an "all ready" revision when the PA // is inactive, we should see the following change. MarkInactive("NoTraffic", "This thing is inactive."), @@ -446,14 +452,16 @@ func TestReconcile(t *testing.T) { // status of the Revision. Objects: []runtime.Object{ Revision("foo", "deploy-timeout", + WithRoutingState(v1.RoutingStateActive, fc), WithLogURL, MarkActive), - pa("foo", "deploy-timeout"), // pa can't be ready since deployment times out. + pa("foo", "deploy-timeout", WithReachabilityReachable), timeoutDeploy(deploy(t, "foo", "deploy-timeout"), "I timed out!"), image("foo", "deploy-timeout"), }, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ Object: Revision("foo", "deploy-timeout", WithLogURL, allUnknownConditions, + WithRoutingState(v1.RoutingStateActive, fc), // When the revision is reconciled after a Deployment has // timed out, we should see it marked with the PDE state. MarkProgressDeadlineExceeded("I timed out!"), withDefaultContainerStatuses(), @@ -471,14 +479,16 @@ func TestReconcile(t *testing.T) { // It then verifies that Reconcile propagates this into the status of the Revision. Objects: []runtime.Object{ Revision("foo", "deploy-replica-failure", + WithRoutingState(v1.RoutingStateActive, fc), WithLogURL, MarkActive), - pa("foo", "deploy-replica-failure"), + pa("foo", "deploy-replica-failure", WithReachabilityReachable), replicaFailureDeploy(deploy(t, "foo", "deploy-replica-failure"), "I replica failed!"), image("foo", "deploy-replica-failure"), }, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ Object: Revision("foo", "deploy-replica-failure", WithLogURL, allUnknownConditions, + WithRoutingState(v1.RoutingStateActive, fc), // When the revision is reconciled after a Deployment has // timed out, we should see it marked with the FailedCreate state. MarkResourcesUnavailable("FailedCreate", "I replica failed!"), @@ -493,8 +503,10 @@ func TestReconcile(t *testing.T) { // Test the propagation of ImagePullBackoff from user container. Objects: []runtime.Object{ Revision("foo", "pull-backoff", - WithLogURL, MarkActivating("Deploying", "")), - pa("foo", "pull-backoff"), // pa can't be ready since deployment times out. + WithLogURL, MarkActivating("Deploying", ""), + WithRoutingState(v1.RoutingStateActive, fc), + ), + pa("foo", "pull-backoff", WithReachabilityReachable), // pa can't be ready since deployment times out. pod(t, "foo", "pull-backoff", WithWaitingContainer("pull-backoff", "ImagePullBackoff", "can't pull it")), timeoutDeploy(deploy(t, "foo", "pull-backoff"), "Timed out!"), image("foo", "pull-backoff"), @@ -502,6 +514,7 @@ func TestReconcile(t *testing.T) { WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ Object: Revision("foo", "pull-backoff", WithLogURL, allUnknownConditions, + WithRoutingState(v1.RoutingStateActive, fc), MarkResourcesUnavailable("ImagePullBackoff", "can't pull it"), withDefaultContainerStatuses(), WithRevisionObservedGeneration(1)), }}, WantUpdates: []clientgotesting.UpdateActionImpl{{ @@ -516,16 +529,21 @@ func TestReconcile(t *testing.T) { // that Reconcile propagates this into the status of the Revision. Objects: []runtime.Object{ Revision("foo", "pod-error", + WithRoutingState(v1.RoutingStateActive, fc), WithLogURL, allUnknownConditions, MarkActive), - pa("foo", "pod-error"), // PA can't be ready, since no traffic. + pa("foo", "pod-error", WithReachabilityReachable), // PA can't be ready, since no traffic. pod(t, "foo", "pod-error", WithFailingContainer("pod-error", 5, "I failed man!")), deploy(t, "foo", "pod-error"), image("foo", "pod-error"), }, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ Object: Revision("foo", "pod-error", - WithLogURL, allUnknownConditions, MarkContainerExiting(5, - v1.RevisionContainerExitingMessage("I failed man!")), withDefaultContainerStatuses(), WithRevisionObservedGeneration(1)), + WithLogURL, allUnknownConditions, + WithRoutingState(v1.RoutingStateActive, fc), + MarkContainerExiting(5, v1.RevisionContainerExitingMessage("I failed man!")), + withDefaultContainerStatuses(), + WithRevisionObservedGeneration(1), + ), }}, WantUpdates: []clientgotesting.UpdateActionImpl{{ Object: pa("foo", "pod-error", WithReachabilityUnreachable), @@ -538,16 +556,22 @@ func TestReconcile(t *testing.T) { // that Reconcile propagates this into the status of the Revision. Objects: []runtime.Object{ Revision("foo", "pod-schedule-error", + WithRoutingState(v1.RoutingStateActive, fc), WithLogURL, allUnknownConditions, MarkActive), - pa("foo", "pod-schedule-error"), // PA can't be ready, since no traffic. + pa("foo", "pod-schedule-error", WithReachabilityReachable), // PA can't be ready, since no traffic. pod(t, "foo", "pod-schedule-error", WithUnschedulableContainer("Insufficient energy", "Unschedulable")), deploy(t, "foo", "pod-schedule-error"), image("foo", "pod-schedule-error"), }, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ Object: Revision("foo", "pod-schedule-error", - WithLogURL, allUnknownConditions, MarkResourcesUnavailable("Insufficient energy", - "Unschedulable"), withDefaultContainerStatuses(), WithRevisionObservedGeneration(1)), + WithLogURL, + allUnknownConditions, + WithRoutingState(v1.RoutingStateActive, fc), + MarkResourcesUnavailable("Insufficient energy", "Unschedulable"), + withDefaultContainerStatuses(), + WithRevisionObservedGeneration(1), + ), }}, WantUpdates: []clientgotesting.UpdateActionImpl{{ Object: pa("foo", "pod-schedule-error", WithReachabilityUnreachable),