Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 22 additions & 13 deletions api/adc/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -448,18 +448,28 @@ func (n *UpstreamNodes) UnmarshalJSON(p []byte) error {
return nil
}

// MarshalJSON implements the json.Marshaler interface for UpstreamNodes.
// By default, Go serializes a nil slice as JSON null. However, for compatibility
// with APISIX semantics, we want a nil UpstreamNodes to be encoded as an empty
// array ([]) instead of null. Non-nil slices are marshaled as usual.
//
// See APISIX upstream nodes schema definition for details:
// https://github.com/apache/apisix/blob/77dacda31277a31d6014b4970e36bae2a5c30907/apisix/schema_def.lua#L295-L338
func (n UpstreamNodes) MarshalJSON() ([]byte, error) {
if n == nil {
return []byte("[]"), nil
func (n Upstream) MarshalJSON() ([]byte, error) {
type Alias Upstream
// APISIX does not allow discovery_type and nodes to exist at the same time.
// https://github.com/apache/apisix/blob/01b4b49eb2ba642b337f7a1fbe1894a77942910b/apisix/schema_def.lua#L501-L504
if n.DiscoveryType != "" {
aux := struct {
Alias
Nodes UpstreamNodes `json:"nodes,omitempty" yaml:"nodes,omitempty"`
}{
Alias: (Alias)(n),
}
aux.Nodes = nil
return json.Marshal(&aux)
}

// By default Go serializes a nil slice as JSON null.
// For APISIX compatibility, nil UpstreamNodes should be encoded as [] instead.
// https://github.com/apache/apisix/blob/77dacda31277a31d6014b4970e36bae2a5c30907/apisix/schema_def.lua#L295-L338
if n.Nodes == nil {
n.Nodes = UpstreamNodes{}
}
return json.Marshal([]UpstreamNode(n))
return json.Marshal((Alias)(n))
}

// ComposeRouteName uses namespace, name and rule name to compose
Expand Down Expand Up @@ -571,8 +581,7 @@ func NewDefaultUpstream() *Upstream {
"managed-by": "apisix-ingress-controller",
},
},
Nodes: make(UpstreamNodes, 0),
Type: Roundrobin,
Type: Roundrobin,
}
}

Expand Down
1 change: 0 additions & 1 deletion api/v2/apisixupstream_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,6 @@ type ApisixUpstreamConfig struct {
UpstreamHost string `json:"upstreamHost,omitempty" yaml:"upstreamHost,omitempty"`

// Discovery configures service discovery for the upstream.
// Deprecated: no longer supported in standalone mode.
// +kubebuilder:validation:Optional
Discovery *Discovery `json:"discovery,omitempty" yaml:"discovery,omitempty"`
}
Expand Down
9 changes: 3 additions & 6 deletions config/crd/bases/apisix.apache.org_apisixupstreams.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,7 @@ spec:
description: ApisixUpstreamSpec defines the upstream configuration.
properties:
discovery:
description: |-
Discovery configures service discovery for the upstream.
Deprecated: no longer supported in standalone mode.
description: Discovery configures service discovery for the upstream.
properties:
args:
additionalProperties:
Expand Down Expand Up @@ -337,9 +335,8 @@ spec:
them if they are set on the port level.
properties:
discovery:
description: |-
Discovery configures service discovery for the upstream.
Deprecated: no longer supported in standalone mode.
description: Discovery configures service discovery for the
upstream.
properties:
args:
additionalProperties:
Expand Down
6 changes: 3 additions & 3 deletions docs/en/latest/reference/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -1325,7 +1325,7 @@ ApisixUpstreamConfig defines configuration for upstream services.
| `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`:<br /> • `pass`: preserve the original Host header<br /> • `node`: use the upstream node’s host<br /> • `rewrite`: set to a custom host via upstreamHost |
| `upstreamHost` _string_ | UpstreamHost sets a custom Host header when passHost is set to `rewrite`. |
| `discovery` _[Discovery](#discovery)_ | Discovery configures service discovery for the upstream. Deprecated: no longer supported in standalone mode. |
| `discovery` _[Discovery](#discovery)_ | Discovery configures service discovery for the upstream. |


_Appears in:_
Expand Down Expand Up @@ -1385,7 +1385,7 @@ definitions and custom configuration.
| `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`:<br /> • `pass`: preserve the original Host header<br /> • `node`: use the upstream node’s host<br /> • `rewrite`: set to a custom host via upstreamHost |
| `upstreamHost` _string_ | UpstreamHost sets a custom Host header when passHost is set to `rewrite`. |
| `discovery` _[Discovery](#discovery)_ | Discovery configures service discovery for the upstream. Deprecated: no longer supported in standalone mode. |
| `discovery` _[Discovery](#discovery)_ | Discovery configures service discovery for the upstream. |
| `portLevelSettings` _[PortLevelSettings](#portlevelsettings) array_ | PortLevelSettings allows fine-grained upstream configuration for specific ports, useful when a backend service exposes multiple ports with different behaviors or protocols. |


Expand Down Expand Up @@ -1555,7 +1555,7 @@ them if they are set on the port level.
| `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`:<br /> • `pass`: preserve the original Host header<br /> • `node`: use the upstream node’s host<br /> • `rewrite`: set to a custom host via upstreamHost |
| `upstreamHost` _string_ | UpstreamHost sets a custom Host header when passHost is set to `rewrite`. |
| `discovery` _[Discovery](#discovery)_ | Discovery configures service discovery for the upstream. Deprecated: no longer supported in standalone mode. |
| `discovery` _[Discovery](#discovery)_ | Discovery configures service discovery for the upstream. |
| `port` _integer_ | Port is a Kubernetes Service port. |


Expand Down
8 changes: 0 additions & 8 deletions docs/en/latest/upgrade-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,14 +138,6 @@ spec:

### API Changes

#### `ApisixUpstream`

Due to current limitations in the [ADC](https://github.com/api7/adc) component, the following fields are not yet supported:

* `spec.discovery`: Service Discovery

More details: [ADC Backend Differences](https://github.com/api7/adc/blob/2449ca81e3c61169f8c1e59efb4c1173a766bce2/libs/backend-apisix-standalone/README.md#differences-in-upstream)

#### `ApisixClusterConfig`

The `ApisixClusterConfig` CRD has been removed in 2.0.0. global rules and configurations should now be managed through the `ApisixGlobalRule` CRDs.
Expand Down
2 changes: 1 addition & 1 deletion internal/adc/translator/apisixroute.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ func (t *Translator) buildUpstream(tctx *provider.TranslateContext, service *adc
}

// no valid upstream
if len(upstreams) == 0 || len(upstreams[0].Nodes) == 0 {
if len(upstreams) == 0 {
return
}

Expand Down
16 changes: 16 additions & 0 deletions internal/adc/translator/apisixupstream.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ import (
"cmp"
"fmt"

"github.com/api7/gopkg/pkg/log"
"github.com/pkg/errors"
"go.uber.org/zap"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"

Expand All @@ -40,6 +42,7 @@ func (t *Translator) translateApisixUpstream(tctx *provider.TranslateContext, au
translateApisixUpstreamRetriesAndTimeout,
translateApisixUpstreamPassHost,
translateUpstreamHealthCheck,
translateUpstreamDiscovery,
} {
if err = f(au, ups); err != nil {
return
Expand All @@ -54,6 +57,8 @@ func (t *Translator) translateApisixUpstream(tctx *provider.TranslateContext, au
}
}

log.Debugw("translated ApisixUpstream", zap.Any("upstream", ups),
zap.String("namespace", au.Namespace), zap.String("name", au.Name))
return
}

Expand Down Expand Up @@ -340,3 +345,14 @@ func translateUpstreamPassiveHealthCheck(config *apiv2.PassiveHealthCheck) *adc.
}
return &passive
}

func translateUpstreamDiscovery(au *apiv2.ApisixUpstream, ups *adc.Upstream) error {
discovery := au.Spec.Discovery
if discovery == nil {
return nil
}
ups.ServiceName = discovery.ServiceName
ups.DiscoveryType = discovery.Type
ups.DiscoveryArgs = discovery.Args
return nil
}
50 changes: 50 additions & 0 deletions test/e2e/crds/v2/upstream.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,4 +135,54 @@ spec:
}
})
})

Context("external service discovery", func() {
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: httpbin-dns
`

au := `
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
name: httpbin-dns
spec:
ingressClassName: %s
discovery:
type: dns
serviceName: %s
`

It("should be able to access through service discovery", func() {
if framework.ProviderType == framework.ProviderTypeAPI7EE {
Skip("api7ee does not support DNS service discovery")
}
svcName := fmt.Sprintf("httpbin-service-e2e-test.%s.svc.cluster.local", s.Namespace())
applier.MustApplyAPIv2(types.NamespacedName{Namespace: s.Namespace(), Name: "httpbin-dns"},
&apiv2.ApisixUpstream{}, fmt.Sprintf(au, s.Namespace(), svcName))
applier.MustApplyAPIv2(types.NamespacedName{Namespace: s.Namespace(), Name: "httpbin-route"},
&apiv2.ApisixRoute{}, fmt.Sprintf(ar, s.Namespace()))

s.RequestAssert(&scaffold.RequestAssert{
Method: "GET",
Path: "/ip",
Host: "httpbin.org",
Check: scaffold.WithExpectedStatus(200),
})
})
})
})
5 changes: 5 additions & 0 deletions test/e2e/framework/manifests/apisix-standalone.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ data:
- 9100
udp: # UDP proxy port list
- 9200
discovery:
dns:
servers:
- "10.96.0.10:53" # use the real address of your dns server.
# currently we use KIND as the standard test environment, so here we can hard-code the default DNS address first.
---
apiVersion: apps/v1
kind: Deployment
Expand Down
5 changes: 5 additions & 0 deletions test/e2e/framework/manifests/apisix.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ data:
- 9100
udp: # UDP proxy port list
- 9200
discovery:
dns:
servers:
- "10.96.0.10:53" # use the real address of your dns server.
# currently we use KIND as the standard test environment, so here we can hard-code the default DNS address first.
---
apiVersion: apps/v1
kind: Deployment
Expand Down
2 changes: 2 additions & 0 deletions test/e2e/scaffold/httpbin.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import (
)

var (
HTTPBinServiceName = "httpbin-service-e2e-test"

_httpbinDeploymentTemplate = `
apiVersion: apps/v1
kind: Deployment
Expand Down
Loading