Generate test snippets from md files POC (#7044)

* Generate test snippets from md POC

* fixes

* fix python lint

* fix snip source

* improvements

* update snip calls

* add copyright header

* lint errors

* lint error in md instructions

* better default snip_id

* run test without snippet gen

* gofmt

* fixes

* fix path

* fixes

* fix verify
This commit is contained in:
Frank Budinsky 2020-04-14 10:13:44 -04:00 committed by GitHub
parent 83dbc79145
commit 3b59501872
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 390 additions and 20 deletions

View File

@ -5,6 +5,7 @@ weight: 40
keywords: [security,authentication,migration] keywords: [security,authentication,migration]
aliases: aliases:
- /docs/tasks/security/mtls-migration/ - /docs/tasks/security/mtls-migration/
test: true
--- ---
This task shows how to ensure your workloads only communicate using mutual TLS as they are migrated to This task shows how to ensure your workloads only communicate using mutual TLS as they are migrated to
@ -55,7 +56,7 @@ the policies to enforce STRICT mutual TLS between the workloads.
* Verify setup by sending an http request (using curl command) from any sleep pod (among those in namespace `foo`, `bar` or `legacy`) to `httpbin.foo`. All requests should success with HTTP code 200. * Verify setup by sending an http request (using curl command) from any sleep pod (among those in namespace `foo`, `bar` or `legacy`) to `httpbin.foo`. All requests should success with HTTP code 200.
{{< text bash >}} {{< text bash >}}
$ for from in "foo" "bar" "legacy"; do for to in "foo" "bar"; do kubectl exec $(kubectl get pod -l app=sleep -n ${from} -o jsonpath={.items..metadata.name}) -c sleep -n ${from} -- curl http://httpbin.${to}:8000/ip -s -o /dev/null -w "sleep.${from} to httpbin.${to}: %{http_code}\n"; done; done $ for from in "foo" "bar" "legacy"; do for to in "foo" "bar"; do kubectl exec "$(kubectl get pod -l app=sleep -n ${from} -o jsonpath={.items..metadata.name})" -c sleep -n ${from} -- curl http://httpbin.${to}:8000/ip -s -o /dev/null -w "sleep.${from} to httpbin.${to}: %{http_code}\n"; done; done
sleep.foo to httpbin.foo: 200 sleep.foo to httpbin.foo: 200
sleep.foo to httpbin.bar: 200 sleep.foo to httpbin.bar: 200
sleep.bar to httpbin.foo: 200 sleep.bar to httpbin.foo: 200
@ -96,7 +97,7 @@ EOF
Now, you should see the request from `sleep.legacy` to `httpbin.foo` failing. Now, you should see the request from `sleep.legacy` to `httpbin.foo` failing.
{{< text bash >}} {{< text bash >}}
$ for from in "foo" "bar" "legacy"; do for to in "foo" "bar"; do kubectl exec $(kubectl get pod -l app=sleep -n ${from} -o jsonpath={.items..metadata.name}) -c sleep -n ${from} -- curl http://httpbin.${to}:8000/ip -s -o /dev/null -w "sleep.${from} to httpbin.${to}: %{http_code}\n"; done; done $ for from in "foo" "bar" "legacy"; do for to in "foo" "bar"; do kubectl exec "$(kubectl get pod -l app=sleep -n ${from} -o jsonpath={.items..metadata.name})" -c sleep -n ${from} -- curl http://httpbin.${to}:8000/ip -s -o /dev/null -w "sleep.${from} to httpbin.${to}: %{http_code}\n"; done; done
sleep.foo to httpbin.foo: 200 sleep.foo to httpbin.foo: 200
sleep.foo to httpbin.bar: 200 sleep.foo to httpbin.bar: 200
sleep.bar to httpbin.foo: 200 sleep.bar to httpbin.foo: 200
@ -110,7 +111,7 @@ If you installed Istio with `values.global.proxy.privileged=true`, you can use `
traffic is encrypted or not. traffic is encrypted or not.
{{< text bash >}} {{< text bash >}}
$ kubectl exec -nfoo $(kubectl get pod -nfoo -lapp=httpbin -ojsonpath={.items..metadata.name}) -c istio-proxy -it -- sudo tcpdump dst port 80 -A $ kubectl exec -nfoo "$(kubectl get pod -nfoo -lapp=httpbin -ojsonpath={.items..metadata.name})" -c istio-proxy -it -- sudo tcpdump dst port 80 -A
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
{{< /text >}} {{< /text >}}
@ -140,7 +141,7 @@ Now, both the `foo` and `bar` namespaces enforce mutual TLS only traffic, so you
failing for both. failing for both.
{{< text bash >}} {{< text bash >}}
$ for from in "foo" "bar" "legacy"; do for to in "foo" "bar"; do kubectl exec $(kubectl get pod -l app=sleep -n ${from} -o jsonpath={.items..metadata.name}) -c sleep -n ${from} -- curl http://httpbin.${to}:8000/ip -s -o /dev/null -w "sleep.${from} to httpbin.${to}: %{http_code}\n"; done; done $ for from in "foo" "bar" "legacy"; do for to in "foo" "bar"; do kubectl exec "$(kubectl get pod -l app=sleep -n ${from} -o jsonpath={.items..metadata.name})" -c sleep -n ${from} -- curl http://httpbin.${to}:8000/ip -s -o /dev/null -w "sleep.${from} to httpbin.${to}: %{http_code}\n"; done; done
{{< /text >}} {{< /text >}}
## Clean up the example ## Clean up the example

View File

@ -0,0 +1,132 @@
#!/bin/bash
# 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/security/authentication/mtls-migration/index.md
####################################################################################################
snip_set_up_the_cluster_1() {
kubectl create ns foo
kubectl apply -f <(istioctl kube-inject -f samples/httpbin/httpbin.yaml) -n foo
kubectl apply -f <(istioctl kube-inject -f samples/sleep/sleep.yaml) -n foo
kubectl create ns bar
kubectl apply -f <(istioctl kube-inject -f samples/httpbin/httpbin.yaml) -n bar
kubectl apply -f <(istioctl kube-inject -f samples/sleep/sleep.yaml) -n bar
}
snip_set_up_the_cluster_2() {
kubectl create ns legacy
kubectl apply -f samples/sleep/sleep.yaml -n legacy
}
snip_set_up_the_cluster_3() {
for from in "foo" "bar" "legacy"; do for to in "foo" "bar"; do kubectl exec "$(kubectl get pod -l app=sleep -n ${from} -o jsonpath={.items..metadata.name})" -c sleep -n ${from} -- curl http://httpbin.${to}:8000/ip -s -o /dev/null -w "sleep.${from} to httpbin.${to}: %{http_code}\n"; done; done
}
# shellcheck disable=SC2034
! read -r -d '' snip_set_up_the_cluster_3_out <<ENDSNIP
sleep.foo to httpbin.foo: 200
sleep.foo to httpbin.bar: 200
sleep.bar to httpbin.foo: 200
sleep.bar to httpbin.bar: 200
sleep.legacy to httpbin.foo: 200
sleep.legacy to httpbin.bar: 200
ENDSNIP
snip_set_up_the_cluster_4() {
kubectl get peerauthentication --all-namespaces
}
# shellcheck disable=SC2034
! read -r -d '' snip_set_up_the_cluster_4_out <<ENDSNIP
No resources found
ENDSNIP
snip_set_up_the_cluster_5() {
kubectl get destinationrule --all-namespaces
}
# shellcheck disable=SC2034
! read -r -d '' snip_set_up_the_cluster_5_out <<ENDSNIP
No resources found
ENDSNIP
snip_lock_down_to_mutual_tls_by_namespace_1() {
kubectl apply -n foo -f - <<EOF
apiVersion: "security.istio.io/v1beta1"
kind: "PeerAuthentication"
metadata:
name: "default"
spec:
mtls:
mode: STRICT
EOF
}
snip_lock_down_to_mutual_tls_by_namespace_2() {
for from in "foo" "bar" "legacy"; do for to in "foo" "bar"; do kubectl exec "$(kubectl get pod -l app=sleep -n ${from} -o jsonpath={.items..metadata.name})" -c sleep -n ${from} -- curl http://httpbin.${to}:8000/ip -s -o /dev/null -w "sleep.${from} to httpbin.${to}: %{http_code}\n"; done; done
}
# shellcheck disable=SC2034
! read -r -d '' snip_lock_down_to_mutual_tls_by_namespace_2_out <<ENDSNIP
sleep.foo to httpbin.foo: 200
sleep.foo to httpbin.bar: 200
sleep.bar to httpbin.foo: 200
sleep.bar to httpbin.bar: 200
sleep.legacy to httpbin.foo: 000
command terminated with exit code 56
sleep.legacy to httpbin.bar: 200
ENDSNIP
snip_lock_down_to_mutual_tls_by_namespace_3() {
kubectl exec -nfoo "$(kubectl get pod -nfoo -lapp=httpbin -ojsonpath={.items..metadata.name})" -c istio-proxy -it -- sudo tcpdump dst port 80 -A
}
# shellcheck disable=SC2034
! read -r -d '' snip_lock_down_to_mutual_tls_by_namespace_3_out <<ENDSNIP
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
ENDSNIP
snip_lock_down_mutual_tls_for_the_entire_mesh_1() {
kubectl apply -n istio-system -f - <<EOF
apiVersion: "security.istio.io/v1beta1"
kind: "PeerAuthentication"
metadata:
name: "default"
spec:
mtls:
mode: STRICT
EOF
}
snip_lock_down_mutual_tls_for_the_entire_mesh_2() {
for from in "foo" "bar" "legacy"; do for to in "foo" "bar"; do kubectl exec "$(kubectl get pod -l app=sleep -n ${from} -o jsonpath={.items..metadata.name})" -c sleep -n ${from} -- curl http://httpbin.${to}:8000/ip -s -o /dev/null -w "sleep.${from} to httpbin.${to}: %{http_code}\n"; done; done
}
snip_clean_up_the_example_1() {
kubectl delete peerauthentication --all-namespaces --all
}
snip_clean_up_the_example_2() {
kubectl delete ns foo bar legacy
}
# shellcheck disable=SC2034
! read -r -d '' snip_clean_up_the_example_2_out <<ENDSNIP
Namespaces foo bar legacy deleted.
ENDSNIP

View File

@ -5,6 +5,7 @@ weight: 30
keywords: [traffic-management,traffic-shifting] keywords: [traffic-management,traffic-shifting]
aliases: aliases:
- /docs/tasks/traffic-management/version-migration.html - /docs/tasks/traffic-management/version-migration.html
test: true
--- ---
This task shows you how to gradually migrate traffic from one version of a This task shows you how to gradually migrate traffic from one version of a
@ -35,7 +36,7 @@ If you haven't already applied destination rules, follow the instructions in [Ap
1. To get started, run this command to route all traffic to the `v1` version of 1. To get started, run this command to route all traffic to the `v1` version of
each microservice. each microservice.
{{< text bash >}} {{< text syntax=bash snip_id=config_all_v1 >}}
$ kubectl apply -f @samples/bookinfo/networking/virtual-service-all-v1.yaml@ $ kubectl apply -f @samples/bookinfo/networking/virtual-service-all-v1.yaml@
{{< /text >}} {{< /text >}}
@ -49,7 +50,7 @@ the [Bookinfo](/docs/examples/bookinfo/#determine-the-ingress-ip-and-port) doc.
1. Transfer 50% of the traffic from `reviews:v1` to `reviews:v3` with the following command: 1. Transfer 50% of the traffic from `reviews:v1` to `reviews:v3` with the following command:
{{< text bash >}} {{< text syntax=bash snip_id=config_50_v3 >}}
$ kubectl apply -f @samples/bookinfo/networking/virtual-service-reviews-50-v3.yaml@ $ kubectl apply -f @samples/bookinfo/networking/virtual-service-reviews-50-v3.yaml@
{{< /text >}} {{< /text >}}
@ -57,7 +58,7 @@ the [Bookinfo](/docs/examples/bookinfo/#determine-the-ingress-ip-and-port) doc.
1. Confirm the rule was replaced: 1. Confirm the rule was replaced:
{{< text bash yaml >}} {{< text syntax=bash outputis=yaml snip_id=verify_config_50_v3 >}}
$ kubectl get virtualservice reviews -o yaml $ kubectl get virtualservice reviews -o yaml
apiVersion: networking.istio.io/v1alpha3 apiVersion: networking.istio.io/v1alpha3
kind: VirtualService kind: VirtualService
@ -92,7 +93,7 @@ the star ratings service, but the `v1` version does not.
1. Assuming you decide that the `reviews:v3` microservice is stable, you can 1. Assuming you decide that the `reviews:v3` microservice is stable, you can
route 100% of the traffic to `reviews:v3` by applying this virtual service: route 100% of the traffic to `reviews:v3` by applying this virtual service:
{{< text bash >}} {{< text syntax=bash snip_id=config_100_v3 >}}
$ kubectl apply -f @samples/bookinfo/networking/virtual-service-reviews-v3.yaml@ $ kubectl apply -f @samples/bookinfo/networking/virtual-service-reviews-v3.yaml@
{{< /text >}} {{< /text >}}
@ -112,7 +113,7 @@ article [Canary Deployments using Istio](/blog/2017/0.1-canary/).
1. Remove the application routing rules: 1. Remove the application routing rules:
{{< text bash >}} {{< text syntax=bash snip_id=cleanup >}}
$ kubectl delete -f @samples/bookinfo/networking/virtual-service-all-v1.yaml@ $ kubectl delete -f @samples/bookinfo/networking/virtual-service-all-v1.yaml@
{{< /text >}} {{< /text >}}

View File

@ -0,0 +1,62 @@
#!/bin/bash
# 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/traffic-shifting/index.md
####################################################################################################
snip_config_all_v1() {
kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml
}
snip_config_50_v3() {
kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-50-v3.yaml
}
snip_verify_config_50_v3() {
kubectl get virtualservice reviews -o yaml
}
# shellcheck disable=SC2034
! read -r -d '' snip_verify_config_50_v3_out <<ENDSNIP
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
...
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
weight: 50
- destination:
host: reviews
subset: v3
weight: 50
ENDSNIP
snip_config_100_v3() {
kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-v3.yaml
}
snip_cleanup() {
kubectl delete -f samples/bookinfo/networking/virtual-service-all-v1.yaml
}

View File

@ -319,10 +319,15 @@ func (s Script) runCommand(ctx Context) {
// Copy the commands from the snippet. // Copy the commands from the snippet.
for _, snippetCommand := range snippetCommands { for _, snippetCommand := range snippetCommands {
commandLines = append(commandLines, filterCommandLine(snippetCommand)) if sinfo.name != "" {
snippetCommand = filterCommandLine(snippetCommand)
}
commandLines = append(commandLines, snippetCommand)
} }
} else { } else {
// Not a snippet, just copy the line directly to the command. // Not a snippet, just copy the line directly to the command.
// TODO commandLines = append(commandLines, line) // Commands outside of snippets should be proper bash
// TODO Need to fix some tests that are incorrectly annotating commands outside of snippets.
commandLines = append(commandLines, filterCommandLine(line)) commandLines = append(commandLines, filterCommandLine(line))
} }
} }
@ -390,6 +395,11 @@ func (s Script) createSnippets(ctx Context) {
// Verify the output for this snippet. // Verify the output for this snippet.
sinfo.verify() sinfo.verify()
if strings.HasPrefix(sinfo.name, "_NOGEN_") {
// No snippet to generate, just verifying output.
continue
}
// Verify the output, if configured to do so. // Verify the output, if configured to do so.
snippetOutput := "" snippetOutput := ""
if sinfo.outputIs != "" { if sinfo.outputIs != "" {
@ -530,7 +540,8 @@ func parseSnippet(ctx Context, lineIndex *int, lines []string) snippetInfo {
} }
if info.name == "" { if info.name == "" {
ctx.Fatalf("snippet missing name") // If no snippet name is set, the framework will run the commands/verifiers without generating snippets.
info.name = fmt.Sprintf("_NOGEN_%d", *lineIndex)
} }
if info.outputIs == "" && info.outputSnippet { if info.outputIs == "" && info.outputSnippet {

19
scripts/gen_snips.sh Executable file
View File

@ -0,0 +1,19 @@
#!/bin/bash
# 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
find content/en -name '*.md' -exec grep --quiet 'test: true' {} \; -exec python scripts/snip.py {} \;

138
scripts/snip.py Normal file
View File

@ -0,0 +1,138 @@
#!/usr/bin/python
# 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.
import sys
import re
import os
linenum = 0
snipnum = 0
section = ""
current_snip = None
multiline_cmd = False
output_started = False
snippets = []
HEADER = """#!/bin/bash
# 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:
# %s
####################################################################################################
"""
startsnip = re.compile(r"^(\s*){{< text (syntax=)?\"?(\w+)\"? .*>}}$")
snippetid = re.compile(r"snip_id=(\w+)")
githubfile = re.compile(r"^([^@]*)@([\w\.\-_/]+)@([^@]*)$")
sectionhead = re.compile(r"^##+ (.*)$")
invalidchar = re.compile(r"[^0-9a-zA-Z_]")
if len(sys.argv) < 2:
print("usage: python snip.py mdfile [ snipdir ]")
sys.exit(1)
markdown = sys.argv[1]
if len(sys.argv) > 2:
snipdir = sys.argv[2]
else:
snipdir = os.path.dirname(markdown)
snipfile = "snips.sh" if markdown.split('/')[-1] == "index.md" else markdown.split('/')[-1] + "_snips.sh"
print("generating snips: " + os.path.join(snipdir, snipfile))
with open(markdown, 'rt') as mdfile:
for line in mdfile:
linenum += 1
match = sectionhead.match(line)
if match:
snipnum = 0
section = invalidchar.sub('', match.group(1).replace(" ", "_")).lower()
continue
match = startsnip.match(line)
if match:
snipnum += 1
indent = match.group(1)
kind = match.group(3)
match = snippetid.search(line)
if match:
id = "snip_" + match.group(1)
else:
id = "snip_%s_%d" % (section, snipnum)
if kind == "bash":
script = "\n%s() {\n" % id
else:
script = "\n# shellcheck disable=SC2034\n! read -r -d '' %s <<ENDSNIP\n" % id
current_snip = {"start": linenum, "id": id, "kind": kind, "indent": indent, "script": ["", script]}
snippets.append(current_snip)
continue
if current_snip != None:
if current_snip["indent"]:
_, line = line.split(current_snip["indent"], 1)
if "{{< /text >}}" in line:
if current_snip["kind"] == "bash" and not output_started:
script = "}\n"
else:
script = "ENDSNIP\n"
current_snip["script"].append(script)
current_snip = None
multiline_cmd = False
output_started = False
else:
if current_snip["kind"] == "bash":
if line.startswith("$ "):
line = line[2:]
else:
if multiline_cmd:
if line == "EOF\n":
multiline_cmd = False
elif not current_snip["script"][-1].endswith("\\\n"):
# command output
if not output_started:
current_snip["script"].append("}\n\n# shellcheck disable=SC2034\n! read -r -d '' %s_out <<ENDSNIP\n" % id)
output_started = True
match = githubfile.match(line)
if match:
line = match.group(1) + match.group(2) + match.group(3)
if "<<EOF" in line:
multiline_cmd = True
current_snip["script"].append(line)
with open(os.path.join(snipdir, snipfile), 'w') as f:
f.write(HEADER % markdown.split("content/en/")[1] if "content/en/" in markdown else markdown)
for snippet in snippets:
lines = snippet["script"]
for line in lines:
f.write(line)

View File

@ -18,6 +18,8 @@ set -e
set -u set -u
set -o pipefail set -o pipefail
source ${REPO_ROOT}/content/en/docs/tasks/traffic-management/traffic-shifting/snips.sh
# setup bookinfo & sleep pods # setup bookinfo & sleep pods
kubectl label namespace default istio-injection=enabled --overwrite || true kubectl label namespace default istio-injection=enabled --overwrite || true
@ -78,8 +80,8 @@ function verify_traffic_shift() {
# Step 1 # Step 1
# $snippet route_all_v1 syntax="bash" outputis="text" outputsnippet="true" # $snippet
$ kubectl apply -f @samples/bookinfo/networking/virtual-service-all-v1.yaml@ snip_config_all_v1
# $verify # $verify
virtualservice.networking.istio.io/productpage created virtualservice.networking.istio.io/productpage created
virtualservice.networking.istio.io/reviews created virtualservice.networking.istio.io/reviews created
@ -92,29 +94,33 @@ verify_traffic_shift 0
# Step 3: switch 50% traffic to v3 # Step 3: switch 50% traffic to v3
# $snippet route_50_percent_v3 syntax="bash" outputis="text" outputsnippet="true" # $snippet
$ kubectl apply -f @samples/bookinfo/networking/virtual-service-reviews-50-v3.yaml@ snip_config_50_v3
# $verify # $verify
virtualservice.networking.istio.io/reviews configured virtualservice.networking.istio.io/reviews configured
# $endsnippet # $endsnippet
istioctl experimental wait --for=distribution VirtualService reviews.default
istioctl experimental wait --for=distribution VirtualService reviews.default
# Step 4: Confirm the rule was replaced # Step 4: Confirm the rule was replaced
# $snippet verify_review_virtualservice syntax="bash" outputis="text" outputsnippet="true" # $snippet
$ kubectl get virtualservice reviews -o yaml snip_verify_config_50_v3
# $verify verifier="contains" # $verify verifier="contains"
subset: v3 subset: v3
# $endsnippet # $endsnippet
#TODO The above verify could instead test the doc output snippet if we add a suitable yaml verifier
#TODO # $verify verifier="yaml-subset"
#TODO echo "$verify_config_50_v3_out"
# Step 5: verify rating stars visible 50% of the time # Step 5: verify rating stars visible 50% of the time
verify_traffic_shift 50 verify_traffic_shift 50
# Step 6: route 100% traffic to v3 # Step 6: route 100% traffic to v3
# $snippet route_100_percent_v3 syntax="bash" outputis="text" outputsnippet="true" # $snippet
$ kubectl apply -f @samples/bookinfo/networking/virtual-service-reviews-v3.yaml@ snip_config_100_v3
# $endsnippet # $endsnippet
verify_traffic_shift 100 verify_traffic_shift 100