From add1dd7dbe5e2e01f42905983bbace7ac5dbffa2 Mon Sep 17 00:00:00 2001 From: "Brandon Waterloo [MSFT]" <36966225+bwateratmsft@users.noreply.github.com> Date: Mon, 28 Nov 2022 17:35:25 -0500 Subject: [PATCH] Pull upstream changes to support images with digest (#3721) --- .../parseDockerLikeImageName.ts | 5 +- .../docker/contracts/ContainerClient.ts | 4 ++ .../test/parseDockerLikeImageName.test.ts | 48 +++++++++++++++++++ 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/runtimes/docker/clients/DockerClientBase/parseDockerLikeImageName.ts b/src/runtimes/docker/clients/DockerClientBase/parseDockerLikeImageName.ts index cd35da9513..521e0685f0 100644 --- a/src/runtimes/docker/clients/DockerClientBase/parseDockerLikeImageName.ts +++ b/src/runtimes/docker/clients/DockerClientBase/parseDockerLikeImageName.ts @@ -19,7 +19,7 @@ import { ImageNameInfo } from '../../contracts/ContainerClient'; * * Tag: Everything after the ":", if it is present. */ -const imageNameRegex = /^((?(localhost|([\w-]+(\.[\w-]+)+))(:\d+)?)\/)?(?[\w-./<>]+)(:(?[\w-.<>]+))?$/; +const imageNameRegex = /^((?(localhost|([\w-]+(\.[\w-]+)+))(:\d+)?)\/)?(?[\w-./<>]+)(:(?[\w-.<>]+))?(@(?.+))?$/; // In certain cases, Docker makes image/tag names "", which is not really valid. We will reinterpret those as `undefined`. const noneImageName = /[<>]/i; @@ -43,12 +43,13 @@ export function parseDockerLikeImageName(originalName: string | undefined): Imag throw new Error('Invalid image name'); } - const { registry, image, tag } = match.groups; + const { registry, image, tag, digest } = match.groups; return { originalName, image: noneImageName.test(image) ? undefined : image, tag: noneImageName.test(tag) ? undefined : tag, + digest, registry, }; } diff --git a/src/runtimes/docker/contracts/ContainerClient.ts b/src/runtimes/docker/contracts/ContainerClient.ts index 432bdad6e5..6ca2f506e9 100644 --- a/src/runtimes/docker/contracts/ContainerClient.ts +++ b/src/runtimes/docker/contracts/ContainerClient.ts @@ -41,6 +41,10 @@ export interface ImageNameInfo { * The tag/anchor name. If absent, this will be undefined. */ readonly tag?: string; + /** + * The digest. If absent, this will be undefined. + */ + readonly digest?: string; } export type Labels = { diff --git a/src/runtimes/docker/test/parseDockerLikeImageName.test.ts b/src/runtimes/docker/test/parseDockerLikeImageName.test.ts index c4b890bf70..86596d5ae6 100644 --- a/src/runtimes/docker/test/parseDockerLikeImageName.test.ts +++ b/src/runtimes/docker/test/parseDockerLikeImageName.test.ts @@ -13,6 +13,7 @@ describe('parseDockerLikeImageName', () => { originalName: 'alpine', image: 'alpine', tag: undefined, + digest: undefined, registry: undefined, }); @@ -20,6 +21,7 @@ describe('parseDockerLikeImageName', () => { originalName: 'hello-world', image: 'hello-world', tag: undefined, + digest: undefined, registry: undefined, }); @@ -27,6 +29,7 @@ describe('parseDockerLikeImageName', () => { originalName: 'hello_world', image: 'hello_world', tag: undefined, + digest: undefined, registry: undefined, }); @@ -34,6 +37,7 @@ describe('parseDockerLikeImageName', () => { originalName: 'library/alpine', image: 'library/alpine', tag: undefined, + digest: undefined, registry: undefined, }); }); @@ -43,6 +47,7 @@ describe('parseDockerLikeImageName', () => { originalName: 'alpine:latest', image: 'alpine', tag: 'latest', + digest: undefined, registry: undefined, }); @@ -50,6 +55,17 @@ describe('parseDockerLikeImageName', () => { originalName: 'library/alpine:5', image: 'library/alpine', tag: '5', + digest: undefined, + registry: undefined, + }); + }); + + it('Should parse those with a digest', () => { + expect(parseDockerLikeImageName('kindest/node:v1.24.0@sha256:0866296e693efe1fed79d5e6c7af8df71fc73ae45e3679af05342239cdc5bc8e')).to.deep.equal({ + originalName: 'kindest/node:v1.24.0@sha256:0866296e693efe1fed79d5e6c7af8df71fc73ae45e3679af05342239cdc5bc8e', + image: 'kindest/node', + tag: 'v1.24.0', + digest: 'sha256:0866296e693efe1fed79d5e6c7af8df71fc73ae45e3679af05342239cdc5bc8e', registry: undefined, }); }); @@ -59,6 +75,7 @@ describe('parseDockerLikeImageName', () => { originalName: 'docker.io/library/alpine:latest', image: 'library/alpine', tag: 'latest', + digest: undefined, registry: 'docker.io', }); @@ -66,6 +83,7 @@ describe('parseDockerLikeImageName', () => { originalName: 'localhost/alpine:latest', image: 'alpine', tag: 'latest', + digest: undefined, registry: 'localhost', }); @@ -73,6 +91,7 @@ describe('parseDockerLikeImageName', () => { originalName: 'with-a.port:5000/library/alpine:latest', image: 'library/alpine', tag: 'latest', + digest: undefined, registry: 'with-a.port:5000', }); @@ -80,6 +99,7 @@ describe('parseDockerLikeImageName', () => { originalName: '1.2.3.4:5000/library/alpine:latest', image: 'library/alpine', tag: 'latest', + digest: undefined, registry: '1.2.3.4:5000', }); @@ -87,6 +107,31 @@ describe('parseDockerLikeImageName', () => { originalName: 'localhost:5000/alpine:latest', image: 'alpine', tag: 'latest', + digest: undefined, + registry: 'localhost:5000', + }); + + expect(parseDockerLikeImageName('with-a.port:5000/library/alpine:latest@sha256:0866296e693efe1fed79d5e6c7af8df71fc73ae45e3679af05342239cdc5bc8e')).to.deep.equal({ + originalName: 'with-a.port:5000/library/alpine:latest@sha256:0866296e693efe1fed79d5e6c7af8df71fc73ae45e3679af05342239cdc5bc8e', + image: 'library/alpine', + tag: 'latest', + digest: 'sha256:0866296e693efe1fed79d5e6c7af8df71fc73ae45e3679af05342239cdc5bc8e', + registry: 'with-a.port:5000', + }); + + expect(parseDockerLikeImageName('1.2.3.4:5000/library/alpine:latest@sha256:0866296e693efe1fed79d5e6c7af8df71fc73ae45e3679af05342239cdc5bc8e')).to.deep.equal({ + originalName: '1.2.3.4:5000/library/alpine:latest@sha256:0866296e693efe1fed79d5e6c7af8df71fc73ae45e3679af05342239cdc5bc8e', + image: 'library/alpine', + tag: 'latest', + digest: 'sha256:0866296e693efe1fed79d5e6c7af8df71fc73ae45e3679af05342239cdc5bc8e', + registry: '1.2.3.4:5000', + }); + + expect(parseDockerLikeImageName('localhost:5000/alpine:latest@sha256:0866296e693efe1fed79d5e6c7af8df71fc73ae45e3679af05342239cdc5bc8e')).to.deep.equal({ + originalName: 'localhost:5000/alpine:latest@sha256:0866296e693efe1fed79d5e6c7af8df71fc73ae45e3679af05342239cdc5bc8e', + image: 'alpine', + tag: 'latest', + digest: 'sha256:0866296e693efe1fed79d5e6c7af8df71fc73ae45e3679af05342239cdc5bc8e', registry: 'localhost:5000', }); }); @@ -97,6 +142,7 @@ describe('parseDockerLikeImageName', () => { originalName: ':', image: undefined, tag: undefined, + digest: undefined, registry: undefined, }); @@ -104,6 +150,7 @@ describe('parseDockerLikeImageName', () => { originalName: '', image: undefined, tag: undefined, + digest: undefined, registry: undefined, }); @@ -111,6 +158,7 @@ describe('parseDockerLikeImageName', () => { originalName: 'alpine:', image: 'alpine', tag: undefined, + digest: undefined, registry: undefined, }); });