dasniko / testcontainers-keycloak

A Testcontainer implementation for Keycloak IAM & SSO.
Apache License 2.0
328 stars 51 forks source link

Extension packaging seems to rely on maven to be in use #62

Closed davipc closed 2 years ago

davipc commented 2 years ago

When trying to startup a test keycloak container to test a rest extension, in this part it seems to assume Maven is being used. When using gradle, I get this exception:

Caused by: java.nio.file.NoSuchFileException: target/keycloak13563541036773513476.jar
    at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:92)
    at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111)
    at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:116)
    at java.base/sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:219)
    at java.base/java.nio.file.Files.newByteChannel(Files.java:370)
    at java.base/java.nio.file.Files.createFile(Files.java:647)
    at java.base/java.nio.file.TempFileHelper.create(TempFileHelper.java:137)
    at java.base/java.nio.file.TempFileHelper.createTempFile(TempFileHelper.java:160)
    at java.base/java.nio.file.Files.createTempFile(Files.java:867)
    at dasniko.testcontainers.keycloak.KeycloakContainer.createKeycloakExtensionDeployment(KeycloakContainer.java:220)

The problematic assumption IMO is here: https://github.com/dasniko/testcontainers-keycloak/blob/2.1.1/src/main/java/dasniko/testcontainers/keycloak/KeycloakContainer.java#L220

There are some references in README.md to paths that also assume the use of Maven, in this related block: https://github.com/dasniko/testcontainers-keycloak/blob/main/README.md?plain=1#L165

For a gradle build, it works with "java/main" rather than "target/classes".

I've found an easy workaround, which I'm using until this is fixed: to create a target folder in the root of the module/application where the test will run.

I hope this helps, and thanks for the amazing plugin, it's helping me a lot!

dasniko commented 2 years ago

Hi, thanks for the hint. You are right, I'm using Maven defaults here, as it is still the most used tool. And you are the first asking for Gradel support ;) Unfortunately I don't have any Gradle experience and thus it will take some time to dig into it.

davipc commented 2 years ago

Hi Niko, Ah, I didn't know it didn't have support. For some reason, it worked fine with gradle on version 1.8.0. For 2.1.1 it works without issues, except for that hard-coded directory. If there was a way to parameterize the build lib dir, it would make it build-automation-tool agnostic. Just an idea: maybe a new method for allowing to set that up would help?

    public KeycloakContainer withBuildLibDir(File buildLibDir) {
        this.buildLibDir = buildLibDir;
        return self();
    }

There may be other ways to do it, but this way you could still stick to a default dir (maven's?), while allowing the setting of different ones for different or customized build automation tools.

dasniko commented 2 years ago

It worked previously by accident. In earlier versions I just mounted the given folder (e.g. target/classes) into the container, so if you specified a Gradle specific output folder, it worked. But this approach didn't work with remote Docker executions and also in the Quarkus distribution, using an expanded archive (folder) doesn't work any more. So I had to change it to build an archive and copy it into the container. That's where this issues starts... ;)

So, as I'm don't know Gradle enough... Can we assume, that, when we specify an extension folder, like "java/main", I can create the local temporary archive file in the "java" folder? Like I do it with "target" from "target/classes". So I could dynamically derive the temporary folder from the given extension folder...

Of course, I could even use some temp or user directory from the system properties, and keeping fingers crossed that it is set. That's the advantage from using a folder in the project directory, I can assume that - at least the project folder itself - is there, otherwise we can't execute the code ;) Perhaps I should just use the project root folder to create the temp archive, as it's been deleted anyways...

I'm talking ab bit too much sometimes, but sorting the thoughts, before implementing code is always a good thing to do ;)

dasniko commented 2 years ago

Hey @davipc would you mind to test a fix on the development branch with tag development-SNAPSHOT with the help of JitPack: https://jitpack.io/#dasniko/testcontainers-keycloak/development-SNAPSHOT Your feedback is appreciated! Thanks.

davipc commented 2 years ago

Hi @dasniko,

Sorry for not coming back to you earlier... this week has been crazy here. Thanks for looking into this so promptly. I'll try to answer your questions from 2 comments above, then the last one.

Can we assume, that, when we specify an extension folder, like "java/main", I can create the local temporary archive file in the "java" folder? Like I do it with "target" from "target/classes". So I could dynamically derive the temporary folder from the given extension folder...

Unfortunately no... in standard gradle projects the source and build directories have different structures. Like in here:

image

Perhaps I should just use the project root folder to create the temp archive, as it's been deleted anyways... I think this is probably the safest approach.

I'm talking a bit too much sometimes, but sorting the thoughts, before implementing code is always a good thing to do ;) No man, you're good. I guess most developers do the same, even if only in their heads. ;-)

Let me test that snapshot branch now, I'll send another comment once I'm done.

davipc commented 2 years ago

It worked like a charm!

I'd have only one suggestion to (IMO) improve it: to create the file inside some temporary directory... so in case there is a crash while running tests, the file doesn't end up hanging in the root project folder, where it could more easily end up being checked in, or cause confusion.

Something like a testcontainer-work or testcontainer-tmp directory maybe?

But again, it already works as it is.

Cheers, Davi

dasniko commented 2 years ago

Thanks for the feedback πŸ™

I also thought about the directory... but, stupid me, there's a much more simpler solution to that.... Just use Files.createTempFile("prefix", "suffix") and the file is created automatically in the systems temporary directory. No hassle with project directories.

...it's always got to know the APIs... πŸ˜³πŸ™„πŸ˜‡

davipc commented 2 years ago

of course, much better :-) thanks @dasniko