http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/ServiceCallClientRouteTest.java ---------------------------------------------------------------------- diff --git a/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/ServiceCallClientRouteTest.java b/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/ServiceCallClientRouteTest.java deleted file mode 100644 index b5e03e3..0000000 --- a/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/ServiceCallClientRouteTest.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * 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.apache.camel.component.kubernetes.processor; - -import org.apache.camel.RoutesBuilder; -import org.apache.camel.builder.RouteBuilder; -import org.apache.camel.model.remote.KubernetesConfigurationDefinition; -import org.apache.camel.test.junit4.CamelTestSupport; -import org.junit.Ignore; -import org.junit.Test; - -@Ignore("Manual test") -public class ServiceCallClientRouteTest extends CamelTestSupport { - - @Test - public void testServiceCall() throws Exception { - getMockEndpoint("mock:result").expectedMessageCount(1); - - template.sendBody("direct:start", "Hello World"); - - assertMockEndpointsSatisfied(); - } - - @Override - protected RoutesBuilder createRouteBuilder() throws Exception { - return new RouteBuilder() { - @Override - public void configure() throws Exception { - KubernetesConfigurationDefinition config = new KubernetesConfigurationDefinition(); - config.setMasterUrl("http://172.28.128.80:8080"); - config.setUsername("admin"); - config.setPassword("admin"); - config.setNamespace("default"); - config.setLookup("client"); - // lets use the built-in round robin (random is default) - config.setLoadBalancerRef("roundrobin"); - - // register configuration - context.setServiceCallConfiguration(config); - - from("direct:start") - .serviceCall("cdi-camel-jetty") - .serviceCall("cdi-camel-jetty") - .to("mock:result"); - } - }; - } -}
http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/ServiceCallEnvironmentRouteTest.java ---------------------------------------------------------------------- diff --git a/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/ServiceCallEnvironmentRouteTest.java b/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/ServiceCallEnvironmentRouteTest.java deleted file mode 100644 index 1e34cb5..0000000 --- a/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/ServiceCallEnvironmentRouteTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * 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.apache.camel.component.kubernetes.processor; - -import org.apache.camel.RoutesBuilder; -import org.apache.camel.builder.RouteBuilder; -import org.apache.camel.model.remote.KubernetesConfigurationDefinition; -import org.apache.camel.test.junit4.CamelTestSupport; -import org.junit.Ignore; -import org.junit.Test; - -@Ignore("Manual test") -public class ServiceCallEnvironmentRouteTest extends CamelTestSupport { - - @Test - public void testServiceCall() throws Exception { - getMockEndpoint("mock:result").expectedMessageCount(1); - - template.sendBody("direct:start", "Hello World"); - - assertMockEndpointsSatisfied(); - } - - @Override - protected RoutesBuilder createRouteBuilder() throws Exception { - return new RouteBuilder() { - @Override - public void configure() throws Exception { - KubernetesConfigurationDefinition config = new KubernetesConfigurationDefinition(); - config.setLookup("environment"); - - // register configuration - context.setServiceCallConfiguration(config); - - from("direct:start") - .serviceCall("cdi-camel-jetty") - .serviceCall("cdi-camel-jetty") - .to("mock:result"); - } - }; - } -} http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/SpringServiceCallClientRouteTest.java ---------------------------------------------------------------------- diff --git a/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/SpringServiceCallClientRouteTest.java b/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/SpringServiceCallClientRouteTest.java deleted file mode 100644 index 3e8fcba3..0000000 --- a/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/SpringServiceCallClientRouteTest.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * 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.apache.camel.component.kubernetes.processor; - -import org.apache.camel.test.spring.CamelSpringTestSupport; -import org.junit.Ignore; -import org.junit.Test; -import org.springframework.context.support.AbstractApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -@Ignore("Manual test") -public class SpringServiceCallClientRouteTest extends CamelSpringTestSupport { - - @Override - protected AbstractApplicationContext createApplicationContext() { - return new ClassPathXmlApplicationContext("org/apache/camel/component/kubernetes/processor/SpringServiceCallClientRouteTest.xml"); - } - - @Test - public void testServiceCall() throws Exception { - getMockEndpoint("mock:result").expectedMessageCount(1); - - template.sendBody("direct:start", "Hello World"); - - assertMockEndpointsSatisfied(); - } -} http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/SpringServiceCallEnvironmentRouteTest.java ---------------------------------------------------------------------- diff --git a/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/SpringServiceCallEnvironmentRouteTest.java b/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/SpringServiceCallEnvironmentRouteTest.java deleted file mode 100644 index bd09c31..0000000 --- a/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/SpringServiceCallEnvironmentRouteTest.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * 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.apache.camel.component.kubernetes.processor; - -import org.apache.camel.test.spring.CamelSpringTestSupport; -import org.junit.Ignore; -import org.junit.Test; -import org.springframework.context.support.AbstractApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -@Ignore("Manual test") -public class SpringServiceCallEnvironmentRouteTest extends CamelSpringTestSupport { - - @Override - protected AbstractApplicationContext createApplicationContext() { - return new ClassPathXmlApplicationContext("org/apache/camel/component/kubernetes/processor/SpringServiceCallEnvironmentRouteTest.xml"); - } - - @Test - public void testServiceCall() throws Exception { - getMockEndpoint("mock:result").expectedMessageCount(1); - - template.sendBody("direct:start", "Hello World"); - - assertMockEndpointsSatisfied(); - } -} http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/cloud/SpringServiceCallClientRouteTest.xml ---------------------------------------------------------------------- diff --git a/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/cloud/SpringServiceCallClientRouteTest.xml b/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/cloud/SpringServiceCallClientRouteTest.xml new file mode 100644 index 0000000..1e98b25 --- /dev/null +++ b/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/cloud/SpringServiceCallClientRouteTest.xml @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ Licensed to the Apache Software Foundation (ASF) under one or more + ~ contributor license agreements. See the NOTICE file distributed with + ~ this work for additional information regarding copyright ownership. + ~ The ASF licenses this file to You under the Apache License, Version 2.0 + ~ (the "License"); you may not use this file except in compliance with + ~ the License. You may obtain a copy of the License at + ~ + ~ 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. + --> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans.xsd + http://camel.apache.org/schema/spring + http://camel.apache.org/schema/spring/camel-spring.xsd"> + + <camelContext xmlns="http://camel.apache.org/schema/spring"> + <!-- + <serviceCallConfiguration id="kubernetes"> + <kubernetesServiceDiscovery masterUrl="http://172.28.128.80:8080" + username="admin" + password="admin" + namespace="default" + lookup="client"/> + </serviceCallConfiguration + --> + + <route> + <from uri="direct:start"/> + <serviceCall name="cdi-camel-jetty"> + <kubernetesServiceDiscovery masterUrl="http://172.28.128.80:8080" + username="admin" + password="admin" + namespace="default" + lookup="client"/> + </serviceCall> + <serviceCall name="cdi-camel-jetty"> + <kubernetesServiceDiscovery masterUrl="http://172.28.128.80:8080" + username="admin" + password="admin" + namespace="default" + lookup="client"/> + </serviceCall> + <to uri="mock:result"/> + </route> + </camelContext> + +</beans> http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/cloud/SpringServiceCallDnsRouteTest.xml ---------------------------------------------------------------------- diff --git a/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/cloud/SpringServiceCallDnsRouteTest.xml b/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/cloud/SpringServiceCallDnsRouteTest.xml new file mode 100644 index 0000000..b8be867 --- /dev/null +++ b/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/cloud/SpringServiceCallDnsRouteTest.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ Licensed to the Apache Software Foundation (ASF) under one or more + ~ contributor license agreements. See the NOTICE file distributed with + ~ this work for additional information regarding copyright ownership. + ~ The ASF licenses this file to You under the Apache License, Version 2.0 + ~ (the "License"); you may not use this file except in compliance with + ~ the License. You may obtain a copy of the License at + ~ + ~ 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. + --> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans.xsd + http://camel.apache.org/schema/spring + http://camel.apache.org/schema/spring/camel-spring.xsd"> + <camelContext xmlns="http://camel.apache.org/schema/spring"> + <!-- + <serviceCallConfiguration id="kubernetes"> + <kubernetesServiceDiscovery lookup="dns"/> + </serviceCallConfiguration> + --> + + <route> + <from uri="direct:start"/> + <serviceCall name="cdi-camel-jetty"> + <kubernetesServiceDiscovery lookup="dns"/> + </serviceCall> + <serviceCall name="cdi-camel-jetty"> + <kubernetesServiceDiscovery lookup="dns"/> + </serviceCall> + <to uri="mock:result"/> + </route> + </camelContext> + +</beans> http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/cloud/SpringServiceCallEnvironmentRouteTest.xml ---------------------------------------------------------------------- diff --git a/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/cloud/SpringServiceCallEnvironmentRouteTest.xml b/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/cloud/SpringServiceCallEnvironmentRouteTest.xml new file mode 100644 index 0000000..8a8686f --- /dev/null +++ b/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/cloud/SpringServiceCallEnvironmentRouteTest.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ Licensed to the Apache Software Foundation (ASF) under one or more + ~ contributor license agreements. See the NOTICE file distributed with + ~ this work for additional information regarding copyright ownership. + ~ The ASF licenses this file to You under the Apache License, Version 2.0 + ~ (the "License"); you may not use this file except in compliance with + ~ the License. You may obtain a copy of the License at + ~ + ~ 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. + --> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans.xsd + http://camel.apache.org/schema/spring + http://camel.apache.org/schema/spring/camel-spring.xsd"> + <camelContext xmlns="http://camel.apache.org/schema/spring"> + <!-- + <serviceCallConfiguration id="kubernetes"> + <kubernetesServiceDiscovery lookup="environment"/> + </serviceCallConfiguration> + --> + + <route> + <from uri="direct:start"/> + <serviceCall name="cdi-camel-jetty"> + <kubernetesServiceDiscovery lookup="environment"/> + </serviceCall> + <serviceCall name="cdi-camel-jetty"> + <kubernetesServiceDiscovery lookup="environment"/> + </serviceCall> + <to uri="mock:result"/> + </route> + </camelContext> + +</beans> http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/processor/SpringServiceCallClientRouteTest.xml ---------------------------------------------------------------------- diff --git a/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/processor/SpringServiceCallClientRouteTest.xml b/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/processor/SpringServiceCallClientRouteTest.xml deleted file mode 100644 index 87162d9..0000000 --- a/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/processor/SpringServiceCallClientRouteTest.xml +++ /dev/null @@ -1,39 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - 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. ---> -<beans xmlns="http://www.springframework.org/schema/beans" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation=" - http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd - http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd - "> - - <camelContext xmlns="http://camel.apache.org/schema/spring"> - - <!-- use client to lookup the service, which requires to setup a number of options --> - <kubernetesConfiguration id="kubernetes" masterUrl="http://172.28.128.80:8080" lookup="client" - username="admin" password="admin" namespace="default" loadBalancerRef="roundrobin"/> - - <route> - <from uri="direct:start"/> - <serviceCall name="cdi-camel-jetty"/> - <serviceCall name="cdi-camel-jetty"/> - <to uri="mock:result"/> - </route> - </camelContext> - -</beans> http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/processor/SpringServiceCallEnvironmentRouteTest.xml ---------------------------------------------------------------------- diff --git a/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/processor/SpringServiceCallEnvironmentRouteTest.xml b/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/processor/SpringServiceCallEnvironmentRouteTest.xml deleted file mode 100644 index 6f2f028..0000000 --- a/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/processor/SpringServiceCallEnvironmentRouteTest.xml +++ /dev/null @@ -1,38 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - 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. ---> -<beans xmlns="http://www.springframework.org/schema/beans" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation=" - http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd - http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd - "> - - <camelContext xmlns="http://camel.apache.org/schema/spring"> - - <!-- use environment variables to lookup the service --> - <kubernetesConfiguration id="kubernetes" lookup="environment"/> - - <route> - <from uri="direct:start"/> - <serviceCall name="cdi-camel-jetty"/> - <serviceCall name="cdi-camel-jetty"/> - <to uri="mock:result"/> - </route> - </camelContext> - -</beans> http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/RibbonConfiguration.java ---------------------------------------------------------------------- diff --git a/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/RibbonConfiguration.java b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/RibbonConfiguration.java index 4931a5b..40bcb31 100644 --- a/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/RibbonConfiguration.java +++ b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/RibbonConfiguration.java @@ -16,16 +16,20 @@ */ package org.apache.camel.component.ribbon; +import java.util.Map; +import java.util.function.Supplier; + import com.netflix.loadbalancer.IPing; import com.netflix.loadbalancer.IRule; public class RibbonConfiguration { - private String namespace; private String username; private String password; private IRule rule; private IPing ping; + private String clientName; + private Map<String, String> clientConfig; public String getNamespace() { return namespace; @@ -55,6 +59,10 @@ public class RibbonConfiguration { return rule; } + public IRule getRuleOrDefault(Supplier<IRule> supplier) { + return rule != null ? rule : supplier.get(); + } + public void setRule(IRule rule) { this.rule = rule; } @@ -63,7 +71,27 @@ public class RibbonConfiguration { return ping; } + public IPing getPingOrDefault(Supplier<IPing> supplier) { + return ping != null ? ping : supplier.get(); + } + public void setPing(IPing ping) { this.ping = ping; } + + public String getClientName() { + return clientName; + } + + public void setClientName(String clientName) { + this.clientName = clientName; + } + + public Map<String, String> getClientConfig() { + return clientConfig; + } + + public void setClientConfig(Map<String, String> clientConfig) { + this.clientConfig = clientConfig; + } } http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/cloud/RibbonLoadBalancer.java ---------------------------------------------------------------------- diff --git a/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/cloud/RibbonLoadBalancer.java b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/cloud/RibbonLoadBalancer.java new file mode 100644 index 0000000..eb23c1b --- /dev/null +++ b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/cloud/RibbonLoadBalancer.java @@ -0,0 +1,231 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * 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.apache.camel.component.ribbon.cloud; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.RejectedExecutionException; + +import com.netflix.client.config.IClientConfig; +import com.netflix.client.config.IClientConfigKey; +import com.netflix.loadbalancer.DummyPing; +import com.netflix.loadbalancer.ILoadBalancer; +import com.netflix.loadbalancer.PollingServerListUpdater; +import com.netflix.loadbalancer.RoundRobinRule; +import com.netflix.loadbalancer.ServerList; +import com.netflix.loadbalancer.ServerListFilter; +import com.netflix.loadbalancer.ZoneAwareLoadBalancer; +import org.apache.camel.CamelContext; +import org.apache.camel.CamelContextAware; +import org.apache.camel.cloud.LoadBalancer; +import org.apache.camel.cloud.LoadBalancerFunction; +import org.apache.camel.cloud.ServiceDefinition; +import org.apache.camel.cloud.ServiceDiscovery; +import org.apache.camel.cloud.ServiceDiscoveryAware; +import org.apache.camel.cloud.ServiceFilter; +import org.apache.camel.cloud.ServiceFilterAware; +import org.apache.camel.component.ribbon.RibbonConfiguration; +import org.apache.camel.support.ServiceSupport; +import org.apache.camel.util.ObjectHelper; +import org.apache.camel.util.ServiceHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class RibbonLoadBalancer + extends ServiceSupport + implements CamelContextAware, ServiceDiscoveryAware, ServiceFilterAware, LoadBalancer { + + private static final Logger LOGGER = LoggerFactory.getLogger(RibbonLoadBalancer.class); + + private final RibbonConfiguration configuration; + private final ConcurrentMap<String, ZoneAwareLoadBalancer<RibbonServiceDefinition>> loadBalancers; + private CamelContext camelContext; + private ServiceDiscovery serviceDiscovery; + private ServiceFilter serviceFilter; + + public RibbonLoadBalancer(RibbonConfiguration configuration) { + this.configuration = configuration; + this.loadBalancers = new ConcurrentHashMap<>(); + } + + @Override + public CamelContext getCamelContext() { + return camelContext; + } + + @Override + public void setCamelContext(CamelContext camelContext) { + this.camelContext = camelContext; + } + + @Override + public ServiceDiscovery getServiceDiscovery() { + return serviceDiscovery; + } + + @Override + public void setServiceDiscovery(ServiceDiscovery serviceDiscovery) { + this.serviceDiscovery = serviceDiscovery; + } + + @Override + public ServiceFilter getServiceFilter() { + return serviceFilter; + } + + @Override + public void setServiceFilter(ServiceFilter serviceFilter) { + this.serviceFilter = serviceFilter; + } + + // ************************ + // lifecycle + // ************************ + + @Override + protected void doStart() throws Exception { + ObjectHelper.notNull(configuration, "configuration"); + ObjectHelper.notNull(camelContext, "camel context"); + ObjectHelper.notNull(serviceDiscovery, "service discovery"); + ObjectHelper.notNull(serviceFilter, "service filter"); + + LOGGER.info("ServiceCall is using ribbon load balancer with service discovery type: {} and service filter type: {}", + serviceDiscovery.getClass(), + serviceFilter.getClass()); + + ServiceHelper.startService(serviceDiscovery); + } + + @Override + protected void doStop() throws Exception { + loadBalancers.values().forEach(ZoneAwareLoadBalancer::stopServerListRefreshing); + loadBalancers.clear(); + + ServiceHelper.stopService(serviceDiscovery); + } + + // ************************ + // Processor + // ************************ + + @Override + public <T> T process(String serviceName, LoadBalancerFunction<T> request) throws Exception { + ILoadBalancer loadBalancer = loadBalancers.computeIfAbsent(serviceName, key -> createLoadBalancer(key, serviceDiscovery)); + RibbonServiceDefinition service = (RibbonServiceDefinition)loadBalancer.chooseServer(serviceName); + + if (service == null) { + throw new RejectedExecutionException("No active services with name " + serviceName); + } + + return request.apply(service); + } + + // ************************ + // Helpers + // ************************ + + private ZoneAwareLoadBalancer<RibbonServiceDefinition> createLoadBalancer(String serviceName, ServiceDiscovery serviceDiscovery) { + // setup client config + IClientConfig config = configuration.getClientName() != null + ? IClientConfig.Builder.newBuilder(configuration.getClientName()).build() + : IClientConfig.Builder.newBuilder().build(); + + if (configuration.getClientConfig() != null) { + for (Map.Entry<String, String> entry : configuration.getClientConfig().entrySet()) { + IClientConfigKey key = IClientConfigKey.Keys.valueOf(entry.getKey()); + String value = entry.getValue(); + + LOGGER.debug("RibbonClientConfig: {}={}", key.key(), value); + config.set(key, value); + } + } + + return new ZoneAwareLoadBalancer<>( + config, + configuration.getRuleOrDefault(RoundRobinRule::new), + configuration.getPingOrDefault(DummyPing::new), + new RibbonServerList(serviceName, serviceDiscovery), + new RibbonServerFilter(serviceFilter), + new PollingServerListUpdater(config)); + } + + static final class RibbonServerList implements ServerList<RibbonServiceDefinition> { + private final String serviceName; + private final ServiceDiscovery serviceDiscovery; + + RibbonServerList(String serviceName, ServiceDiscovery serviceDiscovery) { + this.serviceName = serviceName; + this.serviceDiscovery = serviceDiscovery; + } + + @Override + public List<RibbonServiceDefinition> getInitialListOfServers() { + return asRibbonServerList( + serviceDiscovery.getInitialListOfServices(serviceName) + ); + } + + @Override + public List<RibbonServiceDefinition> getUpdatedListOfServers() { + return asRibbonServerList( + serviceDiscovery.getUpdatedListOfServices(serviceName) + ); + } + + private List<RibbonServiceDefinition> asRibbonServerList(List<ServiceDefinition> services) { + List<RibbonServiceDefinition> ribbonServers = new ArrayList<>(); + + for (ServiceDefinition service : services) { + if (service instanceof RibbonServiceDefinition) { + ribbonServers.add((RibbonServiceDefinition)service); + } else { + RibbonServiceDefinition serviceDef = new RibbonServiceDefinition( + serviceName, + service.getHost(), + service.getPort(), + service.getHealth() + ); + + String zone = serviceDef.getMetadata().get("zone"); + if (zone != null) { + serviceDef.setZone(zone); + } + + ribbonServers.add(serviceDef); + } + } + + return ribbonServers; + } + } + + static final class RibbonServerFilter implements ServerListFilter<RibbonServiceDefinition> { + private final ServiceFilter serviceFilter; + + RibbonServerFilter(ServiceFilter serviceFilter) { + this.serviceFilter = serviceFilter; + } + + public List<RibbonServiceDefinition> getFilteredListOfServers(List<RibbonServiceDefinition> servers) { + return serviceFilter.apply(servers); + } + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/cloud/RibbonLoadBalancerFactory.java ---------------------------------------------------------------------- diff --git a/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/cloud/RibbonLoadBalancerFactory.java b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/cloud/RibbonLoadBalancerFactory.java new file mode 100644 index 0000000..86874f0 --- /dev/null +++ b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/cloud/RibbonLoadBalancerFactory.java @@ -0,0 +1,61 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * 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.apache.camel.component.ribbon.cloud; + +import java.util.Map; + +import org.apache.camel.CamelContext; +import org.apache.camel.cloud.LoadBalancer; +import org.apache.camel.cloud.LoadBalancerFactory; +import org.apache.camel.component.ribbon.RibbonConfiguration; + +public class RibbonLoadBalancerFactory implements LoadBalancerFactory { + private final RibbonConfiguration configuration; + + public RibbonLoadBalancerFactory() { + this.configuration = new RibbonConfiguration(); + } + + // ************************************************************************* + // Properties + // ************************************************************************* + + public String getClientName() { + return configuration.getClientName(); + } + + public void setClientName(String clientName) { + configuration.setClientName(clientName); + } + + public Map<String, String> getProperies() { + return configuration.getClientConfig(); + } + + public void setProperties(Map<String, String> clientConfig) { + configuration.setClientConfig(clientConfig); + } + + // ************************************************************************* + // Factory + // ************************************************************************* + + @Override + public LoadBalancer newInstance(CamelContext camelContext) throws Exception { + return new RibbonLoadBalancer(configuration); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/cloud/RibbonServiceDefinition.java ---------------------------------------------------------------------- diff --git a/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/cloud/RibbonServiceDefinition.java b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/cloud/RibbonServiceDefinition.java new file mode 100644 index 0000000..d9d5772 --- /dev/null +++ b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/cloud/RibbonServiceDefinition.java @@ -0,0 +1,74 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * 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.apache.camel.component.ribbon.cloud; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import com.netflix.loadbalancer.Server; +import org.apache.camel.cloud.ServiceDefinition; +import org.apache.camel.cloud.ServiceHealth; +import org.apache.camel.impl.cloud.DefaultServiceHealth; +import org.apache.camel.util.ObjectHelper; + +public class RibbonServiceDefinition extends Server implements ServiceDefinition { + private String name; + private ServiceHealth health; + + public RibbonServiceDefinition(String name, String host, int port) { + this(name, host, port, DefaultServiceHealth.INSTANCE); + } + + public RibbonServiceDefinition(String name, String host, int port, ServiceHealth healt) { + super(host, port); + this.name = name; + this.health = healt; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getHost() { + return super.getHost(); + } + + @Override + public int getPort() { + return super.getPort(); + } + + @Override + public ServiceHealth getHealth() { + return health; + } + + @Override + public Map<String, String> getMetadata() { + Map<String, String> meta = new HashMap<>(); + ObjectHelper.ifNotEmpty(super.getId(), val -> meta.put("id", val)); + ObjectHelper.ifNotEmpty(super.getZone(), val -> meta.put("zone", val)); + ObjectHelper.ifNotEmpty(super.isAlive(), val -> meta.put("is_alive", Boolean.toString(val))); + ObjectHelper.ifNotEmpty(super.isReadyToServe(), val -> meta.put("ready_to_server", Boolean.toString(val))); + + return Collections.unmodifiableMap(meta); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonProcessorFactory.java ---------------------------------------------------------------------- diff --git a/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonProcessorFactory.java b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonProcessorFactory.java deleted file mode 100644 index 00e9c52..0000000 --- a/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonProcessorFactory.java +++ /dev/null @@ -1,181 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * 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.apache.camel.component.ribbon.processor; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -import com.netflix.loadbalancer.IRule; -import org.apache.camel.ExchangePattern; -import org.apache.camel.Processor; -import org.apache.camel.component.ribbon.RibbonConfiguration; -import org.apache.camel.impl.remote.DefaultServiceCallProcessorFactory; -import org.apache.camel.model.remote.RibbonConfigurationDefinition; -import org.apache.camel.model.remote.ServiceCallConfigurationDefinition; -import org.apache.camel.model.remote.ServiceCallDefinition; -import org.apache.camel.spi.ProcessorFactory; -import org.apache.camel.spi.RouteContext; -import org.apache.camel.spi.ServiceCallServerListStrategy; -import org.apache.camel.util.CamelContextHelper; -import org.apache.camel.util.IntrospectionSupport; - -/** - * {@link ProcessorFactory} that creates the Ribbon implementation of the ServiceCall EIP. - */ -public class RibbonProcessorFactory extends DefaultServiceCallProcessorFactory<RibbonConfiguration, RibbonServer> { - - - @Override - protected Processor createProcessor(RouteContext routeContext, ServiceCallDefinition definition, RibbonConfiguration cfg) throws Exception { - String name = definition.getName(); - String uri = definition.getUri(); - ExchangePattern mep = definition.getPattern(); - - RibbonConfigurationDefinition config = (RibbonConfigurationDefinition) definition.getServiceCallConfiguration(); - RibbonConfigurationDefinition configRef = null; - if (definition.getServiceCallConfigurationRef() != null) { - // lookup in registry first - configRef = CamelContextHelper.lookup(routeContext.getCamelContext(), definition.getServiceCallConfigurationRef(), RibbonConfigurationDefinition.class); - if (configRef == null) { - // and fallback as service configuration - routeContext.getCamelContext().getServiceCallConfiguration(definition.getServiceCallConfigurationRef(), RibbonConfigurationDefinition.class); - } - } - - // if no configuration explicit configured then use default - if (config == null && configRef == null) { - config = routeContext.getCamelContext().getServiceCallConfiguration(null, RibbonConfigurationDefinition.class); - } - if (config == null) { - // if no default then try to find if there configuration in the registry of the given type - Set<RibbonConfigurationDefinition> set = routeContext.getCamelContext().getRegistry().findByType(RibbonConfigurationDefinition.class); - if (set.size() == 1) { - config = set.iterator().next(); - } - } - - if (config == null && configRef == null) { - throw new IllegalStateException("The ServiceCall: " + definition + " must be configured before it can be used."); - } - - // extract the properties from the configuration from the model - Map<String, Object> parameters = new HashMap<>(); - if (configRef != null) { - IntrospectionSupport.getProperties(configRef, parameters, null); - } - if (config != null) { - IntrospectionSupport.getProperties(config, parameters, null); - } - - // and set them on the kubernetes configuration class - IntrospectionSupport.setProperties(cfg, parameters); - - // lookup the load balancer to use (configured on EIP takes precedence vs configured on configuration) - Object lb = configureLoadBalancer(routeContext, definition); - if (lb == null && config != null) { - lb = configureLoadBalancer(routeContext, config); - } - if (lb == null && configRef != null) { - lb = configureLoadBalancer(routeContext, configRef); - } - - // lookup the server list strategy to use (configured on EIP takes precedence vs configured on configuration) - ServiceCallServerListStrategy sl = configureServerListStrategy(routeContext, definition); - if (sl == null && config != null) { - sl = configureServerListStrategy(routeContext, config); - } - if (sl == null && configRef != null) { - sl = configureServerListStrategy(routeContext, configRef); - } - - // must be a ribbon load balancer - if (lb != null && !(lb instanceof IRule)) { - throw new IllegalArgumentException("Load balancer must be of type: " + IRule.class + " but is of type: " + lb.getClass().getName()); - } - - // The component is used to configure what the default scheme to use (eg camel component name). - // The component configured on EIP takes precedence vs configured on configuration. - String component = definition.getComponent(); - if (component == null) { - component = config != null ? config.getComponent() : null; - if (component == null && configRef != null) { - component = configRef.getComponent(); - } - } - - Map<String, String> properties = configureProperties(routeContext, config, configRef); - - RibbonServiceCallProcessor processor = new RibbonServiceCallProcessor(name, uri, component, mep, cfg); - processor.setRule((IRule) lb); - processor.setServerListStrategy(sl); - processor.setRibbonClientConfig(properties); - return processor; - } - - @Override - protected RibbonConfiguration createConfiguration(RouteContext routeContext) throws Exception { - return new RibbonConfiguration(); - } - - private Object configureLoadBalancer(RouteContext routeContext, ServiceCallDefinition sd) { - Object lb = null; - - if (sd != null) { - lb = sd.getLoadBalancer(); - if (lb == null && sd.getLoadBalancerRef() != null) { - String ref = sd.getLoadBalancerRef(); - lb = CamelContextHelper.mandatoryLookup(routeContext.getCamelContext(), ref); - } - } - - return lb; - } - - private Object configureLoadBalancer(RouteContext routeContext, ServiceCallConfigurationDefinition config) { - Object lb = config.getLoadBalancer(); - if (lb == null && config.getLoadBalancerRef() != null) { - String ref = config.getLoadBalancerRef(); - lb = CamelContextHelper.mandatoryLookup(routeContext.getCamelContext(), ref); - } - return lb; - } - - private ServiceCallServerListStrategy configureServerListStrategy(RouteContext routeContext, ServiceCallDefinition sd) { - ServiceCallServerListStrategy lb = null; - - if (sd != null) { - lb = sd.getServerListStrategy(); - if (lb == null && sd.getServerListStrategyRef() != null) { - lb = CamelContextHelper.mandatoryLookup(routeContext.getCamelContext(), sd.getServerListStrategyRef(), ServiceCallServerListStrategy.class); - } - } - - return lb; - } - - private ServiceCallServerListStrategy configureServerListStrategy(RouteContext routeContext, ServiceCallConfigurationDefinition config) { - ServiceCallServerListStrategy lb = config.getServerListStrategy(); - if (lb == null && config.getServerListStrategyRef() != null) { - String ref = config.getServerListStrategyRef(); - lb = CamelContextHelper.mandatoryLookup(routeContext.getCamelContext(), ref, ServiceCallServerListStrategy.class); - } - return lb; - } - -} - http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonServer.java ---------------------------------------------------------------------- diff --git a/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonServer.java b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonServer.java deleted file mode 100644 index d30d656..0000000 --- a/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonServer.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * 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.apache.camel.component.ribbon.processor; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import com.netflix.loadbalancer.Server; -import org.apache.camel.spi.ServiceCallServer; - -import static org.apache.camel.util.ObjectHelper.ifNotEmpty; - -public class RibbonServer extends Server implements ServiceCallServer { - - public RibbonServer(String host, int port) { - super(host, port); - } - - @Override - public String getIp() { - return super.getHost(); - } - - @Override - public int getPort() { - return super.getPort(); - } - - @Override - public Map<String, String> getMetadata() { - Map<String, String> meta = new HashMap<>(); - ifNotEmpty(super.getId(), val -> meta.put("id", val)); - ifNotEmpty(super.getZone(), val -> meta.put("zone", val)); - - if (super.getMetaInfo() != null) { - ifNotEmpty(super.getMetaInfo().getAppName(), val -> meta.put("app_name", val)); - ifNotEmpty(super.getMetaInfo().getServiceIdForDiscovery(), val -> meta.put("discovery_id", val)); - ifNotEmpty(super.getMetaInfo().getInstanceId(), val -> meta.put("instance_id", val)); - ifNotEmpty(super.getMetaInfo().getServerGroup(), val -> meta.put("server_group", val)); - } - - return Collections.unmodifiableMap(meta); - } -} http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallProcessor.java ---------------------------------------------------------------------- diff --git a/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallProcessor.java b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallProcessor.java deleted file mode 100644 index f701ba0..0000000 --- a/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallProcessor.java +++ /dev/null @@ -1,250 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * 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.apache.camel.component.ribbon.processor; - -import java.util.Map; -import java.util.concurrent.RejectedExecutionException; - -import com.netflix.client.config.IClientConfig; -import com.netflix.client.config.IClientConfigKey; -import com.netflix.loadbalancer.DummyPing; -import com.netflix.loadbalancer.IPing; -import com.netflix.loadbalancer.IRule; -import com.netflix.loadbalancer.PollingServerListUpdater; -import com.netflix.loadbalancer.RoundRobinRule; -import com.netflix.loadbalancer.Server; -import com.netflix.loadbalancer.ServerList; -import com.netflix.loadbalancer.ServerListUpdater; -import com.netflix.loadbalancer.ZoneAwareLoadBalancer; -import org.apache.camel.AsyncCallback; -import org.apache.camel.AsyncProcessor; -import org.apache.camel.CamelContext; -import org.apache.camel.CamelContextAware; -import org.apache.camel.Exchange; -import org.apache.camel.ExchangePattern; -import org.apache.camel.Traceable; -import org.apache.camel.component.ribbon.RibbonConfiguration; -import org.apache.camel.impl.remote.DefaultServiceCallExpression; -import org.apache.camel.impl.remote.ServiceCallConstants; -import org.apache.camel.processor.SendDynamicProcessor; -import org.apache.camel.spi.IdAware; -import org.apache.camel.spi.ServiceCallServerListStrategy; -import org.apache.camel.support.ServiceSupport; -import org.apache.camel.util.AsyncProcessorHelper; -import org.apache.camel.util.ServiceHelper; -import org.apache.camel.util.StringHelper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Ribbon based implementation of the the ServiceCall EIP. - */ -public class RibbonServiceCallProcessor extends ServiceSupport implements AsyncProcessor, CamelContextAware, Traceable, IdAware { - - private static final Logger LOG = LoggerFactory.getLogger(RibbonServiceCallProcessor.class); - - private CamelContext camelContext; - private String id; - private final String name; - private final String scheme; - private final String contextPath; - private final String uri; - private final ExchangePattern exchangePattern; - private final RibbonConfiguration configuration; - private ServiceCallServerListStrategy<RibbonServer> serverListStrategy; - private ZoneAwareLoadBalancer<RibbonServer> ribbonLoadBalancer; - private IRule rule; - private IPing ping; - private final DefaultServiceCallExpression serviceCallExpression; - private Map<String, String> ribbonClientConfig; - private SendDynamicProcessor processor; - - public RibbonServiceCallProcessor(String name, String uri, String scheme, ExchangePattern exchangePattern, RibbonConfiguration configuration) { - // setup from the provided name which can contain scheme and context-path information as well - String serviceName; - if (name.contains("/")) { - serviceName = StringHelper.before(name, "/"); - this.contextPath = StringHelper.after(name, "/"); - } else if (name.contains("?")) { - serviceName = StringHelper.before(name, "?"); - this.contextPath = StringHelper.after(name, "?"); - } else { - serviceName = name; - this.contextPath = null; - } - if (serviceName.contains(":")) { - this.scheme = StringHelper.before(serviceName, ":"); - this.name = StringHelper.after(serviceName, ":"); - } else { - this.scheme = scheme; - this.name = serviceName; - } - - this.uri = uri; - this.exchangePattern = exchangePattern; - this.configuration = configuration; - this.rule = configuration.getRule(); - this.ping = configuration.getPing(); - this.serviceCallExpression = new DefaultServiceCallExpression(this.name, this.scheme, this.contextPath, this.uri); - } - - @Override - public void process(Exchange exchange) throws Exception { - AsyncProcessorHelper.process(this, exchange); - } - - @Override - public boolean process(Exchange exchange, AsyncCallback callback) { - Server server = null; - try { - // let the client load balancer chose which server to use - server = ribbonLoadBalancer.chooseServer(); - if (server == null) { - exchange.setException(new RejectedExecutionException("No active services with name " + name)); - } - } catch (Throwable e) { - exchange.setException(e); - } - - if (exchange.getException() != null) { - callback.done(true); - return true; - } - - String ip = server.getHost(); - int port = server.getPort(); - LOG.debug("Service {} active at server: {}:{}", name, ip, port); - - // set selected server as header - exchange.getIn().setHeader(ServiceCallConstants.SERVER_IP, ip); - exchange.getIn().setHeader(ServiceCallConstants.SERVER_PORT, port); - exchange.getIn().setHeader(ServiceCallConstants.SERVICE_NAME, name); - - // use the dynamic send processor to call the service - return processor.process(exchange, callback); - } - - @Override - public CamelContext getCamelContext() { - return camelContext; - } - - @Override - public void setCamelContext(CamelContext camelContext) { - this.camelContext = camelContext; - } - - @Override - public String getId() { - return id; - } - - @Override - public void setId(String id) { - this.id = id; - } - - @Override - public String getTraceLabel() { - return "kubernetes"; - } - - public ServiceCallServerListStrategy getServerListStrategy() { - return serverListStrategy; - } - - public void setServerListStrategy(ServiceCallServerListStrategy serverListStrategy) { - this.serverListStrategy = serverListStrategy; - } - - public IRule getRule() { - return rule; - } - - public void setRule(IRule rule) { - this.rule = rule; - } - - public IPing getPing() { - return ping; - } - - public void setPing(IPing ping) { - this.ping = ping; - } - - public Map<String, String> getRibbonClientConfig() { - return ribbonClientConfig; - } - - public void setRibbonClientConfig(Map<String, String> ribbonClientConfig) { - this.ribbonClientConfig = ribbonClientConfig; - } - - @Override - @SuppressWarnings("unchecked") - protected void doStart() throws Exception { - StringHelper.notEmpty(name, "name", this); - - if (serverListStrategy == null) { - serverListStrategy = new RibbonServiceCallStaticServerListStrategy(); - } - - if (!(serverListStrategy instanceof ServerList)) { - throw new IllegalArgumentException("ServerListStrategy must be instanceof com.netflix.loadbalancer.ServerList but is of type: " + serverListStrategy.getClass().getName()); - } - - if (rule == null) { - // use round robin rule by default - rule = new RoundRobinRule(); - } - if (ping == null) { - // use dummy ping by default - ping = new DummyPing(); - } - - // setup client config - IClientConfig config = IClientConfig.Builder.newBuilder(name).build(); - if (ribbonClientConfig != null) { - for (Map.Entry<String, String> entry : ribbonClientConfig.entrySet()) { - IClientConfigKey key = IClientConfigKey.Keys.valueOf(entry.getKey()); - String value = entry.getValue(); - LOG.debug("RibbonClientConfig: {}={}", key.key(), value); - config.set(key, entry.getValue()); - } - } - - ServerListUpdater updater = new PollingServerListUpdater(config); - ribbonLoadBalancer = new ZoneAwareLoadBalancer<>(config, rule, ping, (ServerList<RibbonServer>) serverListStrategy, null, updater); - - LOG.info("RibbonServiceCall with service name: {} is using load balancer: {} and server list: {}", name, ribbonLoadBalancer, serverListStrategy); - - processor = new SendDynamicProcessor(uri, serviceCallExpression); - processor.setCamelContext(getCamelContext()); - if (exchangePattern != null) { - processor.setPattern(exchangePattern); - } - ServiceHelper.startServices(serverListStrategy, processor); - } - - @Override - protected void doStop() throws Exception { - ServiceHelper.stopServices(processor, serverListStrategy); - } - -} - http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallStaticServerListStrategy.java ---------------------------------------------------------------------- diff --git a/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallStaticServerListStrategy.java b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallStaticServerListStrategy.java deleted file mode 100644 index 6188e6d..0000000 --- a/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallStaticServerListStrategy.java +++ /dev/null @@ -1,108 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * 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.apache.camel.component.ribbon.processor; - -import java.util.ArrayList; -import java.util.List; - -import com.netflix.client.config.IClientConfig; -import com.netflix.loadbalancer.AbstractServerList; -import com.netflix.loadbalancer.ServerList; -import org.apache.camel.spi.ServiceCallServerListStrategy; -import org.apache.camel.util.ObjectHelper; - -/** - * A static list of known servers to be used by the Ribbon load balancer with the Camel Service Call EIP. - * <p/> - * You can implement custom implementations by existing this class and override the {@link #getUpdatedListOfServers()} that is called by Ribbon to refresh the known list - * of servers. For example to periodically query a remote server registry for a list of active servers. - */ -public class RibbonServiceCallStaticServerListStrategy extends AbstractServerList<RibbonServer> implements ServerList<RibbonServer>, ServiceCallServerListStrategy<RibbonServer> { - - private IClientConfig clientConfig; - private final List<RibbonServer> servers = new ArrayList<>(); - - public RibbonServiceCallStaticServerListStrategy() { - } - - public RibbonServiceCallStaticServerListStrategy(List<RibbonServer> servers) { - this.servers.addAll(servers); - } - - /** - * Build a {@link RibbonServiceCallStaticServerListStrategy} with the initial list of servers - * - * @param servers servers separated by comma in the format: host:port,host2:port,host3:port and so on. - */ - public static RibbonServiceCallStaticServerListStrategy build(String servers) { - RibbonServiceCallStaticServerListStrategy answer = new RibbonServiceCallStaticServerListStrategy(); - String[] parts = servers.split(","); - for (String part : parts) { - String host = ObjectHelper.before(part, ":"); - String port = ObjectHelper.after(part, ":"); - int num = Integer.valueOf(port); - answer.addServer(host, num); - } - return answer; - } - - /** - * Add a server to the known list of servers. - */ - public void addServer(RibbonServer server) { - servers.add(server); - } - - /** - * Add a server to the known list of servers. - */ - public void addServer(String host, int port) { - servers.add(new RibbonServer(host, port)); - } - - /** - * Remove an existing server from the list of known servers. - */ - public void removeServer(String host, int port) { - servers.remove(new RibbonServer(host, port)); - } - - @Override - public void initWithNiwsConfig(IClientConfig clientConfig) { - this.clientConfig = clientConfig; - } - - @Override - public List<RibbonServer> getInitialListOfServers() { - return servers; - } - - @Override - public List<RibbonServer> getUpdatedListOfServers() { - return servers; - } - - @Override - public List<RibbonServer> getInitialListOfServers(String name) { - return getInitialListOfServers(); - } - - @Override - public List<RibbonServer> getUpdatedListOfServers(String name) { - return getUpdatedListOfServers(); - } -} http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/main/resources/META-INF/services/org/apache/camel/cloud/ribbon-load-balancer ---------------------------------------------------------------------- diff --git a/components/camel-ribbon/src/main/resources/META-INF/services/org/apache/camel/cloud/ribbon-load-balancer b/components/camel-ribbon/src/main/resources/META-INF/services/org/apache/camel/cloud/ribbon-load-balancer new file mode 100644 index 0000000..161ac23 --- /dev/null +++ b/components/camel-ribbon/src/main/resources/META-INF/services/org/apache/camel/cloud/ribbon-load-balancer @@ -0,0 +1,17 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# 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. +# +class=org.apache.camel.component.ribbon.cloud.RibbonLoadBalancerFactory http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition ---------------------------------------------------------------------- diff --git a/components/camel-ribbon/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition b/components/camel-ribbon/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition deleted file mode 100644 index 5642951..0000000 --- a/components/camel-ribbon/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition +++ /dev/null @@ -1,18 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# 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. -# - -class=org.apache.camel.component.ribbon.processor.RibbonProcessorFactory http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServerListTest.java ---------------------------------------------------------------------- diff --git a/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServerListTest.java b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServerListTest.java new file mode 100644 index 0000000..fcc4f6b --- /dev/null +++ b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServerListTest.java @@ -0,0 +1,56 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * 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.apache.camel.component.ribbon.cloud; + +import java.util.ArrayList; +import java.util.List; + +import com.netflix.loadbalancer.LoadBalancerBuilder; +import com.netflix.loadbalancer.RoundRobinRule; +import com.netflix.loadbalancer.Server; +import com.netflix.loadbalancer.ZoneAwareLoadBalancer; +import org.apache.camel.cloud.ServiceDefinition; +import org.apache.camel.cloud.ServiceDiscovery; +import org.apache.camel.impl.cloud.StaticServiceDiscovery; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class RibbonServerListTest { + @Test + public void testFixedServerList() throws Exception { + List<ServiceDefinition> servers = new ArrayList<>(); + servers.add(new RibbonServiceDefinition("unknown", "localhost", 9090)); + servers.add(new RibbonServiceDefinition("unknown", "localhost", 9091)); + + ServiceDiscovery list = new StaticServiceDiscovery(servers); + + ZoneAwareLoadBalancer<RibbonServiceDefinition> lb = LoadBalancerBuilder.<RibbonServiceDefinition>newBuilder() + .withDynamicServerList(new RibbonLoadBalancer.RibbonServerList("unknown", list)) + .withRule(new RoundRobinRule()) + .buildDynamicServerListLoadBalancer(); + + Server server = lb.chooseServer(); + assertEquals("localhost", server.getHost()); + assertEquals(9091, server.getPort()); + + server = lb.chooseServer(); + assertEquals("localhost", server.getHost()); + assertEquals(9090, server.getPort()); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServiceCallRegistryRouteTest.java ---------------------------------------------------------------------- diff --git a/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServiceCallRegistryRouteTest.java b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServiceCallRegistryRouteTest.java new file mode 100644 index 0000000..7f95639 --- /dev/null +++ b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServiceCallRegistryRouteTest.java @@ -0,0 +1,61 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * 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.apache.camel.component.ribbon.cloud; + +import org.apache.camel.RoutesBuilder; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.ribbon.RibbonConfiguration; +import org.apache.camel.impl.cloud.StaticServiceDiscovery; +import org.apache.camel.model.cloud.ServiceCallConfigurationDefinition; + +public class RibbonServiceCallRegistryRouteTest extends RibbonServiceCallRouteTest { + @Override + protected RoutesBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + // setup a static ribbon server list with these 2 servers to start with + StaticServiceDiscovery servers = new StaticServiceDiscovery(); + servers.addServer("localhost", 9090); + servers.addServer("localhost", 9091); + + RibbonConfiguration configuration = new RibbonConfiguration(); + RibbonLoadBalancer loadBalancer = new RibbonLoadBalancer(configuration); + + // configure camel service call + ServiceCallConfigurationDefinition config = new ServiceCallConfigurationDefinition(); + config.setLoadBalancer(loadBalancer); + config.setServiceDiscovery(servers); + + // register configuration + context.setServiceCallConfiguration(config); + + from("direct:start") + .serviceCall("myService") + .to("mock:result"); + from("jetty:http://localhost:9090") + .to("mock:9090") + .transform().constant("9090"); + from("jetty:http://localhost:9091") + .to("mock:9091") + .transform().constant("9091"); + } + }; + } +} + http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServiceCallRouteTest.java ---------------------------------------------------------------------- diff --git a/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServiceCallRouteTest.java b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServiceCallRouteTest.java new file mode 100644 index 0000000..6bda099 --- /dev/null +++ b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServiceCallRouteTest.java @@ -0,0 +1,72 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * 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.apache.camel.component.ribbon.cloud; + +import org.apache.camel.RoutesBuilder; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.ribbon.RibbonConfiguration; +import org.apache.camel.impl.cloud.StaticServiceDiscovery; +import org.apache.camel.test.junit4.CamelTestSupport; +import org.junit.Test; + +public class RibbonServiceCallRouteTest extends CamelTestSupport { + @Test + public void testServiceCall() throws Exception { + getMockEndpoint("mock:9090").expectedMessageCount(1); + getMockEndpoint("mock:9091").expectedMessageCount(1); + getMockEndpoint("mock:result").expectedMessageCount(2); + + String out = template.requestBody("direct:start", null, String.class); + String out2 = template.requestBody("direct:start", null, String.class); + assertEquals("9091", out); + assertEquals("9090", out2); + + assertMockEndpointsSatisfied(); + } + + @Override + protected RoutesBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + // setup a static ribbon server list with these 2 servers to start with + StaticServiceDiscovery servers = new StaticServiceDiscovery(); + servers.addServer("localhost", 9090); + servers.addServer("localhost", 9091); + + RibbonConfiguration configuration = new RibbonConfiguration(); + RibbonLoadBalancer loadBalancer = new RibbonLoadBalancer(configuration); + + from("direct:start") + .serviceCall() + .name("myService") + .loadBalancer(loadBalancer) + .serviceDiscovery(servers) + .end() + .to("mock:result"); + from("jetty:http://localhost:9090") + .to("mock:9090") + .transform().constant("9090"); + from("jetty:http://localhost:9091") + .to("mock:9091") + .transform().constant("9091"); + } + }; + } +} + http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServiceCallUpdateRouteTest.java ---------------------------------------------------------------------- diff --git a/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServiceCallUpdateRouteTest.java b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServiceCallUpdateRouteTest.java new file mode 100644 index 0000000..c00f1c7 --- /dev/null +++ b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/RibbonServiceCallUpdateRouteTest.java @@ -0,0 +1,99 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * 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.apache.camel.component.ribbon.cloud; + +import java.util.Collections; + +import org.apache.camel.RoutesBuilder; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.ribbon.RibbonConfiguration; +import org.apache.camel.impl.cloud.StaticServiceDiscovery; +import org.apache.camel.test.junit4.CamelTestSupport; +import org.junit.Test; + +public class RibbonServiceCallUpdateRouteTest extends CamelTestSupport { + private final StaticServiceDiscovery servers = new StaticServiceDiscovery(); + + @Override + public void setUp() throws Exception { + // setup a static ribbon server list with these 2 servers to start with + servers.addServer("localhost", 9090); + servers.addServer("localhost", 9091); + + super.setUp(); + } + + @Test + public void testServiceCall() throws Exception { + getMockEndpoint("mock:9090").expectedMessageCount(1); + getMockEndpoint("mock:9091").expectedMessageCount(1); + getMockEndpoint("mock:result").expectedMessageCount(2); + + String out = template.requestBody("direct:start", null, String.class); + String out2 = template.requestBody("direct:start", null, String.class); + assertEquals("9091", out); + assertEquals("9090", out2); + + assertMockEndpointsSatisfied(); + + // stop the first server and remove it from the known list of servers + context.stopRoute("9090"); + servers.removeServer("localhost", 9090); + + // call the other active server + String out3 = template.requestBody("direct:start", null, String.class); + assertEquals("9091", out3); + + // sleep a bit to make the server updated run and detect that a server is no longer in the list + log.debug("Sleeping to all the server list updated to run"); + Thread.sleep(1000); + log.debug("Calling the service now"); + + // call again and it should call 9091 as its the only active server + String out4 = template.requestBody("direct:start", null, String.class); + assertEquals("9091", out4); + } + + @Override + protected RoutesBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + RibbonConfiguration configuration = new RibbonConfiguration(); + // lets update quick so we do not have to sleep so much in the tests + configuration.setClientConfig(Collections.singletonMap("ServerListRefreshInterval", "250")); + RibbonLoadBalancer loadBalancer = new RibbonLoadBalancer(configuration); + + from("direct:start") + .serviceCall() + .name("myService") + .loadBalancer(loadBalancer) + .serviceDiscovery(servers) + .end() + .to("mock:result"); + from("jetty:http://localhost:9090").routeId("9090") + .to("mock:9090") + .transform().constant("9090"); + from("jetty:http://localhost:9091").routeId("9091") + .to("mock:9091") + .transform().constant("9091"); + } + }; + } +} + http://git-wip-us.apache.org/repos/asf/camel/blob/a811f400/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/SpringBeanServiceCallRouteTest.java ---------------------------------------------------------------------- diff --git a/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/SpringBeanServiceCallRouteTest.java b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/SpringBeanServiceCallRouteTest.java new file mode 100644 index 0000000..9c99aec --- /dev/null +++ b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/cloud/SpringBeanServiceCallRouteTest.java @@ -0,0 +1,31 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * 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.apache.camel.component.ribbon.cloud; + +import org.springframework.context.support.AbstractApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.test.annotation.DirtiesContext; + +@DirtiesContext +public class SpringBeanServiceCallRouteTest extends SpringRibbonServiceCallRouteTest { + @Override + protected AbstractApplicationContext createApplicationContext() { + return new ClassPathXmlApplicationContext("org/apache/camel/component/ribbon/cloud/SpringBeanRibbonServiceCallRouteTest.xml"); + } +} +