Skip to content

Commit e4b1c18

Browse files
committed
Add ServiceReady condition to Function status
Reflect the readiness of the underlying service as a new ServiceReady condition on the Function CRD, using the Ready field added in knative/func#3627.
1 parent 3556b1d commit e4b1c18

7 files changed

Lines changed: 205 additions & 65 deletions

File tree

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ make lint
293293
| Field | Type | Description |
294294
|-------|------|-------------|
295295
| `name` | string | Function name from metadata |
296-
| `conditions` | array | Status conditions |
296+
| `conditions` | array | Status conditions (see below) |
297297
| `git.resolvedBranch` | string | Git branch that is being monitored |
298298
| `git.observedCommit` | string | Latest Git commit SHA observed |
299299
| `git.lastChecked` | timestamp | Last time the repository was checked |
@@ -308,6 +308,16 @@ make lint
308308
| `middleware.pendingRebuild` | boolean | Whether a rebuild is pending due to outdated middleware |
309309
| `middleware.lastRebuild` | timestamp | Last time the function was rebuilt for middleware updates |
310310

311+
#### Status Conditions
312+
313+
| Condition | Description |
314+
|-----------|-----------------------------------------------------------------------|
315+
| `Ready` | Summary condition that is `True` when all other conditions are `True` |
316+
| `SourceReady` | Git source was cloned and function metadata was read successfully |
317+
| `Deployed` | Function is deployed |
318+
| `MiddlewareUpToDate` | Middleware is on the latest version (or intentionally skipped) |
319+
| `ServiceReady` | Underlying service of the function is ready to serve traffic |
320+
311321
## Uninstallation
312322

313323
Remove the operator and CRDs:

api/v1alpha1/function_lifecycle.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,16 @@ const (
2020

2121
// TypeMiddlewareUpToDate indicates middleware is current
2222
TypeMiddlewareUpToDate = "MiddlewareUpToDate"
23+
24+
// TypeServiceReady indicates the underlying service (e.g. Knative Service) is ready
25+
TypeServiceReady = "ServiceReady"
2326
)
2427

2528
var FunctionsConditions = []string{
2629
TypeSourceReady,
2730
TypeDeployed,
2831
TypeMiddlewareUpToDate,
32+
TypeServiceReady,
2933
}
3034

3135
// InitializeConditions resets all conditions to ensure a fresh start for each reconcile.
@@ -194,3 +198,24 @@ func (f *Function) MarkMiddlewareNotUpToDateIntentionally(reason, messageFormat
194198
ObservedGeneration: f.Generation,
195199
})
196200
}
201+
202+
// Service condition helpers
203+
204+
func (f *Function) MarkServiceReady() bool {
205+
return meta.SetStatusCondition(&f.Status.Conditions, metav1.Condition{
206+
Type: TypeServiceReady,
207+
Status: metav1.ConditionTrue,
208+
Reason: "ServiceReady",
209+
ObservedGeneration: f.Generation,
210+
})
211+
}
212+
213+
func (f *Function) MarkServiceNotReady(reason, messageFormat string, messageA ...interface{}) bool {
214+
return meta.SetStatusCondition(&f.Status.Conditions, metav1.Condition{
215+
Type: TypeServiceReady,
216+
Status: metav1.ConditionFalse,
217+
Reason: reason,
218+
Message: fmt.Sprintf(messageFormat, messageA...),
219+
ObservedGeneration: f.Generation,
220+
})
221+
}

api/v1alpha1/function_lifecycle_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ func TestCalculateReadyCondition(t *testing.T) {
2121
{Type: TypeSourceReady, Status: metav1.ConditionTrue, Reason: "CloneSucceeded"},
2222
{Type: TypeDeployed, Status: metav1.ConditionTrue, Reason: "DeploySucceeded"},
2323
{Type: TypeMiddlewareUpToDate, Status: metav1.ConditionTrue, Reason: "UpToDate"},
24+
{Type: TypeServiceReady, Status: metav1.ConditionTrue, Reason: "ServiceReady"},
2425
},
2526
expectedStatus: metav1.ConditionTrue,
2627
expectedReason: "ReconcileSucceeded",
@@ -31,6 +32,7 @@ func TestCalculateReadyCondition(t *testing.T) {
3132
{Type: TypeSourceReady, Status: metav1.ConditionTrue, Reason: "CloneSucceeded"},
3233
{Type: TypeDeployed, Status: metav1.ConditionFalse, Reason: "DeployFailed", Message: "deployment failed"},
3334
{Type: TypeMiddlewareUpToDate, Status: metav1.ConditionTrue, Reason: "UpToDate"},
35+
{Type: TypeServiceReady, Status: metav1.ConditionTrue, Reason: "ServiceReady"},
3436
},
3537
expectedStatus: metav1.ConditionFalse,
3638
expectedReason: "DeployFailed",
@@ -42,6 +44,7 @@ func TestCalculateReadyCondition(t *testing.T) {
4244
{Type: TypeSourceReady, Status: metav1.ConditionTrue, Reason: "CloneSucceeded"},
4345
{Type: TypeDeployed, Status: metav1.ConditionUnknown, Reason: "NotChecked", Message: "deployment not checked yet"},
4446
{Type: TypeMiddlewareUpToDate, Status: metav1.ConditionTrue, Reason: "UpToDate"},
47+
{Type: TypeServiceReady, Status: metav1.ConditionTrue, Reason: "ServiceReady"},
4548
},
4649
expectedStatus: metav1.ConditionFalse,
4750
expectedReason: "NotChecked",
@@ -53,6 +56,7 @@ func TestCalculateReadyCondition(t *testing.T) {
5356
{Type: TypeSourceReady, Status: metav1.ConditionUnknown, Reason: "NotCloned", Message: "source not cloned yet"},
5457
{Type: TypeDeployed, Status: metav1.ConditionUnknown, Reason: "NotDeployed", Message: "not deployed yet"},
5558
{Type: TypeMiddlewareUpToDate, Status: metav1.ConditionTrue, Reason: "UpToDate"},
59+
{Type: TypeServiceReady, Status: metav1.ConditionTrue, Reason: "ServiceReady"},
5660
},
5761
expectedStatus: metav1.ConditionFalse,
5862
expectedReason: "NotCloned",
@@ -64,6 +68,7 @@ func TestCalculateReadyCondition(t *testing.T) {
6468
{Type: TypeSourceReady, Status: metav1.ConditionUnknown, Reason: "NotCloned", Message: "source not cloned yet"},
6569
{Type: TypeDeployed, Status: metav1.ConditionFalse, Reason: "DeployFailed", Message: "deployment failed"},
6670
{Type: TypeMiddlewareUpToDate, Status: metav1.ConditionTrue, Reason: "UpToDate"},
71+
{Type: TypeServiceReady, Status: metav1.ConditionTrue, Reason: "ServiceReady"},
6772
},
6873
expectedStatus: metav1.ConditionFalse,
6974
expectedReason: "DeployFailed",
@@ -75,10 +80,23 @@ func TestCalculateReadyCondition(t *testing.T) {
7580
{Type: TypeSourceReady, Status: metav1.ConditionUnknown, Reason: "unknown", Message: ""},
7681
{Type: TypeDeployed, Status: metav1.ConditionUnknown, Reason: "unknown", Message: ""},
7782
{Type: TypeMiddlewareUpToDate, Status: metav1.ConditionUnknown, Reason: "unknown", Message: ""},
83+
{Type: TypeServiceReady, Status: metav1.ConditionUnknown, Reason: "unknown", Message: ""},
7884
},
7985
expectedStatus: metav1.ConditionFalse,
8086
expectedReason: "unknown",
8187
},
88+
{
89+
name: "service not ready makes overall not ready",
90+
conditions: []metav1.Condition{
91+
{Type: TypeSourceReady, Status: metav1.ConditionTrue, Reason: "CloneSucceeded"},
92+
{Type: TypeDeployed, Status: metav1.ConditionTrue, Reason: "DeploySucceeded"},
93+
{Type: TypeMiddlewareUpToDate, Status: metav1.ConditionTrue, Reason: "UpToDate"},
94+
{Type: TypeServiceReady, Status: metav1.ConditionFalse, Reason: "ServiceNotReady", Message: "Underlying service is not ready"},
95+
},
96+
expectedStatus: metav1.ConditionFalse,
97+
expectedReason: "ServiceNotReady",
98+
expectedMessage: "Underlying service is not ready",
99+
},
82100
}
83101

84102
for _, tt := range tests {

go.mod

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ require (
8080
github.com/google/go-containerregistry v0.21.3 // indirect
8181
github.com/google/pprof v0.0.0-20260302011040-a15ffb7f9dcc // indirect
8282
github.com/google/uuid v1.6.0 // indirect
83+
github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc // indirect
8384
github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 // indirect
8485
github.com/hashicorp/go-version v1.8.0 // indirect
8586
github.com/inconshreveable/mousetrap v1.1.0 // indirect
@@ -97,7 +98,7 @@ require (
9798
github.com/pjbgf/sha1cd v0.5.0 // indirect
9899
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
99100
github.com/prometheus/client_model v0.6.2 // indirect
100-
github.com/prometheus/common v0.67.5 // indirect
101+
github.com/prometheus/common v1.20.99 // indirect
101102
github.com/prometheus/procfs v0.20.1 // indirect
102103
github.com/sergi/go-diff v1.4.0 // indirect
103104
github.com/sirupsen/logrus v1.9.4 // indirect
@@ -109,10 +110,10 @@ require (
109110
github.com/x448/float16 v0.8.4 // indirect
110111
github.com/xanzy/ssh-agent v0.3.3 // indirect
111112
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
112-
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0 // indirect
113+
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 // indirect
113114
go.opentelemetry.io/otel v1.43.0 // indirect
114-
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.42.0 // indirect
115-
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.42.0 // indirect
115+
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 // indirect
116+
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 // indirect
116117
go.opentelemetry.io/otel/metric v1.43.0 // indirect
117118
go.opentelemetry.io/otel/sdk v1.43.0 // indirect
118119
go.opentelemetry.io/otel/trace v1.43.0 // indirect
@@ -123,35 +124,35 @@ require (
123124
go.yaml.in/yaml/v3 v3.0.4 // indirect
124125
golang.org/x/crypto v0.50.0 // indirect
125126
golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90 // indirect
126-
golang.org/x/mod v0.34.0 // indirect
127+
golang.org/x/mod v0.35.0 // indirect
127128
golang.org/x/net v0.53.0 // indirect
128129
golang.org/x/oauth2 v0.36.0 // indirect
129130
golang.org/x/sync v0.20.0 // indirect
130131
golang.org/x/sys v0.43.0 // indirect
131132
golang.org/x/term v0.42.0 // indirect
132133
golang.org/x/text v0.36.0 // indirect
133134
golang.org/x/time v0.15.0 // indirect
134-
golang.org/x/tools v0.43.0 // indirect
135+
golang.org/x/tools v0.44.0 // indirect
135136
gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect
136-
google.golang.org/genproto/googleapis/api v0.0.0-20260316180232-0b37fe3546d5 // indirect
137-
google.golang.org/genproto/googleapis/rpc v0.0.0-20260316180232-0b37fe3546d5 // indirect
138-
google.golang.org/grpc v1.79.3 // indirect
137+
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect
138+
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 // indirect
139+
google.golang.org/grpc v1.80.0 // indirect
139140
google.golang.org/protobuf v1.36.11 // indirect
140141
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
141142
gopkg.in/inf.v0 v0.9.1 // indirect
142143
gopkg.in/warnings.v0 v0.1.2 // indirect
143144
gopkg.in/yaml.v2 v2.4.0 // indirect
144-
k8s.io/apiextensions-apiserver v0.35.2 // indirect
145-
k8s.io/apiserver v0.35.2 // indirect
146-
k8s.io/component-base v0.35.2 // indirect
145+
k8s.io/apiextensions-apiserver v0.35.3 // indirect
146+
k8s.io/apiserver v0.35.3 // indirect
147+
k8s.io/component-base v0.35.3 // indirect
147148
k8s.io/klog/v2 v2.140.0 // indirect
148149
k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a // indirect
149-
knative.dev/pkg v0.0.0-20260318013857-98d5a706d4fd // indirect
150+
knative.dev/pkg v0.0.0-20260414003832-e65cbe95a718 // indirect
150151
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0 // indirect
151152
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
152153
sigs.k8s.io/randfill v1.0.0 // indirect
153154
sigs.k8s.io/structured-merge-diff/v6 v6.3.2 // indirect
154155
sigs.k8s.io/yaml v1.6.0 // indirect
155156
)
156157

157-
replace knative.dev/func => knative.dev/func v0.47.1-0.20251218065725-bd17dff4c193
158+
replace knative.dev/func => knative.dev/func v0.47.1-0.20260421122411-87ce20dd94e4

0 commit comments

Comments
 (0)