Skip to content

Commit 0d8732b

Browse files
committed
[Test] Do not rely on MockZenPing for Azure tests (#27945)
This commit changes some Azure tests so that they do not rely on MockZenPing and TestZenDiscovery anymore, but instead use a mocked AzureComputeService that exposes internal test cluster nodes as if they were real Azure nodes. Related to #27859 Closes #27917, #11533
1 parent 0db631c commit 0d8732b

File tree

10 files changed

+209
-390
lines changed

10 files changed

+209
-390
lines changed

core/src/main/java/org/elasticsearch/plugins/DiscoveryPlugin.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919

2020
package org.elasticsearch.plugins;
2121

22-
import java.util.Collection;
2322
import java.util.Collections;
2423
import java.util.Map;
2524
import java.util.function.BiConsumer;

plugins/discovery-azure-classic/src/main/java/org/elasticsearch/discovery/azure/classic/AzureUnicastHostsProvider.java

Lines changed: 25 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ public enum HostType {
6262
this.type = type ;
6363
}
6464

65+
public String getType() {
66+
return type;
67+
}
68+
6569
public static HostType fromString(String type) {
6670
for (HostType hostType : values()) {
6771
if (hostType.type.equalsIgnoreCase(type)) {
@@ -196,43 +200,7 @@ public List<DiscoveryNode> buildDynamicNodes() {
196200
// In other case, it should be the right deployment so we can add it to the list of instances
197201

198202
for (RoleInstance instance : deployment.getRoleInstances()) {
199-
String networkAddress = null;
200-
// Let's detect if we want to use public or private IP
201-
switch (hostType) {
202-
case PRIVATE_IP:
203-
InetAddress privateIp = instance.getIPAddress();
204-
205-
if (privateIp != null) {
206-
if (privateIp.equals(ipAddress)) {
207-
logger.trace("adding ourselves {}", NetworkAddress.format(ipAddress));
208-
}
209-
networkAddress = InetAddresses.toUriString(privateIp);
210-
} else {
211-
logger.trace("no private ip provided. ignoring [{}]...", instance.getInstanceName());
212-
}
213-
break;
214-
case PUBLIC_IP:
215-
for (InstanceEndpoint endpoint : instance.getInstanceEndpoints()) {
216-
if (!publicEndpointName.equals(endpoint.getName())) {
217-
logger.trace("ignoring endpoint [{}] as different than [{}]",
218-
endpoint.getName(), publicEndpointName);
219-
continue;
220-
}
221-
222-
networkAddress = NetworkAddress.format(new InetSocketAddress(endpoint.getVirtualIPAddress(),
223-
endpoint.getPort()));
224-
}
225-
226-
if (networkAddress == null) {
227-
logger.trace("no public ip provided. ignoring [{}]...", instance.getInstanceName());
228-
}
229-
break;
230-
default:
231-
// This could never happen!
232-
logger.warn("undefined host_type [{}]. Please check your settings.", hostType);
233-
return cachedDiscoNodes;
234-
}
235-
203+
final String networkAddress = resolveInstanceAddress(hostType, instance);
236204
if (networkAddress == null) {
237205
// We have a bad parameter here or not enough information from azure
238206
logger.warn("no network address found. ignoring [{}]...", instance.getInstanceName());
@@ -257,4 +225,24 @@ public List<DiscoveryNode> buildDynamicNodes() {
257225

258226
return cachedDiscoNodes;
259227
}
228+
229+
protected String resolveInstanceAddress(final HostType hostType, final RoleInstance instance) {
230+
if (hostType == HostType.PRIVATE_IP) {
231+
final InetAddress privateIp = instance.getIPAddress();
232+
if (privateIp != null) {
233+
return InetAddresses.toUriString(privateIp);
234+
} else {
235+
logger.trace("no private ip provided. ignoring [{}]...", instance.getInstanceName());
236+
}
237+
} else if (hostType == HostType.PUBLIC_IP) {
238+
for (InstanceEndpoint endpoint : instance.getInstanceEndpoints()) {
239+
if (publicEndpointName.equals(endpoint.getName())) {
240+
return NetworkAddress.format(new InetSocketAddress(endpoint.getVirtualIPAddress(), endpoint.getPort()));
241+
} else {
242+
logger.trace("ignoring endpoint [{}] as different than [{}]", endpoint.getName(), publicEndpointName);
243+
}
244+
}
245+
}
246+
return null;
247+
}
260248
}

plugins/discovery-azure-classic/src/main/java/org/elasticsearch/plugin/discovery/azure/classic/AzureDiscoveryPlugin.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,16 @@ protected AzureComputeService createComputeService() {
6161
public Map<String, Supplier<UnicastHostsProvider>> getZenHostsProviders(TransportService transportService,
6262
NetworkService networkService) {
6363
return Collections.singletonMap(AZURE,
64-
() -> new AzureUnicastHostsProvider(settings, createComputeService(), transportService, networkService));
64+
() -> createUnicastHostsProvider(settings, createComputeService(), transportService, networkService));
6565
}
6666

67-
67+
// Used for testing
68+
protected AzureUnicastHostsProvider createUnicastHostsProvider(final Settings settings,
69+
final AzureComputeService azureComputeService,
70+
final TransportService transportService,
71+
final NetworkService networkService) {
72+
return new AzureUnicastHostsProvider(settings, azureComputeService, transportService, networkService);
73+
}
6874

6975
@Override
7076
public List<Setting<?>> getSettings() {
@@ -79,6 +85,4 @@ public List<Setting<?>> getSettings() {
7985
AzureComputeService.Discovery.DEPLOYMENT_SLOT_SETTING,
8086
AzureComputeService.Discovery.ENDPOINT_NAME_SETTING);
8187
}
82-
83-
8488
}

plugins/discovery-azure-classic/src/test/java/org/elasticsearch/cloud/azure/classic/AbstractAzureComputeServiceTestCase.java

Lines changed: 128 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,28 +19,45 @@
1919

2020
package org.elasticsearch.cloud.azure.classic;
2121

22+
import com.microsoft.windowsazure.management.compute.models.DeploymentSlot;
23+
import com.microsoft.windowsazure.management.compute.models.DeploymentStatus;
24+
import com.microsoft.windowsazure.management.compute.models.HostedServiceGetDetailedResponse;
25+
import com.microsoft.windowsazure.management.compute.models.InstanceEndpoint;
26+
import com.microsoft.windowsazure.management.compute.models.RoleInstance;
27+
import com.microsoft.windowsazure.management.compute.models.RoleInstancePowerState;
2228
import org.elasticsearch.action.admin.cluster.node.info.NodesInfoResponse;
29+
import org.elasticsearch.cloud.azure.classic.management.AzureComputeService;
2330
import org.elasticsearch.cloud.azure.classic.management.AzureComputeService.Discovery;
2431
import org.elasticsearch.cloud.azure.classic.management.AzureComputeService.Management;
32+
import org.elasticsearch.cluster.node.DiscoveryNode;
33+
import org.elasticsearch.common.network.NetworkAddress;
34+
import org.elasticsearch.common.network.NetworkService;
2535
import org.elasticsearch.common.settings.Settings;
36+
import org.elasticsearch.common.transport.TransportAddress;
37+
import org.elasticsearch.discovery.azure.classic.AzureUnicastHostsProvider;
38+
import org.elasticsearch.discovery.zen.ZenDiscovery;
39+
import org.elasticsearch.plugin.discovery.azure.classic.AzureDiscoveryPlugin;
2640
import org.elasticsearch.plugins.Plugin;
2741
import org.elasticsearch.test.ESIntegTestCase;
42+
import org.elasticsearch.transport.TransportService;
43+
import org.junit.After;
2844

29-
import java.util.Arrays;
45+
import java.util.ArrayList;
3046
import java.util.Collection;
47+
import java.util.Collections;
48+
import java.util.List;
49+
import java.util.Map;
50+
import java.util.concurrent.ConcurrentHashMap;
51+
52+
import static org.elasticsearch.common.util.CollectionUtils.newSingletonArrayList;
3153

3254
public abstract class AbstractAzureComputeServiceTestCase extends ESIntegTestCase {
3355

34-
private Class<? extends Plugin> mockPlugin;
56+
private static final Map<String, DiscoveryNode> nodes = new ConcurrentHashMap<>();
3557

36-
public AbstractAzureComputeServiceTestCase(Class<? extends Plugin> mockPlugin) {
37-
// We want to inject the Azure API Mock
38-
this.mockPlugin = mockPlugin;
39-
}
40-
41-
@Override
42-
protected boolean addTestZenDiscovery() {
43-
return false;
58+
@After
59+
public void clearAzureNodes() {
60+
nodes.clear();
4461
}
4562

4663
@Override
@@ -49,6 +66,10 @@ protected Settings nodeSettings(int nodeOrdinal) {
4966
.put(super.nodeSettings(nodeOrdinal))
5067
.put("discovery.zen.hosts_provider", "azure");
5168

69+
// Make the test run faster
70+
builder.put(ZenDiscovery.JOIN_TIMEOUT_SETTING.getKey(), "1s")
71+
.put(ZenDiscovery.PING_TIMEOUT_SETTING.getKey(), "500ms");
72+
5273
// We add a fake subscription_id to start mock compute service
5374
builder.put(Management.SUBSCRIPTION_ID_SETTING.getKey(), "fake")
5475
.put(Discovery.REFRESH_SETTING.getKey(), "5s")
@@ -60,13 +81,107 @@ protected Settings nodeSettings(int nodeOrdinal) {
6081

6182
@Override
6283
protected Collection<Class<? extends Plugin>> nodePlugins() {
63-
return Arrays.asList(mockPlugin);
84+
return Collections.singletonList(TestPlugin.class);
6485
}
6586

66-
protected void checkNumberOfNodes(int expected) {
67-
NodesInfoResponse nodeInfos = client().admin().cluster().prepareNodesInfo().execute().actionGet();
87+
@Override
88+
protected boolean addTestZenDiscovery() {
89+
return false;
90+
}
91+
92+
/**
93+
* Register an existing node as a Azure node, exposing its address and details htrough
94+
*
95+
* @param nodeName the name of the node
96+
*/
97+
protected void registerAzureNode(final String nodeName) {
98+
TransportService transportService = internalCluster().getInstance(TransportService.class, nodeName);
99+
assertNotNull(transportService);
100+
DiscoveryNode discoveryNode = transportService.getLocalNode();
101+
assertNotNull(discoveryNode);
102+
if (nodes.put(discoveryNode.getName(), discoveryNode) != null) {
103+
throw new IllegalArgumentException("Node [" + discoveryNode.getName() + "] cannot be registered twice in Azure");
104+
}
105+
}
106+
107+
protected void assertNumberOfNodes(int expected) {
108+
NodesInfoResponse nodeInfos = client().admin().cluster().prepareNodesInfo().clear().execute().actionGet();
68109
assertNotNull(nodeInfos);
69110
assertNotNull(nodeInfos.getNodes());
70111
assertEquals(expected, nodeInfos.getNodes().size());
71112
}
113+
114+
/**
115+
* Test plugin that exposes internal test cluster nodes as if they were real Azure nodes.
116+
* Use {@link #registerAzureNode(String)} method to expose nodes in the tests.
117+
*/
118+
public static class TestPlugin extends AzureDiscoveryPlugin {
119+
120+
public TestPlugin(Settings settings) {
121+
super(settings);
122+
}
123+
124+
@Override
125+
protected AzureComputeService createComputeService() {
126+
return () -> {
127+
final List<RoleInstance> instances = new ArrayList<>();
128+
for (Map.Entry<String, DiscoveryNode> node : nodes.entrySet()) {
129+
final String name = node.getKey();
130+
final DiscoveryNode discoveryNode = node.getValue();
131+
132+
RoleInstance instance = new RoleInstance();
133+
instance.setInstanceName(name);
134+
instance.setHostName(discoveryNode.getHostName());
135+
instance.setPowerState(RoleInstancePowerState.Started);
136+
137+
// Set the private IP address
138+
final TransportAddress transportAddress = discoveryNode.getAddress();
139+
instance.setIPAddress(transportAddress.address().getAddress());
140+
141+
// Set the public IP address
142+
final InstanceEndpoint endpoint = new InstanceEndpoint();
143+
endpoint.setName(Discovery.ENDPOINT_NAME_SETTING.getDefault(Settings.EMPTY));
144+
endpoint.setVirtualIPAddress(transportAddress.address().getAddress());
145+
endpoint.setPort(transportAddress.address().getPort());
146+
instance.setInstanceEndpoints(new ArrayList<>(Collections.singletonList(endpoint)));
147+
instances.add(instance);
148+
}
149+
150+
final HostedServiceGetDetailedResponse.Deployment deployment = new HostedServiceGetDetailedResponse.Deployment();
151+
deployment.setName("dummy");
152+
deployment.setDeploymentSlot(DeploymentSlot.Production);
153+
deployment.setStatus(DeploymentStatus.Running);
154+
deployment.setRoleInstances(new ArrayList<>(Collections.unmodifiableList(instances)));
155+
156+
final HostedServiceGetDetailedResponse response = new HostedServiceGetDetailedResponse();
157+
response.setDeployments(newSingletonArrayList(deployment));
158+
159+
return response;
160+
};
161+
}
162+
163+
/**
164+
* Defines a {@link AzureUnicastHostsProvider} for testing purpose that is able to resolve
165+
* network addresses for Azure instances running on the same host but different ports.
166+
*/
167+
@Override
168+
protected AzureUnicastHostsProvider createUnicastHostsProvider(final Settings settings,
169+
final AzureComputeService azureComputeService,
170+
final TransportService transportService,
171+
final NetworkService networkService) {
172+
return new AzureUnicastHostsProvider(settings, azureComputeService, transportService, networkService) {
173+
@Override
174+
protected String resolveInstanceAddress(final HostType hostType, final RoleInstance instance) {
175+
if (hostType == HostType.PRIVATE_IP) {
176+
DiscoveryNode discoveryNode = nodes.get(instance.getInstanceName());
177+
if (discoveryNode != null) {
178+
// Format the InetSocketAddress to a format that contains the port number
179+
return NetworkAddress.format(discoveryNode.getAddress().address());
180+
}
181+
}
182+
return super.resolveInstanceAddress(hostType, instance);
183+
}
184+
};
185+
}
186+
}
72187
}

plugins/discovery-azure-classic/src/test/java/org/elasticsearch/cloud/azure/classic/AzureComputeServiceSimpleMock.java

Lines changed: 0 additions & 83 deletions
This file was deleted.

0 commit comments

Comments
 (0)