Skip to content

Commit a40f362

Browse files
mgmt, fix ProviderRegistrationPolicy (Azure#31742)
1 parent dda23e7 commit a40f362

File tree

7 files changed

+516
-15
lines changed

7 files changed

+516
-15
lines changed

sdk/resourcemanager/azure-resourcemanager-resources/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## 2.20.0 (2022-10-26)
44

5+
### Bugs Fixed
6+
7+
- Fixed bug that `ProviderRegistrationPolicy` does not work.
8+
59
### Other Changes
610

711
#### Dependency Updates

sdk/resourcemanager/azure-resourcemanager-resources/src/main/java/com/azure/resourcemanager/resources/fluentcore/policy/ProviderRegistrationPolicy.java

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ public Mono<HttpResponse> process(HttpPipelineCallContext context, HttpPipelineN
7878
if (providers == null) {
7979
return next.process();
8080
}
81-
return next.process().flatMap(
81+
return next.clone().process().flatMap(
8282
response -> {
8383
if (!isResponseSuccessful(response)) {
8484
HttpResponse bufferedResponse = response.buffer();
@@ -88,24 +88,44 @@ public Mono<HttpResponse> process(HttpPipelineCallContext context, HttpPipelineN
8888

8989
SerializerAdapter jacksonAdapter =
9090
SerializerFactory.createDefaultManagementSerializerAdapter();
91-
ManagementError cloudError;
91+
ManagementError managementError;
9292
try {
93-
cloudError = jacksonAdapter.deserialize(
93+
managementError = jacksonAdapter.deserialize(
9494
bodyStr, ManagementError.class, SerializerEncoding.JSON);
9595
} catch (IOException e) {
9696
return Mono.just(bufferedResponse);
9797
}
9898

99-
if (cloudError != null && MISSING_SUBSCRIPTION_REGISTRATION.equals(cloudError.getCode())) {
100-
Pattern providerPattern = Pattern.compile(".*'(.*)'");
101-
Matcher providerMatcher = providerPattern.matcher(cloudError.getMessage());
102-
if (!providerMatcher.find()) {
103-
return Mono.just(bufferedResponse);
99+
if (managementError != null
100+
&& MISSING_SUBSCRIPTION_REGISTRATION.equals(managementError.getCode())) {
101+
102+
String resourceNamespace = null;
103+
104+
if (managementError.getDetails() != null) {
105+
// find in details.target
106+
resourceNamespace = managementError.getDetails().stream()
107+
.filter(d -> MISSING_SUBSCRIPTION_REGISTRATION.equals(d.getCode())
108+
&& d.getTarget() != null)
109+
.map(ManagementError::getTarget)
110+
.findFirst().orElse(null);
111+
}
112+
if (resourceNamespace == null) {
113+
// find in message
114+
Pattern providerPattern = Pattern.compile(".*'(.*)'");
115+
Matcher providerMatcher = providerPattern.matcher(managementError.getMessage());
116+
if (!providerMatcher.find()) {
117+
return Mono.just(bufferedResponse);
118+
}
119+
resourceNamespace = providerMatcher.group(1);
104120
}
105121

106122
// Retry after registration
107-
return registerProviderUntilSuccess(providerMatcher.group(1))
108-
.flatMap(afterRegistered -> next.process());
123+
return registerProviderUntilSuccess(resourceNamespace)
124+
// in case error, return the response before registering resource provider
125+
// if not error, this will be ignored
126+
.then(Mono.just(bufferedResponse))
127+
.onErrorReturn(bufferedResponse)
128+
.then(next.clone().process());
109129
}
110130
return Mono.just(bufferedResponse);
111131
}
@@ -124,8 +144,12 @@ private Mono<Void> registerProviderUntilSuccess(String namespace) {
124144
return Mono.empty();
125145
}
126146
return providers.getByNameAsync(namespace)
127-
.flatMap(this::checkProviderRegistered)
128-
.retryWhen(Retry.max(60).filter(ProviderUnregisteredException.class::isInstance));
147+
.flatMap(this::checkProviderRegistered)
148+
.retryWhen(Retry
149+
// 30 * 10sec
150+
.fixedDelay(30,
151+
ResourceManagerUtils.InternalRuntimeContext.getDelayDuration(Duration.ofSeconds(10)))
152+
.filter(ProviderUnregisteredException.class::isInstance));
129153
}
130154
);
131155
}
@@ -134,12 +158,11 @@ private Mono<Void> checkProviderRegistered(Provider provider) throws ProviderUnr
134158
if (isProviderRegistered(provider)) {
135159
return Mono.empty();
136160
}
137-
ResourceManagerUtils.sleep(Duration.ofSeconds(5));
138161
return Mono.error(new ProviderUnregisteredException());
139162
}
140163

141164
private boolean isProviderRegistered(Provider provider) {
142-
return provider.registrationState().equalsIgnoreCase("Registered");
165+
return "Registered".equalsIgnoreCase(provider.registrationState());
143166
}
144167

145168
private static class ProviderUnregisteredException extends RuntimeException {

sdk/resourcemanager/azure-resourcemanager/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## 2.20.0 (2022-10-26)
44

5+
### Bugs Fixed
6+
7+
- Fixed bug that `ProviderRegistrationPolicy` does not work.
8+
59
### Other Changes
610

711
#### Dependency Updates

sdk/resourcemanager/azure-resourcemanager/pom.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@
5454
--add-opens com.azure.resourcemanager.resources/com.azure.resourcemanager.resources=ALL-UNNAMED
5555
--add-opens com.azure.resourcemanager.resources/com.azure.resourcemanager.resources.fluentcore.arm=ALL-UNNAMED
5656
--add-opens com.azure.resourcemanager.sql/com.azure.resourcemanager.sql=ALL-UNNAMED
57+
58+
--add-opens com.azure.core/com.azure.core.implementation.util=ALL-UNNAMED
5759
</javaModulesSurefireArgLine>
5860
</properties>
5961

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
package com.azure.resourcemanager;
5+
6+
import com.azure.core.credential.TokenCredential;
7+
import com.azure.core.http.HttpClient;
8+
import com.azure.core.http.HttpPipeline;
9+
import com.azure.core.http.policy.HttpLogOptions;
10+
import com.azure.core.http.policy.HttpPipelinePolicy;
11+
import com.azure.core.http.policy.RetryPolicy;
12+
import com.azure.core.management.Region;
13+
import com.azure.core.management.profile.AzureProfile;
14+
import com.azure.resourcemanager.containerregistry.models.Registry;
15+
import com.azure.resourcemanager.resources.fluentcore.utils.HttpPipelineProvider;
16+
import com.azure.resourcemanager.resources.fluentcore.utils.ResourceManagerUtils;
17+
import com.azure.resourcemanager.resources.models.Provider;
18+
import com.azure.resourcemanager.test.ResourceManagerTestBase;
19+
import com.azure.resourcemanager.test.utils.TestDelayProvider;
20+
import com.azure.resourcemanager.test.utils.TestIdentifierProvider;
21+
import org.junit.jupiter.api.Assertions;
22+
import org.junit.jupiter.api.Test;
23+
24+
import java.time.Duration;
25+
import java.time.temporal.ChronoUnit;
26+
import java.util.List;
27+
28+
public class ProviderRegistrationPolicyTests extends ResourceManagerTestBase {
29+
30+
private AzureResourceManager azureResourceManager;
31+
32+
private String rgName;
33+
34+
@Override
35+
protected HttpPipeline buildHttpPipeline(
36+
TokenCredential credential,
37+
AzureProfile profile,
38+
HttpLogOptions httpLogOptions,
39+
List<HttpPipelinePolicy> policies,
40+
HttpClient httpClient) {
41+
return HttpPipelineProvider.buildHttpPipeline(
42+
credential,
43+
profile,
44+
null,
45+
httpLogOptions,
46+
null,
47+
new RetryPolicy("Retry-After", ChronoUnit.SECONDS),
48+
policies,
49+
httpClient);
50+
}
51+
52+
@Override
53+
protected void initializeClients(HttpPipeline httpPipeline, AzureProfile profile) {
54+
ResourceManagerUtils.InternalRuntimeContext.setDelayProvider(new TestDelayProvider(!isPlaybackMode()));
55+
ResourceManagerUtils.InternalRuntimeContext internalContext = new ResourceManagerUtils.InternalRuntimeContext();
56+
internalContext.setIdentifierFunction(name -> new TestIdentifierProvider(testResourceNamer));
57+
azureResourceManager = AzureResourceManager.authenticate(httpPipeline, profile).withDefaultSubscription();
58+
setInternalContext(internalContext, azureResourceManager);
59+
60+
rgName = generateRandomResourceName("rg", 8);
61+
}
62+
63+
@Override
64+
protected void cleanUpResources() {
65+
azureResourceManager.resourceGroups().beginDeleteByName(rgName);
66+
}
67+
68+
@Test
69+
public void testProviderRegistrationPolicy() {
70+
final String acrName = generateRandomResourceName("acr", 10);
71+
72+
final String namespace = "Microsoft.ContainerRegistry";
73+
74+
Provider provider = azureResourceManager.providers().getByName(namespace);
75+
if (provider != null && "Registered".equalsIgnoreCase(provider.registrationState())) {
76+
provider = azureResourceManager.providers().unregister(namespace);
77+
78+
// wait for unregister complete
79+
ResourceManagerUtils.sleep(Duration.ofMinutes(5));
80+
81+
provider = azureResourceManager.providers().getByName(namespace);
82+
}
83+
Assertions.assertEquals("Unregistered", provider.registrationState());
84+
85+
Registry registry =
86+
azureResourceManager
87+
.containerRegistries()
88+
.define(acrName)
89+
.withRegion(Region.US_WEST_CENTRAL)
90+
.withNewResourceGroup(rgName)
91+
.withPremiumSku()
92+
.withRegistryNameAsAdminUser()
93+
.withTag("tag1", "value1")
94+
.create();
95+
96+
// above should success even when namespace "Microsoft.ContainerRegistry" not registered
97+
Assertions.assertNotNull(registry);
98+
}
99+
}

sdk/resourcemanager/azure-resourcemanager/src/test/resources/session-records/ProviderRegistrationPolicyTests.testProviderRegistrationPolicy.json

Lines changed: 369 additions & 0 deletions
Large diffs are not rendered by default.

sdk/resourcemanager/docs/HOW_TO_ADD_LIVE_TESTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,4 +100,4 @@ After pull request is ready, comment `/azp run prepare-pipelines` to let the aut
100100

101101
The live tests will be automatically run, before SDK release.
102102

103-
In pull request, comment `/azp run java - <service> - tests.mgmt` to run it manually.
103+
In pull request, comment `/azp run java - <service> - mgmt - tests` to run it manually.

0 commit comments

Comments
 (0)