From f2c4e3a840523631ab005532493b5d3e9a731105 Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Thu, 24 Aug 2023 10:42:17 -0400 Subject: [PATCH 1/2] added back delete image and get image digest for generic v2 --- .../GenericRegistryV2DataProvider.ts | 68 ++++++++++++++++--- 1 file changed, 59 insertions(+), 9 deletions(-) diff --git a/packages/vscode-docker-registries/src/clients/GenericRegistryV2/GenericRegistryV2DataProvider.ts b/packages/vscode-docker-registries/src/clients/GenericRegistryV2/GenericRegistryV2DataProvider.ts index e3dde282..e09d12cf 100644 --- a/packages/vscode-docker-registries/src/clients/GenericRegistryV2/GenericRegistryV2DataProvider.ts +++ b/packages/vscode-docker-registries/src/clients/GenericRegistryV2/GenericRegistryV2DataProvider.ts @@ -4,11 +4,13 @@ *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; -import { RegistryV2DataProvider, V2Registry, V2RegistryItem, V2RegistryRoot } from '../RegistryV2/RegistryV2DataProvider'; +import { RegistryV2DataProvider, V2Registry, V2RegistryRoot, V2Repository, V2Tag } from '../RegistryV2/RegistryV2DataProvider'; import { BasicOAuthProvider } from '../../auth/BasicOAuthProvider'; import { GenericRegistryV2WizardContext, GenericRegistryV2WizardPromptStep } from './GenericRegistryV2WizardPromptStep'; import { RegistryWizard } from '../../wizard/RegistryWizard'; import { RegistryWizardSecretPromptStep, RegistryWizardUsernamePromptStep } from '../../wizard/RegistryWizardPromptStep'; +import { CommonTag } from '../Common/models'; +import { registryV2Request } from '../RegistryV2/registryV2Request'; const GenericV2StorageKey = 'GenericV2ContainerRegistry'; const TrackedRegistriesKey = `${GenericV2StorageKey}.TrackedRegistries`; @@ -17,14 +19,16 @@ interface GenericV2RegistryRoot extends V2RegistryRoot { readonly additionalContextValues: ['genericRegistryV2Root']; } -interface GenericV2RegistryItem extends V2RegistryItem { - readonly additionalContextValues: ['genericRegistryV2']; +interface GenericV2Registry extends V2Registry { + readonly additionalContextValues: ['genericRegistryV2Registry']; } -export type GenericV2Registry = V2Registry & GenericV2RegistryItem; +interface GenericV2RegistryTag extends V2Tag { + readonly additionalContextValues: ['genericRegistryV2Tag']; +} export function isGenericV2Registry(item: unknown): item is GenericV2Registry { - return !!item && typeof item === 'object' && (item as GenericV2Registry).additionalContextValues?.includes('genericRegistryV2') === true; + return !!item && typeof item === 'object' && (item as GenericV2Registry).additionalContextValues?.includes('genericRegistryV2Registry') === true; } export class GenericRegistryV2DataProvider extends RegistryV2DataProvider { @@ -53,7 +57,7 @@ export class GenericRegistryV2DataProvider extends RegistryV2DataProvider { }; } - public async getRegistries(root: GenericV2RegistryRoot | GenericV2RegistryItem): Promise { + public async getRegistries(root: GenericV2RegistryRoot | GenericV2Registry): Promise { const trackedRegistryStrings = this.extensionContext.globalState.get(TrackedRegistriesKey, []); const trackedRegistries = trackedRegistryStrings.map(r => vscode.Uri.parse(r)); @@ -62,13 +66,23 @@ export class GenericRegistryV2DataProvider extends RegistryV2DataProvider { label: r.toString(), parent: root, type: 'commonregistry', - additionalContextValues: ['genericRegistryV2'], + additionalContextValues: ['genericRegistryV2Registry'], baseUrl: r }; }); } - protected override getAuthenticationProvider(item: GenericV2RegistryItem): BasicOAuthProvider { + public async getTags(repository: V2Repository): Promise { + const tags = await super.getTags(repository); + const tagsWithAdditionalContext: GenericV2RegistryTag[] = tags.map(tag => ({ + ...tag, + additionalContextValues: ['genericRegistryV2Tag'] + })); + + return tagsWithAdditionalContext; + } + + protected override getAuthenticationProvider(item: GenericV2Registry): BasicOAuthProvider { const registry = item.baseUrl.toString(); if (!this.authenticationProviders.has(registry)) { @@ -122,7 +136,7 @@ export class GenericRegistryV2DataProvider extends RegistryV2DataProvider { this.authenticationProviders.set(registryUriString, authProvider); } - public async removeTrackedRegistry(registry: GenericV2RegistryItem): Promise { + public async removeTrackedRegistry(registry: GenericV2Registry): Promise { // remove registry url from list of tracked registries const registryUriString = registry.baseUrl.toString(); const trackedRegistryStrings = this.extensionContext.globalState.get(TrackedRegistriesKey, []); @@ -137,4 +151,40 @@ export class GenericRegistryV2DataProvider extends RegistryV2DataProvider { this.authenticationProviders.delete(registryUriString); // TODO: check if the map of auth providers is empty, if so, remove the root from the tree } + + public async deleteTag(item: CommonTag): Promise { + const digest = await this.getImageDigest(item); + const registry = item.parent.parent as unknown as GenericV2Registry; + await registryV2Request({ + authenticationProvider: this.getAuthenticationProvider(registry), + method: 'DELETE', + registryUri: registry.baseUrl, + path: ['v2', item.parent.label, 'manifests', digest], + scopes: [`repository:${item.parent.label}:pull`], + headers: { + 'accept': 'application/vnd.docker.distribution.manifest.v2+json' + } + }); + } + + public async getImageDigest(item: CommonTag): Promise { + const registry = item.parent.parent as unknown as GenericV2Registry; + const response = await registryV2Request({ + authenticationProvider: this.getAuthenticationProvider(registry), + method: 'GET', + registryUri: registry.baseUrl, + path: ['v2', item.parent.label, 'manifests', item.label], + scopes: [`repository:${item.parent.label}:pull`], + headers: { + 'accept': 'application/vnd.docker.distribution.manifest.v2+json' + } + }); + + const digest = response.headers['docker-content-digest']; + if (!digest) { + throw new Error('Could not find digest'); + } + + return digest; + } } From 5457025a6ad6784e4d0382fe73ea1ba54a7fd197 Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Thu, 24 Aug 2023 12:08:36 -0400 Subject: [PATCH 2/2] added Github tag context value --- .../GenericRegistryV2DataProvider.ts | 38 ------------------- .../GitHub/GitHubRegistryDataProvider.ts | 12 +++++- .../RegistryV2/RegistryV2DataProvider.ts | 36 ++++++++++++++++++ 3 files changed, 47 insertions(+), 39 deletions(-) diff --git a/packages/vscode-docker-registries/src/clients/GenericRegistryV2/GenericRegistryV2DataProvider.ts b/packages/vscode-docker-registries/src/clients/GenericRegistryV2/GenericRegistryV2DataProvider.ts index e09d12cf..87f47e21 100644 --- a/packages/vscode-docker-registries/src/clients/GenericRegistryV2/GenericRegistryV2DataProvider.ts +++ b/packages/vscode-docker-registries/src/clients/GenericRegistryV2/GenericRegistryV2DataProvider.ts @@ -9,8 +9,6 @@ import { BasicOAuthProvider } from '../../auth/BasicOAuthProvider'; import { GenericRegistryV2WizardContext, GenericRegistryV2WizardPromptStep } from './GenericRegistryV2WizardPromptStep'; import { RegistryWizard } from '../../wizard/RegistryWizard'; import { RegistryWizardSecretPromptStep, RegistryWizardUsernamePromptStep } from '../../wizard/RegistryWizardPromptStep'; -import { CommonTag } from '../Common/models'; -import { registryV2Request } from '../RegistryV2/registryV2Request'; const GenericV2StorageKey = 'GenericV2ContainerRegistry'; const TrackedRegistriesKey = `${GenericV2StorageKey}.TrackedRegistries`; @@ -151,40 +149,4 @@ export class GenericRegistryV2DataProvider extends RegistryV2DataProvider { this.authenticationProviders.delete(registryUriString); // TODO: check if the map of auth providers is empty, if so, remove the root from the tree } - - public async deleteTag(item: CommonTag): Promise { - const digest = await this.getImageDigest(item); - const registry = item.parent.parent as unknown as GenericV2Registry; - await registryV2Request({ - authenticationProvider: this.getAuthenticationProvider(registry), - method: 'DELETE', - registryUri: registry.baseUrl, - path: ['v2', item.parent.label, 'manifests', digest], - scopes: [`repository:${item.parent.label}:pull`], - headers: { - 'accept': 'application/vnd.docker.distribution.manifest.v2+json' - } - }); - } - - public async getImageDigest(item: CommonTag): Promise { - const registry = item.parent.parent as unknown as GenericV2Registry; - const response = await registryV2Request({ - authenticationProvider: this.getAuthenticationProvider(registry), - method: 'GET', - registryUri: registry.baseUrl, - path: ['v2', item.parent.label, 'manifests', item.label], - scopes: [`repository:${item.parent.label}:pull`], - headers: { - 'accept': 'application/vnd.docker.distribution.manifest.v2+json' - } - }); - - const digest = response.headers['docker-content-digest']; - if (!digest) { - throw new Error('Could not find digest'); - } - - return digest; - } } diff --git a/packages/vscode-docker-registries/src/clients/GitHub/GitHubRegistryDataProvider.ts b/packages/vscode-docker-registries/src/clients/GitHub/GitHubRegistryDataProvider.ts index 9d698a7c..3b4d9835 100644 --- a/packages/vscode-docker-registries/src/clients/GitHub/GitHubRegistryDataProvider.ts +++ b/packages/vscode-docker-registries/src/clients/GitHub/GitHubRegistryDataProvider.ts @@ -5,7 +5,7 @@ import * as vscode from 'vscode'; import { BasicOAuthProvider } from '../../auth/BasicOAuthProvider'; -import { RegistryV2DataProvider, V2Registry, V2RegistryItem, V2RegistryRoot, V2Repository } from '../RegistryV2/RegistryV2DataProvider'; +import { RegistryV2DataProvider, V2Registry, V2RegistryItem, V2RegistryRoot, V2Repository, V2Tag } from '../RegistryV2/RegistryV2DataProvider'; import { registryV2Request } from '../RegistryV2/registryV2Request'; import { AuthenticationProvider } from '../../contracts/AuthenticationProvider'; import { httpRequest } from '../../utils/httpRequest'; @@ -120,6 +120,16 @@ export class GitHubRegistryDataProvider extends RegistryV2DataProvider { return results; } + public async getTags(repository: V2Repository): Promise { + const tags = await super.getTags(repository); + const tagsWithAdditionalContext: V2Tag[] = tags.map(tag => ({ + ...tag, + additionalContextValues: ['githubRegistryTag'] + })); + + return tagsWithAdditionalContext; + } + protected getAuthenticationProvider(item: V2RegistryItem): AuthenticationProvider { return this.authenticationProvider; } diff --git a/packages/vscode-docker-registries/src/clients/RegistryV2/RegistryV2DataProvider.ts b/packages/vscode-docker-registries/src/clients/RegistryV2/RegistryV2DataProvider.ts index f6dab12e..f092db22 100644 --- a/packages/vscode-docker-registries/src/clients/RegistryV2/RegistryV2DataProvider.ts +++ b/packages/vscode-docker-registries/src/clients/RegistryV2/RegistryV2DataProvider.ts @@ -114,5 +114,41 @@ export abstract class RegistryV2DataProvider extends CommonRegistryDataProvider return history?.created ? new Date(history.created) : undefined; } + public async deleteTag(item: CommonTag): Promise { + const digest = await this.getImageDigest(item); + const registry = item.parent.parent as unknown as V2Registry; + await registryV2Request({ + authenticationProvider: this.getAuthenticationProvider(registry), + method: 'DELETE', + registryUri: registry.baseUrl, + path: ['v2', item.parent.label, 'manifests', digest], + scopes: [`repository:${item.parent.label}:pull`], + headers: { + 'accept': 'application/vnd.docker.distribution.manifest.v2+json' + } + }); + } + + public async getImageDigest(item: CommonTag): Promise { + const registry = item.parent.parent as unknown as V2Registry; + const response = await registryV2Request({ + authenticationProvider: this.getAuthenticationProvider(registry), + method: 'GET', + registryUri: registry.baseUrl, + path: ['v2', item.parent.label, 'manifests', item.label], + scopes: [`repository:${item.parent.label}:pull`], + headers: { + 'accept': 'application/vnd.docker.distribution.manifest.v2+json' + } + }); + + const digest = response.headers['docker-content-digest']; + if (!digest) { + throw new Error('Could not find digest'); + } + + return digest; + } + protected abstract getAuthenticationProvider(item: V2RegistryItem): AuthenticationProvider; }