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

Refactor fabric8 catalog watch integration tests (1) #1755

Merged
merged 15 commits into from
Oct 15, 2024

Conversation

wind57
Copy link
Contributor

@wind57 wind57 commented Oct 5, 2024

No description provided.

@wind57 wind57 changed the base branch from main to 3.1.x October 5, 2024 21:26
@wind57
Copy link
Contributor Author

wind57 commented Oct 5, 2024

The main idea here is that I took an existing package of integration tests and re-factored it:

  • it does not need an image
  • it does not need ingress
  • it connects directly to a running cluster

Logically, the tests have not changed at all, I changed the way we set-up thing.

On my laptop, running the previous version (time mvn clean install)

   ________________________________________________________
Executed in  378.78 secs    fish           external
   usr time   18.56 secs  104.00 micros   18.56 secs
   sys time    6.51 secs  708.00 micros    6.51 secs

and the current version:

Executed in  149.69 secs    fish           external
   usr time   23.64 secs   77.00 micros   23.64 secs
   sys time    5.78 secs  800.00 micros    5.78 secs

@@ -42,6 +42,22 @@
<filtering>true</filtering>
</resource>
</resources>

<plugins>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

we do not need to build an image anymore, thus skip this

Copy link
Contributor

Choose a reason for hiding this comment

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

Why? Is it because we use BusyBox instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sorry, I should have been more verbose here.

So, until now, we were building an image out of each integration test maven module. For example, this maven module is called: spring-cloud-kubernetes-fabric8-client-catalog-watcher; using spring-boot-maven-plugin we were building a docker image out of it.

This image was used as a deployment and put in K3s. We also used ingress to hit some endpoints needed for the test itself.

I am proposing that instead of doing that, we still spin an instance of K3s, but now connect to it directly:

protected static final K3sContainer K3S = Commons.container();

....

protected static KubernetesClient client() {
     String kubeConfigYaml = K3S.getKubeConfigYaml();
     Config config = Config.fromKubeconfig(kubeConfigYaml);
     return new KubernetesClientBuilder().withConfig(config).build();
}


.....


@TestConfiguration
static class TestConfig {

     @Bean
     @Primary
            KubernetesClient kubernetesClient() {
                  return client();
	    }
}

So if we do that, we do not need an image, we do not need ingress, we do not need a deployment.

The test itself still asserts all the previous conditions, nothing changes in this regard, but this time its a lot faster.

Copy link
Contributor

Choose a reason for hiding this comment

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

I mean this just configures the underlying KubernetesClient. Before we would deploy and app and then use that app to test if the feature we were concerned about worked the way we expect. How does overriding the KubernetesClient with this configuration allow us to test the feature without the need for an app?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Let me try to explain. In this test, all we care about it what catalog watcher posts as an event. All our testing logic is around that and for that we :

  • have a listener that would catch that event
  • have a rest controller that would allow us to get that event
  • have a deployment and service to deploy the app
  • have ingress so that the rest controller is exposed externally

Then, from the test, we would make changes (deploy busybox for example), then call that rest endpoint to see that the result is correct (via ingress).

But, that catalog watcher does not have to be deployed. All it needs, is a KubernetesClient connected to the cluster and that's it. The rest of the infrastructure can be local (like the controller) and can be provided to the running test via a simple:

@SpringBootTest(class=Application.class)

and that Application.class will take care to load all needed beans.

So instead of going to the ingress path, we now go to a simple :

WebClient client = builder().baseUrl("http://localhost:" + port + "/result").build();

and the value that /result provides to us for assertions, still comes from the cluster.

Copy link
Contributor

Choose a reason for hiding this comment

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

I guess I can see how that might be possible for this specific test but can this approach be generalized for other tests? For example, if we are testing that updating a config map causes a refresh to be sent to an app via the configuration watcher, I don't see how we don't get around deploy one (or more ) apps to verify that happens.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Spot on sir! It works here and in the discovery for example ( my next PR just like this one ). For reload, I am currently testing to see if and how its possible.

Even moving a few tests in this manner, would be beneficial, imo.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

so the idea is not to refactor all the tests, but only some where such changes would be possible. The example you mention with config watcher would not undergo such refactoring for the reason you mention

@@ -77,6 +77,7 @@
</execution>
</executions>
<configuration>
<classesDirectory>${project.build.outputDirectory}</classesDirectory>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

without this, I was getting:

[INFO] Running org.springframework.cloud.kubernetes.fabric8.catalog.watch.Fabric8CatalogWatchWithEndpointSlicesIT
[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.14 s <<< FAILURE! - in org.springframework.cloud.kubernetes.fabric8.catalog.watch.Fabric8CatalogWatchWithEndpointSlicesIT
[ERROR] org.springframework.cloud.kubernetes.fabric8.catalog.watch.Fabric8CatalogWatchWithEndpointSlicesIT  Time elapsed: 0.139 s  <<< ERROR!
java.lang.IllegalStateException: Failed to find merged annotation for @org.springframework.test.context.BootstrapWith(org.springframework.boot.test.context.SpringBootTestContextBootstrapper.class)

I was searching a bit and found this one

Copy link
Contributor

Choose a reason for hiding this comment

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

When was this error occurring? All the time? Or is it because of the changes here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

only because of the changes I did in this PR, we were not getting this one until now.

Copy link
Contributor

Choose a reason for hiding this comment

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

Do you know why?

Copy link
Contributor Author

@wind57 wind57 Oct 11, 2024

Choose a reason for hiding this comment

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

honestly, no, I did not even bother to investigate too much. I was so hyped by the much lower testing times that I almost forgot about this change at all :D

@wind57 wind57 changed the title Refactor integration tests 1 Refactor catalog watch integration tests Oct 5, 2024
@wind57 wind57 changed the title Refactor catalog watch integration tests Refactor fabric8 catalog watch integration tests Oct 5, 2024
@@ -406,10 +406,12 @@ private void waitForDeploymentToBeDeleted(String namespace, Deployment deploymen

Map<String, String> matchLabels = deployment.getSpec().getSelector().getMatchLabels();

long start = System.currentTimeMillis();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

minor debugging here, eventually I will get rid of these statements too, but they do not hurt anyway

@@ -79,7 +79,9 @@ public static String wiremockVersion() {
}

public static void loadBusybox(K3sContainer container) {
Commons.load(container, BUSYBOX_TAR, BUSYBOX, busyboxVersion());
if (!imageAlreadyInK3s(container, BUSYBOX_TAR)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

another thing that I realized: we might already have the image in K3S (only the ones we use to tests like busybox or wiremock), so there is no need to tar it and then move it to the cluster, since its already there. As I progress with refactor, this method will happen for all images

@wind57 wind57 marked this pull request as ready for review October 6, 2024 13:18
@wind57
Copy link
Contributor Author

wind57 commented Oct 6, 2024

@ryanjbaxter first IT refactor

@wind57 wind57 changed the title Refactor fabric8 catalog watch integration tests Refactor fabric8 catalog watch integration tests (1) Oct 9, 2024
@wind57 wind57 requested a review from ryanjbaxter October 11, 2024 07:08
@wind57
Copy link
Contributor Author

wind57 commented Oct 15, 2024

so what do you think? should I be looking at other integration tests that can be refactored in this manner?

@ryanjbaxter ryanjbaxter added this to the 3.1.4 milestone Oct 15, 2024
@ryanjbaxter
Copy link
Contributor

Yes! Sorry your response got lost in my email I think. Appreciate the effort here!

@ryanjbaxter ryanjbaxter merged commit a27bf65 into spring-cloud:3.1.x Oct 15, 2024
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
No open projects
Status: Done
Status: Done
Development

Successfully merging this pull request may close these issues.

3 participants