Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mgmt, testproxy migration, azure-resourcemanager-resources #35476

Merged
merged 22 commits into from
Jul 20, 2023

Conversation

haolingdong-msft
Copy link
Member

@haolingdong-msft haolingdong-msft commented Jun 15, 2023

Description

Before running test, you will need to set below environment variables as usual:

AZURE_SUBSCRIPTION_ID: Use the id value from az account show in the Azure CLI 2.0.
AZURE_CLIENT_ID: Use the appId value from the output taken from a service principal output.
AZURE_CLIENT_SECRET: Use the password value from the service principal output.
AZURE_TENANT_ID: Use the tenant value from the service principal output.
AZURE_TEST_MODE=RECORD


Code change:

  1. Redact api-version and subscription id: 906806f, ab52244
    subscription id not match failure like below:
Uri doesn't match:
    request <[https://REDACTED/%2Fsubscriptions%2F00000000-0000-0000-0000-000000000000%2FresourceGroups%2Frgloc06907fd/providers/Microsoft.Authorization/locks/lock067783a7?api-version=2017-04-01>](https://redacted/%2Fsubscriptions%2F00000000-0000-0000-0000-000000000000%2FresourceGroups%2Frgloc06907fd/providers/Microsoft.Authorization/locks/lock067783a7?api-version=2017-04-01%3E)
    record  <[https://REDACTED/%2Fsubscriptions%2Fec0aa5f7-9e78-40c9-85cd-535c6305b380%2FresourceGroups%2Frgloc06907fd/providers/Microsoft.Authorization/locks/lock067783a7?api-version=2017-04-01>](https://redacted/%2Fsubscriptions%2Fec0aa5f7-9e78-40c9-85cd-535c6305b380%2FresourceGroups%2Frgloc06907fd/providers/Microsoft.Authorization/locks/lock067783a7?api-version=2017-04-01%3E)
Header differences:
  1. Add fake credential in playback to avoid playback failure: 796a321, similar as cofidential ledger: https://github.com/Azure/azure-sdk-for-java/blob/main/sdk/confidentialledger/azure-security-confidentialledger/src/test/java/com/azure/security/confidentialledger/ConfidentialLedgerClientTestBase.java#L100
  2. Code change to make playback work: b5903e4
  3. I did not remove TextReplacementPolicy because it will handle logics like set retry-after to 0 for LRO in playback mode. Look for @samvaity's suggestion on this part.

Question 0:
I met .net environment error (see below) when trying to install testproxy into PATH. Before solving the env issue and initiate assets.json, I want to first check the recorded session records file content, so I run in IDE and run the tests in RECORD mode, the test can pass, but I found the recordings seems not correct, please refer to the file changes in this pr.
@samvaity Is this expected? Must we first initiate assets.json and then do the recording?

image

Please note I have updated this TextReplacementPolicy(sdk/resourcemanager/azure-resourcemanager-test/src/main/java/com/azure/resourcemanager/test/policy/TextReplacementPolicy.java) since currently testproxy will set recordedData to null which will cause NullPointorException in the TextReplacementPolicy.


Question 1:
The testproxy installation issue above can be resolved by clean up the %AppData%\Roaming\NuGet\NuGet.Config file. After deleting the NuGet.Config file, installation succeeds.
But after I added back the needed sources "CosmosProd" to NuGet.Config, installation fails again..This will cause updating testproxy in the future.
@samvaity , seems the testproxy source is conflict with my existing source called CosmosProd. I have pasted my existing sources below. I am a newbee in .net world, wondering can the command in doc be updated to avoid this kind of failure?

nuget.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
    <add key="Microsoft Visual Studio Offline Packages" value="C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\" />
    <add key="CosmosProd" value="https://mscosmos.pkgs.visualstudio.com/_packaging/CosmosProd/nuget/v3/index.json" />
  </packageSources>
</configuration>

Question 2:
Encounter below error when initialize assets.json. @samvaity , could you please check the failure and help to advice?

PS C:\workspace\azure-sdk-for-java\sdk\resourcemanager\azure-resourcemanager-resources>  ..\..\..\eng\common\testproxy\transition-scripts\generate-assets-json.ps1 -InitialPush
git remote -v
azure-sdk       https://github.com/azure-sdk/azure-sdk-for-java.git (fetch)
azure-sdk       https://github.com/azure-sdk/azure-sdk-for-java.git (push)
origin  https://github.com/haolingdong-msft/azure-sdk-for-java.git (fetch)
origin  https://github.com/haolingdong-msft/azure-sdk-for-java.git (push)
remote  https://github.com/Azure/azure-sdk-for-java.git (fetch)
remote  https://github.com/Azure/azure-sdk-for-java.git (push)
Current language=java
test-proxy --version
Writing file C:\workspace\azure-sdk-for-java\sdk\resourcemanager\azure-resourcemanager-resources\assets.json with the following contents
{
  "AssetsRepo": "Azure/azure-sdk-assets",
  "AssetsRepoPrefixPath": "java",
  "TagPrefix": "java/resourcemanager/azure-resourcemanager-resources",
  "Tag": ""
}
test-proxy restore --assets-json-path sdk\resourcemanager\azure-resourcemanager-resources\assets.json
Running proxy version is Azure.Sdk.Tools.TestProxy 20230608.1
git --version
git remote -v
git clone -c core.longpaths=true --no-checkout --filter=tree:0 https://github.com/Azure/azure-sdk-assets .
git sparse-checkout init
git sparse-checkout set --no-cone java/sdk/resourcemanager/azure-resourcemanager-resources
git -c advice.detachedHead=false checkout
git remote -v
git remote set-url origin https://github.com/Azure/azure-sdk-assets
assetsRoot=C:\workspace\azure-sdk-for-java\.assets\Di85Ra3l77\java\sdk\resourcemanager\azure-resourcemanager-resources
Language recording directory name=src.*?session-records
Get-ChildItem -Recurse -Filter "*.json" | Where-Object { if (src.*?session-records.Contains("*")) { .DirectoryName -match src.*?session-records } else { .DirectoryName.Split([IO.Path]::DirectorySeparatorChar) -contains "src.*?session-records" }
C:\workspace\azure-sdk-for-java\.assets\Di85Ra3l77\java\sdk\resourcemanager\azure-resourcemanager-resources\src\test\resources\session-records\DeploymentsTests.canBeginCreateAsync.json
C:\workspace\azure-sdk-for-java\.assets\Di85Ra3l77\java\sdk\resourcemanager\azure-resourcemanager-resources\src\test\resources\session-records\DeploymentsTests.canDeployVirtualNetwork.json
C:\workspace\azure-sdk-for-java\.assets\Di85Ra3l77\java\sdk\resourcemanager\azure-resourcemanager-resources\src\test\resources\session-records\DeploymentsTests.canDeployVirtualNetworkSyncPoll.json
C:\workspace\azure-sdk-for-java\.assets\Di85Ra3l77\java\sdk\resourcemanager\azure-resourcemanager-resources\src\test\resources\session-records\DeploymentsTests.canDeployVirtualNetworkSyncPollWithFailure.json
C:\workspace\azure-sdk-for-java\.assets\Di85Ra3l77\java\sdk\resourcemanager\azure-resourcemanager-resources\src\test\resources\session-records\DeploymentsTests.canDeployVirtualNetworkWithContext.json
C:\workspace\azure-sdk-for-java\.assets\Di85Ra3l77\java\sdk\resourcemanager\azure-resourcemanager-resources\src\test\resources\session-records\DeploymentsTests.canGetErrorWhenDeploymentFail.json
C:\workspace\azure-sdk-for-java\.assets\Di85Ra3l77\java\sdk\resourcemanager\azure-resourcemanager-resources\src\test\resources\session-records\DeploymentsTests.canPostDeploymentWhatIfOnResourceGroup.json
C:\workspace\azure-sdk-for-java\.assets\Di85Ra3l77\java\sdk\resourcemanager\azure-resourcemanager-resources\src\test\resources\session-records\DeploymentsTests.canPostDeploymentWhatIfOnSubscription.json
C:\workspace\azure-sdk-for-java\.assets\Di85Ra3l77\java\sdk\resourcemanager\azure-resourcemanager-resources\src\test\resources\session-records\DeploymentsTests.canUpdateVirtualNetworkDeployment.json
C:\workspace\azure-sdk-for-java\.assets\Di85Ra3l77\java\sdk\resourcemanager\azure-resourcemanager-resources\src\test\resources\session-records\FeaturesTests.canListAndRegisterFeature.json
C:\workspace\azure-sdk-for-java\.assets\Di85Ra3l77\java\sdk\resourcemanager\azure-resourcemanager-resources\src\test\resources\session-records\GenericResourcesTests.canCreateDeleteResourceSyncPoll.json
C:\workspace\azure-sdk-for-java\.assets\Di85Ra3l77\java\sdk\resourcemanager\azure-resourcemanager-resources\src\test\resources\session-records\GenericResourcesTests.canCreateUpdateKindSkuIdentity.json
C:\workspace\azure-sdk-for-java\.assets\Di85Ra3l77\java\sdk\resourcemanager\azure-resourcemanager-resources\src\test\resources\session-records\GenericResourcesTests.canCreateUpdateMoveResource.json
C:\workspace\azure-sdk-for-java\.assets\Di85Ra3l77\java\sdk\resourcemanager\azure-resourcemanager-resources\src\test\resources\session-records\GenericResourcesTests.canValidateMoveResources.json
C:\workspace\azure-sdk-for-java\.assets\Di85Ra3l77\java\sdk\resourcemanager\azure-resourcemanager-resources\src\test\resources\session-records\LocksTests.canCreateLock.json
C:\workspace\azure-sdk-for-java\.assets\Di85Ra3l77\java\sdk\resourcemanager\azure-resourcemanager-resources\src\test\resources\session-records\LocksTests.canCreateUpdateLock.json
C:\workspace\azure-sdk-for-java\.assets\Di85Ra3l77\java\sdk\resourcemanager\azure-resourcemanager-resources\src\test\resources\session-records\ResourceGroupsTests.canCreateResourceGroup.json
C:\workspace\azure-sdk-for-java\.assets\Di85Ra3l77\java\sdk\resourcemanager\azure-resourcemanager-resources\src\test\resources\session-records\SubscriptionsTests.canListLocations.json
C:\workspace\azure-sdk-for-java\.assets\Di85Ra3l77\java\sdk\resourcemanager\azure-resourcemanager-resources\src\test\resources\session-records\SubscriptionsTests.canListSubscriptions.json
C:\workspace\azure-sdk-for-java\.assets\Di85Ra3l77\java\sdk\resourcemanager\azure-resourcemanager-resources\src\test\resources\session-records\TagsTests.canUpdateTag.json
C:\workspace\azure-sdk-for-java\.assets\Di85Ra3l77\java\sdk\resourcemanager\azure-resourcemanager-resources\src\test\resources\session-records\TenantsTests.canListTenants.json
test-proxy push --assets-json-path sdk\resourcemanager\azure-resourcemanager-resources\assets.json
Unhandled exception: Azure.Sdk.Tools.TestProxy.Common.Exceptions.HttpException: Invocation of "git config --get user.name" had a non-zero exit code -1.
StdOut:
StdErr:

   at Azure.Sdk.Tools.TestProxy.Store.GitStore.Push(String pathToAssetsJson) in /mnt/vss/_work/1/s/tools/test-proxy/Azure.Sdk.Tools.TestProxy/Store/GitStore.cs:line 142
   at Azure.Sdk.Tools.TestProxy.Startup.Run(Object commandObj) in /mnt/vss/_work/1/s/tools/test-proxy/Azure.Sdk.Tools.TestProxy/Startup.cs:line 104
   at Azure.Sdk.Tools.TestProxy.CommandOptions.OptionsGenerator.<>c__DisplayClass0_0.<<GenerateCommandLineOptions>b__7>d.MoveNext() in /mnt/vss/_work/1/s/tools/test-proxy/Azure.Sdk.Tools.TestProxy/CommandOptions/OptionsGenerator.cs:line 87
--- End of stack trace from previous location ---
   at System.CommandLine.Invocation.AnonymousCommandHandler.InvokeAsync(InvocationContext context)
   at System.CommandLine.Invocation.InvocationPipeline.<>c__DisplayClass4_0.<<BuildInvocationChain>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass17_0.<<UseParseErrorReporting>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass12_0.<<UseHelp>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass22_0.<<UseVersionOption>b__0>d.MoveNext()--- End of stack trace from previous location ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass19_0.<<UseTypoCorrections>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c.<<UseSuggestDirective>b__18_0>d.MoveNext()
--- End of stack trace from previous location ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass16_0.<<UseParseDirective>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c.<<RegisterWithDotnetSuggest>b__5_0>d.MoveNext()
--- End of stack trace from previous location ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass8_0.<<UseExceptionHandler>b__0>d.MoveNext()
Running proxy version is Azure.Sdk.Tools.TestProxy 20230608.1
git --version
git remote -v
git remote set-url origin https://github.com/Azure/azure-sdk-assets
git status --porcelain
git config --get user.name
git remote -v
git remote set-url origin https://github.com/Azure/azure-sdk-assets
Write-Error: AssetsJsonFile (C:\workspace\azure-sdk-for-java\sdk\resourcemanager\azure-resourcemanager-resources\assets.json) did not have it's tag updated. Check above output messages for erroneous git output.

All SDK Contribution checklist:

  • The pull request does not introduce [breaking changes]
  • CHANGELOG is updated for new features, bug fixes or other significant changes.
  • I have read the contribution guidelines.

General Guidelines and Best Practices

  • Title of the pull request is clear and informative.
  • There are a small number of commits, each of which have an informative message. This means that previously merged commits do not appear in the history of the PR. For more information on cleaning up the commits in your PR, see this page.

Testing Guidelines

  • Pull request includes test coverage for the included changes.

@azure-sdk
Copy link
Collaborator

azure-sdk commented Jun 15, 2023

API change check

APIView has identified API level changes in this PR and created following API reviews.

azure-resourcemanager-resources

@samvaity
Copy link
Member

Deferring to @scbedd for issues related to installing the tooling (Question 1).
For Question 2 - lets talk offline.

@haolingdong-msft
Copy link
Member Author

haolingdong-msft commented Jun 19, 2023

Hi @samvaity , how about question 0?
PS: The RecordPolicy is set in TestBase.(https://github.com/Azure/azure-sdk-for-java/blob/main/sdk/core/azure-core-test/src/main/java/com/azure/core/test/TestBase.java#L182-L184)
Below is the inheritance structure.

class ResourceManagerTestBase extends TestProxyTestBas
class TestProxyTestBase extends TestBase

this one is resolved offline.

@haolingdong-msft
Copy link
Member Author

haolingdong-msft commented Jun 21, 2023

Hi @samvaity, the tests fail in CI in playback mode, but from my local they are successful. Do you have any suggestion or insight for this failure? Not sure if there is additional steps to be done in CI. Thanks.

@haolingdong-msft haolingdong-msft changed the title mgmt, testproxy, azure-resourcemanager-resources update session records mgmt, testproxy, azure-resourcemanager-resources Jun 27, 2023
@scbedd
Copy link
Member

scbedd commented Jun 27, 2023

To directly answer question 2. The proxy is using the default git, which gets access to stored credentials. However, to get the user/email that should be associated with the commit, we actually get these values using git config --get user.name or git config --get user.email.

Reference for what you need to do to make this error go away.

@scbedd
Copy link
Member

scbedd commented Jun 27, 2023

Hi @samvaity, the tests fail in CI in playback mode, but from my local they are successful. Do you have any suggestion or insight for this failure? Not sure if there is additional steps to be done in CI. Thanks.

Hey @haolingdong-msft , can you try a fresh clone of your forked branch? I have a feeling that you have some files locally cached that are causing this not to repro locally.

If you look at the build error it's actually telling you exactly what the problem is in CI.

Uri doesn't match:
    record  <[https://REDACTED/subscriptions/ec0aa5f7-9e78-40c9-85cd-535c6305b380/resources?api-version=2022-09-01>](https://redacted/subscriptions/ec0aa5f7-9e78-40c9-85cd-535c6305b380/resources?api-version=2022-09-01%3E)
    request <[https://REDACTED/subscriptions/00000000-0000-0000-0000-000000000000/resources?api-version=2022-09-01>](https://redacted/subscriptions/00000000-0000-0000-0000-000000000000/resources?api-version=2022-09-01%3E)

This makes me think that you have changes locally that either A) pull down different recordings or B) something else that I'm unaware of.

@haolingdong-msft
Copy link
Member Author

Hi @scbedd, this uri mismatch is because in playback mode, we will set subscription id to ZERO_UUID (00000000-0000-0000-0000-000000000000), but in RECORD mode, we will use a real sub id passed from env variable, it causes match error. To fix this, I have add a sanitizer to redact real sub id to ZERO_UUID. I want to use matcher to skip comparing sub id in url previously, but I found our matcher does not support url parth. I have already fixed it in this commit 906806f. Please let me know if you have better solution to solve this.

@haolingdong-msft
Copy link
Member Author

Hi @samvaity @scbedd , I found when I updated session records locally, and want to re-push to assets repo, the recordings in assets repo cannot get updated. Command I use is:

C:\workspace\azure-sdk-for-java> test-proxy push -a sdk/resourcemanager/azure-resourcemanager-resources/assets.json

I also tried to delete assets.json and .assets dir, and tried to initialize assets.json using below command, but still meet error. Could you please help to suggest?
image

@scbedd
Copy link
Member

scbedd commented Jun 30, 2023

Hi @samvaity @scbedd , I found when I updated session records locally, and want to re-push to assets repo, the recordings in assets repo cannot get updated. Command I use is:

C:\workspace\azure-sdk-for-java> test-proxy push -a sdk/resourcemanager/azure-resourcemanager-resources/assets.json

I also tried to delete assets.json and .assets dir, and tried to initialize assets.json using below command, but still meet error. Could you please help to suggest? image

Hey @haolingdong-msft , the reason that the push is failing and the tag isn't being updated is because there is no content being pushed!

This specific part of your log

image

Indicates to me that no files are being moved into the assets repo. If no files are moved, the tag won't be created, because there will be no new changes to commit!

You definitely have an updated assets.json in this PR, so I'm not certain why you are invoking this script to complete your push action.

Once you've completed initial migration, you only need run your tests in record mode, then test-proxy push -a sdk/resourcemanager/azure-resourcemanager-resources/assets.json (from the root of the repo)

You do not want to re-use the migration script to push recordings. Once the assets.json exists, your recording framework should be dropping the updated recordings already in the .assets folder. This is where content will be push-ed from.

@haolingdong-msft
Copy link
Member Author

/azp run java - resourcemanager - ci

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@haolingdong-msft
Copy link
Member Author

haolingdong-msft commented Jul 5, 2023

Hey @scbedd, if you look at my previous comment. I used initial push because I tried testproxy -push first, it succeeds, but seems assets repo not get updated and CI still fails.

I tried again just now, seems this time testproxy -push works and the assets repo is updated. But I checked the output of text-proxy push, it pushed to tag " java/resourcemanager/azure-resourcemanager-resources_fbfc1e56ca", but the tag in assets.json given to the command is "java/resourcemanager/azure-resourcemanager-resources_4ffc07a0a6", after push, assets.json's tag get updated, is it expected? I'm wondering why create a new tag after test-proxy push, but not reuse the existing tag in asset.json?

image
asset repo commit: Azure/azure-sdk-assets@fbfc1e5
assets.json get updated:
image

@@ -86,7 +86,9 @@ public Mono<HttpResponse> process(HttpPipelineCallContext context, HttpPipelineN
return next.process()
.doOnError(throwable -> {
networkCallRecord.setException(new NetworkCallError(throwable));
recordedData.addNetworkCall(networkCallRecord);
if (recordedData != null) { // when using testproxy, recordedData will be set to null
Copy link
Member

@weidongxu-microsoft weidongxu-microsoft Jul 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If recordedData is null, what TextReplacementPolicy.java does in test proxy setup?

If it does nothing (as it not able to do the addNetworkCall), can we not change this file, and not use it in TestProxyTestBase?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had the same thoughts that I had shared with @haolingdong-msft too. We should not be depending on recordedData/networkCall as with TestProxyTestBase we never initialize this data.

Comment on lines +133 to +172
/**
* @return random password
*/
public static String password() {
// do not record
String password = new ResourceNamer("").randomName("Pa5$", 12);
LOGGER.info("Password: {}", password);
return password;
}

private static String sshPublicKey;

/**
* @return an SSH public key
*/
public static String sshPublicKey() {
if (sshPublicKey == null) {
try {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(1024);
KeyPair pair = keyGen.generateKeyPair();
PublicKey publicKey = pair.getPublic();

RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey;
ByteArrayOutputStream byteOs = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(byteOs);
dos.writeInt("ssh-rsa".getBytes(StandardCharsets.US_ASCII).length);
dos.write("ssh-rsa".getBytes(StandardCharsets.US_ASCII));
dos.writeInt(rsaPublicKey.getPublicExponent().toByteArray().length);
dos.write(rsaPublicKey.getPublicExponent().toByteArray());
dos.writeInt(rsaPublicKey.getModulus().toByteArray().length);
dos.write(rsaPublicKey.getModulus().toByteArray());
String publicKeyEncoded = new String(Base64.getEncoder().encode(byteOs.toByteArray()), StandardCharsets.US_ASCII);
sshPublicKey = "ssh-rsa " + publicKeyEncoded;
} catch (NoSuchAlgorithmException | IOException e) {
throw LOGGER.logExceptionAsError(new IllegalStateException("failed to generate ssh key", e));
}
}
return sshPublicKey;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume these are duplicate code? Either use a common base, or move them to util class.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am fine with some duplicate code, but not lots of them.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently ResourceManagerTestProxyTestBase is just a copy of ResourceManagerTestBase, with updates in 'code change' section in description to fit in TestProxy.
image

Let me try to refine the code to make it easier to reuse the code in ResourceManagerTestBase and easier to see the difference.

Comment on lines +340 to +380
protected HttpClient generateHttpClientWithProxy(NettyAsyncHttpClientBuilder clientBuilder, ProxyOptions proxyOptions) {
if (clientBuilder == null) {
clientBuilder = new NettyAsyncHttpClientBuilder();
}
if (proxyOptions != null) {
clientBuilder.proxy(proxyOptions);
} else {
try {
System.setProperty(USE_SYSTEM_PROXY, VALUE_TRUE);
List<Proxy> proxies = ProxySelector.getDefault().select(new URI(AzureEnvironment.AZURE.getResourceManagerEndpoint()));
if (!proxies.isEmpty()) {
for (Proxy proxy : proxies) {
if (proxy.address() instanceof InetSocketAddress) {
String host = ((InetSocketAddress) proxy.address()).getHostName();
int port = ((InetSocketAddress) proxy.address()).getPort();
switch (proxy.type()) {
case HTTP:
return clientBuilder.proxy(new ProxyOptions(ProxyOptions.Type.HTTP, new InetSocketAddress(host, port))).build();
case SOCKS:
return clientBuilder.proxy(new ProxyOptions(ProxyOptions.Type.SOCKS5, new InetSocketAddress(host, port))).build();
default:
}
}
}
}
String host = null;
int port = 0;
if (System.getProperty(HTTPS_PROXY_HOST) != null && System.getProperty(HTTPS_PROXY_PORT) != null) {
host = System.getProperty(HTTPS_PROXY_HOST);
port = Integer.parseInt(System.getProperty(HTTPS_PROXY_PORT));
} else if (System.getProperty(HTTP_PROXY_HOST) != null && System.getProperty(HTTP_PROXY_PORT) != null) {
host = System.getProperty(HTTP_PROXY_HOST);
port = Integer.parseInt(System.getProperty(HTTP_PROXY_PORT));
}
if (host != null) {
clientBuilder.proxy(new ProxyOptions(ProxyOptions.Type.HTTP, new InetSocketAddress(host, port)));
}
} catch (URISyntaxException e) { }
}
return clientBuilder.build();
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this also duplicate code?

@haolingdong-msft haolingdong-msft requested a review from samvaity July 6, 2023 01:19
@haolingdong-msft haolingdong-msft changed the title mgmt, testproxy, azure-resourcemanager-resources mgmt, testproxy migration, azure-resourcemanager-resources Jul 6, 2023
@@ -241,7 +241,7 @@ protected void beforeTest() {
if (isPlaybackMode()) {
if (interceptorManager.getRecordedData() == null) {
skipInPlayback();
return;
// return;
Copy link
Member Author

@haolingdong-msft haolingdong-msft Jul 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove return here because when using testproxy, interceptorManager.getRecordedData() will be null. If return directly, when running in playback mode, below logics to initialize clients will be skiped.
There will be nullpointer error since the client is not initialized when running tests in playback.
image

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is TextProxyTestBase, I take interceptorManager.getRecordedData() is always null, and skipInPlayback() is always called?

And why do we want skipInPlayback() always called? (regardless whether the test want to skip in playback or not)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isSkipInPlayback = true seems meaning it does not clean up the resource after test complete?

Copy link
Member Author

@haolingdong-msft haolingdong-msft Jul 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isSkipInPlayback = true seems meaning it does not clean up the resource after test complete?

Yes, if we set to true, it will not do test resource clean up calls. Previously I think it is playback mode, there is no need to do resource clean up. But to be consistent with previous logic, we can do resouce clean up as well, that is to delete below whole part. What do you think?

            if (interceptorManager.getRecordedData() == null) {
                skipInPlayback();
                return;
             }

Copy link
Member

@weidongxu-microsoft weidongxu-microsoft Jul 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, you can do this.

Later we may get to test case with @DoNotRecord(skipInPlayback = true), which may have problem under TestProxy setting (I kind of assume code here was to handle that, but not sure). You can handle that later.

Copy link
Member Author

@haolingdong-msft haolingdong-msft Jul 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DoNotRecord(skipInPlayback = true) -> there is this case in resources. I will delete this part logic and try on playback and record mode.

"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "java",
"TagPrefix": "java/resourcemanager/azure-resourcemanager-resources",
"Tag": "java/resourcemanager/azure-resourcemanager-resources_da922b0432"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

@weidongxu-microsoft weidongxu-microsoft Jul 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And retry-after seems not handled.
https://github.com/Azure/azure-sdk-assets/blob/java/resourcemanager/azure-resourcemanager-resources_da922b0432/java/sdk/resourcemanager/azure-resourcemanager-resources/src/test/resources/session-records/DeploymentsTests.canDeployVirtualNetwork.json#L741

(but I am not sure whether there is logic to set it to 0, after load the data. but previously the recorded data is 0

)

Wondering whether playback on long LRO (e.g. sql server) can finish in 30 seconds (current cut-off time for each case in playback).

Copy link
Member Author

@haolingdong-msft haolingdong-msft Jul 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

api-version still there is expected, but in test base (this mather only works in playback mode), we will ignore match api-version, the logic is here:

@joshfree joshfree added the test-proxy Anything relating to test-proxy requests or issues. label Jul 11, 2023
@samvaity
Copy link
Member

I am also noticing the sub-id in teh response body

"id": "/subscriptions/ec0aa5f7-9e78-40c9-8fhu-535c6305b880/resourceGroups/rg1034503",

This can be sanitized with the sanitizer
interceptorManager.addSanitizers(Arrays.asList(new TestProxySanitizer("id", "(?<=%2Fsubscriptions%2F)([^/?]+)", ZERO_UUID, TestProxySanitizerType.BODY_KEY)));

@weidongxu-microsoft
Copy link
Member

Thanks Sameeksha. We may also want to sanitize the LRO headers in response, e.g.
https://github.com/Azure/azure-sdk-assets/blob/java/resourcemanager/azure-resourcemanager-resources_da922b0432/java/sdk/resourcemanager/azure-resourcemanager-resources/src/test/resources/session-records/DeploymentsTests.canDeployVirtualNetwork.json#L739

Though in playback, seems the match function can handle the difference of real subscriptionId and the all 0 ones (or LRO won't work).

interceptorManager.addSanitizers(Arrays.asList(new TestProxySanitizer("(?<=/subscriptions/)([^/?]+)", ZERO_UUID, TestProxySanitizerType.URL)));
interceptorManager.addSanitizers(Arrays.asList(new TestProxySanitizer("(?<=%2Fsubscriptions%2F)([^/?]+)", ZERO_UUID, TestProxySanitizerType.URL)));
// Retry-After
interceptorManager.addSanitizers(Arrays.asList(new TestProxySanitizer("Retry-After", null, "0", TestProxySanitizerType.HEADER)));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One corner case would be service does not set retry-after header.

Though I thought SDK will set the default LRO poll interval to something like 0 during playback, so we are likely fine.

@weidongxu-microsoft
Copy link
Member

weidongxu-microsoft commented Jul 18, 2023

LGTM. Have one comment. You can merge after revert changes in "TextReplacementPolicy.java" and CI pass.

@XiaofeiCao
Copy link
Contributor

XiaofeiCao commented Jul 19, 2023

Thanks Sameeksha. We may also want to sanitize the LRO headers in response, e.g. https://github.com/Azure/azure-sdk-assets/blob/java/resourcemanager/azure-resourcemanager-resources_da922b0432/java/sdk/resourcemanager/azure-resourcemanager-resources/src/test/resources/session-records/DeploymentsTests.canDeployVirtualNetwork.json#L739

Though in playback, seems the match function can handle the difference of real subscriptionId and the all 0 ones (or LRO won't work).

Sanitizers seem to do the work in playback mode(thought match function would do that too).

@XiaofeiCao
Copy link
Contributor

I've encountered timeout reported by Netty http client when batch running playback client using mvn test.

log here:

timeout error stack

[ERROR] com.azure.resourcemanager.resources.FeaturesTests.canListAndRegisterFeature Time elapsed: 60.742 s <<< ERROR!
java.lang.RuntimeException: java.util.concurrent.TimeoutException: Channel response timed out after 60000 milliseconds.
at [email protected]/com.azure.core.http.netty.NettyAsyncHttpClient.sendSync(NettyAsyncHttpClient.java:160)
at com.azure.core.test.http.TestProxyPlaybackClient.startPlayback(TestProxyPlaybackClient.java:91)
at com.azure.core.test.InterceptorManager.getPlaybackClient(InterceptorManager.java:333)
at com.azure.core.test.TestBase.setupTest(TestBase.java:181)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.api.extension.InvocationInterceptor.interceptBeforeEachMethod(InvocationInterceptor.java:103)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptLifecycleMethod(TimeoutExtension.java:128)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptBeforeEachMethod(TimeoutExtension.java:78)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeMethodInExtensionContext(ClassBasedTestDescriptor.java:520)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$synthesizeBeforeEachMethodAdapter$23(ClassBasedTestDescriptor.java:505)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeBeforeEachMethods$3(TestMethodTestDescriptor.java:174)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeBeforeMethodsOrCallbacksUntilExceptionOccurs$6(TestMethodTestDescriptor.java:202)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeBeforeMethodsOrCallbacksUntilExceptionOccurs(TestMethodTestDescriptor.java:202)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeBeforeEachMethods(TestMethodTestDescriptor.java:171)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:134)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService$ExclusiveTask.compute(ForkJoinPoolHierarchicalTestExecutorService.java:202)
at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService.invokeAll(ForkJoinPoolHierarchicalTestExecutorService.java:146)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService$ExclusiveTask.compute(ForkJoinPoolHierarchicalTestExecutorService.java:202)
at java.base/java.util.concurrent.RecursiveAction.exec(RecursiveAction.java:194)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182)
at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165)
Caused by: java.util.concurrent.TimeoutException: Channel response timed out after 60000 milliseconds.
at [email protected]/com.azure.core.http.netty.implementation.AzureSdkHandler.responseTimedOut(AzureSdkHandler.java:200)
at [email protected]/com.azure.core.http.netty.implementation.AzureSdkHandler.lambda$startResponseTracking$2(AzureSdkHandler.java:184)
at [email protected]/io.netty.util.concurrent.PromiseTask.runTask(PromiseTask.java:98)
at [email protected]/io.netty.util.concurrent.ScheduledFutureTask.run(ScheduledFutureTask.java:153)
at [email protected]/io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:174)
at [email protected]/io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:167)
at [email protected]/io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:470)
at [email protected]/io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:569)
at [email protected]/io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
at [email protected]/io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at [email protected]/io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:833)

This only occurs when .assets directory is already under azure-sdk-for-java. When there's no .assets and I let test-proxy to load it for the first time, mvn test passes.

@weidongxu-microsoft
Copy link
Member

Strange... canListAndRegisterFeature just do GET (maybe a few pages) then a POST. It does not have LRO.

@XiaofeiCao
Copy link
Contributor

Issue logged: #35992

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
test-proxy Anything relating to test-proxy requests or issues.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants