### Packages impacted by this PR


### Issues associated with this PR


### Describe the problem that is addressed by this PR


### What are the possible designs available to address the problem? If
there are more than one possible design, why was the one in this PR
chosen?


### Are there test cases added in this PR? _(If not, why?)_


### Provide a list of related PRs _(if any)_


### Command used to generate this PR:**_(Applicable only to SDK release
request PRs)_

### Checklists
- [ ] Added impacted package name to the issue description
- [ ] Does this PR needs any fixes in the SDK Generator?** _(If so,
create an Issue in the
[Autorest/typescript](https://github.com/Azure/autorest.typescript)
repository and link it here)_
- [ ] Added a changelog (if necessary)

---------

Co-authored-by: Timo van Veenendaal <timov@microsoft.com>
Co-authored-by: Harsha Nalluru <sanallur@microsoft.com>
This commit is contained in:
EmmaZhu-MSFT 2023-10-26 16:45:35 +08:00 коммит произвёл GitHub
Родитель 1fafbdb4cb
Коммит 19d46b727b
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
9 изменённых файлов: 107 добавлений и 13 удалений

Просмотреть файл

@ -2,5 +2,5 @@
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "js",
"TagPrefix": "js/storage/storage-blob",
"Tag": "js/storage/storage-blob_69ac1158da"
"Tag": "js/storage/storage-blob_aeafbc09c5"
}

Просмотреть файл

@ -1595,6 +1595,12 @@ describe("BlobClient - ImmutabilityPolicy", () => {
containerName = getImmutableContainerName();
recorder = new Recorder(this.currentTest);
await recorder.start(recorderEnvSetup);
await recorder.addSanitizers(
{
uriSanitizers,
},
["record", "playback"]
);
blobServiceClient = getBSU(recorder);
containerClient = blobServiceClient.getContainerClient(containerName);

Просмотреть файл

@ -7,7 +7,7 @@ import { getBSU } from "./utils";
import { Recorder, isRecordMode, isPlaybackMode, isLiveMode } from "@azure-tools/test-recorder";
import {
getUniqueName,
recorderEnvSetup,
recorderEnvSetupWithCopySource,
testPollerProperties,
uriSanitizers,
} from "./utils/testutils.common";
@ -29,7 +29,8 @@ describe("BlobClient beginCopyFromURL Poller", () => {
beforeEach(async function (this: Context) {
recorder = new Recorder(this.currentTest);
await recorder.start(recorderEnvSetup);
// Copy source for all cases in this suite doesn't include any credential, it's save to keep x-ms-copy-source header.
await recorder.start(recorderEnvSetupWithCopySource);
await recorder.addSanitizers({ uriSanitizers }, ["playback", "record"]);
const blobServiceClient = getBSU(recorder);
containerName = recorder.variable("container", getUniqueName("container"));
@ -141,6 +142,7 @@ describe("BlobClient beginCopyFromURL Poller", () => {
if (!isNode && !isLiveMode()) {
this.skip();
}
const newBlobClient = destinationContainerClient.getBlobClient(
recorder.variable("copiedblob", getUniqueName("copiedblob"))
);
@ -167,6 +169,7 @@ describe("BlobClient beginCopyFromURL Poller", () => {
if (!isNode) {
this.skip();
}
const newBlobClient = destinationContainerClient.getBlobClient(
recorder.variable("copiedblob", getUniqueName("copiedblob"))
);
@ -188,6 +191,7 @@ describe("BlobClient beginCopyFromURL Poller", () => {
if (!isNode && !isLiveMode()) {
this.skip();
}
const newBlobClient = destinationContainerClient.getBlobClient(
recorder.variable("copiedblob", getUniqueName("copiedblob"))
);

Просмотреть файл

@ -3,11 +3,11 @@
import { assert } from "chai";
import {
createAndStartRecorder,
getBSU,
getEncryptionScope_1,
getEncryptionScope_2,
getUniqueName,
recorderEnvSetup,
} from "./utils";
import { Recorder } from "@azure-tools/test-recorder";
import { BlobServiceClient, BlobClient, BlockBlobClient, ContainerClient } from "../src";
@ -29,8 +29,7 @@ describe("Encryption Scope", function () {
let recorder: Recorder;
beforeEach(async function (this: Context) {
recorder = new Recorder(this.currentTest);
await recorder.start(recorderEnvSetup);
recorder = await createAndStartRecorder(this.currentTest);
try {
encryptionScopeName1 = getEncryptionScope_1();

Просмотреть файл

@ -966,6 +966,10 @@ describe("BlobClient Node.js Only - ImmutabilityPolicy", () => {
}
recorder = new Recorder(this.currentTest);
await recorder.start(recorderEnvSetup);
await recorder.addSanitizers(
{ removeHeaderSanitizer: { headersForRemoval: ["x-ms-copy-source"] } },
["playback"]
);
blobServiceClient = getBSU(recorder);
containerClient = blobServiceClient.getContainerClient(containerName);
blobName = recorder.variable("blob", getUniqueName("blob"));

Просмотреть файл

@ -2745,6 +2745,7 @@ describe("Shared Access Signature (SAS) generation Node.js Only - ImmutabilityPo
blobServiceClient.credential as StorageSharedKeyCredential
);
const sasContainerClient = new ContainerClient(`${containerClient.url}?${containerSAS}`);
configureBlobStorageClient(recorder, sasContainerClient);
const sasBlobClient = sasContainerClient.getBlobClient(blobName);
const minutesLater = new Date(recorder.variable("minutesLater", new Date().toISOString()));

Просмотреть файл

@ -2,13 +2,13 @@
// Licensed under the MIT license.
import { assert } from "chai";
import { Pipeline } from "@azure/core-rest-pipeline";
import { Pipeline, PipelineRequest, SendRequest } from "@azure/core-rest-pipeline";
import { AbortController } from "@azure/abort-controller";
import { ContainerClient, RestError, BlobServiceClient } from "../src";
import { getBSU, getUniqueName, recorderEnvSetup, uriSanitizers } from "./utils";
import { injectorPolicy, injectorPolicyName } from "./utils/InjectorPolicy";
import { Recorder } from "@azure-tools/test-recorder";
import { Recorder, isPlaybackMode } from "@azure-tools/test-recorder";
import { Context } from "mocha";
describe("RetryPolicy", () => {
@ -152,6 +152,27 @@ describe("RetryPolicy", () => {
const pipeline: Pipeline = (containerClient as any).storageClientContext.pipeline;
pipeline.addPolicy(injector, { afterPhase: "Retry" });
if (isPlaybackMode()) {
// Recorder looks into the recording for the request hitting secondary host and throws a request mismatch error.
// This policy is a workaround instead to mimic the live test behavior, to throw a 404 ENOTFOUND error when the request hits secondary host that does not exist
pipeline.addPolicy(
{
name: "secondaryHost-policy",
sendRequest: (req: PipelineRequest, next: SendRequest) => {
if (req.url.includes(secondaryHost)) {
throw new RestError(`getaddrinfo ENOTFOUND`, {
code: "ENOTFOUND",
statusCode: 404,
request: req,
});
}
return next(req);
},
},
{ afterPhase: "Retry" }
);
}
let finalRequestURL = "";
try {
const response = await containerClient.getProperties();

Просмотреть файл

@ -6,7 +6,10 @@ import { TokenCredential, GetTokenOptions, AccessToken } from "@azure/core-auth"
import { isPlaybackMode, Recorder, RecorderStartOptions } from "@azure-tools/test-recorder";
import { StorageClient } from "../../src/StorageClient";
import { Pipeline } from "@azure/core-rest-pipeline";
import { FindReplaceSanitizer } from "@azure-tools/test-recorder/types/src/utils/utils";
import {
FindReplaceSanitizer,
RegexSanitizer,
} from "@azure-tools/test-recorder/types/src/utils/utils";
export const testPollerProperties = {
intervalInMs: isPlaybackMode() ? 0 : undefined,
@ -21,7 +24,7 @@ export function configureBlobStorageClient(recorder: Recorder, serviceClient: St
}
}
function getUriSanitizerForQueryParam(paramName: string) {
function getUriSanitizerForQueryParam(paramName: string): RegexSanitizer {
return {
regex: true,
target: `http.+?[^&]*&?(?<param>${paramName}=[^&]+&?)`,
@ -92,8 +95,56 @@ export const recorderEnvSetup: RecorderStartOptions = {
value: "fakestorageaccount:pass123",
},
],
// SAS token may contain sensitive information
uriSanitizers,
},
};
export const recorderEnvSetupWithCopySource: RecorderStartOptions = {
envSetupForPlayback: {
// Used in record and playback modes
// 1. The key-value pairs will be used as the environment variables in playback mode
// 2. If the env variables are present in the recordings as plain strings, they will be replaced with the provided values in record mode
ACCOUNT_KEY: `${mockAccountKey}`,
ACCOUNT_SAS: `${mockSas}`,
STORAGE_CONNECTION_STRING: `DefaultEndpointsProtocol=https;AccountName=${mockAccountName};AccountKey=${mockAccountKey};EndpointSuffix=core.windows.net`,
// Comment following line to skip user delegation key/SAS related cases in record and play
// which depends on this environment variable
// ACCOUNT_TOKEN: `${mockAccountKey}`,
AZURE_CLIENT_ID: `${mockAccountKey}`,
AZURE_TENANT_ID: `${mockAccountKey}`,
AZURE_CLIENT_SECRET: `${mockAccountKey}`,
// MD_ACCOUNT_NAME: `${mockMDAccountName}`,
// MD_ACCOUNT_KEY: `${mockAccountKey}`,
// MD_ACCOUNT_SAS: `${mockSas}`,
// MD_STORAGE_CONNECTION_STRING: `DefaultEndpointsProtocol=https;AccountName=${mockMDAccountName};AccountKey=${mockAccountKey};EndpointSuffix=core.windows.net`,
// ENCRYPTION_SCOPE_1: "antjoscope1",
// ENCRYPTION_SCOPE_2: "antjoscope2",
// IMMUTABLE_CONTAINER_NAME: "fakecontainername",
// ORS_DEST_ACCOUNT_NAME: `${mockAccountName1}`,
// ORS_DEST_ACCOUNT_KEY: `${mockAccountKey}`,
// ORS_DEST_ACCOUNT_SAS: `${mockSas}`,
// ORS_DEST_STORAGE_CONNECTION_STRING: `DefaultEndpointsProtocol=https;AccountName=${mockAccountName1};AccountKey=${mockAccountKey};EndpointSuffix=core.windows.net`,
SOFT_DELETE_ACCOUNT_NAME: `${mockAccountName}`,
SOFT_DELETE_ACCOUNT_KEY: `${mockAccountKey}`,
SOFT_DELETE_ACCOUNT_SAS: `${mockSas}`,
SOFT_DELETE_STORAGE_CONNECTION_STRING: `DefaultEndpointsProtocol=https;AccountName=${mockAccountName};AccountKey=${mockAccountKey};EndpointSuffix=core.windows.net`,
ACCOUNT_NAME: `${mockAccountName}`,
},
sanitizerOptions: {
bodySanitizers: [
{
regex: true,
target: "(.*)&sig=(?<sig_value>.*)",
groupForReplace: "sig_value",
value: mockAccountKey,
},
{
regex: true,
target: "Authorization: SharedKey (?<shared_key>[^\\\\]+)",
groupForReplace: "shared_key",
value: "fakestorageaccount:pass123",
},
],
},
};
@ -198,3 +249,11 @@ export function generateRandomUint8Array(byteLength: number): Uint8Array {
}
return uint8Arr;
}
export async function createAndStartRecorder(testContext?: Mocha.Test): Promise<Recorder> {
const recorder = new Recorder(testContext);
await recorder.start(recorderEnvSetup);
// SAS token may contain sensitive information
await recorder.addSanitizers({ uriSanitizers: uriSanitizers }, ["record", "playback"]);
return recorder;
}

Просмотреть файл

@ -2,5 +2,5 @@
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "js",
"TagPrefix": "js/storage/storage-file-share",
"Tag": "js/storage/storage-file-share_94b5de4453"
"Tag": "js/storage/storage-file-share_da8a5bba62"
}