From 13ffcc3722b6155328998106ee2dbfe27a6188a5 Mon Sep 17 00:00:00 2001 From: Lin Jian Date: Thu, 24 Sep 2020 18:13:45 +0800 Subject: [PATCH] [storage][stg74] container restore (#11457) * interface * includeDeleted --- .../storage-blob/review/storage-blob.api.md | 28 ++++++ .../storage-blob/src/BlobServiceClient.ts | 91 ++++++++++++++++++- .../src/generated/src/storageClientContext.ts | 2 +- .../storage-blob/src/generatedModels.ts | 4 +- 4 files changed, 120 insertions(+), 5 deletions(-) diff --git a/sdk/storage/storage-blob/review/storage-blob.api.md b/sdk/storage/storage-blob/review/storage-blob.api.md index 2348ff6bf019..1736483c5198 100644 --- a/sdk/storage/storage-blob/review/storage-blob.api.md +++ b/sdk/storage/storage-blob/review/storage-blob.api.md @@ -1028,6 +1028,10 @@ export class BlobServiceClient extends StorageClient { getUserDelegationKey(startsOn: Date, expiresOn: Date, options?: ServiceGetUserDelegationKeyOptions): Promise; listContainers(options?: ServiceListContainersOptions): PagedAsyncIterableIterator; setProperties(properties: BlobServiceProperties, options?: ServiceSetPropertiesOptions): Promise; + undeleteContainer(deletedContainerName: string, destinationContainerName?: string, options?: ContainerUndeleteOptions): Promise<{ + containerClient: ContainerClient; + containerUndeleteResponse: ContainerUndeleteResponse; + }>; } // @public @@ -1877,6 +1881,29 @@ export type ContainerSetMetadataResponse = ContainerSetMetadataHeaders & { }; }; +// @public +export interface ContainerUndeleteHeaders { + clientRequestId?: string; + date?: Date; + // (undocumented) + errorCode?: string; + requestId?: string; + version?: string; +} + +// @public +export interface ContainerUndeleteOptions extends CommonOptions { + abortSignal?: AbortSignalLike; + deletedContainerVersion?: string; +} + +// @public +export type ContainerUndeleteResponse = ContainerUndeleteHeaders & { + _response: coreHttp.HttpResponse & { + parsedHeaders: ContainerUndeleteHeaders; + }; +}; + // @public export type CopyPollerBlobClient = Pick & { startCopyFromURL(copySource: string, options?: BlobStartCopyFromURLOptions): Promise; @@ -2729,6 +2756,7 @@ export type ServiceGetUserDelegationKeyResponse = UserDelegationKey & ServiceGet // @public export interface ServiceListContainersOptions extends CommonOptions { abortSignal?: AbortSignalLike; + includeDeleted?: boolean; includeMetadata?: boolean; prefix?: string; } diff --git a/sdk/storage/storage-blob/src/BlobServiceClient.ts b/sdk/storage/storage-blob/src/BlobServiceClient.ts index e48d9cb0d73c..eb236ff53740 100644 --- a/sdk/storage/storage-blob/src/BlobServiceClient.ts +++ b/sdk/storage/storage-blob/src/BlobServiceClient.ts @@ -23,9 +23,10 @@ import { ListContainersIncludeType, UserDelegationKeyModel, ServiceFindBlobsByTagsSegmentResponse, - FilterBlobItem + FilterBlobItem, + ContainerUndeleteResponse } from "./generatedModels"; -import { Service } from "./generated/src/operations"; +import { Container, Service } from "./generated/src/operations"; import { newPipeline, StoragePipelineOptions, Pipeline } from "./Pipeline"; import { ContainerClient, ContainerCreateOptions, ContainerDeleteMethodOptions } from "./Clients"; import { appendToURLPath, extractConnectionStringParts } from "./utils/utils.common"; @@ -213,6 +214,14 @@ export interface ServiceListContainersOptions extends CommonOptions { * should be returned as part of the response body. */ includeMetadata?: boolean; + + /** + * Specifies whether soft deleted containers should be included in the response. + * + * @type {boolean} + * @memberof ServiceListContainersOptions + */ + includeDeleted?: boolean; } /** @@ -313,6 +322,30 @@ export declare type ServiceGetUserDelegationKeyResponse = UserDelegationKey & }; }; +/** + * Options to configure {@link BlobServiceClient.undeleteContainer} operation. + * + * @export + * @interface ContainerUndeleteOptions + */ +export interface ContainerUndeleteOptions extends CommonOptions { + /** + * An implementation of the `AbortSignalLike` interface to signal the request to cancel the operation. + * For example, use the @azure/abort-controller to create an `AbortSignal`. + * + * @type {AbortSignalLike} + * @memberof ContainerUndeleteOptions + */ + abortSignal?: AbortSignalLike; + /** + * Optional. Specifies the version of the deleted container to restore. + * + * @type {string} + * @memberof ContainerUndeleteOptions + */ + deletedContainerVersion?: string; +} + /** * A BlobServiceClient represents a Client to the Azure Storage Blob service allowing you * to manipulate blob containers. @@ -538,6 +571,49 @@ export class BlobServiceClient extends StorageClient { } } + /** + * Restore a previously deleted Blob container. + * This API is only functional if Container Soft Delete is enabled for the storage account associated with the container. + * + * @param {string} deletedContainerName Name of the previously deleted container. + * @param {ContainerUndeleteOptions} [options] Options to configure Container undelete operation. + * @returns {Promise} Container deletion response. + * @memberof BlobServiceClient + */ + public async undeleteContainer( + deletedContainerName: string, + destinationContainerName?: string, + options: ContainerUndeleteOptions = {} + ): Promise<{ + containerClient: ContainerClient; + containerUndeleteResponse: ContainerUndeleteResponse; + }> { + const { span, spanOptions } = createSpan( + "BlobServiceClient-undeleteContainer", + options.tracingOptions + ); + try { + const containerClient = this.getContainerClient( + destinationContainerName || deletedContainerName + ); + const container = new Container((containerClient as any).storageClientContext); + const containerUndeleteResponse = await container.restore({ + deletedContainerName, + ...options, + tracingOptions: { ...options!.tracingOptions, spanOptions } + }); + return { containerClient, containerUndeleteResponse }; + } catch (e) { + span.setStatus({ + code: CanonicalCode.UNKNOWN, + message: e.message + }); + throw e; + } finally { + span.end(); + } + } + /** * Gets the properties of a storage account’s Blob service, including properties * for Storage Analytics and CORS (Cross-Origin Resource Sharing) rules. @@ -1071,10 +1147,19 @@ export class BlobServiceClient extends StorageClient { if (options.prefix === "") { options.prefix = undefined; } + + const include: ListContainersIncludeType[] = []; + if (options.includeDeleted) { + include.push("deleted"); + } + if (options.includeMetadata) { + include.push("metadata"); + } + // AsyncIterableIterator to iterate over containers const listSegmentOptions: ServiceListContainersSegmentOptions = { ...options, - ...(options.includeMetadata ? { include: "metadata" } : {}) + include }; const iter = this.listItems(listSegmentOptions); diff --git a/sdk/storage/storage-blob/src/generated/src/storageClientContext.ts b/sdk/storage/storage-blob/src/generated/src/storageClientContext.ts index ee45e3ba2635..d676d5b88cd0 100644 --- a/sdk/storage/storage-blob/src/generated/src/storageClientContext.ts +++ b/sdk/storage/storage-blob/src/generated/src/storageClientContext.ts @@ -39,7 +39,7 @@ export class StorageClientContext extends coreHttp.ServiceClient { super(undefined, options); - this.version = "2020-02-10"; + this.version = '2020-02-10'; this.baseUri = "{url}"; this.requestContentType = "application/json; charset=utf-8"; this.url = url; diff --git a/sdk/storage/storage-blob/src/generatedModels.ts b/sdk/storage/storage-blob/src/generatedModels.ts index a913e22c4b85..7e7150767ab9 100644 --- a/sdk/storage/storage-blob/src/generatedModels.ts +++ b/sdk/storage/storage-blob/src/generatedModels.ts @@ -146,5 +146,7 @@ export { ServiceFilterBlobsResponse as ServiceFindBlobsByTagsSegmentResponse, FilterBlobItem, BlobQueryHeaders, - BlobQueryResponse as BlobQueryResponseModel + BlobQueryResponse as BlobQueryResponseModel, + ContainerRestoreResponse as ContainerUndeleteResponse, + ContainerRestoreHeaders as ContainerUndeleteHeaders } from "./generated/src/models";