testcontainers / testcontainers-java

Testcontainers is a Java library that supports JUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.
https://testcontainers.org
MIT License
8.03k stars 1.65k forks source link

[Bug]: Failure when attempting to lookup auth config... Exception message: Unrecognized token 'credentials': was expecting ('true', 'false' or 'null') #9478

Open AB-xdev opened 2 weeks ago

AB-xdev commented 2 weeks ago

Module

Core

Testcontainers version

1.20.3

Using the latest Testcontainers version?

Yes

Host OS

Windows 10

Host Arch

x64

Docker version

Client: Version: 27.2.0 API version: 1.47 Go version: go1.21.13 Git commit: 3ab4256 Built: Tue Aug 27 14:17:17 2024 OS/Arch: windows/amd64 Context: desktop-linux

Server: Docker Desktop 4.34.3 (170107) Engine: Version: 27.2.0 API version: 1.47 (minimum version 1.24) Go version: go1.21.13 Git commit: 3ab5c7d Built: Tue Aug 27 14:15:15 2024 OS/Arch: linux/amd64 Experimental: false containerd: Version: 1.7.20 GitCommit: 8fc6bcff51318944179630522a095cc9dbf9f353 runc: Version: 1.1.13 GitCommit: v1.1.13-0-g58aa920 docker-init: Version: 0.19.0 GitCommit: de40ad0

What happened?

When running Testcontainers the following is written to the log:

08:02:21 INFO  [ducttape-0] [ility.RegistryAuthLocator] Failure when attempting to lookup auth config. Please ignore if you don't have images in an authenticated registry. Details: (dockerImageName: testcontainers/ryuk:0.9.0, configFile: C:\Users\xxx\.docker\config.json, configEnv: DOCKER_AUTH_CONFIG). Falling back to docker-java default behaviour. Exception message: Unrecognized token 'credentials': was expecting ('true', 'false' or 'null')
 at [Source: credentials not found in native keychain; line: 1, column: 12] 
Full exception (acquired using debbugger; why is the exception stacktrace cut off and not rethrown?) ``` org.testcontainers.shaded.com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'credentials': was expecting ('true', 'false' or 'null') at [Source: credentials not found in native keychain; line: 1, column: 12] at org.testcontainers.shaded.com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1702) at org.testcontainers.shaded.com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:558) at org.testcontainers.shaded.com.fasterxml.jackson.core.json.ReaderBasedJsonParser._reportInvalidToken(ReaderBasedJsonParser.java:2839) at org.testcontainers.shaded.com.fasterxml.jackson.core.json.ReaderBasedJsonParser._handleOddValue(ReaderBasedJsonParser.java:1903) at org.testcontainers.shaded.com.fasterxml.jackson.core.json.ReaderBasedJsonParser.nextToken(ReaderBasedJsonParser.java:749) at org.testcontainers.shaded.com.fasterxml.jackson.databind.ObjectMapper._initForReading(ObjectMapper.java:3834) at org.testcontainers.shaded.com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3783) at org.testcontainers.shaded.com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:2381) at org.testcontainers.utility.RegistryAuthLocator.runCredentialProvider(RegistryAuthLocator.java:318) at org.testcontainers.utility.RegistryAuthLocator.authConfigUsingStore(RegistryAuthLocator.java:251) at org.testcontainers.utility.RegistryAuthLocator.lookupUncachedAuthConfig(RegistryAuthLocator.java:154) at org.testcontainers.utility.RegistryAuthLocator.lambda$lookupAuthConfig$0(RegistryAuthLocator.java:126) at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1708) at org.testcontainers.utility.RegistryAuthLocator.lookupAuthConfig(RegistryAuthLocator.java:124) at org.testcontainers.dockerclient.AuthDelegatingDockerClientConfig.effectiveAuthConfig(AuthDelegatingDockerClientConfig.java:45) at org.testcontainers.shaded.com.github.dockerjava.core.DockerClientImpl.createContainerCmd(DockerClientImpl.java:390) at com.github.dockerjava.api.DockerClientDelegate.createContainerCmd(DockerClientDelegate.java:199) at com.github.dockerjava.api.DockerClientDelegate.createContainerCmd(DockerClientDelegate.java:199) at org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:380) at org.testcontainers.containers.GenericContainer.lambda$doStart$0(GenericContainer.java:346) at org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:81) at org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:336) at org.testcontainers.containers.GenericContainer.start(GenericContainer.java:322) at org.testcontainers.utility.RyukResourceReaper.maybeStart(RyukResourceReaper.java:78) at org.testcontainers.utility.RyukResourceReaper.init(RyukResourceReaper.java:42) at org.testcontainers.DockerClientFactory.client(DockerClientFactory.java:245) at software.xdev.testcontainers.imagebuilder.AdvancedImageFromDockerFile.resolve(AdvancedImageFromDockerFile.java:146) at software.xdev.testcontainers.imagebuilder.AdvancedImageFromDockerFile.resolve(AdvancedImageFromDockerFile.java:78) at org.testcontainers.utility.LazyFuture.getResolvedValue(LazyFuture.java:20) at org.testcontainers.utility.LazyFuture.get(LazyFuture.java:41) at java.base/java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:317) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) at java.base/java.lang.Thread.run(Thread.java:1583) ```

It looks like docker-credential-desktop is returning different (non-JSON) output, which results in the crash.

Relevant log output

No response

Additional Information

No response

AB-xdev commented 2 weeks ago

This might also be a Docker problem since it looks like it was previously expected that this error was returned to stderr not - like now - to stdout https://github.com/testcontainers/testcontainers-java/blob/77a423c812ad044c0a2076b7495eb298eb72f85b/core/src/main/java/org/testcontainers/utility/RegistryAuthLocator.java#L286-L300

eddumelendez commented 2 days ago

Hi, Can you try with latest Docker Desktop version?

I am running

▶ docker-credential-osxkeychain version
docker-credential-osxkeychain (github.com/docker/docker-credential-helpers) v0.8.0
▶ echo 'myregistry' | docker-credential-osxkeychain get
{"ServerURL":"myregistry","Username":"$oauthtoken","Secret":"myapitoken"}
▶ echo $?
0
▶ echo 'noregistry' | docker-credential-osxkeychain get
credentials not found in native keychain
▶ echo $?
1

And I see our tests are covering correctly this scenario

AB-xdev commented 1 day ago

Hi, Can you try with latest Docker Desktop version?

I'm running Docker Desktop v4.35.1 (currently the latest version) on Windows and nothing has changed.

echo "test" | docker-credential-desktop get still writes to stdout and not to (inside the code expected) stderr causing the above mentioned message to show up.

I walked in detail through the code with the debugger (although that's kind of hard because your .java files don't match your .class files because they are no de-lomboked!) and the following happens:

  1. https://github.com/testcontainers/testcontainers-java/blob/119627f5fe0ea25ba21a3b203ce801cf273d1eaa/core/src/main/java/org/testcontainers/utility/RegistryAuthLocator.java#L286 is executed. The returned data#stderr is empty, while data#stdout contains credentials not found in native keychain
  2. https://github.com/testcontainers/testcontainers-java/blob/119627f5fe0ea25ba21a3b203ce801cf273d1eaa/core/src/main/java/org/testcontainers/utility/RegistryAuthLocator.java#L287 stderr is checked. As it's empty the Credential helper/store ... does not have credentials will never be triggered and the process continues as if there are credentials
  3. https://github.com/testcontainers/testcontainers-java/blob/119627f5fe0ea25ba21a3b203ce801cf273d1eaa/core/src/main/java/org/testcontainers/utility/RegistryAuthLocator.java#L318 It tries to parse the stdout - where JSON input is expected - and fails because stdout is credentials not found in native keychain which is of course not JSON ;)