-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Refactor fabric8 catalog watch integration tests (1) #1755
Conversation
The main idea here is that I took an existing package of integration tests and re-factored it:
Logically, the tests have not changed at all, I changed the way we set-up thing. On my laptop, running the previous version (
and the current version:
|
@@ -42,6 +42,22 @@ | |||
<filtering>true</filtering> | |||
</resource> | |||
</resources> | |||
|
|||
<plugins> |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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> |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you know why?
There was a problem hiding this comment.
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
@@ -406,10 +406,12 @@ private void waitForDeploymentToBeDeleted(String namespace, Deployment deploymen | |||
|
|||
Map<String, String> matchLabels = deployment.getSpec().getSelector().getMatchLabels(); | |||
|
|||
long start = System.currentTimeMillis(); |
There was a problem hiding this comment.
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)) { |
There was a problem hiding this comment.
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
@ryanjbaxter first IT refactor |
so what do you think? should I be looking at other integration tests that can be refactored in this manner? |
Yes! Sorry your response got lost in my email I think. Appreciate the effort here! |
No description provided.