Skip to content
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

Convert existing e2e tests from Gingko to e2e framework #62

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

abdurrehman107
Copy link

The above adds the default e2e tests written using the e2e framework. These were earlier written in Gingko. The PR creates a Kind Cluster and installs Prometheus, Cert Manager and Controller manager.

The e2e_test.go file is left empty so I can include tests in it. Most of the work done in Gingko earlier has been replicated in the e2e_suite_test.go.

There are a couple things such as displaying logs at the end of each test (AfterAll() in Gingko) which I cannot add in e2e framework until we begin writing the tests. I have a few more tests ready, and we can begin on them once this PR is merged.

@k8s-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: abdurrehman107
Once this PR has been reviewed and has the lgtm label, please assign justinsb for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot
Copy link

Hi @abdurrehman107. Thanks for your PR.

I'm waiting for a etcd-io member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@ahrtr
Copy link
Member

ahrtr commented Feb 4, 2025

/ok-to-test

@abdurrehman107 abdurrehman107 force-pushed the abdur-rehman/convert-gingko-to-e2e-framework branch from 0635056 to 8108e75 Compare February 4, 2025 20:04
@abdurrehman107
Copy link
Author

/retest

@ahrtr ahrtr requested review from gdasson and hakman February 4, 2025 20:15
@abdurrehman107 abdurrehman107 force-pushed the abdur-rehman/convert-gingko-to-e2e-framework branch from d6c967c to 48b58ec Compare February 4, 2025 20:28
@abdurrehman107
Copy link
Author

/retest

@abdurrehman107 abdurrehman107 force-pushed the abdur-rehman/convert-gingko-to-e2e-framework branch from c8133bf to 0d14085 Compare February 5, 2025 15:06
test/e2e/e2e_suite_test.go Outdated Show resolved Hide resolved
test/e2e/e2e_suite_test.go Outdated Show resolved Hide resolved
@ahrtr
Copy link
Member

ahrtr commented Feb 5, 2025

The high level structure looks ok, but there is some overlaps between the e2e test suite and the Makefile as pointed out the above comments. The most straightforward way is to reuse the existing Makefile targets. Any refactoring or improvement should be in separate PRs.

@hakman @gdasson @ArkaSaha30 PTAL

The etcdcluster_controller_test.go needs to be updated as well. It can be addressed in a separate PR.

@abdurrehman107 abdurrehman107 force-pushed the abdur-rehman/convert-gingko-to-e2e-framework branch 2 times, most recently from 40c08a3 to 4e63d28 Compare February 5, 2025 19:56
@abdurrehman107 abdurrehman107 requested a review from ahrtr February 5, 2025 19:57
@abdurrehman107
Copy link
Author

The etcdcluster_controller_test.go needs to be updated as well. It can be addressed in a separate PR

Right. I'll take this up in the PR right after the e2e-tests.go PR.

@abdurrehman107 abdurrehman107 force-pushed the abdur-rehman/convert-gingko-to-e2e-framework branch 3 times, most recently from 1f83aa1 to dd1123b Compare February 5, 2025 21:22
test/e2e/e2e_suite_test.go Outdated Show resolved Hide resolved
@ahrtr
Copy link
Member

ahrtr commented Feb 6, 2025

Suggest to follow the same order to setup & teardown the env. All e2e tests will be executed in between.

Setup:

  • Create a Kind cluster
  • prepare the resources
    • generate files
    • generate manifests
    • build operator images
  • install dependencies (optional for now)
    • install prometheus operator
    • install certificate maanger
  • set up environment
    • create namespace
    • install CRD
    • deploy etcd operator

Teardown

  • cleanup environment
    • undeploy etcd-operator
    • uninstall CRD
    • remove namespace
  • remove dependencies (optional)
    • uninstall prometheus operator
    • uninstall certificate manager

Also please always keep in mind that one PR is supposed to do only one thing. Please move unrelated change (i.e. etcd version bumping) into separate PR.

@abdurrehman107
Copy link
Author

Please move unrelated change (i.e. etcd version bumping) into separate PR.

@ahrtr do you want me to remove the go.mod file in my PR, that'll stop from bumping the etcd version but it'll also remove all the new libraries. Or do you want me to only remove the specific lines referring to

@ahrtr
Copy link
Member

ahrtr commented Feb 7, 2025

@ahrtr do you want me to remove the go.mod file in my PR, that'll stop from bumping the etcd version but it'll also remove all the new libraries. Or do you want me to only remove the specific lines referring to

I won't insist on it this time. Please keep in mind next time.

Please organize & order the setup & teardown stuff based on my comment above.

@abdurrehman107 abdurrehman107 force-pushed the abdur-rehman/convert-gingko-to-e2e-framework branch from 8cb7c25 to 366396a Compare February 7, 2025 19:18
@abdurrehman107 abdurrehman107 force-pushed the abdur-rehman/convert-gingko-to-e2e-framework branch from 366396a to 24f0672 Compare February 7, 2025 19:21
@abdurrehman107
Copy link
Author

@ahrtr, implemented your suggestions. Can you please review again?

@abdurrehman107 abdurrehman107 requested a review from ahrtr February 7, 2025 19:41
test/e2e/e2e_suite_test.go Outdated Show resolved Hide resolved
test/e2e/e2e_suite_test.go Show resolved Hide resolved
test/e2e/e2e_suite_test.go Show resolved Hide resolved
@abdurrehman107 abdurrehman107 force-pushed the abdur-rehman/convert-gingko-to-e2e-framework branch from 24f0672 to 053e196 Compare February 7, 2025 22:47
@abdurrehman107
Copy link
Author

Addressed feedback @ahrtr, can you please review again?

@abdurrehman107 abdurrehman107 requested a review from ahrtr February 7, 2025 22:59
testEnv.Setup(
// create KinD cluster and namespace
envfuncs.CreateCluster(kindCluster, kindClusterName),
envfuncs.CreateNamespace(namespace),
Copy link
Member

Choose a reason for hiding this comment

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

Pls move it into "setup up environment" as the first step.

And remove the namespace in "cleanup environment" as the last step.

Copy link
Author

Choose a reason for hiding this comment

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

@ahrtr make undeploy deletes the namespace earlier. So deleting it manually errors out. I think we should also remove the step to create the namespace, since make deploy creates it eitherway.

Copy link
Member

Choose a reason for hiding this comment

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

The existing e2e test create the namespace and deploy the controller in BeforeAll, and undeploy the controller and remove the namespace in AfterAll. Can you sort out why the existing e2e test doesn't run into any issue?

BeforeAll(func() {
By("creating manager namespace")
cmd := exec.Command("kubectl", "create", "ns", namespace)
_, err := utils.Run(cmd)
Expect(err).NotTo(HaveOccurred(), "Failed to create namespace")
By("installing CRDs")
cmd = exec.Command("make", "install")
_, err = utils.Run(cmd)
Expect(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)
Expect(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("cleaning up the curl pod for metrics")
cmd := exec.Command("kubectl", "delete", "pod", "curl-metrics", "-n", namespace)
_, _ = utils.Run(cmd)
By("undeploying the controller-manager")
cmd = exec.Command("make", "undeploy")
_, _ = utils.Run(cmd)
By("uninstalling CRDs")
cmd = exec.Command("make", "uninstall")
_, _ = utils.Run(cmd)
By("removing manager namespace")
cmd = exec.Command("kubectl", "delete", "ns", namespace)
_, _ = utils.Run(cmd)
})

Copy link
Author

@abdurrehman107 abdurrehman107 Feb 10, 2025

Choose a reason for hiding this comment

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

Just manually ran the Gingko tests by commenting out the part where they delete the namespace. It still worked. From my understanding it is meant to be a fault tolerant way to ensure that the namespace does not remain not-deleted at the end of the test.

However, I don't think this is needed in our case. Because we dont have to manually pre-create a Kind cluster like with Gingko (we must have a kind cluster already there to run the e2e test in Gingko). In our case we create and destroy the entire Kind cluster, all within the e2e test. So we don't need a "fault-tolerant" method, because the cluster would get deleted anyways.

Copy link
Member

Choose a reason for hiding this comment

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

Just manually ran the Gingko tests by commenting out the part where they delete the namespace. It still worked.

It works doesn't means it's correct. You create it, then you need to remove it.

It seems that the namespace etcd-operator-system automatically applied? The existing e2e test still manually create the namespace on setup and remove it on teardown as mentioned above. Is it necessary or not? @ArkaSaha30

namespace: etcd-operator-system

Generally, I suggest to following existing e2e pattern. Any improvement can be done later in separate PR.

Copy link
Author

@abdurrehman107 abdurrehman107 Feb 11, 2025

Choose a reason for hiding this comment

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

The existing e2e test still manually create the namespace on setup and remove it on teardown as mentioned above. Is it necessary or not?
Generally, I suggest to following existing e2e pattern. Any improvement can be done later in separate PR.

I think we can add it as of now (it does throw an error that the namespace does not exist), and in a later PR we can remove it in case we feel it is necessary.

I've added it in the latest commit to this PR.

test/e2e/e2e_suite_test.go Show resolved Hide resolved
Comment on lines +139 to +153
if err := os.Chdir("../../"); err != nil {
log.Printf("Unable to set working directory: %s", err)
return ctx, err
}
Copy link
Member

Choose a reason for hiding this comment

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

We expect users to run the e2e test from the root directory. go test ./test/e2e/

Suggested change
if err := os.Chdir("../../"); err != nil {
log.Printf("Unable to set working directory: %s", err)
return ctx, err
}

Copy link
Author

Choose a reason for hiding this comment

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

@ahrtr, I did manually test using go test ./test/e2e from the root directory, the tests fail if I do not move out of the directory. The go test ./test/e2e/ makes them start from the directory test/e2e.

Copy link
Member

Choose a reason for hiding this comment

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

Again, why the existing e2e test work without this?

cc @ArkaSaha30 @hakman

Copy link
Author

@abdurrehman107 abdurrehman107 Feb 11, 2025

Choose a reason for hiding this comment

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

The existing e2e test works because it uses the Run() function mentioned in the utils file. I don't use that specific function because it uses Gingko. I've used the RunCommand() function given by the e2e-framework. Since we wish to completely remove the use of Gingko, I suggest we use this. Below is the function used in the existing tests:

func Run(cmd *exec.Cmd) (string, error) {
	dir, _ := GetProjectDir()
	cmd.Dir = dir

	if err := os.Chdir(cmd.Dir); err != nil {
		_, _ = fmt.Fprintf(GinkgoWriter, "chdir dir: %s\n", err)
	}

	cmd.Env = append(os.Environ(), "GO111MODULE=on")
	command := strings.Join(cmd.Args, " ")
	_, _ = fmt.Fprintf(GinkgoWriter, "running: %s\n", command)
	output, err := cmd.CombinedOutput()
	if err != nil {
		return string(output), fmt.Errorf("%s failed with error: (%v) %s", command, err, string(output))
	}

	return string(output), nil
}

Copy link
Author

Choose a reason for hiding this comment

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

I suggest we also update the test/utils/utils.go file, because it refers to Gingko. I can take it up in another PR.

Copy link
Member

Choose a reason for hiding this comment

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

The existing e2e test works because it uses the Run() function mentioned in the utils file. I don't use that specific function because it uses Gingko. I've used the RunCommand() function given by the e2e-framework.

This isn't convincing. Shouldn't RunCommand() and command.Run() have the same or similar effect? I don't think the root cause is clear. Resolving a problem without knowing the root cause is usually dangerous, nor a recommended way.

Copy link
Author

Choose a reason for hiding this comment

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

I understand what you're saying Benjamin, and technically they should, but they are using different methods to solve the problem. The Run() function takes the input of type exec.Cmd while the RunCommand() function takes in a string and then uses the gexe library to process the command. I'd be happy to hop on a call and go through this together.

cc @ahrtr @hakman @ArkaSaha30

Copy link
Member

Choose a reason for hiding this comment

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

I just spend about 5 minutes to read the source code of the existing e2e test.

Is there any difficulty to follow the same pattern ( reuse the GetProjectDir)?

func GetProjectDir() (string, error) {
wd, err := os.Getwd()
if err != nil {
return wd, err
}
wd = strings.Replace(wd, "/test/e2e", "", -1)
return wd, nil
}

Copy link
Author

Choose a reason for hiding this comment

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

Nope, no issues. I just thought implementing the e2e-framework's approach was simpler. However, I get your idea to just replicate the Gingko tests for now, and we can improve in the future.

No worries, I'll update it.

Copy link
Member

Choose a reason for hiding this comment

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

An alternative would be to replace the make calls with make -f../../Makefile. But that would require the Makefile to be agnostic of where it's being executed, and although doable, it will make it dirtier.

@@ -63,7 +63,7 @@ spec:
args:
- --leader-elect
- --health-probe-bind-address=:8081
image: controller:latest
image: etcd-operator-controller:v0.1
Copy link
Member

Choose a reason for hiding this comment

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

You change "latest" to "v0.1.0", it means that we will have to maintain it each time when we bump the version. Suggest not to change it, and let's always add tag "latest" for the image as well.

Copy link
Author

Choose a reason for hiding this comment

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

@ahrtr we are building the image locally. If I put the tag latest, it for some reason defaults to trying to pull the image from a registry (the default one being DockerHub). I used the tag current and it works. Sounds good?

Copy link
Member

Choose a reason for hiding this comment

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

I don't think changing this would be a good idea unless we want to change the Kustomize stack that comes from the scaffolding. But, if we want to replace it, I believe you'll need to change the instances from the Makefile:

cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}

cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}

Copy link
Author

@abdurrehman107 abdurrehman107 Feb 11, 2025

Choose a reason for hiding this comment

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

So do we just wanna leave the image name to be controller?

Copy link
Member

Choose a reason for hiding this comment

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

Is there a particular reason not to? That file is usually just a template. When running make (the target that calls line 151), it replaces it with the actual location of the image (i.e., gcr.io/etcd-development/etcd-operator:v1.2.3).

But we can leave it as you did and later address this when we do the first release.

@abdurrehman107 abdurrehman107 force-pushed the abdur-rehman/convert-gingko-to-e2e-framework branch from 112a460 to 0f69247 Compare February 10, 2025 16:50
@ahrtr ahrtr requested a review from ivanvc February 10, 2025 16:58
go.mod Outdated
go.uber.org/zap v1.27.0
k8s.io/api v0.32.1
k8s.io/apimachinery v0.32.1
k8s.io/client-go v0.32.1
k8s.io/klog/v2 v2.130.1
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738
sigs.k8s.io/controller-runtime v0.20.1
sigs.k8s.io/e2e-framework v0.5.0

Choose a reason for hiding this comment

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

Can we maintain a separate go.mod for test/e2e ...similar to etcd:https://github.com/etcd-io/etcd/tree/main/tests ?
Also, a newer v0.6.0 is available, can we use that?

Copy link
Author

@abdurrehman107 abdurrehman107 Feb 11, 2025

Choose a reason for hiding this comment

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

Updated the version. Do we want to use a separate go.mod? We can consider doing this in a future PR too.
cc @ahrtr

func TestMain(m *testing.M) {
testEnv = env.New()
kindClusterName := "etcd-cluster"
kindCluster := kind.NewCluster(kindClusterName)

Choose a reason for hiding this comment

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

Should we keep the option for which version of Kubernetes the kind cluster should spin up with? Default can use the latest available.
Ref: https://github.com/kubernetes-sigs/e2e-framework/blob/main/support/kind/kind.go#L28

Copy link
Author

Choose a reason for hiding this comment

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

I don't think spinning a cluster with the latest k8s version should be a problem?

Copy link
Member

Choose a reason for hiding this comment

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

I think being able to set the version makes sense in cases where the controller doesn't work with the latest version yet. That way, we could set it to the latest supported version.

@ahrtr
Copy link
Member

ahrtr commented Feb 10, 2025

I suggest to add a very simple e2e test to do some simple sanity test to ensure the environment is healthy.

@ivanvc
Copy link
Member

ivanvc commented Feb 11, 2025

@abdurrehman107, could you please rebase/sync your branch with the remote main, so it's easier to review without the go.mod changes? Thanks :)

@abdurrehman107 abdurrehman107 force-pushed the abdur-rehman/convert-gingko-to-e2e-framework branch from 00191c4 to 5283edd Compare February 11, 2025 06:25
Signed-off-by: Abdur Rehman <[email protected]>
@abdurrehman107
Copy link
Author

@abdurrehman107, could you please rebase/sync your branch with the remote main, so it's easier to review without the go.mod changes? Thanks :)

The PR keeps failing without the go.mod @ivanvc. We add a new framework, the etcd-framework which adds to the go.mod file. I think it is necessary for the PR.

Signed-off-by: Abdur Rehman <[email protected]>
@@ -6,7 +6,6 @@ you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Copy link
Member

Choose a reason for hiding this comment

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

nit: I don't think we want to remove this line. It comes from the Apache license.

func TestMain(m *testing.M) {
testEnv = env.New()
kindClusterName := "etcd-cluster"
kindCluster := kind.NewCluster(kindClusterName)
Copy link
Member

Choose a reason for hiding this comment

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

I think being able to set the version makes sense in cases where the controller doesn't work with the latest version yet. That way, we could set it to the latest supported version.

Comment on lines +241 to +245
// change working directory for Make file
if err := os.Chdir("../../"); err != nil {
log.Printf("Unable to set working directory: %s", err)
return ctx, err
}
Copy link
Member

Choose a reason for hiding this comment

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

I think you'll be removing the change in directories, so this may not be relevant. But, it is not required here because there are no calls to make.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants