diff --git a/api/adc/types.go b/api/adc/types.go
index 7ff2d6bc5..124094c58 100644
--- a/api/adc/types.go
+++ b/api/adc/types.go
@@ -204,7 +204,7 @@ type UpstreamActiveHealthCheck struct {
Host string `json:"host,omitempty" yaml:"host,omitempty"`
Port int32 `json:"port,omitempty" yaml:"port,omitempty"`
HTTPPath string `json:"http_path,omitempty" yaml:"http_path,omitempty"`
- HTTPSVerifyCert bool `json:"https_verify_certificate,omitempty" yaml:"https_verify_certificate,omitempty"`
+ HTTPSVerifyCert bool `json:"https_verify_cert,omitempty" yaml:"https_verify_cert,omitempty"`
HTTPRequestHeaders []string `json:"req_headers,omitempty" yaml:"req_headers,omitempty"`
Healthy UpstreamActiveHealthCheckHealthy `json:"healthy,omitempty" yaml:"healthy,omitempty"`
Unhealthy UpstreamActiveHealthCheckUnhealthy `json:"unhealthy,omitempty" yaml:"unhealthy,omitempty"`
diff --git a/api/v2/apisixupstream_types.go b/api/v2/apisixupstream_types.go
index 3c0f814cd..a1562618a 100644
--- a/api/v2/apisixupstream_types.go
+++ b/api/v2/apisixupstream_types.go
@@ -91,7 +91,10 @@ type ApisixUpstreamExternalNode struct {
Weight *int `json:"weight,omitempty" yaml:"weight"`
// Port specifies the port number on which the external node is accepting traffic.
+ //
// +kubebuilder:validation:Optional
+ // +kubebuilder:validation:Minimum=1
+ // +kubebuilder:validation:Maximum=65535
Port *int `json:"port,omitempty" yaml:"port"`
}
@@ -118,7 +121,6 @@ type ApisixUpstreamConfig struct {
Timeout *UpstreamTimeout `json:"timeout,omitempty" yaml:"timeout,omitempty"`
// HealthCheck defines the active and passive health check configuration for the upstream.
- // Deprecated: no longer supported in standalone mode.
// +kubebuilder:validation:Optional
HealthCheck *HealthCheck `json:"healthCheck,omitempty" yaml:"healthCheck,omitempty"`
@@ -160,6 +162,8 @@ type PortLevelSettings struct {
ApisixUpstreamConfig `json:",inline" yaml:",inline"`
// Port is a Kubernetes Service port.
+ // +kubebuilder:validation:Minimum=1
+ // +kubebuilder:validation:Maximum=65535
Port int32 `json:"port" yaml:"port"`
}
@@ -221,9 +225,11 @@ type Discovery struct {
// ActiveHealthCheck defines the active upstream health check configuration.
type ActiveHealthCheck struct {
+ // Type is the health check type. Can be `http`, `https`, or `tcp`.
+ //
// +kubebuilder:validation:Optional
// +kubebuilder:validation:Enum=http;https;tcp;
- // Type is the health check type. Can be `http`, `https`, or `tcp`.
+ // +kubebuilder:default=http
Type string `json:"type,omitempty" yaml:"type,omitempty"`
// Timeout sets health check timeout in seconds.
Timeout time.Duration `json:"timeout,omitempty" yaml:"timeout,omitempty"`
@@ -232,9 +238,10 @@ type ActiveHealthCheck struct {
Concurrency int `json:"concurrency,omitempty" yaml:"concurrency,omitempty"`
// Host sets the upstream host.
Host string `json:"host,omitempty" yaml:"host,omitempty"`
- // +kubebuilder:validation:Minimum=0
- // +kubebuilder:validation:Maximum=65535
// Port sets the upstream port.
+ //
+ // +kubebuilder:validation:Minimum=1
+ // +kubebuilder:validation:Maximum=65535
Port int32 `json:"port,omitempty" yaml:"port,omitempty"`
// HTTPPath sets the HTTP probe request path.
HTTPPath string `json:"httpPath,omitempty" yaml:"httpPath,omitempty"`
@@ -254,6 +261,10 @@ type ActiveHealthCheck struct {
type PassiveHealthCheck struct {
// Type specifies the type of passive health check.
// Can be `http`, `https`, or `tcp`.
+ //
+ // +kubebuilder:validation:Optional
+ // +kubebuilder:validation:Enum=http;https;tcp;
+ // +kubebuilder:default=http
Type string `json:"type,omitempty" yaml:"type,omitempty"`
// Healthy defines the conditions under which an upstream node is considered healthy.
Healthy *PassiveHealthCheckHealthy `json:"healthy,omitempty" yaml:"healthy,omitempty"`
@@ -304,6 +315,10 @@ type PassiveHealthCheckUnhealthy struct {
// TCPFailures define the number of TCP failures to define an unhealthy target.
TCPFailures int `json:"tcpFailures,omitempty" yaml:"tcpFailures,omitempty"`
// Timeout sets health check timeout in seconds.
+ // https://github.com/apache/apisix/blob/0151d9e35bba63d7c316187272d88e19db0be634/apisix/schema_def.lua#L196
+ //
+ // +kubebuilder:validation:Minimum=1
+ // +kubebuilder:validation:Maximum=254
Timeouts int `json:"timeout,omitempty" yaml:"timeout,omitempty"`
}
diff --git a/config/crd/bases/apisix.apache.org_apisixupstreams.yaml b/config/crd/bases/apisix.apache.org_apisixupstreams.yaml
index 346795191..2dcb2b632 100644
--- a/config/crd/bases/apisix.apache.org_apisixupstreams.yaml
+++ b/config/crd/bases/apisix.apache.org_apisixupstreams.yaml
@@ -81,6 +81,8 @@ spec:
port:
description: Port specifies the port number on which the external
node is accepting traffic.
+ maximum: 65535
+ minimum: 1
type: integer
type:
description: Type indicates the kind of external node. Can be
@@ -95,9 +97,8 @@ spec:
minItems: 1
type: array
healthCheck:
- description: |-
- HealthCheck defines the active and passive health check configuration for the upstream.
- Deprecated: no longer supported in standalone mode.
+ description: HealthCheck defines the active and passive health check
+ configuration for the upstream.
properties:
active:
description: Active health checks proactively send requests to
@@ -140,7 +141,7 @@ spec:
description: Port sets the upstream port.
format: int32
maximum: 65535
- minimum: 0
+ minimum: 1
type: integer
requestHeaders:
description: RequestHeaders sets the request headers.
@@ -155,6 +156,7 @@ spec:
format: int64
type: integer
type:
+ default: http
description: Type is the health check type. Can be `http`,
`https`, or `tcp`.
enum:
@@ -190,7 +192,11 @@ spec:
minimum: 0
type: integer
timeout:
- description: Timeout sets health check timeout in seconds.
+ description: |-
+ Timeout sets health check timeout in seconds.
+ https://github.com/apache/apisix/blob/0151d9e35bba63d7c316187272d88e19db0be634/apisix/schema_def.lua#L196
+ maximum: 254
+ minimum: 1
type: integer
type: object
type: object
@@ -217,9 +223,14 @@ spec:
type: integer
type: object
type:
+ default: http
description: |-
Type specifies the type of passive health check.
Can be `http`, `https`, or `tcp`.
+ enum:
+ - http
+ - https
+ - tcp
type: string
unhealthy:
description: Unhealthy defines the conditions under which
@@ -245,7 +256,11 @@ spec:
minimum: 0
type: integer
timeout:
- description: Timeout sets health check timeout in seconds.
+ description: |-
+ Timeout sets health check timeout in seconds.
+ https://github.com/apache/apisix/blob/0151d9e35bba63d7c316187272d88e19db0be634/apisix/schema_def.lua#L196
+ maximum: 254
+ minimum: 1
type: integer
type: object
type: object
@@ -344,9 +359,8 @@ spec:
- type
type: object
healthCheck:
- description: |-
- HealthCheck defines the active and passive health check configuration for the upstream.
- Deprecated: no longer supported in standalone mode.
+ description: HealthCheck defines the active and passive health
+ check configuration for the upstream.
properties:
active:
description: Active health checks proactively send requests
@@ -389,7 +403,7 @@ spec:
description: Port sets the upstream port.
format: int32
maximum: 65535
- minimum: 0
+ minimum: 1
type: integer
requestHeaders:
description: RequestHeaders sets the request headers.
@@ -404,6 +418,7 @@ spec:
format: int64
type: integer
type:
+ default: http
description: Type is the health check type. Can be `http`,
`https`, or `tcp`.
enum:
@@ -439,8 +454,11 @@ spec:
minimum: 0
type: integer
timeout:
- description: Timeout sets health check timeout in
- seconds.
+ description: |-
+ Timeout sets health check timeout in seconds.
+ https://github.com/apache/apisix/blob/0151d9e35bba63d7c316187272d88e19db0be634/apisix/schema_def.lua#L196
+ maximum: 254
+ minimum: 1
type: integer
type: object
type: object
@@ -467,9 +485,14 @@ spec:
type: integer
type: object
type:
+ default: http
description: |-
Type specifies the type of passive health check.
Can be `http`, `https`, or `tcp`.
+ enum:
+ - http
+ - https
+ - tcp
type: string
unhealthy:
description: Unhealthy defines the conditions under
@@ -495,8 +518,11 @@ spec:
minimum: 0
type: integer
timeout:
- description: Timeout sets health check timeout in
- seconds.
+ description: |-
+ Timeout sets health check timeout in seconds.
+ https://github.com/apache/apisix/blob/0151d9e35bba63d7c316187272d88e19db0be634/apisix/schema_def.lua#L196
+ maximum: 254
+ minimum: 1
type: integer
type: object
type: object
@@ -559,6 +585,8 @@ spec:
port:
description: Port is a Kubernetes Service port.
format: int32
+ maximum: 65535
+ minimum: 1
type: integer
retries:
description: |-
diff --git a/docs/en/latest/reference/api-reference.md b/docs/en/latest/reference/api-reference.md
index 9dbcdd19a..06203d6ff 100644
--- a/docs/en/latest/reference/api-reference.md
+++ b/docs/en/latest/reference/api-reference.md
@@ -661,7 +661,7 @@ UpstreamActiveHealthCheckHealthy defines the conditions used to actively determi
| `httpCodes` _integer array_ | HTTPCodes define a list of HTTP status codes that are considered unhealthy. |
| `httpFailures` _integer_ | HTTPFailures define the number of HTTP failures to define an unhealthy target. |
| `tcpFailures` _integer_ | TCPFailures define the number of TCP failures to define an unhealthy target. |
-| `timeout` _integer_ | Timeout sets health check timeout in seconds. |
+| `timeout` _integer_ | Timeout sets health check timeout in seconds. https://github.com/apache/apisix/blob/0151d9e35bba63d7c316187272d88e19db0be634/apisix/schema_def.lua#L196 |
| `interval` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#duration-v1-meta)_ | Interval defines the time interval for checking targets, in seconds. |
@@ -1320,7 +1320,7 @@ ApisixUpstreamConfig defines configuration for upstream services.
| `scheme` _string_ | Scheme is the protocol used to communicate with the upstream. Default is `http`. Can be `http`, `https`, `grpc`, or `grpcs`. |
| `retries` _integer_ | Retries defines the number of retry attempts APISIX should make when a failure occurs. Failures include timeouts, network errors, or 5xx status codes. |
| `timeout` _[UpstreamTimeout](#upstreamtimeout)_ | Timeout specifies the connection, send, and read timeouts for upstream requests. |
-| `healthCheck` _[HealthCheck](#healthcheck)_ | HealthCheck defines the active and passive health check configuration for the upstream. Deprecated: no longer supported in standalone mode. |
+| `healthCheck` _[HealthCheck](#healthcheck)_ | HealthCheck defines the active and passive health check configuration for the upstream. |
| `tlsSecret` _[ApisixSecret](#apisixsecret)_ | TLSSecret references a Kubernetes Secret that contains the client certificate and key for mutual TLS when connecting to the upstream. |
| `subsets` _[ApisixUpstreamSubset](#apisixupstreamsubset) array_ | Subsets defines labeled subsets of service endpoints, typically used for service versioning or canary deployments. |
| `passHost` _string_ | PassHost configures how the host header should be determined when a request is forwarded to the upstream. Default is `pass`. Can be `pass`, `node` or `rewrite`:
• `pass`: preserve the original Host header
• `node`: use the upstream node’s host
• `rewrite`: set to a custom host via upstreamHost |
@@ -1380,7 +1380,7 @@ definitions and custom configuration.
| `scheme` _string_ | Scheme is the protocol used to communicate with the upstream. Default is `http`. Can be `http`, `https`, `grpc`, or `grpcs`. |
| `retries` _integer_ | Retries defines the number of retry attempts APISIX should make when a failure occurs. Failures include timeouts, network errors, or 5xx status codes. |
| `timeout` _[UpstreamTimeout](#upstreamtimeout)_ | Timeout specifies the connection, send, and read timeouts for upstream requests. |
-| `healthCheck` _[HealthCheck](#healthcheck)_ | HealthCheck defines the active and passive health check configuration for the upstream. Deprecated: no longer supported in standalone mode. |
+| `healthCheck` _[HealthCheck](#healthcheck)_ | HealthCheck defines the active and passive health check configuration for the upstream. |
| `tlsSecret` _[ApisixSecret](#apisixsecret)_ | TLSSecret references a Kubernetes Secret that contains the client certificate and key for mutual TLS when connecting to the upstream. |
| `subsets` _[ApisixUpstreamSubset](#apisixupstreamsubset) array_ | Subsets defines labeled subsets of service endpoints, typically used for service versioning or canary deployments. |
| `passHost` _string_ | PassHost configures how the host header should be determined when a request is forwarded to the upstream. Default is `pass`. Can be `pass`, `node` or `rewrite`:
• `pass`: preserve the original Host header
• `node`: use the upstream node’s host
• `rewrite`: set to a custom host via upstreamHost |
@@ -1528,7 +1528,7 @@ UpstreamPassiveHealthCheckUnhealthy defines the conditions used to passively det
| `httpCodes` _integer array_ | HTTPCodes define a list of HTTP status codes that are considered unhealthy. |
| `httpFailures` _integer_ | HTTPFailures define the number of HTTP failures to define an unhealthy target. |
| `tcpFailures` _integer_ | TCPFailures define the number of TCP failures to define an unhealthy target. |
-| `timeout` _integer_ | Timeout sets health check timeout in seconds. |
+| `timeout` _integer_ | Timeout sets health check timeout in seconds. https://github.com/apache/apisix/blob/0151d9e35bba63d7c316187272d88e19db0be634/apisix/schema_def.lua#L196 |
_Appears in:_
@@ -1550,7 +1550,7 @@ them if they are set on the port level.
| `scheme` _string_ | Scheme is the protocol used to communicate with the upstream. Default is `http`. Can be `http`, `https`, `grpc`, or `grpcs`. |
| `retries` _integer_ | Retries defines the number of retry attempts APISIX should make when a failure occurs. Failures include timeouts, network errors, or 5xx status codes. |
| `timeout` _[UpstreamTimeout](#upstreamtimeout)_ | Timeout specifies the connection, send, and read timeouts for upstream requests. |
-| `healthCheck` _[HealthCheck](#healthcheck)_ | HealthCheck defines the active and passive health check configuration for the upstream. Deprecated: no longer supported in standalone mode. |
+| `healthCheck` _[HealthCheck](#healthcheck)_ | HealthCheck defines the active and passive health check configuration for the upstream. |
| `tlsSecret` _[ApisixSecret](#apisixsecret)_ | TLSSecret references a Kubernetes Secret that contains the client certificate and key for mutual TLS when connecting to the upstream. |
| `subsets` _[ApisixUpstreamSubset](#apisixupstreamsubset) array_ | Subsets defines labeled subsets of service endpoints, typically used for service versioning or canary deployments. |
| `passHost` _string_ | PassHost configures how the host header should be determined when a request is forwarded to the upstream. Default is `pass`. Can be `pass`, `node` or `rewrite`:
• `pass`: preserve the original Host header
• `node`: use the upstream node’s host
• `rewrite`: set to a custom host via upstreamHost |
diff --git a/docs/en/latest/upgrade-guide.md b/docs/en/latest/upgrade-guide.md
index 11216386b..a8b3a6d28 100644
--- a/docs/en/latest/upgrade-guide.md
+++ b/docs/en/latest/upgrade-guide.md
@@ -143,7 +143,6 @@ spec:
Due to current limitations in the [ADC](https://github.com/api7/adc) component, the following fields are not yet supported:
* `spec.discovery`: Service Discovery
-* `spec.healthCheck`: Health Checking
More details: [ADC Backend Differences](https://github.com/api7/adc/blob/2449ca81e3c61169f8c1e59efb4c1173a766bce2/libs/backend-apisix-standalone/README.md#differences-in-upstream)
diff --git a/internal/adc/translator/apisixupstream.go b/internal/adc/translator/apisixupstream.go
index f4faf2980..5a76025ec 100644
--- a/internal/adc/translator/apisixupstream.go
+++ b/internal/adc/translator/apisixupstream.go
@@ -39,6 +39,7 @@ func (t *Translator) translateApisixUpstream(tctx *provider.TranslateContext, au
translateApisixUpstreamLoadBalancer,
translateApisixUpstreamRetriesAndTimeout,
translateApisixUpstreamPassHost,
+ translateUpstreamHealthCheck,
} {
if err = f(au, ups); err != nil {
return
@@ -252,3 +253,90 @@ func translateApisixUpstreamExternalNodesService(tctx *provider.TranslateContext
return nil
}
+
+func translateUpstreamHealthCheck(au *apiv2.ApisixUpstream, ups *adc.Upstream) error {
+ if au == nil {
+ return nil
+ }
+ healcheck := au.Spec.HealthCheck
+ if healcheck == nil || (healcheck.Passive == nil && healcheck.Active == nil) {
+ return nil
+ }
+ var hc adc.UpstreamHealthCheck
+ if healcheck.Passive != nil {
+ hc.Passive = translateUpstreamPassiveHealthCheck(healcheck.Passive)
+ }
+
+ if healcheck.Active != nil {
+ active, err := translateUpstreamActiveHealthCheck(healcheck.Active)
+ if err != nil {
+ return err
+ }
+ hc.Active = active
+ }
+
+ ups.Checks = &hc
+ return nil
+}
+
+func translateUpstreamActiveHealthCheck(config *apiv2.ActiveHealthCheck) (*adc.UpstreamActiveHealthCheck, error) {
+ var active adc.UpstreamActiveHealthCheck
+ if config.Type == "" {
+ config.Type = apiv2.HealthCheckHTTP
+ }
+
+ active.Timeout = int(config.Timeout.Seconds())
+ active.Port = config.Port
+ active.Concurrency = config.Concurrency
+ active.Host = config.Host
+ active.HTTPPath = config.HTTPPath
+ active.HTTPRequestHeaders = config.RequestHeaders
+
+ if config.StrictTLS == nil || *config.StrictTLS {
+ active.HTTPSVerifyCert = true
+ }
+
+ if config.Healthy != nil {
+ active.Healthy.Successes = config.Healthy.Successes
+ active.Healthy.HTTPStatuses = config.Healthy.HTTPCodes
+
+ if config.Healthy.Interval.Duration < apiv2.ActiveHealthCheckMinInterval {
+ return nil, fmt.Errorf(`"healthCheck.active.healthy.interval" has invalid value`)
+ }
+ active.Healthy.Interval = int(config.Healthy.Interval.Seconds())
+ }
+
+ if config.Unhealthy != nil {
+ active.Unhealthy.HTTPFailures = config.Unhealthy.HTTPFailures
+ active.Unhealthy.TCPFailures = config.Unhealthy.TCPFailures
+ active.Unhealthy.Timeouts = config.Unhealthy.Timeouts
+ active.Unhealthy.HTTPStatuses = config.Unhealthy.HTTPCodes
+
+ if config.Unhealthy.Interval.Duration < apiv2.ActiveHealthCheckMinInterval {
+ return nil, fmt.Errorf(`"healthCheck.active.unhealthy.interval" has invalid value`)
+ }
+ active.Unhealthy.Interval = int(config.Unhealthy.Interval.Seconds())
+ }
+
+ return &active, nil
+}
+
+func translateUpstreamPassiveHealthCheck(config *apiv2.PassiveHealthCheck) *adc.UpstreamPassiveHealthCheck {
+ var passive adc.UpstreamPassiveHealthCheck
+ if config.Type == "" {
+ config.Type = apiv2.HealthCheckHTTP
+ }
+
+ if config.Healthy != nil {
+ passive.Healthy.Successes = config.Healthy.Successes
+ passive.Healthy.HTTPStatuses = config.Healthy.HTTPCodes
+ }
+
+ if config.Unhealthy != nil {
+ passive.Unhealthy.HTTPFailures = config.Unhealthy.HTTPFailures
+ passive.Unhealthy.TCPFailures = config.Unhealthy.TCPFailures
+ passive.Unhealthy.Timeouts = config.Unhealthy.Timeouts
+ passive.Unhealthy.HTTPStatuses = config.Unhealthy.HTTPCodes
+ }
+ return &passive
+}
diff --git a/internal/adc/translator/translator.go b/internal/adc/translator/translator.go
index 0d50661a0..4c9bf0d84 100644
--- a/internal/adc/translator/translator.go
+++ b/internal/adc/translator/translator.go
@@ -34,7 +34,6 @@ func NewTranslator(log logr.Logger) *Translator {
}
type TranslateResult struct {
- Routes []*adctypes.Route
Services []*adctypes.Service
SSL []*adctypes.SSL
GlobalRules adctypes.GlobalRule
diff --git a/test/e2e/crds/v2/upstream.go b/test/e2e/crds/v2/upstream.go
new file mode 100644
index 000000000..7d7d9a614
--- /dev/null
+++ b/test/e2e/crds/v2/upstream.go
@@ -0,0 +1,138 @@
+// 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 v2
+
+import (
+ "context"
+ "fmt"
+ "time"
+
+ . "github.com/onsi/ginkgo/v2"
+ . "github.com/onsi/gomega"
+ "k8s.io/apimachinery/pkg/types"
+
+ apiv2 "github.com/apache/apisix-ingress-controller/api/v2"
+ "github.com/apache/apisix-ingress-controller/test/e2e/framework"
+ "github.com/apache/apisix-ingress-controller/test/e2e/scaffold"
+)
+
+var _ = Describe("Test ApisixUpstream", Label("apisix.apache.org", "v2", "apisixupstream"), func() {
+ var (
+ s = scaffold.NewDefaultScaffold()
+ applier = framework.NewApplier(s.GinkgoT, s.K8sClient, s.CreateResourceFromString)
+ )
+ BeforeEach(func() {
+ By("create GatewayProxy")
+ err := s.CreateResourceFromString(s.GetGatewayProxySpec())
+ Expect(err).NotTo(HaveOccurred(), "creating GatewayProxy")
+ time.Sleep(5 * time.Second)
+
+ By("create IngressClass")
+ err = s.CreateResourceFromStringWithNamespace(s.GetIngressClassYaml(), "")
+ Expect(err).NotTo(HaveOccurred(), "creating IngressClass")
+ time.Sleep(5 * time.Second)
+ })
+
+ Context("Health Check", func() {
+ It("active and passive", func() {
+ auWithHealthcheck := `
+apiVersion: apisix.apache.org/v2
+kind: ApisixUpstream
+metadata:
+ name: active
+spec:
+ ingressClassName: %s
+ externalNodes:
+ - type: Domain
+ name: httpbin-service-e2e-test
+ - type: Domain
+ name: invalid.httpbin.host
+ - type: Domain
+ name: invalid1.httpbin.host
+ retries: 1
+ healthCheck:
+ active:
+ type: http
+ httpPath: /ip
+ healthy:
+ httpCodes: [200]
+ interval: 1s
+ unhealthy:
+ httpFailures: 2
+ interval: 1s
+ passive:
+ healthy:
+ httpCodes: [200]
+ unhealthy:
+ httpCodes: [502]
+`
+ applier.MustApplyAPIv2(types.NamespacedName{Namespace: s.Namespace(), Name: "active"},
+ &apiv2.ApisixUpstream{}, fmt.Sprintf(auWithHealthcheck, s.Namespace()))
+
+ ar := `
+apiVersion: apisix.apache.org/v2
+kind: ApisixRoute
+metadata:
+ name: httpbin-route
+spec:
+ ingressClassName: %s
+ http:
+ - name: rule1
+ match:
+ hosts:
+ - httpbin.org
+ paths:
+ - /*
+ upstreams:
+ - name: active
+`
+ applier.MustApplyAPIv2(types.NamespacedName{Namespace: s.Namespace(), Name: "httpbin-route"},
+ &apiv2.ApisixRoute{}, fmt.Sprintf(ar, s.Namespace()))
+
+ By("triggering the health check")
+ s.RequestAssert(&scaffold.RequestAssert{
+ Method: "GET",
+ Path: "/ip",
+ Host: "httpbin.org",
+ })
+ time.Sleep(2 * time.Second)
+
+ ups, err := s.Deployer.DefaultDataplaneResource().Upstream().List(context.Background())
+ Expect(err).ToNot(HaveOccurred(), "listing upstreams")
+ Expect(ups).To(HaveLen(1), "the number of upstreams")
+ Expect(ups[0].Nodes).To(HaveLen(3), "the number of upstream nodes")
+ Expect(ups[0].Checks).ToNot(BeNil(), "the healthcheck configuration")
+ Expect(ups[0].Checks.Active).ToNot(BeNil(), "the active healthcheck configuration")
+ Expect(ups[0].Checks.Active.Healthy).ToNot(BeNil(), "the active healthy configuration")
+ Expect(ups[0].Checks.Active.Unhealthy).ToNot(BeNil(), "the active unhealthy configuration")
+ Expect(ups[0].Checks.Active.Healthy.Interval).To(Equal(1), "the healthy interval")
+ Expect(ups[0].Checks.Active.Healthy.HTTPStatuses).To(Equal([]int{200}), "the healthy http status")
+ Expect(ups[0].Checks.Active.Unhealthy.Interval).To(Equal(1), "the unhealthy interval")
+ Expect(ups[0].Checks.Active.Unhealthy.HTTPFailures).To(Equal(2), "the unhealthy http failures")
+ Expect(ups[0].Checks.Passive).ToNot(BeNil(), "the passive healthcheck configuration")
+ Expect(ups[0].Checks.Passive.Healthy).ToNot(BeNil(), "the passive healthy configuration")
+ Expect(ups[0].Checks.Passive.Unhealthy).ToNot(BeNil(), "the passive unhealthy configuration")
+ Expect(ups[0].Checks.Passive.Healthy.HTTPStatuses).To(Equal([]int{200}), "the passive healthy http status")
+ Expect(ups[0].Checks.Passive.Unhealthy.HTTPStatuses).To(Equal([]int{502}), "the passive unhealthy http status")
+
+ for range 100 {
+ s.NewAPISIXClient().GET("/ip").WithHost("httpbin.org").Expect().Status(200)
+ }
+ })
+ })
+})