Skip to content

Commit 9b6ed46

Browse files
authored
Merge pull request #16 from jackshirazi/edot-agents-integration
Integration test for EDOT agents with operator, plus skeleton for collector
2 parents a9630d4 + 783dfcb commit 9b6ed46

21 files changed

+382
-0
lines changed
+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
name: Regression Testing Operator Integration
2+
3+
on:
4+
workflow_dispatch:
5+
6+
env:
7+
AGENT_TESTS: python nodejs java
8+
#go dotnet --- both pending
9+
10+
jobs:
11+
integration-test:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- name: Checkout
15+
uses: actions/checkout@v4
16+
with:
17+
fetch-depth: 0
18+
19+
- name: Create Kind cluster and local Docker registry
20+
run:
21+
bash test/operator/kind-with-registry.sh
22+
23+
- name: Create Test Images
24+
run: |
25+
for t in ${AGENT_TESTS[@]}
26+
do
27+
echo "Creating image for $t"
28+
docker build -t $t-test-app test/operator/$t
29+
docker tag $t-test-app localhost:5001/registry/$t-test-app
30+
docker push localhost:5001/registry/$t-test-app
31+
done
32+
33+
- name: Set up Helm
34+
uses: azure/setup-helm@v4
35+
with:
36+
version: v3.11.2
37+
38+
- name: Install Operator Skeleton
39+
run: |
40+
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.15.3/cert-manager.yaml
41+
bash test/operator/wait_for_pod_start.sh cert-manager cert-manager- 1/1 3
42+
helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts
43+
helm repo update
44+
helm install opentelemetry-operator --namespace opentelemetry-operator-system open-telemetry/opentelemetry-operator --create-namespace --set manager.collectorImage.repository="docker.elastic.co/beats/elastic-agent:8.15.0-SNAPSHOT",manager.extraArgs={"--enable-go-instrumentation=true"}
45+
bash test/operator/wait_for_pod_start.sh opentelemetry-operator-system opentelemetry-operator 2/2 1
46+
kubectl get pods -A
47+
48+
- name: Add Namespaces And Instrumentation Skeleton
49+
run: |
50+
kubectl create namespace banana
51+
kubectl create -f test/operator/elastic-instrumentation.yml
52+
53+
- name: Start And Test Collector Skeleton
54+
run: |
55+
echo "Nothing here yet"
56+
57+
- name: Start Test Images
58+
run: |
59+
for t in ${AGENT_TESTS[@]}
60+
do
61+
if [ "x$t" = "xgo" ]; then CONTAINER_READY="2/2"; else CONTAINER_READY="1/1"; fi
62+
AGENT_START_GREP=`grep -A1 AGENT_HAS_STARTED_IF_YOU_SEE test/operator/$t/test-app.yaml | perl -ne '/value:\s*"(.*)"/ && print "$1\n"'`
63+
echo "Starting pod for $t"
64+
kubectl create -f test/operator/$t/test-app.yaml
65+
bash test/operator/wait_for_pod_start.sh banana $t-test-app $CONTAINER_READY 1
66+
bash test/operator/wait_for_agent_start.sh banana $t-test-app "$AGENT_START_GREP"
67+
kubectl delete -f test/operator/$t/test-app.yaml
68+
done

test/operator/dotnet/Dockerfile

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# https://hub.docker.com/_/microsoft-dotnet
2+
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
3+
WORKDIR /source
4+
5+
# copy csproj and restore as distinct layers
6+
COPY *.csproj .
7+
RUN dotnet restore
8+
9+
# copy everything else and build app
10+
COPY . .
11+
RUN dotnet publish -c release -o /app --no-restore
12+
13+
# final stage/image
14+
FROM mcr.microsoft.com/dotnet/aspnet:8.0
15+
WORKDIR /app
16+
COPY --from=build /app ./
17+
ENTRYPOINT ["dotnet", "dotnetapp.dll"]

test/operator/dotnet/Program.cs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
var builder = WebApplication.CreateBuilder(args);
2+
_ = builder.Logging.SetMinimumLevel(LogLevel.Trace);
3+
var app = builder.Build();
4+
5+
app.MapGet("/", () => "Hello World!");
6+
7+
app.Run();

test/operator/dotnet/dotnetapp.csproj

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
</PropertyGroup>
8+
9+
</Project>

test/operator/dotnet/test-app.yaml

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
apiVersion: v1
2+
kind: Pod
3+
metadata:
4+
name: dotnet-test-app
5+
namespace: banana
6+
annotations:
7+
instrumentation.opentelemetry.io/inject-dotnet: "opentelemetry-operator-system/elastic-instrumentation"
8+
labels:
9+
app: dotnet-test-app
10+
spec:
11+
containers:
12+
- image: localhost:5001/registry/dotnet-test-app
13+
imagePullPolicy: Always
14+
name: dotnet-test-app
15+
env:
16+
- name: OTEL_LOG_LEVEL
17+
value: "debug"
18+
- name: ELASTIC_OTEL_LOG_TARGETS
19+
value: "stdout"
20+
- name: AGENT_HAS_STARTED_IF_YOU_SEE
21+
value: "Elastic Distribution of OpenTelemetry .NET"
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
apiVersion: opentelemetry.io/v1alpha1
2+
kind: Instrumentation
3+
metadata:
4+
name: elastic-instrumentation
5+
namespace: opentelemetry-operator-system
6+
spec:
7+
exporter:
8+
endpoint: http://opentelemetry-kube-stack-daemon-collector:4318
9+
propagators:
10+
- tracecontext
11+
- baggage
12+
- b3
13+
sampler:
14+
type: parentbased_traceidratio
15+
argument: "1.0"
16+
java:
17+
image: docker.elastic.co/observability/elastic-otel-javaagent:1.0.0
18+
nodejs:
19+
image: docker.elastic.co/observability/elastic-otel-node:edge
20+
dotnet:
21+
image: docker.elastic.co/observability/elastic-otel-dotnet:edge
22+
python:
23+
image: docker.elastic.co/observability/elastic-otel-python:edge
24+
go:
25+
image: ghcr.io/open-telemetry/opentelemetry-go-instrumentation/autoinstrumentation-go:v0.14.0-alpha

test/operator/go/Dockerfile

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#dummy implementation for now
2+
FROM busybox
3+
CMD ["bash", "-c", "sleep", "6000"]

test/operator/go/test-app.yaml

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
apiVersion: v1
2+
kind: Pod
3+
metadata:
4+
name: go-test-app
5+
namespace: banana
6+
annotations:
7+
instrumentation.opentelemetry.io/inject-go: "opentelemetry-operator-system/elastic-instrumentation"
8+
instrumentation.opentelemetry.io/otel-go-auto-target-exe: "/usr/src/app/productcatalogservice"
9+
sidecar.opentelemetry.io/inject: "true"
10+
labels:
11+
app: go-test-app
12+
spec:
13+
shareProcessNamespace: true
14+
containers:
15+
- image: ghcr.io/open-telemetry/opentelemetry-operator/e2e-test-app-golang:main
16+
imagePullPolicy: Always
17+
name: go-test-app
18+
env:
19+
- name: OTEL_LOG_LEVEL
20+
value: "debug"
21+
- name: AGENT_HAS_STARTED_IF_YOU_SEE
22+
value: "no idea"
23+
securityContext:
24+
runAsUser: 0
25+
privileged: true

test/operator/java/Dockerfile

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
FROM eclipse-temurin:17
2+
COPY Hello.java /usr/src/Hello.java
3+
CMD ["java", "/usr/src/Hello.java"]

test/operator/java/Hello.java

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
public class Hello{
2+
public static void main(String[] args) throws Exception {
3+
System.out.println("This is java app in a container");
4+
for(;;) {
5+
Thread.sleep(2000L);
6+
test();
7+
}
8+
}
9+
public static void test() {
10+
System.out.println("Executing test()");
11+
}
12+
}

test/operator/java/test-app.yaml

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
apiVersion: v1
2+
kind: Pod
3+
metadata:
4+
name: java-test-app
5+
namespace: banana
6+
annotations:
7+
instrumentation.opentelemetry.io/inject-java: "opentelemetry-operator-system/elastic-instrumentation"
8+
labels:
9+
app: java-test-app
10+
spec:
11+
containers:
12+
- image: localhost:5001/registry/java-test-app
13+
imagePullPolicy: Always
14+
name: java-test-app
15+
env:
16+
- name: OTEL_JAVAAGENT_DEBUG
17+
value: "true"
18+
- name: AGENT_HAS_STARTED_IF_YOU_SEE
19+
value: "javaagent.tooling.VersionLogger - opentelemetry-javaagent"

test/operator/kind-with-registry.sh

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#!/bin/sh
2+
set -o errexit
3+
#https://kind.sigs.k8s.io/docs/user/local-registry/
4+
5+
# create registry container unless it already exists
6+
reg_name='kind-registry'
7+
reg_port='5001'
8+
if [ "$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" != 'true' ]; then
9+
docker run \
10+
-d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \
11+
registry:2
12+
fi
13+
14+
# create a cluster with the local registry enabled in containerd
15+
cat <<EOF | kind create cluster --config=-
16+
kind: Cluster
17+
apiVersion: kind.x-k8s.io/v1alpha4
18+
containerdConfigPatches:
19+
- |-
20+
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"]
21+
endpoint = ["http://${reg_name}:5000"]
22+
EOF
23+
24+
# connect the registry to the cluster network if not already connected
25+
if [ "$(docker inspect -f='{{json .NetworkSettings.Networks.kind}}' "${reg_name}")" = 'null' ]; then
26+
docker network connect "kind" "${reg_name}"
27+
fi
28+
29+
# Document the local registry
30+
# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry
31+
cat <<EOF | kubectl apply -f -
32+
apiVersion: v1
33+
kind: ConfigMap
34+
metadata:
35+
name: local-registry-hosting
36+
namespace: kube-public
37+
data:
38+
localRegistryHosting.v1: |
39+
host: "localhost:${reg_port}"
40+
help: "https://kind.sigs.k8s.io/docs/user/local-registry/"
41+
EOF
42+

test/operator/nodejs/Dockerfile

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
FROM node
2+
3+
ADD ./app.js .
4+
5+
ENTRYPOINT [ "node", "app.js" ]

test/operator/nodejs/app.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
var http = require("http");
2+
3+
http.createServer(function (request, response) {
4+
response.writeHead(200, {'Content-Type': 'text/plain'});
5+
response.end('Hello from kubernetes\n');
6+
}).listen(8080);
7+
8+
console.log('Server running at http://127.0.0.1:8080/');

test/operator/nodejs/test-app.yaml

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
apiVersion: v1
2+
kind: Pod
3+
metadata:
4+
name: nodejs-test-app
5+
namespace: banana
6+
annotations:
7+
instrumentation.opentelemetry.io/inject-nodejs: "opentelemetry-operator-system/elastic-instrumentation"
8+
labels:
9+
app: nodejs-test-app
10+
spec:
11+
containers:
12+
- image: localhost:5001/registry/nodejs-test-app
13+
imagePullPolicy: Always
14+
name: nodejs-test-app
15+
env:
16+
- name: OTEL_LOG_LEVEL
17+
value: "debug"
18+
- name: AGENT_HAS_STARTED_IF_YOU_SEE
19+
value: "@opentelemetry/instrumentation-http Applying instrumentation patch for nodejs core module"

test/operator/python/Dockerfile

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
FROM python:3.9-slim-buster
2+
3+
WORKDIR /app
4+
5+
COPY . /app
6+
7+
RUN pip install --no-cache-dir -r requirements.txt
8+
9+
CMD [ "python3", "-m" , "flask", "run"]

test/operator/python/app.py

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# app.py
2+
from flask import Flask
3+
4+
app = Flask(__name__)
5+
6+
@app.route("/")
7+
def hello_world():
8+
return "Hello, World!"

test/operator/python/requirements.txt

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
blinker==1.8.2
2+
click==8.1.7
3+
Flask==3.0.3
4+
itsdangerous==2.2.0
5+
Jinja2==3.1.4
6+
MarkupSafe==2.1.5
7+
Werkzeug==3.0.4

test/operator/python/test-app.yaml

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
apiVersion: v1
2+
kind: Pod
3+
metadata:
4+
name: python-test-app
5+
namespace: banana
6+
annotations:
7+
instrumentation.opentelemetry.io/inject-python: "opentelemetry-operator-system/elastic-instrumentation"
8+
labels:
9+
app: python-test-app
10+
spec:
11+
containers:
12+
- image: localhost:5001/registry/python-test-app
13+
imagePullPolicy: Always
14+
name: python-test-app
15+
env:
16+
- name: OTEL_LOG_LEVEL
17+
value: "debug"
18+
- name: AGENT_HAS_STARTED_IF_YOU_SEE
19+
value: "Exception while exporting metrics HTTPConnectionPool"

test/operator/wait_for_agent_start.sh

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/bin/bash
2+
3+
set -euxo pipefail
4+
5+
MAX_WAIT_SECONDS=60
6+
NAMESPACE=$1
7+
POD_NAME=$2
8+
GREP=$3
9+
10+
echo "Waiting up to $MAX_WAIT_SECONDS seconds for the agent to start in $NAMESPACE/$POD_NAME"
11+
count=0
12+
while [ $count -lt $MAX_WAIT_SECONDS ]
13+
do
14+
count=`expr $count + 1`
15+
STARTED=$(kubectl logs $POD_NAME -n $NAMESPACE | (grep "$GREP" || true) | wc -l)
16+
if [ $STARTED -eq 1 ]
17+
then
18+
exit 0
19+
fi
20+
sleep 1
21+
done
22+
23+
echo "error: the $NAMESPACE/$POD_NAME pod failed to start an agent within $MAX_WAIT_SECONDS seconds"
24+
echo "-- pod info:"
25+
kubectl logs $POD_NAME -n $NAMESPACE
26+
kubectl describe pod/$POD_NAME -n $NAMESPACE
27+
echo "--"
28+
exit 1

0 commit comments

Comments
 (0)