Skip to content

Commit 7b3deb5

Browse files
feat: add support for host pass in upstream crd (#1889)
Co-authored-by: Katlinsky, Ilya <[email protected]>
1 parent 14e3c61 commit 7b3deb5

File tree

7 files changed

+292
-35
lines changed

7 files changed

+292
-35
lines changed

docs/en/latest/references/apisix_upstream.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,5 @@ See the [definition](https://github.com/apache/apisix-ingress-controller/blob/ma
8383
| discovery.serviceName | string | Name of the upstream service. |
8484
| discovery.type | string | Types of Service Discovery, which indicates what registry in APISIX the discovery uses. Should match the entry in APISIX's config. Can refer to the [doc](https://apisix.apache.org/docs/apisix/discovery/) |
8585
| discovery.args | object | Args map for discovery-spcefic parameters. Also can refer to the [doc](https://apisix.apache.org/docs/apisix/discovery/) |
86+
| passHost | string | Configures the host when the request is forwarded to the upstream. Can be one of pass, node or rewrite. Defaults to pass if not specified: pass - transparently passes the client's host to the Upstream, node - uses the host configured in the node of the Upstream, rewrite - uses the value configured in upstreamHost.
87+
| upstreamHost | string | Specifies the host of the Upstream request. This is only valid if the passHost is set to rewrite.

pkg/kube/apisix/apis/config/v2/types.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,16 @@ type ApisixUpstreamConfig struct {
543543
// +optional
544544
Subsets []ApisixUpstreamSubset `json:"subsets,omitempty" yaml:"subsets,omitempty"`
545545

546+
// Configures the host when the request is forwarded to the upstream.
547+
// Can be one of pass, node or rewrite.
548+
// +optional
549+
PassHost string `json:"passHost,omitempty" yaml:"passHost,omitempty"`
550+
551+
// Specifies the host of the Upstream request. This is only valid if
552+
// the pass_host is set to rewrite
553+
// +optional
554+
UpstreamHost string `json:"upstreamHost,omitempty" yaml:"upstreamHost,omitempty"`
555+
546556
// Discovery is used to configure service discovery for upstream.
547557
// +optional
548558
Discovery *Discovery `json:"discovery,omitempty" yaml:"discovery,omitempty"`

pkg/providers/translation/apisix_upstream.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ import (
2121
apisixv1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1"
2222
)
2323

24+
type passHostConfig struct {
25+
passHost string
26+
upstreamHost string
27+
}
28+
2429
func (t *translator) TranslateUpstreamConfigV2(au *configv2.ApisixUpstreamConfig) (*apisixv1.Upstream, error) {
2530
ups := apisixv1.NewDefaultUpstream()
2631
if err := t.translateUpstreamScheme(au.Scheme, ups); err != nil {
@@ -38,6 +43,9 @@ func (t *translator) TranslateUpstreamConfigV2(au *configv2.ApisixUpstreamConfig
3843
if err := t.translateClientTLSV2(au.TLSSecret, ups); err != nil {
3944
return nil, err
4045
}
46+
if err := t.translatePassHost(&passHostConfig{au.PassHost, au.UpstreamHost}, ups); err != nil {
47+
return nil, err
48+
}
4149
if err := t.translateUpstreamDiscovery(au.Discovery, ups); err != nil {
4250
return nil, err
4351
}
@@ -368,3 +376,16 @@ func (t *translator) translateUpstreamPassiveHealthCheckV2(config *configv2.Pass
368376
}
369377
return &passive, nil
370378
}
379+
380+
func (t *translator) translatePassHost(ph *passHostConfig, ups *apisixv1.Upstream) error {
381+
switch ph.passHost {
382+
case "", apisixv1.PassHostPass, apisixv1.PassHostNode, apisixv1.PassHostRewrite:
383+
ups.PassHost = ph.passHost
384+
default:
385+
return &TranslateError{Field: "passHost", Reason: "invalid value"}
386+
}
387+
388+
ups.UpstreamHost = ph.upstreamHost
389+
390+
return nil
391+
}

pkg/providers/translation/apisix_upstream_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,3 +409,50 @@ func TestUpstreamRetriesAndTimeoutV2(t *testing.T) {
409409
Read: 15,
410410
}, ups.Timeout)
411411
}
412+
413+
func TestUpstreamPassHost(t *testing.T) {
414+
tr := &translator{}
415+
tests := []struct {
416+
name string
417+
phc *passHostConfig
418+
wantFunc func(t *testing.T, err error, ups *apisixv1.Upstream, phc *passHostConfig)
419+
}{
420+
{
421+
name: "should be empty when settings not set explicitly",
422+
phc: &passHostConfig{},
423+
wantFunc: func(t *testing.T, err error, ups *apisixv1.Upstream, phc *passHostConfig) {
424+
assert.Nil(t, err)
425+
assert.Empty(t, ups.PassHost)
426+
assert.Empty(t, ups.UpstreamHost)
427+
},
428+
},
429+
{
430+
name: "should set passHost to pass",
431+
phc: &passHostConfig{passHost: apisixv1.PassHostPass},
432+
wantFunc: func(t *testing.T, err error, ups *apisixv1.Upstream, phc *passHostConfig) {
433+
assert.Nil(t, err)
434+
assert.Equal(t, phc.passHost, ups.PassHost)
435+
assert.Empty(t, ups.UpstreamHost)
436+
},
437+
},
438+
{
439+
name: "should fail when passHost set to invalid value",
440+
phc: &passHostConfig{passHost: "unknown"},
441+
wantFunc: func(t *testing.T, err error, ups *apisixv1.Upstream, phc *passHostConfig) {
442+
assert.Equal(t, &TranslateError{
443+
Field: "passHost",
444+
Reason: "invalid value",
445+
}, err)
446+
},
447+
},
448+
}
449+
450+
for _, tt := range tests {
451+
t.Run(tt.name, func(t *testing.T) {
452+
ups := apisixv1.NewDefaultUpstream()
453+
err := tr.translatePassHost(tt.phc, ups)
454+
455+
tt.wantFunc(t, err, ups, tt.phc)
456+
})
457+
}
458+
}

pkg/types/apisix/v1/types.go

Lines changed: 52 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,13 @@ const (
7979
// DefaultUpstreamTimeout represents the default connect,
8080
// read and send timeout (in seconds) with upstreams.
8181
DefaultUpstreamTimeout = 60
82+
83+
// PassHostPass represents pass option for pass_host Upstream settings.
84+
PassHostPass = "pass"
85+
// PassHostPass represents node option for pass_host Upstream settings.
86+
PassHostNode = "node"
87+
// PassHostPass represents rewrite option for pass_host Upstream settings.
88+
PassHostRewrite = "rewrite"
8289
)
8390

8491
var ValidSchemes map[string]struct{} = map[string]struct{}{
@@ -196,15 +203,17 @@ func (p *Plugins) DeepCopy() *Plugins {
196203
type Upstream struct {
197204
Metadata `json:",inline" yaml:",inline"`
198205

199-
Type string `json:"type,omitempty" yaml:"type,omitempty"`
200-
HashOn string `json:"hash_on,omitempty" yaml:"hash_on,omitempty"`
201-
Key string `json:"key,omitempty" yaml:"key,omitempty"`
202-
Checks *UpstreamHealthCheck `json:"checks,omitempty" yaml:"checks,omitempty"`
203-
Nodes UpstreamNodes `json:"nodes" yaml:"nodes"`
204-
Scheme string `json:"scheme,omitempty" yaml:"scheme,omitempty"`
205-
Retries *int `json:"retries,omitempty" yaml:"retries,omitempty"`
206-
Timeout *UpstreamTimeout `json:"timeout,omitempty" yaml:"timeout,omitempty"`
207-
TLS *ClientTLS `json:"tls,omitempty" yaml:"tls,omitempty"`
206+
Type string `json:"type,omitempty" yaml:"type,omitempty"`
207+
HashOn string `json:"hash_on,omitempty" yaml:"hash_on,omitempty"`
208+
Key string `json:"key,omitempty" yaml:"key,omitempty"`
209+
Checks *UpstreamHealthCheck `json:"checks,omitempty" yaml:"checks,omitempty"`
210+
Nodes UpstreamNodes `json:"nodes" yaml:"nodes"`
211+
Scheme string `json:"scheme,omitempty" yaml:"scheme,omitempty"`
212+
Retries *int `json:"retries,omitempty" yaml:"retries,omitempty"`
213+
Timeout *UpstreamTimeout `json:"timeout,omitempty" yaml:"timeout,omitempty"`
214+
TLS *ClientTLS `json:"tls,omitempty" yaml:"tls,omitempty"`
215+
PassHost string `json:"pass_host,omitempty" yaml:"pass_host,omitempty"`
216+
UpstreamHost string `json:"upstream_host,omitempty" yaml:"upstream_host,omitempty"`
208217

209218
// for Service Discovery
210219
ServiceName string `json:"service_name,omitempty" yaml:"service_name,omitempty"`
@@ -271,10 +280,12 @@ func (up Upstream) MarshalJSON() ([]byte, error) {
271280
Key string `json:"key,omitempty" yaml:"key,omitempty"`
272281
Checks *UpstreamHealthCheck `json:"checks,omitempty" yaml:"checks,omitempty"`
273282
//Nodes UpstreamNodes `json:"nodes" yaml:"nodes"`
274-
Scheme string `json:"scheme,omitempty" yaml:"scheme,omitempty"`
275-
Retries *int `json:"retries,omitempty" yaml:"retries,omitempty"`
276-
Timeout *UpstreamTimeout `json:"timeout,omitempty" yaml:"timeout,omitempty"`
277-
TLS *ClientTLS `json:"tls,omitempty" yaml:"tls,omitempty"`
283+
Scheme string `json:"scheme,omitempty" yaml:"scheme,omitempty"`
284+
Retries *int `json:"retries,omitempty" yaml:"retries,omitempty"`
285+
Timeout *UpstreamTimeout `json:"timeout,omitempty" yaml:"timeout,omitempty"`
286+
HostPass string `json:"pass_host,omitempty" yaml:"pass_host,omitempty"`
287+
UpstreamHost string `json:"upstream_host,omitempty" yaml:"upstream_host,omitempty"`
288+
TLS *ClientTLS `json:"tls,omitempty" yaml:"tls,omitempty"`
278289

279290
// for Service Discovery
280291
ServiceName string `json:"service_name,omitempty" yaml:"service_name,omitempty"`
@@ -288,10 +299,12 @@ func (up Upstream) MarshalJSON() ([]byte, error) {
288299
Key: up.Key,
289300
Checks: up.Checks,
290301
//Nodes: up.Nodes,
291-
Scheme: up.Scheme,
292-
Retries: up.Retries,
293-
Timeout: up.Timeout,
294-
TLS: up.TLS,
302+
Scheme: up.Scheme,
303+
Retries: up.Retries,
304+
Timeout: up.Timeout,
305+
HostPass: up.PassHost,
306+
UpstreamHost: up.UpstreamHost,
307+
TLS: up.TLS,
295308

296309
ServiceName: up.ServiceName,
297310
DiscoveryType: up.DiscoveryType,
@@ -301,15 +314,17 @@ func (up Upstream) MarshalJSON() ([]byte, error) {
301314
return json.Marshal(&struct {
302315
Metadata `json:",inline" yaml:",inline"`
303316

304-
Type string `json:"type,omitempty" yaml:"type,omitempty"`
305-
HashOn string `json:"hash_on,omitempty" yaml:"hash_on,omitempty"`
306-
Key string `json:"key,omitempty" yaml:"key,omitempty"`
307-
Checks *UpstreamHealthCheck `json:"checks,omitempty" yaml:"checks,omitempty"`
308-
Nodes UpstreamNodes `json:"nodes" yaml:"nodes"`
309-
Scheme string `json:"scheme,omitempty" yaml:"scheme,omitempty"`
310-
Retries *int `json:"retries,omitempty" yaml:"retries,omitempty"`
311-
Timeout *UpstreamTimeout `json:"timeout,omitempty" yaml:"timeout,omitempty"`
312-
TLS *ClientTLS `json:"tls,omitempty" yaml:"tls,omitempty"`
317+
Type string `json:"type,omitempty" yaml:"type,omitempty"`
318+
HashOn string `json:"hash_on,omitempty" yaml:"hash_on,omitempty"`
319+
Key string `json:"key,omitempty" yaml:"key,omitempty"`
320+
Checks *UpstreamHealthCheck `json:"checks,omitempty" yaml:"checks,omitempty"`
321+
Nodes UpstreamNodes `json:"nodes" yaml:"nodes"`
322+
Scheme string `json:"scheme,omitempty" yaml:"scheme,omitempty"`
323+
Retries *int `json:"retries,omitempty" yaml:"retries,omitempty"`
324+
Timeout *UpstreamTimeout `json:"timeout,omitempty" yaml:"timeout,omitempty"`
325+
HostPass string `json:"pass_host,omitempty" yaml:"pass_host,omitempty"`
326+
UpstreamHost string `json:"upstream_host,omitempty" yaml:"upstream_host,omitempty"`
327+
TLS *ClientTLS `json:"tls,omitempty" yaml:"tls,omitempty"`
313328

314329
// for Service Discovery
315330
//ServiceName string `json:"service_name,omitempty" yaml:"service_name,omitempty"`
@@ -318,15 +333,17 @@ func (up Upstream) MarshalJSON() ([]byte, error) {
318333
}{
319334
Metadata: up.Metadata,
320335

321-
Type: up.Type,
322-
HashOn: up.HashOn,
323-
Key: up.Key,
324-
Checks: up.Checks,
325-
Nodes: up.Nodes,
326-
Scheme: up.Scheme,
327-
Retries: up.Retries,
328-
Timeout: up.Timeout,
329-
TLS: up.TLS,
336+
Type: up.Type,
337+
HashOn: up.HashOn,
338+
Key: up.Key,
339+
Checks: up.Checks,
340+
Nodes: up.Nodes,
341+
Scheme: up.Scheme,
342+
Retries: up.Retries,
343+
Timeout: up.Timeout,
344+
HostPass: up.PassHost,
345+
UpstreamHost: up.UpstreamHost,
346+
TLS: up.TLS,
330347

331348
//ServiceName: up.ServiceName,
332349
//DiscoveryType: up.DiscoveryType,

samples/deploy/crd/v1/ApisixUpstream.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,15 @@ spec:
516516
type: string
517517
send:
518518
type: string
519+
passHost:
520+
type: string
521+
enum:
522+
- pass
523+
- node
524+
- rewrite
525+
upstreamHost:
526+
type: string
527+
pattern: "^\\*?[0-9a-zA-Z-._]+$"
519528
tlsSecret:
520529
description: ApisixSecret describes the Kubernetes Secret name and
521530
namespace.

0 commit comments

Comments
 (0)