Skip to content

Commit 0c19a9d

Browse files
committed
feat: translate BackendTrafficPolicy health checks to APISIX upstream
1 parent f839117 commit 0c19a9d

2 files changed

Lines changed: 241 additions & 0 deletions

File tree

internal/adc/translator/httproute_test.go

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ package translator
2020
import (
2121
"context"
2222
"testing"
23+
"time"
2324

2425
"github.com/go-logr/logr"
2526
"github.com/stretchr/testify/assert"
@@ -32,6 +33,7 @@ import (
3233
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
3334
gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
3435

36+
adctypes "github.com/apache/apisix-ingress-controller/api/adc"
3537
"github.com/apache/apisix-ingress-controller/api/v1alpha1"
3638
apiv2 "github.com/apache/apisix-ingress-controller/api/v2"
3739
"github.com/apache/apisix-ingress-controller/internal/provider"
@@ -148,3 +150,162 @@ func TestTranslateHTTPRouteUpstreamScheme(t *testing.T) {
148150
})
149151
}
150152
}
153+
154+
func TestAttachBackendTrafficPolicyHealthCheck(t *testing.T) {
155+
trueVal := true
156+
falseVal := false
157+
158+
tests := []struct {
159+
name string
160+
policy *v1alpha1.BackendTrafficPolicy
161+
wantChecks *adctypes.UpstreamHealthCheck
162+
}{
163+
{
164+
name: "nil health check produces no checks",
165+
policy: &v1alpha1.BackendTrafficPolicy{},
166+
wantChecks: nil,
167+
},
168+
{
169+
name: "active health check with all fields",
170+
policy: &v1alpha1.BackendTrafficPolicy{
171+
Spec: v1alpha1.BackendTrafficPolicySpec{
172+
HealthCheck: &v1alpha1.HealthCheck{
173+
Active: &v1alpha1.ActiveHealthCheck{
174+
Type: "http",
175+
Timeout: metav1.Duration{Duration: 3 * time.Second},
176+
HTTPPath: "/healthz",
177+
Concurrency: 10,
178+
Host: "example.com",
179+
Port: 8080,
180+
StrictTLS: &trueVal,
181+
RequestHeaders: []string{"X-Custom: value"},
182+
Healthy: &v1alpha1.ActiveHealthCheckHealthy{
183+
Interval: metav1.Duration{Duration: 5 * time.Second},
184+
PassiveHealthCheckHealthy: v1alpha1.PassiveHealthCheckHealthy{
185+
HTTPCodes: []int{200, 201},
186+
Successes: 3,
187+
},
188+
},
189+
Unhealthy: &v1alpha1.ActiveHealthCheckUnhealthy{
190+
Interval: metav1.Duration{Duration: 2 * time.Second},
191+
PassiveHealthCheckUnhealthy: v1alpha1.PassiveHealthCheckUnhealthy{
192+
HTTPCodes: []int{500, 503},
193+
HTTPFailures: 5,
194+
TCPFailures: 2,
195+
Timeouts: 3,
196+
},
197+
},
198+
},
199+
},
200+
},
201+
},
202+
wantChecks: &adctypes.UpstreamHealthCheck{
203+
Active: &adctypes.UpstreamActiveHealthCheck{
204+
Type: "http",
205+
Timeout: 3,
206+
HTTPPath: "/healthz",
207+
Concurrency: 10,
208+
Host: "example.com",
209+
Port: 8080,
210+
HTTPSVerifyCertificate: true,
211+
HTTPRequestHeaders: []string{"X-Custom: value"},
212+
Healthy: adctypes.UpstreamActiveHealthCheckHealthy{
213+
Interval: 5,
214+
UpstreamPassiveHealthCheckHealthy: adctypes.UpstreamPassiveHealthCheckHealthy{
215+
HTTPStatuses: []int{200, 201},
216+
Successes: 3,
217+
},
218+
},
219+
Unhealthy: adctypes.UpstreamActiveHealthCheckUnhealthy{
220+
Interval: 2,
221+
UpstreamPassiveHealthCheckUnhealthy: adctypes.UpstreamPassiveHealthCheckUnhealthy{
222+
HTTPStatuses: []int{500, 503},
223+
HTTPFailures: 5,
224+
TCPFailures: 2,
225+
Timeouts: 3,
226+
},
227+
},
228+
},
229+
},
230+
},
231+
{
232+
name: "strictTLS false disables certificate verification",
233+
policy: &v1alpha1.BackendTrafficPolicy{
234+
Spec: v1alpha1.BackendTrafficPolicySpec{
235+
HealthCheck: &v1alpha1.HealthCheck{
236+
Active: &v1alpha1.ActiveHealthCheck{
237+
StrictTLS: &falseVal,
238+
Healthy: &v1alpha1.ActiveHealthCheckHealthy{
239+
Interval: metav1.Duration{Duration: 1 * time.Second},
240+
},
241+
},
242+
},
243+
},
244+
},
245+
wantChecks: &adctypes.UpstreamHealthCheck{
246+
Active: &adctypes.UpstreamActiveHealthCheck{
247+
Type: "http",
248+
HTTPSVerifyCertificate: false,
249+
Healthy: adctypes.UpstreamActiveHealthCheckHealthy{
250+
Interval: 1,
251+
},
252+
},
253+
},
254+
},
255+
{
256+
name: "active and passive health checks together",
257+
policy: &v1alpha1.BackendTrafficPolicy{
258+
Spec: v1alpha1.BackendTrafficPolicySpec{
259+
HealthCheck: &v1alpha1.HealthCheck{
260+
Active: &v1alpha1.ActiveHealthCheck{
261+
Type: "tcp",
262+
Healthy: &v1alpha1.ActiveHealthCheckHealthy{
263+
Interval: metav1.Duration{Duration: 1 * time.Second},
264+
},
265+
},
266+
Passive: &v1alpha1.PassiveHealthCheck{
267+
Type: "http",
268+
Healthy: &v1alpha1.PassiveHealthCheckHealthy{
269+
HTTPCodes: []int{200},
270+
Successes: 2,
271+
},
272+
Unhealthy: &v1alpha1.PassiveHealthCheckUnhealthy{
273+
HTTPCodes: []int{500},
274+
HTTPFailures: 3,
275+
},
276+
},
277+
},
278+
},
279+
},
280+
wantChecks: &adctypes.UpstreamHealthCheck{
281+
Active: &adctypes.UpstreamActiveHealthCheck{
282+
Type: "tcp",
283+
HTTPSVerifyCertificate: true,
284+
Healthy: adctypes.UpstreamActiveHealthCheckHealthy{
285+
Interval: 1,
286+
},
287+
},
288+
Passive: &adctypes.UpstreamPassiveHealthCheck{
289+
Type: "http",
290+
Healthy: adctypes.UpstreamPassiveHealthCheckHealthy{
291+
HTTPStatuses: []int{200},
292+
Successes: 2,
293+
},
294+
Unhealthy: adctypes.UpstreamPassiveHealthCheckUnhealthy{
295+
HTTPStatuses: []int{500},
296+
HTTPFailures: 3,
297+
},
298+
},
299+
},
300+
},
301+
}
302+
303+
translator := &Translator{Log: logr.Discard()}
304+
for _, tt := range tests {
305+
t.Run(tt.name, func(t *testing.T) {
306+
ups := adctypes.NewDefaultUpstream()
307+
translator.attachBackendTrafficPolicyToUpstream(tt.policy, ups)
308+
assert.Equal(t, tt.wantChecks, ups.Checks)
309+
})
310+
}
311+
}

internal/adc/translator/policies.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,84 @@ func (t *Translator) attachBackendTrafficPolicyToUpstream(policy *v1alpha1.Backe
7979
upstream.HashOn = policy.Spec.LoadBalancer.HashOn
8080
upstream.Key = policy.Spec.LoadBalancer.Key
8181
}
82+
if policy.Spec.HealthCheck != nil {
83+
upstream.Checks = translateBTPHealthCheck(policy.Spec.HealthCheck)
84+
}
85+
}
86+
87+
func translateBTPHealthCheck(hc *v1alpha1.HealthCheck) *adctypes.UpstreamHealthCheck {
88+
if hc == nil || (hc.Active == nil && hc.Passive == nil) {
89+
return nil
90+
}
91+
result := &adctypes.UpstreamHealthCheck{}
92+
if hc.Active != nil {
93+
result.Active = translateBTPActiveHealthCheck(hc.Active)
94+
}
95+
if hc.Passive != nil {
96+
result.Passive = translateBTPPassiveHealthCheck(hc.Passive)
97+
}
98+
return result
99+
}
100+
101+
func translateBTPActiveHealthCheck(config *v1alpha1.ActiveHealthCheck) *adctypes.UpstreamActiveHealthCheck {
102+
t := config.Type
103+
if t == "" {
104+
t = "http"
105+
}
106+
active := &adctypes.UpstreamActiveHealthCheck{
107+
Type: t,
108+
Timeout: int(config.Timeout.Seconds()),
109+
Concurrency: config.Concurrency,
110+
Host: config.Host,
111+
Port: config.Port,
112+
HTTPPath: config.HTTPPath,
113+
HTTPSVerifyCertificate: config.StrictTLS == nil || *config.StrictTLS,
114+
HTTPRequestHeaders: config.RequestHeaders,
115+
}
116+
if config.Healthy != nil {
117+
active.Healthy = adctypes.UpstreamActiveHealthCheckHealthy{
118+
Interval: int(config.Healthy.Interval.Seconds()),
119+
UpstreamPassiveHealthCheckHealthy: adctypes.UpstreamPassiveHealthCheckHealthy{
120+
HTTPStatuses: config.Healthy.HTTPCodes,
121+
Successes: config.Healthy.Successes,
122+
},
123+
}
124+
}
125+
if config.Unhealthy != nil {
126+
active.Unhealthy = adctypes.UpstreamActiveHealthCheckUnhealthy{
127+
Interval: int(config.Unhealthy.Interval.Seconds()),
128+
UpstreamPassiveHealthCheckUnhealthy: adctypes.UpstreamPassiveHealthCheckUnhealthy{
129+
HTTPStatuses: config.Unhealthy.HTTPCodes,
130+
HTTPFailures: config.Unhealthy.HTTPFailures,
131+
TCPFailures: config.Unhealthy.TCPFailures,
132+
Timeouts: config.Unhealthy.Timeouts,
133+
},
134+
}
135+
}
136+
return active
137+
}
138+
139+
func translateBTPPassiveHealthCheck(config *v1alpha1.PassiveHealthCheck) *adctypes.UpstreamPassiveHealthCheck {
140+
t := config.Type
141+
if t == "" {
142+
t = "http"
143+
}
144+
passive := &adctypes.UpstreamPassiveHealthCheck{
145+
Type: t,
146+
}
147+
if config.Healthy != nil {
148+
passive.Healthy = adctypes.UpstreamPassiveHealthCheckHealthy{
149+
HTTPStatuses: config.Healthy.HTTPCodes,
150+
Successes: config.Healthy.Successes,
151+
}
152+
}
153+
if config.Unhealthy != nil {
154+
passive.Unhealthy = adctypes.UpstreamPassiveHealthCheckUnhealthy{
155+
HTTPStatuses: config.Unhealthy.HTTPCodes,
156+
HTTPFailures: config.Unhealthy.HTTPFailures,
157+
TCPFailures: config.Unhealthy.TCPFailures,
158+
Timeouts: config.Unhealthy.Timeouts,
159+
}
160+
}
161+
return passive
82162
}

0 commit comments

Comments
 (0)