Skip to content

Adding integ tests for nodejs instrumentation (#191) #211

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 8 commits into from
Closed
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
28 changes: 28 additions & 0 deletions .github/workflows/operator-integration-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,24 @@ jobs:
go run integration-tests/manifests/cmd/validate_instrumentation_vars.go default integration-tests/manifests/cmd/ns_instrumentation_env_variables.json
kubectl delete instrumentation sample-instrumentation

- name: Test for default instrumentation resources for nodejs
run: |
cat integration-tests/nodejs/sample-deployment-nodejs.yaml
kubectl apply -f integration-tests/nodejs/sample-deployment-nodejs.yaml
sleep 5
kubectl wait --for=condition=Available deployment/nginx -n default
kubectl get pods -A
kubectl describe pods -n default
go run integration-tests/manifests/cmd/validate_instrumentation_vars.go default integration-tests/nodejs/default_instrumentation_nodejs_env_variables.json

- name: Test for defined instrumentation resources for nodejs
run: |
kubectl apply -f integration-tests/manifests/sample-instrumentation.yaml
kubectl delete pods --all -n default
sleep 5
kubectl wait --for=condition=Ready pod --all -n default
go run integration-tests/manifests/cmd/validate_instrumentation_vars.go default integration-tests/manifests/cmd/ns_instrumentation_env_variables.json
kubectl delete instrumentation sample-instrumentation

- name: Test for default instrumentation resources for all languages
run: |
Expand Down Expand Up @@ -195,6 +213,8 @@ jobs:
sleep 5
go test -v -run TestDotNetOnlyDeployment ./integration-tests/manifests/annotations -timeout 30m
sleep 5
go test -v -run TestNodeJSOnlyDeployment ./integration-tests/manifests/annotations -timeout 30m
sleep 5
go test -v -run TestAnnotationsOnMultipleResources ./integration-tests/manifests/annotations -timeout 30m

DaemonsetAnnotationsTest:
Expand Down Expand Up @@ -245,6 +265,8 @@ jobs:
sleep 5
go test -v -run TestDotNetOnlyDaemonSet ./integration-tests/manifests/annotations -timeout 30m
sleep 5
go test -v -run TestNodeJSOnlyDaemonSet ./integration-tests/manifests/annotations -timeout 30m
sleep 5
go test -v -run TestAutoAnnotationForManualAnnotationRemoval ./integration-tests/manifests/annotations -timeout 30m

StatefulsetAnnotationsTest:
Expand Down Expand Up @@ -293,6 +315,10 @@ jobs:
sleep 5
go test -v -run TestPythonOnlyStatefulSet ./integration-tests/manifests/annotations -timeout 30m
sleep 5
go test -v -run TestDotNetOnlyStatefulSet ./integration-tests/manifests/annotations -timeout 30m
sleep 5
go test -v -run TestNodeJSOnlyStatefulSet ./integration-tests/manifests/annotations -timeout 30m
sleep 5
go test -v -run TestOnlyNonAnnotatedAppsShouldBeRestarted ./integration-tests/manifests/annotations -timeout 30m


Expand Down Expand Up @@ -342,4 +368,6 @@ jobs:
sleep 5
go test -v -run TestDotNetOnlyNamespace ./integration-tests/manifests/annotations -timeout 30m
sleep 5
go test -v -run TestNodeJSOnlyNamespace ./integration-tests/manifests/annotations -timeout 30m
sleep 5
go test -v -run TestAlreadyAutoAnnotatedResourceShouldNotRestart ./integration-tests/manifests/annotations -timeout 30m
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ ARG VERSION_DATE
ARG AGENT_VERSION
ARG AUTO_INSTRUMENTATION_JAVA_VERSION
ARG AUTO_INSTRUMENTATION_PYTHON_VERSION
ARG AUTO_INSTRUMENTATION_NODEJS_VERSION
ARG AUTO_INSTRUMENTATION_DOTNET_VERSION
ARG DCMG_EXPORTER_VERSION
ARG NEURON_MONITOR_VERSION
Expand Down
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ VERSION_PKG ?= "github.com/aws/amazon-cloudwatch-agent-operator/internal/version
AGENT_VERSION ?= "$(shell grep -v '\#' versions.txt | grep cloudwatch-agent | awk -F= '{print $$2}')"
AUTO_INSTRUMENTATION_JAVA_VERSION ?= "$(shell grep -v '\#' versions.txt | grep aws-otel-java-instrumentation | awk -F= '{print $$2}')"
AUTO_INSTRUMENTATION_PYTHON_VERSION ?= "$(shell grep -v '\#' versions.txt | grep aws-otel-python-instrumentation | awk -F= '{print $$2}')"
AUTO_INSTRUMENTATION_NODEJS_VERSION ?= "$(shell grep -v '\#' versions.txt | grep aws-otel-nodejs-instrumentation | awk -F= '{print $$2}')"
AUTO_INSTRUMENTATION_DOTNET_VERSION ?= "$(shell grep -v '\#' versions.txt | grep aws-otel-dotnet-instrumentation | awk -F= '{print $$2}')"
DCGM_EXPORTER_VERSION ?= "$(shell grep -v '\#' versions.txt | grep dcgm-exporter | awk -F= '{print $$2}')"
NEURON_MONITOR_VERSION ?= "$(shell grep -v '\#' versions.txt | grep neuron-monitor | awk -F= '{print $$2}')"
Expand Down Expand Up @@ -154,6 +155,7 @@ generate: controller-gen api-docs
# buildx is used to ensure same results for arm based systems (m1/2 chips)
.PHONY: container
container:
docker buildx build --load --platform linux/${ARCH} -t ${IMG} --build-arg VERSION_PKG=${VERSION_PKG} --build-arg VERSION=${VERSION} --build-arg VERSION_DATE=${VERSION_DATE} --build-arg AGENT_VERSION=${AGENT_VERSION} --build-arg AUTO_INSTRUMENTATION_JAVA_VERSION=${AUTO_INSTRUMENTATION_JAVA_VERSION} --build-arg AUTO_INSTRUMENTATION_PYTHON_VERSION=${AUTO_INSTRUMENTATION_PYTHON_VERSION} --build-arg AUTO_INSTRUMENTATION_NODEJS_VERSION=${AUTO_INSTRUMENTATION_NODEJS_VERSION} --build-arg DCGM_EXPORTER_VERSION=${DCGM_EXPORTER_VERSION} --build-arg NEURON_MONITOR_VERSION=${NEURON_MONITOR_VERSION} .
docker buildx build --load --platform linux/${ARCH} -t ${IMG} --build-arg VERSION_PKG=${VERSION_PKG} --build-arg VERSION=${VERSION} --build-arg VERSION_DATE=${VERSION_DATE} --build-arg AGENT_VERSION=${AGENT_VERSION} --build-arg AUTO_INSTRUMENTATION_JAVA_VERSION=${AUTO_INSTRUMENTATION_JAVA_VERSION} --build-arg AUTO_INSTRUMENTATION_PYTHON_VERSION=${AUTO_INSTRUMENTATION_PYTHON_VERSION} --build-arg AUTO_INSTRUMENTATION_DOTNET_VERSION=${AUTO_INSTRUMENTATION_DOTNET_VERSION} --build-arg DCGM_EXPORTER_VERSION=${DCGM_EXPORTER_VERSION} --build-arg NEURON_MONITOR_VERSION=${NEURON_MONITOR_VERSION} .

# Push the container image, used only for local dev purposes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ func TestAllLanguagesDaemonSet(t *testing.T) {
Deployments: []string{""},
StatefulSets: []string{""},
},
NodeJS: auto.AnnotationResources{
Namespaces: []string{""},
DaemonSets: []string{filepath.Join(uniqueNamespace, daemonSetName)},
Deployments: []string{""},
StatefulSets: []string{""},
},
}
jsonStr, err := json.Marshal(annotationConfig)
if err != nil {
Expand All @@ -51,7 +57,7 @@ func TestAllLanguagesDaemonSet(t *testing.T) {
startTime := time.Now()
updateTheOperator(t, clientSet, string(jsonStr))

if err := checkResourceAnnotations(t, clientSet, "daemonset", uniqueNamespace, daemonSetName, sampleDaemonsetYamlRelPath, startTime, []string{injectJavaAnnotation, autoAnnotateJavaAnnotation, injectPythonAnnotation, autoAnnotatePythonAnnotation, injectDotNetAnnotation, autoAnnotateDotNetAnnotation}, false); err != nil {
if err := checkResourceAnnotations(t, clientSet, "daemonset", uniqueNamespace, daemonSetName, sampleDaemonsetYamlRelPath, startTime, []string{injectJavaAnnotation, autoAnnotateJavaAnnotation, injectPythonAnnotation, autoAnnotatePythonAnnotation, injectDotNetAnnotation, autoAnnotateDotNetAnnotation, injectNodeJSAnnotation, autoAnnotateNodeJSAnnotation}, false); err != nil {
t.Fatalf("Failed annotation check: %s", err.Error())
}

Expand Down Expand Up @@ -156,3 +162,27 @@ func TestDotNetOnlyDaemonSet(t *testing.T) {
}

}
func TestNodeJSOnlyDaemonSet(t *testing.T) {
clientSet := setupTest(t)
randomNumber, err := rand.Int(rand.Reader, big.NewInt(9000))
if err != nil {
panic(err)
}
randomNumber.Add(randomNumber, big.NewInt(1000)) //adding a hash to namespace
uniqueNamespace := fmt.Sprintf("daemonset-namespace-nodejs-only-%d", randomNumber)
annotationConfig := auto.AnnotationConfig{
NodeJS: auto.AnnotationResources{
DaemonSets: []string{filepath.Join(uniqueNamespace, daemonSetName)},
},
}
jsonStr, err := json.Marshal(annotationConfig)
if err != nil {
t.Error("Error:", err)
}
startTime := time.Now()
updateTheOperator(t, clientSet, string(jsonStr))

if err := checkResourceAnnotations(t, clientSet, "daemonset", uniqueNamespace, daemonSetName, sampleDaemonsetYamlRelPath, startTime, []string{injectNodeJSAnnotation, autoAnnotateNodeJSAnnotation}, false); err != nil {
t.Fatalf("Failed annotation check: %s", err.Error())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ const (
injectDotNetAnnotation = "instrumentation.opentelemetry.io/inject-dotnet"
autoAnnotateDotNetAnnotation = "cloudwatch.aws.amazon.com/auto-annotate-dotnet"

injectNodeJSAnnotation = "instrumentation.opentelemetry.io/inject-nodejs"
autoAnnotateNodeJSAnnotation = "cloudwatch.aws.amazon.com/auto-annotate-nodejs"

deploymentName = "sample-deployment"
nginxDeploymentName = "nginx"
statefulSetName = "sample-statefulset"
Expand Down Expand Up @@ -175,8 +178,9 @@ func checkNameSpaceAnnotations(t *testing.T, clientSet *kubernetes.Clientset, ex
fmt.Println("There was an error getting namespace, ", err)
return false
}

for _, annotation := range expectedAnnotations {
fmt.Printf("\n This is the annotation: %v and its status %v, namespace name: %v, \n", annotation, ns.Status, ns.Name)
fmt.Printf("\n This is the annotation: %v and its status %v, namespace name: %v, \n", ns.ObjectMeta.Annotations, ns.Status, ns.Name)
if ns.ObjectMeta.Annotations[annotation] != "true" {
time.Sleep(timeBetweenRetries)
correct = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,20 @@ func TestAllLanguagesDeployment(t *testing.T) {
Deployments: []string{filepath.Join(uniqueNamespace, deploymentName)},
StatefulSets: []string{""},
},
NodeJS: auto.AnnotationResources{
Namespaces: []string{""},
DaemonSets: []string{""},
Deployments: []string{filepath.Join(uniqueNamespace, deploymentName)},
StatefulSets: []string{""},
},
}
jsonStr, err := json.Marshal(annotationConfig)
assert.Nil(t, err)

startTime := time.Now()
updateTheOperator(t, clientSet, string(jsonStr))

if err := checkResourceAnnotations(t, clientSet, "deployment", uniqueNamespace, deploymentName, sampleDeploymentYamlNameRelPath, startTime, []string{injectJavaAnnotation, autoAnnotateJavaAnnotation, injectPythonAnnotation, autoAnnotatePythonAnnotation, injectDotNetAnnotation, autoAnnotateDotNetAnnotation}, false); err != nil {
if err := checkResourceAnnotations(t, clientSet, "deployment", uniqueNamespace, deploymentName, sampleDeploymentYamlNameRelPath, startTime, []string{injectJavaAnnotation, autoAnnotateJavaAnnotation, injectPythonAnnotation, autoAnnotatePythonAnnotation, injectDotNetAnnotation, autoAnnotateDotNetAnnotation, injectNodeJSAnnotation, autoAnnotateNodeJSAnnotation}, false); err != nil {
t.Fatalf("Failed annotation check: %s", err.Error())
}

Expand Down Expand Up @@ -167,3 +173,38 @@ func TestDotNetOnlyDeployment(t *testing.T) {
}

}

func TestNodeJSOnlyDeployment(t *testing.T) {

clientSet := setupTest(t)
randomNumber, err := rand.Int(rand.Reader, big.NewInt(9000))
if err != nil {
panic(err)
}
randomNumber.Add(randomNumber, big.NewInt(1000)) //adding a hash to namespace
uniqueNamespace := fmt.Sprintf("deployment-namespace-nodejs-only-%d", randomNumber)

annotationConfig := auto.AnnotationConfig{
NodeJS: auto.AnnotationResources{
Namespaces: []string{""},
DaemonSets: []string{""},
Deployments: []string{filepath.Join(uniqueNamespace, deploymentName)},
StatefulSets: []string{""},
},
}
jsonStr, err := json.Marshal(annotationConfig)
if err != nil {
t.Error("Error:", err)
}

startTime := time.Now()
updateTheOperator(t, clientSet, string(jsonStr))
if err != nil {
t.Errorf("Failed to get deployment app: %s", err.Error())
}

if err := checkResourceAnnotations(t, clientSet, "deployment", uniqueNamespace, deploymentName, sampleDeploymentYamlNameRelPath, startTime, []string{injectNodeJSAnnotation, autoAnnotateNodeJSAnnotation}, false); err != nil {
t.Fatalf("Failed annotation check: %s", err.Error())
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ func TestAllLanguagesNamespace(t *testing.T) {
Deployments: []string{""},
StatefulSets: []string{""},
},
NodeJS: auto.AnnotationResources{
Namespaces: []string{uniqueNamespace},
DaemonSets: []string{""},
Deployments: []string{""},
StatefulSets: []string{""},
},
}
jsonStr, err := json.Marshal(annotationConfig)
if err != nil {
Expand All @@ -58,7 +64,7 @@ func TestAllLanguagesNamespace(t *testing.T) {
startTime := time.Now()

updateTheOperator(t, clientSet, string(jsonStr))
if !checkNameSpaceAnnotations(t, clientSet, []string{injectJavaAnnotation, autoAnnotateJavaAnnotation, injectPythonAnnotation, autoAnnotatePythonAnnotation, injectDotNetAnnotation, autoAnnotateDotNetAnnotation}, uniqueNamespace, startTime) {
if !checkNameSpaceAnnotations(t, clientSet, []string{injectJavaAnnotation, autoAnnotateJavaAnnotation, injectPythonAnnotation, autoAnnotatePythonAnnotation, injectDotNetAnnotation, autoAnnotateDotNetAnnotation, injectNodeJSAnnotation, autoAnnotateNodeJSAnnotation}, uniqueNamespace, startTime) {
t.Error("Missing Languages annotations")
}
}
Expand Down Expand Up @@ -184,6 +190,44 @@ func TestDotNetOnlyNamespace(t *testing.T) {
}
}

func TestNodeJSOnlyNamespace(t *testing.T) {

clientSet := setupTest(t)
randomNumber, err := rand.Int(rand.Reader, big.NewInt(9000))
if err != nil {
panic(err)
}
randomNumber.Add(randomNumber, big.NewInt(1000)) //adding a hash to namespace
uniqueNamespace := fmt.Sprintf("namespace-nodejs-only-%d", randomNumber)
if err := createNamespace(clientSet, uniqueNamespace); err != nil {
t.Fatalf("Failed to create/apply resoures on namespace: %v", err)
}

defer func() {
if err := deleteNamespace(clientSet, uniqueNamespace); err != nil {
t.Fatalf("Failed to delete namespace: %v", err)
}
}()

annotationConfig := auto.AnnotationConfig{
DotNet: auto.AnnotationResources{
Namespaces: []string{uniqueNamespace},
},
}
jsonStr, err := json.Marshal(annotationConfig)
if err != nil {
t.Error("Error:", err)
}

startTime := time.Now()

updateTheOperator(t, clientSet, string(jsonStr))

if !checkNameSpaceAnnotations(t, clientSet, []string{injectNodeJSAnnotation, autoAnnotateNodeJSAnnotation}, uniqueNamespace, startTime) {
t.Error("Missing nodejs annotations")
}
}

// Multiple resources on the same namespace should all get annotations
func TestAnnotationsOnMultipleResources(t *testing.T) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,20 @@ func TestAllLanguagesStatefulSet(t *testing.T) {
Deployments: []string{""},
StatefulSets: []string{filepath.Join(uniqueNamespace, statefulSetName)},
},
NodeJS: auto.AnnotationResources{
Namespaces: []string{""},
DaemonSets: []string{""},
Deployments: []string{""},
StatefulSets: []string{filepath.Join(uniqueNamespace, statefulSetName)},
},
}
jsonStr, err := json.Marshal(annotationConfig)
if err != nil {
t.Error("Error:", err)
}
startTime := time.Now()
updateTheOperator(t, clientSet, string(jsonStr))
if err := checkResourceAnnotations(t, clientSet, "statefulset", uniqueNamespace, statefulSetName, sampleStatefulsetYamlNameRelPath, startTime, []string{injectJavaAnnotation, autoAnnotateJavaAnnotation, injectPythonAnnotation, autoAnnotatePythonAnnotation, injectDotNetAnnotation, autoAnnotateDotNetAnnotation}, false); err != nil {
if err := checkResourceAnnotations(t, clientSet, "statefulset", uniqueNamespace, statefulSetName, sampleStatefulsetYamlNameRelPath, startTime, []string{injectJavaAnnotation, autoAnnotateJavaAnnotation, injectPythonAnnotation, autoAnnotatePythonAnnotation, injectDotNetAnnotation, autoAnnotateDotNetAnnotation, injectNodeJSAnnotation, autoAnnotateNodeJSAnnotation}, false); err != nil {
t.Fatalf("Failed annotation check: %s", err.Error())
}
}
Expand Down Expand Up @@ -150,7 +156,36 @@ func TestDotNetOnlyStatefulSet(t *testing.T) {
startTime := time.Now()
updateTheOperator(t, clientSet, string(jsonStr))

if err := checkResourceAnnotations(t, clientSet, "statefulset", uniqueNamespace, statefulSetName, sampleStatefulsetYamlNameRelPath, startTime, []string{injectPythonAnnotation, autoAnnotatePythonAnnotation, injectDotNetAnnotation, autoAnnotateDotNetAnnotation}, false); err != nil {
if err := checkResourceAnnotations(t, clientSet, "statefulset", uniqueNamespace, statefulSetName, sampleStatefulsetYamlNameRelPath, startTime, []string{injectDotNetAnnotation, autoAnnotateDotNetAnnotation}, false); err != nil {
t.Fatalf("Failed annotation check: %s", err.Error())
}
}
func TestNodeJSOnlyStatefulSet(t *testing.T) {

clientSet := setupTest(t)
randomNumber, err := rand.Int(rand.Reader, big.NewInt(9000))
if err != nil {
panic(err)
}
randomNumber.Add(randomNumber, big.NewInt(1000)) //adding a hash to namespace
uniqueNamespace := fmt.Sprintf("statefulset-namespace-nodejs-only-%d", randomNumber)
annotationConfig := auto.AnnotationConfig{
NodeJS: auto.AnnotationResources{
Namespaces: []string{""},
DaemonSets: []string{""},
Deployments: []string{""},
StatefulSets: []string{filepath.Join(uniqueNamespace, statefulSetName)},
},
}
jsonStr, err := json.Marshal(annotationConfig)
if err != nil {
t.Error("Error:", err)
}

startTime := time.Now()
updateTheOperator(t, clientSet, string(jsonStr))

if err := checkResourceAnnotations(t, clientSet, "statefulset", uniqueNamespace, statefulSetName, sampleStatefulsetYamlNameRelPath, startTime, []string{injectNodeJSAnnotation, autoAnnotateNodeJSAnnotation}, false); err != nil {
t.Fatalf("Failed annotation check: %s", err.Error())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

{
"OTEL_AWS_APPLICATION_SIGNALS_ENABLED": "true",
"OTEL_TRACES_SAMPLER_ARG" : "endpoint=http://cloudwatch-agent.amazon-cloudwatch:2000",
"OTEL_TRACES_SAMPLER": "xray",
"OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf",
"OTEL_EXPORTER_OTLP_TRACES_ENDPOINT" : "http://cloudwatch-agent.amazon-cloudwatch:4316/v1/traces",
"OTEL_AWS_APPLICATION_SIGNALS_EXPORTER_ENDPOINT": "http://cloudwatch-agent.amazon-cloudwatch:4316/v1/metrics",
"OTEL_METRICS_EXPORTER": "none",
"OTEL_LOGS_EXPORTER": "none"
}
20 changes: 20 additions & 0 deletions integration-tests/nodejs/sample-deployment-nodejs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
annotations:
instrumentation.opentelemetry.io/inject-nodejs: "true"
spec:
containers:
- name: nginx
image: nginx:1.14.2
restartPolicy: Always
status: {}
Loading
Loading