More doc testing (#7253)

* Ingress control test

* Ingress control test

* fix lint

* fix package

* fix path

* improve _verify_like

* curl -s

* debug

* fix compare

* remove flaky verify call

* fix path

* regen
This commit is contained in:
Frank Budinsky 2020-05-12 08:58:07 -04:00 committed by GitHub
parent 34483f9e1f
commit 4f7622e3aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 349 additions and 19 deletions

View File

@ -6,6 +6,7 @@ keywords: [traffic-management,ingress]
aliases:
- /docs/tasks/ingress.html
- /docs/tasks/ingress
test: true
---
Along with support for Kubernetes [Ingress](/docs/tasks/traffic-management/ingress/kubernetes-ingress/), Istio offers another configuration model, [Istio Gateway](/docs/reference/config/networking/gateway/). A `Gateway` provides more extensive customization and flexibility than `Ingress`, and allows Istio features such as monitoring and route rules to be applied to traffic entering the cluster.
@ -28,8 +29,8 @@ Execute the following command to determine if your Kubernetes cluster is running
{{< text bash >}}
$ kubectl get svc istio-ingressgateway -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingressgateway LoadBalancer 172.21.109.129 130.211.10.121 80:31380/TCP,443:31390/TCP,31400:31400/TCP 17h
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingressgateway LoadBalancer 172.21.109.129 130.211.10.121 ... 17h
{{< /text >}}
If the `EXTERNAL-IP` value is set, your environment has an external load balancer that you can use for the ingress gateway.
@ -85,15 +86,15 @@ Setting the ingress IP depends on the cluster provider:
1. _GKE:_
{{< text bash >}}
$ export INGRESS_HOST=<workerNodeAddress>
$ export INGRESS_HOST=worker-node-address
{{< /text >}}
You need to create firewall rules to allow the TCP traffic to the _ingressgateway_ service's ports.
Run the following commands to allow the traffic for the HTTP port, the secure port (HTTPS) or both:
{{< text bash >}}
$ gcloud compute firewall-rules create allow-gateway-http --allow tcp:$INGRESS_PORT
$ gcloud compute firewall-rules create allow-gateway-https --allow tcp:$SECURE_INGRESS_PORT
$ gcloud compute firewall-rules create allow-gateway-http --allow "tcp:$INGRESS_PORT"
$ gcloud compute firewall-rules create allow-gateway-https --allow "tcp:$SECURE_INGRESS_PORT"
{{< /text >}}
1. _Minikube:_
@ -197,7 +198,7 @@ Let's see how you can configure a `Gateway` on port 80 for HTTP traffic.
1. Access the _httpbin_ service using _curl_:
{{< text bash >}}
$ curl -I -HHost:httpbin.example.com http://$INGRESS_HOST:$INGRESS_PORT/status/200
$ curl -s -I -HHost:httpbin.example.com "http://$INGRESS_HOST:$INGRESS_PORT/status/200"
HTTP/1.1 200 OK
server: envoy
date: Mon, 29 Jan 2018 04:45:49 GMT
@ -215,7 +216,7 @@ Let's see how you can configure a `Gateway` on port 80 for HTTP traffic.
1. Access any other URL that has not been explicitly exposed. You should see an HTTP 404 error:
{{< text bash >}}
$ curl -I -HHost:httpbin.example.com http://$INGRESS_HOST:$INGRESS_PORT/headers
$ curl -s -I -HHost:httpbin.example.com "http://$INGRESS_HOST:$INGRESS_PORT/headers"
HTTP/1.1 404 Not Found
date: Mon, 29 Jan 2018 04:45:49 GMT
server: envoy
@ -289,7 +290,7 @@ they have valid values, according to the output of the following commands:
{{< text bash >}}
$ kubectl get svc -n istio-system
$ echo INGRESS_HOST=$INGRESS_HOST, INGRESS_PORT=$INGRESS_PORT
$ echo "INGRESS_HOST=$INGRESS_HOST, INGRESS_PORT=$INGRESS_PORT"
{{< /text >}}
1. Check that you have no other Istio ingress gateways defined on the same port:

View File

@ -0,0 +1,195 @@
#!/bin/bash
# shellcheck disable=SC2034,SC2153,SC2155
# Copyright Istio Authors. All Rights Reserved.
#
# 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.
####################################################################################################
# WARNING: THIS IS AN AUTO-GENERATED FILE, DO NOT EDIT. PLEASE MODIFY THE ORIGINAL MARKDOWN FILE:
# docs/tasks/traffic-management/ingress/ingress-control/index.md
####################################################################################################
snip_determining_the_ingress_ip_and_ports_1() {
kubectl get svc istio-ingressgateway -n istio-system
}
! read -r -d '' snip_determining_the_ingress_ip_and_ports_1_out <<\ENDSNIP
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingressgateway LoadBalancer 172.21.109.129 130.211.10.121 ... 17h
ENDSNIP
snip_determining_the_ingress_ip_and_ports_2() {
export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].port}')
export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].port}')
export TCP_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="tcp")].port}')
}
snip_determining_the_ingress_ip_and_ports_3() {
export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
}
snip_determining_the_ingress_ip_and_ports_4() {
export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}')
export TCP_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="tcp")].nodePort}')
}
snip_determining_the_ingress_ip_and_ports_5() {
export INGRESS_HOST=worker-node-address
}
snip_determining_the_ingress_ip_and_ports_6() {
gcloud compute firewall-rules create allow-gateway-http --allow "tcp:$INGRESS_PORT"
gcloud compute firewall-rules create allow-gateway-https --allow "tcp:$SECURE_INGRESS_PORT"
}
snip_determining_the_ingress_ip_and_ports_7() {
export INGRESS_HOST=$(minikube ip)
}
snip_determining_the_ingress_ip_and_ports_8() {
export INGRESS_HOST=127.0.0.1
}
snip_determining_the_ingress_ip_and_ports_9() {
export INGRESS_HOST=$(kubectl get po -l istio=ingressgateway -n istio-system -o jsonpath='{.items[0].status.hostIP}')
}
snip_configuring_ingress_using_an_istio_gateway_1() {
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: httpbin-gateway
spec:
selector:
istio: ingressgateway # use Istio default gateway implementation
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "httpbin.example.com"
EOF
}
snip_configuring_ingress_using_an_istio_gateway_2() {
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: httpbin
spec:
hosts:
- "httpbin.example.com"
gateways:
- httpbin-gateway
http:
- match:
- uri:
prefix: /status
- uri:
prefix: /delay
route:
- destination:
port:
number: 8000
host: httpbin
EOF
}
snip_configuring_ingress_using_an_istio_gateway_3() {
curl -s -I -HHost:httpbin.example.com "http://$INGRESS_HOST:$INGRESS_PORT/status/200"
}
! read -r -d '' snip_configuring_ingress_using_an_istio_gateway_3_out <<\ENDSNIP
HTTP/1.1 200 OK
server: envoy
date: Mon, 29 Jan 2018 04:45:49 GMT
content-type: text/html; charset=utf-8
access-control-allow-origin: *
access-control-allow-credentials: true
content-length: 0
x-envoy-upstream-service-time: 48
ENDSNIP
snip_configuring_ingress_using_an_istio_gateway_4() {
curl -s -I -HHost:httpbin.example.com "http://$INGRESS_HOST:$INGRESS_PORT/headers"
}
! read -r -d '' snip_configuring_ingress_using_an_istio_gateway_4_out <<\ENDSNIP
HTTP/1.1 404 Not Found
date: Mon, 29 Jan 2018 04:45:49 GMT
server: envoy
content-length: 0
ENDSNIP
snip_accessing_ingress_services_using_a_browser_1() {
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: httpbin-gateway
spec:
selector:
istio: ingressgateway # use Istio default gateway implementation
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: httpbin
spec:
hosts:
- "*"
gateways:
- httpbin-gateway
http:
- match:
- uri:
prefix: /headers
route:
- destination:
port:
number: 8000
host: httpbin
EOF
}
snip_troubleshooting_1() {
kubectl get svc -n istio-system
echo "INGRESS_HOST=$INGRESS_HOST, INGRESS_PORT=$INGRESS_PORT"
}
snip_troubleshooting_2() {
kubectl get gateway --all-namespaces
}
snip_troubleshooting_3() {
kubectl get ingress --all-namespaces
}
snip_cleanup_1() {
kubectl delete gateway httpbin-gateway
kubectl delete virtualservice httpbin
kubectl delete --ignore-not-found=true -f samples/httpbin/httpbin.yaml
}

View File

@ -141,6 +141,10 @@ The framework includes the following built-in verify functions:
Verify that `out` does not contains the substring `expected`. Failure messages will include
the specified `msg`.
1. **`_verify_first_line`** `out` `expected` `msg`
Verify that the first line of `out` matches the first line in `expected`.
1. **`_verify_elided`** `out` `expected` `msg`
Verify that `out` contains the lines in `expected` where `...` on a line matches one or
@ -157,7 +161,7 @@ The framework includes the following built-in verify functions:
1. different elapsed time values (e.g., `30s` is like `5m`)
1. different ip values (e.g., `172.21.0.1` is like `10.0.0.31`)
1. prefix match ending with a dash character (e.g., `reviews-v1-12345...` is like `reviews-v1-67890...`)
1. expected `?` is wildcard, matches anything
1. expected `...` is a wildcard token, matches anything
This function is useful for comparing the output of commands that include some run-specific

View File

@ -0,0 +1,42 @@
// Copyright Istio 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 ingress
import (
"testing"
"istio.io/istio/pkg/test/framework"
"istio.io/istio.io/pkg/test/istioio"
)
func TestIngressControl(t *testing.T) {
framework.
NewTest(t).
Run(istioio.NewBuilder("tasks__traffic_management__ingress_control").
Add(istioio.Script{
Input: istioio.Path("scripts/ingress_control.sh"),
}).
Defer(istioio.Script{
Input: istioio.Inline{
FileName: "cleanup.sh",
Value: `
set +e # ignore cleanup errors
source ${REPO_ROOT}/content/en/docs/tasks/traffic-management/ingress/ingress-control/snips.sh
snip_cleanup_1`,
},
}).
Build())
}

View File

@ -0,0 +1,69 @@
#!/usr/bin/env bash
# shellcheck disable=SC1090,SC2154
# Copyright Istio 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.
set -e
set -u
set -o pipefail
source "${REPO_ROOT}/content/en/docs/tasks/traffic-management/ingress/ingress-control/snips.sh"
source "${REPO_ROOT}/tests/util/samples.sh"
kubectl label namespace default istio-injection=enabled --overwrite
# start the httpbin sample
startup_httpbin_sample
# check for external load balancer
out=$(snip_determining_the_ingress_ip_and_ports_1 2>&1)
_verify_like "$out" "$snip_determining_the_ingress_ip_and_ports_1_out" "snip_determining_the_ingress_ip_and_ports_1"
# set INGRESS_HOST, INGRESS_PORT, and SECURE_INGRESS_PORT environment variables
if [[ "$out" != *"<none>"* && "$out" != *"<pending>"* ]]; then
# external load balancer
snip_determining_the_ingress_ip_and_ports_2
else
# node port
snip_determining_the_ingress_ip_and_ports_4
snip_determining_the_ingress_ip_and_ports_9
fi
# create the gateway and routes
snip_configuring_ingress_using_an_istio_gateway_1
snip_configuring_ingress_using_an_istio_gateway_2
# wait for rules to propagate
sleep 5s # TODO: call proper wait utility (e.g., istioctl wait)
# access the httpbin service
out=$(snip_configuring_ingress_using_an_istio_gateway_3 2>&1)
#_verify_first_line "$out" "$snip_configuring_ingress_using_an_istio_gateway_3_out" "snip_configuring_ingress_using_an_istio_gateway_3"
_verify_contains "$out" "HTTP/1.1 200 OK" "snip_configuring_ingress_using_an_istio_gateway_3"
# access the httpbin service
out=$(snip_configuring_ingress_using_an_istio_gateway_4 2>&1)
#_verify_first_line "$out" "$snip_configuring_ingress_using_an_istio_gateway_4_out" "snip_configuring_ingress_using_an_istio_gateway_4"
_verify_contains "$out" "HTTP/1.1 404 Not Found" "snip_configuring_ingress_using_an_istio_gateway_3"
# configure for web browser
snip_accessing_ingress_services_using_a_browser_1
# wait for rules to propagate
sleep 5s # TODO: call proper wait utility (e.g., istioctl wait)
# access httpbin without host header
out=$(curl -s -I "http://$INGRESS_HOST:$INGRESS_PORT/headers" 2>&1)
_verify_contains "$out" "HTTP/1.1 200 OK" "request_httpbin_without_host_header"

View File

@ -44,10 +44,10 @@ _verify_contains "$out" "Code 503 :" "trip_circuit_breaker"
out=$(kubectl -n istio-io-circuitbreaker exec $FORTIO_POD -c istio-proxy -- \
pilot-agent request GET stats | grep httpbin | grep pending 2>&1)
expected="cluster.outbound|8000||httpbin.istio-io-circuitbreaker.svc.cluster.local.circuit_breakers.default.rq_pending_open: ?
cluster.outbound|8000||httpbin.istio-io-circuitbreaker.svc.cluster.local.circuit_breakers.high.rq_pending_open: ?
cluster.outbound|8000||httpbin.istio-io-circuitbreaker.svc.cluster.local.upstream_rq_pending_active: ?
cluster.outbound|8000||httpbin.istio-io-circuitbreaker.svc.cluster.local.upstream_rq_pending_failure_eject: ?
cluster.outbound|8000||httpbin.istio-io-circuitbreaker.svc.cluster.local.upstream_rq_pending_overflow: ?
cluster.outbound|8000||httpbin.istio-io-circuitbreaker.svc.cluster.local.upstream_rq_pending_total: ?"
expected="cluster.outbound|8000||httpbin.istio-io-circuitbreaker.svc.cluster.local.circuit_breakers.default.rq_pending_open: ...
cluster.outbound|8000||httpbin.istio-io-circuitbreaker.svc.cluster.local.circuit_breakers.high.rq_pending_open: ...
cluster.outbound|8000||httpbin.istio-io-circuitbreaker.svc.cluster.local.upstream_rq_pending_active: ...
cluster.outbound|8000||httpbin.istio-io-circuitbreaker.svc.cluster.local.upstream_rq_pending_failure_eject: ...
cluster.outbound|8000||httpbin.istio-io-circuitbreaker.svc.cluster.local.upstream_rq_pending_overflow: ...
cluster.outbound|8000||httpbin.istio-io-circuitbreaker.svc.cluster.local.upstream_rq_pending_total: ..."
_verify_like "$out" "$expected" "print_statistics_after_tripping"

View File

@ -25,7 +25,7 @@ _verify_same() {
local expected=$2
local msg=$3
if [ "$out" != "$expected" ]; then
if [[ "$out" != "$expected" ]]; then
_err_exit "$msg" "$out"
fi
}
@ -78,6 +78,25 @@ _verify_elided() {
fi
}
# Verify that the first line of $out matches the first line in $expected.
# TODO ???? flaky behavior, doesn't seem to work as expected
_verify_first_line() {
local out=$1
local expected=$2
local msg=$3
# TODO ???? the following seem to leave a trailing \n in some cases and then the following check fails
IFS=$'\n' read -r out_first_line <<< "$out"
IFS=$'\n' read -r expected_first_line <<< "$expected"
echo "out first line: \"$out_first_line\""
echo "expected first line: \"$expected_first_line\""
# TODO ???? following fails because one or the other might have a \n at the end of the string, when the other does not
if [[ "$out_first_line" != "$expected_first_line" ]]; then
_err_exit "$msg" "$out"
fi
}
# Verify that $out is "like" $expected. Like implies:
# 1. Same number of lines
# 2. Same number of whitespace-seperated tokens per line
@ -85,7 +104,7 @@ _verify_elided() {
# - different elapsed time values
# - different ip values
# - prefix match ending with a dash character
# - expected ? is wildcard, matches anything
# - expected ... is a wildcard token, matches anything
_verify_like() {
local out=$1
local expected=$2
@ -124,7 +143,7 @@ _verify_like() {
for j in "${!otokens[@]}"; do
local etok=${etokens[j]}
if [[ "$etok" == "?" ]]; then
if [[ "$etok" == "..." ]]; then
continue
fi
@ -138,7 +157,7 @@ _verify_like() {
continue
fi
if [[ "$otok" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ && "$etok" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
if [[ ("$otok" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ || "$otok" == "<none>" || "$otok" == "<pending>") && "$etok" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
continue
fi