/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.kie.server.client;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import com.github.tomakehurst.wiremock.WireMockServer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.kie.server.common.rest.KieServerHttpRequestException;
import org.kie.server.api.model.KieServerInfo;
import org.kie.server.api.model.ServiceResponse;
import org.kie.server.client.balancer.BalancerStrategy;
import org.kie.server.client.balancer.LoadBalancer;
import org.kie.server.client.impl.AbstractKieServicesClientImpl;
import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static org.junit.Assert.*;
public class LoadBalancerClientTest {
private String mockServerBaseUri1;
private String mockServerBaseUri2;
private String mockServerBaseUri3;
private WireMockServer wireMockServer1;
private WireMockServer wireMockServer2;
private WireMockServer wireMockServer3;
private KieServicesConfiguration config;
protected WireMockServer createMockServer(String version, int port) {
WireMockServer wireMockServer = new WireMockServer(port);
wireMockServer.stubFor(get(urlEqualTo("/"))
.withHeader("Accept", equalTo("application/xml"))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/xml")
.withBody("<response type=\"SUCCESS\" msg=\"Kie Server info\">\n" +
" <kie-server-info>\n" +
" <version>" + version + "</version>\n" +
" </kie-server-info>\n" +
"</response>")));
return wireMockServer;
}
@Before
public void startServers() {
int port1 = BaseKieServicesClientTest.findFreePort();
wireMockServer1 = createMockServer("1", port1);
wireMockServer1.start();
int port2 = BaseKieServicesClientTest.findFreePort();
wireMockServer2 = createMockServer("2", port2);
wireMockServer2.start();
int port3 = BaseKieServicesClientTest.findFreePort();
wireMockServer3 = createMockServer("3", port3);
wireMockServer3.start();
mockServerBaseUri1 = "http://localhost:" + port1;
mockServerBaseUri2 = "http://localhost:" + port2;
mockServerBaseUri3 = "http://localhost:" + port3;
String mockServerBaseUri3Duplicated = "http://localhost:" + port3;
config = KieServicesFactory.newRestConfiguration( mockServerBaseUri1+"|"+ mockServerBaseUri2 + "|" + mockServerBaseUri3 + "|" + mockServerBaseUri3Duplicated, null, null );
// set capabilities upfront to avoid additional request to server info to make the tests more determinable
config.setCapabilities(Arrays.asList("KieServer"));
}
@After
public void stopServers() {
wireMockServer1.stop();
wireMockServer2.stop();
wireMockServer3.stop();
}
@Test
public void testCloneConfigurationWithLoadBalancer() {
KieServicesConfiguration cloned = config.clone();
assertNotNull(cloned);
assertNull(cloned.getLoadBalancer());
cloned.setLoadBalancer(LoadBalancer.getDefault("test url"));
KieServicesConfiguration cloneOfCloned = cloned.clone();
assertNotNull(cloned);
assertNotNull(cloned.getLoadBalancer());
assertEquals(cloned.getLoadBalancer(), cloneOfCloned.getLoadBalancer());
}
@Test
public void testDefaultLoadBalancer() {
KieServicesClient client = KieServicesFactory.newKieServicesClient(config);
List<String> available = ((AbstractKieServicesClientImpl)client).getLoadBalancer().getAvailableEndpoints();
assertNotNull(available);
assertEquals(3, available.size());
ServiceResponse<KieServerInfo> response = client.getServerInfo();
assertSuccess(response);
assertEquals("Server version", "1", response.getResult().getVersion());
response = client.getServerInfo();
assertSuccess(response);
assertEquals("Server version", "2", response.getResult().getVersion());
response = client.getServerInfo();
assertSuccess(response);
assertEquals("Server version", "3", response.getResult().getVersion());
}
@Test
public void testRandomLoadBalancer() {
config.setLoadBalancer(LoadBalancer.forStrategy(config.getServerUrl(), BalancerStrategy.Type.RANDOM_STRATEGY));
KieServicesClient client = KieServicesFactory.newKieServicesClient(config);
List<String> available = ((AbstractKieServicesClientImpl)client).getLoadBalancer().getAvailableEndpoints();
assertNotNull(available);
assertEquals(3, available.size());
ServiceResponse<KieServerInfo> response = client.getServerInfo();
assertSuccess(response);
// assertEquals("Server version", "1", response.getResult().getVersion());
response = client.getServerInfo();
assertSuccess(response);
// assertEquals("Server version", "2", response.getResult().getVersion());
response = client.getServerInfo();
assertSuccess(response);
// assertEquals("Server version", "3", response.getResult().getVersion());
}
@Test
public void testDefaultLoadBalancerUnavailableServer() throws Exception {
wireMockServer1.stop();
KieServicesClient client = KieServicesFactory.newKieServicesClient(config);
ServiceResponse<KieServerInfo> response = client.getServerInfo();
assertSuccess(response);
assertEquals("Server version", "2", response.getResult().getVersion());
response = client.getServerInfo();
assertSuccess(response);
assertEquals("Server version", "3", response.getResult().getVersion());
response = client.getServerInfo();
assertSuccess(response);
assertEquals("Server version", "2", response.getResult().getVersion());
response = client.getServerInfo();
assertSuccess(response);
assertEquals("Server version", "3", response.getResult().getVersion());
List<String> available = ((AbstractKieServicesClientImpl)client).getLoadBalancer().getAvailableEndpoints();
assertNotNull(available);
assertEquals(2, available.size());
// now let's put back online server 1
wireMockServer1.start();
Future waitForResult = ((AbstractKieServicesClientImpl)client).getLoadBalancer().checkFailedEndpoints();
waitForResult.get(5, TimeUnit.SECONDS);
available = ((AbstractKieServicesClientImpl)client).getLoadBalancer().getAvailableEndpoints();
assertNotNull(available);
assertEquals(3, available.size());
response = client.getServerInfo();
assertSuccess(response);
assertEquals("Server version", "2", response.getResult().getVersion());
response = client.getServerInfo();
assertSuccess(response);
assertEquals("Server version", "3", response.getResult().getVersion());
// this is the most important as it was offline before (server 1)
response = client.getServerInfo();
assertSuccess(response);
assertEquals("Server version", "1", response.getResult().getVersion());
}
@Test
public void testDefaultLoadBalancerNoServersAvailable() throws Exception {
KieServicesClient client = KieServicesFactory.newKieServicesClient(config);
ServiceResponse<KieServerInfo> response = client.getServerInfo();
assertSuccess(response);
assertEquals("Server version", "1", response.getResult().getVersion());
wireMockServer1.stop();
wireMockServer2.stop();
wireMockServer3.stop();
try {
client.getServerInfo();
fail("No servers available as all of them were stopped");
} catch (KieServerHttpRequestException e) {
assertEquals("No available endpoints found", e.getMessage());
}
// now let's put back online server 1
wireMockServer1.start();
try {
client.getServerInfo();
fail("No servers available even though one was started as load balancer was not refreshed");
} catch (KieServerHttpRequestException e) {
assertEquals("No available endpoints found", e.getMessage());
}
// now let's refresh load balancer info
Future waitForResult = ((AbstractKieServicesClientImpl)client).getLoadBalancer().checkFailedEndpoints();
waitForResult.get(5, TimeUnit.SECONDS);
response = client.getServerInfo();
assertSuccess(response);
assertEquals("Server version", "1", response.getResult().getVersion());
}
@Test
public void testDefaultLoadBalancerNotValidHost() throws Exception {
config = KieServicesFactory.newRestConfiguration( "http://not-existing-host.com:8080/server", null, null );
// set capabilities upfront to avoid additional request to server info to make the tests more determinable
config.setCapabilities(Arrays.asList("KieServer"));
KieServicesClient client = KieServicesFactory.newKieServicesClient(config);
try {
client.getServerInfo();
fail("There is no valid kie server url");
} catch (KieServerHttpRequestException e) {
// expected since no valid endpoint was found
}
List<String> failed = ((AbstractKieServicesClientImpl)client).getLoadBalancer().getFailedEndpoints();
assertEquals(1, failed.size());
((AbstractKieServicesClientImpl)client).getLoadBalancer().activate(mockServerBaseUri1);
ServiceResponse<KieServerInfo> response = client.getServerInfo();
assertSuccess(response);
assertEquals("Server version", "1", response.getResult().getVersion());
}
private void assertSuccess(ServiceResponse<?> response) {
assertEquals("Response type", ServiceResponse.ResponseType.SUCCESS, response.getType());
}
}