diff --git a/lib/datasource/docker/common.ts b/lib/datasource/docker/common.ts index b90cf21ea0892a4c829fef5d3d48b98c1c93cace..f50a1ae99dd4561aceecab74be98a3c5ffa78afb 100644 --- a/lib/datasource/docker/common.ts +++ b/lib/datasource/docker/common.ts @@ -196,7 +196,10 @@ export function getRegistryRepository( } let dockerRepository = split.join('/'); if (!registryHost) { - registryHost = registryUrl; + registryHost = registryUrl.replace( + 'https://docker.io', + 'https://index.docker.io' + ); } if (registryHost === 'docker.io') { registryHost = 'index.docker.io'; diff --git a/lib/datasource/docker/index.spec.ts b/lib/datasource/docker/index.spec.ts index 7be603c7cb522e30108636bf31fce85826ba422d..965c272c865995355b13b19a6a2daeaa3d90c24d 100644 --- a/lib/datasource/docker/index.spec.ts +++ b/lib/datasource/docker/index.spec.ts @@ -391,6 +391,7 @@ describe(getName(), () => { const res = await getPkgReleases({ datasource: id, depName: 'node', + registryUrls: ['https://docker.io'], }); expect(res).toBeNull(); expect(httpMock.getTrace()).toMatchSnapshot(); diff --git a/lib/datasource/docker/index.ts b/lib/datasource/docker/index.ts index 3c2739cdb337571ebacb8386a007dd88ea24f2c4..f81fc9f8de3b87a240bec528136fff1eb462563b 100644 --- a/lib/datasource/docker/index.ts +++ b/lib/datasource/docker/index.ts @@ -3,6 +3,7 @@ import parseLinkHeader from 'parse-link-header'; import { logger } from '../../logger'; import { ExternalHostError } from '../../types/errors/external-host-error'; import * as packageCache from '../../util/cache/package'; +import { ensurePathPrefix } from '../../util/url'; import { api as dockerVersioning, id as dockerVersioningId, @@ -65,7 +66,8 @@ async function getDockerApiTags( // AWS ECR limits the maximum number of results to 1000 // See https://docs.aws.amazon.com/AmazonECR/latest/APIReference/API_DescribeRepositories.html#ECR-DescribeRepositories-request-maxResults const limit = ecrRegex.test(registryHost) ? 1000 : 10000; - let url = `${registryHost}/v2/${dockerRepository}/tags/list?n=${limit}`; + let url = `${registryHost}/${dockerRepository}/tags/list?n=${limit}`; + url = ensurePathPrefix(url, '/v2'); const headers = await getAuthHeaders(registryHost, dockerRepository); if (!headers) { logger.debug('Failed to get authHeaders for getTags lookup'); diff --git a/lib/util/url.spec.ts b/lib/util/url.spec.ts index e6425b7a84a5eb016a5b09ae7321c8549ed13b6e..a3ed562d9ae067ecda6e5fd1f22e4e4ed505a70b 100644 --- a/lib/util/url.spec.ts +++ b/lib/util/url.spec.ts @@ -1,5 +1,6 @@ import { getName } from '../../test/util'; import { + ensurePathPrefix, parseUrl, resolveBaseUrl, trimTrailingSlash, @@ -77,4 +78,16 @@ describe(getName(), () => { expect(trimTrailingSlash('foo/')).toBe('foo'); expect(trimTrailingSlash('foo//////')).toBe('foo'); }); + + it('ensures path prefix', () => { + expect(ensurePathPrefix('https://index.docker.io', '/v2')).toBe( + 'https://index.docker.io/v2' + ); + expect(ensurePathPrefix('https://index.docker.io/v2', '/v2')).toBe( + 'https://index.docker.io/v2' + ); + expect( + ensurePathPrefix('https://index.docker.io/v2/something', '/v2') + ).toBe('https://index.docker.io/v2/something'); + }); }); diff --git a/lib/util/url.ts b/lib/util/url.ts index 0c9b975f7e961189deffecb14034ccffe65ae1e8..b84548b24138a12cd5a4e97c20b5269400273743 100644 --- a/lib/util/url.ts +++ b/lib/util/url.ts @@ -1,5 +1,14 @@ import urlJoin from 'url-join'; +export function ensurePathPrefix(url: string, prefix: string): string { + const parsed = new URL(url); + const fullPath = url.replace(parsed.origin, ''); + if (fullPath.startsWith(prefix)) { + return url; + } + return parsed.origin + prefix + fullPath; +} + export function ensureTrailingSlash(url: string): string { return url.replace(/\/?$/, '/'); }