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
18 changes: 15 additions & 3 deletions docs/book/src/cronjob-tutorial/testdata/project/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,21 @@ vet: ## Run go vet against code.
test: manifests generate fmt vet envtest ## Run tests.
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test $$(go list ./... | grep -v /e2e) -coverprofile cover.out

# Utilize Kind or modify the e2e tests to load the image locally, enabling compatibility with other vendors.
.PHONY: test-e2e # Run the e2e tests against a Kind k8s instance that is spun up.
test-e2e:
# TODO(user): To use a different vendor for e2e tests, modify the setup under 'tests/e2e'.
# The default setup assumes Kind is pre-installed and builds/loads the Manager Docker image locally.
# Prometheus and CertManager are installed by default; skip with:
# - PROMETHEUS_INSTALL_SKIP=true
# - CERT_MANAGER_INSTALL_SKIP=true
.PHONY: test-e2e
test-e2e: ## Run the e2e tests. Expected an isolated environment using Kind.
@command -v kind >/dev/null 2>&1 || { \
echo "Kind is not installed. Please install Kind manually."; \
exit 1; \
}
@kind get clusters | grep -q 'kind' || { \
echo "No Kind cluster is running. Please start a Kind cluster before running the e2e tests."; \
exit 1; \
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @DerekTBrown, @majewsky

The changes on this PR should be enough to sort out the scenarios that you raised.
See that we need to have kind up and running for the e2e-tests
Therefore, if anyone run the integration tests without customize them against an env which is not using kind then the test will fail.

c/c @TAM360

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@camilamacedo86 I think the documentation should also include the information about newly introduced environment variables, and the purpose behind them.

Copy link
Member Author

@camilamacedo86 camilamacedo86 Aug 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is documented in the makefile target (see this file)
Also, in the e2e tests scaffolds golang docs.
So, I am not sure what/where more would like to see this info doc.

Please, note that by default the tests will now fails when someone runs in the scenarios where it is executed a cluster that is not kind. So, it will be very unlike someone be able to run make test-e2e against an env without be forced to know what test-e2e does and check its scaffold

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@camilamacedo86 wouldn't it be better idea to include it in the docs as well?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@camilamacedo86 wouldn't it be better idea to include it in the docs as well?

It is not the goal of this PR
but we can add that under reference in a follow up.
I am totally OK with. Could you please raise an issue to track the need?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@camilamacedo86 I'll create a new issue, once this PR merges.

go test ./test/e2e/ -v -ginkgo.v

.PHONY: lint
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,71 @@ package e2e

import (
"fmt"
"os"
"os/exec"
"testing"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

"tutorial.kubebuilder.io/project/test/utils"
)

var (
// Optional Environment Variables:
// - PROMETHEUS_INSTALL_SKIP=true: Skips Prometheus Operator installation during test setup.
// - CERT_MANAGER_INSTALL_SKIP=true: Skips CertManager installation during test setup.
// These variables are useful if Prometheus or CertManager is already installed, avoiding
// re-installation and conflicts.
skipPrometheusInstall = os.Getenv("PROMETHEUS_INSTALL_SKIP") == "true"
skipCertManagerInstall = os.Getenv("CERT_MANAGER_INSTALL_SKIP") == "true"

// projectImage is the name of the image which will be build and loaded
// with the code source changes to be tested.
projectImage = "example.com/project:v0.0.1"
)

// Run e2e tests using the Ginkgo runner.
// TestE2E runs the end-to-end (e2e) test suite for the project. These tests execute in an isolated,
// temporary environment to validate project changes with the the purposed to be used in CI jobs.
// The default setup requires Kind, builds/loads the Manager Docker image locally, and installs
// CertManager and Prometheus.
func TestE2E(t *testing.T) {
RegisterFailHandler(Fail)
_, _ = fmt.Fprintf(GinkgoWriter, "Starting project suite\n")
_, _ = fmt.Fprintf(GinkgoWriter, "Starting project integration test suite\n")
RunSpecs(t, "e2e suite")
}

var _ = BeforeSuite(func() {
By("building the manager(Operator) image")
cmd := exec.Command("make", "docker-build", fmt.Sprintf("IMG=%s", projectImage))
_, err := utils.Run(cmd)
ExpectWithOffset(1, err).NotTo(HaveOccurred(), "Failed to build the manager(Operator) image")

// TODO(user): If you want to change the e2e test vendor from Kind, ensure the image is
// built and available before running the tests. Also, remove the following block.
By("loading the manager(Operator) image on Kind")
err = utils.LoadImageToKindClusterWithName(projectImage)
ExpectWithOffset(1, err).NotTo(HaveOccurred(), "Failed to load the manager(Operator) image into Kind")

// Setup Prometheus and CertManager before the suite if not skipped
if !skipPrometheusInstall {
_, _ = fmt.Fprintf(GinkgoWriter, "Installing Prometheus Operator...\n")
Expect(utils.InstallPrometheusOperator()).To(Succeed(), "Failed to install Prometheus Operator")
}
if !skipCertManagerInstall {
_, _ = fmt.Fprintf(GinkgoWriter, "Installing CertManager...\n")
Expect(utils.InstallCertManager()).To(Succeed(), "Failed to install CertManager")
}
})

var _ = AfterSuite(func() {
// Teardown Prometheus and CertManager after the suite if not skipped
if !skipPrometheusInstall {
_, _ = fmt.Fprintf(GinkgoWriter, "Uninstalling Prometheus Operator...\n")
utils.UninstallPrometheusOperator()
}
if !skipCertManagerInstall {
_, _ = fmt.Fprintf(GinkgoWriter, "Uninstalling CertManager...\n")
utils.UninstallCertManager()
}
})
Original file line number Diff line number Diff line change
Expand Up @@ -29,63 +29,52 @@ import (

const namespace = "project-system"

// Define a set of end-to-end (e2e) tests to validate the behavior of the controller.
var _ = Describe("controller", Ordered, func() {
// Before running the tests, set up the environment by creating the namespace,
// installing CRDs, and deploying the controller.
BeforeAll(func() {
By("installing prometheus operator")
Expect(utils.InstallPrometheusOperator()).To(Succeed())

By("installing the cert-manager")
Expect(utils.InstallCertManager()).To(Succeed())

By("creating manager namespace")
cmd := exec.Command("kubectl", "create", "ns", namespace)
_, _ = utils.Run(cmd)
_, err := utils.Run(cmd)
ExpectWithOffset(1, err).NotTo(HaveOccurred(), "Failed to create namespace")

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

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

// After all tests have been executed, clean up by undeploying the controller, uninstalling CRDs,
// and deleting the namespace.
AfterAll(func() {
By("uninstalling the Prometheus manager bundle")
utils.UninstallPrometheusOperator()
By("undeploying the controller-manager")
cmd := exec.Command("make", "undeploy")
_, _ = utils.Run(cmd)

By("uninstalling the cert-manager bundle")
utils.UninstallCertManager()
By("uninstalling CRDs")
cmd = exec.Command("make", "uninstall")
_, _ = utils.Run(cmd)

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

// The Context block contains the actual tests that validate the operator's behavior.
Context("Operator", func() {
It("should run successfully", func() {
var controllerPodName string
var err error

// projectimage stores the name of the image used in the example
var projectimage = "example.com/project:v0.0.1"

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

By("loading the the manager(Operator) image on Kind")
err = utils.LoadImageToKindClusterWithName(projectimage)
ExpectWithOffset(1, err).NotTo(HaveOccurred())

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

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

By("validating that the controller-manager pod is running as expected")
verifyControllerUp := func() error {
// Get pod name

cmd = exec.Command("kubectl", "get",
// Get the name of the controller-manager pod
cmd := exec.Command("kubectl", "get",
"pods", "-l", "control-plane=controller-manager",
"-o", "go-template={{ range .items }}"+
"{{ if not .metadata.deletionTimestamp }}"+
Expand All @@ -95,28 +84,31 @@ var _ = Describe("controller", Ordered, func() {
)

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

// Validate pod status
// Validate the pod's status
cmd = exec.Command("kubectl", "get",
"pods", controllerPodName, "-o", "jsonpath={.status.phase}",
"-n", namespace,
)
status, err := utils.Run(cmd)
ExpectWithOffset(2, err).NotTo(HaveOccurred())
ExpectWithOffset(2, err).NotTo(HaveOccurred(), "Failed to retrieve controller-manager pod status")
if string(status) != "Running" {
return fmt.Errorf("controller pod in %s status", status)
}
return nil
}
// Repeatedly check if the controller-manager pod is running until it succeeds or times out.
EventuallyWithOffset(1, verifyControllerUp, time.Minute, time.Second).Should(Succeed())

})

// TODO(user): Customize the e2e test suite to include
// additional scenarios specific to your project.
})
})
18 changes: 15 additions & 3 deletions docs/book/src/getting-started/testdata/project/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,21 @@ vet: ## Run go vet against code.
test: manifests generate fmt vet envtest ## Run tests.
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test $$(go list ./... | grep -v /e2e) -coverprofile cover.out

# Utilize Kind or modify the e2e tests to load the image locally, enabling compatibility with other vendors.
.PHONY: test-e2e # Run the e2e tests against a Kind k8s instance that is spun up.
test-e2e:
# TODO(user): To use a different vendor for e2e tests, modify the setup under 'tests/e2e'.
# The default setup assumes Kind is pre-installed and builds/loads the Manager Docker image locally.
# Prometheus and CertManager are installed by default; skip with:
# - PROMETHEUS_INSTALL_SKIP=true
# - CERT_MANAGER_INSTALL_SKIP=true
.PHONY: test-e2e
test-e2e: ## Run the e2e tests. Expected an isolated environment using Kind.
@command -v kind >/dev/null 2>&1 || { \
echo "Kind is not installed. Please install Kind manually."; \
exit 1; \
}
@kind get clusters | grep -q 'kind' || { \
echo "No Kind cluster is running. Please start a Kind cluster before running the e2e tests."; \
exit 1; \
}
go test ./test/e2e/ -v -ginkgo.v

.PHONY: lint
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,71 @@ package e2e

import (
"fmt"
"os"
"os/exec"
"testing"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

"example.com/memcached/test/utils"
)

var (
// Optional Environment Variables:
// - PROMETHEUS_INSTALL_SKIP=true: Skips Prometheus Operator installation during test setup.
// - CERT_MANAGER_INSTALL_SKIP=true: Skips CertManager installation during test setup.
// These variables are useful if Prometheus or CertManager is already installed, avoiding
// re-installation and conflicts.
skipPrometheusInstall = os.Getenv("PROMETHEUS_INSTALL_SKIP") == "true"
skipCertManagerInstall = os.Getenv("CERT_MANAGER_INSTALL_SKIP") == "true"

// projectImage is the name of the image which will be build and loaded
// with the code source changes to be tested.
projectImage = "example.com/project:v0.0.1"
)

// Run e2e tests using the Ginkgo runner.
// TestE2E runs the end-to-end (e2e) test suite for the project. These tests execute in an isolated,
// temporary environment to validate project changes with the the purposed to be used in CI jobs.
// The default setup requires Kind, builds/loads the Manager Docker image locally, and installs
// CertManager and Prometheus.
func TestE2E(t *testing.T) {
RegisterFailHandler(Fail)
_, _ = fmt.Fprintf(GinkgoWriter, "Starting project suite\n")
_, _ = fmt.Fprintf(GinkgoWriter, "Starting project integration test suite\n")
RunSpecs(t, "e2e suite")
}

var _ = BeforeSuite(func() {
By("building the manager(Operator) image")
cmd := exec.Command("make", "docker-build", fmt.Sprintf("IMG=%s", projectImage))
_, err := utils.Run(cmd)
ExpectWithOffset(1, err).NotTo(HaveOccurred(), "Failed to build the manager(Operator) image")

// TODO(user): If you want to change the e2e test vendor from Kind, ensure the image is
// built and available before running the tests. Also, remove the following block.
By("loading the manager(Operator) image on Kind")
err = utils.LoadImageToKindClusterWithName(projectImage)
ExpectWithOffset(1, err).NotTo(HaveOccurred(), "Failed to load the manager(Operator) image into Kind")

// Setup Prometheus and CertManager before the suite if not skipped
if !skipPrometheusInstall {
_, _ = fmt.Fprintf(GinkgoWriter, "Installing Prometheus Operator...\n")
Expect(utils.InstallPrometheusOperator()).To(Succeed(), "Failed to install Prometheus Operator")
}
if !skipCertManagerInstall {
_, _ = fmt.Fprintf(GinkgoWriter, "Installing CertManager...\n")
Expect(utils.InstallCertManager()).To(Succeed(), "Failed to install CertManager")
}
})

var _ = AfterSuite(func() {
// Teardown Prometheus and CertManager after the suite if not skipped
if !skipPrometheusInstall {
_, _ = fmt.Fprintf(GinkgoWriter, "Uninstalling Prometheus Operator...\n")
utils.UninstallPrometheusOperator()
}
if !skipCertManagerInstall {
_, _ = fmt.Fprintf(GinkgoWriter, "Uninstalling CertManager...\n")
utils.UninstallCertManager()
}
})
Loading