Rerecord storage cases (#27127)
### 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:
Родитель
1fafbdb4cb
Коммит
19d46b727b
|
@ -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"
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче