Skip to content

Commit

Permalink
test(e2e): make target namespace configurable
Browse files Browse the repository at this point in the history
  • Loading branch information
basti1302 committed May 22, 2024
1 parent 2558dce commit a8f49ae
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 92 deletions.
2 changes: 1 addition & 1 deletion internal/webhook/dash0_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func (h *Handler) SetupWebhookWithManager(mgr ctrl.Manager) error {
return nil
}

func (h *Handler) Handle(ctx context.Context, request admission.Request) admission.Response {
func (h *Handler) Handle(_ context.Context, request admission.Request) admission.Response {
logger := log.WithValues("gvk", request.Kind, "namespace", request.Namespace, "name", request.Name)
logger.Info("incoming admission request")

Expand Down
90 changes: 74 additions & 16 deletions test/e2e/e2e_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
)

const (
certmanagerVersion = "v1.5.3"
certmanagerVersion = "v1.14.5"
certmanagerURLTmpl = "https://github.com/jetstack/cert-manager/releases/download/%s/cert-manager.yaml"
tracesJsonMaxLineLength = 1_048_576
verifyTelemetryTimeout = 60 * time.Second
Expand Down Expand Up @@ -152,8 +152,8 @@ func UninstallCertManager() {
}
}

func ReinstallCollectorAndClearExportedTelemetry() error {
_ = UninstallCollector()
func ReinstallCollectorAndClearExportedTelemetry(namespace string) error {
_ = UninstallCollector(namespace)
_ = os.Remove("e2e-test-received-data/traces.jsonl")
_ = os.Remove("e2e-test-received-data/metrics.jsonl")
_ = os.Remove("e2e-test-received-data/logs.jsonl")
Expand All @@ -164,7 +164,7 @@ func ReinstallCollectorAndClearExportedTelemetry() error {
"dash0-opentelemetry-collector-daemonset",
"open-telemetry/opentelemetry-collector",
"--namespace",
"default",
namespace,
"--values",
"test-resources/collector/values.yaml",
"--set",
Expand All @@ -180,48 +180,106 @@ func ReinstallCollectorAndClearExportedTelemetry() error {
"daemonset",
"dash0-opentelemetry-collector-daemonset-agent",
"--namespace",
"default",
namespace,
"--timeout",
"30s",
))
}

func UninstallCollector() error {
func UninstallCollector(namespace string) error {
return RunAndIgnoreOutput(
exec.Command(
"helm",
"uninstall",
"dash0-opentelemetry-collector-daemonset",
"--namespace",
"default",
namespace,
"--ignore-not-found",
))
}

func InstallNodeJsDeployment() error {
func DeployOperator(namespace string, image string) {
By("deploying the controller-manager")
ExpectWithOffset(1, RunAndIgnoreOutput(exec.Command("make", "deploy", fmt.Sprintf("IMG=%s", image))))

var controllerPodName string
By("validating that the controller-manager pod is running as expected")
verifyControllerUp := func() error {
cmd := exec.Command("kubectl", "get",
"pods", "-l", "control-plane=controller-manager",
"-o", "go-template={{ range .items }}"+
"{{ if not .metadata.deletionTimestamp }}"+
"{{ .metadata.name }}"+
"{{ \"\\n\" }}{{ end }}{{ end }}",
"-n", namespace,
)

podOutput, err := Run(cmd, false)
ExpectWithOffset(2, err).NotTo(HaveOccurred())
podNames := GetNonEmptyLines(string(podOutput))
if len(podNames) != 1 {
return fmt.Errorf("expect 1 controller pods running, but got %d", len(podNames))
}
controllerPodName = podNames[0]
ExpectWithOffset(2, controllerPodName).To(ContainSubstring("controller-manager"))

cmd = exec.Command("kubectl", "get",
"pods", controllerPodName, "-o", "jsonpath={.status.phase}",
"-n", namespace,
)
status, err := Run(cmd)
ExpectWithOffset(2, err).NotTo(HaveOccurred())
if string(status) != "Running" {
return fmt.Errorf("controller pod in %s status", status)
}
return nil
}

EventuallyWithOffset(1, verifyControllerUp, 120*time.Second, time.Second).Should(Succeed())
}

func UndeployOperator() {
By("undeploying the controller-manager")
ExpectWithOffset(1, RunAndIgnoreOutput(exec.Command("make", "undeploy"))).To(Succeed())
}

func InstallNodeJsDeployment(namespace string) error {
imageName := "dash0-operator-nodejs-20-express-test-app"
err := RunMultipleFromStrings([][]string{
{"docker", "build", "test-resources/node.js/express", "-t", imageName},
{"kubectl", "apply", "-f", "test-resources/node.js/express/deploy.yaml"},
{"kubectl", "apply", "-f", "test-resources/node.js/express/deploy.yaml", "--namespace", namespace},
})
if err != nil {
return err
}

return RunAndIgnoreOutput(
exec.Command(
"kubectl", "wait", "deployment.apps/dash0-operator-nodejs-20-express-test-deployment",
"--for", "condition=Available",
"--namespace", "default",
"--timeout", "30s",
"kubectl",
"wait",
"deployment.apps/dash0-operator-nodejs-20-express-test-deployment",
"--for",
"condition=Available",
"--namespace",
namespace,
"--timeout",
"30s",
))
}

func UninstallNodeJsDeployment() error {
return RunAndIgnoreOutput(exec.Command("kubectl", "delete", "-f", "test-resources/node.js/express/deploy.yaml"))
func UninstallNodeJsDeployment(namespace string) error {
return RunAndIgnoreOutput(
exec.Command(
"kubectl",
"delete",
"--namespace",
namespace,
"-f",
"test-resources/node.js/express/deploy.yaml",
))
}

func SendRequestAndVerifySpansHaveBeenProduced() {
func SendRequestsAndVerifySpansHaveBeenProduced() {
timestampLowerBound := time.Now()

By("verify that the resource has been instrumented and is sending telemetry", func() {
Expand Down
137 changes: 62 additions & 75 deletions test/e2e/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,39 @@ import (
)

const (
namespace = "dash0-operator-system"
operatorNamespace = "dash0-operator-system"
operatorImage = "dash0-operator-controller:latest"

applicationUnderTestNamespace = "default"

managerYaml = "config/manager/manager.yaml"
managerYamlBackup = managerYaml + ".backup"
)

var (
originalKubeContext string
managerYamlNeedsRevert bool

skipCertManagerInstall = false
skipCertManagerUninstall = false
)

var _ = Describe("controller", Ordered, func() {
var _ = Describe("Dash0 Kubernetes Operator", Ordered, func() {

BeforeAll(func() {
pwdOutput, err := Run(exec.Command("pwd"), false)
ExpectWithOffset(1, err).NotTo(HaveOccurred())
workingDir := strings.TrimSpace(string(pwdOutput))
fmt.Fprintf(GinkgoWriter, "workingDir: %s\n", workingDir)

if v, ok := os.LookupEnv("SKIP_CERT_MANAGER_UNINSTALL"); ok {
skipCertManagerUninstall = strings.ToLower(v) == "true"
}
if v, ok := os.LookupEnv("SKIP_CERT_MANAGER"); ok {
skipCertManagerInstall = strings.ToLower(v) == "true"
skipCertManagerUninstall = skipCertManagerInstall
}

By("Reading current imagePullPolicy")
yqOutput, err := Run(exec.Command(
"yq",
Expand All @@ -50,15 +65,14 @@ var _ = Describe("controller", Ordered, func() {
ExpectWithOffset(1, err).NotTo(HaveOccurred())
managerYamlNeedsRevert = true
By("temporarily changing imagePullPolicy to \"Never\"")
_, err = Run(exec.Command(
ExpectWithOffset(1, RunAndIgnoreOutput(exec.Command(
"yq",
"-i",
"with(select(documentIndex == 1) | "+
".spec.template.spec.containers[] | "+
"select(.name == \"manager\"); "+
".imagePullPolicy |= \"Never\")",
managerYaml))
ExpectWithOffset(1, err).NotTo(HaveOccurred())
managerYaml))).To(Succeed())
}

By("reading current kubectx")
Expand All @@ -67,23 +81,36 @@ var _ = Describe("controller", Ordered, func() {
originalKubeContext = strings.TrimSpace(string(kubectxOutput))

By("switching to kubectx docker-desktop, previous context " + originalKubeContext + " will be restored later")
_, err = Run(exec.Command("kubectx", "docker-desktop"))
ExpectWithOffset(1, err).NotTo(HaveOccurred())
ExpectWithOffset(1, RunAndIgnoreOutput(exec.Command("kubectx", "docker-desktop"))).To(Succeed())

if !skipCertManagerInstall {
By("installing the cert-manager")
ExpectWithOffset(1, InstallCertManager()).To(Succeed())
}

By("installing the cert-manager")
Expect(InstallCertManager()).To(Succeed())
if applicationUnderTestNamespace != "default" {
By("creating namespace for application under test")
ExpectWithOffset(1,
RunAndIgnoreOutput(exec.Command("kubectl", "create", "ns", applicationUnderTestNamespace))).To(Succeed())
}

By("installing the collector")
Expect(ReinstallCollectorAndClearExportedTelemetry()).To(Succeed())
ExpectWithOffset(1, ReinstallCollectorAndClearExportedTelemetry(applicationUnderTestNamespace)).To(Succeed())

By("creating manager namespace")
cmd := exec.Command("kubectl", "create", "ns", namespace)
_, _ = Run(cmd)
ExpectWithOffset(1, RunAndIgnoreOutput(exec.Command("kubectl", "create", "ns", operatorNamespace))).To(Succeed())

By("building the manager(Operator) image")
ExpectWithOffset(1,
RunAndIgnoreOutput(exec.Command("make", "docker-build", fmt.Sprintf("IMG=%s", operatorImage)))).To(Succeed())

By("installing CRDs")
ExpectWithOffset(1, RunAndIgnoreOutput(exec.Command("make", "install"))).To(Succeed())
})

AfterAll(func() {
By("uninstalling the Node.js deployment")
Expect(UninstallNodeJsDeployment()).Should(Succeed())
ExpectWithOffset(1, UninstallNodeJsDeployment(applicationUnderTestNamespace)).To(Succeed())

if managerYamlNeedsRevert {
By("reverting changes to " + managerYaml)
Expand All @@ -93,15 +120,21 @@ var _ = Describe("controller", Ordered, func() {
ExpectWithOffset(1, err).NotTo(HaveOccurred())
}

By("uninstalling the cert-manager bundle")
UninstallCertManager()
if !skipCertManagerUninstall {
By("uninstalling the cert-manager bundle")
UninstallCertManager()
}

By("uninstalling the collector")
Expect(UninstallCollector()).To(Succeed())
Expect(UninstallCollector(applicationUnderTestNamespace)).To(Succeed())

By("removing manager namespace")
cmd := exec.Command("kubectl", "delete", "ns", namespace)
_, _ = Run(cmd)
_ = RunAndIgnoreOutput(exec.Command("kubectl", "delete", "ns", operatorNamespace))

if applicationUnderTestNamespace != "default" {
By("removing namespace for application under test")
_ = RunAndIgnoreOutput(exec.Command("kubectl", "delete", "ns", applicationUnderTestNamespace))
}

By("switching back to original kubectx " + originalKubeContext)
output, err := Run(exec.Command("kubectx", originalKubeContext))
Expand All @@ -111,68 +144,22 @@ var _ = Describe("controller", Ordered, func() {
fmt.Fprint(GinkgoWriter, string(output))
})

Context("Operator", func() {
It("should start the controller successfully and modify deployments", func() {
var controllerPodName string
var err error

var projectimage = "dash0-operator-controller:latest"

By("building the manager(Operator) image")
cmd := exec.Command("make", "docker-build", fmt.Sprintf("IMG=%s", projectimage))
_, err = Run(cmd)
ExpectWithOffset(1, err).NotTo(HaveOccurred())

By("installing CRDs")
cmd = exec.Command("make", "install")
_, err = Run(cmd)
ExpectWithOffset(1, err).NotTo(HaveOccurred())

By("deploying the controller-manager")
cmd = exec.Command("make", "deploy", fmt.Sprintf("IMG=%s", projectimage))
_, err = Run(cmd)
ExpectWithOffset(1, err).NotTo(HaveOccurred())

By("validating that the controller-manager pod is running as expected")
verifyControllerUp := func() error {
cmd = exec.Command("kubectl", "get",
"pods", "-l", "control-plane=controller-manager",
"-o", "go-template={{ range .items }}"+
"{{ if not .metadata.deletionTimestamp }}"+
"{{ .metadata.name }}"+
"{{ \"\\n\" }}{{ end }}{{ end }}",
"-n", namespace,
)

podOutput, err := Run(cmd)
ExpectWithOffset(2, err).NotTo(HaveOccurred())
podNames := GetNonEmptyLines(string(podOutput))
if len(podNames) != 1 {
return fmt.Errorf("expect 1 controller pods running, but got %d", len(podNames))
}
controllerPodName = podNames[0]
ExpectWithOffset(2, controllerPodName).Should(ContainSubstring("controller-manager"))

cmd = exec.Command("kubectl", "get",
"pods", controllerPodName, "-o", "jsonpath={.status.phase}",
"-n", namespace,
)
status, err := Run(cmd)
ExpectWithOffset(2, err).NotTo(HaveOccurred())
if string(status) != "Running" {
return fmt.Errorf("controller pod in %s status", status)
}
return nil
}
EventuallyWithOffset(1, verifyControllerUp, 120*time.Second, time.Second).Should(Succeed())
Context("the Dash0 operator's webhook", func() {

BeforeAll(func() {
DeployOperator(operatorNamespace, operatorImage)
fmt.Fprint(GinkgoWriter, "waiting 10 seconds\n")
time.Sleep(10 * time.Second)
})

By("installing the Node.js deployment")
Expect(InstallNodeJsDeployment()).To(Succeed())
AfterAll(func() {
UndeployOperator()
})

SendRequestAndVerifySpansHaveBeenProduced()
It("should modify new deployments", func() {
By("installing the Node.js deployment")
Expect(InstallNodeJsDeployment(applicationUnderTestNamespace)).To(Succeed())
SendRequestsAndVerifySpansHaveBeenProduced()
})
})
})
Expand Down

0 comments on commit a8f49ae

Please sign in to comment.