mirror of https://github.com/linkerd/linkerd2.git
IPv6/dual-stack integration tests (#12575)
* IPv6 integration tests This adds a new test `TestDualStack` to the deep suite that ensures requests to a dual stack service are always routed the the IPv6 endpoint. It also amends other tests in the suite for them to work in IPv6-only clusters: - skipports: replaced the booksapp with emojivoto, given the servers in the former don't bind to IPv6 addresses - endpoints: amended the regexes to include IPv6 addresses - localhost: bumped nginx for it to bind to the IPv6 loopback as well Note the `TestDualStack` test is disabled by default because Github runners don't support IPv6. To run it locally, first deploy a dual-stack cluster via: ``` kind create cluster --config test/integration/deep/kind-dualstack.yml ``` (for testing IPv6-only clusters, use the `kind-ipv6.yml` config) Then load the images and trigger the test with: ``` bin/tests --name deep-dual-stack --skip-cluster-create $PWD/target/cli/linux-amd64/linkerd ```
This commit is contained in:
parent
9b4405761f
commit
b21686a9be
|
@ -14,7 +14,9 @@ testdir="$bindir"/../test/integration
|
|||
|
||||
export default_test_names=(deep deep-native-sidecar viz external helm-upgrade uninstall upgrade-edge default-policy-deny rsa-ca)
|
||||
export external_resource_test_names=(external-resources)
|
||||
export all_test_names=(cluster-domain cni-calico-deep multicluster "${default_test_names[*]}" "${external_resource_test_names[*]}")
|
||||
# TODO(alpeb): add test cni-calico-deep-dual-stack
|
||||
export dual_stack_test_names=(deep-dual-stack)
|
||||
export all_test_names=(cluster-domain cni-calico-deep multicluster "${default_test_names[*]}" "${external_resource_test_names[*]}" "${dual_stack_test_names[*]}")
|
||||
images_load_default=(proxy controller policy-controller web metrics-api tap)
|
||||
|
||||
tests_usage() {
|
||||
|
@ -448,6 +450,10 @@ run_deep-native-sidecar_test() {
|
|||
run_test "$testdir/deep/..." --native-sidecar
|
||||
}
|
||||
|
||||
run_deep-dual-stack_test() {
|
||||
run_test "$testdir/deep/..." --dual-stack
|
||||
}
|
||||
|
||||
run_default-policy-deny_test() {
|
||||
export default_inbound_policy='deny'
|
||||
run_test "$testdir/install/..."
|
||||
|
|
|
@ -0,0 +1,180 @@
|
|||
package dualstack
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/linkerd/linkerd2/testutil"
|
||||
)
|
||||
|
||||
type IP struct {
|
||||
IP string `json:"ip"`
|
||||
}
|
||||
|
||||
var TestHelper *testutil.TestHelper
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
TestHelper = testutil.NewTestHelper()
|
||||
// Block test execution until control plane is running
|
||||
TestHelper.WaitUntilDeployReady(testutil.LinkerdDeployReplicasEdge)
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
// TestDualStack creates an injected pod that starts two servers, one listening
|
||||
// on the IPv4 wildcard address and serving the string "IPv4", and another
|
||||
// listening on the IPv6 wildcard address and serving the string "IPv6". They
|
||||
// are fronted by a DualStack Service. We test that we can reach those two IPs
|
||||
// directly, and that making a request to the service's FQDN always hits the
|
||||
// IPv6 endpoint.
|
||||
func TestDualStack(t *testing.T) {
|
||||
if !TestHelper.DualStack() {
|
||||
t.Skip("Skipping Skip DualStack test")
|
||||
}
|
||||
|
||||
TestHelper.WithDataPlaneNamespace(context.Background(), "dualstack-test", map[string]string{}, t, func(t *testing.T, ns string) {
|
||||
out, err := TestHelper.Kubectl("",
|
||||
"create", "configmap", "go-app",
|
||||
"--from-file=main.go=testdata/ipfamilies-server.go",
|
||||
"-n", ns,
|
||||
)
|
||||
if err != nil {
|
||||
testutil.AnnotatedFatalf(t, "unexpected error", "unexpected error: %v\noutput:\n%s", err, out)
|
||||
}
|
||||
|
||||
out, err = TestHelper.Kubectl("",
|
||||
"apply", "-f", "testdata/ipfamilies-server-client.yml",
|
||||
"-n", ns,
|
||||
)
|
||||
if err != nil {
|
||||
testutil.AnnotatedFatalf(t, "unexpected error", "unexpected error: %v\noutput:\n%s", err, out)
|
||||
}
|
||||
|
||||
checkPods(t, ns, "ipfamilies-server")
|
||||
checkPods(t, ns, "client")
|
||||
|
||||
var clientIPv6, serverIPv4, serverIPv6 string
|
||||
|
||||
t.Run("Retrieve pod IPs", func(t *testing.T) {
|
||||
cmd := []string{
|
||||
"get", "po",
|
||||
"-o", "jsonpath='{.items[*].status.podIPs}'",
|
||||
"-n", ns,
|
||||
}
|
||||
|
||||
out, err = TestHelper.Kubectl("", append(cmd, "-l", "app=server")...)
|
||||
if err != nil {
|
||||
testutil.AnnotatedFatalf(t, "unexpected error", "unexpected error: %v\noutput:\n%s", err, out)
|
||||
}
|
||||
|
||||
var IPs []IP
|
||||
out = strings.Trim(out, "'")
|
||||
if err = json.Unmarshal([]byte(out), &IPs); err != nil {
|
||||
testutil.AnnotatedFatalf(t, "error unmarshaling JSON", "error unmarshaling JSON '%s': %s", out, err)
|
||||
}
|
||||
if len(IPs) != 2 {
|
||||
testutil.AnnotatedFatalf(t, "unexpected number of IPs", "expected 2 IPs, got %s", fmt.Sprint(len(IPs)))
|
||||
}
|
||||
serverIPv4 = IPs[0].IP
|
||||
serverIPv6 = IPs[1].IP
|
||||
|
||||
out, err = TestHelper.Kubectl("", append(cmd, "-l", "app=client")...)
|
||||
if err != nil {
|
||||
testutil.AnnotatedFatalf(t, "unexpected error", "unexpected error: %v\noutput:\n%s", err, out)
|
||||
}
|
||||
|
||||
out = strings.Trim(out, "'")
|
||||
if err = json.Unmarshal([]byte(out), &IPs); err != nil {
|
||||
testutil.AnnotatedFatalf(t, "error unmarshaling JSON", "error unmarshaling JSON '%s': %s", out, err)
|
||||
}
|
||||
if len(IPs) != 2 {
|
||||
testutil.AnnotatedFatalf(t, "unexpected number of IPs", "expected 2 IPs, got %s", fmt.Sprint(len(IPs)))
|
||||
}
|
||||
clientIPv6 = IPs[1].IP
|
||||
})
|
||||
|
||||
t.Run("Apply policy", func(t *testing.T) {
|
||||
file, err := os.Open("testdata/ipfamilies-policy.yml")
|
||||
if err != nil {
|
||||
testutil.AnnotatedFatalf(t, "unexpected error", "unexpected error: %v", err)
|
||||
}
|
||||
defer file.Close()
|
||||
manifest, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
testutil.AnnotatedFatalf(t, "unexpected error", "unexpected error: %v", err)
|
||||
}
|
||||
in := strings.ReplaceAll(string(manifest), "{IPv6}", clientIPv6)
|
||||
out, err = TestHelper.KubectlApply(in, ns)
|
||||
if err != nil {
|
||||
testutil.AnnotatedFatalf(t, "unexpected error", "unexpected error: %v\noutput:\n%s", err, out)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Hit IPv4 addr directly", func(t *testing.T) {
|
||||
out, err = TestHelper.Kubectl("",
|
||||
"exec", "deploy/client",
|
||||
"-c", "curl",
|
||||
"-n", ns,
|
||||
"--",
|
||||
"curl", "-s", "http://"+serverIPv4+":8080",
|
||||
)
|
||||
if err != nil {
|
||||
testutil.AnnotatedFatalf(t, "unexpected error", "unexpected error: %v\noutput:\n%s", err, out)
|
||||
}
|
||||
if out != "IPv4\n" {
|
||||
testutil.AnnotatedFatalf(t, "unexpected output", "expected 'IPv4', received '%s'", out)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Hit IPv6 addr directly", func(t *testing.T) {
|
||||
out, err = TestHelper.Kubectl("",
|
||||
"exec", "deploy/client",
|
||||
"-c", "curl",
|
||||
"-n", ns,
|
||||
"--",
|
||||
"curl", "-s", "http://["+serverIPv6+"]:8080",
|
||||
)
|
||||
if err != nil {
|
||||
testutil.AnnotatedFatalf(t, "unexpected error", "unexpected error: %v\noutput:\n%s", err, out)
|
||||
}
|
||||
if out != "IPv6\n" {
|
||||
testutil.AnnotatedFatalf(t, "expected 'IPv6', received '%s'", out)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Hit FQDN directly (should always resolve to IPv6)", func(t *testing.T) {
|
||||
for i := 0; i < 10; i++ {
|
||||
out, err = TestHelper.Kubectl("",
|
||||
"exec", "deploy/client",
|
||||
"-c", "curl",
|
||||
"-n", ns,
|
||||
"--",
|
||||
"curl", "-s", "http://ipfamilies-server:8080",
|
||||
)
|
||||
if err != nil {
|
||||
testutil.AnnotatedFatalf(t, "unexpected error", "unexpected error: %v\noutput:\n%s", err, out)
|
||||
}
|
||||
if out != "IPv6\n" {
|
||||
testutil.AnnotatedFatalf(t, "expected 'IPv6', received '%s'", out)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func checkPods(t *testing.T, ns, pod string) {
|
||||
t.Helper()
|
||||
|
||||
if err := TestHelper.CheckPods(context.Background(), ns, pod, 1); err != nil {
|
||||
//nolint:errorlint
|
||||
if rce, ok := err.(*testutil.RestartCountError); ok {
|
||||
testutil.AnnotatedWarn(t, "CheckPods timed-out", rce)
|
||||
} else {
|
||||
testutil.AnnotatedError(t, "CheckPods timed-out", err)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
apiVersion: policy.linkerd.io/v1beta2
|
||||
kind: Server
|
||||
metadata:
|
||||
name: ipfamilies
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: ipfamilies-server
|
||||
port: http
|
||||
proxyProtocol: HTTP/1
|
||||
---
|
||||
apiVersion: policy.linkerd.io/v1alpha1
|
||||
kind: AuthorizationPolicy
|
||||
metadata:
|
||||
name: ipfamilies
|
||||
spec:
|
||||
targetRef:
|
||||
group: policy.linkerd.io
|
||||
kind: Server
|
||||
name: ipfamilies
|
||||
requiredAuthenticationRefs:
|
||||
- name: ipfamilies
|
||||
kind: NetworkAuthentication
|
||||
group: policy.linkerd.io
|
||||
---
|
||||
apiVersion: policy.linkerd.io/v1alpha1
|
||||
kind: NetworkAuthentication
|
||||
metadata:
|
||||
name: ipfamilies
|
||||
spec:
|
||||
networks:
|
||||
- cidr: {IPv6}/128
|
|
@ -0,0 +1,73 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: ipfamilies-server
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: server
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
linkerd.io/inject: enabled
|
||||
labels:
|
||||
app: server
|
||||
spec:
|
||||
containers:
|
||||
- image: ghcr.io/alpeb/family-server:v1
|
||||
image: golang:1.22-alpine
|
||||
name: ipfamilies-server
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
name: http
|
||||
protocol: TCP
|
||||
command: ["/bin/sh"]
|
||||
args:
|
||||
- -c
|
||||
- 'go run /go/src/app/main.go'
|
||||
volumeMounts:
|
||||
- name: go-app
|
||||
mountPath: /go/src/app
|
||||
volumes:
|
||||
- name: go-app
|
||||
configMap:
|
||||
name: go-app
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: ipfamilies-server
|
||||
spec:
|
||||
ipFamilies:
|
||||
- IPv4
|
||||
- IPv6
|
||||
ipFamilyPolicy: RequireDualStack
|
||||
ports:
|
||||
- name: http
|
||||
port: 8080
|
||||
protocol: TCP
|
||||
targetPort: http
|
||||
selector:
|
||||
app: server
|
||||
type: ClusterIP
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: client
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: client
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
linkerd.io/inject: enabled
|
||||
labels:
|
||||
app: client
|
||||
spec:
|
||||
containers:
|
||||
- name: curl
|
||||
image: curlimages/curl
|
||||
command: [ "sh", "-c", "--" ]
|
||||
args: [ "sleep infinity" ]
|
|
@ -0,0 +1,41 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type (
|
||||
ipv4Handler struct{}
|
||||
ipv6Handler struct{}
|
||||
)
|
||||
|
||||
func (ipv4Handler) ServeHTTP(w http.ResponseWriter, _ *http.Request) {
|
||||
fmt.Fprintf(w, "IPv4\n")
|
||||
}
|
||||
|
||||
func (ipv6Handler) ServeHTTP(w http.ResponseWriter, _ *http.Request) {
|
||||
fmt.Fprintf(w, "IPv6\n")
|
||||
}
|
||||
|
||||
func main() {
|
||||
log.Print("Server started")
|
||||
|
||||
go func() {
|
||||
ln, err := net.Listen("tcp4", "0.0.0.0:8080")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
srv := &http.Server{Handler: ipv4Handler{}}
|
||||
log.Fatal(srv.Serve(ln))
|
||||
}()
|
||||
|
||||
ln, err := net.Listen("tcp6", "[::]:8080")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
srv := &http.Server{Handler: ipv6Handler{}}
|
||||
log.Fatal(srv.Serve(ln))
|
||||
}
|
|
@ -108,7 +108,7 @@ func createTestCaseTable(controlNs, endpointNs string) []testCase {
|
|||
expectedRE: `\[
|
||||
\{
|
||||
"namespace": "(\S*)",
|
||||
"ip": "\d+\.\d+\.\d+\.\d+",
|
||||
"ip": "[a-f0-9.:]+",
|
||||
"port": 8086,
|
||||
"pod": "linkerd-destination\-[a-f0-9]+\-[a-z0-9]+",
|
||||
"service": "linkerd-dst\.\S*",
|
||||
|
@ -125,7 +125,7 @@ func createTestCaseTable(controlNs, endpointNs string) []testCase {
|
|||
expectedRE: `\[
|
||||
\{
|
||||
"namespace": "(\S*)",
|
||||
"ip": "\d+\.\d+\.\d+\.\d+",
|
||||
"ip": "[a-f0-9.:]+",
|
||||
"port": 8080,
|
||||
"pod": "linkerd-identity\-[a-f0-9]+\-[a-z0-9]+",
|
||||
"service": "linkerd-identity\.\S*",
|
||||
|
@ -142,7 +142,7 @@ func createTestCaseTable(controlNs, endpointNs string) []testCase {
|
|||
expectedRE: `\[
|
||||
\{
|
||||
"namespace": "(\S*)",
|
||||
"ip": "\d+\.\d+\.\d+\.\d+",
|
||||
"ip": "[a-f0-9.:]+",
|
||||
"port": 8443,
|
||||
"pod": "linkerd-proxy-injector-[a-f0-9]+\-[a-z0-9]+",
|
||||
"service": "linkerd-proxy-injector\.\S*",
|
||||
|
@ -159,7 +159,7 @@ func createTestCaseTable(controlNs, endpointNs string) []testCase {
|
|||
expectedRE: `\[
|
||||
\{
|
||||
"namespace": "(\S*)",
|
||||
"ip": "\d+\.\d+\.\d+\.\d+",
|
||||
"ip": "[a-f0-9.:]+",
|
||||
"port": 8080,
|
||||
"pod": "nginx-[a-f0-9]+\-[a-z0-9]+",
|
||||
"service": "nginx\.\S*",
|
||||
|
|
|
@ -126,6 +126,10 @@ func TestInstall(t *testing.T) {
|
|||
cmd = append(cmd, "--set", "proxy.nativeSidecar=true")
|
||||
}
|
||||
|
||||
if TestHelper.DualStack() {
|
||||
cmd = append(cmd, "--set", "disableIPv6=false")
|
||||
}
|
||||
|
||||
// Pipe cmd & args to `linkerd`
|
||||
out, err = TestHelper.LinkerdRun(cmd...)
|
||||
if err != nil {
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
kind: Cluster
|
||||
apiVersion: kind.x-k8s.io/v1alpha4
|
||||
networking:
|
||||
ipFamily: dual
|
|
@ -0,0 +1,4 @@
|
|||
kind: Cluster
|
||||
apiVersion: kind.x-k8s.io/v1alpha4
|
||||
networking:
|
||||
ipFamily: ipv6
|
|
@ -3,6 +3,7 @@ package localhost
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/netip"
|
||||
"os"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
@ -163,7 +164,16 @@ func TestLocalhostRouting(t *testing.T) {
|
|||
testutil.AnnotatedFatalf(t, "unexpected error", "unexpected error: no IP address found for %s/%s", ns, podName)
|
||||
}
|
||||
|
||||
statusCode, err := TestHelper.Kubectl("", append(execCommand, podIP)...)
|
||||
addr, err := netip.ParseAddr(podIP)
|
||||
if err != nil {
|
||||
testutil.AnnotatedFatalf(t, "Invalid IP", "Invalid IP '%s': %s", podIP, err)
|
||||
}
|
||||
if addr.Is6() {
|
||||
podIP = fmt.Sprintf("[%s]", podIP)
|
||||
}
|
||||
url := fmt.Sprintf("http://%s:80", podIP)
|
||||
|
||||
statusCode, err := TestHelper.Kubectl("", append(execCommand, url)...)
|
||||
if err != nil {
|
||||
testutil.AnnotatedFatalf(t, "unexpected error received when calling 'kubectl exec'", "unexpected error received when calling 'kubectl exec': %v", err)
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ spec:
|
|||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.14.2
|
||||
image: nginx:1.25.5
|
||||
ports:
|
||||
- containerPort: 80
|
||||
- name: curl
|
||||
|
|
|
@ -14,8 +14,8 @@ import (
|
|||
var TestHelper *testutil.TestHelper
|
||||
|
||||
var (
|
||||
skipPortsNs = "skip-ports-test"
|
||||
booksappDeployments = []string{"books", "traffic", "authors", "webapp"}
|
||||
skipPortsNs = "skip-ports-test"
|
||||
emojivotoDeployments = []string{"emoji", "vote-bot", "voting", "web"}
|
||||
)
|
||||
|
||||
func secureRequestMatcher(dst string) *prommatch.Matcher {
|
||||
|
@ -65,8 +65,8 @@ func TestSkipInboundPorts(t *testing.T) {
|
|||
"'kubectl apply' command failed\n%s", out)
|
||||
}
|
||||
|
||||
// Check all booksapp deployments are up and running
|
||||
for _, deploy := range booksappDeployments {
|
||||
// Check all emojivoto deployments are up and running
|
||||
for _, deploy := range emojivotoDeployments {
|
||||
if err := TestHelper.CheckPods(ctx, ns, deploy, 1); err != nil {
|
||||
//nolint:errorlint
|
||||
if rce, ok := err.(*testutil.RestartCountError); ok {
|
||||
|
@ -81,7 +81,7 @@ func TestSkipInboundPorts(t *testing.T) {
|
|||
// Wait for slow-cookers to start sending requests by using a short
|
||||
// time window through RetryFor.
|
||||
err := testutil.RetryFor(30*time.Second, func() error {
|
||||
pods, err := TestHelper.GetPods(ctx, ns, map[string]string{"app": "webapp"})
|
||||
pods, err := TestHelper.GetPods(ctx, ns, map[string]string{"app": "web-svc"})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting pods\n%w", err)
|
||||
}
|
||||
|
@ -94,10 +94,10 @@ func TestSkipInboundPorts(t *testing.T) {
|
|||
return fmt.Errorf("error getting metrics for pod\n%w", err)
|
||||
}
|
||||
s := prommatch.Suite{}.
|
||||
MustContain("secure requests to authors", secureRequestMatcher("authors")).
|
||||
MustContain("insecure requests to books", insecureRequestMatcher("books")).
|
||||
MustNotContain("insecure requests to authors", insecureRequestMatcher("authors")).
|
||||
MustNotContain("secure requests to books", secureRequestMatcher("books"))
|
||||
MustContain("secure requests to emoji-svc", secureRequestMatcher("emoji-svc")).
|
||||
MustContain("insecure requests to voting-svc", insecureRequestMatcher("voting-svc")).
|
||||
MustNotContain("insecure requests to emoji-svc", insecureRequestMatcher("emoji-svc")).
|
||||
MustNotContain("secure requests to voting-svc", secureRequestMatcher("voting-svc"))
|
||||
if err := s.CheckString(metrics); err != nil {
|
||||
return fmt.Errorf("error matching metrics\n%w", err)
|
||||
}
|
||||
|
|
|
@ -1,191 +1,207 @@
|
|||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: emoji
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: voting
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: web
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: webapp
|
||||
labels:
|
||||
app: webapp
|
||||
project: booksapp
|
||||
name: emoji-svc
|
||||
spec:
|
||||
ports:
|
||||
- name: grpc
|
||||
port: 8080
|
||||
targetPort: 8080
|
||||
- name: prom
|
||||
port: 8801
|
||||
targetPort: 8801
|
||||
selector:
|
||||
app: webapp
|
||||
app: emoji-svc
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: voting-svc
|
||||
spec:
|
||||
ports:
|
||||
- name: grpc
|
||||
port: 8080
|
||||
targetPort: 8080
|
||||
- name: prom
|
||||
port: 8801
|
||||
targetPort: 8801
|
||||
selector:
|
||||
app: voting-svc
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: web-svc
|
||||
spec:
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
targetPort: 8080
|
||||
selector:
|
||||
app: web-svc
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- name: service
|
||||
port: 7000
|
||||
---
|
||||
kind: Deployment
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: webapp
|
||||
labels:
|
||||
app: webapp
|
||||
project: booksapp
|
||||
app.kubernetes.io/part-of: booksapp
|
||||
app.kubernetes.io/name: emoji
|
||||
app.kubernetes.io/part-of: emojivoto
|
||||
app.kubernetes.io/version: v11
|
||||
name: emoji
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: webapp
|
||||
project: booksapp
|
||||
app: emoji-svc
|
||||
version: v11
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: webapp
|
||||
project: booksapp
|
||||
app: emoji-svc
|
||||
version: v11
|
||||
spec:
|
||||
dnsPolicy: ClusterFirst
|
||||
containers:
|
||||
- name: service
|
||||
image: buoyantio/booksapp:v0.0.5
|
||||
env:
|
||||
- name: DATABASE_URL
|
||||
value: sqlite3:db/db.sqlite3
|
||||
- name: AUTHORS_SITE
|
||||
value: http://authors:7001
|
||||
- name: BOOKS_SITE
|
||||
value: http://books:7002
|
||||
args: ["prod:webapp"]
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /ping
|
||||
port: 7000
|
||||
- env:
|
||||
- name: GRPC_PORT
|
||||
value: "8080"
|
||||
- name: PROM_PORT
|
||||
value: "8801"
|
||||
image: docker.l5d.io/buoyantio/emojivoto-emoji-svc:v11
|
||||
name: emoji-svc
|
||||
ports:
|
||||
- name: service
|
||||
containerPort: 7000
|
||||
- containerPort: 8080
|
||||
name: grpc
|
||||
- containerPort: 8801
|
||||
name: prom
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
serviceAccountName: emoji
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: authors
|
||||
labels:
|
||||
app: authors
|
||||
project: booksapp
|
||||
spec:
|
||||
selector:
|
||||
app: authors
|
||||
ports:
|
||||
- name: service
|
||||
port: 7001
|
||||
---
|
||||
kind: Deployment
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: authors
|
||||
labels:
|
||||
app: authors
|
||||
project: booksapp
|
||||
app.kubernetes.io/part-of: booksapp
|
||||
app.kubernetes.io/name: vote-bot
|
||||
app.kubernetes.io/part-of: emojivoto
|
||||
app.kubernetes.io/version: v11
|
||||
name: vote-bot
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: authors
|
||||
project: booksapp
|
||||
app: vote-bot
|
||||
version: v11
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: authors
|
||||
project: booksapp
|
||||
app: vote-bot
|
||||
version: v11
|
||||
spec:
|
||||
dnsPolicy: ClusterFirst
|
||||
containers:
|
||||
- name: service
|
||||
image: buoyantio/booksapp:v0.0.5
|
||||
- command:
|
||||
- emojivoto-vote-bot
|
||||
env:
|
||||
- name: DATABASE_URL
|
||||
value: sqlite3:db/db.sqlite3
|
||||
- name: BOOKS_SITE
|
||||
value: http://books:7002
|
||||
- name: FAILURE_RATE
|
||||
value: "0.0"
|
||||
args: ["prod:authors"]
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /ping
|
||||
port: 7001
|
||||
ports:
|
||||
- name: service
|
||||
containerPort: 7001
|
||||
- name: WEB_HOST
|
||||
value: web-svc:80
|
||||
image: docker.l5d.io/buoyantio/emojivoto-web:v11
|
||||
name: vote-bot
|
||||
resources:
|
||||
requests:
|
||||
cpu: 10m
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: books
|
||||
labels:
|
||||
app: books
|
||||
project: booksapp
|
||||
spec:
|
||||
selector:
|
||||
app: books
|
||||
ports:
|
||||
- name: service
|
||||
port: 7002
|
||||
---
|
||||
kind: Deployment
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: books
|
||||
labels:
|
||||
app: books
|
||||
project: booksapp
|
||||
app.kubernetes.io/part-of: booksapp
|
||||
app.kubernetes.io/name: voting
|
||||
app.kubernetes.io/part-of: emojivoto
|
||||
app.kubernetes.io/version: v11
|
||||
name: voting
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: books
|
||||
project: booksapp
|
||||
app: voting-svc
|
||||
version: v11
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
config.linkerd.io/skip-inbound-ports: "7002"
|
||||
config.linkerd.io/skip-inbound-ports: "8080"
|
||||
labels:
|
||||
app: books
|
||||
project: booksapp
|
||||
app: voting-svc
|
||||
version: v11
|
||||
spec:
|
||||
dnsPolicy: ClusterFirst
|
||||
containers:
|
||||
- name: service
|
||||
image: buoyantio/booksapp:v0.0.5
|
||||
env:
|
||||
- name: DATABASE_URL
|
||||
value: sqlite3:db/db.sqlite3
|
||||
- name: AUTHORS_SITE
|
||||
value: http://authors:7001
|
||||
args: ["prod:books"]
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /ping
|
||||
port: 7002
|
||||
- env:
|
||||
- name: GRPC_PORT
|
||||
value: "8080"
|
||||
- name: PROM_PORT
|
||||
value: "8801"
|
||||
image: docker.l5d.io/buoyantio/emojivoto-voting-svc:v11
|
||||
name: voting-svc
|
||||
ports:
|
||||
- name: service
|
||||
containerPort: 7002
|
||||
- containerPort: 8080
|
||||
name: grpc
|
||||
- containerPort: 8801
|
||||
name: prom
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
serviceAccountName: voting
|
||||
---
|
||||
kind: Deployment
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: traffic
|
||||
labels:
|
||||
app: traffic
|
||||
project: booksapp
|
||||
app.kubernetes.io/part-of: booksapp
|
||||
app.kubernetes.io/name: web
|
||||
app.kubernetes.io/part-of: emojivoto
|
||||
app.kubernetes.io/version: v11
|
||||
name: web
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: traffic
|
||||
project: booksapp
|
||||
app: web-svc
|
||||
version: v11
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: traffic
|
||||
project: booksapp
|
||||
app: web-svc
|
||||
version: v11
|
||||
spec:
|
||||
dnsPolicy: ClusterFirst
|
||||
containers:
|
||||
- name: traffic
|
||||
image: buoyantio/booksapp-traffic:v0.0.3
|
||||
args:
|
||||
- "-initial-delay=30s"
|
||||
- "webapp:7000"
|
||||
- env:
|
||||
- name: WEB_PORT
|
||||
value: "8080"
|
||||
- name: EMOJISVC_HOST
|
||||
value: emoji-svc:8080
|
||||
- name: VOTINGSVC_HOST
|
||||
value: voting-svc:8080
|
||||
- name: INDEX_BUNDLE
|
||||
value: dist/index_bundle.js
|
||||
image: docker.l5d.io/buoyantio/emojivoto-web:v11
|
||||
name: web-svc
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
name: http
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
serviceAccountName: web
|
||||
|
|
|
@ -38,6 +38,7 @@ type TestHelper struct {
|
|||
uninstall bool
|
||||
cni bool
|
||||
calico bool
|
||||
dualStack bool
|
||||
nativeSidecar bool
|
||||
defaultInboundPolicy string
|
||||
httpClient http.Client
|
||||
|
@ -208,6 +209,7 @@ func NewTestHelper() *TestHelper {
|
|||
uninstall := flag.Bool("uninstall", false, "whether to run the 'linkerd uninstall' integration test")
|
||||
cni := flag.Bool("cni", false, "whether to install linkerd with CNI enabled")
|
||||
calico := flag.Bool("calico", false, "whether to install calico CNI plugin")
|
||||
dualStack := flag.Bool("dual-stack", false, "whether to run the dual-stack tests")
|
||||
nativeSidecar := flag.Bool("native-sidecar", false, "whether to install using native sidecar injection")
|
||||
defaultInboundPolicy := flag.String("default-inbound-policy", "", "if non-empty, passed to --set proxy.defaultInboundPolicy at linkerd's install time")
|
||||
flag.Parse()
|
||||
|
@ -254,6 +256,7 @@ func NewTestHelper() *TestHelper {
|
|||
externalPrometheus: *externalPrometheus,
|
||||
cni: *cni,
|
||||
calico: *calico,
|
||||
dualStack: *dualStack,
|
||||
nativeSidecar: *nativeSidecar,
|
||||
uninstall: *uninstall,
|
||||
defaultInboundPolicy: *defaultInboundPolicy,
|
||||
|
@ -399,6 +402,11 @@ func (h *TestHelper) Calico() bool {
|
|||
return h.calico
|
||||
}
|
||||
|
||||
// DualStack determines whether the DualStack tests are run
|
||||
func (h *TestHelper) DualStack() bool {
|
||||
return h.dualStack
|
||||
}
|
||||
|
||||
// NativeSidecar determines whether native sidecar injection is enabled
|
||||
func (h *TestHelper) NativeSidecar() bool {
|
||||
return h.nativeSidecar
|
||||
|
|
Loading…
Reference in New Issue