Skip to content

Commit

Permalink
test(e2e): always generate test ID in test, not in the app under test
Browse files Browse the repository at this point in the history
This solves an issue where the test suite would read an outdated test ID
from disk for cronjobs and fail to match cronjob spans.
  • Loading branch information
basti1302 committed Aug 21, 2024
1 parent d01d1a4 commit 051f84b
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 131 deletions.
1 change: 0 additions & 1 deletion test-resources/e2e-test-volumes/test-uuid/.gitignore

This file was deleted.

17 changes: 4 additions & 13 deletions test-resources/node.js/express/app.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2024 Dash0 Inc.
// SPDX-License-Identifier: Apache-2.0

const crypto = require('node:crypto');
const fs = require('node:fs/promises');
const express = require('express');

const port = parseInt(process.env.PORT || '1207');
Expand All @@ -22,18 +20,11 @@ const server = app.listen(port, () => {
});

if (process.env.TRIGGER_SELF_AND_EXIT) {
const testId = crypto.randomUUID();

(async function () {
const testIdFile = process.env.TEST_ID_FILE || '/test-uuid/test.id';
try {
await fs.writeFile(testIdFile, testId);
console.log(`Test ID ${testId} has been written to file ${testIdFile}.`);
} catch (err) {
console.error(
`Unable to write test ID ${testId} to file ${testIdFile}, matching spans in the end-to-end test will not work.`,
err,
);
const testId = process.env.TEST_ID;
if (!testId) {
console.error('TEST_ID environment variable is not set, exiting');
process.exit(1);
}

for (let i = 0; i < 120; i++) {
Expand Down
10 changes: 0 additions & 10 deletions test-resources/node.js/express/cronjob.yaml.template
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,6 @@ spec:
value: "true"
- name: TRIGGER_SELF_AND_EXIT
value: "true"
- name: TEST_ID_FILE
value: "/test-uuid/cronjob.test.id"
ports:
- containerPort: 1205
imagePullPolicy: Never
volumeMounts:
- name: test-uuid
mountPath: /test-uuid
volumes:
- name: test-uuid
hostPath:
path: $PWD/test-resources/e2e-test-volumes/test-uuid
type: DirectoryOrCreate
10 changes: 0 additions & 10 deletions test-resources/node.js/express/job.yaml.template
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,6 @@ spec:
value: "true"
- name: TRIGGER_SELF_AND_EXIT
value: "true"
- name: TEST_ID_FILE
value: "/test-uuid/job.test.id"
ports:
- containerPort: 1208
imagePullPolicy: Never
volumeMounts:
- name: test-uuid
mountPath: /test-uuid
volumes:
- name: test-uuid
hostPath:
path: $PWD/test-resources/e2e-test-volumes/test-uuid
type: DirectoryOrCreate
89 changes: 72 additions & 17 deletions test/e2e/application_under_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@ import (
"os"
"os/exec"

"gopkg.in/yaml.v3"

. "github.com/onsi/ginkgo/v2" //nolint:golint,revive
. "github.com/onsi/gomega"
)

const (
applicationUnderTestNamespace = "e2e-application-under-test-namespace"
applicationPath = "test-resources/node.js/express"
)

func rebuildNodeJsApplicationContainerImage() {
Expand All @@ -24,13 +27,14 @@ func rebuildNodeJsApplicationContainerImage() {
exec.Command(
"docker",
"build",
"test-resources/node.js/express",
applicationPath,
"-t",
"dash0-operator-nodejs-20-express-test-app",
))).To(Succeed())
}

func installNodeJsCronJob(namespace string) error {
func installNodeJsCronJob(namespace string, testId string) error {
addTestIdToCronjobManifest(testId)
return installNodeJsApplication(
namespace,
"cronjob",
Expand All @@ -42,7 +46,7 @@ func uninstallNodeJsCronJob(namespace string) error {
return uninstallNodeJsApplication(namespace, "cronjob")
}

func installNodeJsDaemonSet(namespace string) error {
func installNodeJsDaemonSet(namespace string, testId string) error {
return installNodeJsApplication(
namespace,
"daemonset",
Expand All @@ -60,7 +64,8 @@ func installNodeJsDaemonSet(namespace string) error {
)
}

func installNodeJsDaemonSetWithOptOutLabel(namespace string) error {
//nolint:unparam
func installNodeJsDaemonSetWithOptOutLabel(namespace string, testId string) error {
return installNodeJsApplication(
namespace,
"daemonset.opt-out",
Expand All @@ -82,7 +87,7 @@ func uninstallNodeJsDaemonSet(namespace string) error {
return uninstallNodeJsApplication(namespace, "daemonset")
}

func installNodeJsDeployment(namespace string) error {
func installNodeJsDeployment(namespace string, testId string) error {
return installNodeJsApplication(
namespace,
"deployment",
Expand All @@ -104,7 +109,8 @@ func uninstallNodeJsDeployment(namespace string) error {
return uninstallNodeJsApplication(namespace, "deployment")
}

func installNodeJsJob(namespace string) error {
func installNodeJsJob(namespace string, testId string) error {
addTestIdToJobManifest(testId)
return installNodeJsApplication(
namespace,
"job",
Expand All @@ -116,7 +122,8 @@ func uninstallNodeJsJob(namespace string) error {
return uninstallNodeJsApplication(namespace, "job")
}

func installNodeJsPod(namespace string) error {
//nolint:unparam
func installNodeJsPod(namespace string, testId string) error {
return installNodeJsApplication(
namespace,
"pod",
Expand All @@ -140,7 +147,8 @@ func uninstallNodeJsPod(namespace string) error {
return uninstallNodeJsApplication(namespace, "pod")
}

func installNodeJsReplicaSet(namespace string) error {
//nolint:unparam
func installNodeJsReplicaSet(namespace string, testId string) error {
return installNodeJsApplication(
namespace,
"replicaset",
Expand All @@ -164,7 +172,8 @@ func uninstallNodeJsReplicaSet(namespace string) error {
return uninstallNodeJsApplication(namespace, "replicaset")
}

func installNodeJsStatefulSet(namespace string) error {
//nolint:unparam
func installNodeJsStatefulSet(namespace string, testId string) error {
return installNodeJsApplication(
namespace,
"statefulset",
Expand Down Expand Up @@ -199,7 +208,7 @@ func removeAllTestApplications(namespace string) {

func installNodeJsApplication(
namespace string,
templateName string,
workloadType string,
waitCommand *exec.Cmd,
) error {
err := runAndIgnoreOutput(exec.Command(
Expand All @@ -208,18 +217,18 @@ func installNodeJsApplication(
"--namespace",
namespace,
"-f",
fmt.Sprintf("test-resources/node.js/express/%s.yaml", templateName),
manifest(workloadType),
))
if err != nil {
return err
}
if waitCommand == nil {
return nil
}
return waitForApplicationToBecomeReady(templateName, waitCommand)
return waitForApplicationToBecomeReady(workloadType, waitCommand)
}

func uninstallNodeJsApplication(namespace string, kind string) error {
func uninstallNodeJsApplication(namespace string, workloadType string) error {
return runAndIgnoreOutput(
exec.Command(
"kubectl",
Expand All @@ -228,7 +237,7 @@ func uninstallNodeJsApplication(namespace string, kind string) error {
namespace,
"--ignore-not-found",
"-f",
fmt.Sprintf("test-resources/node.js/express/%s.yaml", kind),
manifest(workloadType),
))
}

Expand Down Expand Up @@ -259,7 +268,53 @@ func removeOptOutLabel(namespace string, workloadType string, workloadName strin
))
}

func deleteTestIdFiles() {
_ = os.Remove("test-resources/e2e-test-volumes/test-uuid/cronjob.test.id")
_ = os.Remove("test-resources/e2e-test-volumes/test-uuid/job.test.id")
func addTestIdToCronjobManifest(testId string) {
filename := manifest("cronjob")
applicationManifestContentRaw, err := os.ReadFile(filename)
Expect(err).ToNot(HaveOccurred())
applicationManifestParsed := make(map[string]interface{})
Expect(yaml.Unmarshal(applicationManifestContentRaw, &applicationManifestParsed)).To(Succeed())
cronjobSpec := (applicationManifestParsed["spec"]).(map[string]interface{})
jobTemplate := (cronjobSpec["jobTemplate"]).(map[string]interface{})
jobTemplate["spec"] = addEnvVarToContainer(testId, jobTemplate)
cronjobSpec["jobTemplate"] = jobTemplate
applicationManifestParsed["spec"] = cronjobSpec
updatedApplicationManifestContentRaw, err := yaml.Marshal(&applicationManifestParsed)
Expect(err).ToNot(HaveOccurred())
Expect(os.WriteFile(filename, updatedApplicationManifestContentRaw, 0644)).To(Succeed())
}

func addTestIdToJobManifest(testId string) {
filename := manifest("job")
applicationManifestContentRaw, err := os.ReadFile(filename)
Expect(err).ToNot(HaveOccurred())
applicationManifestParsed := make(map[string]interface{})
Expect(yaml.Unmarshal(applicationManifestContentRaw, &applicationManifestParsed)).To(Succeed())
applicationManifestParsed["spec"] = addEnvVarToContainer(testId, applicationManifestParsed)
updatedApplicationManifestContentRaw, err := yaml.Marshal(&applicationManifestParsed)
Expect(err).ToNot(HaveOccurred())
Expect(os.WriteFile(filename, updatedApplicationManifestContentRaw, 0644)).To(Succeed())
}

func addEnvVarToContainer(testId string, jobTemplateOrManifest map[string]interface{}) map[string]interface{} {
jobSpec := (jobTemplateOrManifest["spec"]).(map[string]interface{})
template := (jobSpec["template"]).(map[string]interface{})
podSpec := (template["spec"]).(map[string]interface{})
containers := (podSpec["containers"]).([]interface{})
container := (containers[0]).(map[string]interface{})
env := (container["env"]).([]interface{})
newEnvVar := make(map[string]string)
newEnvVar["name"] = "TEST_ID"
newEnvVar["value"] = testId
env = append(env, newEnvVar)
container["env"] = env
containers[0] = container
podSpec["containers"] = containers
template["spec"] = podSpec
jobSpec["template"] = template
return jobSpec
}

func manifest(workloadType string) string {
return fmt.Sprintf("%s/%s.yaml", applicationPath, workloadType)
}
Loading

0 comments on commit 051f84b

Please sign in to comment.