Skip to content

Commit

Permalink
fix(datasource/docker): Artifactory next link is broken for tags api (#…
Browse files Browse the repository at this point in the history
…20745)

Co-authored-by: Rhys Arkins <rhys@arkins.net>
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
  • Loading branch information
3 people authored Mar 5, 2023
1 parent 939c793 commit eb5db5b
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 28 deletions.
4 changes: 3 additions & 1 deletion lib/modules/datasource/docker/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ export const gitRefLabel = 'org.opencontainers.image.revision';

const JFROG_ARTIFACTORY_RES_HEADER = 'x-jfrog-version';

export function isArtifactoryServer(res: HttpResponse | undefined): boolean {
export function isArtifactoryServer<T = unknown>(
res: HttpResponse<T> | undefined
): boolean {
return is.string(res?.headers[JFROG_ARTIFACTORY_RES_HEADER]);
}
66 changes: 40 additions & 26 deletions lib/modules/datasource/docker/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
} from '@aws-sdk/client-ecr';
import { mockClient } from 'aws-sdk-client-mock';
import { getDigest, getPkgReleases } from '..';
import { range } from '../../../../lib/util/range';
import * as httpMock from '../../../../test/http-mock';
import { logger, mocked } from '../../../../test/util';
import {
Expand Down Expand Up @@ -1193,32 +1194,45 @@ describe('modules/datasource/docker/index', () => {
await expect(getPkgReleases(config)).rejects.toThrow(EXTERNAL_HOST_ERROR);
});

it.each([[true], [false]])(
'jfrog artifactory - retry tags for official images by injecting `/library` after repository and before image, abortOnError=%p',
async (abortOnError) => {
hostRules.find.mockReturnValue({ abortOnError });
const tags = ['18.0.0'];
httpMock
.scope('https://org.jfrog.io/v2')
.get('/virtual-mirror/node/tags/list?n=10000')
.reply(200, '', {})
.get('/virtual-mirror/node/tags/list?n=10000')
.reply(404, '', { 'x-jfrog-version': 'Artifactory/7.42.2 74202900' })
.get('/virtual-mirror/library/node/tags/list?n=10000')
.reply(200, '', {})
.get('/virtual-mirror/library/node/tags/list?n=10000')
.reply(200, { tags }, {})
.get('/')
.reply(200, '', {})
.get('/virtual-mirror/node/manifests/18.0.0')
.reply(200, '', {});
const res = await getPkgReleases({
datasource: DockerDatasource.id,
depName: 'org.jfrog.io/virtual-mirror/node',
});
expect(res?.releases).toHaveLength(1);
}
);
it('jfrog artifactory - retry tags for official images by injecting `/library` after repository and before image', async () => {
const tags1 = [...range(1, 10000)].map((i) => `${i}.0.0`);
const tags2 = [...range(10000, 10050)].map((i) => `${i}.0.0`);
httpMock
.scope('https://org.jfrog.io/v2')
.get('/virtual-mirror/node/tags/list?n=10000')
.reply(200, '', { 'x-jfrog-version': 'Artifactory/7.42.2 74202900' })
.get('/virtual-mirror/node/tags/list?n=10000')
.reply(404, '', { 'x-jfrog-version': 'Artifactory/7.42.2 74202900' })
.get('/virtual-mirror/library/node/tags/list?n=10000')
.reply(200, '', {})
.get('/virtual-mirror/library/node/tags/list?n=10000')
// Note the Link is incorrect and should be `</virtual-mirror/library/node/tags/list?n=10000&last=10000>; rel="next", `
// Artifactory incorrectly returns a next link without the virtual repository name
// this is due to a bug in Artifactory https://jfrog.atlassian.net/browse/RTFACT-18971
.reply(
200,
{ tags: tags1 },
{
'x-jfrog-version': 'Artifactory/7.42.2 74202900',
link: '</library/node/tags/list?n=10000&last=10000>; rel="next", ',
}
)
.get('/virtual-mirror/library/node/tags/list?n=10000&last=10000')
.reply(
200,
{ tags: tags2 },
{ 'x-jfrog-version': 'Artifactory/7.42.2 74202900' }
)
.get('/')
.reply(200, '', {})
.get('/virtual-mirror/node/manifests/10050.0.0')
.reply(200, '', {});
const res = await getPkgReleases({
datasource: DockerDatasource.id,
depName: 'org.jfrog.io/virtual-mirror/node',
});
expect(res?.releases).toHaveLength(10050);
});

it('uses lower tag limit for ECR deps', async () => {
httpMock
Expand Down
10 changes: 9 additions & 1 deletion lib/modules/datasource/docker/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -883,7 +883,15 @@ export class DockerDatasource extends Datasource {
}
tags = tags.concat(res.body.tags);
const linkHeader = parseLinkHeader(res.headers.link);
url = linkHeader?.next ? URL.resolve(url, linkHeader.next.url) : null;
if (isArtifactoryServer(res)) {
// Artifactory incorrectly returns a next link without the virtual repository name
// this is due to a bug in Artifactory https://jfrog.atlassian.net/browse/RTFACT-18971
url = linkHeader?.next?.last
? `${url}&last=${linkHeader.next.last}`
: null;
} else {
url = linkHeader?.next ? URL.resolve(url, linkHeader.next.url) : null;
}
page += 1;
} while (url && page < 20);
return tags;
Expand Down

0 comments on commit eb5db5b

Please sign in to comment.