diff --git a/packages/testcontainers/src/container-runtime/auth/credential-provider.test.ts b/packages/testcontainers/src/container-runtime/auth/credential-provider.test.ts index feb541c29..9a2c553bf 100644 --- a/packages/testcontainers/src/container-runtime/auth/credential-provider.test.ts +++ b/packages/testcontainers/src/container-runtime/auth/credential-provider.test.ts @@ -21,7 +21,6 @@ describe.sequential("CredentialProvider", () => { }); it("should return the auth config for a registry", async () => { - mockExecReturns(JSON.stringify({ registry: "username" })); mockSpawnReturns( 0, JSON.stringify({ @@ -40,24 +39,7 @@ describe.sequential("CredentialProvider", () => { }); }); - it("should not return auth config for registry which is a partial match", async () => { - mockExecReturns(JSON.stringify({ "https://registry.example.com": "username" })); - mockSpawnReturns( - 0, - JSON.stringify({ - ServerURL: "https://registry.example.com", - Username: "username", - Secret: "secret", - }) - ); - - expect( - await credentialProvider.getAuthConfig("https://registry.example.co", containerRuntimeConfig) - ).toBeUndefined(); - }); - it("should default to the registry url when the server url is not returned", async () => { - mockExecReturns(JSON.stringify({ "https://registry.example.com": "username" })); mockSpawnReturns( 0, JSON.stringify({ @@ -66,55 +48,20 @@ describe.sequential("CredentialProvider", () => { }) ); - expect(await credentialProvider.getAuthConfig("https://registry.example.com", containerRuntimeConfig)).toEqual({ - registryAddress: "https://registry.example.com", + expect(await credentialProvider.getAuthConfig("registry.example.com", containerRuntimeConfig)).toEqual({ + registryAddress: "registry.example.com", username: "username", password: "secret", }); }); - it("should return undefined when no auth config found for registry", async () => { - mockExecReturns(JSON.stringify({ registry2: "username" })); - - const credentials = await credentialProvider.getAuthConfig("registry1", containerRuntimeConfig); - - expect(credentials).toBeUndefined(); - }); - it("should return undefined when provider name not provided", async () => { - const credentialProvider = new TestCredentialProvider("name", undefined!); + const credentialProvider = new TestCredentialProvider("name", undefined); expect(await credentialProvider.getAuthConfig("registry", containerRuntimeConfig)).toBeUndefined(); }); - it("should throw when list credentials fails", async () => { - mockExecThrows(); - - await expect(() => credentialProvider.getAuthConfig("registry", containerRuntimeConfig)).rejects.toThrow( - "An error occurred listing credentials" - ); - }); - - it("should throw when list credentials output cannot be parsed", async () => { - mockExecReturns("CANNOT_PARSE"); - - await expect(() => credentialProvider.getAuthConfig("registry", containerRuntimeConfig)).rejects.toThrow( - "Unexpected response from Docker credential provider LIST command" - ); - }); - - it("should not throw when list credentials command is not implemented", async () => { - mockExec.mockImplementationOnce((command, callback) => { - return callback(new Error(), null, "list is unimplemented\n"); - }); - - const credentials = await credentialProvider.getAuthConfig("registry", containerRuntimeConfig); - - expect(credentials).toBeUndefined(); - }); - it("should throw when get credentials fails", async () => { - mockExecReturns(JSON.stringify({ registry: "username" })); mockSpawnReturns( 1, JSON.stringify({ @@ -130,7 +77,6 @@ describe.sequential("CredentialProvider", () => { }); it("should throw when get credentials output cannot be parsed", async () => { - mockExecReturns(JSON.stringify({ registry: "username" })); mockSpawnReturns(0, "CANNOT_PARSE"); await expect(() => credentialProvider.getAuthConfig("registry", containerRuntimeConfig)).rejects.toThrow( @@ -139,18 +85,6 @@ describe.sequential("CredentialProvider", () => { }); }); -function mockExecReturns(stdout: string) { - mockExec.mockImplementationOnce((command, callback) => { - return callback(null, stdout); - }); -} - -function mockExecThrows() { - mockExec.mockImplementationOnce((command, callback) => { - return callback("An error occurred"); - }); -} - function mockSpawnReturns(exitCode: number, stdout: string) { const sink = new EventEmitter() as ChildProcess; @@ -173,7 +107,7 @@ function mockSpawnReturns(exitCode: number, stdout: string) { class TestCredentialProvider extends CredentialProvider { constructor( private readonly name: string, - private readonly credentialProviderName: string + private readonly credentialProviderName: string | undefined ) { super(); } diff --git a/packages/testcontainers/src/container-runtime/auth/credential-provider.ts b/packages/testcontainers/src/container-runtime/auth/credential-provider.ts index fa3d95435..991baeece 100644 --- a/packages/testcontainers/src/container-runtime/auth/credential-provider.ts +++ b/packages/testcontainers/src/container-runtime/auth/credential-provider.ts @@ -1,13 +1,7 @@ -import { exec, spawn } from "child_process"; +import { spawn } from "child_process"; import { log } from "../../common"; import { RegistryAuthLocator } from "./registry-auth-locator"; -import { registryMatches } from "./registry-matches"; -import { - AuthConfig, - ContainerRuntimeConfig, - CredentialProviderGetResponse, - CredentialProviderListResponse, -} from "./types"; +import { AuthConfig, ContainerRuntimeConfig, CredentialProviderGetResponse } from "./types"; export abstract class CredentialProvider implements RegistryAuthLocator { abstract getName(): string; @@ -23,45 +17,15 @@ export abstract class CredentialProvider implements RegistryAuthLocator { const programName = `docker-credential-${credentialProviderName}`; log.debug(`Executing Docker credential provider "${programName}"`); - const credentials = await this.listCredentials(programName); - - const credentialForRegistry = Object.keys(credentials).find((aRegistry) => registryMatches(aRegistry, registry)); - if (!credentialForRegistry) { - log.debug(`No credential found for registry "${registry}"`); - return undefined; - } - const response = await this.runCredentialProvider(registry, programName); return { username: response.Username, password: response.Secret, - registryAddress: response.ServerURL ?? credentialForRegistry, + registryAddress: response.ServerURL ?? registry, }; } - private listCredentials(providerName: string): Promise { - return new Promise((resolve, reject) => { - exec(`${providerName} list`, (err, stdout, stderr) => { - if (err) { - if (stderr === "list is unimplemented\n") { - return resolve({}); - } - - log.error(`An error occurred listing credentials: ${err}`); - return reject(new Error("An error occurred listing credentials")); - } - try { - const response = JSON.parse(stdout); - return resolve(response); - } catch (e) { - log.error(`Unexpected response from Docker credential provider LIST command: "${stdout}"`); - return reject(new Error("Unexpected response from Docker credential provider LIST command")); - } - }); - }); - } - private runCredentialProvider(registry: string, providerName: string): Promise { return new Promise((resolve, reject) => { const sink = spawn(providerName, ["get"]);