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

Add dev services for kubernetes #28305

Merged
merged 1 commit into from
Oct 28, 2022
Merged

Add dev services for kubernetes #28305

merged 1 commit into from
Oct 28, 2022

Conversation

scrocquesel
Copy link
Contributor

Closes #28189

Some design advices are more than welcome to adjust some behavior of dev service for kubernetes:

  • Currently some integration tests like openshift-client use k8s mock server provided by AbstractKubernetesTestResource. This set systemProps to be read by fabric8 client and return config properties with key of the same key name. The kubernetes-client extension override those values with quarkus.* properties if any. The issue is that Dev services return the configuration as quarkus properties and if not disabled, it will override the configuration to connect to the Mock Server. Disabling dev services when mock server is used seems not doable.
    I guess a lot of people are using the Mock Server do to their tests and would experience a breaking change.

    Should dev service be disabled by default ?
    Should AbstractKubernetesTestResource be updated to return ``quarkus.` prefixed properties instead of fabric8 systemProps properties (not sure if this would work) ?
    Should we disable dev services manually in those project assuming the breaking change in behavior ?

  • dev services for Kubernetes do its best to detect if a kubernetes configuration is defined so that the developer or test runner can use its own current kubeconfig. While, I think this is a valid default use case, it is not so easy to force dev services to start a cluster. This differs from how other dev services work because there is generally no such thing as a config file in home directory or env var for client of databases/message broker/..., and it should be rare a user defines master-url manually to disable dev services.
    Quarkus extension first build a fabric8 Config object and call autoconfigure on it inconditionally. If a kubeconfig is found, master-url will be set. Therefore, user needs to pass -Dkubernetes.auth.tryKubeConfig=false when running test or dev mode to bypass any kubeconfig present in home directory. Dev services use same logic to guess if master-url would be set at runtime and decide if a cluster should be started.
    In my case, and I think some user will be in the same case, I have a valid k8s cluster but still would prefer to use dev service cluster to isolate dev and tests and have automatic cleanup when stopping dev mode.
    Should a quarkus.kubernetes-client.auto-configure (or quarkus.kubernetes-client.devservices.override-kubeconfig`) be added to disable the fabric8 autoconfigure behavior ? At least, this property could be set in properties or dotenv file.

  • Regarding docker image name, current testcontainer implementation used to start a api server only cluster do not allow to pass a docker image name for the api server and etcd containers. It is possible to specify a version if it is supported by the package (see https://github.com/dajudge/kindcontainer/blob/master/k8s-versions.json). If a user needs to change the registry name/path, it must provide a testcontainer image name substitutor. Do you have any concern about this ?

@quarkus-bot
Copy link

quarkus-bot bot commented Sep 29, 2022

Thanks for your pull request!

The title of your pull request does not follow our editorial rules. Could you have a look?

  • title should preferably start with an uppercase character (if it makes sense!)
  • title should not start with chore/docs/feat/fix/refactor but be a proper sentence

This message is automatically generated by a bot.

@scrocquesel scrocquesel changed the title feat: add dev services for kubernetes Add dev services for kubernetes Sep 29, 2022
@scrocquesel scrocquesel force-pushed the gh-28189 branch 3 times, most recently from fd12643 to 922af72 Compare October 1, 2022 09:58
@scrocquesel
Copy link
Contributor Author

1/, I find out how to disable dev services when quarkus-test-kubernetes-client is imported. For now, it is one or another.
2/, added a devservices.override-kubeconfig property.

@scrocquesel scrocquesel force-pushed the gh-28189 branch 2 times, most recently from 11e2723 to 1328373 Compare October 1, 2022 14:33
@scrocquesel scrocquesel marked this pull request as ready for review October 1, 2022 14:35
@quarkus-bot

This comment has been minimized.

@geoand
Copy link
Contributor

geoand commented Oct 3, 2022

Thanks for this!

We'll have to take a close look and get back to you.

Copy link
Contributor

@Sgitario Sgitario left a comment

Choose a reason for hiding this comment

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

Apart from my comments, I think we should cover the new dev services as part of the existing integration-tests/kubernetes-client module.
There is an internal testing framework we can use for this (see @QuarkusDevModeTest).

<dependency>
<groupId>com.dajudge.kindcontainer</groupId>
<artifactId>kindcontainer</artifactId>
<version>1.3.0</version>
Copy link
Contributor

Choose a reason for hiding this comment

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

I think all the versions we provide should be declared in bom/application/pom.xml

Copy link
Contributor

Choose a reason for hiding this comment

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

Does this work on all platforms?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, but AFAIK it can't be tested with windows container, so test should be disable in Windows test profile.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Apart from my comments, I think we should cover the new dev services as part of the existing integration-tests/kubernetes-client module. There is an internal testing framework we can use for this (see @QuarkusDevModeTest).

@Sgitario integration-tests/kubernetes-client use quarkus-test-kubernetes-client and its AbstractKubernetesTestResource which already set fabric8 systemProps and dev services may interfere. Moreover, from my understanding, @QuarkusDevModeTest start the apps in Dev Mode after dev services already starts in Test mode as part of the buildStep.

import java.util.Arrays;
import java.util.function.BooleanSupplier;

class NoQuarkusTestKubernetesClient implements BooleanSupplier {
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't see what is the purpose of this logic, can you please clarify?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This refer to the first point in description. io.quarkus.test.kubernetes.client package contains all quarkus mock server test class used to actually mock kubernetes. This is the package that I think most people use to write unit test. It is not compatible with dev services because they barely do the same thing to configure a KubernetesClient to connect to the test server. Dev services wins because quarkus properties override the system props properties, but it can't detect it because systemProps are set latter by a test resource class. Thus, all existing unit test would fail if we don't disable dev services when the mock package is used.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think that we need a couple of things here:

  • a more descriptive name
  • a comment that explain(s) why?
  • documentation
  • (optionally) create a feature requrest to allow for multiple clients with qualifiers.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added documentation and guide. First time doing this.

.orElseGet(() -> latest(KindContainerVersion.class)));
break;
default:
throw new RuntimeException();
Copy link
Contributor

Choose a reason for hiding this comment

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

We should throw a descriptive message here.

user.getClientCertificateData(),
"quarkus.kubernetes-client.client-key-data", user.getClientKeyData(),
"quarkus.kubernetes-client.client-key-algo", Config.getKeyAlgorithm(null, user.getClientKeyData()),
"quarkus.kubernetes-client.namespace", "default");
Copy link
Contributor

Choose a reason for hiding this comment

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

Are we always using the "default" namespace on purpose? This can be set from kubeconfig as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually, the test container starts with only the default namespace. We may support additional namespace by adding additional devservices config. But it can be done in a second step, there is a lot that can be configured at startup like applying yaml resource.

return new KubernetesDevServiceCfg(devServicesConfig);
}

private static final class KubernetesDevServiceCfg {
Copy link
Contributor

Choose a reason for hiding this comment

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

I never implemented a dev service, but why do we need this class instead of using directly KubernetesClientBuildConfig?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I reuse the logic from elsewhere. The difference is that the class must implements equals to be able to detect changes.


public Map<String, String> getKubeconfig() {
var image = getContainerInfo().getConfig().getImage();
if (image.contains("rancher/k3s")) {
Copy link
Contributor

Choose a reason for hiding this comment

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

shouldn't we use the flavor instead of the image to do this logic?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unfortunately, when attaching to a running container we can just describe the container and do some reverse logic to guess what dev services config was used to actually build it. I think of image name or a label applied at creation and choose the former.

Copy link
Contributor

Choose a reason for hiding this comment

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

In theory one could bring their own image, so generally a label is preferable.

return getKubernetesClientConfigFromKubeConfig(getKubeconfigFromApiContainer(containerAddress.getUrl()));
}

throw new RuntimeException();
Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Sgitario I don't see where the link point at.

@quarkus-bot quarkus-bot bot added the area/dependencies Pull requests that update a dependency file label Oct 5, 2022
@iocanel iocanel self-requested a review October 14, 2022 07:10
Copy link
Contributor

@iocanel iocanel left a comment

Choose a reason for hiding this comment

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

Overall looks good.

I am a bit sceptic about the handling of the conflict with the mock client.
Maybe the simplest solution would be to just log a warning and if user decides to disable the devservices. That might be simpler / cleaner. I don't mind the current approach as long as we document it.

So both ways are fine by me.

import java.util.Arrays;
import java.util.function.BooleanSupplier;

class NoQuarkusTestKubernetesClient implements BooleanSupplier {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think that we need a couple of things here:

  • a more descriptive name
  • a comment that explain(s) why?
  • documentation
  • (optionally) create a feature requrest to allow for multiple clients with qualifiers.

@scrocquesel
Copy link
Contributor Author

One last blocking issue, I can't find out how to not run integration test for JDK 11 Windows Container job. It fails because docker is not available in those jobs. Help wanted.

@scrocquesel scrocquesel requested a review from iocanel October 15, 2022 15:19
@quarkus-bot

This comment has been minimized.

@iocanel
Copy link
Contributor

iocanel commented Oct 26, 2022

One last blocking issue, I can't find out how to not run integration test for JDK 11 Windows Container job. It fails because docker is not available in those jobs. Help wanted.

@geoand? Any ideas?

@geoand
Copy link
Contributor

geoand commented Oct 26, 2022

I'll have a look later on

Copy link
Contributor

@iocanel iocanel left a comment

Choose a reason for hiding this comment

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

LGTM
Once the CI issues are addressed we can merge.

@geoand
Copy link
Contributor

geoand commented Oct 26, 2022

One last blocking issue, I can't find out how to not run integration test for JDK 11 Windows Container job. It fails because docker is not available in those jobs. Help wanted.

Not sure what you mean here. We intentionally don't run container related tests on Windows. Is there a test that is running that shouldn't be?

@scrocquesel
Copy link
Contributor Author

One last blocking issue, I can't find out how to not run integration test for JDK 11 Windows Container job. It fails because docker is not available in those jobs. Help wanted.

Not sure what you mean here. We intentionally don't run container related tests on Windows. Is there a test that is running that shouldn't be?

That's what I observed on CI but not locally see https://github.com/scrocquesel/quarkus/actions/runs/3256150273

@scrocquesel
Copy link
Contributor Author

One last blocking issue, I can't find out how to not run integration test for JDK 11 Windows Container job. It fails because docker is not available in those jobs. Help wanted.

Not sure what you mean here. We intentionally don't run container related tests on Windows. Is there a test that is running that shouldn't be?

That's what I observed on CI but not locally see https://github.com/scrocquesel/quarkus/actions/runs/3256150273

The test that should not run are those added by this PR

@geoand
Copy link
Contributor

geoand commented Oct 27, 2022

I still don't see which Kubernetes tests you say are failing on the Windows run.

@scrocquesel
Copy link
Contributor Author

I still don't see which Kubernetes tests you say are failing on the Windows run.

You are right. As the job keep failing, I thought it was the new test.

@geoand
Copy link
Contributor

geoand commented Oct 27, 2022

Can you please rebase onto main so we can be sure nothing has broken in the meantime?
If CI is good after that, let's merge

@quarkus-bot

This comment has been minimized.

@quarkus-bot
Copy link

quarkus-bot bot commented Oct 28, 2022

Failing Jobs - Building 4f32580

Status Name Step Failures Logs Raw logs
✔️ JVM Tests - JDK 11
JVM Tests - JDK 11 Windows Build Failures Logs Raw logs
✔️ JVM Tests - JDK 17
✔️ JVM Tests - JDK 17 MacOS M1
JVM Tests - JDK 18 Build Failures Logs Raw logs

Full information is available in the Build summary check run.

Failures

⚙️ JVM Tests - JDK 11 Windows #

- Failing: extensions/opentelemetry/deployment 
! Skipped: integration-tests/micrometer-prometheus integration-tests/opentelemetry integration-tests/opentelemetry-grpc and 5 more

📦 extensions/opentelemetry/deployment

io.quarkus.opentelemetry.deployment.instrumentation.RestClientOpenTelemetryTest.client line 65 - More details - Source on GitHub

org.opentest4j.AssertionFailedError: expected: <SERVER> but was: <CLIENT>
	at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
	at org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)

⚙️ JVM Tests - JDK 18 #

- Failing: integration-tests/elytron-undertow 

📦 integration-tests/elytron-undertow

io.quarkus.it.undertow.elytron.BaseAuthRestTest.testPost line 28 - More details - Source on GitHub

java.lang.AssertionError: 
1 expectation failed.
Expected status code <200> but was <500>.

@geoand geoand merged commit 3d77353 into quarkusio:main Oct 28, 2022
@quarkus-bot quarkus-bot bot added this to the 2.15 - main milestone Oct 28, 2022
@quarkus-bot quarkus-bot bot added kind/enhancement New feature or request and removed triage/waiting-for-ci Ready to merge when CI successfully finishes labels Oct 28, 2022
@gsmet gsmet modified the milestones: 2.15 - main, 2.14.0.Final Oct 28, 2022
@gsmet gsmet modified the milestones: 2.14.0.Final, 2.15 - main Oct 31, 2022
@gsmet
Copy link
Member

gsmet commented Oct 31, 2022

Hmmm, I think it's too big of a behavioral change to get backported post CR1, especially since I saw some CI failures that might be related to it. Let's give it some bake time.

Sgitario added a commit to Sgitario/quarkus that referenced this pull request Oct 31, 2022
These tests are executed in the Windows machine where there is no Docker instance running. 
Related to the changes in quarkusio#28305
Related to CI failures like https://github.com/quarkusio/quarkus/runs/9165337690#user-content-test-failure-org.acme.applicationconfigresourcetest-1
////
= Dev Services for Kubernetes
include::_attributes.adoc[]
:categories: messaging
Copy link
Contributor

Choose a reason for hiding this comment

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

A little late for this but I suspect this category isn't correct…

Copy link
Member

Choose a reason for hiding this comment

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

@metacosm I will have a look thanks

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My bad. Should be cloud I guess like other k8s pages.

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.

Dev services for Kubernetes client
6 participants