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
4 changes: 2 additions & 2 deletions .github/scripts/run-e2e-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ source ../ref/.github/scripts/prepare-e2e-secrets.sh

echo "Running tests for environment '$FLC_ENVIRONMENT'..."

if [[ -z "${TARGET_IMAGE}" ]]; then
make IMG="$TARGET_IMAGE" test/e2e-publish
if [[ -n "${TARGET_IMAGE}" ]]; then
make IMAGE_URI="$TARGET_IMAGE" test/e2e-publish
else
echo "fall back to default branch target"
make BRANCH="$TARGET_BRANCH" test/e2e-publish
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/e2e-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ jobs:
flc-namespace: dto-ocp-ondemand
flc-environment: dto-ocp-fips
helm-chart: ${{ github.event.inputs.helm-chart || 'oci://quay.io/dynatrace/dynatrace-operator:0.0.0-nightly-chart' }}
target-image: format('{0}-fips', (${{ github.event.inputs.target || 'main' }}))
target-image: ${{ format('{0}-fips', github.event.inputs.target || 'main') }}
tenant1-name: ${{ secrets.TENANT1_NAME }}
tenant1-apitoken: ${{ secrets.TENANT1_APITOKEN }}
tenant1-apitoken-nosettings: ${{ secrets.TENANT1_APITOKEN_NOSETTINGS }}
Expand Down
9 changes: 9 additions & 0 deletions hack/make/deploy/deploy.mk
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@ DEBUG_LOGS ?= true
PLATFORM ?= "kubernetes"
HELM_CHART ?= config/helm/chart/default

## Display the image name used to deploy the helm chart
deploy/show-image-ref:
@echo $(IMAGE_URI)

## Display the image name used to deploy the FIPS helm chart
deploy/show-image-ref/fips:
@# Don't call make here to omit the make[1] lines for normal CLI usage.
@echo $(IMAGE_URI)-fips

## Deploy the operator without the csi-driver
deploy/no-csi:
@make ENABLE_CSI=false $(@D)
Expand Down
2 changes: 1 addition & 1 deletion test/features/cloudnative/upgrade/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func Feature(t *testing.T) features.Feature {

// update to snapshot
withCSI := true
builder.Assess("upgrade operator", helpers.ToFeatureFunc(operator.InstallViaMake(withCSI), true))
builder.Assess("upgrade operator", helpers.ToFeatureFunc(operator.InstallLocal(withCSI), true))
builder.Assess("restart half of sample apps", sampleApp.Restart())
cloudnative.AssessSampleInitContainers(builder, sampleApp)

Expand Down
2 changes: 1 addition & 1 deletion test/features/extensions/upgrade/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func Feature(t *testing.T) features.Feature {

// update to snapshot
withCSI := false
builder.Assess("upgrade operator", helpers.ToFeatureFunc(operator.InstallViaMake(withCSI), true))
builder.Assess("upgrade operator", helpers.ToFeatureFunc(operator.InstallLocal(withCSI), true))

builder.Assess("extensions execution controller started", statefulset.WaitFor(testDynakube.Extensions().GetExecutionControllerStatefulsetName(), testDynakube.Namespace))

Expand Down
110 changes: 93 additions & 17 deletions test/helpers/components/operator/installation.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@ package operator
import (
"bytes"
"context"
"errors"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"

"github.com/Dynatrace/dynatrace-operator/test/helpers/components/csi"
"github.com/Dynatrace/dynatrace-operator/test/helpers/components/webhook"
"github.com/Dynatrace/dynatrace-operator/test/helpers/platform"
"github.com/Dynatrace/dynatrace-operator/test/project"
"k8s.io/klog/v2"
"sigs.k8s.io/e2e-framework/pkg/env"
"sigs.k8s.io/e2e-framework/pkg/envconf"
"sigs.k8s.io/e2e-framework/third_party/helm"
Expand All @@ -22,22 +26,25 @@ const (
helmRegistryURL = "oci://public.ecr.aws/dynatrace/dynatrace-operator"
)

func InstallViaMake(withCSI bool) env.Func {
// Install the operator chart with the specified tag and CSI mode.
func Install(releaseTag string, withCSI bool) env.Func {
return func(ctx context.Context, envConfig *envconf.Config) (context.Context, error) {
rootDir := project.RootDir()
err := execMakeCommand(rootDir, "deploy", fmt.Sprintf("ENABLE_CSI=%t", withCSI))
if releaseTag == "" {
return ctx, errors.New("missing release tag")
}
err := installViaHelm(releaseTag, withCSI)
if err != nil {
return ctx, err
}
ctx, err = VerifyInstall(ctx, envConfig, withCSI)

return ctx, err
return VerifyInstall(ctx, envConfig, withCSI)
}
}

func InstallViaHelm(releaseTag string, withCSI bool, namespace string) env.Func {
// InstallLocal deploys the operator helm chart from filesystem.
func InstallLocal(withCSI bool) env.Func {
return func(ctx context.Context, envConfig *envconf.Config) (context.Context, error) {
err := installViaHelm(releaseTag, withCSI, namespace)
err := installViaHelm("", withCSI)
if err != nil {
return ctx, err
}
Expand All @@ -46,7 +53,7 @@ func InstallViaHelm(releaseTag string, withCSI bool, namespace string) env.Func
}
}

func UninstallViaMake(withCSI bool) env.Func {
func Uninstall(withCSI bool) env.Func {
return func(ctx context.Context, envConfig *envconf.Config) (context.Context, error) {
rootDir := project.RootDir()
if withCSI {
Expand Down Expand Up @@ -90,33 +97,102 @@ func execMakeCommand(rootDir, makeTarget string, envVariables ...string) error {
err := command.Run()

if len(b.String()) != 0 {
fmt.Println("out:", b.String()) //nolint
fmt.Println("out:", b.String()) //nolint:forbidigo
}

if len(bErr.String()) != 0 {
fmt.Println("err:", bErr.String()) //nolint
fmt.Println("err:", bErr.String()) //nolint:forbidigo
}

return err
}

func installViaHelm(releaseTag string, withCsi bool, namespace string) error {
func installViaHelm(releaseTag string, withCSI bool) error {
manager := helm.New("''")

_platform, err := platform.NewResolver().GetPlatform()
if err != nil {
return err
}

return manager.RunUpgrade(helm.WithNamespace(namespace),
opts, err := getHelmOptions(releaseTag, _platform, withCSI)
if err != nil {
return err
}

var klogLevel klog.Level
// Show helm command args and output
// Set only fails if the input does not conform to stronv.ParseInt(x, 10, 32)
_ = klogLevel.Set("4")
defer func() {
// Reset to default value to prevent other logs from showing up
_ = klogLevel.Set("0")
}()

return manager.RunUpgrade(opts...)
}

func getHelmOptions(releaseTag, platform string, withCSI bool) ([]helm.Option, error) {
opts := []helm.Option{
helm.WithReleaseName("dynatrace-operator"),
helm.WithArgs(helmRegistryURL),
helm.WithVersion(releaseTag),
helm.WithNamespace("dynatrace"),
helm.WithArgs("--create-namespace"),
helm.WithArgs("--install"),
helm.WithArgs("--set", fmt.Sprintf("platform=%s", _platform)),
helm.WithArgs("--set", fmt.Sprintf("platform=%s", platform)),
helm.WithArgs("--set", "installCRD=true"),
helm.WithArgs("--set", fmt.Sprintf("csidriver.enabled=%t", withCsi)),
helm.WithArgs("--set", fmt.Sprintf("csidriver.enabled=%t", withCSI)),
helm.WithArgs("--set", "manifests=true"),
)
helm.WithArgs("--set", "debugLogs=true"),
}

// Install from registry
if releaseTag != "" {
return append(opts,
helm.WithArgs(helmRegistryURL),
helm.WithVersion(releaseTag),
), nil
}

// Install nightly
if chartURI := os.Getenv("HELM_CHART"); strings.HasSuffix(chartURI, ":0.0.0-nightly-chart") {
return append(opts, helm.WithArgs(chartURI)), nil
}

// Install from filesystem
rootDir := project.RootDir()
imageRef, err := getImageRef(rootDir)
if err != nil {
return nil, err
}

if imageRef == "" {
return nil, errors.New("could not determine operator image")
}

return append(opts,
helm.WithArgs("--set", "image="+strings.TrimSpace(imageRef)),
helm.WithArgs(filepath.Join(rootDir, "config", "helm", "chart", "default")),
), nil
}

func getImageRef(rootDir string) (string, error) {
command := exec.Command("make", "-C", rootDir, "deploy/show-image-ref")
command.Env = os.Environ()
stdout, stderr := new(bytes.Buffer), new(bytes.Buffer)
command.Stdout = stdout
command.Stderr = stderr
err := command.Run()
if err != nil || stderr.String() != "" {
return "", fmt.Errorf("%s: %w", stderr, err)
}
lines := strings.Split(strings.TrimSpace(stdout.String()), "\n")
stdout.Reset()
for _, line := range lines {
// make prints things to stdout, e.g. make[1]: Entering directory
if !strings.HasPrefix(line, "make[") {
stdout.WriteString(line)
}
}

return stdout.String(), nil
}
99 changes: 99 additions & 0 deletions test/helpers/components/operator/installation_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
//go:build e2e

package operator

import (
"os"
"path/filepath"
"testing"

"github.com/Dynatrace/dynatrace-operator/test/project"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"sigs.k8s.io/e2e-framework/third_party/helm"
)

func TestGetHelmOptions(t *testing.T) {
assertOptions := func(t *testing.T, expect *helm.Opts, options []helm.Option) {
t.Helper()
got := new(helm.Opts)
for _, opt := range options {
opt(got)
}
assert.Equal(t, expect, got)
}

t.Run("use release tag", func(t *testing.T) {
opts, err := getHelmOptions("1.2.3", "test", true)
require.NoError(t, err)
assertOptions(t, &helm.Opts{
Namespace: "dynatrace",
ReleaseName: "dynatrace-operator",
Version: "1.2.3",
Args: []string{
"--create-namespace",
"--install",
"--set", "platform=test",
"--set", "installCRD=true",
"--set", "csidriver.enabled=true",
"--set", "manifests=true",
"--set", "debugLogs=true",
helmRegistryURL,
},
}, opts)
})

t.Run("use nightly", func(t *testing.T) {
t.Setenv("HELM_CHART", "oci://registry:0.0.0-nightly-chart")
opts, err := getHelmOptions("", "test", true)
require.NoError(t, err)
assertOptions(t, &helm.Opts{
Namespace: "dynatrace",
ReleaseName: "dynatrace-operator",
Args: []string{
"--create-namespace",
"--install",
"--set", "platform=test",
"--set", "installCRD=true",
"--set", "csidriver.enabled=true",
"--set", "manifests=true",
"--set", "debugLogs=true",
"oci://registry:0.0.0-nightly-chart",
},
}, opts)
})

t.Run("use filesystem", func(t *testing.T) {
tempDir := t.TempDir()
require.NoError(t, os.WriteFile(filepath.Join(tempDir, "make"), []byte("#!/bin/sh\necho repo:tag"), os.ModePerm)) //nolint:gosec
t.Setenv("PATH", tempDir+":"+os.Getenv("PATH"))

t.Setenv("HELM_CHART", "oci://registry:snapshot-test")
opts, err := getHelmOptions("", "test", false)
require.NoError(t, err)
assertOptions(t, &helm.Opts{
Namespace: "dynatrace",
ReleaseName: "dynatrace-operator",
Args: []string{
"--create-namespace",
"--install",
"--set", "platform=test",
"--set", "installCRD=true",
"--set", "csidriver.enabled=false",
"--set", "manifests=true",
"--set", "debugLogs=true",
"--set", "image=repo:tag",
filepath.Join(project.RootDir(), "config", "helm", "chart", "default"),
},
}, opts)
})

t.Run("no image found", func(t *testing.T) {
tempDir := t.TempDir()
require.NoError(t, os.WriteFile(filepath.Join(tempDir, "make"), []byte("#!/bin/sh\necho make[1] Entering directory"), os.ModePerm)) //nolint:gosec
t.Setenv("PATH", tempDir+":"+os.Getenv("PATH"))

_, err := getHelmOptions("", "test", false)
require.Error(t, err)
})
}
4 changes: 2 additions & 2 deletions test/scenarios/istio/istio_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ func TestMain(m *testing.M) {
testEnv.Setup(
helpers.SetScheme,
namespace.CreateForEnv(nsWithIstio),
operator.InstallViaMake(true),
operator.InstallLocal(true),
)
// If we cleaned up during a fail-fast (aka.: /debug) it wouldn't be possible to investigate the error.
if !cfg.FailFast() {
testEnv.Finish(operator.UninstallViaMake(true))
testEnv.Finish(operator.Uninstall(true))
testEnv.Finish(namespace.CreateForEnv(nsWithoutIstio))
}

Expand Down
4 changes: 2 additions & 2 deletions test/scenarios/nocsi/no_csi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ func TestMain(m *testing.M) {
testEnv = env.NewWithConfig(cfg)
testEnv.Setup(
helpers.SetScheme,
operator.InstallViaMake(false),
operator.InstallLocal(false),
)
// If we cleaned up during a fail-fast (aka.: /debug) it wouldn't be possible to investigate the error.
if !cfg.FailFast() {
testEnv.Finish(operator.UninstallViaMake(false))
testEnv.Finish(operator.Uninstall(false))
}

testEnv.AfterEachTest(func(ctx context.Context, c *envconf.Config, t *testing.T) (context.Context, error) {
Expand Down
4 changes: 2 additions & 2 deletions test/scenarios/release/release_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ func TestMain(m *testing.M) {
testEnv = env.NewWithConfig(cfg)
testEnv.Setup(
helpers.SetScheme,
operator.InstallViaHelm(releaseTag, true, operator.DefaultNamespace), // TODO: add logic to get releaseTag in a dynamic way instead of hard coding it
operator.Install(releaseTag, true), // TODO: add logic to get releaseTag in a dynamic way instead of hard coding it
)
// If we cleaned up during a fail-fast (aka.: /debug) it wouldn't be possible to investigate the error.
if !cfg.FailFast() {
testEnv.Finish(operator.UninstallViaMake(true))
testEnv.Finish(operator.Uninstall(true))
}

testEnv.AfterEachTest(func(ctx context.Context, c *envconf.Config, t *testing.T) (context.Context, error) {
Expand Down
4 changes: 2 additions & 2 deletions test/scenarios/standard/standard_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ func TestMain(m *testing.M) {
testEnv = env.NewWithConfig(cfg)
testEnv.Setup(
helpers.SetScheme,
operator.InstallViaMake(true),
operator.InstallLocal(true),
)
// If we cleaned up during a fail-fast (aka.: /debug) it wouldn't be possible to investigate the error.
if !cfg.FailFast() {
testEnv.Finish(operator.UninstallViaMake(true))
testEnv.Finish(operator.Uninstall(true))
}

testEnv.AfterEachTest(func(ctx context.Context, c *envconf.Config, t *testing.T) (context.Context, error) {
Expand Down
Loading