Skip to content

Commit 1f62b02

Browse files
authored
chore(conformance): Add timeout configuration (#795)
* Add inferencepool_lifecycle test. * Resolve setup issues and enable InferencePool test * removed todo comment in helper.go * Add InferencePoolLifecycle test * update comments in helper.go * remove Conformanc.go from log message * Remove lifecycle test. * Removed unused helper methods ( inference pool must have selector & must be deleted) * Set timeout values as constant * change timeout.go to timing.go
1 parent 8baf74c commit 1f62b02

File tree

4 files changed

+89
-38
lines changed

4 files changed

+89
-38
lines changed

conformance/conformance.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import (
2525
"io/fs"
2626
"os"
2727
"testing"
28-
"time"
2928

3029
"github.com/stretchr/testify/require"
3130
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
@@ -64,6 +63,7 @@ import (
6463

6564
// Import the Inference Extension API types
6665
inferencev1alpha2 "sigs.k8s.io/gateway-api-inference-extension/api/v1alpha2"
66+
inferenceconfig "sigs.k8s.io/gateway-api-inference-extension/conformance/utils/config"
6767
)
6868

6969
// Constants for the shared Gateway
@@ -245,16 +245,16 @@ func ensureGatewayAvailableAndReady(t *testing.T, k8sClient client.Client, opts
245245
t.Logf("Attempting to fetch Gateway %s/%s.", gatewayNN.Namespace, gatewayNN.Name)
246246
gw := &gatewayv1.Gateway{} // This gw instance will be populated by the poll function
247247

248-
// Define polling interval
249-
// TODO: Make this configurable using a local TimeoutConfig (from ConformanceOptions perhaps)
250-
pollingInterval := 5 * time.Second
251-
// Use the GatewayMustHaveAddress timeout from the suite's TimeoutConfig for the Gateway object to appear
252-
waitForGatewayCreationTimeout := opts.TimeoutConfig.GatewayMustHaveAddress
248+
// Use extension-specific config for the polling interval defined in timeout.go.
249+
extTimeoutConf := inferenceconfig.DefaultInferenceExtensionTimeoutConfig()
250+
251+
// Use the GatewayMustHaveAddress timeout from the suite's base TimeoutConfig for the Gateway object to appear.
252+
waitForGatewayCreationTimeout := extTimeoutConf.TimeoutConfig.GatewayMustHaveAddress
253253

254254
logDebugf(t, opts.Debug, "Waiting up to %v for Gateway object %s/%s to appear after manifest application...", waitForGatewayCreationTimeout, gatewayNN.Namespace, gatewayNN.Name)
255255

256256
ctx := context.TODO()
257-
pollErr := wait.PollUntilContextTimeout(ctx, pollingInterval, waitForGatewayCreationTimeout, true, func(pollCtx context.Context) (bool, error) {
257+
pollErr := wait.PollUntilContextTimeout(ctx, extTimeoutConf.GatewayObjectPollInterval, waitForGatewayCreationTimeout, true, func(pollCtx context.Context) (bool, error) {
258258
fetchErr := k8sClient.Get(pollCtx, gatewayNN, gw)
259259
if fetchErr == nil {
260260
t.Logf("Successfully fetched Gateway %s/%s. Spec.GatewayClassName: %s",

conformance/tests/basic/inferencepool_accepted.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ var InferencePoolAccepted = suite.ConformanceTest{
5454
Status: metav1.ConditionTrue,
5555
Reason: "", // "" means we don't strictly check the Reason for this basic test.
5656
}
57-
infrakubernetes.InferencePoolMustHaveCondition(t, s.Client, s.TimeoutConfig, poolNN, acceptedCondition)
57+
infrakubernetes.InferencePoolMustHaveCondition(t, s.Client, poolNN, acceptedCondition)
5858
})
5959
},
6060
}

conformance/utils/config/timing.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
Copyright 2025 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package config
18+
19+
import (
20+
"time"
21+
22+
// Import the upstream Gateway API timeout config
23+
gatewayconfig "sigs.k8s.io/gateway-api/conformance/utils/config"
24+
)
25+
26+
// InferenceExtensionTimeoutConfig embeds the upstream TimeoutConfig and adds
27+
// extension-specific timeout values.
28+
type InferenceExtensionTimeoutConfig struct {
29+
// All fields from gatewayconfig.TimeoutConfig will be available directly.
30+
gatewayconfig.TimeoutConfig
31+
32+
// InferencePoolMustHaveConditionTimeout represents the maximum time to wait for an InferencePool to have a specific condition.
33+
InferencePoolMustHaveConditionTimeout time.Duration
34+
35+
// InferencePoolMustHaveConditionInterval represents the polling interval for checking an InferencePool's condition.
36+
InferencePoolMustHaveConditionInterval time.Duration
37+
38+
// GatewayObjectPollInterval is the polling interval used when waiting for a Gateway object to appear.
39+
GatewayObjectPollInterval time.Duration
40+
}
41+
42+
func DefaultInferenceExtensionTimeoutConfig() InferenceExtensionTimeoutConfig {
43+
return InferenceExtensionTimeoutConfig{
44+
TimeoutConfig: gatewayconfig.DefaultTimeoutConfig(),
45+
InferencePoolMustHaveConditionTimeout: 300 * time.Second,
46+
InferencePoolMustHaveConditionInterval: 10 * time.Second,
47+
GatewayObjectPollInterval: 5 * time.Second,
48+
}
49+
}

conformance/utils/kubernetes/helpers.go

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import (
2323
"fmt"
2424
"reflect"
2525
"testing"
26-
"time"
2726

2827
"github.com/stretchr/testify/require"
2928
apierrors "k8s.io/apimachinery/pkg/api/errors"
@@ -36,7 +35,7 @@ import (
3635
inferenceapi "sigs.k8s.io/gateway-api-inference-extension/api/v1alpha2" // Adjust if your API version is different
3736

3837
// Import necessary utilities from the core Gateway API conformance suite
39-
"sigs.k8s.io/gateway-api/conformance/utils/config"
38+
"sigs.k8s.io/gateway-api-inference-extension/conformance/utils/config"
4039
)
4140

4241
// checkCondition is a helper function similar to findConditionInList or CheckCondition
@@ -67,45 +66,48 @@ func checkCondition(t *testing.T, conditions []metav1.Condition, expectedConditi
6766
// InferencePoolMustHaveCondition waits for the specified InferencePool resource
6867
// to exist and report the expected status condition within one of its parent statuses.
6968
// It polls the InferencePool's status until the condition is met or the timeout occurs.
70-
func InferencePoolMustHaveCondition(t *testing.T, c client.Client, timeoutConfig config.TimeoutConfig, poolNN types.NamespacedName, expectedCondition metav1.Condition) {
69+
func InferencePoolMustHaveCondition(t *testing.T, c client.Client, poolNN types.NamespacedName, expectedCondition metav1.Condition) {
7170
t.Helper() // Marks this function as a test helper
7271

72+
var timeoutConfig config.InferenceExtensionTimeoutConfig = config.DefaultInferenceExtensionTimeoutConfig()
7373
var lastObservedPool *inferenceapi.InferencePool
7474
var lastError error
7575
var conditionFound bool
76-
var interval time.Duration = 5 * time.Second // pull interval for status checks.
77-
78-
// TODO: Make retry interval configurable.
79-
waitErr := wait.PollUntilContextTimeout(context.Background(), interval, timeoutConfig.DefaultTestTimeout, true, func(ctx context.Context) (bool, error) {
80-
pool := &inferenceapi.InferencePool{} // This is the type instance used for Get
81-
err := c.Get(ctx, poolNN, pool)
82-
if err != nil {
83-
if apierrors.IsNotFound(err) {
84-
t.Logf("InferencePool %s not found yet. Retrying.", poolNN.String())
76+
77+
waitErr := wait.PollUntilContextTimeout(
78+
context.Background(),
79+
timeoutConfig.InferencePoolMustHaveConditionInterval,
80+
timeoutConfig.InferencePoolMustHaveConditionTimeout,
81+
true, func(ctx context.Context) (bool, error) {
82+
pool := &inferenceapi.InferencePool{} // This is the type instance used for Get
83+
err := c.Get(ctx, poolNN, pool)
84+
if err != nil {
85+
if apierrors.IsNotFound(err) {
86+
t.Logf("InferencePool %s not found yet. Retrying.", poolNN.String())
87+
lastError = err
88+
return false, nil
89+
}
90+
t.Logf("Error fetching InferencePool %s (type: %s): %v. Retrying.", poolNN.String(), reflect.TypeOf(pool).String(), err)
8591
lastError = err
8692
return false, nil
8793
}
88-
t.Logf("Error fetching InferencePool %s (type: %s): %v. Retrying.", poolNN.String(), reflect.TypeOf(pool).String(), err)
89-
lastError = err
90-
return false, nil
91-
}
92-
lastObservedPool = pool
93-
lastError = nil
94-
conditionFound = false
94+
lastObservedPool = pool
95+
lastError = nil
96+
conditionFound = false
9597

96-
if len(pool.Status.Parents) == 0 {
97-
t.Logf("InferencePool %s has no parent statuses reported yet.", poolNN.String())
98-
return false, nil
99-
}
98+
if len(pool.Status.Parents) == 0 {
99+
t.Logf("InferencePool %s has no parent statuses reported yet.", poolNN.String())
100+
return false, nil
101+
}
100102

101-
for _, parentStatus := range pool.Status.Parents {
102-
if checkCondition(t, parentStatus.Conditions, expectedCondition) {
103-
conditionFound = true
104-
return true, nil
103+
for _, parentStatus := range pool.Status.Parents {
104+
if checkCondition(t, parentStatus.Conditions, expectedCondition) {
105+
conditionFound = true
106+
return true, nil
107+
}
105108
}
106-
}
107-
return false, nil
108-
})
109+
return false, nil
110+
})
109111

110112
if waitErr != nil || !conditionFound {
111113
debugMsg := ""

0 commit comments

Comments
 (0)