Merge branch 'master' of https://github.com/kubernetes/ingress-nginx into proxyssl
This commit is contained in:
commit
65b9e2c574
391 changed files with 23957 additions and 20447 deletions
|
|
@ -39,12 +39,14 @@ import (
|
|||
"k8s.io/ingress-nginx/internal/ingress/annotations/cors"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/customhttperrors"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/defaultbackend"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/fastcgi"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/http2pushpreload"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/influxdb"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/ipwhitelist"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/loadbalancing"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/log"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/luarestywaf"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/mirror"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/portinredirect"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/proxy"
|
||||
|
|
@ -83,6 +85,7 @@ type Ingress struct {
|
|||
CustomHTTPErrors []int
|
||||
DefaultBackend *apiv1.Service
|
||||
//TODO: Change this back into an error when https://github.com/imdario/mergo/issues/100 is resolved
|
||||
FastCGI fastcgi.Config
|
||||
Denied *string
|
||||
ExternalAuth authreq.Config
|
||||
EnableGlobalAuth bool
|
||||
|
|
@ -109,6 +112,7 @@ type Ingress struct {
|
|||
LuaRestyWAF luarestywaf.Config
|
||||
InfluxDB influxdb.Config
|
||||
ModSecurity modsecurity.Config
|
||||
Mirror mirror.Config
|
||||
}
|
||||
|
||||
// Extractor defines the annotation parsers to be used in the extraction of annotations
|
||||
|
|
@ -130,6 +134,7 @@ func NewAnnotationExtractor(cfg resolver.Resolver) Extractor {
|
|||
"CorsConfig": cors.NewParser(cfg),
|
||||
"CustomHTTPErrors": customhttperrors.NewParser(cfg),
|
||||
"DefaultBackend": defaultbackend.NewParser(cfg),
|
||||
"FastCGI": fastcgi.NewParser(cfg),
|
||||
"ExternalAuth": authreq.NewParser(cfg),
|
||||
"EnableGlobalAuth": authreqglobal.NewParser(cfg),
|
||||
"HTTP2PushPreload": http2pushpreload.NewParser(cfg),
|
||||
|
|
@ -156,6 +161,7 @@ func NewAnnotationExtractor(cfg resolver.Resolver) Extractor {
|
|||
"InfluxDB": influxdb.NewParser(cfg),
|
||||
"BackendProtocol": backendprotocol.NewParser(cfg),
|
||||
"ModSecurity": modsecurity.NewParser(cfg),
|
||||
"Mirror": mirror.NewParser(cfg),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ func (m mockCfg) GetAuthCertificate(name string) (*resolver.AuthSSLCert, error)
|
|||
return &resolver.AuthSSLCert{
|
||||
Secret: name,
|
||||
CAFileName: "/opt/ca.pem",
|
||||
PemSHA: "123",
|
||||
CASHA: "123",
|
||||
}, nil
|
||||
}
|
||||
return nil, nil
|
||||
|
|
|
|||
|
|
@ -86,12 +86,7 @@ func (e1 *Config) Equal(e2 *Config) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
match = sets.StringElementsMatch(e1.AuthCacheDuration, e2.AuthCacheDuration)
|
||||
if !match {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
return sets.StringElementsMatch(e1.AuthCacheDuration, e2.AuthCacheDuration)
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ func TestHeaderAnnotations(t *testing.T) {
|
|||
i, err := NewParser(&resolver.Mock{}).Parse(ing)
|
||||
if test.expErr {
|
||||
if err == nil {
|
||||
t.Errorf("%v: expected error but retuned nil", err.Error())
|
||||
t.Error("expected error but retuned nil")
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
|
@ -216,7 +216,7 @@ func TestCacheDurationAnnotations(t *testing.T) {
|
|||
i, err := NewParser(&resolver.Mock{}).Parse(ing)
|
||||
if test.expErr {
|
||||
if err == nil {
|
||||
t.Errorf("%v: expected error but retuned nil", err.Error())
|
||||
t.Errorf("expected error but retuned nil")
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ func (m mockSecret) GetAuthCertificate(name string) (*resolver.AuthSSLCert, erro
|
|||
return &resolver.AuthSSLCert{
|
||||
Secret: "default/demo-secret",
|
||||
CAFileName: "/ssl/ca.crt",
|
||||
PemSHA: "abc",
|
||||
CASHA: "abc",
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
|
@ -202,12 +202,12 @@ func TestEquals(t *testing.T) {
|
|||
sslCert1 := resolver.AuthSSLCert{
|
||||
Secret: "default/demo-secret",
|
||||
CAFileName: "/ssl/ca.crt",
|
||||
PemSHA: "abc",
|
||||
CASHA: "abc",
|
||||
}
|
||||
sslCert2 := resolver.AuthSSLCert{
|
||||
Secret: "default/other-demo-secret",
|
||||
CAFileName: "/ssl/ca.crt",
|
||||
PemSHA: "abc",
|
||||
CASHA: "abc",
|
||||
}
|
||||
cfg1.AuthSSLCert = sslCert1
|
||||
cfg2.AuthSSLCert = sslCert2
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ import (
|
|||
const HTTP = "HTTP"
|
||||
|
||||
var (
|
||||
validProtocols = regexp.MustCompile(`^(HTTP|HTTPS|AJP|GRPC|GRPCS)$`)
|
||||
validProtocols = regexp.MustCompile(`^(HTTP|HTTPS|AJP|GRPC|GRPCS|FCGI)$`)
|
||||
)
|
||||
|
||||
type backendProtocol struct {
|
||||
|
|
|
|||
107
internal/ingress/annotations/fastcgi/main.go
Normal file
107
internal/ingress/annotations/fastcgi/main.go
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed 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 fastcgi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
networking "k8s.io/api/networking/v1beta1"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
|
||||
ing_errors "k8s.io/ingress-nginx/internal/ingress/errors"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
type fastcgi struct {
|
||||
r resolver.Resolver
|
||||
}
|
||||
|
||||
// Config describes the per location fastcgi config
|
||||
type Config struct {
|
||||
Index string `json:"index"`
|
||||
Params map[string]string `json:"params"`
|
||||
}
|
||||
|
||||
// Equal tests for equality between two Configuration types
|
||||
func (l1 *Config) Equal(l2 *Config) bool {
|
||||
if l1 == l2 {
|
||||
return true
|
||||
}
|
||||
|
||||
if l1 == nil || l2 == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if l1.Index != l2.Index {
|
||||
return false
|
||||
}
|
||||
|
||||
return reflect.DeepEqual(l1.Params, l2.Params)
|
||||
}
|
||||
|
||||
// NewParser creates a new fastcgiConfig protocol annotation parser
|
||||
func NewParser(r resolver.Resolver) parser.IngressAnnotation {
|
||||
return fastcgi{r}
|
||||
}
|
||||
|
||||
// ParseAnnotations parses the annotations contained in the ingress
|
||||
// rule used to indicate the fastcgiConfig.
|
||||
func (a fastcgi) Parse(ing *networking.Ingress) (interface{}, error) {
|
||||
|
||||
fcgiConfig := Config{}
|
||||
|
||||
if ing.GetAnnotations() == nil {
|
||||
return fcgiConfig, nil
|
||||
}
|
||||
|
||||
index, err := parser.GetStringAnnotation("fastcgi-index", ing)
|
||||
if err != nil {
|
||||
index = ""
|
||||
}
|
||||
fcgiConfig.Index = index
|
||||
|
||||
cm, err := parser.GetStringAnnotation("fastcgi-params-configmap", ing)
|
||||
if err != nil {
|
||||
return fcgiConfig, nil
|
||||
}
|
||||
|
||||
cmns, cmn, err := cache.SplitMetaNamespaceKey(cm)
|
||||
if err != nil {
|
||||
return fcgiConfig, ing_errors.LocationDenied{
|
||||
Reason: errors.Wrap(err, "error reading configmap name from annotation"),
|
||||
}
|
||||
}
|
||||
|
||||
if cmns == "" {
|
||||
cmns = ing.Namespace
|
||||
}
|
||||
|
||||
cm = fmt.Sprintf("%v/%v", cmns, cmn)
|
||||
cmap, err := a.r.GetConfigMap(cm)
|
||||
if err != nil {
|
||||
return fcgiConfig, ing_errors.LocationDenied{
|
||||
Reason: errors.Wrapf(err, "unexpected error reading configmap %v", cm),
|
||||
}
|
||||
}
|
||||
|
||||
fcgiConfig.Params = cmap.Data
|
||||
|
||||
return fcgiConfig, nil
|
||||
}
|
||||
263
internal/ingress/annotations/fastcgi/main_test.go
Normal file
263
internal/ingress/annotations/fastcgi/main_test.go
Normal file
|
|
@ -0,0 +1,263 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed 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 fastcgi
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
api "k8s.io/api/core/v1"
|
||||
networking "k8s.io/api/networking/v1beta1"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
|
||||
"k8s.io/ingress-nginx/internal/ingress/errors"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
)
|
||||
|
||||
func buildIngress() *networking.Ingress {
|
||||
return &networking.Ingress{
|
||||
ObjectMeta: meta_v1.ObjectMeta{
|
||||
Name: "foo",
|
||||
Namespace: api.NamespaceDefault,
|
||||
},
|
||||
Spec: networking.IngressSpec{
|
||||
Backend: &networking.IngressBackend{
|
||||
ServiceName: "fastcgi",
|
||||
ServicePort: intstr.FromInt(80),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type mockConfigMap struct {
|
||||
resolver.Mock
|
||||
}
|
||||
|
||||
func (m mockConfigMap) GetConfigMap(name string) (*api.ConfigMap, error) {
|
||||
if name != "default/demo-configmap" {
|
||||
return nil, errors.Errorf("there is no configmap with name %v", name)
|
||||
}
|
||||
|
||||
return &api.ConfigMap{
|
||||
ObjectMeta: meta_v1.ObjectMeta{
|
||||
Namespace: api.NamespaceDefault,
|
||||
Name: "demo-secret",
|
||||
},
|
||||
Data: map[string]string{"REDIRECT_STATUS": "200", "SERVER_NAME": "$server_name"},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func TestParseEmptyFastCGIAnnotations(t *testing.T) {
|
||||
ing := buildIngress()
|
||||
|
||||
i, err := NewParser(&mockConfigMap{}).Parse(ing)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error parsing ingress without fastcgi")
|
||||
}
|
||||
|
||||
config, ok := i.(Config)
|
||||
if !ok {
|
||||
t.Errorf("Parse do not return a Config object")
|
||||
}
|
||||
|
||||
if config.Index != "" {
|
||||
t.Errorf("Index should be an empty string")
|
||||
}
|
||||
|
||||
if 0 != len(config.Params) {
|
||||
t.Errorf("Params should be an empty slice")
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseFastCGIIndexAnnotation(t *testing.T) {
|
||||
ing := buildIngress()
|
||||
|
||||
const expectedAnnotation = "index.php"
|
||||
|
||||
data := map[string]string{}
|
||||
data[parser.GetAnnotationWithPrefix("fastcgi-index")] = expectedAnnotation
|
||||
ing.SetAnnotations(data)
|
||||
|
||||
i, err := NewParser(&mockConfigMap{}).Parse(ing)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error parsing ingress without fastcgi")
|
||||
}
|
||||
|
||||
config, ok := i.(Config)
|
||||
if !ok {
|
||||
t.Errorf("Parse do not return a Config object")
|
||||
}
|
||||
|
||||
if config.Index != "index.php" {
|
||||
t.Errorf("expected %s but %v returned", expectedAnnotation, config.Index)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseEmptyFastCGIParamsConfigMapAnnotation(t *testing.T) {
|
||||
ing := buildIngress()
|
||||
|
||||
data := map[string]string{}
|
||||
data[parser.GetAnnotationWithPrefix("fastcgi-params-configmap")] = ""
|
||||
ing.SetAnnotations(data)
|
||||
|
||||
i, err := NewParser(&mockConfigMap{}).Parse(ing)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error parsing ingress without fastcgi")
|
||||
}
|
||||
|
||||
config, ok := i.(Config)
|
||||
if !ok {
|
||||
t.Errorf("Parse do not return a Config object")
|
||||
}
|
||||
|
||||
if 0 != len(config.Params) {
|
||||
t.Errorf("Params should be an empty slice")
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseFastCGIInvalidParamsConfigMapAnnotation(t *testing.T) {
|
||||
ing := buildIngress()
|
||||
|
||||
invalidConfigMapList := []string{"unknown/configMap", "unknown/config/map"}
|
||||
for _, configmap := range invalidConfigMapList {
|
||||
|
||||
data := map[string]string{}
|
||||
data[parser.GetAnnotationWithPrefix("fastcgi-params-configmap")] = configmap
|
||||
ing.SetAnnotations(data)
|
||||
|
||||
i, err := NewParser(&mockConfigMap{}).Parse(ing)
|
||||
if err == nil {
|
||||
t.Errorf("Reading an unexisting configmap should return an error")
|
||||
}
|
||||
|
||||
config, ok := i.(Config)
|
||||
if !ok {
|
||||
t.Errorf("Parse do not return a Config object")
|
||||
}
|
||||
|
||||
if 0 != len(config.Params) {
|
||||
t.Errorf("Params should be an empty slice")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseFastCGIParamsConfigMapAnnotationWithoutNS(t *testing.T) {
|
||||
ing := buildIngress()
|
||||
|
||||
data := map[string]string{}
|
||||
data[parser.GetAnnotationWithPrefix("fastcgi-params-configmap")] = "demo-configmap"
|
||||
ing.SetAnnotations(data)
|
||||
|
||||
i, err := NewParser(&mockConfigMap{}).Parse(ing)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error parsing ingress without fastcgi")
|
||||
}
|
||||
|
||||
config, ok := i.(Config)
|
||||
if !ok {
|
||||
t.Errorf("Parse do not return a Config object")
|
||||
}
|
||||
|
||||
if 2 != len(config.Params) {
|
||||
t.Errorf("Params should have a length of 2")
|
||||
}
|
||||
|
||||
if "200" != config.Params["REDIRECT_STATUS"] || "$server_name" != config.Params["SERVER_NAME"] {
|
||||
t.Errorf("Params value is not the one expected")
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseFastCGIParamsConfigMapAnnotationWithNS(t *testing.T) {
|
||||
ing := buildIngress()
|
||||
|
||||
data := map[string]string{}
|
||||
data[parser.GetAnnotationWithPrefix("fastcgi-params-configmap")] = "default/demo-configmap"
|
||||
ing.SetAnnotations(data)
|
||||
|
||||
i, err := NewParser(&mockConfigMap{}).Parse(ing)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error parsing ingress without fastcgi")
|
||||
}
|
||||
|
||||
config, ok := i.(Config)
|
||||
if !ok {
|
||||
t.Errorf("Parse do not return a Config object")
|
||||
}
|
||||
|
||||
if 2 != len(config.Params) {
|
||||
t.Errorf("Params should have a length of 2")
|
||||
}
|
||||
|
||||
if "200" != config.Params["REDIRECT_STATUS"] || "$server_name" != config.Params["SERVER_NAME"] {
|
||||
t.Errorf("Params value is not the one expected")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigEquality(t *testing.T) {
|
||||
|
||||
var nilConfig *Config
|
||||
|
||||
config := Config{
|
||||
Index: "index.php",
|
||||
Params: map[string]string{"REDIRECT_STATUS": "200", "SERVER_NAME": "$server_name"},
|
||||
}
|
||||
|
||||
configCopy := Config{
|
||||
Index: "index.php",
|
||||
Params: map[string]string{"REDIRECT_STATUS": "200", "SERVER_NAME": "$server_name"},
|
||||
}
|
||||
|
||||
config2 := Config{
|
||||
Index: "index.php",
|
||||
Params: map[string]string{"REDIRECT_STATUS": "200"},
|
||||
}
|
||||
|
||||
config3 := Config{
|
||||
Index: "index.py",
|
||||
Params: map[string]string{"SERVER_NAME": "$server_name", "REDIRECT_STATUS": "200"},
|
||||
}
|
||||
|
||||
config4 := Config{
|
||||
Index: "index.php",
|
||||
Params: map[string]string{"SERVER_NAME": "$server_name", "REDIRECT_STATUS": "200"},
|
||||
}
|
||||
|
||||
if !config.Equal(&config) {
|
||||
t.Errorf("config should be equal to itself")
|
||||
}
|
||||
|
||||
if nilConfig.Equal(&config) {
|
||||
t.Errorf("Foo")
|
||||
}
|
||||
|
||||
if !config.Equal(&configCopy) {
|
||||
t.Errorf("config should be equal to configCopy")
|
||||
}
|
||||
|
||||
if config.Equal(&config2) {
|
||||
t.Errorf("config2 should not be equal to config")
|
||||
}
|
||||
|
||||
if config.Equal(&config3) {
|
||||
t.Errorf("config3 should not be equal to config")
|
||||
}
|
||||
|
||||
if !config.Equal(&config4) {
|
||||
t.Errorf("config4 should be equal to config")
|
||||
}
|
||||
}
|
||||
58
internal/ingress/annotations/mirror/main.go
Normal file
58
internal/ingress/annotations/mirror/main.go
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed 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 mirror
|
||||
|
||||
import (
|
||||
networking "k8s.io/api/networking/v1beta1"
|
||||
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
// Config returns the mirror to use in a given location
|
||||
type Config struct {
|
||||
URI string `json:"uri"`
|
||||
RequestBody string `json:"requestBody"`
|
||||
}
|
||||
|
||||
type mirror struct {
|
||||
r resolver.Resolver
|
||||
}
|
||||
|
||||
// NewParser creates a new mirror configuration annotation parser
|
||||
func NewParser(r resolver.Resolver) parser.IngressAnnotation {
|
||||
return mirror{r}
|
||||
}
|
||||
|
||||
// ParseAnnotations parses the annotations contained in the ingress
|
||||
// rule used to configure mirror
|
||||
func (a mirror) Parse(ing *networking.Ingress) (interface{}, error) {
|
||||
config := &Config{}
|
||||
var err error
|
||||
|
||||
config.URI, err = parser.GetStringAnnotation("mirror-uri", ing)
|
||||
if err != nil {
|
||||
config.URI = ""
|
||||
}
|
||||
|
||||
config.RequestBody, err = parser.GetStringAnnotation("mirror-request-body", ing)
|
||||
if err != nil || config.RequestBody != "off" {
|
||||
config.RequestBody = "on"
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
86
internal/ingress/annotations/mirror/main_test.go
Normal file
86
internal/ingress/annotations/mirror/main_test.go
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed 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 mirror
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
api "k8s.io/api/core/v1"
|
||||
networking "k8s.io/api/networking/v1beta1"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
uri := parser.GetAnnotationWithPrefix("mirror-uri")
|
||||
requestBody := parser.GetAnnotationWithPrefix("mirror-request-body")
|
||||
|
||||
ap := NewParser(&resolver.Mock{})
|
||||
if ap == nil {
|
||||
t.Fatalf("expected a parser.IngressAnnotation but returned nil")
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
annotations map[string]string
|
||||
expected *Config
|
||||
}{
|
||||
{map[string]string{uri: "/mirror", requestBody: ""}, &Config{
|
||||
URI: "/mirror",
|
||||
RequestBody: "on",
|
||||
}},
|
||||
{map[string]string{uri: "/mirror", requestBody: "off"}, &Config{
|
||||
URI: "/mirror",
|
||||
RequestBody: "off",
|
||||
}},
|
||||
{map[string]string{uri: "", requestBody: "ahh"}, &Config{
|
||||
URI: "",
|
||||
RequestBody: "on",
|
||||
}},
|
||||
{map[string]string{uri: "", requestBody: ""}, &Config{
|
||||
URI: "",
|
||||
RequestBody: "on",
|
||||
}},
|
||||
{map[string]string{}, &Config{
|
||||
URI: "",
|
||||
RequestBody: "on",
|
||||
}},
|
||||
{nil, &Config{
|
||||
URI: "",
|
||||
RequestBody: "on",
|
||||
}},
|
||||
}
|
||||
|
||||
ing := &networking.Ingress{
|
||||
ObjectMeta: meta_v1.ObjectMeta{
|
||||
Name: "foo",
|
||||
Namespace: api.NamespaceDefault,
|
||||
},
|
||||
Spec: networking.IngressSpec{},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
ing.SetAnnotations(testCase.annotations)
|
||||
result, _ := ap.Parse(ing)
|
||||
fmt.Printf("%t", result)
|
||||
if !reflect.DeepEqual(result, testCase.expected) {
|
||||
t.Errorf("expected %v but returned %v, annotations: %s", testCase.expected, result, testCase.annotations)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -25,22 +25,23 @@ import (
|
|||
|
||||
// Config returns the proxy timeout to use in the upstream server/s
|
||||
type Config struct {
|
||||
BodySize string `json:"bodySize"`
|
||||
ConnectTimeout int `json:"connectTimeout"`
|
||||
SendTimeout int `json:"sendTimeout"`
|
||||
ReadTimeout int `json:"readTimeout"`
|
||||
BuffersNumber int `json:"buffersNumber"`
|
||||
BufferSize string `json:"bufferSize"`
|
||||
CookieDomain string `json:"cookieDomain"`
|
||||
CookiePath string `json:"cookiePath"`
|
||||
NextUpstream string `json:"nextUpstream"`
|
||||
NextUpstreamTimeout int `json:"nextUpstreamTimeout"`
|
||||
NextUpstreamTries int `json:"nextUpstreamTries"`
|
||||
ProxyRedirectFrom string `json:"proxyRedirectFrom"`
|
||||
ProxyRedirectTo string `json:"proxyRedirectTo"`
|
||||
RequestBuffering string `json:"requestBuffering"`
|
||||
ProxyBuffering string `json:"proxyBuffering"`
|
||||
ProxyHTTPVersion string `json:"proxyHTTPVersion"`
|
||||
BodySize string `json:"bodySize"`
|
||||
ConnectTimeout int `json:"connectTimeout"`
|
||||
SendTimeout int `json:"sendTimeout"`
|
||||
ReadTimeout int `json:"readTimeout"`
|
||||
BuffersNumber int `json:"buffersNumber"`
|
||||
BufferSize string `json:"bufferSize"`
|
||||
CookieDomain string `json:"cookieDomain"`
|
||||
CookiePath string `json:"cookiePath"`
|
||||
NextUpstream string `json:"nextUpstream"`
|
||||
NextUpstreamTimeout int `json:"nextUpstreamTimeout"`
|
||||
NextUpstreamTries int `json:"nextUpstreamTries"`
|
||||
ProxyRedirectFrom string `json:"proxyRedirectFrom"`
|
||||
ProxyRedirectTo string `json:"proxyRedirectTo"`
|
||||
RequestBuffering string `json:"requestBuffering"`
|
||||
ProxyBuffering string `json:"proxyBuffering"`
|
||||
ProxyHTTPVersion string `json:"proxyHTTPVersion"`
|
||||
ProxyMaxTempFileSize string `json:"proxyMaxTempFileSize"`
|
||||
}
|
||||
|
||||
// Equal tests for equality between two Configuration types
|
||||
|
|
@ -100,6 +101,10 @@ func (l1 *Config) Equal(l2 *Config) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
if l1.ProxyMaxTempFileSize != l2.ProxyMaxTempFileSize {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
@ -200,5 +205,10 @@ func (a proxy) Parse(ing *networking.Ingress) (interface{}, error) {
|
|||
config.ProxyHTTPVersion = defBackend.ProxyHTTPVersion
|
||||
}
|
||||
|
||||
config.ProxyMaxTempFileSize, err = parser.GetStringAnnotation("proxy-max-temp-file-size", ing)
|
||||
if err != nil {
|
||||
config.ProxyMaxTempFileSize = defBackend.ProxyMaxTempFileSize
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ func (m mockBackend) GetDefaultBackend() defaults.Backend {
|
|||
ProxyRequestBuffering: "on",
|
||||
ProxyBuffering: "off",
|
||||
ProxyHTTPVersion: "1.1",
|
||||
ProxyMaxTempFileSize: "1024m",
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -101,6 +102,7 @@ func TestProxy(t *testing.T) {
|
|||
data[parser.GetAnnotationWithPrefix("proxy-request-buffering")] = "off"
|
||||
data[parser.GetAnnotationWithPrefix("proxy-buffering")] = "on"
|
||||
data[parser.GetAnnotationWithPrefix("proxy-http-version")] = "1.0"
|
||||
data[parser.GetAnnotationWithPrefix("proxy-max-temp-file-size")] = "128k"
|
||||
ing.SetAnnotations(data)
|
||||
|
||||
i, err := NewParser(mockBackend{}).Parse(ing)
|
||||
|
|
@ -147,6 +149,9 @@ func TestProxy(t *testing.T) {
|
|||
if p.ProxyHTTPVersion != "1.0" {
|
||||
t.Errorf("expected 1.0 as proxy-http-version but returned %v", p.ProxyHTTPVersion)
|
||||
}
|
||||
if p.ProxyMaxTempFileSize != "128k" {
|
||||
t.Errorf("expected 128k as proxy-max-temp-file-size but returned %v", p.ProxyMaxTempFileSize)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProxyWithNoAnnotation(t *testing.T) {
|
||||
|
|
@ -196,4 +201,7 @@ func TestProxyWithNoAnnotation(t *testing.T) {
|
|||
if p.ProxyHTTPVersion != "1.1" {
|
||||
t.Errorf("expected 1.1 as proxy-http-version but returned %v", p.ProxyHTTPVersion)
|
||||
}
|
||||
if p.ProxyMaxTempFileSize != "1024m" {
|
||||
t.Errorf("expected 1024m as proxy-max-temp-file-size but returned %v", p.ProxyMaxTempFileSize)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ func TestIngressAffinityCookieConfig(t *testing.T) {
|
|||
}
|
||||
|
||||
if nginxAffinity.Cookie.Name != "INGRESSCOOKIE" {
|
||||
t.Errorf("expected route as session-cookie-name but returned %v", nginxAffinity.Cookie.Name)
|
||||
t.Errorf("expected INGRESSCOOKIE as session-cookie-name but returned %v", nginxAffinity.Cookie.Name)
|
||||
}
|
||||
|
||||
if nginxAffinity.Cookie.Expires != "4500" {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue