Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ jobs:
- default-policy-deny
- external
- rsa-ca
- tracing
- helm-upgrade
- uninstall
- upgrade-edge
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ jobs:
- cni-calico-deep
- deep
- viz
- tracing
- default-policy-deny
- external
- rsa-ca
Expand Down
6 changes: 5 additions & 1 deletion bin/_test-helpers.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ testdir=$bindir/../test/integration

##### Test setup helpers #####

export default_test_names=(deep deep-native-sidecar viz external helm-upgrade uninstall upgrade-edge default-policy-deny rsa-ca)
export default_test_names=(deep deep-native-sidecar viz tracing external helm-upgrade uninstall upgrade-edge default-policy-deny rsa-ca)
export external_resource_test_names=(external-resources)
# TODO(alpeb): add test cni-calico-deep-dual-stack
export dual_stack_test_names=(deep-dual-stack)
Expand Down Expand Up @@ -473,6 +473,10 @@ run_rsa-ca_test() {
run_test "$testdir/rsa-ca/..."
}

run_tracing_test() {
run_test "$testdir/tracing/..."
}

run_external_test() {
run_test "$testdir/external/..."
}
Expand Down
80 changes: 80 additions & 0 deletions test/integration/tracing/install_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package deeptest

import (
"fmt"
"os"
"testing"

"github.com/linkerd/linkerd2/testutil"
)

//////////////////////
/// TEST SETUP ///
//////////////////////

var (
TestHelper *testutil.TestHelper
)

func TestMain(m *testing.M) {
TestHelper = testutil.NewTestHelper()
os.Exit(m.Run())
}

// TestInstall will install the linkerd control plane to be used in the rest of
// the tracing suite tests.
func TestInstall(t *testing.T) {
err := TestHelper.InstallGatewayAPI()
if err != nil {
testutil.AnnotatedFatal(t, "failed to install gateway-api", err)
}

// Install CRDs
cmd := []string{
"install",
"--crds",
"--controller-log-level", "debug",
"--set", fmt.Sprintf("proxy.image.version=%s", TestHelper.GetVersion()),
"--set", "heartbeatSchedule=1 2 3 4 5",
"--values", "testdata/tracing-values.yaml",
}

// Pipe cmd & args to `linkerd`
out, err := TestHelper.LinkerdRun(cmd...)
if err != nil {
testutil.AnnotatedFatal(t, "'linkerd install' command failed", err)
}

out, err = TestHelper.KubectlApplyWithArgs(out)
if err != nil {
testutil.AnnotatedFatalf(t, "'kubectl apply' command failed",
"'kubectl apply' command failed\n%s", out)
}

// Install control-plane
cmd = []string{
"install",
"--controller-log-level", "debug",
"--set", fmt.Sprintf("proxy.image.version=%s", TestHelper.GetVersion()),
"--set", "heartbeatSchedule=1 2 3 4 5",
"--values", "testdata/tracing-values.yaml",
}

// Pipe cmd & args to `linkerd`
out, err = TestHelper.LinkerdRun(cmd...)
if err != nil {
testutil.AnnotatedFatal(t, "'linkerd install' command failed", err)
}

out, err = TestHelper.KubectlApplyWithArgs(out)
if err != nil {
testutil.AnnotatedFatalf(t, "'kubectl apply' command failed",
"'kubectl apply' command failed\n%s", out)
}

out, err = TestHelper.LinkerdRun("check", "--wait=3m")
if err != nil {
testutil.AnnotatedFatalf(t, "'linkerd check' command failed",
"'linkerd check' command failed\n%s", out)
}
}
7 changes: 7 additions & 0 deletions test/integration/tracing/testdata/tracing-values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
proxy:
tracing:
enable: true
collector:
endpoint: otel-collector-opentelemetry-collector.tracing:4317
meshIdentity:
serviceAccountName: otel-collector-opentelemetry-collector.tracing
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
apiVersion: v1
kind: Namespace
metadata:
name: tracing-test
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: emoji
Expand Down
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably pin the jaeger and otel collector versions in the test values files, not sure if there's a way to make dependabot pick those up when they're not in the usual places (lockfiles, etc.).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that we should pin versions for reproducibility. Even if dependabot doesn't know about them and we have to bump them manually whenever we want to test against a new version of the tracing architecture.

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
provisionDataStore:
cassandra: false
allInOne:
enabled: true
storage:
type: memory
agent:
enabled: false
collector:
enabled: false
query:
enabled: false
18 changes: 18 additions & 0 deletions test/integration/tracing/tracing/testdata/otel-values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
mode: deployment
image:
repository: ghcr.io/open-telemetry/opentelemetry-collector-releases/opentelemetry-collector-k8s
command:
name: otelcol-k8s
config:
exporters:
debug: { }
otlp/jaeger:
endpoint: http://jaeger-collector.tracing:4317
tls:
insecure: true
service:
pipelines:
traces:
exporters:
- debug
- otlp/jaeger
6 changes: 6 additions & 0 deletions test/integration/tracing/tracing/testdata/tracing.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: v1
kind: Namespace
metadata:
name: tracing
annotations:
linkerd.io/inject: enabled
162 changes: 162 additions & 0 deletions test/integration/tracing/tracing/tracing_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
package tracing

import (
"context"
"encoding/json"
"errors"
"fmt"
"os"
"testing"
"time"

"github.com/linkerd/linkerd2/testutil"
)

type (
traces struct {
Data []trace `json:"data"`
}

trace struct {
Processes map[string]process `json:"processes"`
}

process struct {
ServiceName string `json:"serviceName"`
}
)

//////////////////////
/// TEST SETUP ///
//////////////////////

var TestHelper *testutil.TestHelper

func TestMain(m *testing.M) {
TestHelper = testutil.NewTestHelper()
// Block test execution until viz extension is running
TestHelper.WaitUntilDeployReady(testutil.LinkerdDeployReplicasEdge)
os.Exit(m.Run())
}

//////////////////////
/// TEST EXECUTION ///
//////////////////////

func TestTracing(t *testing.T) {
ctx := context.Background()

tracingNs := "tracing"
installTracing(t, tracingNs)

TestHelper.WithDataPlaneNamespace(ctx, "tracing-test", map[string]string{}, t, func(t *testing.T, namespace string) {
emojivotoYaml, err := testutil.ReadFile("testdata/emojivoto.yaml")
if err != nil {
testutil.AnnotatedFatalf(t, "failed to read emojivoto yaml",
"failed to read emojivoto yaml\n%s\n", err)
}

out, err := TestHelper.KubectlApply(emojivotoYaml, namespace)
if err != nil {
testutil.AnnotatedFatalf(t, "'kubectl apply' command failed",
"'kubectl apply' command failed\n%s", out)
}

// wait for deployments to start
for _, deploy := range []struct {
ns string
name string
}{
{ns: namespace, name: "vote-bot"},
{ns: namespace, name: "web"},
{ns: namespace, name: "emoji"},
{ns: namespace, name: "voting"},
{ns: tracingNs, name: "otel-collector-opentelemetry-collector"},
{ns: tracingNs, name: "jaeger"},
} {
if err := TestHelper.CheckPods(ctx, deploy.ns, deploy.name, 1); err != nil {
var rce *testutil.RestartCountError
if errors.As(err, &rce) {
testutil.AnnotatedWarn(t, "CheckPods timed-out", rce)
}
}
}

t.Run("expect full trace", func(t *testing.T) {
timeout := 1 * time.Minute
err = testutil.RetryFor(timeout, func() error {
url, err := TestHelper.URLFor(ctx, tracingNs, "jaeger", 16686)
if err != nil {
return err
}

tracesJSON, err := TestHelper.HTTPGetURL(url + "/api/traces?lookback=1h&service=linkerd-proxy")
if err != nil {
return err
}
traces := traces{}

err = json.Unmarshal([]byte(tracesJSON), &traces)
if err != nil {
return err
}

if !hasTraceWithProcess(&traces, "linkerd-proxy") {
return noProxyTraceFound{}
}
return nil
})
if err != nil {
testutil.AnnotatedFatal(t, fmt.Sprintf("timed-out checking trace (%s)", timeout), err)
}
})
})
}

func installTracing(t *testing.T, namespace string) {
tracingYaml, err := testutil.ReadFile("testdata/tracing.yaml")
if err != nil {
testutil.AnnotatedFatalf(t, "failed to read tracing yaml",
"failed to read emojivoto yaml\n%s\n", err)
}

out, err := TestHelper.KubectlApply(tracingYaml, namespace)
if err != nil {
testutil.AnnotatedFatalf(t, "'kubectl apply' command failed",
"'kubectl apply' command failed\n%s", out)
}

stdout, stderr, err := TestHelper.HelmRun("repo", "add", "jaegertracing", "https://jaegertracing.github.io/helm-charts")
if err != nil {
testutil.AnnotatedFatalf(t, "failed to add jaeger repository", "failed to add jaeger repository\n%s\n------\n%s\n", stdout, stderr)
}
stdout, stderr, err = TestHelper.HelmRun("repo", "add", "open-telemetry", "https://open-telemetry.github.io/opentelemetry-helm-charts")
if err != nil {
testutil.AnnotatedFatalf(t, "failed to add OpenTelemetry repository", "failed to add OpenTelemetry repository\n%s\n------\n%s\n", stdout, stderr)
}
stdout, stderr, err = TestHelper.HelmRun("install", "jaeger", "jaegertracing/jaeger", "--namespace=tracing", "--values=testdata/jaeger-aio-values.yaml")
if err != nil {
testutil.AnnotatedFatalf(t, "failed to install jaeger", "failed to install jaeger\n%s\n------\n%s\n", stdout, stderr)
}
stdout, stderr, err = TestHelper.HelmRun("install", "otel-collector", "open-telemetry/opentelemetry-collector", "--namespace=tracing", "--values=testdata/otel-values.yaml")
if err != nil {
testutil.AnnotatedFatalf(t, "failed to install OpenTelemetry", "failed to install OpenTelemetry\n%s\n------\n%s\n", stdout, stderr)
}
}

func hasTraceWithProcess(traces *traces, ps string) bool {
for _, trace := range traces.Data {
for _, process := range trace.Processes {
if process.ServiceName == ps {
return true
}
}
}
return false
}

type noProxyTraceFound struct{}

func (e noProxyTraceFound) Error() string {
return "no trace found with processes: linkerd-proxy"
}
12 changes: 0 additions & 12 deletions test/integration/viz/tracing/testdata/check.jaeger.golden

This file was deleted.

Loading