Repository navigation
fix: preserve fractional upstream timeouts (backport apache/apisix-ingress-controller#2894) #497
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| // Licensed to the Apache Software Foundation (ASF) under one | ||
| // or more contributor license agreements. See the NOTICE file | ||
| // distributed with this work for additional information | ||
| // regarding copyright ownership. The ASF licenses this file | ||
| // to you under the Apache License, Version 2.0 (the | ||
| // "License"); you may not use this file except in compliance | ||
| // with the License. You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, | ||
| // software distributed under the License is distributed on an | ||
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| // KIND, either express or implied. See the License for the | ||
| // specific language governing permissions and limitations | ||
| // under the License. | ||
|
|
||
| package translator | ||
|
|
||
| import ( | ||
| "testing" | ||
| "time" | ||
|
|
||
| "github.com/stretchr/testify/assert" | ||
| "github.com/stretchr/testify/require" | ||
| metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
|
|
||
| "github.com/apache/apisix-ingress-controller/api/adc" | ||
| "github.com/apache/apisix-ingress-controller/api/v1alpha1" | ||
| apiv2 "github.com/apache/apisix-ingress-controller/api/v2" | ||
| ) | ||
|
|
||
| func TestTranslateApisixUpstreamRetriesAndTimeoutPreservesSubsecondValues(t *testing.T) { | ||
| config := &apiv2.ApisixUpstreamConfig{ | ||
| Timeout: &apiv2.UpstreamTimeout{ | ||
| Connect: metav1.Duration{Duration: 500 * time.Millisecond}, | ||
| Read: metav1.Duration{Duration: 1500 * time.Millisecond}, | ||
| Send: metav1.Duration{Duration: 2500 * time.Millisecond}, | ||
| }, | ||
| } | ||
| upstream := adc.NewDefaultUpstream() | ||
|
|
||
| err := translateApisixUpstreamRetriesAndTimeout(config, upstream) | ||
|
|
||
| require.NoError(t, err) | ||
| assert.Equal(t, 0.5, upstream.Timeout.Connect) | ||
| assert.Equal(t, 1.5, upstream.Timeout.Read) | ||
| assert.Equal(t, 2.5, upstream.Timeout.Send) | ||
| } | ||
|
|
||
| func TestBuildTimeoutPreservesSubsecondValues(t *testing.T) { | ||
| rule := apiv2.ApisixRouteHTTP{ | ||
| Timeout: &apiv2.UpstreamTimeout{ | ||
| Connect: metav1.Duration{Duration: 500 * time.Millisecond}, | ||
| Read: metav1.Duration{Duration: 1500 * time.Millisecond}, | ||
| Send: metav1.Duration{Duration: 2500 * time.Millisecond}, | ||
| }, | ||
| } | ||
|
|
||
| timeout := (&Translator{}).buildTimeout(rule) | ||
|
|
||
| assert.Equal(t, 0.5, timeout.Connect) | ||
| assert.Equal(t, 1.5, timeout.Read) | ||
| assert.Equal(t, 2.5, timeout.Send) | ||
| } | ||
|
|
||
| func TestAttachBackendTrafficPolicyToUpstreamPreservesSubsecondValues(t *testing.T) { | ||
| policy := &v1alpha1.BackendTrafficPolicy{ | ||
| Spec: v1alpha1.BackendTrafficPolicySpec{ | ||
| Timeout: &v1alpha1.Timeout{ | ||
| Connect: metav1.Duration{}, | ||
| Read: metav1.Duration{Duration: 1500 * time.Millisecond}, | ||
| Send: metav1.Duration{Duration: 2500 * time.Millisecond}, | ||
| }, | ||
| }, | ||
| } | ||
| upstream := &adc.Upstream{} | ||
|
|
||
| (&Translator{}).attachBackendTrafficPolicyToUpstream(policy, upstream) | ||
|
|
||
| assert.Equal(t, 60.0, upstream.Timeout.Connect) | ||
| assert.Equal(t, 1.5, upstream.Timeout.Read) | ||
| assert.Equal(t, 2.5, upstream.Timeout.Send) | ||
| } | ||
|
Comment on lines
+67
to
+84
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win 🔎 Supported by static analysis🏁 Script executed: sed -n '65,90p' internal/adc/translator/timeouts_test.go
sed -n '107,133p' api/v1alpha1/backendtrafficpolicy_types.go
sed -n '355,388p' config/crd/bases/apisix.apache.org_backendtrafficpolicies.yamlRepository: api7/api7-ingress-controller Length of output: 3315 🏁 Script executed: set -o pipefail
printf '%s\n' '--- BackendTrafficPolicy references and registration ---'
rg -n -F --glob '!vendor/**' --glob '!config/crd/bases/apisix.apache.org_backendtrafficpolicies.yaml' -e 'BackendTrafficPolicy' -e 'backendtrafficpolic' api internal pkg config docs examples test 2>/dev/null || test "$?" -eq 1
printf '%s\n' '--- duration examples and fractional values ---'
rg -n --glob '!vendor/**' -e '([0-9]+\.[0-9]+s|[0-9]+ms|500ms|1500ms|2500ms)' api config docs examples test internal pkg 2>/dev/null || test "$?" -eq 1
printf '%s\n' '--- PR diff for implicated files ---'
git diff --no-ext-diff --unified=30 b288e011821ee7384b12f603cea30e1468630086 c231e1c0af0a42d0a49ef31d7834338a2962e749 -- internal/adc/translator/timeouts_test.go api/v1alpha1/backendtrafficpolicy_types.go config/crd/bases/apisix.apache.org_backendtrafficpolicies.yamlRepository: api7/api7-ingress-controller Length of output: 26437 🏁 Script executed: set -o pipefail
printf '%s\n' '--- documented BackendTrafficPolicy timeout contract ---'
rg -n -C 8 -F -- 'Timeout' docs/en/latest/reference/api-reference.md docs/en/latest/reference/example.md docs/en/latest/getting-started/load-balancing.md examples test/e2e/crds/v1alpha1/backendtrafficpolicy.go
printf '%s\n' '--- timeout type declarations ---'
rg -n -C 12 -F -- 'type UpstreamTimeout' api
rg -n -C 12 -F -- 'Timeout *' api/v1alpha1 api/v2
printf '%s\n' '--- timeout schemas in generated CRDs ---'
rg -n -C 6 -e 'timeout:|connect:|read:|send:|pattern:.*s' config/crd/bases config/crd 2>/dev/null || test "$?" -eq 1
printf '%s\n' '--- policy admission and translation path ---'
sed -n '55,205p' internal/controller/policies.go
sed -n '35,135p' internal/adc/translator/policies.go
sed -n '255,280p' api/v1alpha1/backendtrafficpolicy_types.goRepository: api7/api7-ingress-controller Length of output: 42031 🏁 Script executed: printf '%s\n' '--- complete BackendTrafficPolicy Timeout documentation ---'
sed -n '245,272p' docs/en/latest/reference/api-reference.md
sed -n '665,692p' docs/en/latest/reference/api-reference.md
printf '%s\n' '--- exact timeout declarations and comments ---'
rg -n -C 10 -F -- 'type Timeout struct' api/v1alpha1/backendtrafficpolicy_types.go
rg -n -C 10 -F -- 'type UpstreamTimeout struct' api/v2Repository: api7/api7-ingress-controller Length of output: 5930 Align BackendTrafficPolicy validation with fractional durations. The test constructs Update the BackendTrafficPolicy validation pattern and regenerate the CRD so the test covers a supported input. Keep the independent 🤖 Prompt for AI Agents |
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🔎 Supported by static analysis
🏁 Script executed:
Repository: api7/api7-ingress-controller
Length of output: 1103
🏁 Script executed:
Repository: api7/api7-ingress-controller
Length of output: 41092
🏁 Script executed:
Repository: api7/api7-ingress-controller
Length of output: 42140
🏁 Script executed:
Repository: api7/api7-ingress-controller
Length of output: 10176
🌐 Web query:
official Apache APISIX schema upstream timeout connect read send greater than zero schema_def.lua💡 Result:
Preserve the fallback for non-positive route timeouts.
cmp.Orretains-0.5for-500ms, so the ADC route receives an invalid timeout instead of the 60-second fallback. The CRD does not constrain these duration strings, while APISIX requires timeout values greater than zero. Map non-positive durations to the default and preserve positive fractional values.🐛 Suggested fix
🤖 Prompt for AI Agents
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to the CRDS type definition, should there be no negative values? Please confirm again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Length of output: 20924
🏁 Script executed:
Length of output: 5678
@AlinsRanI checked again. The current ApisixRoute CRD does not prohibit negative timeout values.api/v2/apisixroute_types.go,UpstreamTimeoutusesmetav1.Duration. This type accepts signed durations such as"-500ms".config/crd/bases/apisix.apache.org_apisixroutes.yaml, Line 328–341, the timeout fields have onlytype: string. No pattern or CEL rule requires a non-negative value.Thus,
"-500ms"can reachbuildTimeout, wherecmp.Or(-0.5, 60)returns-0.5.My original wording was too broad: the old code did not default all negative values. It defaulted negative subsecond values only because integer conversion truncated them to zero. Explicitly rejecting negative durations is also a valid solution; defaulting them is not the only option.
The negative-value concern remains valid, but it is a validation gap rather than a general fallback contract.
You are interacting with an AI system.