diff --git a/web/crux/src/app/registry/registry-clients/github-api-client.ts b/web/crux/src/app/registry/registry-clients/github-api-client.ts index 66e879ec8..05a995a08 100644 --- a/web/crux/src/app/registry/registry-clients/github-api-client.ts +++ b/web/crux/src/app/registry/registry-clients/github-api-client.ts @@ -75,7 +75,8 @@ class GithubRegistryClient implements RegistryApiClient { async labels(image: string, tag: string): Promise> { // NOTE(@robot9706): ghcr.io expects the accept manifest to be "v1" but it responds with v2 manifests const labelClient = new V2Labels( - 'ghcr.io', + REGISTRY_GITHUB_URL, + this.imageNamePrefix, { headers: this.basicAuthHeaders, }, diff --git a/web/crux/src/app/registry/registry-clients/gitlab-api-client.ts b/web/crux/src/app/registry/registry-clients/gitlab-api-client.ts index 9c5b29f0a..931e7f939 100644 --- a/web/crux/src/app/registry/registry-clients/gitlab-api-client.ts +++ b/web/crux/src/app/registry/registry-clients/gitlab-api-client.ts @@ -84,9 +84,10 @@ export class GitlabRegistryClient implements RegistryApiClient { } async labels(image: string, tag: string): Promise> { - const labelClient = new V2Labels(this.urls.registryUrl, null, null, { + const labelClient = new V2Labels(this.urls.registryUrl, null, null, null, { headers: this.basicAuthHeaders, }) + return labelClient.fetchLabels(image, tag) } } diff --git a/web/crux/src/app/registry/registry-clients/google-api-client.ts b/web/crux/src/app/registry/registry-clients/google-api-client.ts index ae9f2b15e..0719e6b55 100644 --- a/web/crux/src/app/registry/registry-clients/google-api-client.ts +++ b/web/crux/src/app/registry/registry-clients/google-api-client.ts @@ -101,11 +101,12 @@ export class GoogleRegistryClient implements RegistryApiClient { await this.registryCredentialsToBearerAuth() } - const labelClient = new V2Labels(this.url, { + const labelClient = new V2Labels(this.url, null, { headers: { Authorization: (this.headers as Record).Authorization, }, }) + return labelClient.fetchLabels(image, tag) } } diff --git a/web/crux/src/app/registry/registry-clients/hub-api-client.ts b/web/crux/src/app/registry/registry-clients/hub-api-client.ts index 0eb60a2a7..93c32eb9f 100644 --- a/web/crux/src/app/registry/registry-clients/hub-api-client.ts +++ b/web/crux/src/app/registry/registry-clients/hub-api-client.ts @@ -81,6 +81,7 @@ export default abstract class HubApiClient { async labels(image: string, tag: string): Promise> { const labelClient = new V2Labels(DOCKER_HUB_REGISTRY_URL) + return labelClient.fetchLabels(this.prefix ? `${this.prefix}/${image}` : image, tag) } } diff --git a/web/crux/src/app/registry/registry-clients/private-hub-api-client.ts b/web/crux/src/app/registry/registry-clients/private-hub-api-client.ts index e6fa15898..92eb58798 100644 --- a/web/crux/src/app/registry/registry-clients/private-hub-api-client.ts +++ b/web/crux/src/app/registry/registry-clients/private-hub-api-client.ts @@ -87,7 +87,8 @@ export default class PrivateHubApiClient extends HubApiClient implements Registr } async labels(image: string, tag: string): Promise> { - const labelClient = new V2Labels(DOCKER_HUB_REGISTRY_URL, null, null, this.labelsAuth) + const labelClient = new V2Labels(DOCKER_HUB_REGISTRY_URL, null, null, null, this.labelsAuth) + return labelClient.fetchLabels(this.prefix ? `${this.prefix}/${image}` : image, tag) } } diff --git a/web/crux/src/app/registry/registry-clients/v2-api-client.ts b/web/crux/src/app/registry/registry-clients/v2-api-client.ts index 124d9ed26..3f9847fa9 100644 --- a/web/crux/src/app/registry/registry-clients/v2-api-client.ts +++ b/web/crux/src/app/registry/registry-clients/v2-api-client.ts @@ -68,9 +68,10 @@ class RegistryV2ApiClient implements RegistryApiClient { } async labels(image: string, tag: string): Promise> { - const labelClient = new V2Labels(this.url, { + const labelClient = new V2Labels(this.url, null, { headers: this.headers, }) + return labelClient.fetchLabels(image, tag) } diff --git a/web/crux/src/app/registry/registry-clients/v2-labels.ts b/web/crux/src/app/registry/registry-clients/v2-labels.ts index ebffe9163..6f57545aa 100644 --- a/web/crux/src/app/registry/registry-clients/v2-labels.ts +++ b/web/crux/src/app/registry/registry-clients/v2-labels.ts @@ -67,10 +67,11 @@ export default class V2Labels { private requestInit: RequestInit constructor( - private baseUrl: string, + private readonly baseUrl: string, + private readonly imageNamePrefix?: string, requestInit?: RequestInit, manifestMime?: string, - private tokenInit?: RequestInit, + private readonly tokenInit?: RequestInit, ) { this.requestInit = requestInit ?? {} this.requestInit = { @@ -130,17 +131,21 @@ export default class V2Labels { const tokenService = params.service const tokenScope = params.scope + const tokenInit = this.tokenInit ?? this.requestInit + const tokenUrl = `${tokenServer}?service=${encodeURIComponent(tokenService)}&scope=${encodeURIComponent( tokenScope, )}` this.logger.debug(`Fetching token from '${tokenUrl}'`) - const tokenResponse = await fetch(tokenUrl, this.tokenInit) + const tokenResponse = await fetch(tokenUrl, tokenInit) this.logger.debug(`Got token response for '${tokenUrl}' - ${tokenResponse.status}`) if (tokenResponse.status !== 200) { + this.logger.error('V2 token fetch failed', tokenResponse.status, await tokenResponse.text()) + throw new CruxInternalServerErrorException({ message: 'Failed to fetch V2 token', }) @@ -206,6 +211,7 @@ export default class V2Labels { return null } + this.logger.error('V2 API fetch failed', result.res.status, result.data) throw new CruxInternalServerErrorException({ message: 'Failed to fetch v2 API!', }) @@ -214,7 +220,7 @@ export default class V2Labels { return result.data } - async fetchLabelsByManifest( + private async fetchLabelsByManifest( image: string, manifest: ManifestBaseResponse, depth: number, @@ -259,11 +265,16 @@ export default class V2Labels { } async fetchLabels(image: string, tag: string): Promise> { + if (this.imageNamePrefix) { + image = `${this.imageNamePrefix}/${image}` + } + const manifest = await this.fetchV2(`${image}/manifests/${tag ?? 'latest'}`, { headers: { Accept: this.manifestMimeType, }, }) + if (!manifest) { return {} }