merge from master

This commit is contained in:
liuwei 2018-11-02 13:13:24 +08:00
commit ce6e564f82
86 changed files with 1448 additions and 3530 deletions

View file

@ -52,7 +52,7 @@ GOBUILD_FLAGS :=
ALL_ARCH = amd64 arm arm64 ppc64le
QEMUVERSION = v2.12.0-1
QEMUVERSION = v3.0.0
BUSTED_ARGS =-v --pattern=_test
@ -61,7 +61,7 @@ IMAGE = $(REGISTRY)/$(IMGNAME)
MULTI_ARCH_IMG = $(IMAGE)-$(ARCH)
# Set default base image dynamically for each arch
BASEIMAGE?=quay.io/kubernetes-ingress-controller/nginx-$(ARCH):0.65
BASEIMAGE?=quay.io/kubernetes-ingress-controller/nginx-$(ARCH):0.66
ifeq ($(ARCH),arm)
QEMUARCH=arm

View file

@ -41,19 +41,6 @@ fi
SCRIPT_ROOT=$(dirname ${BASH_SOURCE})/..
mkdir -p ${SCRIPT_ROOT}/test/binaries
TEST_BINARIES=$( cd "${SCRIPT_ROOT}/test/binaries" ; pwd -P )
export PATH=${TEST_BINARIES}:$PATH
if ! [ -x "$(command -v kubectl)" ]; then
echo "downloading kubectl..."
curl -sSLo ${TEST_BINARIES}/kubectl \
https://storage.googleapis.com/kubernetes-release/release/v1.11.0/bin/linux/amd64/kubectl
chmod +x ${TEST_BINARIES}/kubectl
fi
ginkgo build ./test/e2e
exec -- \

View file

@ -40,7 +40,7 @@ if [ "$missing" = true ];then
exit 1
fi
E2E_IMAGE=quay.io/kubernetes-ingress-controller/e2e:v10102018-dcc6495
E2E_IMAGE=quay.io/kubernetes-ingress-controller/e2e:v10292018-240c7274b
DOCKER_OPTS=${DOCKER_OPTS:-""}

View file

@ -84,6 +84,8 @@ Takes the form "namespace/name".`)
Configured inside the NGINX status server. All requests received on the port
defined by the healthz-port parameter are forwarded internally to this path.`)
healthCheckTimeout = flags.Duration("health-check-timeout", 10, `Time limit, in seconds, for a probe to health-check-path to succeed.`)
updateStatus = flags.Bool("update-status", true,
`Update the load-balancer status of Ingress objects this controller satisfies.
Requires setting the publish-service parameter to a valid Service reference.`)
@ -217,6 +219,7 @@ Feature backed by OpenResty Lua libraries. Requires that OCSP stapling is not en
ConfigMapName: *configMap,
DefaultSSLCertificate: *defSSLCertificate,
DefaultHealthzURL: *defHealthzURL,
HealthCheckTimeout: *healthCheckTimeout,
PublishService: *publishSvc,
PublishStatusAddress: *publishStatusAddress,
ForceNamespaceIsolation: *forceIsolation,

View file

@ -94,7 +94,7 @@ func main() {
if err != nil {
// TODO (antoineco): compare with error types from k8s.io/apimachinery/pkg/api/errors
if strings.Contains(err.Error(), "cannot get services in the namespace") {
glog.Fatalf("✖ The cluster seems to be running with a restrictive Authorization mode and the Ingress controller does not have the required permissions to operate normally.")
glog.Fatal("✖ The cluster seems to be running with a restrictive Authorization mode and the Ingress controller does not have the required permissions to operate normally.")
}
glog.Fatalf("No service with name %v found: %v", conf.DefaultService, err)
}
@ -160,7 +160,7 @@ func handleSigterm(ngx *controller.NGINXController, exit exiter) {
signalChan := make(chan os.Signal, 1)
signal.Notify(signalChan, syscall.SIGTERM)
<-signalChan
glog.Infof("Received SIGTERM, shutting down")
glog.Info("Received SIGTERM, shutting down")
exitCode := 0
if err := ngx.Stop(); err != nil {
@ -168,7 +168,7 @@ func handleSigterm(ngx *controller.NGINXController, exit exiter) {
exitCode = 1
}
glog.Infof("Handled quit, awaiting Pod deletion")
glog.Info("Handled quit, awaiting Pod deletion")
time.Sleep(10 * time.Second)
glog.Infof("Exiting with %v", exitCode)

View file

@ -2,8 +2,7 @@
## Contents
- [Generic Deployment](#generic-deployment)
- [Mandatory command](#mandatory-command)
- [Prerequisite Generic Deployment Command](#prerequisite-generic-deployment-command)
- [Provider Specific Steps](#provider-specific-steps)
- [Docker for Mac](#docker-for-mac)
- [minikube](#minikube)
@ -159,7 +158,7 @@ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/mast
```
!!! tip
For extended notes regarding deployments on bare-metal, see [Bare-metal considerations](./baremetal/).
For extended notes regarding deployments on bare-metal, see [Bare-metal considerations](./baremetal.md/).
### Verify installation

View file

@ -4,7 +4,7 @@ It is possible to enable Client-Certificate Authentication by adding additional
Before getting started you must have the following Certificates Setup:
1. CA certificate and Key(Intermediate Certs need to be in CA)
2. Server Certificate(Signed by CA) and Key (CN should be equal the the hostname you will use)
2. Server Certificate(Signed by CA) and Key (CN should be equal the hostname you will use)
3. Client Certificate(Signed by CA) and Key
## Creating Certificate Secrets

View file

@ -10,7 +10,7 @@ They are set in the container spec of the `nginx-ingress-controller` Deployment
| `--annotations-prefix string` | Prefix of the Ingress annotations specific to the NGINX controller. (default "nginx.ingress.kubernetes.io") |
| `--apiserver-host string` | Address of the Kubernetes API server. Takes the form "protocol://address:port". If not specified, it is assumed the program runs inside a Kubernetes cluster and local discovery is attempted. |
| `--configmap string` | Name of the ConfigMap containing custom global configurations for the controller. |
| `--default-backend-service string` | Service used to serve HTTP requests not matching any known server name (catch-all). Takes the form "namespace/name". The controller configures NGINX to forward requests to the first port of this Service. If not specified, 404 page will be returned diretly from Nginx.|
| `--default-backend-service string` | Service used to serve HTTP requests not matching any known server name (catch-all). Takes the form "namespace/name". The controller configures NGINX to forward requests to the first port of this Service. If not specified, a 404 page will be returned directly from NGINX.|
| `--default-server-port int` | When `default-backend-service` is not specified or specified service does not have any endpoint, a local endpoint with this port will be used to serve 404 page from inside Nginx. |
| `--default-ssl-certificate string` | Secret containing a SSL certificate to be used by the default HTTPS server (catch-all). Takes the form "namespace/name". |
| `--election-id string` | Election id to use for Ingress status updates. (default "ingress-controller-leader") |

View file

@ -80,6 +80,9 @@ You can add these Kubernetes annotations to specific Ingress objects to customiz
|[nginx.ingress.kubernetes.io/lua-resty-waf-debug](#lua-resty-waf)|"true" or "false"|
|[nginx.ingress.kubernetes.io/lua-resty-waf-ignore-rulesets](#lua-resty-waf)|string|
|[nginx.ingress.kubernetes.io/lua-resty-waf-extra-rules](#lua-resty-waf)|string|
|[nginx.ingress.kubernetes.io/lua-resty-waf-allow-unknown-content-types](#lua-resty-waf)|"true" or "false"|
|[nginx.ingress.kubernetes.io/lua-resty-waf-score-threshold](#lua-resty-waf)|number|
|[nginx.ingress.kubernetes.io/lua-resty-waf-process-multipart-body](#lua-resty-waf)|"true" or "false"|
|[nginx.ingress.kubernetes.io/enable-influxdb](#influxdb)|"true" or "false"|
|[nginx.ingress.kubernetes.io/influxdb-measurement](#influxdb)|string|
|[nginx.ingress.kubernetes.io/influxdb-port](#influxdb)|string|
@ -558,6 +561,32 @@ It is also possible to configure custom WAF rules per ingress using the `nginx.i
nginx.ingress.kubernetes.io/lua-resty-waf-extra-rules: '[=[ { "access": [ { "actions": { "disrupt" : "DENY" }, "id": 10001, "msg": "my custom rule", "operator": "STR_CONTAINS", "pattern": "foo", "vars": [ { "parse": [ "values", 1 ], "type": "REQUEST_ARGS" } ] } ], "body_filter": [], "header_filter":[] } ]=]'
```
Since the default allowed contents were `"text/html", "text/json", "application/json"`
We can enable the following annotation for allow all contents type:
```yaml
nginx.ingress.kubernetes.io/lua-resty-waf-allow-unknown-content-types: "true"
```
The default score of lua-resty-waf is 5, which usually triggered if hitting 2 default rules, you can modify the score threshold with following annotation:
```yaml
nginx.ingress.kubernetes.io/lua-resty-waf-score-threshold: "10"
```
When you enabled HTTPS in the endpoint and since resty-lua will return 500 error when processing "multipart" contents
Reference for this [issue](https://github.com/p0pr0ck5/lua-resty-waf/issues/166)
By default, it will be "true"
You may enable the following annotation for work around:
```yaml
nginx.ingress.kubernetes.io/lua-resty-waf-process-multipart-body: "false"
```
For details on how to write WAF rules, please refer to [https://github.com/p0pr0ck5/lua-resty-waf](https://github.com/p0pr0ck5/lua-resty-waf).
[configmap]: ./configmap.md

View file

@ -86,6 +86,7 @@ The following table shows a configuration option's name, type, and the default v
|[proxy-protocol-header-timeout](#proxy-protocol-header-timeout)|string|"5s"|
|[use-gzip](#use-gzip)|bool|"true"|
|[use-geoip](#use-geoip)|bool|"true"|
|[use-geoip2](#use-geoip2)|bool|"false"|
|[enable-brotli](#enable-brotli)|bool|"false"|
|[brotli-level](#brotli-level)|int|4|
|[brotli-types](#brotli-types)|string|"application/xml+rss application/atom+xml application/javascript application/x-javascript application/json application/rss+xml application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/svg+xml image/x-icon text/css text/plain text/x-component"|
@ -498,6 +499,13 @@ The default mime type list to compress is: `application/atom+xml application/jav
Enables or disables ["geoip" module](http://nginx.org/en/docs/http/ngx_http_geoip_module.html) that creates variables with values depending on the client IP address, using the precompiled MaxMind databases.
_**default:**_ true
> __Note:__ MaxMind legacy databases are discontinued and will not receive updates after 2019-01-02, cf. [discontinuation notice](https://support.maxmind.com/geolite-legacy-discontinuation-notice/). Consider [use-geoip2](#use-geoip2) below.
## use-geoip2
Enables the [geoip2 module](https://github.com/leev/ngx_http_geoip2_module) for NGINX.
_**default:**_ false
## enable-brotli
Enables or disables compression of HTTP responses using the ["brotli" module](https://github.com/google/ngx_brotli).

View file

@ -4,7 +4,7 @@
Anytime we reference a TLS secret, we mean a PEM-encoded X.509, RSA (2048) secret.
You can generate a self-signed certificate and private key with with:
You can generate a self-signed certificate and private key with:
```bash
$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ${KEY_FILE} -out ${CERT_FILE} -subj "/CN=${HOST}/O=${HOST}"`

View file

@ -20,7 +20,7 @@ set -o pipefail
SCRIPT_ROOT=$(dirname ${BASH_SOURCE})/..
INPUT="namespace.yaml configmap.yaml tcp-services-configmap.yaml udp-services-configmap.yaml rbac.yaml with-rbac.yaml"
INPUT="namespace.yaml configmap.yaml rbac.yaml with-rbac.yaml"
MANIFEST=$(cd ${SCRIPT_ROOT}/deploy; cat ${INPUT})
echo "${MANIFEST}" > ${SCRIPT_ROOT}/deploy/mandatory.yaml

View file

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
FROM quay.io/kubernetes-ingress-controller/nginx-amd64:0.63
FROM quay.io/kubernetes-ingress-controller/nginx-amd64:0.66
RUN clean-install \
g++ \
@ -61,3 +61,7 @@ RUN luarocks install luacheck \
RUN go get github.com/onsi/ginkgo/ginkgo \
&& go get golang.org/x/lint/golint
RUN curl -Lo /usr/local/bin/kubectl https://storage.googleapis.com/kubernetes-release/release/v1.12.0/bin/linux/amd64/kubectl \
&& chmod +x /usr/local/bin/kubectl

View file

@ -13,7 +13,7 @@
# limitations under the License.
# 0.0.0 shouldn't clobber any released builds
TAG ?= 0.65
TAG ?= 0.66
REGISTRY ?= quay.io/kubernetes-ingress-controller
ARCH ?= $(shell go env GOARCH)
DOCKER ?= docker
@ -26,7 +26,7 @@ ifeq ($(GOHOSTOS),darwin)
SED_I=sed -i ''
endif
QEMUVERSION=v2.12.0-1
QEMUVERSION=v3.0.0
IMGNAME = nginx
IMAGE = $(REGISTRY)/$(IMGNAME)

View file

@ -14,6 +14,7 @@ This custom nginx image contains:
- [zipkin-cpp-opentracing](https://github.com/rnburn/zipkin-cpp-opentracing)
- [ModSecurity-nginx](https://github.com/SpiderLabs/ModSecurity-nginx) (only supported in x86_64)
- [brotli](https://github.com/google/brotli)
- [geoip2](https://github.com/leev/ngx_http_geoip2_module)
**How to use this image:**
This image provides a default configuration file with no backend servers.

View file

@ -29,13 +29,13 @@ export NGINX_OPENTRACING_VERSION=0.6.0
export OPENTRACING_CPP_VERSION=1.5.0
export ZIPKIN_CPP_VERSION=0.5.2
export JAEGER_VERSION=ba0fa3fa6dbb01995d996f988a897e272100bf95
export MODSECURITY_VERSION=37b76e88df4bce8a9846345c27271d7e6ce1acfb
export MODSECURITY_VERSION=56cfa4e4805bb6134b97143052a9b48919cc294f
export LUA_NGX_VERSION=e94f2e5d64daa45ff396e262d8dab8e56f5f10e0
export LUA_UPSTREAM_VERSION=0.07
export NGINX_INFLUXDB_VERSION=f20cfb2458c338f162132f5a21eb021e2cbe6383
export GEOIP2_VERSION=3.0
export NGINX_INFLUXDB_VERSION=0e2cb6cbf850a29c81e44be9e33d9a15d45c50e8
export GEOIP2_VERSION=3.2
export NGINX_AJP_VERSION=bf6cd93f2098b59260de8d494f0f4b1f11a84627
export LUAJIT_VERSION=8e35a1932250b0313c06393061f332c760efdf40
export LUAJIT_VERSION=c58fe79b870f1934479bf14fe8035fc3d9fdfde2
export BUILD_PATH=/tmp/build
@ -53,10 +53,6 @@ get_src()
rm -rf "$f"
}
if [[ ${ARCH} == "ppc64le" ]]; then
clean-install software-properties-common
fi
apt-get update && apt-get dist-upgrade -y
# install required packages to build
@ -94,8 +90,15 @@ clean-install \
dumb-init \
gdb \
valgrind \
bc \
|| exit 1
if [[ ${ARCH} == "ppc64le" ]]; then
wget http://ftp.us.debian.org/debian/pool/main/a/apt/libapt-pkg5.0_1.7.0_ppc64el.deb
dpkg -i libapt-pkg5.0_1.7.0_ppc64el.deb
clean-install python3-apt python3-software-properties software-properties-common
fi
if [[ ${ARCH} == "x86_64" ]]; then
ln -s /usr/lib/x86_64-linux-gnu/liblua5.1.so /usr/lib/liblua.so
ln -s /usr/lib/x86_64-linux-gnu /usr/lib/lua-platform-path
@ -125,12 +128,23 @@ function geoip_get {
wget -O $GEOIP_FOLDER/$1 $2 || { echo "Could not download $1, exiting." ; exit 1; }
gunzip $GEOIP_FOLDER/$1
}
function geoip2_get {
wget -O $GEOIP_FOLDER/$1.tar.gz $2 || { echo "Could not download $1, exiting." ; exit 1; }
mkdir $GEOIP_FOLDER/$1 && tar xf $GEOIP_FOLDER/$1.tar.gz -C $GEOIP_FOLDER/$1 --strip-components 1 && mv $GEOIP_FOLDER/$1/$1.mmdb $GEOIP_FOLDER/$1.mmdb && rm -rf $GEOIP_FOLDER/$1
}
geoip_get "GeoIPASNum.dat.gz" "http://download.maxmind.com/download/geoip/database/asnum/GeoIPASNum.dat.gz"
geoip_get "GeoIP.dat.gz" "https://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz"
geoip_get "GeoLite2-City.mmdb.gz" "http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz"
geoip_get "GeoLite2-ASN.mmdb.gz" "http://geolite.maxmind.com/download/geoip/database/GeoLite2-ASN.tar.gz"
geoip_get "GeoLiteCity.dat.gz" "https://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz"
geoip2_get "GeoLite2-City" "http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz"
geoip2_get "GeoLite2-ASN" "http://geolite.maxmind.com/download/geoip/database/GeoLite2-ASN.tar.gz"
if [[ (${ARCH} == "ppc64le") ]]; then
echo "deb http://deb.debian.org/debian experimental main" >> /etc/apt/sources.list
apt-get update
apt-get -t experimental install -y luajit
fi
mkdir --verbose -p "$BUILD_PATH"
cd "$BUILD_PATH"
@ -163,7 +177,7 @@ get_src 4455ca507936bc4b658ded10a90d8ebbbd61c58f06207be565a4ffdc885687b5 \
get_src 30affaf0f3a84193f7127cc0135da91773ce45d902414082273dae78914f73df \
"https://github.com/rnburn/zipkin-cpp-opentracing/archive/v$ZIPKIN_CPP_VERSION.tar.gz"
get_src fe7d3188e097d68f1942d46c4adba262d9ddcf433409ebc15bb5355bfb001a4a \
get_src a75e3c0249c8ce4313d21b43d3cf3dcd89518dd6582ef7c6697cb7fe6ef5a84e \
"https://github.com/SpiderLabs/ModSecurity-nginx/archive/$MODSECURITY_VERSION.tar.gz"
get_src b68286966f292fb552511b71bd8bc11af8f12c8aa760372d1437ac8760cb2f25 \
@ -202,13 +216,13 @@ get_src a77bf0d7cf6a9ba017d0dc973b1a58f13e48242dd3849c5e99c07d250667c44c \
get_src d81b33129c6fb5203b571fa4d8394823bf473d8872c0357a1d0f14420b1483bd \
"https://github.com/cloudflare/lua-resty-cookie/archive/v0.1.0.tar.gz"
get_src 5a4485be0031d285f2bdf59afb1f7b8f3cef4c476595ed66f1258206e1b5c3ac \
get_src 21dab7625a028d4560d0215c4bc3b82f6153344f933abb99dc9fd5f0d19519ab \
"https://github.com/openresty/luajit2/archive/$LUAJIT_VERSION.tar.gz"
get_src 1897d7677d99c1cedeb95b2eb00652a4a7e8e604304c3053a93bd3ba7dd82884 \
get_src c673fcee37c1c4794f921b6710b09e8a0e1e58117aa788f798507d033f737192 \
"https://github.com/influxdata/nginx-influxdb-module/archive/$NGINX_INFLUXDB_VERSION.tar.gz"
get_src 65a191688348a05d8d92b2e7ce9c6eb8cb8322205c34637da582a1205864133d \
get_src 15bd1005228cf2c869a6f09e8c41a6aaa6846e4936c473106786ae8ac860fab7 \
"https://github.com/leev/ngx_http_geoip2_module/archive/$GEOIP2_VERSION.tar.gz"
get_src 5f629a50ba22347c441421091da70fdc2ac14586619934534e5a0f8a1390a950 \
@ -221,21 +235,44 @@ export MAKEFLAGS=-j${CORES}
export CTEST_BUILD_FLAGS=${MAKEFLAGS}
export HUNTER_JOBS_NUMBER=${CORES}
OPENSSL_DIR="$BUILD_PATH/openssl"
mkdir -p $OPENSSL_DIR
cd $OPENSSL_DIR
# Install Openssl 1.1.1 from source
wget http://http.debian.net/debian/pool/main/o/openssl/openssl_1.1.1-1.dsc
wget http://http.debian.net/debian/pool/main/o/openssl/openssl_1.1.1.orig.tar.gz
wget http://http.debian.net/debian/pool/main/o/openssl/openssl_1.1.1.orig.tar.gz.asc
wget http://http.debian.net/debian/pool/main/o/openssl/openssl_1.1.1-1.debian.tar.xz
tar zxpvf openssl_1.1.1.orig.tar.gz
cd openssl-1.1.1/
tar xpvf ../openssl_1.1.1-1.debian.tar.xz
dpkg-buildpackage -rfakeroot
cd ..
dpkg -i openssl_1.1.1-1_*.deb libssl1.1_1.1.1-1_*.deb libssl-dev_1.1.1-1_*.deb
# Install luajit from openresty fork
export LUAJIT_LIB=/usr/local/lib
export LUA_LIB_DIR="$LUAJIT_LIB/lua"
# luajit is available only as deb package on ppc64le
if [[ (${ARCH} == "ppc64le") ]]; then
clean-install luajit
else
if [[ (${ARCH} != "ppc64le") ]]; then
cd "$BUILD_PATH/luajit2-$LUAJIT_VERSION"
make CCDEBUG=-g
make install
export LUAJIT_INC=/usr/local/include/luajit-2.1
export LUA_LIB_DIR="$LUAJIT_LIB/lua"
fi
# Installing luarocks packages
if [[ ${ARCH} == "x86_64" ]]; then
export PCRE_DIR=/usr/lib/x86_64-linux-gnu
fi
if [[ ${ARCH} == "armv7l" ]]; then
export PCRE_DIR=/usr/lib/armhf-linux-gnu
fi
@ -248,7 +285,8 @@ if [[ ${ARCH} == "ppc64le" ]]; then
export PCRE_DIR=/usr/lib/powerpc64le-linux-gnu
fi
luarocks install lrexlib-pcre 2.7.2-1
cd "$BUILD_PATH"
luarocks install lrexlib-pcre 2.7.2-1 PCRE_LIBDIR=${PCRE_DIR}
cd "$BUILD_PATH/lua-resty-core-0.1.15"
make install
@ -375,9 +413,7 @@ git submodule update
cd "$BUILD_PATH"
git clone -b v3/master --single-branch https://github.com/SpiderLabs/ModSecurity
cd ModSecurity/
# TODO: use a tag once 3.0.3 is released
# checkout v3.0.3
# git checkout
git checkout 973c1f1028429452308bcbce7df8a6283dc59ffe
git submodule init
git submodule update
sh build.sh

View file

@ -27,6 +27,9 @@ import (
"k8s.io/ingress-nginx/internal/ingress/resolver"
)
// HTTP protocol
const HTTP = "HTTP"
var (
validProtocols = regexp.MustCompile(`^(HTTP|HTTPS|AJP|GRPC|GRPCS)$`)
)
@ -44,18 +47,18 @@ func NewParser(r resolver.Resolver) parser.IngressAnnotation {
// rule used to indicate the backend protocol.
func (a backendProtocol) Parse(ing *extensions.Ingress) (interface{}, error) {
if ing.GetAnnotations() == nil {
return "HTTP", nil
return HTTP, nil
}
proto, err := parser.GetStringAnnotation("backend-protocol", ing)
if err != nil {
return "HTTP", nil
return HTTP, nil
}
proto = strings.TrimSpace(strings.ToUpper(proto))
if !validProtocols.MatchString(proto) {
glog.Warningf("Protocol %v is not a valid value for the backend-protocol annotation. Using HTTP as protocol", proto)
return "HTTP", nil
return HTTP, nil
}
return proto, nil

View file

@ -35,6 +35,9 @@ type Config struct {
Debug bool `json:"debug"`
IgnoredRuleSets []string `json:"ignored-rulesets"`
ExtraRulesetString string `json:"extra-ruleset-string"`
ScoreThreshold int `json:"score-threshold"`
AllowUnknownContentTypes bool `json:"allow-unknown-content-types"`
ProcessMultipartBody bool `json:"process-multipart-body"`
}
// Equal tests for equality between two Config types
@ -57,6 +60,15 @@ func (e1 *Config) Equal(e2 *Config) bool {
if e1.ExtraRulesetString != e2.ExtraRulesetString {
return false
}
if e1.ScoreThreshold != e2.ScoreThreshold {
return false
}
if e1.AllowUnknownContentTypes != e2.AllowUnknownContentTypes {
return false
}
if e1.ProcessMultipartBody != e2.ProcessMultipartBody {
return false
}
return true
}
@ -95,10 +107,22 @@ func (a luarestywaf) Parse(ing *extensions.Ingress) (interface{}, error) {
// TODO(elvinefendi) maybe validate the ruleset string here
extraRulesetString, _ := parser.GetStringAnnotation("lua-resty-waf-extra-rules", ing)
scoreThreshold, _ := parser.GetIntAnnotation("lua-resty-waf-score-threshold", ing)
allowUnknownContentTypes, _ := parser.GetBoolAnnotation("lua-resty-waf-allow-unknown-content-types", ing)
processMultipartBody, err := parser.GetBoolAnnotation("lua-resty-waf-process-multipart-body", ing)
if err != nil {
processMultipartBody = true
}
return &Config{
Mode: mode,
Debug: debug,
IgnoredRuleSets: ignoredRuleSets,
ExtraRulesetString: extraRulesetString,
ScoreThreshold: scoreThreshold,
AllowUnknownContentTypes: allowUnknownContentTypes,
ProcessMultipartBody: processMultipartBody,
}, nil
}

View file

@ -30,6 +30,9 @@ func TestParse(t *testing.T) {
luaRestyWAFAnnotation := parser.GetAnnotationWithPrefix("lua-resty-waf")
luaRestyWAFDebugAnnotation := parser.GetAnnotationWithPrefix("lua-resty-waf-debug")
luaRestyWAFIgnoredRuleSetsAnnotation := parser.GetAnnotationWithPrefix("lua-resty-waf-ignore-rulesets")
luaRestyWAFScoreThresholdAnnotation := parser.GetAnnotationWithPrefix("lua-resty-waf-score-threshold")
luaRestyWAFAllowUnknownContentTypesAnnotation := parser.GetAnnotationWithPrefix("lua-resty-waf-allow-unknown-content-types")
luaRestyWAFProcessMultipartBody := parser.GetAnnotationWithPrefix("lua-resty-waf-process-multipart-body")
ap := NewParser(&resolver.Mock{})
if ap == nil {
@ -43,21 +46,25 @@ func TestParse(t *testing.T) {
{nil, &Config{}},
{map[string]string{}, &Config{}},
{map[string]string{luaRestyWAFAnnotation: "active"}, &Config{Mode: "ACTIVE", Debug: false, IgnoredRuleSets: []string{}}},
{map[string]string{luaRestyWAFAnnotation: "active"}, &Config{Mode: "ACTIVE", Debug: false, IgnoredRuleSets: []string{}, ProcessMultipartBody: true}},
{map[string]string{luaRestyWAFDebugAnnotation: "true"}, &Config{Debug: false}},
{map[string]string{luaRestyWAFAnnotation: "active", luaRestyWAFDebugAnnotation: "true"}, &Config{Mode: "ACTIVE", Debug: true, IgnoredRuleSets: []string{}}},
{map[string]string{luaRestyWAFAnnotation: "active", luaRestyWAFDebugAnnotation: "false"}, &Config{Mode: "ACTIVE", Debug: false, IgnoredRuleSets: []string{}}},
{map[string]string{luaRestyWAFAnnotation: "inactive", luaRestyWAFDebugAnnotation: "true"}, &Config{Mode: "INACTIVE", Debug: true, IgnoredRuleSets: []string{}}},
{map[string]string{luaRestyWAFAnnotation: "active", luaRestyWAFDebugAnnotation: "true"}, &Config{Mode: "ACTIVE", Debug: true, IgnoredRuleSets: []string{}, ProcessMultipartBody: true}},
{map[string]string{luaRestyWAFAnnotation: "active", luaRestyWAFDebugAnnotation: "false"}, &Config{Mode: "ACTIVE", Debug: false, IgnoredRuleSets: []string{}, ProcessMultipartBody: true}},
{map[string]string{luaRestyWAFAnnotation: "inactive", luaRestyWAFDebugAnnotation: "true"}, &Config{Mode: "INACTIVE", Debug: true, IgnoredRuleSets: []string{}, ProcessMultipartBody: true}},
{map[string]string{
luaRestyWAFAnnotation: "active",
luaRestyWAFDebugAnnotation: "true",
luaRestyWAFIgnoredRuleSetsAnnotation: "ruleset1, ruleset2 ruleset3, another.ruleset"},
&Config{Mode: "ACTIVE", Debug: true, IgnoredRuleSets: []string{"ruleset1", "ruleset2", "ruleset3", "another.ruleset"}}},
luaRestyWAFIgnoredRuleSetsAnnotation: "ruleset1, ruleset2 ruleset3, another.ruleset",
luaRestyWAFScoreThresholdAnnotation: "10",
luaRestyWAFAllowUnknownContentTypesAnnotation: "true"},
&Config{Mode: "ACTIVE", Debug: true, IgnoredRuleSets: []string{"ruleset1", "ruleset2", "ruleset3", "another.ruleset"}, ScoreThreshold: 10, AllowUnknownContentTypes: true, ProcessMultipartBody: true}},
{map[string]string{luaRestyWAFAnnotation: "siMulate", luaRestyWAFDebugAnnotation: "true"}, &Config{Mode: "SIMULATE", Debug: true, IgnoredRuleSets: []string{}}},
{map[string]string{luaRestyWAFAnnotation: "siMulate", luaRestyWAFDebugAnnotation: "true"}, &Config{Mode: "SIMULATE", Debug: true, IgnoredRuleSets: []string{}, ProcessMultipartBody: true}},
{map[string]string{luaRestyWAFAnnotation: "siMulateX", luaRestyWAFDebugAnnotation: "true"}, &Config{Debug: false}},
{map[string]string{luaRestyWAFAnnotation: "active", luaRestyWAFProcessMultipartBody: "false"}, &Config{Mode: "ACTIVE", ProcessMultipartBody: false, IgnoredRuleSets: []string{}}},
}
ing := &extensions.Ingress{

View file

@ -39,7 +39,7 @@ type Config struct {
// AppRoot defines the Application Root that the Controller must redirect if it's in '/' context
AppRoot string `json:"appRoot"`
// UseRegex indicates whether or not the locations use regex paths
UseRegex bool `json:useRegex`
UseRegex bool `json:"useRegex"`
}
// Equal tests for equality between two Redirect types

View file

@ -191,7 +191,7 @@ func TestUseRegex(t *testing.T) {
if !ok {
t.Errorf("expected a App Context")
}
if redirect.UseRegex != true {
if !redirect.UseRegex {
t.Errorf("Unexpected value got in UseRegex")
}
}

View file

@ -38,7 +38,8 @@ func (n NGINXController) Name() string {
func (n *NGINXController) Check(_ *http.Request) error {
url := fmt.Sprintf("http://127.0.0.1:%v%v", n.cfg.ListenPorts.Status, ngxHealthPath)
statusCode, err := simpleGet(url)
timeout := n.cfg.HealthCheckTimeout
statusCode, err := simpleGet(url, timeout)
if err != nil {
return err
}
@ -48,7 +49,7 @@ func (n *NGINXController) Check(_ *http.Request) error {
}
url = fmt.Sprintf("http://127.0.0.1:%v/is-dynamic-lb-initialized", n.cfg.ListenPorts.Status)
statusCode, err = simpleGet(url)
statusCode, err = simpleGet(url, timeout)
if err != nil {
return err
}
@ -75,9 +76,9 @@ func (n *NGINXController) Check(_ *http.Request) error {
return err
}
func simpleGet(url string) (int, error) {
func simpleGet(url string, timeout time.Duration) (int, error) {
client := &http.Client{
Timeout: 10 * time.Second,
Timeout: timeout * time.Second,
Transport: &http.Transport{DisableKeepAlives: true},
}

View file

@ -102,10 +102,10 @@ type Configuration struct {
// By default access logs go to /var/log/nginx/access.log
AccessLogPath string `json:"access-log-path,omitempty"`
// WorkerCpuAffinity bind nginx worker processes to CPUs this will improve response latency
// WorkerCPUAffinity bind nginx worker processes to CPUs this will improve response latency
// http://nginx.org/en/docs/ngx_core_module.html#worker_cpu_affinity
// By default this is disabled
WorkerCpuAffinity string `json:"worker-cpu-affinity,omitempty"`
WorkerCPUAffinity string `json:"worker-cpu-affinity,omitempty"`
// ErrorLogPath sets the path of the error logs
// http://nginx.org/en/docs/ngx_core_module.html#error_log
// By default error logs go to /var/log/nginx/error.log
@ -347,6 +347,10 @@ type Configuration struct {
// http://nginx.org/en/docs/http/ngx_http_geoip_module.html
UseGeoIP bool `json:"use-geoip,omitempty"`
// UseGeoIP2 enables the geoip2 module for NGINX
// By default this is disabled
UseGeoIP2 bool `json:"use-geoip2,omitempty"`
// Enables or disables the use of the NGINX Brotli Module for compression
// https://github.com/google/ngx_brotli
EnableBrotli bool `json:"enable-brotli,omitempty"`
@ -438,11 +442,11 @@ type Configuration struct {
// If the request does not have a request-id, should we generate a random value?
// Default: true
GenerateRequestId bool `json:"generate-request-id,omitempty"`
GenerateRequestID bool `json:"generate-request-id,omitempty"`
// Adds an X-Original-Uri header with the original request URI to the backend request
// Default: true
ProxyAddOriginalUriHeader bool `json:"proxy-add-original-uri-header"`
ProxyAddOriginalURIHeader bool `json:"proxy-add-original-uri-header"`
// EnableOpentracing enables the nginx Opentracing extension
// https://github.com/opentracing-contrib/nginx-opentracing
@ -570,7 +574,7 @@ func NewDefault() Configuration {
cfg := Configuration{
AllowBackendServerHeader: false,
AccessLogPath: "/var/log/nginx/access.log",
WorkerCpuAffinity: "",
WorkerCPUAffinity: "",
ErrorLogPath: "/var/log/nginx/error.log",
BlockCIDRs: defBlockEntity,
BlockUserAgents: defBlockEntity,
@ -587,8 +591,8 @@ func NewDefault() Configuration {
UseForwardedHeaders: true,
ForwardedForHeader: "X-Forwarded-For",
ComputeFullForwardedFor: false,
ProxyAddOriginalUriHeader: true,
GenerateRequestId: true,
ProxyAddOriginalURIHeader: true,
GenerateRequestID: true,
HTTP2MaxFieldSize: "4k",
HTTP2MaxHeaderSize: "16k",
HTTP2MaxRequests: 1000,
@ -630,6 +634,7 @@ func NewDefault() Configuration {
EnableBrotli: false,
UseGzip: true,
UseGeoIP: true,
UseGeoIP2: false,
WorkerProcesses: strconv.Itoa(runtime.NumCPU()),
WorkerShutdownTimeout: "10s",
LoadBalanceAlgorithm: defaultLoadBalancerAlgorithm,

View file

@ -61,6 +61,7 @@ type Configuration struct {
ForceNamespaceIsolation bool
DefaultHealthzURL string
HealthCheckTimeout time.Duration
DefaultSSLCertificate string
// +optional

View file

@ -18,7 +18,6 @@ package controller
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
@ -257,7 +256,7 @@ func (n *NGINXController) Start() {
n.store.Run(n.stopCh)
if n.syncStatus != nil {
go n.syncStatus.Run(context.Background())
go n.syncStatus.Run()
}
cmd := nginxExecCommand()
@ -812,12 +811,7 @@ func configureCertificates(pcfg *ingress.Configuration, port int) error {
}
url := fmt.Sprintf("http://localhost:%d/configuration/servers", port)
err := post(url, servers)
if err != nil {
return err
}
return nil
return post(url, servers)
}
func post(url string, data interface{}) error {

View file

@ -90,7 +90,7 @@ func TestMergeConfigMapToStruct(t *testing.T) {
def.WorkerShutdownTimeout = "99s"
def.NginxStatusIpv4Whitelist = []string{"127.0.0.1", "10.0.0.0/24"}
def.NginxStatusIpv6Whitelist = []string{"::1", "2001::/16"}
def.ProxyAddOriginalUriHeader = false
def.ProxyAddOriginalURIHeader = false
hash, err := hashstructure.Hash(def, &hashstructure.HashOptions{
TagName: "json",

View file

@ -209,8 +209,6 @@ func buildLuaSharedDictionaries(s interface{}, disableLuaRestyWAF bool) string {
"lua_shared_dict configuration_data 5M",
"lua_shared_dict certificate_data 16M",
"lua_shared_dict locks 512k",
"lua_shared_dict balancer_ewma 1M",
"lua_shared_dict balancer_ewma_last_touched_at 1M",
"lua_shared_dict sticky_sessions 1M",
}
@ -724,19 +722,6 @@ func buildUpstreamName(loc interface{}) string {
return upstreamName
}
// TODO: Needs Unit Tests
func isSticky(host string, loc *ingress.Location, stickyLocations map[string][]string) bool {
if _, ok := stickyLocations[host]; ok {
for _, sl := range stickyLocations[host] {
if sl == loc.Path {
return true
}
}
}
return false
}
func buildNextUpstream(i, r interface{}) string {
nextUpstream, ok := i.(string)
if !ok {

View file

@ -171,7 +171,7 @@ func NewSocketCollector(pod, namespace, class string) (*SocketCollector, error)
bytesSent: prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Name: "bytes_sent",
Help: "The the number of bytes sent to a client",
Help: "The number of bytes sent to a client",
Namespace: PrometheusNamespace,
Buckets: prometheus.ExponentialBuckets(10, 10, 7), // 7 buckets, exponential factor of 10.
ConstLabels: constLabels,

View file

@ -51,7 +51,7 @@ const (
// Sync ...
type Sync interface {
Run(ctx context.Context)
Run()
Shutdown()
}
@ -93,22 +93,102 @@ type statusSync struct {
pod *k8s.PodInfo
elector *leaderelection.LeaderElector
// workqueue used to keep in sync the status IP/s
// in the Ingress rules
syncQueue *task.Queue
}
// Run starts the loop to keep the status in sync
func (s statusSync) Run(ctx context.Context) {
s.elector.Run(ctx)
func (s statusSync) Run() {
// we need to use the defined ingress class to allow multiple leaders
// in order to update information about ingress status
electionID := fmt.Sprintf("%v-%v", s.Config.ElectionID, s.Config.DefaultIngressClass)
if s.Config.IngressClass != "" {
electionID = fmt.Sprintf("%v-%v", s.Config.ElectionID, s.Config.IngressClass)
}
// start a new context
ctx := context.Background()
var cancelContext context.CancelFunc
var newLeaderCtx = func(ctx context.Context) context.CancelFunc {
// allow to cancel the context in case we stop being the leader
leaderCtx, cancel := context.WithCancel(ctx)
go s.elector.Run(leaderCtx)
return cancel
}
var stopCh chan struct{}
callbacks := leaderelection.LeaderCallbacks{
OnStartedLeading: func(ctx context.Context) {
glog.V(2).Infof("I am the new status update leader")
stopCh = make(chan struct{})
go s.syncQueue.Run(time.Second, stopCh)
// trigger initial sync
s.syncQueue.EnqueueTask(task.GetDummyObject("sync status"))
// when this instance is the leader we need to enqueue
// an item to trigger the update of the Ingress status.
wait.PollUntil(updateInterval, func() (bool, error) {
s.syncQueue.EnqueueTask(task.GetDummyObject("sync status"))
return false, nil
}, stopCh)
},
OnStoppedLeading: func() {
glog.V(2).Infof("I am not status update leader anymore")
close(stopCh)
// cancel the context
cancelContext()
cancelContext = newLeaderCtx(ctx)
},
OnNewLeader: func(identity string) {
glog.Infof("new leader elected: %v", identity)
},
}
broadcaster := record.NewBroadcaster()
hostname, _ := os.Hostname()
recorder := broadcaster.NewRecorder(scheme.Scheme, apiv1.EventSource{
Component: "ingress-leader-elector",
Host: hostname,
})
lock := resourcelock.ConfigMapLock{
ConfigMapMeta: metav1.ObjectMeta{Namespace: s.pod.Namespace, Name: electionID},
Client: s.Config.Client.CoreV1(),
LockConfig: resourcelock.ResourceLockConfig{
Identity: s.pod.Name,
EventRecorder: recorder,
},
}
ttl := 30 * time.Second
var err error
s.elector, err = leaderelection.NewLeaderElector(leaderelection.LeaderElectionConfig{
Lock: &lock,
LeaseDuration: ttl,
RenewDeadline: ttl / 2,
RetryPeriod: ttl / 4,
Callbacks: callbacks,
})
if err != nil {
glog.Fatalf("unexpected error starting leader election: %v", err)
}
cancelContext = newLeaderCtx(ctx)
}
// Shutdown stop the sync. In case the instance is the leader it will remove the current IP
// if there is no other instances running.
func (s statusSync) Shutdown() {
go s.syncQueue.Shutdown()
// remove IP from Ingress
if !s.elector.IsLeader() {
if s.elector != nil && !s.elector.IsLeader() {
return
}
@ -146,6 +226,10 @@ func (s *statusSync) sync(key interface{}) error {
return nil
}
if s.elector != nil && !s.elector.IsLeader() {
return fmt.Errorf("i am not the current leader. Skiping status update")
}
addrs, err := s.runningAddresses()
if err != nil {
return err
@ -173,66 +257,6 @@ func NewStatusSyncer(config Config) Sync {
}
st.syncQueue = task.NewCustomTaskQueue(st.sync, st.keyfunc)
// we need to use the defined ingress class to allow multiple leaders
// in order to update information about ingress status
electionID := fmt.Sprintf("%v-%v", config.ElectionID, config.DefaultIngressClass)
if config.IngressClass != "" {
electionID = fmt.Sprintf("%v-%v", config.ElectionID, config.IngressClass)
}
var stopCh chan struct{}
callbacks := leaderelection.LeaderCallbacks{
OnStartedLeading: func(ctx context.Context) {
glog.V(2).Infof("I am the new status update leader")
stopCh = make(chan struct{})
go st.syncQueue.Run(time.Second, stopCh)
// when this instance is the leader we need to enqueue
// an item to trigger the update of the Ingress status.
wait.PollUntil(updateInterval, func() (bool, error) {
st.syncQueue.EnqueueTask(task.GetDummyObject("sync status"))
return false, nil
}, stopCh)
},
OnStoppedLeading: func() {
glog.V(2).Infof("I am not status update leader anymore")
close(stopCh)
},
OnNewLeader: func(identity string) {
glog.Infof("new leader elected: %v", identity)
},
}
broadcaster := record.NewBroadcaster()
hostname, _ := os.Hostname()
recorder := broadcaster.NewRecorder(scheme.Scheme, apiv1.EventSource{
Component: "ingress-leader-elector",
Host: hostname,
})
lock := resourcelock.ConfigMapLock{
ConfigMapMeta: metav1.ObjectMeta{Namespace: pod.Namespace, Name: electionID},
Client: config.Client.CoreV1(),
LockConfig: resourcelock.ResourceLockConfig{
Identity: pod.Name,
EventRecorder: recorder,
},
}
ttl := 30 * time.Second
le, err := leaderelection.NewLeaderElector(leaderelection.LeaderElectionConfig{
Lock: &lock,
LeaseDuration: ttl,
RenewDeadline: ttl / 2,
RetryPeriod: ttl / 4,
Callbacks: callbacks,
})
if err != nil {
glog.Fatalf("unexpected error starting leader election: %v", err)
}
st.elector = le
return st
}
@ -333,6 +357,13 @@ func (s *statusSync) updateStatus(newIngressPoint []apiv1.LoadBalancerIngress) {
sort.SliceStable(newIngressPoint, lessLoadBalancerIngress(newIngressPoint))
for _, ing := range ings {
curIPs := ing.Status.LoadBalancer.Ingress
sort.SliceStable(curIPs, lessLoadBalancerIngress(curIPs))
if ingressSliceEqual(curIPs, newIngressPoint) {
glog.V(3).Infof("skipping update of Ingress %v/%v (no change)", ing.Namespace, ing.Name)
continue
}
batch.Queue(runUpdate(ing, newIngressPoint, s.Client))
}
@ -347,14 +378,6 @@ func runUpdate(ing *extensions.Ingress, status []apiv1.LoadBalancerIngress,
return nil, nil
}
curIPs := ing.Status.LoadBalancer.Ingress
sort.SliceStable(curIPs, lessLoadBalancerIngress(curIPs))
if ingressSliceEqual(status, curIPs) {
glog.V(3).Infof("skipping update of Ingress %v/%v (no change)", ing.Namespace, ing.Name)
return true, nil
}
ingClient := client.ExtensionsV1beta1().Ingresses(ing.Namespace)
currIng, err := ingClient.Get(ing.Name, metav1.GetOptions{})
@ -398,5 +421,6 @@ func ingressSliceEqual(lhs, rhs []apiv1.LoadBalancerIngress) bool {
return false
}
}
return true
}

View file

@ -17,7 +17,6 @@ limitations under the License.
package status
import (
"context"
"os"
"testing"
"time"
@ -298,7 +297,7 @@ func TestStatusActions(t *testing.T) {
fk := fkSync.(statusSync)
// start it and wait for the election and syn actions
go fk.Run(context.Background())
go fk.Run()
// wait for the election
time.Sleep(100 * time.Millisecond)
// execute sync

View file

@ -5,38 +5,17 @@
-- /finagle-core/src/main/scala/com/twitter/finagle/loadbalancer/PeakEwma.scala
local resty_lock = require("resty.lock")
local util = require("util")
local split = require("util.split")
local DECAY_TIME = 10 -- this value is in seconds
local LOCK_KEY = ":ewma_key"
local PICK_SET_SIZE = 2
local ewma_lock = resty_lock:new("locks", {timeout = 0, exptime = 0.1})
local balancer_ewma = {}
local balancer_ewma_last_touched_at = {}
local _M = { name = "ewma" }
local function lock(upstream)
local _, err = ewma_lock:lock(upstream .. LOCK_KEY)
if err then
if err ~= "timeout" then
ngx.log(ngx.ERR, string.format("EWMA Balancer failed to lock: %s", tostring(err)))
end
end
return err
end
local function unlock()
local ok, err = ewma_lock:unlock()
if not ok then
ngx.log(ngx.ERR, string.format("EWMA Balancer failed to unlock: %s", tostring(err)))
end
return err
end
local function decay_ewma(ewma, last_touched_at, rtt, now)
local td = now - last_touched_at
td = (td > 0) and td or 0
@ -47,40 +26,18 @@ local function decay_ewma(ewma, last_touched_at, rtt, now)
end
local function get_or_update_ewma(upstream, rtt, update)
local lock_err = nil
if update then
lock_err = lock(upstream)
end
local ewma = ngx.shared.balancer_ewma:get(upstream) or 0
if lock_err ~= nil then
return ewma, lock_err
end
local ewma = balancer_ewma[upstream] or 0
local now = ngx.now()
local last_touched_at = ngx.shared.balancer_ewma_last_touched_at:get(upstream) or 0
local last_touched_at = balancer_ewma_last_touched_at[upstream] or 0
ewma = decay_ewma(ewma, last_touched_at, rtt, now)
if not update then
return ewma, nil
end
local success, err, forcible = ngx.shared.balancer_ewma_last_touched_at:set(upstream, now)
if not success then
ngx.log(ngx.WARN, "balancer_ewma_last_touched_at:set failed " .. err)
end
if forcible then
ngx.log(ngx.WARN, "balancer_ewma_last_touched_at:set valid items forcibly overwritten")
end
success, err, forcible = ngx.shared.balancer_ewma:set(upstream, ewma)
if not success then
ngx.log(ngx.WARN, "balancer_ewma:set failed " .. err)
end
if forcible then
ngx.log(ngx.WARN, "balancer_ewma:set valid items forcibly overwritten")
end
unlock()
balancer_ewma_last_touched_at[upstream] = now
balancer_ewma[upstream] = ewma
return ewma, nil
end
@ -153,8 +110,8 @@ function _M.sync(self, backend)
self.peers = backend.endpoints
-- TODO: Reset state of EWMA per backend
ngx.shared.balancer_ewma:flush_all()
ngx.shared.balancer_ewma_last_touched_at:flush_all()
balancer_ewma = {}
balancer_ewma_last_touched_at = {}
end
function _M.new(self, backend)

View file

@ -94,22 +94,17 @@ local function set_cookie(self, value)
end
end
local function pick_random(instance)
local index = math.random(instance.npoints)
return instance:next(index)
end
function _M.balance(self)
local cookie, err = ck:new()
if not cookie then
ngx.log(ngx.ERR, err)
return pick_random(self.instance)
ngx.log(ngx.ERR, "error while initializing cookie: " .. tostring(err))
return
end
local key = cookie:get(self.cookie_name)
if not key then
local tmp_endpoint_string = pick_random(self.instance)
key = encrypted_endpoint_string(self, tmp_endpoint_string)
local random_str = string.format("%s.%s", ngx.now(), ngx.worker.pid())
key = encrypted_endpoint_string(self, random_str)
set_cookie(self, key)
end

View file

@ -26,10 +26,6 @@ describe("Balancer ewma", function()
local instance = balancer_ewma:new(backend)
local stats = { ["10.184.7.40:8080"] = 0.5, ["10.184.97.100:8080"] = 0.3 }
ngx.shared.balancer_ewma.get = function(self, key) return stats[key] end
local t = ngx.now()-10
ngx.shared.balancer_ewma_last_touched_at.get = function(self, key) return t end
local peer = instance:balance()
assert.equal("10.184.97.100:8080", peer)
@ -52,13 +48,7 @@ describe("Balancer ewma", function()
endpoints = { { address = "10.184.7.40", port = "8080", maxFails = 0, failTimeout = 0 } }
}
local s1 = spy.on(ngx.shared.balancer_ewma, "flush_all")
local s2 = spy.on(ngx.shared.balancer_ewma_last_touched_at, "flush_all")
instance:sync(new_backend)
assert.spy(s1).was_not_called()
assert.spy(s2).was_not_called()
end)
it("updates endpoints", function()
@ -77,13 +67,7 @@ describe("Balancer ewma", function()
local new_backend = util.deepcopy(backend)
new_backend.endpoints[1].maxFails = 3
local s1 = spy.on(ngx.shared.balancer_ewma, "flush_all")
local s2 = spy.on(ngx.shared.balancer_ewma_last_touched_at, "flush_all")
instance:sync(new_backend)
assert.spy(s1).was_called()
assert.spy(s2).was_called()
end)
end)
end)

View file

@ -116,7 +116,8 @@ describe("Sticky", function()
local cookie_instance = {
set = function(self, payload)
assert.equal(payload.key, test_backend.sessionAffinityConfig.cookieSessionAffinity.name)
assert.equal(payload.value, util[test_backend_hash_fn .. "_digest"](test_backend_endpoint))
local expected_len = #util[test_backend_hash_fn .. "_digest"]("anything")
assert.equal(#payload.value, expected_len)
assert.equal(payload.path, ngx.var.location_path)
assert.equal(payload.domain, nil)
assert.equal(payload.httponly, true)

View file

@ -12,6 +12,10 @@
# setup custom paths that do not require root access
pid /tmp/nginx.pid;
{{ if $cfg.UseGeoIP2 }}
load_module /etc/nginx/modules/ngx_http_geoip2_module.so;
{{ end }}
{{ if $cfg.EnableModsecurity }}
load_module /etc/nginx/modules/ngx_http_modsecurity_module.so;
{{ end }}
@ -23,8 +27,8 @@ load_module /etc/nginx/modules/ngx_http_opentracing_module.so;
daemon off;
worker_processes {{ $cfg.WorkerProcesses }};
{{ if gt (len $cfg.WorkerCpuAffinity) 0 }}
worker_cpu_affinity {{ $cfg.WorkerCpuAffinity }};
{{ if gt (len $cfg.WorkerCPUAffinity) 0 }}
worker_cpu_affinity {{ $cfg.WorkerCPUAffinity }};
{{ end }}
{{ if ne .MaxOpenFiles 0 }}
@ -123,6 +127,26 @@ http {
geoip_proxy_recursive on;
{{ end }}
{{ if $cfg.UseGeoIP2 }}
# https://github.com/leev/ngx_http_geoip2_module#example-usage
geoip2 /etc/nginx/geoip/GeoLite2-City.mmdb {
$geoip2_city_country_code source=$the_real_ip country iso_code;
$geoip2_city_country_name source=$the_real_ip country names en;
$geoip2_city source=$the_real_ip city names en;
$geoip2_postal_code source=$the_real_ip postal code;
$geoip2_dma_code source=$the_real_ip location metro_code;
$geoip2_latitude source=$the_real_ip location latitude;
$geoip2_longitude source=$the_real_ip location longitude;
$geoip2_region_code source=$the_real_ip subdivisions 0 iso_code;
$geoip2_region_name source=$the_real_ip subdivisions 0 names en;
}
geoip2 /etc/nginx/geoip/GeoLite2-ASN.mmdb {
$geoip2_asn source=$the_real_ip autonomous_system_number;
}
{{ end }}
aio threads;
aio_write on;
@ -322,7 +346,7 @@ http {
# If no such header is provided, it can provide a random value.
map $http_x_request_id $req_id {
default $http_x_request_id;
{{ if $cfg.GenerateRequestId }}
{{ if $cfg.GenerateRequestID }}
"" $request_id;
{{ end }}
}
@ -891,9 +915,23 @@ stream {
waf:set_option("mode", "{{ $location.LuaRestyWAF.Mode }}")
waf:set_option("storage_zone", "waf_storage")
{{ if $location.LuaRestyWAF.AllowUnknownContentTypes }}
waf:set_option("allow_unknown_content_types", true)
{{ else }}
waf:set_option("allowed_content_types", { "text/html", "text/json", "application/json" })
{{ end }}
waf:set_option("event_log_level", ngx.WARN)
{{ if gt $location.LuaRestyWAF.ScoreThreshold 0 }}
waf:set_option("score_threshold", {{ $location.LuaRestyWAF.ScoreThreshold }})
{{ end }}
{{ if not $location.LuaRestyWAF.ProcessMultipartBody }}
waf:set_option("process_multipart_body", false)
{{ end }}
{{ if $location.LuaRestyWAF.Debug }}
waf:set_option("debug", true)
waf:set_option("event_log_request_arguments", true)
@ -1077,7 +1115,7 @@ stream {
{{ $proxySetHeader }} X-Forwarded-Host $best_http_host;
{{ $proxySetHeader }} X-Forwarded-Port $pass_port;
{{ $proxySetHeader }} X-Forwarded-Proto $pass_access_scheme;
{{ if $all.Cfg.ProxyAddOriginalUriHeader }}
{{ if $all.Cfg.ProxyAddOriginalURIHeader }}
{{ $proxySetHeader }} X-Original-URI $request_uri;
{{ end }}
{{ $proxySetHeader }} X-Scheme $pass_access_scheme;
@ -1135,7 +1173,6 @@ stream {
proxy_set_header X-Service-Port $service_port;
{{ end }}
{{ if not (empty $location.Backend) }}
{{ buildProxyPass $server.Hostname $all.Backends $location }}
{{ if (or (eq $location.Proxy.ProxyRedirectFrom "default") (eq $location.Proxy.ProxyRedirectFrom "off")) }}
proxy_redirect {{ $location.Proxy.ProxyRedirectFrom }};
@ -1143,10 +1180,6 @@ stream {
proxy_redirect {{ $location.Proxy.ProxyRedirectFrom }} {{ $location.Proxy.ProxyRedirectTo }};
{{ end }}
{{ else }}
# No endpoints available for the request
return 503;
{{ end }}
{{ else }}
# Location denied. Reason: {{ $location.Denied | printf "%q" }}
return 503;
{{ end }}

View file

@ -16,23 +16,27 @@ limitations under the License.
package annotations
/*
import (
"fmt"
"net/http"
"strings"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/parnurzeal/gorequest"
"k8s.io/api/extensions/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/ingress-nginx/test/e2e/framework"
)
// TODO(elvinefendi) merge this with Affinity tests in test/e2e/lua/dynamic_configuration.go
var _ = framework.IngressNginxDescribe("Annotations - Affinity", func() {
var _ = framework.IngressNginxDescribe("Annotations - Affinity/Sticky Sessions", func() {
f := framework.NewDefaultFramework("affinity")
BeforeEach(func() {
err := f.DisableDynamicConfiguration()
Expect(err).NotTo(HaveOccurred())
err = f.NewEchoDeploymentWithReplicas(2)
Expect(err).NotTo(HaveOccurred())
f.NewEchoDeploymentWithReplicas(2)
})
AfterEach(func() {
@ -46,16 +50,12 @@ var _ = framework.IngressNginxDescribe("Annotations - Affinity", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "proxy_pass http://sticky-"+f.IngressController.Namespace+"-http-svc-80;")
return strings.Contains(server, fmt.Sprintf("server_name %s ;", host))
})
Expect(err).NotTo(HaveOccurred())
resp, _, errs := gorequest.New().
Get(f.IngressController.HTTPURL).
@ -67,36 +67,6 @@ var _ = framework.IngressNginxDescribe("Annotations - Affinity", func() {
Expect(resp.Header.Get("Set-Cookie")).Should(ContainSubstring("SERVERID="))
})
It("should redirect to '/something' with enabled affinity", func() {
host := "example.com"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/affinity": "cookie",
"nginx.ingress.kubernetes.io/session-cookie-name": "SERVERID",
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "proxy_pass http://sticky-"+f.IngressController.Namespace+"-http-svc-80;")
})
Expect(err).NotTo(HaveOccurred())
resp, body, errs := gorequest.New().
Get(f.IngressController.HTTPURL).
Set("Host", host).
End()
Expect(len(errs)).Should(BeNumerically("==", 0))
Expect(resp.StatusCode).Should(Equal(http.StatusOK))
Expect(body).Should(ContainSubstring(fmt.Sprintf("request_uri=http://%v:8080/", host)))
Expect(resp.Header.Get("Set-Cookie")).Should(ContainSubstring("SERVERID="))
})
It("should set the path to /something on the generated cookie", func() {
host := "example.com"
annotations := map[string]string{
@ -105,16 +75,12 @@ var _ = framework.IngressNginxDescribe("Annotations - Affinity", func() {
}
ing := framework.NewSingleIngress(host, "/something", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "proxy_pass http://sticky-"+f.IngressController.Namespace+"-http-svc-80;")
return strings.Contains(server, fmt.Sprintf("server_name %s ;", host))
})
Expect(err).NotTo(HaveOccurred())
resp, _, errs := gorequest.New().
Get(f.IngressController.HTTPURL+"/something").
@ -126,14 +92,14 @@ var _ = framework.IngressNginxDescribe("Annotations - Affinity", func() {
Expect(resp.Header.Get("Set-Cookie")).Should(ContainSubstring("Path=/something"))
})
It("should set the path to / on the generated cookie if there's more than one rule referring to the same backend", func() {
It("does not set the path to / on the generated cookie if there's more than one rule referring to the same backend", func() {
host := "example.com"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/affinity": "cookie",
"nginx.ingress.kubernetes.io/session-cookie-name": "SERVERID",
}
ing, err := f.EnsureIngress(&v1beta1.Ingress{
f.EnsureIngress(&v1beta1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: host,
Namespace: f.IngressController.Namespace,
@ -168,14 +134,10 @@ var _ = framework.IngressNginxDescribe("Annotations - Affinity", func() {
},
})
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "proxy_pass http://sticky-"+f.IngressController.Namespace+"-http-svc-80;")
return strings.Contains(server, fmt.Sprintf("server_name %s ;", host))
})
Expect(err).NotTo(HaveOccurred())
resp, _, errs := gorequest.New().
Get(f.IngressController.HTTPURL+"/something").
@ -184,7 +146,15 @@ var _ = framework.IngressNginxDescribe("Annotations - Affinity", func() {
Expect(len(errs)).Should(BeNumerically("==", 0))
Expect(resp.StatusCode).Should(Equal(http.StatusOK))
Expect(resp.Header.Get("Set-Cookie")).Should(ContainSubstring("Path=/;"))
Expect(resp.Header.Get("Set-Cookie")).Should(ContainSubstring("Path=/something;"))
resp, _, errs = gorequest.New().
Get(f.IngressController.HTTPURL+"/somewhereelese").
Set("Host", host).
End()
Expect(len(errs)).Should(BeNumerically("==", 0))
Expect(resp.StatusCode).Should(Equal(http.StatusOK))
Expect(resp.Header.Get("Set-Cookie")).Should(ContainSubstring("Path=/somewhereelese;"))
})
})
*/

View file

@ -31,8 +31,7 @@ var _ = framework.IngressNginxDescribe("Annotations - Alias", func() {
f := framework.NewDefaultFramework("alias")
BeforeEach(func() {
err := f.NewEchoDeployment()
Expect(err).NotTo(HaveOccurred())
f.NewEchoDeployment()
})
AfterEach(func() {
@ -43,17 +42,13 @@ var _ = framework.IngressNginxDescribe("Annotations - Alias", func() {
annotations := map[string]string{}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("server_name foo")) &&
Expect(server).ShouldNot(ContainSubstring("return 503"))
})
Expect(err).NotTo(HaveOccurred())
resp, body, errs := gorequest.New().
Get(f.IngressController.HTTPURL).
@ -81,17 +76,13 @@ var _ = framework.IngressNginxDescribe("Annotations - Alias", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("server_name foo")) &&
Expect(server).ShouldNot(ContainSubstring("return 503"))
})
Expect(err).NotTo(HaveOccurred())
hosts := []string{"foo", "bar"}
for _, host := range hosts {

View file

@ -0,0 +1,66 @@
/*
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 annotations
import (
"net/http"
"time"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/parnurzeal/gorequest"
"k8s.io/ingress-nginx/test/e2e/framework"
)
var _ = framework.IngressNginxDescribe("Annotations - Approot", func() {
f := framework.NewDefaultFramework("approot")
BeforeEach(func() {
f.NewEchoDeploymentWithReplicas(2)
})
AfterEach(func() {
})
It("should redirect to /foo", func() {
host := "approot.bar.com"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/app-root": "/foo",
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
f.EnsureIngress(ing)
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring(`if ($uri = /) {`)) &&
Expect(server).Should(ContainSubstring(`return 302 /foo;`))
})
resp, _, errs := gorequest.New().
Get(f.IngressController.HTTPURL).
Retry(10, 1*time.Second, http.StatusNotFound).
RedirectPolicy(noRedirectPolicyFunc).
Set("Host", host).
End()
Expect(len(errs)).Should(BeNumerically("==", 0))
Expect(resp.StatusCode).Should(Equal(http.StatusFound))
Expect(resp.Header.Get("Location")).Should(Equal("http://approot.bar.com/foo"))
})
})

View file

@ -25,6 +25,7 @@ import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/parnurzeal/gorequest"
corev1 "k8s.io/api/core/v1"
@ -39,8 +40,7 @@ var _ = framework.IngressNginxDescribe("Annotations - Auth", func() {
f := framework.NewDefaultFramework("auth")
BeforeEach(func() {
err := f.NewEchoDeployment()
Expect(err).NotTo(HaveOccurred())
f.NewEchoDeployment()
})
AfterEach(func() {
@ -50,17 +50,13 @@ var _ = framework.IngressNginxDescribe("Annotations - Auth", func() {
host := "auth"
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, nil)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("server_name auth")) &&
Expect(server).ShouldNot(ContainSubstring("return 503"))
})
Expect(err).NotTo(HaveOccurred())
resp, body, errs := gorequest.New().
Get(f.IngressController.HTTPURL).
@ -82,17 +78,13 @@ var _ = framework.IngressNginxDescribe("Annotations - Auth", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("server_name auth")) &&
Expect(server).Should(ContainSubstring("return 503"))
})
Expect(err).NotTo(HaveOccurred())
resp, body, errs := gorequest.New().
Get(f.IngressController.HTTPURL).
@ -108,10 +100,7 @@ var _ = framework.IngressNginxDescribe("Annotations - Auth", func() {
It("should return status code 401 when authentication is configured but Authorization header is not configured", func() {
host := "auth"
s, err := f.EnsureSecret(buildSecret("foo", "bar", "test", f.IngressController.Namespace))
Expect(err).NotTo(HaveOccurred())
Expect(s).NotTo(BeNil())
Expect(s.ObjectMeta).NotTo(BeNil())
s := f.EnsureSecret(buildSecret("foo", "bar", "test", f.IngressController.Namespace))
annotations := map[string]string{
"nginx.ingress.kubernetes.io/auth-type": "basic",
@ -120,17 +109,13 @@ var _ = framework.IngressNginxDescribe("Annotations - Auth", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err = f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("server_name auth")) &&
Expect(server).ShouldNot(ContainSubstring("return 503"))
})
Expect(err).NotTo(HaveOccurred())
resp, body, errs := gorequest.New().
Get(f.IngressController.HTTPURL).
@ -146,10 +131,7 @@ var _ = framework.IngressNginxDescribe("Annotations - Auth", func() {
It("should return status code 401 when authentication is configured and Authorization header is sent with invalid credentials", func() {
host := "auth"
s, err := f.EnsureSecret(buildSecret("foo", "bar", "test", f.IngressController.Namespace))
Expect(err).NotTo(HaveOccurred())
Expect(s).NotTo(BeNil())
Expect(s.ObjectMeta).NotTo(BeNil())
s := f.EnsureSecret(buildSecret("foo", "bar", "test", f.IngressController.Namespace))
annotations := map[string]string{
"nginx.ingress.kubernetes.io/auth-type": "basic",
@ -158,17 +140,13 @@ var _ = framework.IngressNginxDescribe("Annotations - Auth", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err = f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("server_name auth")) &&
Expect(server).ShouldNot(ContainSubstring("return 503"))
})
Expect(err).NotTo(HaveOccurred())
resp, body, errs := gorequest.New().
Get(f.IngressController.HTTPURL).
@ -185,10 +163,7 @@ var _ = framework.IngressNginxDescribe("Annotations - Auth", func() {
It("should return status code 200 when authentication is configured and Authorization header is sent", func() {
host := "auth"
s, err := f.EnsureSecret(buildSecret("foo", "bar", "test", f.IngressController.Namespace))
Expect(err).NotTo(HaveOccurred())
Expect(s).NotTo(BeNil())
Expect(s.ObjectMeta).NotTo(BeNil())
s := f.EnsureSecret(buildSecret("foo", "bar", "test", f.IngressController.Namespace))
annotations := map[string]string{
"nginx.ingress.kubernetes.io/auth-type": "basic",
@ -197,17 +172,13 @@ var _ = framework.IngressNginxDescribe("Annotations - Auth", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err = f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("server_name auth")) &&
Expect(server).ShouldNot(ContainSubstring("return 503"))
})
Expect(err).NotTo(HaveOccurred())
resp, _, errs := gorequest.New().
Get(f.IngressController.HTTPURL).
@ -223,7 +194,7 @@ var _ = framework.IngressNginxDescribe("Annotations - Auth", func() {
It("should return status code 500 when authentication is configured with invalid content and Authorization header is sent", func() {
host := "auth"
s, err := f.EnsureSecret(
s := f.EnsureSecret(
&corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
@ -236,9 +207,6 @@ var _ = framework.IngressNginxDescribe("Annotations - Auth", func() {
Type: corev1.SecretTypeOpaque,
},
)
Expect(err).NotTo(HaveOccurred())
Expect(s).NotTo(BeNil())
Expect(s.ObjectMeta).NotTo(BeNil())
annotations := map[string]string{
"nginx.ingress.kubernetes.io/auth-type": "basic",
@ -247,17 +215,13 @@ var _ = framework.IngressNginxDescribe("Annotations - Auth", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err = f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("server_name auth")) &&
Expect(server).ShouldNot(ContainSubstring("return 503"))
})
Expect(err).NotTo(HaveOccurred())
resp, _, errs := gorequest.New().
Get(f.IngressController.HTTPURL).
@ -274,11 +238,10 @@ var _ = framework.IngressNginxDescribe("Annotations - Auth", func() {
host := "auth"
BeforeEach(func() {
err := f.NewHttpbinDeployment()
Expect(err).NotTo(HaveOccurred())
f.NewHttpbinDeployment()
var httpbinIP string
err = wait.PollImmediate(time.Second, time.Minute, func() (bool, error) {
err := wait.PollImmediate(time.Second, time.Minute, func() (bool, error) {
e, err := f.KubeClientSet.CoreV1().Endpoints(f.IngressController.Namespace).Get("httpbin", metav1.GetOptions{})
if errors.IsNotFound(err) {
return false, nil
@ -300,15 +263,11 @@ var _ = framework.IngressNginxDescribe("Annotations - Auth", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err = f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host, func(server string) bool {
f.WaitForNginxServer(host, func(server string) bool {
return Expect(server).ShouldNot(ContainSubstring("return 503"))
})
Expect(err).NotTo(HaveOccurred())
})
It("should return status code 200 when signed in", func() {

View file

@ -19,20 +19,20 @@ package annotations
import (
"crypto/tls"
"fmt"
"net/http"
"strings"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/parnurzeal/gorequest"
"k8s.io/ingress-nginx/test/e2e/framework"
"net/http"
"strings"
)
var _ = framework.IngressNginxDescribe("Annotations - AuthTLS", func() {
f := framework.NewDefaultFramework("authtls")
BeforeEach(func() {
err := f.NewEchoDeploymentWithReplicas(2)
Expect(err).NotTo(HaveOccurred())
f.NewEchoDeploymentWithReplicas(2)
})
AfterEach(func() {
@ -54,10 +54,7 @@ var _ = framework.IngressNginxDescribe("Annotations - AuthTLS", func() {
}
ing := framework.NewSingleIngressWithTLS(host, "/", host, nameSpace, "http-svc", 80, &annotations)
_, err = f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
f.EnsureIngress(ing)
// Since we can use the same certificate-chain for tls as well as mutual-auth, we will check all values
sslCertDirective := fmt.Sprintf("ssl_certificate /etc/ingress-controller/ssl/%s-%s.pem;", nameSpace, host)
@ -67,11 +64,14 @@ var _ = framework.IngressNginxDescribe("Annotations - AuthTLS", func() {
sslVerify := "ssl_verify_client on;"
sslVerifyDepth := "ssl_verify_depth 1;"
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, sslCertDirective) && strings.Contains(server, sslKeyDirective) && strings.Contains(server, sslClientCertDirective) && strings.Contains(server, sslVerify) && strings.Contains(server, sslVerifyDepth)
return strings.Contains(server, sslCertDirective) &&
strings.Contains(server, sslKeyDirective) &&
strings.Contains(server, sslClientCertDirective) &&
strings.Contains(server, sslVerify) &&
strings.Contains(server, sslVerifyDepth)
})
Expect(err).NotTo(HaveOccurred())
// Send Request without Client Certs
req := gorequest.New()
@ -112,10 +112,7 @@ var _ = framework.IngressNginxDescribe("Annotations - AuthTLS", func() {
}
ing := framework.NewSingleIngressWithTLS(host, "/", host, nameSpace, "http-svc", 80, &annotations)
_, err = f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
f.EnsureIngress(ing)
// Since we can use the same certificate-chain for tls as well as mutual-auth, we will check all values
sslCertDirective := fmt.Sprintf("ssl_certificate /etc/ingress-controller/ssl/%s-%s.pem;", nameSpace, host)
@ -125,11 +122,10 @@ var _ = framework.IngressNginxDescribe("Annotations - AuthTLS", func() {
sslVerify := "ssl_verify_client off;"
sslVerifyDepth := "ssl_verify_depth 2;"
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, sslCertDirective) && strings.Contains(server, sslKeyDirective) && strings.Contains(server, sslClientCertDirective) && strings.Contains(server, sslVerify) && strings.Contains(server, sslVerifyDepth)
})
Expect(err).NotTo(HaveOccurred())
// Send Request without Client Certs
req := gorequest.New()
@ -163,9 +159,7 @@ var _ = framework.IngressNginxDescribe("Annotations - AuthTLS", func() {
}
ing := framework.NewSingleIngressWithTLS(host, "/", host, nameSpace, "http-svc", 80, &annotations)
_, err = f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
f.EnsureIngress(ing)
// Since we can use the same certificate-chain for tls as well as mutual-auth, we will check all values
sslCertDirective := fmt.Sprintf("ssl_certificate /etc/ingress-controller/ssl/%s-%s.pem;", nameSpace, host)
@ -177,11 +171,16 @@ var _ = framework.IngressNginxDescribe("Annotations - AuthTLS", func() {
sslErrorPage := fmt.Sprintf("error_page 495 496 = %s;", f.IngressController.HTTPURL+errorPath)
sslUpstreamClientCert := "proxy_set_header ssl-client-cert $ssl_client_escaped_cert;"
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, sslCertDirective) && strings.Contains(server, sslKeyDirective) && strings.Contains(server, sslClientCertDirective) && strings.Contains(server, sslVerify) && strings.Contains(server, sslVerifyDepth) && strings.Contains(server, sslErrorPage) && strings.Contains(server, sslUpstreamClientCert)
return strings.Contains(server, sslCertDirective) &&
strings.Contains(server, sslKeyDirective) &&
strings.Contains(server, sslClientCertDirective) &&
strings.Contains(server, sslVerify) &&
strings.Contains(server, sslVerifyDepth) &&
strings.Contains(server, sslErrorPage) &&
strings.Contains(server, sslUpstreamClientCert)
})
Expect(err).NotTo(HaveOccurred())
// Send Request without Client Certs
req := gorequest.New()

View file

@ -26,8 +26,7 @@ var _ = framework.IngressNginxDescribe("Annotations - Backendprotocol", func() {
f := framework.NewDefaultFramework("backendprotocol")
BeforeEach(func() {
err := f.NewEchoDeploymentWithReplicas(2)
Expect(err).NotTo(HaveOccurred())
f.NewEchoDeploymentWithReplicas(2)
})
AfterEach(func() {
@ -40,16 +39,12 @@ var _ = framework.IngressNginxDescribe("Annotations - Backendprotocol", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("proxy_pass https://upstream_balancer;"))
})
Expect(err).NotTo(HaveOccurred())
})
It("should set backend protocol to grpc://", func() {
@ -59,16 +54,12 @@ var _ = framework.IngressNginxDescribe("Annotations - Backendprotocol", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("grpc_pass grpc://upstream_balancer;"))
})
Expect(err).NotTo(HaveOccurred())
})
It("should set backend protocol to grpcs://", func() {
@ -78,16 +69,12 @@ var _ = framework.IngressNginxDescribe("Annotations - Backendprotocol", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("grpc_pass grpcs://upstream_balancer;"))
})
Expect(err).NotTo(HaveOccurred())
})
It("should set backend protocol to ''", func() {
@ -97,15 +84,11 @@ var _ = framework.IngressNginxDescribe("Annotations - Backendprotocol", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("ajp_pass upstream_balancer;"))
})
Expect(err).NotTo(HaveOccurred())
})
})

View file

@ -26,8 +26,7 @@ var _ = framework.IngressNginxDescribe("Annotations - Client-Body-Buffer-Size",
f := framework.NewDefaultFramework("clientbodybuffersize")
BeforeEach(func() {
err := f.NewEchoDeploymentWithReplicas(2)
Expect(err).NotTo(HaveOccurred())
f.NewEchoDeploymentWithReplicas(2)
})
AfterEach(func() {
@ -40,16 +39,12 @@ var _ = framework.IngressNginxDescribe("Annotations - Client-Body-Buffer-Size",
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("client_body_buffer_size 1000;"))
})
Expect(err).NotTo(HaveOccurred())
})
It("should set client_body_buffer_size to 1K", func() {
@ -59,16 +54,12 @@ var _ = framework.IngressNginxDescribe("Annotations - Client-Body-Buffer-Size",
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("client_body_buffer_size 1K;"))
})
Expect(err).NotTo(HaveOccurred())
})
It("should set client_body_buffer_size to 1k", func() {
@ -78,16 +69,12 @@ var _ = framework.IngressNginxDescribe("Annotations - Client-Body-Buffer-Size",
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("client_body_buffer_size 1k;"))
})
Expect(err).NotTo(HaveOccurred())
})
It("should set client_body_buffer_size to 1m", func() {
@ -97,16 +84,12 @@ var _ = framework.IngressNginxDescribe("Annotations - Client-Body-Buffer-Size",
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("client_body_buffer_size 1m;"))
})
Expect(err).NotTo(HaveOccurred())
})
It("should set client_body_buffer_size to 1M", func() {
@ -116,16 +99,12 @@ var _ = framework.IngressNginxDescribe("Annotations - Client-Body-Buffer-Size",
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("client_body_buffer_size 1M;"))
})
Expect(err).NotTo(HaveOccurred())
})
It("should not set client_body_buffer_size to invalid 1b", func() {
@ -135,15 +114,11 @@ var _ = framework.IngressNginxDescribe("Annotations - Client-Body-Buffer-Size",
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).ShouldNot(ContainSubstring("client_body_buffer_size 1b;"))
})
Expect(err).NotTo(HaveOccurred())
})
})

View file

@ -31,8 +31,7 @@ var _ = framework.IngressNginxDescribe("Annotations - Connection", func() {
f := framework.NewDefaultFramework("connection")
BeforeEach(func() {
err := f.NewEchoDeploymentWithReplicas(2)
Expect(err).NotTo(HaveOccurred())
f.NewEchoDeploymentWithReplicas(2)
})
AfterEach(func() {
@ -45,16 +44,12 @@ var _ = framework.IngressNginxDescribe("Annotations - Connection", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring(`proxy_set_header Connection keep-alive;`))
})
Expect(err).NotTo(HaveOccurred())
resp, body, errs := gorequest.New().
Get(f.IngressController.HTTPURL).

View file

@ -17,10 +17,11 @@ limitations under the License.
package annotations
import (
"net/http"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/parnurzeal/gorequest"
"net/http"
"k8s.io/ingress-nginx/test/e2e/framework"
)
@ -29,8 +30,7 @@ var _ = framework.IngressNginxDescribe("Annotations - CORS", func() {
f := framework.NewDefaultFramework("cors")
BeforeEach(func() {
err := f.NewEchoDeploymentWithReplicas(2)
Expect(err).NotTo(HaveOccurred())
f.NewEchoDeploymentWithReplicas(2)
})
AfterEach(func() {
@ -43,40 +43,32 @@ var _ = framework.IngressNginxDescribe("Annotations - CORS", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("more_set_headers 'Access-Control-Allow-Methods: GET, PUT, POST, DELETE, PATCH, OPTIONS';"))
})
Expect(err).NotTo(HaveOccurred())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("more_set_headers 'Access-Control-Allow-Origin: *';"))
})
Expect(err).NotTo(HaveOccurred())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("more_set_headers 'Access-Control-Allow-Headers: DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';"))
})
Expect(err).NotTo(HaveOccurred())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("more_set_headers 'Access-Control-Max-Age: 1728000';"))
})
Expect(err).NotTo(HaveOccurred())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("more_set_headers 'Access-Control-Allow-Credentials: true';"))
})
Expect(err).NotTo(HaveOccurred())
uri := "/"
resp, _, errs := gorequest.New().
@ -95,16 +87,12 @@ var _ = framework.IngressNginxDescribe("Annotations - CORS", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("more_set_headers 'Access-Control-Allow-Methods: POST, GET';"))
})
Expect(err).NotTo(HaveOccurred())
})
It("should set cors max-age", func() {
@ -115,16 +103,12 @@ var _ = framework.IngressNginxDescribe("Annotations - CORS", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("more_set_headers 'Access-Control-Max-Age: 200';"))
})
Expect(err).NotTo(HaveOccurred())
})
It("should disable cors allow credentials", func() {
@ -135,16 +119,12 @@ var _ = framework.IngressNginxDescribe("Annotations - CORS", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).ShouldNot(ContainSubstring("more_set_headers 'Access-Control-Allow-Credentials: true';"))
})
Expect(err).NotTo(HaveOccurred())
})
It("should allow origin for cors", func() {
@ -155,16 +135,12 @@ var _ = framework.IngressNginxDescribe("Annotations - CORS", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("more_set_headers 'Access-Control-Allow-Origin: https://origin.cors.com:8080';"))
})
Expect(err).NotTo(HaveOccurred())
})
It("should allow headers for cors", func() {
@ -175,15 +151,11 @@ var _ = framework.IngressNginxDescribe("Annotations - CORS", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("more_set_headers 'Access-Control-Allow-Headers: DNT, User-Agent';"))
})
Expect(err).NotTo(HaveOccurred())
})
})

View file

@ -32,8 +32,7 @@ var _ = framework.IngressNginxDescribe("Annotations - custom default-backend", f
f := framework.NewDefaultFramework("default-backend")
BeforeEach(func() {
err := f.NewEchoDeployment()
Expect(err).NotTo(HaveOccurred())
f.NewEchoDeployment()
})
Context("when default backend annotation is enabled", func() {
@ -44,18 +43,14 @@ var _ = framework.IngressNginxDescribe("Annotations - custom default-backend", f
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "invalid", 80, &annotations)
_, err := f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
f.EnsureIngress(ing)
time.Sleep(5 * time.Second)
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring(fmt.Sprintf("server_name %v", host)))
})
Expect(err).NotTo(HaveOccurred())
uri := "/alma/armud"
resp, body, errs := gorequest.New().

View file

@ -0,0 +1,66 @@
/*
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 annotations
import (
"net/http"
"time"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/parnurzeal/gorequest"
"k8s.io/ingress-nginx/test/e2e/framework"
)
var _ = framework.IngressNginxDescribe("Annotations - Forcesslredirect", func() {
f := framework.NewDefaultFramework("forcesslredirect")
BeforeEach(func() {
f.NewEchoDeploymentWithReplicas(2)
})
AfterEach(func() {
})
It("should redirect to https", func() {
host := "forcesslredirect.bar.com"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/force-ssl-redirect": "true",
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
f.EnsureIngress(ing)
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring(`if ($redirect_to_https) {`)) &&
Expect(server).Should(ContainSubstring(`return 308 https://$best_http_host$request_uri;`))
})
resp, _, errs := gorequest.New().
Get(f.IngressController.HTTPURL).
Retry(10, 1*time.Second, http.StatusNotFound).
RedirectPolicy(noRedirectPolicyFunc).
Set("Host", host).
End()
Expect(len(errs)).Should(BeNumerically("==", 0))
Expect(resp.StatusCode).Should(Equal(http.StatusPermanentRedirect))
Expect(resp.Header.Get("Location")).Should(Equal("https://forcesslredirect.bar.com/"))
})
})

View file

@ -31,8 +31,7 @@ var _ = framework.IngressNginxDescribe("Annotations - Fromtowwwredirect", func()
f := framework.NewDefaultFramework("fromtowwwredirect")
BeforeEach(func() {
err := f.NewEchoDeploymentWithReplicas(2)
Expect(err).NotTo(HaveOccurred())
f.NewEchoDeploymentWithReplicas(2)
})
AfterEach(func() {
@ -47,30 +46,25 @@ var _ = framework.IngressNginxDescribe("Annotations - Fromtowwwredirect", func()
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxConfiguration(
f.WaitForNginxConfiguration(
func(cfg string) bool {
return Expect(cfg).Should(ContainSubstring(`server_name www.fromtowwwredirect.bar.com;`)) &&
Expect(cfg).Should(ContainSubstring(`return 308 $scheme://fromtowwwredirect.bar.com$request_uri;`))
})
Expect(err).NotTo(HaveOccurred())
By("sending request to www.fromtowwwredirect.bar.com")
gorequest.New().
resp, _, errs := gorequest.New().
Get(fmt.Sprintf("%s/%s", f.IngressController.HTTPURL, "foo")).
Retry(10, 1*time.Second, http.StatusNotFound).
RedirectPolicy(noRedirectPolicyFunc).
Set("Host", fmt.Sprintf("%s.%s", "www", host)).
End()
log, err := f.NginxLogs()
Expect(err).ToNot(HaveOccurred())
Expect(log).ToNot(BeEmpty())
Expect(log).To(ContainSubstring(fmt.Sprintf(` "GET /foo HTTP/1.1" 308 171 "-" "Go-http-client/1.1"`)))
Expect(len(errs)).Should(BeNumerically("==", 0))
Expect(resp.StatusCode).Should(Equal(http.StatusPermanentRedirect))
Expect(resp.Header.Get("Location")).Should(Equal("http://fromtowwwredirect.bar.com/foo"))
})
})

View file

@ -29,8 +29,7 @@ var _ = framework.IngressNginxDescribe("Annotations - grpc", func() {
f := framework.NewDefaultFramework("grpc")
BeforeEach(func() {
err := f.NewGRPCFortuneTellerDeployment()
Expect(err).NotTo(HaveOccurred())
f.NewGRPCFortuneTellerDeployment()
})
Context("when grpc is enabled", func() {
@ -42,25 +41,20 @@ var _ = framework.IngressNginxDescribe("Annotations - grpc", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "fortune-teller", 50051, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring(fmt.Sprintf("server_name %v", host))) &&
Expect(server).ShouldNot(ContainSubstring("return 503"))
})
Expect(err).NotTo(HaveOccurred())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("grpc_pass")) &&
Expect(server).Should(ContainSubstring("grpc_set_header")) &&
Expect(server).ShouldNot(ContainSubstring("proxy_pass"))
})
Expect(err).NotTo(HaveOccurred())
})
})
})

View file

@ -23,9 +23,10 @@ import (
"os/exec"
"time"
jsoniter "github.com/json-iterator/go"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
jsoniter "github.com/json-iterator/go"
"github.com/parnurzeal/gorequest"
corev1 "k8s.io/api/core/v1"
@ -39,17 +40,13 @@ var _ = framework.IngressNginxDescribe("Annotations - influxdb", func() {
f := framework.NewDefaultFramework("influxdb")
BeforeEach(func() {
err := f.NewInfluxDBDeployment()
Expect(err).NotTo(HaveOccurred())
err = f.NewEchoDeployment()
Expect(err).NotTo(HaveOccurred())
f.NewInfluxDBDeployment()
f.NewEchoDeployment()
})
Context("when influxdb is enabled", func() {
It("should send the request metric to the influxdb server", func() {
ifs, err := createInfluxDBService(f)
Expect(err).NotTo(HaveOccurred())
ifs := createInfluxDBService(f)
// Ingress configured with InfluxDB annotations
host := "influxdb.e2e.local"
@ -80,6 +77,8 @@ var _ = framework.IngressNginxDescribe("Annotations - influxdb", func() {
time.Sleep(5 * time.Second)
var measurements string
var err error
err = wait.PollImmediate(time.Second, time.Minute, func() (bool, error) {
measurements, err = extractInfluxDBMeasurements(f)
if err != nil {
@ -100,7 +99,7 @@ var _ = framework.IngressNginxDescribe("Annotations - influxdb", func() {
})
})
func createInfluxDBService(f *framework.Framework) (*corev1.Service, error) {
func createInfluxDBService(f *framework.Framework) *corev1.Service {
service := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "inflxudb-svc",
@ -120,29 +119,18 @@ func createInfluxDBService(f *framework.Framework) (*corev1.Service, error) {
},
}
s, err := f.EnsureService(service)
if err != nil {
return nil, err
}
if s == nil {
return nil, fmt.Errorf("unexpected error creating service for influxdb deployment")
}
return s, nil
return f.EnsureService(service)
}
func createInfluxDBIngress(f *framework.Framework, host, service string, port int, annotations map[string]string) {
ing, err := f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, service, port, &annotations))
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, service, port, &annotations)
f.EnsureIngress(ing)
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring(fmt.Sprintf("server_name %v", host))) &&
Expect(server).ShouldNot(ContainSubstring("return 503"))
})
Expect(err).NotTo(HaveOccurred())
}
func extractInfluxDBMeasurements(f *framework.Framework) (string, error) {
@ -183,8 +171,7 @@ func execInfluxDBCommand(pod *corev1.Pod, command string) (string, error) {
execErr bytes.Buffer
)
args := fmt.Sprintf("kubectl exec --namespace %v %v -- %v", pod.Namespace, pod.Name, command)
cmd := exec.Command("/bin/bash", "-c", args)
cmd := exec.Command("/bin/bash", "-c", fmt.Sprintf("%v exec --namespace %s %s -- %s", framework.KubectlPath, pod.Namespace, pod.Name, command))
cmd.Stdout = &execOut
cmd.Stderr = &execErr
@ -195,7 +182,7 @@ func execInfluxDBCommand(pod *corev1.Pod, command string) (string, error) {
}
if err != nil {
return "", fmt.Errorf("could not execute: %v", err)
return "", fmt.Errorf("could not execute '%s %s': %v", cmd.Path, cmd.Args, err)
}
return execOut.String(), nil

View file

@ -0,0 +1,79 @@
/*
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 annotations
import (
"regexp"
"strings"
. "github.com/onsi/ginkgo"
"k8s.io/ingress-nginx/test/e2e/framework"
)
var _ = framework.IngressNginxDescribe("Annotations - IPWhiteList", func() {
f := framework.NewDefaultFramework("ipwhitelist")
BeforeEach(func() {
f.NewEchoDeploymentWithReplicas(2)
})
AfterEach(func() {
})
It("should set valid ip whitelist range", func() {
host := "ipwhitelist.foo.com"
nameSpace := f.IngressController.Namespace
annotations := map[string]string{
"nginx.ingress.kubernetes.io/whitelist-source-range": "18.0.0.0/8, 56.0.0.0/8",
}
ing := framework.NewSingleIngress(host, "/", host, nameSpace, "http-svc", 80, &annotations)
f.EnsureIngress(ing)
denyRegex := regexp.MustCompile("geo \\$the_real_ip \\$deny_[A-Za-z]{32}")
denyString := ""
f.WaitForNginxConfiguration(
func(conf string) bool {
match := denyRegex.FindStringSubmatch(conf)
// If no match found, return false
if !(len(match) > 0) {
return false
}
denyString = strings.Replace(match[0], "geo $the_real_ip ", "", -1)
return strings.Contains(conf, match[0])
})
ipOne := "18.0.0.0/8 0;"
ipTwo := "56.0.0.0/8 0;"
f.WaitForNginxConfiguration(
func(conf string) bool {
return strings.Contains(conf, ipOne) && strings.Contains(conf, ipTwo)
})
denyStatement := "if (" + denyString + ")"
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, denyStatement)
})
})
})

View file

@ -19,6 +19,7 @@ package annotations
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"k8s.io/ingress-nginx/test/e2e/framework"
)
@ -26,8 +27,7 @@ var _ = framework.IngressNginxDescribe("Annotations - Log", func() {
f := framework.NewDefaultFramework("log")
BeforeEach(func() {
err := f.NewEchoDeploymentWithReplicas(2)
Expect(err).NotTo(HaveOccurred())
f.NewEchoDeploymentWithReplicas(2)
})
AfterEach(func() {
@ -40,16 +40,12 @@ var _ = framework.IngressNginxDescribe("Annotations - Log", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring(`access_log off;`))
})
Expect(err).NotTo(HaveOccurred())
})
It("set rewrite_log on", func() {
@ -59,15 +55,11 @@ var _ = framework.IngressNginxDescribe("Annotations - Log", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring(`rewrite_log on;`))
})
Expect(err).NotTo(HaveOccurred())
})
})

View file

@ -32,8 +32,7 @@ var _ = framework.IngressNginxDescribe("Annotations - lua-resty-waf", func() {
f := framework.NewDefaultFramework("luarestywaf")
BeforeEach(func() {
err := f.NewEchoDeployment()
Expect(err).NotTo(HaveOccurred())
f.NewEchoDeployment()
})
Context("when lua-resty-waf is enabled", func() {
@ -65,6 +64,71 @@ var _ = framework.IngressNginxDescribe("Annotations - lua-resty-waf", func() {
Expect(len(errs)).Should(Equal(0))
Expect(resp.StatusCode).Should(Equal(http.StatusOK))
})
It("should apply the score threshold", func() {
host := "foo"
createIngress(f, host, "http-svc", 80, map[string]string{
"nginx.ingress.kubernetes.io/lua-resty-waf": "active",
"nginx.ingress.kubernetes.io/lua-resty-waf-score-threshold": "20"})
url := fmt.Sprintf("%s?msg=<A href=\"http://mysite.com/\">XSS</A>", f.IngressController.HTTPURL)
resp, _, errs := gorequest.New().
Get(url).
Set("Host", host).
End()
Expect(len(errs)).Should(Equal(0))
Expect(resp.StatusCode).Should(Equal(http.StatusOK))
})
It("should not reject request with an unknown content type", func() {
host := "foo"
contenttype := "application/octet-stream"
createIngress(f, host, "http-svc", 80, map[string]string{
"nginx.ingress.kubernetes.io/lua-resty-waf-allow-unknown-content-types": "true",
"nginx.ingress.kubernetes.io/lua-resty-waf": "active"})
url := fmt.Sprintf("%s?msg=my-message", f.IngressController.HTTPURL)
resp, _, errs := gorequest.New().
Get(url).
Set("Host", host).
Set("Content-Type", contenttype).
End()
Expect(len(errs)).Should(Equal(0))
Expect(resp.StatusCode).Should(Equal(http.StatusOK))
})
It("should not fail a request with multipart content type when multipart body processing disabled", func() {
contenttype := "multipart/form-data; boundary=alamofire.boundary.3fc2e849279e18fc"
host := "foo"
createIngress(f, host, "http-svc", 80, map[string]string{
"nginx.ingress.kubernetes.io/lua-resty-waf-process-multipart-body": "false",
"nginx.ingress.kubernetes.io/lua-resty-waf": "active"})
url := fmt.Sprintf("%s?msg=my-message", f.IngressController.HTTPURL)
resp, _, errs := gorequest.New().
Get(url).
Set("Host", host).
Set("Content-Type", contenttype).
End()
Expect(len(errs)).Should(Equal(0))
Expect(resp.StatusCode).Should(Equal(http.StatusOK))
})
It("should fail a request with multipart content type when multipart body processing enabled by default", func() {
contenttype := "multipart/form-data; boundary=alamofire.boundary.3fc2e849279e18fc"
host := "foo"
createIngress(f, host, "http-svc", 80, map[string]string{
"nginx.ingress.kubernetes.io/lua-resty-waf": "active"})
url := fmt.Sprintf("%s?msg=my-message", f.IngressController.HTTPURL)
resp, _, errs := gorequest.New().
Get(url).
Set("Host", host).
Set("Content-Type", contenttype).
End()
Expect(len(errs)).Should(Equal(0))
Expect(resp.StatusCode).Should(Equal(http.StatusBadRequest))
})
It("should apply configured extra rules", func() {
host := "foo"
createIngress(f, host, "http-svc", 80, map[string]string{
@ -139,16 +203,14 @@ var _ = framework.IngressNginxDescribe("Annotations - lua-resty-waf", func() {
})
func createIngress(f *framework.Framework, host, service string, port int, annotations map[string]string) {
ing, err := f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, service, port, &annotations))
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, service, port, &annotations)
f.EnsureIngress(ing)
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring(fmt.Sprintf("server_name %v", host))) &&
Expect(server).ShouldNot(ContainSubstring("return 503"))
})
Expect(err).NotTo(HaveOccurred())
time.Sleep(1 * time.Second)

View file

@ -17,9 +17,10 @@ limitations under the License.
package annotations
import (
"strings"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"strings"
"k8s.io/ingress-nginx/test/e2e/framework"
)
@ -28,8 +29,7 @@ var _ = framework.IngressNginxDescribe("Annotations - Proxy", func() {
f := framework.NewDefaultFramework("proxy")
BeforeEach(func() {
err := f.NewEchoDeploymentWithReplicas(2)
Expect(err).NotTo(HaveOccurred())
f.NewEchoDeploymentWithReplicas(2)
})
AfterEach(func() {
@ -43,16 +43,12 @@ var _ = framework.IngressNginxDescribe("Annotations - Proxy", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("proxy_redirect off;"))
})
Expect(err).NotTo(HaveOccurred())
})
It("should set proxy_redirect to default", func() {
@ -63,16 +59,12 @@ var _ = framework.IngressNginxDescribe("Annotations - Proxy", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("proxy_redirect default;"))
})
Expect(err).NotTo(HaveOccurred())
})
It("should set proxy_redirect to hello.com goodbye.com", func() {
@ -83,16 +75,12 @@ var _ = framework.IngressNginxDescribe("Annotations - Proxy", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("proxy_redirect hello.com goodbye.com;"))
})
Expect(err).NotTo(HaveOccurred())
})
It("should set proxy client-max-body-size to 8m", func() {
@ -102,16 +90,12 @@ var _ = framework.IngressNginxDescribe("Annotations - Proxy", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("client_max_body_size 8m;"))
})
Expect(err).NotTo(HaveOccurred())
})
It("should not set proxy client-max-body-size to incorrect value", func() {
@ -121,16 +105,12 @@ var _ = framework.IngressNginxDescribe("Annotations - Proxy", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).ShouldNot(ContainSubstring("client_max_body_size 15r;"))
})
Expect(err).NotTo(HaveOccurred())
})
It("should set valid proxy timeouts", func() {
@ -142,16 +122,12 @@ var _ = framework.IngressNginxDescribe("Annotations - Proxy", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "proxy_connect_timeout 50s;") && strings.Contains(server, "proxy_send_timeout 20s;") && strings.Contains(server, "proxy_read_timeout 20s;")
})
Expect(err).NotTo(HaveOccurred())
})
It("should not set invalid proxy timeouts", func() {
@ -163,16 +139,12 @@ var _ = framework.IngressNginxDescribe("Annotations - Proxy", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return !strings.Contains(server, "proxy_connect_timeout 50ks;") && !strings.Contains(server, "proxy_send_timeout 20ks;") && !strings.Contains(server, "proxy_read_timeout 60s;")
})
Expect(err).NotTo(HaveOccurred())
})
It("should turn on proxy-buffering", func() {
@ -183,16 +155,12 @@ var _ = framework.IngressNginxDescribe("Annotations - Proxy", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "proxy_buffering on;") && strings.Contains(server, "proxy_buffer_size 8k;") && strings.Contains(server, "proxy_buffers 4 8k;") && strings.Contains(server, "proxy_request_buffering on;")
})
Expect(err).NotTo(HaveOccurred())
})
It("should turn off proxy-request-buffering", func() {
@ -202,16 +170,12 @@ var _ = framework.IngressNginxDescribe("Annotations - Proxy", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("proxy_request_buffering off;"))
})
Expect(err).NotTo(HaveOccurred())
})
It("should build proxy next upstream", func() {
@ -222,16 +186,12 @@ var _ = framework.IngressNginxDescribe("Annotations - Proxy", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "proxy_next_upstream error timeout http_502;") && strings.Contains(server, "proxy_next_upstream_tries 5;")
})
Expect(err).NotTo(HaveOccurred())
})
It("should setup proxy cookies", func() {
@ -242,16 +202,11 @@ var _ = framework.IngressNginxDescribe("Annotations - Proxy", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "proxy_cookie_domain localhost example.org;") && strings.Contains(server, "proxy_cookie_path /one/ /;")
})
Expect(err).NotTo(HaveOccurred())
})
})

View file

@ -53,17 +53,13 @@ var _ = framework.IngressNginxDescribe("Annotations - Redirect", func() {
annotations := map[string]string{"nginx.ingress.kubernetes.io/permanent-redirect": redirectURL}
ing := framework.NewSingleIngress(host, redirectPath, host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, fmt.Sprintf("if ($uri ~* %s) {", redirectPath)) &&
strings.Contains(server, fmt.Sprintf("return 301 %s;", redirectURL))
})
Expect(err).NotTo(HaveOccurred())
By("sending request to redirected URL path")
@ -93,17 +89,13 @@ var _ = framework.IngressNginxDescribe("Annotations - Redirect", func() {
}
ing := framework.NewSingleIngress(host, redirectPath, host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, fmt.Sprintf("if ($uri ~* %s) {", redirectPath)) &&
strings.Contains(server, fmt.Sprintf("return %d %s;", redirectCode, redirectURL))
})
Expect(err).NotTo(HaveOccurred())
By("sending request to redirected URL path")

View file

@ -33,8 +33,7 @@ var _ = framework.IngressNginxDescribe("Annotations - Rewrite", func() {
f := framework.NewDefaultFramework("rewrite")
BeforeEach(func() {
err := f.NewEchoDeploymentWithReplicas(1)
Expect(err).NotTo(HaveOccurred())
f.NewEchoDeploymentWithReplicas(1)
})
AfterEach(func() {
@ -48,17 +47,13 @@ var _ = framework.IngressNginxDescribe("Annotations - Rewrite", func() {
expectBodyRequestURI := fmt.Sprintf("request_uri=http://%v:8080/", host)
ing := framework.NewSingleIngress(host, "/something", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, `rewrite "(?i)/something/(.*)" /$1 break;`) &&
strings.Contains(server, `rewrite "(?i)/something$" / break;`)
})
Expect(err).NotTo(HaveOccurred())
By("sending request to Ingress rule path (lowercase)")
@ -93,16 +88,12 @@ var _ = framework.IngressNginxDescribe("Annotations - Rewrite", func() {
}
ing := framework.NewSingleIngress(host, "/something", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "rewrite_log on;")
})
Expect(err).NotTo(HaveOccurred())
resp, _, errs := gorequest.New().
Get(f.IngressController.HTTPURL+"/something").
@ -123,15 +114,12 @@ var _ = framework.IngressNginxDescribe("Annotations - Rewrite", func() {
By("creating a regular ingress definition")
ing := framework.NewSingleIngress("kube-lego", "/.well-known/acme/challenge", host, f.IngressController.Namespace, "http-svc", 80, &map[string]string{})
_, err := f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
f.EnsureIngress(ing)
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "/.well-known/acme/challenge")
})
Expect(err).NotTo(HaveOccurred())
By("making a request to the non-rewritten location")
resp, body, errs := gorequest.New().
@ -148,15 +136,13 @@ var _ = framework.IngressNginxDescribe("Annotations - Rewrite", func() {
"nginx.ingress.kubernetes.io/rewrite-target": "/new/backend",
}
rewriteIng := framework.NewSingleIngress("rewrite-index", "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err = f.EnsureIngress(rewriteIng)
Expect(err).NotTo(HaveOccurred())
Expect(rewriteIng).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.EnsureIngress(rewriteIng)
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "location ~* ^/ {") && strings.Contains(server, `location ~* "^/.well-known/acme/challenge" {`)
})
Expect(err).NotTo(HaveOccurred())
By("making a second request to the non-rewritten location")
resp, body, errs = gorequest.New().
@ -173,15 +159,12 @@ var _ = framework.IngressNginxDescribe("Annotations - Rewrite", func() {
By("creating a regular ingress definition")
ing := framework.NewSingleIngress("foo", "/foo", host, f.IngressController.Namespace, "http-svc", 80, &map[string]string{})
_, err := f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
f.EnsureIngress(ing)
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "location /foo {")
})
Expect(err).NotTo(HaveOccurred())
By(`creating an ingress definition with the use-regex amd rewrite-target annotation`)
annotations := map[string]string{
@ -189,15 +172,12 @@ var _ = framework.IngressNginxDescribe("Annotations - Rewrite", func() {
"nginx.ingress.kubernetes.io/rewrite-target": "/new/backend",
}
ing = framework.NewSingleIngress("regex", "/foo.+", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err = f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
f.EnsureIngress(ing)
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, `location ~* "^/foo" {`) && strings.Contains(server, `location ~* "^/foo.+\/?(?<baseuri>.*)" {`)
})
Expect(err).NotTo(HaveOccurred())
By("ensuring '/foo' matches '~* ^/foo'")
resp, body, errs := gorequest.New().
@ -225,9 +205,7 @@ var _ = framework.IngressNginxDescribe("Annotations - Rewrite", func() {
By("creating a regular ingress definition")
ing := framework.NewSingleIngress("foo", "/foo/bar/bar", host, f.IngressController.Namespace, "http-svc", 80, &map[string]string{})
_, err := f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
f.EnsureIngress(ing)
By(`creating an ingress definition with the use-regex annotation`)
annotations := map[string]string{
@ -235,15 +213,12 @@ var _ = framework.IngressNginxDescribe("Annotations - Rewrite", func() {
"nginx.ingress.kubernetes.io/rewrite-target": "/new/backend",
}
ing = framework.NewSingleIngress("regex", "/foo/bar/[a-z]{3}", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err = f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
f.EnsureIngress(ing)
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, `location ~* "^/foo/bar/bar" {`) && strings.Contains(server, `location ~* "^/foo/bar/[a-z]{3}\/?(?<baseuri>.*)" {`)
})
Expect(err).NotTo(HaveOccurred())
By("check that '/foo/bar/bar' does not match the longest exact path")
resp, body, errs := gorequest.New().

View file

@ -0,0 +1,53 @@
/*
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 annotations
import (
"strings"
. "github.com/onsi/ginkgo"
"k8s.io/ingress-nginx/test/e2e/framework"
)
var _ = framework.IngressNginxDescribe("Annotations - ServerSnippet", func() {
f := framework.NewDefaultFramework("serversnippet")
BeforeEach(func() {
f.NewEchoDeploymentWithReplicas(2)
})
AfterEach(func() {
})
It(`add valid directives to server via server snippet"`, func() {
host := "serversnippet.foo.com"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/server-snippet": `
more_set_headers "Content-Length: $content_length";
more_set_headers "Content-Type: $content_type";`,
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
f.EnsureIngress(ing)
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, `more_set_headers "Content-Length: $content_length`) && strings.Contains(server, `more_set_headers "Content-Type: $content_type";`)
})
})
})

View file

@ -26,8 +26,7 @@ var _ = framework.IngressNginxDescribe("Annotations - Configurationsnippet", fun
f := framework.NewDefaultFramework("configurationsnippet")
BeforeEach(func() {
err := f.NewEchoDeploymentWithReplicas(2)
Expect(err).NotTo(HaveOccurred())
f.NewEchoDeploymentWithReplicas(2)
})
AfterEach(func() {
@ -41,15 +40,11 @@ var _ = framework.IngressNginxDescribe("Annotations - Configurationsnippet", fun
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring(`more_set_headers "Request-Id: $req_id";`))
})
Expect(err).NotTo(HaveOccurred())
})
})

View file

@ -27,8 +27,7 @@ var _ = framework.IngressNginxDescribe("Annotations - SSL CIPHERS", func() {
f := framework.NewDefaultFramework("sslciphers")
BeforeEach(func() {
err := f.NewEchoDeploymentWithReplicas(2)
Expect(err).NotTo(HaveOccurred())
f.NewEchoDeploymentWithReplicas(2)
})
AfterEach(func() {
@ -41,15 +40,11 @@ var _ = framework.IngressNginxDescribe("Annotations - SSL CIPHERS", func() {
}
ing := framework.NewSingleIngress(host, "/something", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("ssl_ciphers ALL:!aNULL:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;"))
})
Expect(err).NotTo(HaveOccurred())
})
})

View file

@ -26,8 +26,7 @@ var _ = framework.IngressNginxDescribe("Annotations - Upstreamvhost", func() {
f := framework.NewDefaultFramework("upstreamvhost")
BeforeEach(func() {
err := f.NewEchoDeploymentWithReplicas(2)
Expect(err).NotTo(HaveOccurred())
f.NewEchoDeploymentWithReplicas(2)
})
AfterEach(func() {
@ -40,15 +39,11 @@ var _ = framework.IngressNginxDescribe("Annotations - Upstreamvhost", func() {
}
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring(`proxy_set_header Host "upstreamvhost.bar.com";`))
})
Expect(err).NotTo(HaveOccurred())
})
})

View file

@ -23,6 +23,7 @@ import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/parnurzeal/gorequest"
appsv1beta1 "k8s.io/api/apps/v1beta1"
@ -34,8 +35,7 @@ var _ = framework.IngressNginxDescribe("Dynamic Certificate", func() {
f := framework.NewDefaultFramework("custom-default-backend")
BeforeEach(func() {
err := f.NewEchoDeploymentWithReplicas(1)
Expect(err).NotTo(HaveOccurred())
f.NewEchoDeploymentWithReplicas(1)
framework.UpdateDeployment(f.KubeClientSet, f.IngressController.Namespace, "nginx-ingress-controller", 1,
func(deployment *appsv1beta1.Deployment) error {
@ -47,11 +47,10 @@ var _ = framework.IngressNginxDescribe("Dynamic Certificate", func() {
return err
})
err = f.WaitForNginxServer("_",
f.WaitForNginxServer("_",
func(server string) bool {
return strings.Contains(server, "set $proxy_upstream_name \"upstream-default-backend\"")
})
Expect(err).ToNot(HaveOccurred())
})
It("uses custom default backend", func() {

File diff suppressed because it is too large Load diff

View file

@ -17,13 +17,14 @@ limitations under the License.
package e2e
import (
"os"
"testing"
"github.com/golang/glog"
"github.com/onsi/ginkgo"
"github.com/onsi/ginkgo/config"
"github.com/onsi/gomega"
"k8s.io/apiserver/pkg/util/logs"
// required
_ "k8s.io/client-go/plugin/pkg/client/auth"
@ -36,6 +37,7 @@ import (
_ "k8s.io/ingress-nginx/test/e2e/servicebackend"
_ "k8s.io/ingress-nginx/test/e2e/settings"
_ "k8s.io/ingress-nginx/test/e2e/ssl"
_ "k8s.io/ingress-nginx/test/e2e/status"
)
// RunE2ETests checks configuration parameters (specified through flags) and then runs
@ -50,7 +52,12 @@ func RunE2ETests(t *testing.T) {
config.GinkgoConfig.SkipString = `\[Flaky\]|\[Feature:.+\]`
}
glog.Infof("Starting e2e run %q on Ginkgo node %d", framework.RunID, config.GinkgoConfig.ParallelNode)
if os.Getenv("KUBECTL_PATH") != "" {
framework.KubectlPath = os.Getenv("KUBECTL_PATH")
framework.Logf("Using kubectl path '%s'", framework.KubectlPath)
}
framework.Logf("Starting e2e run %q on Ginkgo node %d", framework.RunID, config.GinkgoConfig.ParallelNode)
ginkgo.RunSpecs(t, "nginx-ingress-controller e2e suite")
}

View file

@ -17,10 +17,9 @@ limitations under the License.
package framework
import (
"fmt"
"time"
"github.com/pkg/errors"
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
extensions "k8s.io/api/extensions/v1beta1"
@ -30,23 +29,23 @@ import (
)
// NewEchoDeployment creates a new single replica deployment of the echoserver image in a particular namespace
func (f *Framework) NewEchoDeployment() error {
return f.NewEchoDeploymentWithReplicas(1)
func (f *Framework) NewEchoDeployment() {
f.NewEchoDeploymentWithReplicas(1)
}
// NewEchoDeploymentWithReplicas creates a new deployment of the echoserver image in a particular namespace. Number of
// replicas is configurable
func (f *Framework) NewEchoDeploymentWithReplicas(replicas int32) error {
return f.NewDeployment("http-svc", "gcr.io/kubernetes-e2e-test-images/echoserver:2.1", 8080, replicas)
func (f *Framework) NewEchoDeploymentWithReplicas(replicas int32) {
f.NewDeployment("http-svc", "gcr.io/kubernetes-e2e-test-images/echoserver:2.1", 8080, replicas)
}
// NewHttpbinDeployment creates a new single replica deployment of the httpbin image in a particular namespace.
func (f *Framework) NewHttpbinDeployment() error {
return f.NewDeployment("httpbin", "kennethreitz/httpbin", 80, 1)
func (f *Framework) NewHttpbinDeployment() {
f.NewDeployment("httpbin", "kennethreitz/httpbin", 80, 1)
}
// NewDeployment creates a new deployment in a particular namespace.
func (f *Framework) NewDeployment(name, image string, port int32, replicas int32) error {
func (f *Framework) NewDeployment(name, image string, port int32, replicas int32) {
deployment := &extensions.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: name,
@ -86,20 +85,13 @@ func (f *Framework) NewDeployment(name, image string, port int32, replicas int32
}
d, err := f.EnsureDeployment(deployment)
if err != nil {
return err
}
if d == nil {
return fmt.Errorf("unexpected error creating deployement %s", name)
}
Expect(err).NotTo(HaveOccurred(), "failed to create a deployment")
Expect(d).NotTo(BeNil(), "expected a deployement but none returned")
err = WaitForPodsReady(f.KubeClientSet, 5*time.Minute, int(replicas), f.IngressController.Namespace, metav1.ListOptions{
LabelSelector: fields.SelectorFromSet(fields.Set(d.Spec.Template.ObjectMeta.Labels)).String(),
})
if err != nil {
return errors.Wrap(err, "failed to wait for to become ready")
}
Expect(err).NotTo(HaveOccurred(), "failed to wait for to become ready")
service := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
@ -121,14 +113,6 @@ func (f *Framework) NewDeployment(name, image string, port int32, replicas int32
},
}
s, err := f.EnsureService(service)
if err != nil {
return err
}
if s == nil {
return fmt.Errorf("unexpected error creating service %s", name)
}
return nil
s := f.EnsureService(service)
Expect(s).NotTo(BeNil(), "expected a service but none returned")
}

View file

@ -19,7 +19,11 @@ package framework
import (
"bytes"
"fmt"
"io"
"os/exec"
"regexp"
"strconv"
"strings"
"k8s.io/api/core/v1"
)
@ -31,14 +35,14 @@ func (f *Framework) ExecCommand(pod *v1.Pod, command string) (string, error) {
execErr bytes.Buffer
)
args := fmt.Sprintf("kubectl exec --namespace %v %v --container nginx-ingress-controller -- %v", pod.Namespace, pod.Name, command)
cmd := exec.Command("/bin/bash", "-c", args)
cmd := exec.Command("/bin/bash", "-c", fmt.Sprintf("%v exec --namespace %s %s --container nginx-ingress-controller -- %s", KubectlPath, pod.Namespace, pod.Name, command))
cmd.Stdout = &execOut
cmd.Stderr = &execErr
err := cmd.Run()
if err != nil {
return "", fmt.Errorf("could not execute: %v", err)
return "", fmt.Errorf("could not execute '%s %s': %v", cmd.Path, cmd.Args, err)
}
if execErr.Len() > 0 {
@ -59,3 +63,51 @@ func (f *Framework) NewIngressController(namespace string) error {
return nil
}
var (
proxyRegexp = regexp.MustCompile("Starting to serve on .*:([0-9]+)")
)
// KubectlProxy creates a proxy to kubernetes apiserver
func (f *Framework) KubectlProxy(port int) (int, *exec.Cmd, error) {
cmd := exec.Command("/bin/bash", "-c", fmt.Sprintf("%s proxy --accept-hosts=.* --address=0.0.0.0 --port=%d", KubectlPath, port))
stdout, stderr, err := startCmdAndStreamOutput(cmd)
if err != nil {
return -1, nil, err
}
defer stdout.Close()
defer stderr.Close()
buf := make([]byte, 128)
var n int
if n, err = stdout.Read(buf); err != nil {
return -1, cmd, fmt.Errorf("Failed to read from kubectl proxy stdout: %v", err)
}
output := string(buf[:n])
match := proxyRegexp.FindStringSubmatch(output)
if len(match) == 2 {
if port, err := strconv.Atoi(match[1]); err == nil {
return port, cmd, nil
}
}
return -1, cmd, fmt.Errorf("Failed to parse port from proxy stdout: %s", output)
}
func startCmdAndStreamOutput(cmd *exec.Cmd) (stdout, stderr io.ReadCloser, err error) {
stdout, err = cmd.StdoutPipe()
if err != nil {
return
}
stderr, err = cmd.StderrPipe()
if err != nil {
return
}
Logf("Asynchronously running '%s'", strings.Join(cmd.Args, " "))
err = cmd.Start()
return
}

View file

@ -46,6 +46,11 @@ const (
HTTPS RequestScheme = "https"
)
var (
// KubectlPath defines the full path of the kubectl binary
KubectlPath = "/usr/local/bin/kubectl"
)
// Framework supports common operations used by e2e tests; it will keep a client & a namespace for you.
type Framework struct {
BaseName string
@ -112,14 +117,10 @@ func (f *Framework) BeforeEach() {
})
Expect(err).NotTo(HaveOccurred())
HTTPURL, err := f.GetNginxURL(HTTP)
Expect(err).NotTo(HaveOccurred())
HTTPURL := f.GetNginxURL(HTTP)
f.IngressController.HTTPURL = HTTPURL
HTTPSURL, err := f.GetNginxURL(HTTPS)
Expect(err).NotTo(HaveOccurred())
HTTPSURL := f.GetNginxURL(HTTPS)
f.IngressController.HTTPSURL = HTTPSURL
// we wait for any change in the informers and SSL certificate generation
@ -149,8 +150,10 @@ func IngressNginxDescribe(text string, body func()) bool {
// GetNginxIP returns the IP address of the minikube cluster
// where the NGINX ingress controller is running
func (f *Framework) GetNginxIP() (string, error) {
return os.Getenv("NODE_IP"), nil
func (f *Framework) GetNginxIP() string {
nodeIP := os.Getenv("NODE_IP")
Expect(nodeIP).NotTo(BeEmpty(), "env variable NODE_IP is empty")
return nodeIP
}
// GetNginxPort returns the number of TCP port where NGINX is running
@ -173,33 +176,28 @@ func (f *Framework) GetNginxPort(name string) (int, error) {
}
// GetNginxURL returns the URL should be used to make a request to NGINX
func (f *Framework) GetNginxURL(scheme RequestScheme) (string, error) {
ip, err := f.GetNginxIP()
if err != nil {
return "", err
}
func (f *Framework) GetNginxURL(scheme RequestScheme) string {
ip := f.GetNginxIP()
port, err := f.GetNginxPort(fmt.Sprintf("%v", scheme))
if err != nil {
return "", err
}
Expect(err).NotTo(HaveOccurred(), "unexpected error obtaning NGINX Port")
return fmt.Sprintf("%v://%v:%v", scheme, ip, port), nil
return fmt.Sprintf("%v://%v:%v", scheme, ip, port)
}
// WaitForNginxServer waits until the nginx configuration contains a particular server section
func (f *Framework) WaitForNginxServer(name string, matcher func(cfg string) bool) error {
return wait.Poll(Poll, time.Minute*5, f.matchNginxConditions(name, matcher))
func (f *Framework) WaitForNginxServer(name string, matcher func(cfg string) bool) {
err := wait.Poll(Poll, time.Minute*5, f.matchNginxConditions(name, matcher))
Expect(err).NotTo(HaveOccurred(), "unexpected error waiting for nginx server condition/s")
}
// WaitForNginxConfiguration waits until the nginx configuration contains a particular configuration
func (f *Framework) WaitForNginxConfiguration(matcher func(cfg string) bool) error {
return wait.Poll(Poll, time.Minute*5, f.matchNginxConditions("", matcher))
func (f *Framework) WaitForNginxConfiguration(matcher func(cfg string) bool) {
err := wait.Poll(Poll, time.Minute*5, f.matchNginxConditions("", matcher))
Expect(err).NotTo(HaveOccurred(), "unexpected error waiting for nginx server condition/s")
}
// NginxLogs returns the logs of the nginx ingress controller pod running
func (f *Framework) NginxLogs() (string, error) {
l, err := f.KubeClientSet.CoreV1().Pods(f.IngressController.Namespace).List(metav1.ListOptions{
func nginxLogs(client kubernetes.Interface, namespace string) (string, error) {
l, err := client.CoreV1().Pods(namespace).List(metav1.ListOptions{
LabelSelector: "app.kubernetes.io/name=ingress-nginx",
})
if err != nil {
@ -209,7 +207,7 @@ func (f *Framework) NginxLogs() (string, error) {
for _, pod := range l.Items {
if strings.HasPrefix(pod.GetName(), "nginx-ingress-controller") {
if isRunning, err := podRunningReady(&pod); err == nil && isRunning {
return f.Logs(&pod)
return Logs(&pod)
}
}
}
@ -217,6 +215,11 @@ func (f *Framework) NginxLogs() (string, error) {
return "", fmt.Errorf("no nginx ingress controller pod is running (logs)")
}
// NginxLogs returns the logs of the nginx ingress controller pod running
func (f *Framework) NginxLogs() (string, error) {
return nginxLogs(f.KubeClientSet, f.IngressController.Namespace)
}
func (f *Framework) matchNginxConditions(name string, matcher func(cfg string) bool) wait.ConditionFunc {
return func() (bool, error) {
l, err := f.KubeClientSet.CoreV1().Pods(f.IngressController.Namespace).List(metav1.ListOptions{
@ -311,16 +314,12 @@ func (f *Framework) GetNginxConfigMapData() (map[string]string, error) {
}
// SetNginxConfigMapData sets ingress-nginx's nginx-configuration configMap data
func (f *Framework) SetNginxConfigMapData(cmData map[string]string) error {
func (f *Framework) SetNginxConfigMapData(cmData map[string]string) {
// Needs to do a Get and Set, Update will not take just the Data field
// or a configMap that is not the very last revision
config, err := f.getNginxConfigMap()
if err != nil {
return err
}
if config == nil {
return fmt.Errorf("Unable to get nginx-configuration configMap")
}
Expect(err).NotTo(HaveOccurred())
Expect(config).NotTo(BeNil(), "expected a configmap but none returned")
config.Data = cmData
@ -328,25 +327,19 @@ func (f *Framework) SetNginxConfigMapData(cmData map[string]string) error {
CoreV1().
ConfigMaps(f.IngressController.Namespace).
Update(config)
if err != nil {
return err
}
Expect(err).NotTo(HaveOccurred())
time.Sleep(5 * time.Second)
return err
}
// UpdateNginxConfigMapData updates single field in ingress-nginx's nginx-configuration map data
func (f *Framework) UpdateNginxConfigMapData(key string, value string) error {
func (f *Framework) UpdateNginxConfigMapData(key string, value string) {
config, err := f.GetNginxConfigMapData()
if err != nil {
return err
}
Expect(err).NotTo(HaveOccurred(), "unexpected error reading configmap")
config[key] = value
return f.SetNginxConfigMapData(config)
f.SetNginxConfigMapData(config)
}
// UpdateDeployment runs the given updateFunc on the deployment and waits for it to be updated
@ -380,7 +373,7 @@ func UpdateDeployment(kubeClientSet kubernetes.Interface, namespace string, name
LabelSelector: fields.SelectorFromSet(fields.Set(deployment.Spec.Template.ObjectMeta.Labels)).String(),
})
if err != nil {
return errors.Wrapf(err, "failed to wait for nginx-ingress-controller replica count to be %v", replicas)
return errors.Wrapf(err, "waiting for nginx-ingress-controller replica count to be %v", replicas)
}
return nil
@ -428,6 +421,7 @@ func newSingleIngress(name, path, host, ns, service string, port int, annotation
},
},
}
if withTLS {
ing.Spec.TLS = []extensions.IngressTLS{
{

View file

@ -17,10 +17,9 @@ limitations under the License.
package framework
import (
"fmt"
"time"
"github.com/pkg/errors"
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
extensions "k8s.io/api/extensions/v1beta1"
@ -31,13 +30,13 @@ import (
// NewGRPCFortuneTellerDeployment creates a new single replica
// deployment of the fortune teller image in a particular namespace
func (f *Framework) NewGRPCFortuneTellerDeployment() error {
return f.NewNewGRPCFortuneTellerDeploymentWithReplicas(1)
func (f *Framework) NewGRPCFortuneTellerDeployment() {
f.NewNewGRPCFortuneTellerDeploymentWithReplicas(1)
}
// NewNewGRPCFortuneTellerDeploymentWithReplicas creates a new deployment of the
// fortune teller image in a particular namespace. Number of replicas is configurable
func (f *Framework) NewNewGRPCFortuneTellerDeploymentWithReplicas(replicas int32) error {
func (f *Framework) NewNewGRPCFortuneTellerDeploymentWithReplicas(replicas int32) {
deployment := &extensions.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "fortune-teller",
@ -77,20 +76,13 @@ func (f *Framework) NewNewGRPCFortuneTellerDeploymentWithReplicas(replicas int32
}
d, err := f.EnsureDeployment(deployment)
if err != nil {
return err
}
if d == nil {
return fmt.Errorf("unexpected error creating deployement for fortune-teller")
}
Expect(err).NotTo(HaveOccurred())
Expect(d).NotTo(BeNil(), "expected a fortune-teller deployment")
err = WaitForPodsReady(f.KubeClientSet, 5*time.Minute, int(replicas), f.IngressController.Namespace, metav1.ListOptions{
LabelSelector: fields.SelectorFromSet(fields.Set(d.Spec.Template.ObjectMeta.Labels)).String(),
})
if err != nil {
return errors.Wrap(err, "failed to wait for to become ready")
}
Expect(err).NotTo(HaveOccurred(), "failed to wait for to become ready")
service := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
@ -112,14 +104,5 @@ func (f *Framework) NewNewGRPCFortuneTellerDeploymentWithReplicas(replicas int32
},
}
s, err := f.EnsureService(service)
if err != nil {
return err
}
if s == nil {
return fmt.Errorf("unexpected error creating service for fortune-teller deployment")
}
return nil
f.EnsureService(service)
}

View file

@ -17,10 +17,9 @@ limitations under the License.
package framework
import (
"fmt"
"time"
"github.com/pkg/errors"
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
extensions "k8s.io/api/extensions/v1beta1"
@ -60,7 +59,7 @@ bind-address = "0.0.0.0:8088"
// NewInfluxDBDeployment creates an InfluxDB server configured to reply
// on 8086/tcp and 8089/udp
func (f *Framework) NewInfluxDBDeployment() error {
func (f *Framework) NewInfluxDBDeployment() {
configuration := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "influxdb-config",
@ -72,13 +71,9 @@ func (f *Framework) NewInfluxDBDeployment() error {
}
cm, err := f.EnsureConfigMap(configuration)
if err != nil {
return err
}
Expect(err).NotTo(HaveOccurred(), "failed to create an Influxdb deployment")
if cm == nil {
return fmt.Errorf("unexpected error creating configmap for influxdb")
}
Expect(cm).NotTo(BeNil(), "expected a configmap but none returned")
deployment := &extensions.Deployment{
ObjectMeta: metav1.ObjectMeta{
@ -143,20 +138,12 @@ func (f *Framework) NewInfluxDBDeployment() error {
}
d, err := f.EnsureDeployment(deployment)
if err != nil {
return err
}
Expect(err).NotTo(HaveOccurred(), "failed to create an Influxdb deployment")
if d == nil {
return fmt.Errorf("unexpected error creating deployement for influxdb")
}
Expect(d).NotTo(BeNil(), "unexpected error creating deployement for influxdb")
err = WaitForPodsReady(f.KubeClientSet, 5*time.Minute, 1, f.IngressController.Namespace, metav1.ListOptions{
LabelSelector: fields.SelectorFromSet(fields.Set(d.Spec.Template.ObjectMeta.Labels)).String(),
})
if err != nil {
return errors.Wrap(err, "failed to wait for influxdb to become ready")
}
return nil
Expect(err).NotTo(HaveOccurred(), "failed to wait for influxdb to become ready")
}

View file

@ -20,6 +20,8 @@ import (
"fmt"
"time"
. "github.com/onsi/gomega"
api "k8s.io/api/core/v1"
core "k8s.io/api/core/v1"
extensions "k8s.io/api/extensions/v1beta1"
@ -31,15 +33,23 @@ import (
)
// EnsureSecret creates a Secret object or returns it if it already exists.
func (f *Framework) EnsureSecret(secret *api.Secret) (*api.Secret, error) {
func (f *Framework) EnsureSecret(secret *api.Secret) *api.Secret {
s, err := f.KubeClientSet.CoreV1().Secrets(secret.Namespace).Create(secret)
if err != nil {
if k8sErrors.IsAlreadyExists(err) {
return f.KubeClientSet.CoreV1().Secrets(secret.Namespace).Update(secret)
s, err := f.KubeClientSet.CoreV1().Secrets(secret.Namespace).Update(secret)
Expect(err).NotTo(HaveOccurred(), "unexpected error updating secret")
return s
}
return nil, err
Expect(err).NotTo(HaveOccurred(), "unexpected error creating secret")
}
return s, nil
Expect(s).NotTo(BeNil())
Expect(s.ObjectMeta).NotTo(BeNil())
return s
}
// EnsureConfigMap creates a ConfigMap object or returns it if it already exists.
@ -51,40 +61,49 @@ func (f *Framework) EnsureConfigMap(configMap *api.ConfigMap) (*api.ConfigMap, e
}
return nil, err
}
return cm, nil
}
// EnsureIngress creates an Ingress object or returns it if it already exists.
func (f *Framework) EnsureIngress(ingress *extensions.Ingress) (*extensions.Ingress, error) {
s, err := f.KubeClientSet.ExtensionsV1beta1().Ingresses(ingress.Namespace).Update(ingress)
func (f *Framework) EnsureIngress(ingress *extensions.Ingress) *extensions.Ingress {
ing, err := f.KubeClientSet.ExtensionsV1beta1().Ingresses(ingress.Namespace).Update(ingress)
if err != nil {
if k8sErrors.IsNotFound(err) {
s, err = f.KubeClientSet.ExtensionsV1beta1().Ingresses(ingress.Namespace).Create(ingress)
if err != nil {
return nil, err
}
} else {
return nil, err
}
ing, err = f.KubeClientSet.ExtensionsV1beta1().Ingresses(ingress.Namespace).Create(ingress)
Expect(err).NotTo(HaveOccurred(), "unexpected error creating ingress")
return ing
}
if s.Annotations == nil {
s.Annotations = make(map[string]string)
Expect(err).NotTo(HaveOccurred())
}
return s, nil
Expect(ing).NotTo(BeNil())
if ing.Annotations == nil {
ing.Annotations = make(map[string]string)
}
return ing
}
// EnsureService creates a Service object or returns it if it already exists.
func (f *Framework) EnsureService(service *core.Service) (*core.Service, error) {
func (f *Framework) EnsureService(service *core.Service) *core.Service {
s, err := f.KubeClientSet.CoreV1().Services(service.Namespace).Update(service)
if err != nil {
if k8sErrors.IsNotFound(err) {
return f.KubeClientSet.CoreV1().Services(service.Namespace).Create(service)
s, err := f.KubeClientSet.CoreV1().Services(service.Namespace).Create(service)
Expect(err).NotTo(HaveOccurred(), "unexpected error creating service")
return s
}
return nil, err
Expect(err).NotTo(HaveOccurred())
}
return s, nil
Expect(s).NotTo(BeNil(), "expected a service but none returned")
return s
}
// EnsureDeployment creates a Deployment object or returns it if it already exists.

View file

@ -25,7 +25,7 @@ import (
)
// Logs returns the log entries of a given Pod.
func (f *Framework) Logs(pod *v1.Pod) (string, error) {
func Logs(pod *v1.Pod) (string, error) {
var (
execOut bytes.Buffer
execErr bytes.Buffer
@ -35,14 +35,13 @@ func (f *Framework) Logs(pod *v1.Pod) (string, error) {
return "", fmt.Errorf("could not determine which container to use")
}
args := fmt.Sprintf("kubectl logs -n %v %v", pod.Namespace, pod.Name)
cmd := exec.Command("/bin/bash", "-c", args)
cmd := exec.Command("/bin/bash", "-c", fmt.Sprintf("%v logs --namespace %s %s", KubectlPath, pod.Namespace, pod.Name))
cmd.Stdout = &execOut
cmd.Stderr = &execErr
err := cmd.Run()
if err != nil {
return "", fmt.Errorf("could not execute: %v", err)
return "", fmt.Errorf("could not execute '%s %s': %v", cmd.Path, cmd.Args, err)
}
if execErr.Len() > 0 {

View file

@ -32,6 +32,8 @@ import (
"strings"
"time"
. "github.com/onsi/gomega"
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
@ -140,8 +142,9 @@ func CreateIngressMASecret(client kubernetes.Interface, host string, secretName,
}
// WaitForTLS waits until the TLS handshake with a given server completes successfully.
func WaitForTLS(url string, tlsConfig *tls.Config) error {
return wait.Poll(Poll, 30*time.Second, matchTLSServerName(url, tlsConfig))
func WaitForTLS(url string, tlsConfig *tls.Config) {
err := wait.Poll(Poll, 30*time.Second, matchTLSServerName(url, tlsConfig))
Expect(err).NotTo(HaveOccurred(), "timeout waiting for TLS configuration in URL %s", url)
}
// generateRSACert generates a basic self signed certificate using a key length

View file

@ -27,7 +27,6 @@ import (
appsv1beta1 "k8s.io/api/apps/v1beta1"
extensions "k8s.io/api/extensions/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/ingress-nginx/test/e2e/framework"
)
@ -37,17 +36,24 @@ var _ = framework.IngressNginxDescribe("Dynamic Certificate", func() {
host := "foo.com"
BeforeEach(func() {
err := enableDynamicCertificates(f.IngressController.Namespace, f.KubeClientSet)
Expect(err).NotTo(HaveOccurred())
err := framework.UpdateDeployment(f.KubeClientSet, f.IngressController.Namespace, "nginx-ingress-controller", 1,
func(deployment *appsv1beta1.Deployment) error {
args := deployment.Spec.Template.Spec.Containers[0].Args
args = append(args, "--enable-dynamic-certificates")
args = append(args, "--enable-ssl-chain-completion=false")
deployment.Spec.Template.Spec.Containers[0].Args = args
_, err := f.KubeClientSet.AppsV1beta1().Deployments(f.IngressController.Namespace).Update(deployment)
err = f.WaitForNginxConfiguration(
func(cfg string) bool {
return strings.Contains(cfg, "ok, res = pcall(require, \"certificate\")")
return err
})
Expect(err).NotTo(HaveOccurred())
err = f.NewEchoDeploymentWithReplicas(1)
Expect(err).NotTo(HaveOccurred())
f.WaitForNginxConfiguration(
func(cfg string) bool {
return strings.Contains(cfg, "ok, res = pcall(require, \"certificate\")")
})
f.NewEchoDeploymentWithReplicas(1)
})
It("picks up the certificate when we add TLS spec to existing ingress", func() {
@ -74,27 +80,27 @@ var _ = framework.IngressNginxDescribe("Dynamic Certificate", func() {
})
It("picks up the previously missing secret for a given ingress without reloading", func() {
ing, err := f.EnsureIngress(framework.NewSingleIngressWithTLS(host, "/", host, f.IngressController.Namespace, "http-svc", 80, nil))
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
ing := framework.NewSingleIngressWithTLS(host, "/", host, f.IngressController.Namespace, "http-svc", 80, nil)
f.EnsureIngress(ing)
time.Sleep(waitForLuaSync)
ensureHTTPSRequest(fmt.Sprintf("%s?id=dummy_log_splitter_foo_bar", f.IngressController.HTTPSURL), host, "ingress.local")
_, err = framework.CreateIngressTLSSecret(f.KubeClientSet,
_, err := framework.CreateIngressTLSSecret(f.KubeClientSet,
ing.Spec.TLS[0].Hosts,
ing.Spec.TLS[0].SecretName,
ing.Namespace)
Expect(err).ToNot(HaveOccurred())
By("configuring certificate_by_lua and skipping Nginx configuration of the new certificate")
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "ssl_certificate_by_lua_block") &&
!strings.Contains(server, fmt.Sprintf("ssl_certificate /etc/ingress-controller/ssl/%s-%s.pem;", ing.Namespace, host)) &&
!strings.Contains(server, fmt.Sprintf("ssl_certificate_key /etc/ingress-controller/ssl/%s-%s.pem;", ing.Namespace, host)) &&
strings.Contains(server, "listen 443")
})
Expect(err).ToNot(HaveOccurred())
time.Sleep(waitForLuaSync)
@ -114,14 +120,13 @@ var _ = framework.IngressNginxDescribe("Dynamic Certificate", func() {
Context("given an ingress with TLS correctly configured", func() {
BeforeEach(func() {
ing, err := f.EnsureIngress(framework.NewSingleIngressWithTLS(host, "/", host, f.IngressController.Namespace, "http-svc", 80, nil))
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
ing := f.EnsureIngress(framework.NewSingleIngressWithTLS(host, "/", host, f.IngressController.Namespace, "http-svc", 80, nil))
time.Sleep(waitForLuaSync)
ensureHTTPSRequest(f.IngressController.HTTPSURL, host, "ingress.local")
_, err = framework.CreateIngressTLSSecret(f.KubeClientSet,
_, err := framework.CreateIngressTLSSecret(f.KubeClientSet,
ing.Spec.TLS[0].Hosts,
ing.Spec.TLS[0].SecretName,
ing.Namespace)
@ -129,14 +134,13 @@ var _ = framework.IngressNginxDescribe("Dynamic Certificate", func() {
time.Sleep(waitForLuaSync)
By("configuring certificate_by_lua and skipping Nginx configuration of the new certificate")
err = f.WaitForNginxServer(ing.Spec.TLS[0].Hosts[0],
f.WaitForNginxServer(ing.Spec.TLS[0].Hosts[0],
func(server string) bool {
return strings.Contains(server, "ssl_certificate_by_lua_block") &&
!strings.Contains(server, fmt.Sprintf("ssl_certificate /etc/ingress-controller/ssl/%s-%s.pem;", ing.Namespace, host)) &&
!strings.Contains(server, fmt.Sprintf("ssl_certificate_key /etc/ingress-controller/ssl/%s-%s.pem;", ing.Namespace, host)) &&
strings.Contains(server, "listen 443")
})
Expect(err).ToNot(HaveOccurred())
time.Sleep(waitForLuaSync)
@ -146,6 +150,7 @@ var _ = framework.IngressNginxDescribe("Dynamic Certificate", func() {
It("picks up the updated certificate without reloading", func() {
ing, err := f.KubeClientSet.ExtensionsV1beta1().Ingresses(f.IngressController.Namespace).Get(host, metav1.GetOptions{})
Expect(err).ToNot(HaveOccurred())
ensureHTTPSRequest(fmt.Sprintf("%s?id=dummy_log_splitter_foo_bar", f.IngressController.HTTPSURL), host, host)
@ -157,14 +162,13 @@ var _ = framework.IngressNginxDescribe("Dynamic Certificate", func() {
time.Sleep(waitForLuaSync)
By("configuring certificate_by_lua and skipping Nginx configuration of the new certificate")
err = f.WaitForNginxServer(ing.Spec.TLS[0].Hosts[0],
f.WaitForNginxServer(ing.Spec.TLS[0].Hosts[0],
func(server string) bool {
return strings.Contains(server, "ssl_certificate_by_lua_block") &&
!strings.Contains(server, fmt.Sprintf("ssl_certificate /etc/ingress-controller/ssl/%s-%s.pem;", ing.Namespace, host)) &&
!strings.Contains(server, fmt.Sprintf("ssl_certificate_key /etc/ingress-controller/ssl/%s-%s.pem;", ing.Namespace, host)) &&
strings.Contains(server, "listen 443")
})
Expect(err).ToNot(HaveOccurred())
time.Sleep(waitForLuaSync)
@ -192,14 +196,13 @@ var _ = framework.IngressNginxDescribe("Dynamic Certificate", func() {
time.Sleep(waitForLuaSync)
By("configuring certificate_by_lua and skipping Nginx configuration of the new certificate")
err = f.WaitForNginxServer(ing.Spec.TLS[0].Hosts[0],
f.WaitForNginxServer(ing.Spec.TLS[0].Hosts[0],
func(server string) bool {
return strings.Contains(server, "ssl_certificate_by_lua_block") &&
strings.Contains(server, "ssl_certificate /etc/ingress-controller/ssl/default-fake-certificate.pem;") &&
strings.Contains(server, "ssl_certificate_key /etc/ingress-controller/ssl/default-fake-certificate.pem;") &&
strings.Contains(server, "listen 443")
})
Expect(err).ToNot(HaveOccurred())
time.Sleep(waitForLuaSync)
@ -242,16 +245,3 @@ var _ = framework.IngressNginxDescribe("Dynamic Certificate", func() {
})
})
})
func enableDynamicCertificates(namespace string, kubeClientSet kubernetes.Interface) error {
return framework.UpdateDeployment(kubeClientSet, namespace, "nginx-ingress-controller", 1,
func(deployment *appsv1beta1.Deployment) error {
args := deployment.Spec.Template.Spec.Containers[0].Args
args = append(args, "--enable-dynamic-certificates")
args = append(args, "--enable-ssl-chain-completion=false")
deployment.Spec.Template.Spec.Containers[0].Args = args
_, err := kubeClientSet.AppsV1beta1().Deployments(namespace).Update(deployment)
return err
})
}

View file

@ -47,60 +47,54 @@ var _ = framework.IngressNginxDescribe("Dynamic Configuration", func() {
f := framework.NewDefaultFramework("dynamic-configuration")
BeforeEach(func() {
err := f.NewEchoDeploymentWithReplicas(1)
Expect(err).NotTo(HaveOccurred())
f.NewEchoDeploymentWithReplicas(1)
ensureIngress(f, "foo.com")
})
It("configures balancer Lua middleware correctly", func() {
err := f.WaitForNginxConfiguration(func(cfg string) bool {
f.WaitForNginxConfiguration(func(cfg string) bool {
return strings.Contains(cfg, "balancer.init_worker()") && strings.Contains(cfg, "balancer.balance()")
})
Expect(err).NotTo(HaveOccurred())
host := "foo.com"
err = f.WaitForNginxServer(host, func(server string) bool {
f.WaitForNginxServer(host, func(server string) bool {
return strings.Contains(server, "balancer.rewrite()") && strings.Contains(server, "balancer.log()")
})
Expect(err).NotTo(HaveOccurred())
})
It("sets nameservers for Lua", func() {
err := f.WaitForNginxConfiguration(func(cfg string) bool {
f.WaitForNginxConfiguration(func(cfg string) bool {
r := regexp.MustCompile(`configuration.nameservers = { [".,0-9a-zA-Z]+ }`)
return r.MatchString(cfg)
})
Expect(err).NotTo(HaveOccurred())
})
Context("when only backends change", func() {
It("handles endpoints only changes", func() {
var nginxConfig string
err := f.WaitForNginxConfiguration(func(cfg string) bool {
f.WaitForNginxConfiguration(func(cfg string) bool {
nginxConfig = cfg
return true
})
replicas := 2
err = framework.UpdateDeployment(f.KubeClientSet, f.IngressController.Namespace, "http-svc", replicas, nil)
err := framework.UpdateDeployment(f.KubeClientSet, f.IngressController.Namespace, "http-svc", replicas, nil)
Expect(err).NotTo(HaveOccurred())
time.Sleep(waitForLuaSync)
ensureRequest(f, "foo.com")
var newNginxConfig string
err = f.WaitForNginxConfiguration(func(cfg string) bool {
f.WaitForNginxConfiguration(func(cfg string) bool {
newNginxConfig = cfg
return true
})
Expect(nginxConfig).Should(Equal(newNginxConfig))
})
It("handles an annotation change", func() {
var nginxConfig string
err := f.WaitForNginxConfiguration(func(cfg string) bool {
f.WaitForNginxConfiguration(func(cfg string) bool {
nginxConfig = cfg
return true
})
@ -116,7 +110,7 @@ var _ = framework.IngressNginxDescribe("Dynamic Configuration", func() {
ensureRequest(f, "foo.com")
var newNginxConfig string
err = f.WaitForNginxConfiguration(func(cfg string) bool {
f.WaitForNginxConfiguration(func(cfg string) bool {
newNginxConfig = cfg
return true
})
@ -127,7 +121,7 @@ var _ = framework.IngressNginxDescribe("Dynamic Configuration", func() {
It("handles a non backend update", func() {
var nginxConfig string
err := f.WaitForNginxConfiguration(func(cfg string) bool {
f.WaitForNginxConfiguration(func(cfg string) bool {
nginxConfig = cfg
return true
})
@ -149,11 +143,10 @@ var _ = framework.IngressNginxDescribe("Dynamic Configuration", func() {
Expect(err).ToNot(HaveOccurred())
var newNginxConfig string
err = f.WaitForNginxConfiguration(func(cfg string) bool {
f.WaitForNginxConfiguration(func(cfg string) bool {
newNginxConfig = cfg
return true
})
Expect(nginxConfig).ShouldNot(Equal(newNginxConfig))
})
@ -181,7 +174,7 @@ func ensureIngress(f *framework.Framework, host string) *extensions.Ingress {
"nginx.ingress.kubernetes.io/session-cookie-max-age": "172800"}))
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) &&
strings.Contains(server, "proxy_pass http://upstream_balancer;")

View file

@ -45,15 +45,12 @@ var _ = framework.IngressNginxDescribe("Service backend - 503", func() {
host := "nonexistent.svc.com"
bi := buildIngressWithNonexistentService(host, f.IngressController.Namespace, "/")
ing, err := f.EnsureIngress(bi)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
f.EnsureIngress(bi)
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "return 503;")
return strings.Contains(server, "proxy_pass http://upstream_balancer;")
})
Expect(err).NotTo(HaveOccurred())
resp, _, errs := gorequest.New().
Get(f.IngressController.HTTPURL).
@ -68,19 +65,15 @@ var _ = framework.IngressNginxDescribe("Service backend - 503", func() {
bi, bs := buildIngressWithUnavailableServiceEndpoints(host, f.IngressController.Namespace, "/")
svc, err := f.EnsureService(bs)
Expect(err).NotTo(HaveOccurred())
svc := f.EnsureService(bs)
Expect(svc).NotTo(BeNil())
ing, err := f.EnsureIngress(bi)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
f.EnsureIngress(bi)
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "return 503;")
return strings.Contains(server, "proxy_pass http://upstream_balancer;")
})
Expect(err).NotTo(HaveOccurred())
resp, _, errs := gorequest.New().
Get(f.IngressController.HTTPURL).

View file

@ -30,8 +30,7 @@ var _ = framework.IngressNginxDescribe("Configmap change", func() {
f := framework.NewDefaultFramework("configmap-change")
BeforeEach(func() {
err := f.NewEchoDeployment()
Expect(err).NotTo(HaveOccurred())
f.NewEchoDeployment()
})
AfterEach(func() {
@ -40,22 +39,20 @@ var _ = framework.IngressNginxDescribe("Configmap change", func() {
It("should reload after an update in the configuration", func() {
host := "configmap-change"
ing, err := f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, nil))
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, nil)
f.EnsureIngress(ing)
wlKey := "whitelist-source-range"
wlValue := "1.1.1.1"
By("adding a whitelist-source-range")
err = f.UpdateNginxConfigMapData(wlKey, wlValue)
Expect(err).NotTo(HaveOccurred())
f.UpdateNginxConfigMapData(wlKey, wlValue)
checksumRegex := regexp.MustCompile("Configuration checksum:\\s+(\\d+)")
checksum := ""
err = f.WaitForNginxConfiguration(
f.WaitForNginxConfiguration(
func(cfg string) bool {
// before returning, extract the current checksum
match := checksumRegex.FindStringSubmatch(cfg)
@ -66,16 +63,14 @@ var _ = framework.IngressNginxDescribe("Configmap change", func() {
return strings.Contains(cfg, "geo $the_real_ip $deny_") &&
strings.Contains(cfg, "1.1.1.1 0")
})
Expect(err).NotTo(HaveOccurred())
Expect(checksum).NotTo(BeEmpty())
By("changing error-log-level")
err = f.UpdateNginxConfigMapData("error-log-level", "debug")
Expect(err).NotTo(HaveOccurred())
f.UpdateNginxConfigMapData("error-log-level", "debug")
newChecksum := ""
err = f.WaitForNginxConfiguration(
f.WaitForNginxConfiguration(
func(cfg string) bool {
match := checksumRegex.FindStringSubmatch(cfg)
if len(match) > 0 {
@ -84,8 +79,6 @@ var _ = framework.IngressNginxDescribe("Configmap change", func() {
return strings.ContainsAny(cfg, "error_log /var/log/nginx/error.log debug;")
})
Expect(err).NotTo(HaveOccurred())
Expect(checksum).NotTo(BeEquivalentTo(newChecksum))
})
})

View file

@ -34,11 +34,8 @@ var _ = framework.IngressNginxDescribe("X-Forwarded headers", func() {
setting := "use-forwarded-headers"
BeforeEach(func() {
err := f.NewEchoDeployment()
Expect(err).NotTo(HaveOccurred())
err = f.UpdateNginxConfigMapData(setting, "false")
Expect(err).NotTo(HaveOccurred())
f.NewEchoDeployment()
f.UpdateNginxConfigMapData(setting, "false")
})
AfterEach(func() {
@ -47,18 +44,15 @@ var _ = framework.IngressNginxDescribe("X-Forwarded headers", func() {
It("should trust X-Forwarded headers when setting is true", func() {
host := "forwarded-headers"
err := f.UpdateNginxConfigMapData(setting, "true")
Expect(err).NotTo(HaveOccurred())
f.UpdateNginxConfigMapData(setting, "true")
ing, err := f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, nil))
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, nil)
f.EnsureIngress(ing)
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "server_name forwarded-headers")
})
Expect(err).NotTo(HaveOccurred())
resp, body, errs := gorequest.New().
Get(f.IngressController.HTTPURL).
@ -80,18 +74,14 @@ var _ = framework.IngressNginxDescribe("X-Forwarded headers", func() {
It("should not trust X-Forwarded headers when setting is false", func() {
host := "forwarded-headers"
err := f.UpdateNginxConfigMapData(setting, "false")
Expect(err).NotTo(HaveOccurred())
f.UpdateNginxConfigMapData(setting, "false")
ing, err := f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, nil))
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, nil))
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "server_name forwarded-headers")
})
Expect(err).NotTo(HaveOccurred())
resp, body, errs := gorequest.New().
Get(f.IngressController.HTTPURL).

View file

@ -0,0 +1,90 @@
/*
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 settings
import (
"strings"
"net/http"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/parnurzeal/gorequest"
"k8s.io/ingress-nginx/test/e2e/framework"
)
var _ = framework.IngressNginxDescribe("Geoip2", func() {
f := framework.NewDefaultFramework("geoip2")
host := "geoip2"
BeforeEach(func() {
f.NewEchoDeployment()
})
It("should only allow requests from specific countries", func() {
f.UpdateNginxConfigMapData("use-geoip2", "true")
httpSnippetAllowingOnlyAustralia :=
`map $geoip2_city_country_code $blocked_country {
default 1;
AU 0;
}`
f.UpdateNginxConfigMapData("http-snippet", httpSnippetAllowingOnlyAustralia)
f.WaitForNginxConfiguration(
func(cfg string) bool {
return strings.Contains(cfg, "map $geoip2_city_country_code $blocked_country")
})
configSnippet :=
`if ($blocked_country) {
return 403;
}`
annotations := map[string]string{
"nginx.ingress.kubernetes.io/configuration-snippet": configSnippet,
}
f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &annotations))
f.WaitForNginxConfiguration(
func(cfg string) bool {
return strings.Contains(cfg, "if ($blocked_country)")
})
// Should be blocked
usIP := "8.8.8.8"
resp, _, errs := gorequest.New().
Get(f.IngressController.HTTPURL).
Set("Host", host).
Set("X-Forwarded-For", usIP).
End()
Expect(errs).To(BeNil())
Expect(resp.StatusCode).Should(Equal(http.StatusForbidden))
// Shouldn't be blocked
australianIP := "1.1.1.1"
resp, _, errs = gorequest.New().
Get(f.IngressController.HTTPURL).
Set("Host", host).
Set("X-Forwarded-For", australianIP).
End()
Expect(errs).To(BeNil())
Expect(resp.StatusCode).Should(Equal(http.StatusOK))
})
})

View file

@ -33,28 +33,22 @@ var _ = framework.IngressNginxDescribe("Global access block", func() {
host := "global-access-block"
BeforeEach(func() {
err := f.NewEchoDeploymentWithReplicas(1)
Expect(err).NotTo(HaveOccurred())
ing, err := f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, nil))
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
f.NewEchoDeploymentWithReplicas(1)
f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, nil))
})
AfterEach(func() {
})
It("should block CIDRs defined in the ConfigMap", func() {
err := f.UpdateNginxConfigMapData("block-cidrs", "172.16.0.0/12,192.168.0.0/16,10.0.0.0/8")
Expect(err).NotTo(HaveOccurred())
f.UpdateNginxConfigMapData("block-cidrs", "172.16.0.0/12,192.168.0.0/16,10.0.0.0/8")
err = f.WaitForNginxConfiguration(
f.WaitForNginxConfiguration(
func(cfg string) bool {
return strings.Contains(cfg, "deny 172.16.0.0/12;") &&
strings.Contains(cfg, "deny 192.168.0.0/16;") &&
strings.Contains(cfg, "deny 10.0.0.0/8;")
})
Expect(err).NotTo(HaveOccurred())
// This test works for minikube, but may have problems with real kubernetes clusters,
// especially if connection is done via Internet. In this case, the test should be disabled/removed.
@ -67,15 +61,13 @@ var _ = framework.IngressNginxDescribe("Global access block", func() {
})
It("should block User-Agents defined in the ConfigMap", func() {
err := f.UpdateNginxConfigMapData("block-user-agents", "~*chrome\\/68\\.0\\.3440\\.106\\ safari\\/537\\.36,AlphaBot")
Expect(err).NotTo(HaveOccurred())
f.UpdateNginxConfigMapData("block-user-agents", "~*chrome\\/68\\.0\\.3440\\.106\\ safari\\/537\\.36,AlphaBot")
err = f.WaitForNginxConfiguration(
f.WaitForNginxConfiguration(
func(cfg string) bool {
return strings.Contains(cfg, "~*chrome\\/68\\.0\\.3440\\.106\\ safari\\/537\\.36 1;") &&
strings.Contains(cfg, "AlphaBot 1;")
})
Expect(err).NotTo(HaveOccurred())
// Should be blocked
resp, _, errs := gorequest.New().
@ -105,15 +97,13 @@ var _ = framework.IngressNginxDescribe("Global access block", func() {
})
It("should block Referers defined in the ConfigMap", func() {
err := f.UpdateNginxConfigMapData("block-referers", "~*example\\.com,qwerty")
Expect(err).NotTo(HaveOccurred())
f.UpdateNginxConfigMapData("block-referers", "~*example\\.com,qwerty")
err = f.WaitForNginxConfiguration(
f.WaitForNginxConfiguration(
func(cfg string) bool {
return strings.Contains(cfg, "~*example\\.com 1;") &&
strings.Contains(cfg, "qwerty 1;")
})
Expect(err).NotTo(HaveOccurred())
// Should be blocked
resp, _, errs := gorequest.New().

View file

@ -20,7 +20,6 @@ import (
"strings"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"k8s.io/ingress-nginx/test/e2e/framework"
)
@ -31,13 +30,11 @@ var _ = framework.IngressNginxDescribe("Main Snippet", func() {
It("should add value of main-snippet setting to nginx config", func() {
expectedComment := "# main snippet"
err := f.UpdateNginxConfigMapData(mainSnippet, expectedComment)
Expect(err).NotTo(HaveOccurred())
f.UpdateNginxConfigMapData(mainSnippet, expectedComment)
err = f.WaitForNginxConfiguration(
f.WaitForNginxConfiguration(
func(cfg string) bool {
return strings.Contains(cfg, expectedComment)
})
Expect(err).NotTo(HaveOccurred())
})
})

View file

@ -20,7 +20,6 @@ import (
"strings"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"k8s.io/ingress-nginx/test/e2e/framework"
)
@ -31,34 +30,29 @@ var _ = framework.IngressNginxDescribe("Multi Accept", func() {
It("should be enabled by default", func() {
expectedDirective := "multi_accept on;"
err := f.WaitForNginxConfiguration(
f.WaitForNginxConfiguration(
func(cfg string) bool {
return strings.Contains(cfg, expectedDirective)
})
Expect(err).NotTo(HaveOccurred())
})
It("should be enabled when set to true", func() {
expectedDirective := "multi_accept on;"
err := f.UpdateNginxConfigMapData(multiAccept, "true")
Expect(err).NotTo(HaveOccurred())
f.UpdateNginxConfigMapData(multiAccept, "true")
err = f.WaitForNginxConfiguration(
f.WaitForNginxConfiguration(
func(cfg string) bool {
return strings.Contains(cfg, expectedDirective)
})
Expect(err).NotTo(HaveOccurred())
})
It("should be disabled when set to false", func() {
expectedDirective := "multi_accept off;"
err := f.UpdateNginxConfigMapData(multiAccept, "false")
Expect(err).NotTo(HaveOccurred())
f.UpdateNginxConfigMapData(multiAccept, "false")
err = f.WaitForNginxConfiguration(
f.WaitForNginxConfiguration(
func(cfg string) bool {
return strings.Contains(cfg, expectedDirective)
})
Expect(err).NotTo(HaveOccurred())
})
})

View file

@ -43,32 +43,24 @@ var _ = framework.IngressNginxDescribe("No Auth locations", func() {
noAuthPath := "/noauth"
BeforeEach(func() {
err := f.NewEchoDeployment()
Expect(err).NotTo(HaveOccurred())
f.NewEchoDeployment()
s, err := f.EnsureSecret(buildSecret(username, password, secretName, f.IngressController.Namespace))
Expect(err).NotTo(HaveOccurred())
Expect(s).NotTo(BeNil())
Expect(s.ObjectMeta).NotTo(BeNil())
s := f.EnsureSecret(buildSecret(username, password, secretName, f.IngressController.Namespace))
err = f.UpdateNginxConfigMapData(setting, noAuthPath)
Expect(err).NotTo(HaveOccurred())
f.UpdateNginxConfigMapData(setting, noAuthPath)
bi := buildBasicAuthIngressWithSecondPath(host, f.IngressController.Namespace, s.Name, noAuthPath)
ing, err := f.EnsureIngress(bi)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
f.EnsureIngress(bi)
})
AfterEach(func() {
})
It("should return status code 401 when accessing '/' unauthentication", func() {
err := f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("test auth"))
})
Expect(err).NotTo(HaveOccurred())
resp, body, errs := gorequest.New().
Get(f.IngressController.HTTPURL).
@ -81,11 +73,10 @@ var _ = framework.IngressNginxDescribe("No Auth locations", func() {
})
It("should return status code 200 when accessing '/' authentication", func() {
err := f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("test auth"))
})
Expect(err).NotTo(HaveOccurred())
resp, _, errs := gorequest.New().
Get(f.IngressController.HTTPURL).
@ -98,11 +89,10 @@ var _ = framework.IngressNginxDescribe("No Auth locations", func() {
})
It("should return status code 200 when accessing '/noauth' unauthenticated", func() {
err := f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("test auth"))
})
Expect(err).NotTo(HaveOccurred())
resp, _, errs := gorequest.New().
Get(fmt.Sprintf("%s/noauth", f.IngressController.HTTPURL)).
@ -156,8 +146,9 @@ func buildBasicAuthIngressWithSecondPath(host, namespace, secretName, pathName s
func buildSecret(username, password, name, namespace string) *corev1.Secret {
out, err := exec.Command("openssl", "passwd", "-crypt", password).CombinedOutput()
Expect(err).NotTo(HaveOccurred(), "creating password")
encpass := fmt.Sprintf("%v:%s\n", username, out)
Expect(err).NotTo(HaveOccurred())
return &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{

View file

@ -35,11 +35,8 @@ var _ = framework.IngressNginxDescribe("Proxy Protocol", func() {
setting := "use-proxy-protocol"
BeforeEach(func() {
err := f.NewEchoDeployment()
Expect(err).NotTo(HaveOccurred())
err = f.UpdateNginxConfigMapData(setting, "false")
Expect(err).NotTo(HaveOccurred())
f.NewEchoDeployment()
f.UpdateNginxConfigMapData(setting, "false")
})
AfterEach(func() {
@ -48,27 +45,22 @@ var _ = framework.IngressNginxDescribe("Proxy Protocol", func() {
It("should respect port passed by the PROXY Protocol", func() {
host := "proxy-protocol"
err := f.UpdateNginxConfigMapData(setting, "true")
Expect(err).NotTo(HaveOccurred())
f.UpdateNginxConfigMapData(setting, "true")
ing, err := f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, nil))
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, nil))
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "server_name proxy-protocol") &&
strings.Contains(server, "listen 80 proxy_protocol")
})
Expect(err).NotTo(HaveOccurred())
ip, err := f.GetNginxIP()
Expect(err).NotTo(HaveOccurred())
ip := f.GetNginxIP()
port, err := f.GetNginxPort("http")
Expect(err).NotTo(HaveOccurred())
Expect(err).NotTo(HaveOccurred(), "unexpected error obtaning NGINX Port")
conn, err := net.Dial("tcp", net.JoinHostPort(ip, strconv.Itoa(port)))
Expect(err).NotTo(HaveOccurred())
Expect(err).NotTo(HaveOccurred(), "unexpected error creating connection to %s:%d", ip, port)
defer conn.Close()
header := "PROXY TCP4 192.168.0.1 192.168.0.11 56324 1234\r\n"
@ -76,7 +68,7 @@ var _ = framework.IngressNginxDescribe("Proxy Protocol", func() {
conn.Write([]byte("GET / HTTP/1.1\r\nHost: proxy-protocol\r\n\r\n"))
data, err := ioutil.ReadAll(conn)
Expect(err).NotTo(HaveOccurred())
Expect(err).NotTo(HaveOccurred(), "unexpected error reading connection data")
body := string(data)
Expect(body).Should(ContainSubstring(fmt.Sprintf("host=%v", "proxy-protocol")))
Expect(body).Should(ContainSubstring(fmt.Sprintf("x-forwarded-port=80")))

View file

@ -20,7 +20,6 @@ import (
"strings"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"k8s.io/api/extensions/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -33,34 +32,28 @@ var _ = framework.IngressNginxDescribe("Server Tokens", func() {
serverTokens := "server-tokens"
BeforeEach(func() {
err := f.NewEchoDeployment()
Expect(err).NotTo(HaveOccurred())
f.NewEchoDeployment()
})
AfterEach(func() {
})
It("should not exists Server header in the response", func() {
err := f.UpdateNginxConfigMapData(serverTokens, "false")
Expect(err).NotTo(HaveOccurred())
f.UpdateNginxConfigMapData(serverTokens, "false")
ing, err := f.EnsureIngress(framework.NewSingleIngress(serverTokens, "/", serverTokens, f.IngressController.Namespace, "http-svc", 80, nil))
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
f.EnsureIngress(framework.NewSingleIngress(serverTokens, "/", serverTokens, f.IngressController.Namespace, "http-svc", 80, nil))
err = f.WaitForNginxConfiguration(
f.WaitForNginxConfiguration(
func(cfg string) bool {
return strings.Contains(cfg, "server_tokens off") &&
strings.Contains(cfg, "more_clear_headers Server;")
})
Expect(err).NotTo(HaveOccurred())
})
It("should exists Server header in the response when is enabled", func() {
err := f.UpdateNginxConfigMapData(serverTokens, "true")
Expect(err).NotTo(HaveOccurred())
f.UpdateNginxConfigMapData(serverTokens, "true")
ing, err := f.EnsureIngress(&v1beta1.Ingress{
f.EnsureIngress(&v1beta1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: serverTokens,
Namespace: f.IngressController.Namespace,
@ -88,13 +81,9 @@ var _ = framework.IngressNginxDescribe("Server Tokens", func() {
},
})
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxConfiguration(
f.WaitForNginxConfiguration(
func(cfg string) bool {
return strings.Contains(cfg, "server_tokens on")
})
Expect(err).NotTo(HaveOccurred())
})
})

View file

@ -34,8 +34,7 @@ var _ = framework.IngressNginxDescribe("Settings - TLS)", func() {
host := "settings-tls"
BeforeEach(func() {
err := f.NewEchoDeployment()
Expect(err).NotTo(HaveOccurred())
f.NewEchoDeployment()
})
AfterEach(func() {
@ -52,19 +51,15 @@ var _ = framework.IngressNginxDescribe("Settings - TLS)", func() {
tlsConfig, err := tlsEndpoint(f, host)
Expect(err).NotTo(HaveOccurred())
err = framework.WaitForTLS(f.IngressController.HTTPSURL, tlsConfig)
Expect(err).NotTo(HaveOccurred())
framework.WaitForTLS(f.IngressController.HTTPSURL, tlsConfig)
By("setting cipher suite")
f.UpdateNginxConfigMapData(sslCiphers, testCiphers)
err = f.UpdateNginxConfigMapData(sslCiphers, testCiphers)
Expect(err).NotTo(HaveOccurred())
err = f.WaitForNginxConfiguration(
f.WaitForNginxConfiguration(
func(cfg string) bool {
return strings.Contains(cfg, fmt.Sprintf("ssl_ciphers '%s';", testCiphers))
})
Expect(err).NotTo(HaveOccurred())
resp, _, errs := gorequest.New().
Get(f.IngressController.HTTPSURL).
@ -78,15 +73,12 @@ var _ = framework.IngressNginxDescribe("Settings - TLS)", func() {
Expect(resp.TLS.CipherSuite).Should(BeNumerically("==", tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384))
By("enforcing TLS v1.0")
f.UpdateNginxConfigMapData(sslProtocols, "TLSv1")
err = f.UpdateNginxConfigMapData(sslProtocols, "TLSv1")
Expect(err).NotTo(HaveOccurred())
err = f.WaitForNginxConfiguration(
f.WaitForNginxConfiguration(
func(cfg string) bool {
return strings.Contains(cfg, "ssl_protocols TLSv1;")
})
Expect(err).NotTo(HaveOccurred())
resp, _, errs = gorequest.New().
Get(f.IngressController.HTTPSURL).
@ -108,19 +100,15 @@ var _ = framework.IngressNginxDescribe("Settings - TLS)", func() {
tlsConfig, err := tlsEndpoint(f, host)
Expect(err).NotTo(HaveOccurred())
err = framework.WaitForTLS(f.IngressController.HTTPSURL, tlsConfig)
Expect(err).NotTo(HaveOccurred())
framework.WaitForTLS(f.IngressController.HTTPSURL, tlsConfig)
By("setting max-age parameter")
f.UpdateNginxConfigMapData(hstsMaxAge, "86400")
err = f.UpdateNginxConfigMapData(hstsMaxAge, "86400")
Expect(err).NotTo(HaveOccurred())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "Strict-Transport-Security: max-age=86400; includeSubDomains\"")
})
Expect(err).NotTo(HaveOccurred())
resp, _, errs := gorequest.New().
Get(f.IngressController.HTTPSURL).
@ -133,15 +121,12 @@ var _ = framework.IngressNginxDescribe("Settings - TLS)", func() {
Expect(resp.Header.Get("Strict-Transport-Security")).Should(ContainSubstring("max-age=86400"))
By("setting includeSubDomains parameter")
f.UpdateNginxConfigMapData(hstsIncludeSubdomains, "false")
err = f.UpdateNginxConfigMapData(hstsIncludeSubdomains, "false")
Expect(err).NotTo(HaveOccurred())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "Strict-Transport-Security: max-age=86400\"")
})
Expect(err).NotTo(HaveOccurred())
resp, _, errs = gorequest.New().
Get(f.IngressController.HTTPSURL).
@ -154,15 +139,12 @@ var _ = framework.IngressNginxDescribe("Settings - TLS)", func() {
Expect(resp.Header.Get("Strict-Transport-Security")).ShouldNot(ContainSubstring("includeSubDomains"))
By("setting preload parameter")
f.UpdateNginxConfigMapData(hstsPreload, "true")
err = f.UpdateNginxConfigMapData(hstsPreload, "true")
Expect(err).NotTo(HaveOccurred())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "Strict-Transport-Security: max-age=86400; preload\"")
})
Expect(err).NotTo(HaveOccurred())
resp, _, errs = gorequest.New().
Get(f.IngressController.HTTPSURL).
@ -177,11 +159,7 @@ var _ = framework.IngressNginxDescribe("Settings - TLS)", func() {
})
func tlsEndpoint(f *framework.Framework, host string) (*tls.Config, error) {
ing, err := f.EnsureIngress(framework.NewSingleIngressWithTLS(host, "/", host, f.IngressController.Namespace, "http-svc", 80, nil))
if err != nil {
return nil, err
}
ing := f.EnsureIngress(framework.NewSingleIngressWithTLS(host, "/", host, f.IngressController.Namespace, "http-svc", 80, nil))
return framework.CreateIngressTLSSecret(f.KubeClientSet,
ing.Spec.TLS[0].Hosts,
ing.Spec.TLS[0].SecretName,

View file

@ -33,8 +33,7 @@ var _ = framework.IngressNginxDescribe("SSL", func() {
f := framework.NewDefaultFramework("ssl")
BeforeEach(func() {
err := f.NewEchoDeployment()
Expect(err).NotTo(HaveOccurred())
f.NewEchoDeployment()
})
AfterEach(func() {
@ -43,7 +42,7 @@ var _ = framework.IngressNginxDescribe("SSL", func() {
It("should not appear references to secret updates not used in ingress rules", func() {
host := "ssl-update"
dummySecret, err := f.EnsureSecret(&v1.Secret{
dummySecret := f.EnsureSecret(&v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "dummy",
Namespace: f.IngressController.Namespace,
@ -52,24 +51,20 @@ var _ = framework.IngressNginxDescribe("SSL", func() {
"key": []byte("value"),
},
})
Expect(err).NotTo(HaveOccurred())
ing, err := f.EnsureIngress(framework.NewSingleIngressWithTLS(host, "/", host, f.IngressController.Namespace, "http-svc", 80, nil))
Expect(err).ToNot(HaveOccurred())
Expect(ing).ToNot(BeNil())
ing := f.EnsureIngress(framework.NewSingleIngressWithTLS(host, "/", host, f.IngressController.Namespace, "http-svc", 80, nil))
_, err = framework.CreateIngressTLSSecret(f.KubeClientSet,
_, err := framework.CreateIngressTLSSecret(f.KubeClientSet,
ing.Spec.TLS[0].Hosts,
ing.Spec.TLS[0].SecretName,
ing.Namespace)
Expect(err).ToNot(HaveOccurred())
err = f.WaitForNginxServer(host,
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "server_name ssl-update") &&
strings.Contains(server, "listen 443")
})
Expect(err).ToNot(HaveOccurred())
log, err := f.NginxLogs()
Expect(err).ToNot(HaveOccurred())

141
test/e2e/status/update.go Normal file
View file

@ -0,0 +1,141 @@
/*
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 settings
import (
"fmt"
"log"
"net"
"strings"
"time"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
appsv1beta1 "k8s.io/api/apps/v1beta1"
apiv1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/ingress-nginx/test/e2e/framework"
)
var _ = framework.IngressNginxDescribe("Status Update [Status]", func() {
f := framework.NewDefaultFramework("status-update")
host := "status-update"
address := getHostIP()
BeforeEach(func() {
})
AfterEach(func() {
})
It("should update status field after client-go reconnection", func() {
port, cmd, err := f.KubectlProxy(0)
Expect(err).NotTo(HaveOccurred(), "unexpected error starting kubectl proxy")
err = framework.UpdateDeployment(f.KubeClientSet, f.IngressController.Namespace, "nginx-ingress-controller", 1,
func(deployment *appsv1beta1.Deployment) error {
args := deployment.Spec.Template.Spec.Containers[0].Args
args = append(args, fmt.Sprintf("--apiserver-host=http://%s:%d", address.String(), port))
args = append(args, "--publish-status-address=1.1.0.0")
// flags --publish-service and --publish-status-address are mutually exclusive
var index int
for k, v := range args {
if strings.Index(v, "--publish-service") != -1 {
index = k
break
}
}
if index > -1 {
args[index] = ""
}
deployment.Spec.Template.Spec.Containers[0].Args = args
_, err := f.KubeClientSet.AppsV1beta1().Deployments(f.IngressController.Namespace).Update(deployment)
return err
})
Expect(err).NotTo(HaveOccurred(), "unexpected error updating ingress controller deployment flags")
f.NewEchoDeploymentWithReplicas(1)
ing := f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, nil))
f.WaitForNginxConfiguration(
func(cfg string) bool {
return strings.Contains(cfg, fmt.Sprintf("server_name %s", host))
})
framework.Logf("waiting for leader election and initial status update")
time.Sleep(30 * time.Second)
err = cmd.Process.Kill()
Expect(err).NotTo(HaveOccurred(), "unexpected error terminating kubectl proxy")
ing, err = f.KubeClientSet.Extensions().Ingresses(f.IngressController.Namespace).Get(host, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred(), "unexpected error getting %s/%v Ingress", f.IngressController.Namespace, host)
ing.Status.LoadBalancer.Ingress = []apiv1.LoadBalancerIngress{}
_, err = f.KubeClientSet.Extensions().Ingresses(f.IngressController.Namespace).UpdateStatus(ing)
Expect(err).NotTo(HaveOccurred(), "unexpected error cleaning Ingress status")
time.Sleep(10 * time.Second)
err = f.KubeClientSet.CoreV1().
ConfigMaps(f.IngressController.Namespace).
Delete("ingress-controller-leader-nginx", &metav1.DeleteOptions{})
Expect(err).NotTo(HaveOccurred(), "unexpected error deleting leader election configmap")
_, cmd, err = f.KubectlProxy(port)
Expect(err).NotTo(HaveOccurred(), "unexpected error starting kubectl proxy")
defer func() {
if cmd != nil {
err := cmd.Process.Kill()
Expect(err).NotTo(HaveOccurred(), "unexpected error terminating kubectl proxy")
}
}()
err = wait.Poll(10*time.Second, time.Minute*3, func() (done bool, err error) {
ing, err = f.KubeClientSet.Extensions().Ingresses(f.IngressController.Namespace).Get(host, metav1.GetOptions{})
if err != nil {
return false, err
}
if len(ing.Status.LoadBalancer.Ingress) != 1 {
return false, nil
}
return true, nil
})
Expect(err).NotTo(HaveOccurred(), "unexpected error waiting for ingress status")
Expect(ing.Status.LoadBalancer.Ingress).Should(Equal([]apiv1.LoadBalancerIngress{
{IP: "1.1.0.0"},
}))
})
})
func getHostIP() net.IP {
conn, err := net.Dial("udp", "8.8.8.8:80")
if err != nil {
log.Fatal(err)
}
defer conn.Close()
localAddr := conn.LocalAddr().(*net.UDPAddr)
return localAddr.IP
}

View file

@ -22,7 +22,7 @@ if test -e kubectl; then
echo "skipping download of kubectl"
else
echo "downloading kubectl..."
curl -Lo kubectl https://storage.googleapis.com/kubernetes-release/release/v1.11.0/bin/linux/amd64/kubectl && \
curl -Lo kubectl https://storage.googleapis.com/kubernetes-release/release/v1.12.0/bin/linux/amd64/kubectl && \
chmod +x kubectl && sudo mv kubectl /usr/local/bin/
fi
@ -31,6 +31,9 @@ touch ${HOME}/.kube/config
export KUBECONFIG=${HOME}/.kube/config
echo "starting Kubernetes cluster..."
curl -Lo $DIR/dind-cluster-v1.11.sh https://raw.githubusercontent.com/kubernetes-sigs/kubeadm-dind-cluster/master/fixed/dind-cluster-v1.11.sh && \
chmod +x $DIR/dind-cluster-v1.11.sh
$DIR/dind-cluster-v1.11.sh up
kubectl config use-context dind