You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2016/05/24 12:45:36 UTC

[1/4] camel git commit: CAMEL-9683: A new toService EIP that uses a client discovery to lookup alive services and pick a service ip/port to use when calling the service from Camel route. Allows to plugin different providers. Added camel-ribbon as impleme

Repository: camel
Updated Branches:
  refs/heads/master f28b44edd -> 8447297a2


http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/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
new file mode 100644
index 0000000..8b03a74
--- /dev/null
+++ b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonProcessorFactory.java
@@ -0,0 +1,207 @@
+/**
+ * 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.model.ProcessorDefinition;
+import org.apache.camel.model.PropertyDefinition;
+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 implements ProcessorFactory {
+
+    @Override
+    public Processor createChildProcessor(RouteContext routeContext, ProcessorDefinition<?> definition, boolean mandatory) throws Exception {
+        // not in use
+        return null;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public Processor createProcessor(RouteContext routeContext, ProcessorDefinition<?> definition) throws Exception {
+        if (definition instanceof ServiceCallDefinition) {
+            ServiceCallDefinition sc = (ServiceCallDefinition) definition;
+
+            String name = sc.getName();
+            String uri = sc.getUri();
+            ExchangePattern mep = sc.getPattern();
+
+            RibbonConfigurationDefinition config = (RibbonConfigurationDefinition) sc.getServiceCallConfiguration();
+            RibbonConfigurationDefinition configRef = null;
+            if (sc.getServiceCallConfigurationRef() != null) {
+                // lookup in registry first
+                configRef = CamelContextHelper.lookup(routeContext.getCamelContext(), sc.getServiceCallConfigurationRef(), RibbonConfigurationDefinition.class);
+                if (configRef == null) {
+                    // and fallback as service configuration
+                    routeContext.getCamelContext().getServiceCallConfiguration(sc.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
+            RibbonConfiguration rc = new RibbonConfiguration();
+            IntrospectionSupport.setProperties(rc, parameters);
+
+            // lookup the load balancer to use (configured on EIP takes precedence vs configured on configuration)
+            Object lb = configureLoadBalancer(routeContext, sc);
+            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, sc);
+            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)
+            String 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, rc);
+            processor.setRule((IRule) lb);
+            processor.setServerListStrategy(sl);
+            processor.setRibbonClientConfig(properties);
+            return processor;
+        } else {
+            return null;
+        }
+    }
+
+    private Map<String, String> configureProperties(RouteContext routeContext, ServiceCallConfigurationDefinition config, ServiceCallConfigurationDefinition configRef) throws Exception {
+        Map<String, String> answer = new HashMap<>();
+        if (config != null && config.getProperties() != null) {
+            for (PropertyDefinition prop : config.getProperties()) {
+                // support property placeholders
+                String key = CamelContextHelper.parseText(routeContext.getCamelContext(), prop.getKey());
+                String value = CamelContextHelper.parseText(routeContext.getCamelContext(), prop.getValue());
+                answer.put(key, value);
+            }
+        }
+        if (configRef != null && configRef.getProperties() != null) {
+            for (PropertyDefinition prop : configRef.getProperties()) {
+                // support property placeholders
+                String key = CamelContextHelper.parseText(routeContext.getCamelContext(), prop.getKey());
+                String value = CamelContextHelper.parseText(routeContext.getCamelContext(), prop.getValue());
+                answer.put(key, value);
+            }
+        }
+        return answer;
+    }
+
+    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/4b81b4ae/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
new file mode 100644
index 0000000..d4e5bbf
--- /dev/null
+++ b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonServer.java
@@ -0,0 +1,33 @@
+/**
+ * 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 com.netflix.loadbalancer.Server;
+import org.apache.camel.spi.ServiceCallServer;
+
+public class RibbonServer extends Server implements ServiceCallServer {
+
+    public RibbonServer(String host, int port) {
+        super(host, port);
+    }
+
+    @Override
+    public String getIp() {
+        return getHost();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallExpression.java
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallExpression.java b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallExpression.java
new file mode 100644
index 0000000..b04330a
--- /dev/null
+++ b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallExpression.java
@@ -0,0 +1,40 @@
+/**
+ * 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 org.apache.camel.Exchange;
+import org.apache.camel.component.ribbon.RibbonConstants;
+import org.apache.camel.support.ServiceCallExpressionSupport;
+import org.apache.camel.util.ExchangeHelper;
+
+public class RibbonServiceCallExpression extends ServiceCallExpressionSupport {
+
+    public RibbonServiceCallExpression(String name, String scheme, String contextPath, String uri) {
+        super(name, scheme, contextPath, uri);
+    }
+
+    @Override
+    public String getIp(Exchange exchange) throws Exception {
+        return ExchangeHelper.getMandatoryHeader(exchange, RibbonConstants.RIBBON_SERVER_IP, String.class);
+    }
+
+    @Override
+    public int getPort(Exchange exchange) throws Exception {
+        return ExchangeHelper.getMandatoryHeader(exchange, RibbonConstants.RIBBON_SERVER_PORT, int.class);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/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
new file mode 100644
index 0000000..8748420
--- /dev/null
+++ b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallProcessor.java
@@ -0,0 +1,248 @@
+/**
+ * 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.component.ribbon.RibbonConstants;
+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.ObjectHelper;
+import org.apache.camel.util.ServiceHelper;
+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 RibbonServiceCallExpression 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 = ObjectHelper.before(name, "/");
+            this.contextPath = ObjectHelper.after(name, "/");
+        } else if (name.contains("?")) {
+            serviceName = ObjectHelper.before(name, "?");
+            this.contextPath = ObjectHelper.after(name, "?");
+        } else {
+            serviceName = name;
+            this.contextPath = null;
+        }
+        if (serviceName.contains(":")) {
+            this.scheme = ObjectHelper.before(serviceName, ":");
+            this.name = ObjectHelper.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 RibbonServiceCallExpression(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(RibbonConstants.RIBBON_SERVER_IP, ip);
+        exchange.getIn().setHeader(RibbonConstants.RIBBON_SERVER_PORT, port);
+
+        // 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 {
+        ObjectHelper.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/4b81b4ae/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
new file mode 100644
index 0000000..0e3ced4
--- /dev/null
+++ b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallStaticServerListStrategy.java
@@ -0,0 +1,98 @@
+/**
+ * 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;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/components/camel-ribbon/src/main/resources/META-INF/LICENSE.txt
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/main/resources/META-INF/LICENSE.txt b/components/camel-ribbon/src/main/resources/META-INF/LICENSE.txt
new file mode 100644
index 0000000..6b0b127
--- /dev/null
+++ b/components/camel-ribbon/src/main/resources/META-INF/LICENSE.txt
@@ -0,0 +1,203 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
+

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/components/camel-ribbon/src/main/resources/META-INF/NOTICE.txt
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/main/resources/META-INF/NOTICE.txt b/components/camel-ribbon/src/main/resources/META-INF/NOTICE.txt
new file mode 100644
index 0000000..2e215bf
--- /dev/null
+++ b/components/camel-ribbon/src/main/resources/META-INF/NOTICE.txt
@@ -0,0 +1,11 @@
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for the Apache Camel distribution.                    ==
+   =========================================================================
+
+   This product includes software developed by
+   The Apache Software Foundation (http://www.apache.org/).
+
+   Please read the different LICENSE files present in the licenses directory of
+   this distribution.

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/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
new file mode 100644
index 0000000..5642951
--- /dev/null
+++ b/components/camel-ribbon/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition
@@ -0,0 +1,18 @@
+#
+# 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/4b81b4ae/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServerListTest.java
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServerListTest.java b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServerListTest.java
new file mode 100644
index 0000000..4671709
--- /dev/null
+++ b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServerListTest.java
@@ -0,0 +1,53 @@
+/**
+ * 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 junit.framework.TestCase;
+
+import com.netflix.loadbalancer.LoadBalancerBuilder;
+import com.netflix.loadbalancer.RoundRobinRule;
+import com.netflix.loadbalancer.Server;
+import com.netflix.loadbalancer.ServerList;
+import com.netflix.loadbalancer.ZoneAwareLoadBalancer;
+import org.junit.Test;
+
+public class RibbonServerListTest extends TestCase {
+
+    @Test
+    public void testFixedServerList() throws Exception {
+        List<RibbonServer> servers = new ArrayList<>();
+        servers.add(new RibbonServer("localhost", 9090));
+        servers.add(new RibbonServer("localhost", 9091));
+
+        ServerList<RibbonServer> list = new RibbonServiceCallStaticServerListStrategy(servers);
+
+        ZoneAwareLoadBalancer<RibbonServer> lb = LoadBalancerBuilder.<RibbonServer>newBuilder()
+            .withDynamicServerList(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/4b81b4ae/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallRegistryRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallRegistryRouteTest.java b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallRegistryRouteTest.java
new file mode 100644
index 0000000..b1c7d4d
--- /dev/null
+++ b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallRegistryRouteTest.java
@@ -0,0 +1,57 @@
+/**
+ * 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 org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.remote.RibbonConfigurationDefinition;
+
+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
+                RibbonServiceCallStaticServerListStrategy servers = new RibbonServiceCallStaticServerListStrategy();
+                servers.addServer("localhost", 9090);
+                servers.addServer("localhost", 9091);
+
+                // configure camel service call
+                RibbonConfigurationDefinition config = new RibbonConfigurationDefinition();
+                config.setServerListStrategy(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/4b81b4ae/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallRouteTest.java b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallRouteTest.java
new file mode 100644
index 0000000..a3abc29
--- /dev/null
+++ b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallRouteTest.java
@@ -0,0 +1,65 @@
+/**
+ * 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 org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+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
+                RibbonServiceCallStaticServerListStrategy servers = new RibbonServiceCallStaticServerListStrategy();
+                servers.addServer("localhost", 9090);
+                servers.addServer("localhost", 9091);
+
+                from("direct:start")
+                        .serviceCall().name("myService").ribbonConfiguration().serverListStrategy(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/4b81b4ae/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallUpdateRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallUpdateRouteTest.java b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallUpdateRouteTest.java
new file mode 100644
index 0000000..a37f5bc
--- /dev/null
+++ b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/RibbonServiceCallUpdateRouteTest.java
@@ -0,0 +1,90 @@
+/**
+ * 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 org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+
+public class RibbonServiceCallUpdateRouteTest extends CamelTestSupport {
+
+    private final RibbonServiceCallStaticServerListStrategy servers = new RibbonServiceCallStaticServerListStrategy();
+
+    @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 {
+                from("direct:start")
+                        .serviceCall().name("myService")
+                            // lets update quick so we do not have to sleep so much in the tests
+                            .ribbonConfiguration().serverListStrategy(servers).clientProperty("ServerListRefreshInterval", "250").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/4b81b4ae/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/SpringRibbonServiceCallRouteTest.java
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/SpringRibbonServiceCallRouteTest.java b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/SpringRibbonServiceCallRouteTest.java
new file mode 100644
index 0000000..6b35b75
--- /dev/null
+++ b/components/camel-ribbon/src/test/java/org/apache/camel/component/ribbon/processor/SpringRibbonServiceCallRouteTest.java
@@ -0,0 +1,46 @@
+/**
+ * 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 org.apache.camel.test.spring.CamelSpringTestSupport;
+import org.junit.Test;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+public class SpringRibbonServiceCallRouteTest extends CamelSpringTestSupport {
+
+    @Override
+    protected AbstractApplicationContext createApplicationContext() {
+        return new ClassPathXmlApplicationContext("org/apache/camel/component/ribbon/processor/SpringRibbonServiceCallRouteTest.xml");
+    }
+
+    @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();
+    }
+
+}
+

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/components/camel-ribbon/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/test/resources/log4j.properties b/components/camel-ribbon/src/test/resources/log4j.properties
new file mode 100644
index 0000000..f138e1d
--- /dev/null
+++ b/components/camel-ribbon/src/test/resources/log4j.properties
@@ -0,0 +1,37 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+#
+# The logging properties used
+#
+log4j.rootLogger=INFO, file
+
+log4j.logger.org.apache.camel.component.kubernetes=DEBUG
+log4j.logger.org.apache.camel.component.ribbon=DEBUG
+
+# CONSOLE appender not used by default
+log4j.appender.out=org.apache.log4j.ConsoleAppender
+log4j.appender.out.layout=org.apache.log4j.PatternLayout
+log4j.appender.out.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n
+
+# File appender
+log4j.appender.file=org.apache.log4j.FileAppender
+log4j.appender.file.layout=org.apache.log4j.PatternLayout
+log4j.appender.file.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n
+log4j.appender.file.file=target/camel-ribbon-test.log
+log4j.appender.file.append=true
+

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/components/camel-ribbon/src/test/resources/org/apache/camel/component/ribbon/processor/SpringRibbonServiceCallRouteTest.xml
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/test/resources/org/apache/camel/component/ribbon/processor/SpringRibbonServiceCallRouteTest.xml b/components/camel-ribbon/src/test/resources/org/apache/camel/component/ribbon/processor/SpringRibbonServiceCallRouteTest.xml
new file mode 100644
index 0000000..6b2df8d
--- /dev/null
+++ b/components/camel-ribbon/src/test/resources/org/apache/camel/component/ribbon/processor/SpringRibbonServiceCallRouteTest.xml
@@ -0,0 +1,60 @@
+<?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
+    ">
+
+  <!-- setup a static ribbon server list with these 2 servers to start with -->
+  <!-- call the build method with the argument below -->
+  <bean id="servers" class="org.apache.camel.component.ribbon.processor.RibbonServiceCallStaticServerListStrategy"
+        factory-method="build">
+    <constructor-arg index="0" value="localhost:9090,localhost:9091"/>
+  </bean>
+
+  <camelContext xmlns="http://camel.apache.org/schema/spring">
+
+    <!-- service call configuration to use ribbon -->
+    <ribbonConfiguration id="ribbon" serverListStrategyRef="servers"/>
+
+    <route>
+      <from uri="direct:start"/>
+      <serviceCall name="myService"/>
+      <to uri="mock:result"/>
+    </route>
+
+    <route>
+      <from uri="jetty:http://localhost:9090"/>
+      <to uri="mock:9090"/>
+      <transform>
+        <constant>9090</constant>
+      </transform>
+    </route>
+
+    <route>
+      <from uri="jetty:http://localhost:9091"/>
+      <to uri="mock:9091"/>
+      <transform>
+        <constant>9091</constant>
+      </transform>
+    </route>
+  </camelContext>
+
+</beans>

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/components/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java
----------------------------------------------------------------------
diff --git a/components/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java b/components/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java
index 5f94f6b..89d2502 100644
--- a/components/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java
+++ b/components/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java
@@ -57,6 +57,8 @@ import org.apache.camel.model.RouteContextRefDefinition;
 import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.model.ThreadPoolProfileDefinition;
 import org.apache.camel.model.dataformat.DataFormatsDefinition;
+import org.apache.camel.model.remote.KubernetesConfigurationDefinition;
+import org.apache.camel.model.remote.RibbonConfigurationDefinition;
 import org.apache.camel.model.rest.RestConfigurationDefinition;
 import org.apache.camel.model.rest.RestDefinition;
 import org.apache.camel.spi.PackageScanFilter;
@@ -152,6 +154,8 @@ public class CamelContextFactoryBean extends AbstractCamelContextFactoryBean<Spr
     private CamelJMXAgentDefinition camelJMXAgent;
     @XmlElements({
             @XmlElement(name = "hystrixConfiguration", type = HystrixConfigurationDefinition.class, required = false),
+            @XmlElement(name = "kubernetesConfiguration", type = KubernetesConfigurationDefinition.class, required = false),
+            @XmlElement(name = "ribbonConfiguration", type = RibbonConfigurationDefinition.class, required = false),
             @XmlElement(name = "template", type = CamelProducerTemplateFactoryBean.class, required = false),
             @XmlElement(name = "consumerTemplate", type = CamelConsumerTemplateFactoryBean.class, required = false),
             @XmlElement(name = "proxy", type = CamelProxyFactoryDefinition.class, required = false),

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/components/camel-spring/src/main/java/org/apache/camel/spring/handler/CamelNamespaceHandler.java
----------------------------------------------------------------------
diff --git a/components/camel-spring/src/main/java/org/apache/camel/spring/handler/CamelNamespaceHandler.java b/components/camel-spring/src/main/java/org/apache/camel/spring/handler/CamelNamespaceHandler.java
index fd062a0..855d6d3 100644
--- a/components/camel-spring/src/main/java/org/apache/camel/spring/handler/CamelNamespaceHandler.java
+++ b/components/camel-spring/src/main/java/org/apache/camel/spring/handler/CamelNamespaceHandler.java
@@ -40,6 +40,8 @@ import org.apache.camel.impl.DefaultCamelContextNameStrategy;
 import org.apache.camel.model.FromDefinition;
 import org.apache.camel.model.HystrixConfigurationDefinition;
 import org.apache.camel.model.SendDefinition;
+import org.apache.camel.model.remote.KubernetesConfigurationDefinition;
+import org.apache.camel.model.remote.RibbonConfigurationDefinition;
 import org.apache.camel.spi.CamelContextNameStrategy;
 import org.apache.camel.spi.NamespaceAware;
 import org.apache.camel.spring.CamelBeanPostProcessor;
@@ -139,11 +141,13 @@ public class CamelNamespaceHandler extends NamespaceHandlerSupport {
         addBeanDefinitionParser("threadPool", CamelThreadPoolFactoryBean.class, true, true);
         addBeanDefinitionParser("redeliveryPolicyProfile", CamelRedeliveryPolicyFactoryBean.class, true, true);
 
-        // jmx agent, stream caching, hystrix configuration and property placeholder cannot be used outside of the camel context
+        // jmx agent, stream caching, hystrix, service call configurations and property placeholder cannot be used outside of the camel context
         addBeanDefinitionParser("jmxAgent", CamelJMXAgentDefinition.class, false, false);
         addBeanDefinitionParser("streamCaching", CamelStreamCachingStrategyDefinition.class, false, false);
         addBeanDefinitionParser("propertyPlaceholder", CamelPropertyPlaceholderDefinition.class, false, false);
         addBeanDefinitionParser("hystrixConfiguration", HystrixConfigurationDefinition.class, false, false);
+        addBeanDefinitionParser("kubernetesConfiguration", KubernetesConfigurationDefinition.class, false, false);
+        addBeanDefinitionParser("ribbonConfiguration", RibbonConfigurationDefinition.class, false, false);
 
         // errorhandler could be the sub element of camelContext or defined outside camelContext
         BeanDefinitionParser errorHandlerParser = new ErrorHandlerDefinitionParser();

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/components/pom.xml
----------------------------------------------------------------------
diff --git a/components/pom.xml b/components/pom.xml
index e84bf7f..724f757 100644
--- a/components/pom.xml
+++ b/components/pom.xml
@@ -203,6 +203,7 @@
     <module>camel-quickfix</module>
     <module>camel-rabbitmq</module>
     <module>camel-restlet</module>
+    <module>camel-ribbon</module>
     <module>camel-rmi</module>
     <module>camel-routebox</module>
     <module>camel-rss</module>

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/parent/pom.xml
----------------------------------------------------------------------
diff --git a/parent/pom.xml b/parent/pom.xml
index 8de5e07..6d911fe 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -476,6 +476,7 @@
     <restlet-joda-time-version>2.3</restlet-joda-time-version>
     <rhino-bundle-version>1.7R2_3</rhino-bundle-version>
     <rhino-version>1.7R2</rhino-version>
+    <ribbon-version>2.2.0</ribbon-version>
     <rome-bundle-version>1.0_3</rome-bundle-version>
     <rome-version>1.0</rome-version>
     <rxjava-version>1.1.5</rxjava-version>
@@ -1480,6 +1481,11 @@
       </dependency>
       <dependency>
         <groupId>org.apache.camel</groupId>
+        <artifactId>camel-ribbon</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.camel</groupId>
         <artifactId>camel-rmi</artifactId>
         <version>${project.version}</version>
       </dependency>


[3/4] camel git commit: CAMEL-9683: A new toService EIP that uses a client discovery to lookup alive services and pick a service ip/port to use when calling the service from Camel route. Allows to plugin different providers. Added camel-ribbon as impleme

Posted by da...@apache.org.
CAMEL-9683: A new toService EIP that uses a client discovery to lookup alive services and pick a service ip/port to use when calling the service from Camel route. Allows to plugin different providers. Added camel-ribbon as implementation as well.


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/4b81b4ae
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/4b81b4ae
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/4b81b4ae

Branch: refs/heads/master
Commit: 4b81b4ae366928c3a2a07a0e103b95a19f3438d0
Parents: f28b44e
Author: Claus Ibsen <da...@apache.org>
Authored: Tue May 24 13:18:39 2016 +0200
Committer: Claus Ibsen <da...@apache.org>
Committed: Tue May 24 14:38:54 2016 +0200

----------------------------------------------------------------------
 apache-camel/pom.xml                            |   4 +
 .../src/main/descriptors/common-bin.xml         |   1 +
 .../java/org/apache/camel/CamelContext.java     |  26 ++
 .../apache/camel/impl/DefaultCamelContext.java  |  34 ++
 .../java/org/apache/camel/model/Constants.java  |   1 +
 .../model/HystrixConfigurationDefinition.java   |   3 +
 .../apache/camel/model/HystrixDefinition.java   |   3 +
 .../apache/camel/model/ProcessorDefinition.java |  43 +++
 .../KubernetesConfigurationDefinition.java      | 364 +++++++++++++++++++
 .../remote/RibbonConfigurationDefinition.java   |  48 +++
 .../ServiceCallConfigurationDefinition.java     | 209 +++++++++++
 .../model/remote/ServiceCallDefinition.java     | 253 +++++++++++++
 .../apache/camel/model/remote/package-info.java |  23 ++
 .../camel/spi/ServiceCallLoadBalancer.java      |  36 ++
 .../org/apache/camel/spi/ServiceCallServer.java |  36 ++
 .../spi/ServiceCallServerListStrategy.java      |  45 +++
 .../support/ServiceCallExpressionSupport.java   | 101 +++++
 .../org/apache/camel/model/remote/jaxb.index    |  20 +
 .../blueprint/CamelContextFactoryBean.java      |   4 +
 components/camel-kubernetes/pom.xml             |  33 +-
 .../src/main/docs/kubernetes.adoc               |   4 +-
 .../kubernetes/KubernetesConfiguration.java     |  31 +-
 .../kubernetes/KubernetesConstants.java         |   5 +
 .../kubernetes/KubernetesEndpoint.java          |  21 +-
 .../consumer/KubernetesNamespacesConsumer.java  |   4 +-
 .../consumer/KubernetesPodsConsumer.java        |   4 +-
 ...ubernetesReplicationControllersConsumer.java |   4 +-
 .../consumer/KubernetesSecretsConsumer.java     |   4 +-
 .../consumer/KubernetesServicesConsumer.java    |   4 +-
 .../KubernetesClientServiceCallProcessor.java   | 251 +++++++++++++
 .../KubernetesDnsServiceCallExpression.java     |  81 +++++
 .../KubernetesDnsServiceCallProcessor.java      | 155 ++++++++
 ...bernetesEnvironmentServiceCallProcessor.java | 165 +++++++++
 .../processor/KubernetesProcessorFactory.java   | 208 +++++++++++
 .../kubernetes/processor/KubernetesServer.java  |  41 +++
 .../KubernetesServiceCallExpression.java        |  40 ++
 ...KubernetesServiceCallServerListStrategy.java | 106 ++++++
 .../processor/RandomLoadBalancer.java           |  40 ++
 .../processor/RoundRobinBalancer.java           |  44 +++
 .../apache/camel/model/ServiceCallDefinition    |  18 +
 .../processor/ServiceCallClientRouteTest.java   |  62 ++++
 .../ServiceCallEnvironmentRouteTest.java        |  57 +++
 .../SpringServiceCallClientRouteTest.java       |  41 +++
 .../SpringServiceCallEnvironmentRouteTest.java  |  41 +++
 .../src/test/resources/log4j.properties         |   2 +-
 .../SpringServiceCallClientRouteTest.xml        |  39 ++
 .../SpringServiceCallEnvironmentRouteTest.xml   |  38 ++
 components/camel-ribbon/pom.xml                 |  89 +++++
 .../component/ribbon/RibbonConfiguration.java   |  69 ++++
 .../camel/component/ribbon/RibbonConstants.java |  25 ++
 .../processor/RibbonProcessorFactory.java       | 207 +++++++++++
 .../ribbon/processor/RibbonServer.java          |  33 ++
 .../processor/RibbonServiceCallExpression.java  |  40 ++
 .../processor/RibbonServiceCallProcessor.java   | 248 +++++++++++++
 ...bbonServiceCallStaticServerListStrategy.java |  98 +++++
 .../src/main/resources/META-INF/LICENSE.txt     | 203 +++++++++++
 .../src/main/resources/META-INF/NOTICE.txt      |  11 +
 .../apache/camel/model/ServiceCallDefinition    |  18 +
 .../ribbon/processor/RibbonServerListTest.java  |  53 +++
 .../RibbonServiceCallRegistryRouteTest.java     |  57 +++
 .../processor/RibbonServiceCallRouteTest.java   |  65 ++++
 .../RibbonServiceCallUpdateRouteTest.java       |  90 +++++
 .../SpringRibbonServiceCallRouteTest.java       |  46 +++
 .../src/test/resources/log4j.properties         |  37 ++
 .../SpringRibbonServiceCallRouteTest.xml        |  60 +++
 .../camel/spring/CamelContextFactoryBean.java   |   4 +
 .../spring/handler/CamelNamespaceHandler.java   |   6 +-
 components/pom.xml                              |   1 +
 parent/pom.xml                                  |   6 +
 69 files changed, 4220 insertions(+), 43 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/apache-camel/pom.xml
----------------------------------------------------------------------
diff --git a/apache-camel/pom.xml b/apache-camel/pom.xml
index a556261..fd86a54 100644
--- a/apache-camel/pom.xml
+++ b/apache-camel/pom.xml
@@ -680,6 +680,10 @@
     </dependency>
     <dependency>
       <groupId>org.apache.camel</groupId>
+      <artifactId>camel-ribbon</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
       <artifactId>camel-rmi</artifactId>
     </dependency>
     <dependency>

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/apache-camel/src/main/descriptors/common-bin.xml
----------------------------------------------------------------------
diff --git a/apache-camel/src/main/descriptors/common-bin.xml b/apache-camel/src/main/descriptors/common-bin.xml
index 5745702..ceac7f1 100644
--- a/apache-camel/src/main/descriptors/common-bin.xml
+++ b/apache-camel/src/main/descriptors/common-bin.xml
@@ -180,6 +180,7 @@
         <include>org.apache.camel:camel-quickfix</include>
         <include>org.apache.camel:camel-rabbitmq</include>
         <include>org.apache.camel:camel-restlet</include>
+        <include>org.apache.camel:camel-ribbon</include>
         <include>org.apache.camel:camel-rmi</include>
         <include>org.apache.camel:camel-routebox</include>
         <include>org.apache.camel:camel-rss</include>

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/camel-core/src/main/java/org/apache/camel/CamelContext.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/CamelContext.java b/camel-core/src/main/java/org/apache/camel/CamelContext.java
index d830e2d..e5d13fd 100644
--- a/camel-core/src/main/java/org/apache/camel/CamelContext.java
+++ b/camel-core/src/main/java/org/apache/camel/CamelContext.java
@@ -34,6 +34,7 @@ import org.apache.camel.model.DataFormatDefinition;
 import org.apache.camel.model.ProcessorDefinition;
 import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.model.RoutesDefinition;
+import org.apache.camel.model.remote.ServiceCallConfigurationDefinition;
 import org.apache.camel.model.rest.RestDefinition;
 import org.apache.camel.model.rest.RestsDefinition;
 import org.apache.camel.spi.AsyncProcessorAwaitManager;
@@ -565,6 +566,31 @@ public interface CamelContext extends SuspendableService, RuntimeConfiguration {
     Collection<RestConfiguration> getRestConfigurations();
 
     /**
+     * Gets the service call configuration by the given name. If no name is given and there is only one configuration
+     * which matches the type then this configuration is returned.
+     *
+     * @param serviceName name of service, or <tt>null</tt> to return the default configuration
+     * @param type implementation of the configuration such as kubernetes, ribbon etc.
+     * @return the configuration, or <tt>null</tt> if no configuration has been registered
+     */
+    <T extends ServiceCallConfigurationDefinition> T getServiceCallConfiguration(String serviceName, Class<T> type);
+
+    /**
+     * Sets the default service call configuration
+     *
+     * @param configuration the configuration
+     */
+    void setServiceCallConfiguration(ServiceCallConfigurationDefinition configuration);
+
+    /**
+     * Adds the service call configuration
+     *
+     * @param serviceName name of the service
+     * @param configuration the configuration
+     */
+    void addServiceCallConfiguration(String serviceName, ServiceCallConfigurationDefinition configuration);
+
+    /**
      * Returns the order in which the route inputs was started.
      * <p/>
      * The order may not be according to the startupOrder defined on the route.

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
index 180fa99..38ee073 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
@@ -100,6 +100,7 @@ import org.apache.camel.model.ProcessorDefinitionHelper;
 import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.model.RouteDefinitionHelper;
 import org.apache.camel.model.RoutesDefinition;
+import org.apache.camel.model.remote.ServiceCallConfigurationDefinition;
 import org.apache.camel.model.rest.RestDefinition;
 import org.apache.camel.model.rest.RestsDefinition;
 import org.apache.camel.processor.interceptor.BacklogDebugger;
@@ -206,6 +207,7 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
     private final List<RouteDefinition> routeDefinitions = new ArrayList<RouteDefinition>();
     private final List<RestDefinition> restDefinitions = new ArrayList<RestDefinition>();
     private Map<String, RestConfiguration> restConfigurations = new ConcurrentHashMap<>();
+    private Map<String, ServiceCallConfigurationDefinition> serviceCallConfigurations = new ConcurrentHashMap<>();
     private RestRegistry restRegistry = new DefaultRestRegistry();
     private List<InterceptStrategy> interceptStrategies = new ArrayList<InterceptStrategy>();
     private List<RoutePolicyFactory> routePolicyFactories = new ArrayList<RoutePolicyFactory>();
@@ -2551,6 +2553,7 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
     public void addRestConfiguration(RestConfiguration restConfiguration) {
         restConfigurations.put(restConfiguration.getComponent(), restConfiguration);
     }
+
     public RestConfiguration getRestConfiguration(String component, boolean defaultIfNotExist) {
         if (component == null) {
             component = "";
@@ -2566,6 +2569,37 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
         return config;
     }
 
+    @SuppressWarnings("unchecked")
+    public <T extends ServiceCallConfigurationDefinition> T getServiceCallConfiguration(String serviceName, Class<T> type) {
+        if (serviceName == null) {
+            serviceName = "";
+        }
+
+        ServiceCallConfigurationDefinition config = serviceCallConfigurations.get(serviceName);
+        if (config == null) {
+            for (ServiceCallConfigurationDefinition candidate : serviceCallConfigurations.values()) {
+                if (type == null || type.isInstance(candidate)) {
+                    config = candidate;
+                    break;
+                }
+            }
+        }
+
+        if (config != null) {
+            return type != null ? type.cast(config) : (T) config;
+        } else {
+            return null;
+        }
+    }
+
+    public void setServiceCallConfiguration(ServiceCallConfigurationDefinition configuration) {
+        serviceCallConfigurations.put("", configuration);
+    }
+
+    public void addServiceCallConfiguration(String serviceName, ServiceCallConfigurationDefinition configuration) {
+        serviceCallConfigurations.put(serviceName, configuration);
+    }
+
     public List<InterceptStrategy> getInterceptStrategies() {
         return interceptStrategies;
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/camel-core/src/main/java/org/apache/camel/model/Constants.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/Constants.java b/camel-core/src/main/java/org/apache/camel/model/Constants.java
index b33eef7..9c72ac1 100644
--- a/camel-core/src/main/java/org/apache/camel/model/Constants.java
+++ b/camel-core/src/main/java/org/apache/camel/model/Constants.java
@@ -30,6 +30,7 @@ public final class Constants {
         + "org.apache.camel.model.dataformat:"
         + "org.apache.camel.model.language:"
         + "org.apache.camel.model.loadbalancer:"
+        + "org.apache.camel.model.remote:"
         + "org.apache.camel.model.rest";
 
     public static final String PLACEHOLDER_QNAME = "http://camel.apache.org/schema/placeholder";

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/camel-core/src/main/java/org/apache/camel/model/HystrixConfigurationDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/HystrixConfigurationDefinition.java b/camel-core/src/main/java/org/apache/camel/model/HystrixConfigurationDefinition.java
index 3993f47..9a02058 100644
--- a/camel-core/src/main/java/org/apache/camel/model/HystrixConfigurationDefinition.java
+++ b/camel-core/src/main/java/org/apache/camel/model/HystrixConfigurationDefinition.java
@@ -28,6 +28,9 @@ import javax.xml.bind.annotation.XmlTransient;
 
 import org.apache.camel.spi.Metadata;
 
+/**
+ * Hystrix Circuit Breaker EIP configuration
+ */
 @Metadata(label = "eip,routing,circuitbreaker")
 @XmlRootElement(name = "hystrixConfiguration")
 @XmlAccessorType(XmlAccessType.FIELD)

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/camel-core/src/main/java/org/apache/camel/model/HystrixDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/HystrixDefinition.java b/camel-core/src/main/java/org/apache/camel/model/HystrixDefinition.java
index 6251759..7ef7302 100644
--- a/camel-core/src/main/java/org/apache/camel/model/HystrixDefinition.java
+++ b/camel-core/src/main/java/org/apache/camel/model/HystrixDefinition.java
@@ -31,6 +31,9 @@ import org.apache.camel.Processor;
 import org.apache.camel.spi.Metadata;
 import org.apache.camel.spi.RouteContext;
 
+/**
+ * Hystrix Circuit Breaker EIP
+ */
 @Metadata(label = "eip,routing,circuitbreaker")
 @XmlRootElement(name = "hystrix")
 @XmlAccessorType(XmlAccessType.FIELD)

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinition.java b/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinition.java
index 2270ef3..c178af5 100644
--- a/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinition.java
+++ b/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinition.java
@@ -53,6 +53,7 @@ import org.apache.camel.model.language.ConstantExpression;
 import org.apache.camel.model.language.ExpressionDefinition;
 import org.apache.camel.model.language.LanguageExpression;
 import org.apache.camel.model.language.SimpleExpression;
+import org.apache.camel.model.remote.ServiceCallDefinition;
 import org.apache.camel.model.rest.RestDefinition;
 import org.apache.camel.processor.InterceptEndpointProcessor;
 import org.apache.camel.processor.Pipeline;
@@ -654,6 +655,48 @@ public abstract class ProcessorDefinition<Type extends ProcessorDefinition<Type>
     }
 
     /**
+     * Calls the service
+     *
+     * @return the builder
+     */
+    @SuppressWarnings("unchecked")
+    public ServiceCallDefinition serviceCall() {
+        ServiceCallDefinition answer = new ServiceCallDefinition();
+        addOutput(answer);
+        return answer;
+    }
+
+    /**
+     * Calls the service
+     *
+     * @param name the service name
+     * @return the builder
+     */
+    @SuppressWarnings("unchecked")
+    public Type serviceCall(String name) {
+        ServiceCallDefinition answer = new ServiceCallDefinition();
+        answer.setName(name);
+        addOutput(answer);
+        return (Type) this;
+    }
+
+    /**
+     * Calls the service
+     *
+     * @param name the service name
+     * @param uri  the endpoint uri to use for calling the service
+     * @return the builder
+     */
+    @SuppressWarnings("unchecked")
+    public Type serviceCall(String name, String uri) {
+        ServiceCallDefinition answer = new ServiceCallDefinition();
+        answer.setName(name);
+        answer.setUri(uri);
+        addOutput(answer);
+        return (Type) this;
+    }
+
+    /**
      * Sends the exchange to the given endpoint
      *
      * @param endpoint  the endpoint to send to

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/camel-core/src/main/java/org/apache/camel/model/remote/KubernetesConfigurationDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/remote/KubernetesConfigurationDefinition.java b/camel-core/src/main/java/org/apache/camel/model/remote/KubernetesConfigurationDefinition.java
new file mode 100644
index 0000000..d4bd95a
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/model/remote/KubernetesConfigurationDefinition.java
@@ -0,0 +1,364 @@
+/**
+ * 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.model.remote;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.apache.camel.spi.Metadata;
+
+/**
+ * Kubernetes remote service call configuration
+ */
+@Metadata(label = "eip,routing,remote")
+@XmlRootElement(name = "kubernetesConfiguration")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class KubernetesConfigurationDefinition extends ServiceCallConfigurationDefinition {
+
+    @XmlAttribute @Metadata(defaultValue = "environment")
+    private String lookup;
+    @XmlAttribute
+    private String dnsDomain;
+    @XmlAttribute
+    private String namespace;
+    @XmlAttribute
+    private String apiVersion;
+    @XmlAttribute @Metadata(label = "client")
+    private String masterUrl;
+    @XmlAttribute @Metadata(label = "client")
+    private String username;
+    @XmlAttribute @Metadata(label = "client")
+    private String password;
+    @XmlAttribute @Metadata(label = "client")
+    private String oauthToken;
+    @XmlAttribute @Metadata(label = "client")
+    private String caCertData;
+    @XmlAttribute @Metadata(label = "client")
+    private String caCertFile;
+    @XmlAttribute @Metadata(label = "client")
+    private String clientCertData;
+    @XmlAttribute @Metadata(label = "client")
+    private String clientCertFile;
+    @XmlAttribute @Metadata(label = "client")
+    private String clientKeyAlgo;
+    @XmlAttribute @Metadata(label = "client")
+    private String clientKeyData;
+    @XmlAttribute @Metadata(label = "client")
+    private String clientKeyFile;
+    @XmlAttribute @Metadata(label = "client")
+    private String clientKeyPassphrase;
+    @XmlAttribute @Metadata(label = "client")
+    private Boolean trustCerts;
+
+    public KubernetesConfigurationDefinition() {
+    }
+
+    public KubernetesConfigurationDefinition(ServiceCallDefinition parent) {
+        super(parent);
+    }
+
+    // Getter/Setter
+    // -------------------------------------------------------------------------
+
+
+    public String getMasterUrl() {
+        return masterUrl;
+    }
+
+    public void setMasterUrl(String masterUrl) {
+        this.masterUrl = masterUrl;
+    }
+
+    public String getNamespace() {
+        return namespace;
+    }
+
+    public void setNamespace(String namespace) {
+        this.namespace = namespace;
+    }
+
+    public String getApiVersion() {
+        return apiVersion;
+    }
+
+    public void setApiVersion(String apiVersion) {
+        this.apiVersion = apiVersion;
+    }
+
+    public String getLookup() {
+        return lookup;
+    }
+
+    public void setLookup(String lookup) {
+        this.lookup = lookup;
+    }
+
+    public String getDnsDomain() {
+        return dnsDomain;
+    }
+
+    public void setDnsDomain(String dnsDomain) {
+        this.dnsDomain = dnsDomain;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public String getOauthToken() {
+        return oauthToken;
+    }
+
+    public void setOauthToken(String oauthToken) {
+        this.oauthToken = oauthToken;
+    }
+
+    public String getCaCertData() {
+        return caCertData;
+    }
+
+    public void setCaCertData(String caCertData) {
+        this.caCertData = caCertData;
+    }
+
+    public String getCaCertFile() {
+        return caCertFile;
+    }
+
+    public void setCaCertFile(String caCertFile) {
+        this.caCertFile = caCertFile;
+    }
+
+    public String getClientCertData() {
+        return clientCertData;
+    }
+
+    public void setClientCertData(String clientCertData) {
+        this.clientCertData = clientCertData;
+    }
+
+    public String getClientCertFile() {
+        return clientCertFile;
+    }
+
+    public void setClientCertFile(String clientCertFile) {
+        this.clientCertFile = clientCertFile;
+    }
+
+    public String getClientKeyAlgo() {
+        return clientKeyAlgo;
+    }
+
+    public void setClientKeyAlgo(String clientKeyAlgo) {
+        this.clientKeyAlgo = clientKeyAlgo;
+    }
+
+    public String getClientKeyData() {
+        return clientKeyData;
+    }
+
+    public void setClientKeyData(String clientKeyData) {
+        this.clientKeyData = clientKeyData;
+    }
+
+    public String getClientKeyFile() {
+        return clientKeyFile;
+    }
+
+    public void setClientKeyFile(String clientKeyFile) {
+        this.clientKeyFile = clientKeyFile;
+    }
+
+    public String getClientKeyPassphrase() {
+        return clientKeyPassphrase;
+    }
+
+    public void setClientKeyPassphrase(String clientKeyPassphrase) {
+        this.clientKeyPassphrase = clientKeyPassphrase;
+    }
+
+    public Boolean getTrustCerts() {
+        return trustCerts;
+    }
+
+    public void setTrustCerts(Boolean trustCerts) {
+        this.trustCerts = trustCerts;
+    }
+
+    // Fluent API
+    // -------------------------------------------------------------------------
+
+    /**
+     * Sets the URL to the master when using client lookup
+     */
+    public KubernetesConfigurationDefinition masterUrl(String masterUrl) {
+        setMasterUrl(masterUrl);
+        return this;
+    }
+
+    /**
+     * Sets the namespace to use. Will by default use namespace from the ENV variable KUBERNETES_MASTER.
+     */
+    public KubernetesConfigurationDefinition namespace(String namespace) {
+        setNamespace(namespace);
+        return this;
+    }
+
+    /**
+     * Sets the API version when using client lookup
+     */
+    public KubernetesConfigurationDefinition apiVersion(String apiVersion) {
+        setApiVersion(apiVersion);
+        return this;
+    }
+
+    /**
+     * How to perform service lookup. Possible values: client, dns, environment.
+     * <p/>
+     * When using client, then the client queries the kubernetes master to obtain a list
+     * of active pods that provides the service, and then random (or round robin) select a pod.
+     * <p/>
+     * When using dns the service name is resolved as <tt>name.namespace.service.dnsDomain</tt>.
+     * <p/>
+     * When using environment then environment variables are used to lookup the service.
+     * <p/>
+     * By default environment is used.
+     */
+    public KubernetesConfigurationDefinition lookup(String lookup) {
+        setLookup(lookup);
+        return this;
+    }
+
+    /**
+     * Sets the DNS domain to use for DNS lookup.
+     */
+    public KubernetesConfigurationDefinition dnsDomain(String dnsDomain) {
+        setDnsDomain(dnsDomain);
+        return this;
+    }
+
+    /**
+     * Sets the username for authentication when using client lookup
+     */
+    public KubernetesConfigurationDefinition username(String username) {
+        setUsername(username);
+        return this;
+    }
+
+    /**
+     * Sets the password for authentication when using client lookup
+     */
+    public KubernetesConfigurationDefinition password(String password) {
+        setPassword(password);
+        return this;
+    }
+
+    /**
+     * Sets the OAUTH token for authentication (instead of username/password) when using client lookup
+     */
+    public KubernetesConfigurationDefinition oauthToken(String oauthToken) {
+        setOauthToken(oauthToken);
+        return this;
+    }
+
+    /**
+     * Sets the Certificate Authority data when using client lookup
+     */
+    public KubernetesConfigurationDefinition caCertData(String caCertData) {
+        setCaCertData(caCertData);
+        return this;
+    }
+
+    /**
+     * Sets the Certificate Authority data that are loaded from the file when using client lookup
+     */
+    public KubernetesConfigurationDefinition caCertFile(String caCertFile) {
+        setCaCertFile(caCertFile);
+        return this;
+    }
+
+    /**
+     * Sets the Client Certificate data when using client lookup
+     */
+    public KubernetesConfigurationDefinition clientCertData(String clientCertData) {
+        setClientCertData(clientCertData);
+        return this;
+    }
+
+    /**
+     * Sets the Client Certificate data that are loaded from the file when using client lookup
+     */
+    public KubernetesConfigurationDefinition clientCertFile(String clientCertFile) {
+        setClientCertFile(clientCertFile);
+        return this;
+    }
+
+    /**
+     * Sets the Client Keystore algorithm, such as RSA when using client lookup
+     */
+    public KubernetesConfigurationDefinition clientKeyAlgo(String clientKeyAlgo) {
+        setClientKeyAlgo(clientKeyAlgo);
+        return this;
+    }
+
+    /**
+     * Sets the Client Keystore data when using client lookup
+     */
+    public KubernetesConfigurationDefinition clientKeyData(String clientKeyData) {
+        setClientKeyData(clientKeyData);
+        return this;
+    }
+
+    /**
+     * Sets the Client Keystore data that are loaded from the file when using client lookup
+     */
+    public KubernetesConfigurationDefinition clientKeyFile(String clientKeyFile) {
+        setClientKeyFile(clientKeyFile);
+        return this;
+    }
+
+    /**
+     * Sets the Client Keystore passphrase when using client lookup
+     */
+    public KubernetesConfigurationDefinition clientKeyPassphrase(String clientKeyPassphrase) {
+        setClientKeyPassphrase(clientKeyPassphrase);
+        return this;
+    }
+
+    /**
+     * Sets whether to turn on trust certificate check when using client lookup
+     */
+    public KubernetesConfigurationDefinition trustCerts(boolean trustCerts) {
+        setTrustCerts(trustCerts);
+        return this;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/camel-core/src/main/java/org/apache/camel/model/remote/RibbonConfigurationDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/remote/RibbonConfigurationDefinition.java b/camel-core/src/main/java/org/apache/camel/model/remote/RibbonConfigurationDefinition.java
new file mode 100644
index 0000000..a528538
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/model/remote/RibbonConfigurationDefinition.java
@@ -0,0 +1,48 @@
+/**
+ * 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.model.remote;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.apache.camel.spi.Metadata;
+
+/**
+ * Ribbon remote service call configuration
+ */
+@Metadata(label = "eip,routing,remote")
+@XmlRootElement(name = "ribbonConfiguration")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class RibbonConfigurationDefinition extends ServiceCallConfigurationDefinition {
+
+    public RibbonConfigurationDefinition() {
+    }
+
+    public RibbonConfigurationDefinition(ServiceCallDefinition parent) {
+        super(parent);
+    }
+
+    // Getter/Setter
+    // -------------------------------------------------------------------------
+
+    // currently no ribbon specific options
+
+    // Fluent API
+    // -------------------------------------------------------------------------
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/camel-core/src/main/java/org/apache/camel/model/remote/ServiceCallConfigurationDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/remote/ServiceCallConfigurationDefinition.java b/camel-core/src/main/java/org/apache/camel/model/remote/ServiceCallConfigurationDefinition.java
new file mode 100644
index 0000000..562e0df
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/model/remote/ServiceCallConfigurationDefinition.java
@@ -0,0 +1,209 @@
+/**
+ * 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.model.remote;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAnyAttribute;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+import javax.xml.namespace.QName;
+
+import org.apache.camel.model.IdentifiedType;
+import org.apache.camel.model.OtherAttributesAware;
+import org.apache.camel.model.ProcessorDefinition;
+import org.apache.camel.model.PropertyDefinition;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.ServiceCallLoadBalancer;
+import org.apache.camel.spi.ServiceCallServerListStrategy;
+
+/**
+ * Remote service call configuration
+ */
+@Metadata(label = "eip,routing,remote")
+@XmlRootElement(name = "serviceCallConfiguration")
+@XmlAccessorType(XmlAccessType.FIELD)
+public abstract class ServiceCallConfigurationDefinition extends IdentifiedType implements OtherAttributesAware {
+
+    @XmlTransient
+    private ServiceCallDefinition parent;
+    @XmlAttribute @Metadata(defaultValue = "http")
+    private String component;
+    @XmlAttribute
+    private String loadBalancerRef;
+    @XmlTransient
+    private ServiceCallLoadBalancer loadBalancer;
+    @XmlAttribute
+    private String serverListStrategyRef;
+    @XmlTransient
+    private ServiceCallServerListStrategy serverListStrategy;
+    @XmlElement(name = "clientProperty") @Metadata(label = "advanced")
+    private List<PropertyDefinition> properties;
+    // use xs:any to support optional property placeholders
+    @XmlAnyAttribute
+    private Map<QName, Object> otherAttributes;
+
+    public ServiceCallConfigurationDefinition() {
+    }
+
+    public ServiceCallConfigurationDefinition(ServiceCallDefinition parent) {
+        this.parent = parent;
+    }
+
+    // Getter/Setter
+    // -------------------------------------------------------------------------
+
+
+    public String getComponent() {
+        return component;
+    }
+
+    public void setComponent(String component) {
+        this.component = component;
+    }
+
+    public String getLoadBalancerRef() {
+        return loadBalancerRef;
+    }
+
+    public void setLoadBalancerRef(String loadBalancerRef) {
+        this.loadBalancerRef = loadBalancerRef;
+    }
+
+    public ServiceCallLoadBalancer getLoadBalancer() {
+        return loadBalancer;
+    }
+
+    public void setLoadBalancer(ServiceCallLoadBalancer loadBalancer) {
+        this.loadBalancer = loadBalancer;
+    }
+
+    public String getServerListStrategyRef() {
+        return serverListStrategyRef;
+    }
+
+    public void setServerListStrategyRef(String serverListStrategyRef) {
+        this.serverListStrategyRef = serverListStrategyRef;
+    }
+
+    public ServiceCallServerListStrategy getServerListStrategy() {
+        return serverListStrategy;
+    }
+
+    public void setServerListStrategy(ServiceCallServerListStrategy serverListStrategy) {
+        this.serverListStrategy = serverListStrategy;
+    }
+
+    public List<PropertyDefinition> getProperties() {
+        return properties;
+    }
+
+    public void setProperties(List<PropertyDefinition> properties) {
+        this.properties = properties;
+    }
+
+    @Override
+    public Map<QName, Object> getOtherAttributes() {
+        return otherAttributes;
+    }
+
+    @Override
+    public void setOtherAttributes(Map<QName, Object> otherAttributes) {
+        this.otherAttributes = otherAttributes;
+    }
+
+    // Fluent API
+    // -------------------------------------------------------------------------
+
+    /**
+     * Sets the default Camel component to use for calling the remote service.
+     * <p/>
+     * By default the http component is used. You can configure this to use <tt>netty4-http</tt>, <tt>jetty</tt>,
+     * <tt>restlet</tt> or some other components of choice. If the service is not HTTP protocol you can use other
+     * components such as <tt>mqtt</tt>, <tt>jms</tt>, <tt>amqp</tt> etc.
+     * <p/>
+     * If the service call has been configured using an uri, then the component from the uri is used instead
+     * of this default component.
+     */
+    public ServiceCallConfigurationDefinition component(String component) {
+        setComponent(component);
+        return this;
+    }
+
+    /**
+     * Sets a reference to a custom {@link org.apache.camel.spi.ServiceCallLoadBalancer} to use.
+     */
+    public ServiceCallConfigurationDefinition loadBalancer(String loadBalancerRef) {
+        setLoadBalancerRef(loadBalancerRef);
+        return this;
+    }
+
+    /**
+     * Sets a custom {@link org.apache.camel.spi.ServiceCallLoadBalancer} to use.
+     */
+    public ServiceCallConfigurationDefinition loadBalancer(ServiceCallLoadBalancer loadBalancer) {
+        setLoadBalancer(loadBalancer);
+        return this;
+    }
+
+    /**
+     * Sets a reference to a custom {@link org.apache.camel.spi.ServiceCallServerListStrategy} to use.
+     */
+    public ServiceCallConfigurationDefinition serverListStrategy(String serverListStrategyRef) {
+        setServerListStrategyRef(serverListStrategyRef);
+        return this;
+    }
+
+    /**
+     * Sets a custom {@link org.apache.camel.spi.ServiceCallServerListStrategy} to use.
+     */
+    public ServiceCallConfigurationDefinition serverListStrategy(ServiceCallServerListStrategy serverListStrategy) {
+        setServerListStrategy(serverListStrategy);
+        return this;
+    }
+
+    /**
+     * Adds a custom client property to use.
+     * <p/>
+     * These properties are specific to what service call implementation are in use. For example if using ribbon, then
+     * the client properties are define in com.netflix.client.config.CommonClientConfigKey.
+     */
+    public ServiceCallConfigurationDefinition clientProperty(String key, String value) {
+        if (properties == null) {
+            properties = new ArrayList<>();
+        }
+        PropertyDefinition prop = new PropertyDefinition();
+        prop.setKey(key);
+        prop.setValue(value);
+        properties.add(prop);
+        return this;
+    }
+
+    /**
+     * End of configuration
+     */
+    public ProcessorDefinition end() {
+        // end parent as well so we do not have to use 2x end
+        return parent.end();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/camel-core/src/main/java/org/apache/camel/model/remote/ServiceCallDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/remote/ServiceCallDefinition.java b/camel-core/src/main/java/org/apache/camel/model/remote/ServiceCallDefinition.java
new file mode 100644
index 0000000..25ead8d
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/model/remote/ServiceCallDefinition.java
@@ -0,0 +1,253 @@
+/**
+ * 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.model.remote;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.Processor;
+import org.apache.camel.model.NoOutputDefinition;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.RouteContext;
+import org.apache.camel.spi.ServiceCallLoadBalancer;
+import org.apache.camel.spi.ServiceCallServerListStrategy;
+
+/**
+ * Remote service call
+ */
+@Metadata(label = "eip,routing")
+@XmlRootElement(name = "serviceCall")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class ServiceCallDefinition extends NoOutputDefinition<ServiceCallDefinition> {
+
+    @XmlAttribute @Metadata(required = "true")
+    private String name;
+    @XmlAttribute @Metadata(required = "true")
+    private String uri;
+    @XmlAttribute
+    private ExchangePattern pattern;
+    @XmlElement
+    private ServiceCallConfigurationDefinition serviceCallConfiguration;
+    @XmlAttribute
+    private String serviceCallConfigurationRef;
+    @XmlAttribute
+    private String loadBalancerRef;
+    // TODO: allow to use custom type as load balancer
+    @XmlTransient
+    private ServiceCallLoadBalancer loadBalancer;
+    @XmlAttribute
+    private String serverListStrategyRef;
+    @XmlTransient
+    private ServiceCallServerListStrategy serverListStrategy;
+
+    public ServiceCallDefinition() {
+    }
+
+    @Override
+    public String toString() {
+        return "ServiceCall[" + name + "]";
+    }
+
+    @Override
+    public String getLabel() {
+        return "serviceCall";
+    }
+
+    @Override
+    public Processor createProcessor(RouteContext routeContext) throws Exception {
+        throw new IllegalStateException("Cannot find Camel component supporting the ServiceCall EIP such as camel-kubernetes or camel-ribbon.");
+    }
+
+    // Fluent API
+    // -------------------------------------------------------------------------
+
+    /**
+     * Sets the optional {@link ExchangePattern} used to invoke this endpoint
+     */
+    public ServiceCallDefinition pattern(ExchangePattern pattern) {
+        setPattern(pattern);
+        return this;
+    }
+
+    /**
+     * Sets the name of the service to use
+     */
+    public ServiceCallDefinition name(String name) {
+        setName(name);
+        return this;
+    }
+
+    /**
+     * Sets the uri of the service to use
+     */
+    public ServiceCallDefinition uri(String uri) {
+        setUri(uri);
+        return this;
+    }
+
+    /**
+     * Configures the Service Call EIP using Kubernetes
+     * <p/>
+     * Use <tt>end</tt> when configuration is complete, to return back to the Service Call EIP.
+     */
+    public KubernetesConfigurationDefinition kubernetesConfiguration() {
+        serviceCallConfiguration = new KubernetesConfigurationDefinition(this);
+        return (KubernetesConfigurationDefinition) serviceCallConfiguration;
+    }
+
+    /**
+     * Configures the Service Call EIP using Ribbon
+     * <p/>
+     * Use <tt>end</tt> when configuration is complete, to return back to the Service Call EIP.
+     */
+    public RibbonConfigurationDefinition ribbonConfiguration() {
+        serviceCallConfiguration = new RibbonConfigurationDefinition(this);
+        return (RibbonConfigurationDefinition) serviceCallConfiguration;
+    }
+
+    /**
+     * Configures the ServiceCall using the given configuration
+     */
+    public ServiceCallDefinition serviceCallConfiguration(ServiceCallConfigurationDefinition configuration) {
+        serviceCallConfiguration = configuration;
+        return this;
+    }
+
+    /**
+     * Refers to a ServiceCall configuration to use
+     */
+    public ServiceCallDefinition serviceCallConfiguration(String ref) {
+        serviceCallConfigurationRef = ref;
+        return this;
+    }
+
+    /**
+     * Sets a reference to a custom {@link org.apache.camel.spi.ServiceCallLoadBalancer} to use.
+     */
+    public ServiceCallDefinition loadBalancer(String loadBalancerRef) {
+        setLoadBalancerRef(loadBalancerRef);
+        return this;
+    }
+
+    /**
+     * Sets a custom {@link org.apache.camel.spi.ServiceCallLoadBalancer} to use.
+     */
+    public ServiceCallDefinition loadBalancer(ServiceCallLoadBalancer loadBalancer) {
+        setLoadBalancer(loadBalancer);
+        return this;
+    }
+
+    /**
+     * Sets a reference to a custom {@link org.apache.camel.spi.ServiceCallServerListStrategy} to use.
+     */
+    public ServiceCallDefinition serverListStrategy(String serverListStrategyRef) {
+        setServerListStrategyRef(serverListStrategyRef);
+        return this;
+    }
+
+    /**
+     * Sets a custom {@link org.apache.camel.spi.ServiceCallServerListStrategy} to use.
+     */
+    public ServiceCallDefinition serverListStrategy(ServiceCallServerListStrategy serverListStrategy) {
+        setServerListStrategy(serverListStrategy);
+        return this;
+    }
+
+    // Properties
+    // -------------------------------------------------------------------------
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public ExchangePattern getPattern() {
+        return pattern;
+    }
+
+    public void setPattern(ExchangePattern pattern) {
+        this.pattern = pattern;
+    }
+
+    public ServiceCallConfigurationDefinition getServiceCallConfiguration() {
+        return serviceCallConfiguration;
+    }
+
+    public void setServiceCallConfiguration(ServiceCallConfigurationDefinition serviceCallConfiguration) {
+        this.serviceCallConfiguration = serviceCallConfiguration;
+    }
+
+    public String getServiceCallConfigurationRef() {
+        return serviceCallConfigurationRef;
+    }
+
+    public void setServiceCallConfigurationRef(String serviceCallConfigurationRef) {
+        this.serviceCallConfigurationRef = serviceCallConfigurationRef;
+    }
+
+    public String getUri() {
+        return uri;
+    }
+
+    /**
+     * The uri of the endpoint to send to.
+     * The uri can be dynamic computed using the {@link org.apache.camel.language.simple.SimpleLanguage} expression.
+     */
+    public void setUri(String uri) {
+        this.uri = uri;
+    }
+
+    public String getLoadBalancerRef() {
+        return loadBalancerRef;
+    }
+
+    public void setLoadBalancerRef(String loadBalancerRef) {
+        this.loadBalancerRef = loadBalancerRef;
+    }
+
+    public ServiceCallLoadBalancer getLoadBalancer() {
+        return loadBalancer;
+    }
+
+    public void setLoadBalancer(ServiceCallLoadBalancer loadBalancer) {
+        this.loadBalancer = loadBalancer;
+    }
+
+    public String getServerListStrategyRef() {
+        return serverListStrategyRef;
+    }
+
+    public void setServerListStrategyRef(String serverListStrategyRef) {
+        this.serverListStrategyRef = serverListStrategyRef;
+    }
+
+    public ServiceCallServerListStrategy getServerListStrategy() {
+        return serverListStrategy;
+    }
+
+    public void setServerListStrategy(ServiceCallServerListStrategy serverListStrategy) {
+        this.serverListStrategy = serverListStrategy;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/camel-core/src/main/java/org/apache/camel/model/remote/package-info.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/remote/package-info.java b/camel-core/src/main/java/org/apache/camel/model/remote/package-info.java
new file mode 100644
index 0000000..5d6e89e
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/model/remote/package-info.java
@@ -0,0 +1,23 @@
+/**
+ * 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.
+ */
+
+
+/**
+ * The JAXB POJOs for the remote service call DSL
+ */
+@javax.xml.bind.annotation.XmlSchema(namespace = "http://camel.apache.org/schema/spring", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
+package org.apache.camel.model.remote;

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/camel-core/src/main/java/org/apache/camel/spi/ServiceCallLoadBalancer.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/spi/ServiceCallLoadBalancer.java b/camel-core/src/main/java/org/apache/camel/spi/ServiceCallLoadBalancer.java
new file mode 100644
index 0000000..908fcbb
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/spi/ServiceCallLoadBalancer.java
@@ -0,0 +1,36 @@
+/**
+ * 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.spi;
+
+import java.util.Collection;
+
+/**
+ * Allows SPIs to implement custom load balancing strategies for the Service Call EIP.
+ *
+ * @see ServiceCallServerListStrategy
+ */
+public interface ServiceCallLoadBalancer<T extends ServiceCallServer> {
+
+    /**
+     * Chooses one of the servers to use using the implemented strategy.
+     *
+     * @param servers  list of servers
+     * @return the chosen server to use.
+     */
+    T chooseServer(Collection<T> servers);
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServer.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServer.java b/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServer.java
new file mode 100644
index 0000000..1579599
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServer.java
@@ -0,0 +1,36 @@
+/**
+ * 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.spi;
+
+/**
+ * Represents a server that host a service for the Service Call EIP.
+ *
+ * @see ServiceCallLoadBalancer
+ * @see ServiceCallServerListStrategy
+ */
+public interface ServiceCallServer {
+
+    /**
+     * Gets the IP or hostname of the server hosting the service
+     */
+    String getIp();
+
+    /**
+     * Gets the port number of the server hosting the service
+     */
+    int getPort();
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServerListStrategy.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServerListStrategy.java b/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServerListStrategy.java
new file mode 100644
index 0000000..b7edee9
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/spi/ServiceCallServerListStrategy.java
@@ -0,0 +1,45 @@
+/**
+ * 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.spi;
+
+import java.util.Collection;
+
+/**
+ * Allows SPIs to implement custom server list strategies for the Service Call EIP.
+ *
+ * @see ServiceCallLoadBalancer
+ * @see ServiceCallServer
+ */
+public interface ServiceCallServerListStrategy<T extends ServiceCallServer> {
+
+    /**
+     * Gets the initial list of servers.
+     * <p/>
+     * This method may return <tt>null</tt> or an empty list.
+     */
+    Collection<T> getInitialListOfServers();
+
+    /**
+     * Gets the updated list of servers.
+     * <p/>
+     * This method can either be called on-demand prior to a service call, or have
+     * a background job that is scheduled to update the list, or a watcher
+     * that triggers when the list of servers changes.
+     */
+    Collection<T> getUpdatedListOfServers();
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/camel-core/src/main/java/org/apache/camel/support/ServiceCallExpressionSupport.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/support/ServiceCallExpressionSupport.java b/camel-core/src/main/java/org/apache/camel/support/ServiceCallExpressionSupport.java
new file mode 100644
index 0000000..9901038
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/support/ServiceCallExpressionSupport.java
@@ -0,0 +1,101 @@
+/**
+ * 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.support;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.model.remote.ServiceCallDefinition;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Support class for custom implementations of {@link ServiceCallDefinition ServiceCall EIP} components.
+ * <p/>
+ * Below are some examples how to call a service and what Camel endpoint URI is constructed based on the input:
+ * <pre>
+     serviceCall("myService") -> http://hostname:port
+     serviceCall("myService/foo") -> http://hostname:port/foo
+     serviceCall("http:myService/foo") -> http:hostname:port/foo
+     serviceCall("myService", "http:myService.host:myService.port/foo") -> http:hostname:port/foo
+     serviceCall("myService", "netty4:tcp:myService?connectTimeout=1000") -> netty:tcp:hostname:port?connectTimeout=1000
+ * </pre>
+ */
+public abstract class ServiceCallExpressionSupport extends ExpressionAdapter {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ServiceCallExpressionSupport.class);
+
+    private final String name;
+    private final String scheme;
+    private final String contextPath;
+    private final String uri;
+
+    public ServiceCallExpressionSupport(String name, String scheme, String contextPath, String uri) {
+        this.name = name;
+        this.scheme = scheme;
+        this.contextPath = contextPath;
+        this.uri = uri;
+    }
+
+    public abstract String getIp(Exchange exchange) throws Exception;
+
+    public abstract int getPort(Exchange exchange) throws Exception;
+
+    @Override
+    public Object evaluate(Exchange exchange) {
+        try {
+            String ip = getIp(exchange);
+            int port = getPort(exchange);
+            return buildCamelEndpointUri(ip, port, name, uri, contextPath, scheme);
+        } catch (Exception e) {
+            throw ObjectHelper.wrapRuntimeCamelException(e);
+        }
+    }
+
+    protected static String buildCamelEndpointUri(String ip, int port, String name, String uri, String contextPath, String scheme) {
+        // build basic uri if none provided
+        String answer = uri;
+        if (answer == null) {
+            if (scheme == null) {
+                // use http/https by default if no scheme has been configured
+                if (port == 443) {
+                    scheme = "https";
+                } else {
+                    scheme = "http";
+                }
+            }
+            answer = scheme + "://" + ip + ":" + port;
+            if (contextPath != null) {
+                answer += "" + contextPath;
+            }
+        } else {
+            // we have existing uri, then replace the serviceName with ip:port
+            if (answer.contains(name + ".host")) {
+                answer = answer.replaceFirst(name + "\\.host", ip);
+            }
+            if (answer.contains(name + ".port")) {
+                answer = answer.replaceFirst(name + "\\.port", "" + port);
+            }
+            if (answer.contains(name)) {
+                answer = answer.replaceFirst(name, ip + ":" + port);
+            }
+        }
+
+        LOG.debug("Camel endpoint uri: {} for calling service: {} on server {}:{}", answer, name, ip, port);
+        return answer;
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/camel-core/src/main/resources/org/apache/camel/model/remote/jaxb.index
----------------------------------------------------------------------
diff --git a/camel-core/src/main/resources/org/apache/camel/model/remote/jaxb.index b/camel-core/src/main/resources/org/apache/camel/model/remote/jaxb.index
new file mode 100644
index 0000000..29147c2
--- /dev/null
+++ b/camel-core/src/main/resources/org/apache/camel/model/remote/jaxb.index
@@ -0,0 +1,20 @@
+## ------------------------------------------------------------------------
+## 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.
+## ------------------------------------------------------------------------
+KubernetesConfigurationDefinition
+RibbonConfigurationDefinition
+ServiceCallDefinition
+ServiceCallConfigurationDefinition

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/CamelContextFactoryBean.java
----------------------------------------------------------------------
diff --git a/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/CamelContextFactoryBean.java b/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/CamelContextFactoryBean.java
index 0c6e832..d04ca11 100644
--- a/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/CamelContextFactoryBean.java
+++ b/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/CamelContextFactoryBean.java
@@ -58,6 +58,8 @@ import org.apache.camel.model.RouteContextRefDefinition;
 import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.model.ThreadPoolProfileDefinition;
 import org.apache.camel.model.dataformat.DataFormatsDefinition;
+import org.apache.camel.model.remote.KubernetesConfigurationDefinition;
+import org.apache.camel.model.remote.RibbonConfigurationDefinition;
 import org.apache.camel.model.rest.RestConfigurationDefinition;
 import org.apache.camel.model.rest.RestDefinition;
 import org.apache.camel.spi.PackageScanFilter;
@@ -142,6 +144,8 @@ public class CamelContextFactoryBean extends AbstractCamelContextFactoryBean<Blu
     private CamelStreamCachingStrategyDefinition camelStreamCachingStrategy;
     @XmlElements({
         @XmlElement(name = "hystrixConfiguration", type = HystrixConfigurationDefinition.class, required = false),
+        @XmlElement(name = "kubernetesConfiguration", type = KubernetesConfigurationDefinition.class, required = false),
+        @XmlElement(name = "ribbonConfiguration", type = RibbonConfigurationDefinition.class, required = false),
         @XmlElement(name = "template", type = CamelProducerTemplateFactoryBean.class, required = false),
         @XmlElement(name = "consumerTemplate", type = CamelConsumerTemplateFactoryBean.class, required = false),
         @XmlElement(name = "proxy", type = CamelProxyFactoryBean.class, required = false),

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/components/camel-kubernetes/pom.xml
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/pom.xml b/components/camel-kubernetes/pom.xml
index 1d39ba4..89c3fcc 100644
--- a/components/camel-kubernetes/pom.xml
+++ b/components/camel-kubernetes/pom.xml
@@ -1,14 +1,20 @@
 <?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. -->
+<!--
+  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.
+-->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 
   <modelVersion>4.0.0</modelVersion>
@@ -46,7 +52,12 @@
     <!-- testing -->
     <dependency>
       <groupId>org.apache.camel</groupId>
-      <artifactId>camel-test</artifactId>
+      <artifactId>camel-test-spring</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-http</artifactId>
       <scope>test</scope>
     </dependency>
     <dependency>

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/components/camel-kubernetes/src/main/docs/kubernetes.adoc
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/docs/kubernetes.adoc b/components/camel-kubernetes/src/main/docs/kubernetes.adoc
index 93ed8f8..3507e04 100644
--- a/components/camel-kubernetes/src/main/docs/kubernetes.adoc
+++ b/components/camel-kubernetes/src/main/docs/kubernetes.adoc
@@ -44,6 +44,7 @@ The Kubernetes component has no options.
 
 
 
+
 // endpoint options: START
 The Kubernetes component supports 23 endpoint options which are listed below:
 
@@ -56,7 +57,7 @@ The Kubernetes component supports 23 endpoint options which are listed below:
 | category | common |  | String | *Required* Kubernetes Producer and Consumer category
 | kubernetesClient | common |  | DefaultKubernetesClient | Default KubernetesClient to use if provided
 | bridgeErrorHandler | consumer | false | boolean | Allows for bridging the consumer to the Camel routing Error Handler which mean any exceptions occurred while the consumer is trying to pickup incoming messages or the likes will now be processed as a message and handled by the routing Error Handler. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions that will be logged at WARN/ERROR level and ignored.
-| namespaceName | consumer |  | String | The namespace name
+| namespace | consumer |  | String | The namespace
 | poolSize | consumer | 1 | int | The Consumer pool size
 | exceptionHandler | consumer (advanced) |  | ExceptionHandler | To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this options is not in use. By default the consumer will deal with exceptions that will be logged at WARN/ERROR level and ignored.
 | operation | producer |  | String | Producer operation to do on Kubernetes
@@ -80,6 +81,7 @@ The Kubernetes component supports 23 endpoint options which are listed below:
 
 
 
+
 [[Kubernetes-Headers]]
 Headers
 ^^^^^^^

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/KubernetesConfiguration.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/KubernetesConfiguration.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/KubernetesConfiguration.java
index bd965ac..de35463 100644
--- a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/KubernetesConfiguration.java
+++ b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/KubernetesConfiguration.java
@@ -86,7 +86,7 @@ public class KubernetesConfiguration {
     private Boolean trustCerts;
 
     @UriParam(label = "consumer")
-    private String namespaceName;
+    private String namespace;
     
     @UriParam(label = "consumer", defaultValue = "1")
     private int poolSize = 1;
@@ -279,16 +279,33 @@ public class KubernetesConfiguration {
     }
 
     /**
-     * The namespace name
+     * The namespace
      */
+    public String getNamespace() {
+        return namespace;
+    }
+
+    public void setNamespace(String namespace) {
+        this.namespace = namespace;
+    }
+
+
+    /**
+     * @deprecated use {@link #getNamespace()}
+     */
+    @Deprecated
     public String getNamespaceName() {
-        return namespaceName;
+        return getNamespace();
     }
 
-    public void setNamespaceName(String namespaceName) {
-        this.namespaceName = namespaceName;
+    /**
+     * @deprecated use {@link #setNamespace(String)}
+     */
+    @Deprecated
+    public void setNamespaceName(String namespace) {
+        setNamespace(namespace);
     }
-    
+
     /**
      * The Consumer pool size
      */
@@ -308,6 +325,6 @@ public class KubernetesConfiguration {
                 + ", clientCertData=" + clientCertData + ", clientCertFile=" + clientCertFile + ", clientKeyAlgo="
                 + clientKeyAlgo + ", clientKeyData=" + clientKeyData + ", clientKeyFile=" + clientKeyFile
                 + ", clientKeyPassphrase=" + clientKeyPassphrase + ", oauthToken=" + oauthToken + ", trustCerts="
-                + trustCerts + ", namespaceName=" + namespaceName + "]";
+                + trustCerts + ", namespaceName=" + namespace + "]";
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/KubernetesConstants.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/KubernetesConstants.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/KubernetesConstants.java
index 3d78497..29a3fa9 100644
--- a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/KubernetesConstants.java
+++ b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/KubernetesConstants.java
@@ -17,6 +17,11 @@
 package org.apache.camel.component.kubernetes;
 
 public interface KubernetesConstants {
+
+    // Service Call EIP
+    String KUBERNETES_SERVER_IP = "CamelKubernetesServerIp";
+    String KUBERNETES_SERVER_PORT = "CamelKubernetesServerPort";
+
     // Producer
     String KUBERNETES_OPERATION = "CamelKubernetesOperation";
     String KUBERNETES_NAMESPACE_NAME = "CamelKubernetesNamespaceName";

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/KubernetesEndpoint.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/KubernetesEndpoint.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/KubernetesEndpoint.java
index c0312a3..3204f5f 100644
--- a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/KubernetesEndpoint.java
+++ b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/KubernetesEndpoint.java
@@ -21,7 +21,7 @@ import java.util.concurrent.ExecutorService;
 import io.fabric8.kubernetes.client.Config;
 import io.fabric8.kubernetes.client.ConfigBuilder;
 import io.fabric8.kubernetes.client.DefaultKubernetesClient;
-
+import io.fabric8.kubernetes.client.KubernetesClient;
 import org.apache.camel.Consumer;
 import org.apache.camel.Processor;
 import org.apache.camel.Producer;
@@ -61,7 +61,7 @@ public class KubernetesEndpoint extends DefaultEndpoint {
     @UriParam
     private KubernetesConfiguration configuration;
 
-    private DefaultKubernetesClient client;
+    private transient KubernetesClient client;
 
     public KubernetesEndpoint(String uri, KubernetesComponent component, KubernetesConfiguration config) {
         super(uri, component);
@@ -160,22 +160,22 @@ public class KubernetesEndpoint extends DefaultEndpoint {
     @Override
     protected void doStart() throws Exception {
         super.doStart();
-
-        client = configuration.getKubernetesClient() != null ? configuration.getKubernetesClient()
-                : createKubernetesClient();
+        client = configuration.getKubernetesClient() != null ? configuration.getKubernetesClient() : createKubernetesClient();
     }
 
     @Override
     protected void doStop() throws Exception {
         super.doStop();
-        client.close();
+        if (client != null) {
+            client.close();
+        }
     }
     
     public ExecutorService createExecutor() {
         return getCamelContext().getExecutorServiceManager().newFixedThreadPool(this, "KubernetesConsumer", configuration.getPoolSize());
     }
 
-    public DefaultKubernetesClient getKubernetesClient() {
+    public KubernetesClient getKubernetesClient() {
         return client;
     }
 
@@ -186,10 +186,9 @@ public class KubernetesEndpoint extends DefaultEndpoint {
         return configuration;
     }
 
-    private DefaultKubernetesClient createKubernetesClient() {
+    private KubernetesClient createKubernetesClient() {
         LOG.debug("Create Kubernetes client with the following Configuration: " + configuration.toString());
 
-        DefaultKubernetesClient kubeClient = new DefaultKubernetesClient();
         ConfigBuilder builder = new ConfigBuilder();
         builder.withMasterUrl(configuration.getMasterUrl());
         if ((ObjectHelper.isNotEmpty(configuration.getUsername())
@@ -232,8 +231,6 @@ public class KubernetesEndpoint extends DefaultEndpoint {
         }
 
         Config conf = builder.build();
-
-        kubeClient = new DefaultKubernetesClient(conf);
-        return kubeClient;
+        return new DefaultKubernetesClient(conf);
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/consumer/KubernetesNamespacesConsumer.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/consumer/KubernetesNamespacesConsumer.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/consumer/KubernetesNamespacesConsumer.java
index e3d6d08..4786ede 100644
--- a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/consumer/KubernetesNamespacesConsumer.java
+++ b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/consumer/KubernetesNamespacesConsumer.java
@@ -77,9 +77,9 @@ public class KubernetesNamespacesConsumer extends DefaultConsumer {
         @Override
         public void run() {
             if (ObjectHelper.isNotEmpty(getEndpoint().getKubernetesConfiguration().getOauthToken())) {
-                if (ObjectHelper.isNotEmpty(getEndpoint().getKubernetesConfiguration().getNamespaceName())) {
+                if (ObjectHelper.isNotEmpty(getEndpoint().getKubernetesConfiguration().getNamespace())) {
                     getEndpoint().getKubernetesClient().namespaces()
-                            .withName(getEndpoint().getKubernetesConfiguration().getNamespaceName())
+                            .withName(getEndpoint().getKubernetesConfiguration().getNamespace())
                             .watch(new Watcher<Namespace>() {
 
                                 @Override

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/consumer/KubernetesPodsConsumer.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/consumer/KubernetesPodsConsumer.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/consumer/KubernetesPodsConsumer.java
index b92d05d..727d7f4 100644
--- a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/consumer/KubernetesPodsConsumer.java
+++ b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/consumer/KubernetesPodsConsumer.java
@@ -77,9 +77,9 @@ public class KubernetesPodsConsumer extends DefaultConsumer {
         @Override
         public void run() {
             if (ObjectHelper.isNotEmpty(getEndpoint().getKubernetesConfiguration().getOauthToken())) {
-                if (ObjectHelper.isNotEmpty(getEndpoint().getKubernetesConfiguration().getNamespaceName())) {
+                if (ObjectHelper.isNotEmpty(getEndpoint().getKubernetesConfiguration().getNamespace())) {
                     getEndpoint().getKubernetesClient().pods()
-                            .inNamespace(getEndpoint().getKubernetesConfiguration().getNamespaceName())
+                            .inNamespace(getEndpoint().getKubernetesConfiguration().getNamespace())
                             .watch(new Watcher<Pod>() {
 
                                 @Override

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/consumer/KubernetesReplicationControllersConsumer.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/consumer/KubernetesReplicationControllersConsumer.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/consumer/KubernetesReplicationControllersConsumer.java
index da577b7..03f9be3 100644
--- a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/consumer/KubernetesReplicationControllersConsumer.java
+++ b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/consumer/KubernetesReplicationControllersConsumer.java
@@ -78,9 +78,9 @@ public class KubernetesReplicationControllersConsumer extends DefaultConsumer {
         @Override
         public void run() {
             if (ObjectHelper.isNotEmpty(getEndpoint().getKubernetesConfiguration().getOauthToken())) {
-                if (ObjectHelper.isNotEmpty(getEndpoint().getKubernetesConfiguration().getNamespaceName())) {
+                if (ObjectHelper.isNotEmpty(getEndpoint().getKubernetesConfiguration().getNamespace())) {
                     getEndpoint().getKubernetesClient().replicationControllers()
-                            .inNamespace(getEndpoint().getKubernetesConfiguration().getNamespaceName())
+                            .inNamespace(getEndpoint().getKubernetesConfiguration().getNamespace())
                             .watch(new Watcher<ReplicationController>() {
 
                                 @Override

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/consumer/KubernetesSecretsConsumer.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/consumer/KubernetesSecretsConsumer.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/consumer/KubernetesSecretsConsumer.java
index daadb11..a677945 100644
--- a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/consumer/KubernetesSecretsConsumer.java
+++ b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/consumer/KubernetesSecretsConsumer.java
@@ -78,9 +78,9 @@ public class KubernetesSecretsConsumer extends DefaultConsumer {
         @Override
         public void run() {
             if (ObjectHelper.isNotEmpty(getEndpoint().getKubernetesConfiguration().getOauthToken())) {
-                if (ObjectHelper.isNotEmpty(getEndpoint().getKubernetesConfiguration().getNamespaceName())) {
+                if (ObjectHelper.isNotEmpty(getEndpoint().getKubernetesConfiguration().getNamespace())) {
                     getEndpoint().getKubernetesClient().secrets()
-                            .inNamespace(getEndpoint().getKubernetesConfiguration().getNamespaceName())
+                            .inNamespace(getEndpoint().getKubernetesConfiguration().getNamespace())
                             .watch(new Watcher<Secret>() {
 
                                 @Override

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/consumer/KubernetesServicesConsumer.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/consumer/KubernetesServicesConsumer.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/consumer/KubernetesServicesConsumer.java
index d8b28ae..b51746f 100644
--- a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/consumer/KubernetesServicesConsumer.java
+++ b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/consumer/KubernetesServicesConsumer.java
@@ -77,9 +77,9 @@ public class KubernetesServicesConsumer extends DefaultConsumer {
         @Override
         public void run() {
             if (ObjectHelper.isNotEmpty(getEndpoint().getKubernetesConfiguration().getOauthToken())) {
-                if (ObjectHelper.isNotEmpty(getEndpoint().getKubernetesConfiguration().getNamespaceName())) {
+                if (ObjectHelper.isNotEmpty(getEndpoint().getKubernetesConfiguration().getNamespace())) {
                     getEndpoint().getKubernetesClient().services()
-                            .inNamespace(getEndpoint().getKubernetesConfiguration().getNamespaceName())
+                            .inNamespace(getEndpoint().getKubernetesConfiguration().getNamespace())
                             .watch(new Watcher<Service>() {
 
                                 @Override


[4/4] camel git commit: Add missing components to release kit

Posted by da...@apache.org.
Add missing components to release kit


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/8447297a
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/8447297a
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/8447297a

Branch: refs/heads/master
Commit: 8447297a23203be0a39dcb971ef2c3c0f0f7909f
Parents: 4b81b4a
Author: Claus Ibsen <da...@apache.org>
Authored: Tue May 24 14:41:11 2016 +0200
Committer: Claus Ibsen <da...@apache.org>
Committed: Tue May 24 14:41:11 2016 +0200

----------------------------------------------------------------------
 apache-camel/pom.xml                             | 8 ++++++++
 apache-camel/src/main/descriptors/common-bin.xml | 1 +
 parent/pom.xml                                   | 5 +++++
 3 files changed, 14 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/8447297a/apache-camel/pom.xml
----------------------------------------------------------------------
diff --git a/apache-camel/pom.xml b/apache-camel/pom.xml
index fd86a54..8f2d51e 100644
--- a/apache-camel/pom.xml
+++ b/apache-camel/pom.xml
@@ -872,6 +872,14 @@
     </dependency>
     <dependency>
       <groupId>org.apache.camel</groupId>
+      <artifactId>camel-tarfile</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-telegram</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
       <artifactId>camel-test</artifactId>
     </dependency>
     <dependency>

http://git-wip-us.apache.org/repos/asf/camel/blob/8447297a/apache-camel/src/main/descriptors/common-bin.xml
----------------------------------------------------------------------
diff --git a/apache-camel/src/main/descriptors/common-bin.xml b/apache-camel/src/main/descriptors/common-bin.xml
index ceac7f1..2858d54 100644
--- a/apache-camel/src/main/descriptors/common-bin.xml
+++ b/apache-camel/src/main/descriptors/common-bin.xml
@@ -228,6 +228,7 @@
         <include>org.apache.camel:camel-swagger</include>
         <include>org.apache.camel:camel-swagger-java</include> 
         <include>org.apache.camel:camel-tagsoup</include>
+        <include>org.apache.camel:camel-tarfile</include>
         <include>org.apache.camel:camel-telegram</include>
         <include>org.apache.camel:camel-test</include>
         <include>org.apache.camel:camel-test-blueprint</include>

http://git-wip-us.apache.org/repos/asf/camel/blob/8447297a/parent/pom.xml
----------------------------------------------------------------------
diff --git a/parent/pom.xml b/parent/pom.xml
index 6d911fe..b531621 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -1721,6 +1721,11 @@
       </dependency>
       <dependency>
         <groupId>org.apache.camel</groupId>
+        <artifactId>camel-tarfile</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.camel</groupId>
         <artifactId>camel-telegram</artifactId>
         <version>${project.version}</version>
       </dependency>


[2/4] camel git commit: CAMEL-9683: A new toService EIP that uses a client discovery to lookup alive services and pick a service ip/port to use when calling the service from Camel route. Allows to plugin different providers. Added camel-ribbon as impleme

Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesClientServiceCallProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesClientServiceCallProcessor.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesClientServiceCallProcessor.java
new file mode 100644
index 0000000..f1af317
--- /dev/null
+++ b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesClientServiceCallProcessor.java
@@ -0,0 +1,251 @@
+/**
+ * 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 java.util.Collection;
+import java.util.concurrent.RejectedExecutionException;
+
+import io.fabric8.kubernetes.client.AutoAdaptableKubernetesClient;
+import io.fabric8.kubernetes.client.Config;
+import io.fabric8.kubernetes.client.ConfigBuilder;
+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.kubernetes.KubernetesConfiguration;
+import org.apache.camel.component.kubernetes.KubernetesConstants;
+import org.apache.camel.processor.SendDynamicProcessor;
+import org.apache.camel.spi.IdAware;
+import org.apache.camel.spi.ServiceCallLoadBalancer;
+import org.apache.camel.spi.ServiceCallServerListStrategy;
+import org.apache.camel.support.ServiceSupport;
+import org.apache.camel.util.AsyncProcessorHelper;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.ServiceHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Kubernetes based implementation of the the ServiceCall EIP where the service lookup is client based.
+ */
+public class KubernetesClientServiceCallProcessor extends ServiceSupport implements AsyncProcessor, CamelContextAware, Traceable, IdAware {
+
+    private static final Logger LOG = LoggerFactory.getLogger(KubernetesClientServiceCallProcessor.class);
+
+    private CamelContext camelContext;
+    private String id;
+    private final String name;
+    private final String scheme;
+    private final String contextPath;
+    private final String namespace;
+    private final String uri;
+    private final ExchangePattern exchangePattern;
+    private final KubernetesConfiguration configuration;
+    private final KubernetesServiceCallExpression serviceCallExpression;
+    private ServiceCallServerListStrategy<KubernetesServer> serverListStrategy;
+    private ServiceCallLoadBalancer<KubernetesServer> loadBalancer;
+    private SendDynamicProcessor processor;
+
+    public KubernetesClientServiceCallProcessor(String name, String namespace, String scheme, String uri, ExchangePattern exchangePattern, KubernetesConfiguration configuration) {
+        // setup from the provided name which can contain scheme and context-path information as well
+        String serviceName;
+        if (name.contains("/")) {
+            serviceName = ObjectHelper.before(name, "/");
+            this.contextPath = ObjectHelper.after(name, "/");
+        } else if (name.contains("?")) {
+            serviceName = ObjectHelper.before(name, "?");
+            this.contextPath = ObjectHelper.after(name, "?");
+        } else {
+            serviceName = name;
+            this.contextPath = null;
+        }
+        if (serviceName.contains(":")) {
+            this.scheme = ObjectHelper.before(serviceName, ":");
+            this.name = ObjectHelper.after(serviceName, ":");
+        } else {
+            this.scheme = scheme;
+            this.name = serviceName;
+        }
+
+        // if no namespace configured then resolve from environment variables
+        if (namespace == null) {
+            this.namespace = System.getenv("KUBERNETES_NAMESPACE");
+        } else {
+            this.namespace = namespace;
+        }
+        this.uri = uri;
+        this.exchangePattern = exchangePattern;
+        this.configuration = configuration;
+        this.serviceCallExpression = new KubernetesServiceCallExpression(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) {
+        Collection<KubernetesServer> servers = null;
+        try {
+            servers = serverListStrategy.getUpdatedListOfServers();
+            if (servers == null || servers.isEmpty()) {
+                exchange.setException(new RejectedExecutionException("No active services with name " + name + " in namespace " + namespace));
+            }
+        } catch (Throwable e) {
+            exchange.setException(e);
+        }
+
+        if (exchange.getException() != null) {
+            callback.done(true);
+            return true;
+        }
+
+        // let the client load balancer chose which server to use
+        KubernetesServer server = loadBalancer.chooseServer(servers);
+        String ip = server.getIp();
+        int port = server.getPort();
+        LOG.debug("Service {} active at server: {}:{}", name, ip, port);
+
+        // set selected server as header
+        exchange.getIn().setHeader(KubernetesConstants.KUBERNETES_SERVER_IP, ip);
+        exchange.getIn().setHeader(KubernetesConstants.KUBERNETES_SERVER_PORT, port);
+
+        // 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 ServiceCallLoadBalancer<KubernetesServer> getLoadBalancer() {
+        return loadBalancer;
+    }
+
+    public void setLoadBalancer(ServiceCallLoadBalancer<KubernetesServer> loadBalancer) {
+        this.loadBalancer = loadBalancer;
+    }
+
+    public ServiceCallServerListStrategy getServerListStrategy() {
+        return serverListStrategy;
+    }
+
+    public void setServerListStrategy(ServiceCallServerListStrategy serverListStrategy) {
+        this.serverListStrategy = serverListStrategy;
+    }
+
+    @Override
+    protected void doStart() throws Exception {
+        ObjectHelper.notEmpty(name, "name", this);
+        ObjectHelper.notEmpty(namespace, "namespace", this);
+        ObjectHelper.notEmpty(configuration.getMasterUrl(), "masterUrl", this);
+
+        if (loadBalancer == null) {
+            loadBalancer = new RandomLoadBalancer();
+        }
+        if (serverListStrategy == null) {
+            serverListStrategy = new KubernetesServiceCallServerListStrategy(name, namespace, null, createKubernetesClient());
+        }
+        LOG.info("KubernetesServiceCall at namespace: {} with service name: {} is using load balancer: {} and service discovery: {}", namespace, name, loadBalancer, 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);
+    }
+
+    private AutoAdaptableKubernetesClient createKubernetesClient() {
+        LOG.debug("Create Kubernetes client with the following Configuration: " + configuration.toString());
+
+        ConfigBuilder builder = new ConfigBuilder();
+        builder.withMasterUrl(configuration.getMasterUrl());
+        if ((ObjectHelper.isNotEmpty(configuration.getUsername())
+                && ObjectHelper.isNotEmpty(configuration.getPassword()))
+                && ObjectHelper.isEmpty(configuration.getOauthToken())) {
+            builder.withUsername(configuration.getUsername());
+            builder.withPassword(configuration.getPassword());
+        } else {
+            builder.withOauthToken(configuration.getOauthToken());
+        }
+        if (ObjectHelper.isNotEmpty(configuration.getCaCertData())) {
+            builder.withCaCertData(configuration.getCaCertData());
+        }
+        if (ObjectHelper.isNotEmpty(configuration.getCaCertFile())) {
+            builder.withCaCertFile(configuration.getCaCertFile());
+        }
+        if (ObjectHelper.isNotEmpty(configuration.getClientCertData())) {
+            builder.withClientCertData(configuration.getClientCertData());
+        }
+        if (ObjectHelper.isNotEmpty(configuration.getClientCertFile())) {
+            builder.withClientCertFile(configuration.getClientCertFile());
+        }
+        if (ObjectHelper.isNotEmpty(configuration.getApiVersion())) {
+            builder.withApiVersion(configuration.getApiVersion());
+        }
+        if (ObjectHelper.isNotEmpty(configuration.getClientKeyAlgo())) {
+            builder.withClientKeyAlgo(configuration.getClientKeyAlgo());
+        }
+        if (ObjectHelper.isNotEmpty(configuration.getClientKeyData())) {
+            builder.withClientKeyData(configuration.getClientKeyData());
+        }
+        if (ObjectHelper.isNotEmpty(configuration.getClientKeyFile())) {
+            builder.withClientKeyFile(configuration.getClientKeyFile());
+        }
+        if (ObjectHelper.isNotEmpty(configuration.getClientKeyPassphrase())) {
+            builder.withClientKeyPassphrase(configuration.getClientKeyPassphrase());
+        }
+        if (ObjectHelper.isNotEmpty(configuration.getTrustCerts())) {
+            builder.withTrustCerts(configuration.getTrustCerts());
+        }
+
+        Config conf = builder.build();
+        return new AutoAdaptableKubernetesClient(conf);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesDnsServiceCallExpression.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesDnsServiceCallExpression.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesDnsServiceCallExpression.java
new file mode 100644
index 0000000..d5e3751
--- /dev/null
+++ b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesDnsServiceCallExpression.java
@@ -0,0 +1,81 @@
+/**
+ * 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.Exchange;
+import org.apache.camel.support.ExpressionAdapter;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class KubernetesDnsServiceCallExpression extends ExpressionAdapter {
+
+    private static final Logger LOG = LoggerFactory.getLogger(KubernetesDnsServiceCallExpression.class);
+
+    private final String name;
+    private final String namespace;
+    private final String scheme;
+    private final String contextPath;
+    private final String uri;
+    private final String dnsDomain;
+
+    public KubernetesDnsServiceCallExpression(String name, String namespace, String scheme, String contextPath, String uri, String dnsDomain) {
+        this.name = name;
+        this.namespace = namespace;
+        this.scheme = scheme;
+        this.contextPath = contextPath;
+        this.uri = uri;
+        this.dnsDomain = dnsDomain;
+    }
+
+    @Override
+    public Object evaluate(Exchange exchange) {
+        try {
+            return buildCamelEndpointUri(name, namespace, uri, contextPath, scheme, dnsDomain);
+        } catch (Exception e) {
+            throw ObjectHelper.wrapRuntimeCamelException(e);
+        }
+    }
+
+    protected static String buildCamelEndpointUri(String name, String namespace, String uri, String contextPath, String scheme, String dnsDomain) {
+        // build basic uri if none provided
+        String answer = uri;
+        if (answer == null) {
+            if (scheme == null) {
+                // use http by default if no scheme has been configured
+                scheme = "http";
+            }
+            answer = scheme + "://" + asKubernetesDnsServicePart(name, namespace, dnsDomain);
+            if (contextPath != null) {
+                answer += "/" + contextPath;
+            }
+        } else {
+            // we have existing uri, then replace the serviceName with name.namespace.svc.dnsDomain
+            if (answer.contains(name)) {
+                answer = answer.replaceFirst(name, asKubernetesDnsServicePart(name, namespace, dnsDomain));
+            }
+        }
+
+        LOG.debug("Camel endpoint uri: {} for calling service: {}", answer, name);
+        return answer;
+    }
+
+    protected static String asKubernetesDnsServicePart(String name, String namespace, String dnsDomain) {
+        return name + "." + namespace + ".svc." + dnsDomain;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesDnsServiceCallProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesDnsServiceCallProcessor.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesDnsServiceCallProcessor.java
new file mode 100644
index 0000000..8e66086
--- /dev/null
+++ b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesDnsServiceCallProcessor.java
@@ -0,0 +1,155 @@
+/**
+ * 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.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.kubernetes.KubernetesConstants;
+import org.apache.camel.processor.SendDynamicProcessor;
+import org.apache.camel.spi.IdAware;
+import org.apache.camel.support.ServiceSupport;
+import org.apache.camel.util.AsyncProcessorHelper;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.ServiceHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Kubernetes based implementation of the the ServiceCall EIP where the service lookup is environment variable based.
+ */
+public class KubernetesDnsServiceCallProcessor extends ServiceSupport implements AsyncProcessor, CamelContextAware, Traceable, IdAware {
+
+    private static final Logger LOG = LoggerFactory.getLogger(KubernetesClientServiceCallProcessor.class);
+
+    private CamelContext camelContext;
+    private String id;
+    private final String name;
+    private final String scheme;
+    private final String contextPath;
+    private final String namespace;
+    private final String uri;
+    private final String dnsDomain;
+    private final ExchangePattern exchangePattern;
+    private final KubernetesServiceCallExpression serviceCallExpression;
+    private SendDynamicProcessor processor;
+    private String ip;
+    private long port;
+
+    public KubernetesDnsServiceCallProcessor(String name, String namespace, String scheme, String uri, ExchangePattern exchangePattern, String dnsDomain) {
+        // setup from the provided name which can contain scheme and context-path information as well
+        String serviceName;
+        if (name.contains("/")) {
+            serviceName = ObjectHelper.before(name, "/");
+            this.contextPath = ObjectHelper.after(name, "/");
+        } else if (name.contains("?")) {
+            serviceName = ObjectHelper.before(name, "?");
+            this.contextPath = ObjectHelper.after(name, "?");
+        } else {
+            serviceName = name;
+            this.contextPath = null;
+        }
+        if (serviceName.contains(":")) {
+            this.scheme = ObjectHelper.before(serviceName, ":");
+            this.name = ObjectHelper.after(serviceName, ":");
+        } else {
+            this.scheme = scheme;
+            this.name = serviceName;
+        }
+
+        // if no namespace configured then resolve from environment variables
+        if (namespace == null) {
+            this.namespace = System.getenv("KUBERNETES_NAMESPACE");
+        } else {
+            this.namespace = namespace;
+        }
+        this.uri = uri;
+        this.exchangePattern = exchangePattern;
+        this.dnsDomain = dnsDomain;
+        this.serviceCallExpression = new KubernetesServiceCallExpression(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) {
+        // use a
+
+        LOG.debug("Service {} active at server: {}:{}", name, ip, port);
+
+        // set selected server as header
+        exchange.getIn().setHeader(KubernetesConstants.KUBERNETES_SERVER_IP, ip);
+        exchange.getIn().setHeader(KubernetesConstants.KUBERNETES_SERVER_PORT, port);
+
+        // 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";
+    }
+
+    @Override
+    protected void doStart() throws Exception {
+        ObjectHelper.notEmpty(name, "name", this);
+        ObjectHelper.notEmpty(namespace, "namespace", this);
+        ObjectHelper.notEmpty(dnsDomain, "dnsDomain", this);
+
+        LOG.info("KubernetesServiceCall at namespace: {} with service name: {} using DNS domain {}", namespace, name, dnsDomain);
+
+        processor = new SendDynamicProcessor(uri, serviceCallExpression);
+        processor.setCamelContext(getCamelContext());
+        if (exchangePattern != null) {
+            processor.setPattern(exchangePattern);
+        }
+        ServiceHelper.startServices(processor);
+    }
+
+    @Override
+    protected void doStop() throws Exception {
+        ServiceHelper.stopServices(processor);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesEnvironmentServiceCallProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesEnvironmentServiceCallProcessor.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesEnvironmentServiceCallProcessor.java
new file mode 100644
index 0000000..378f19a
--- /dev/null
+++ b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesEnvironmentServiceCallProcessor.java
@@ -0,0 +1,165 @@
+/**
+ * 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 java.util.concurrent.RejectedExecutionException;
+
+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.kubernetes.KubernetesConstants;
+import org.apache.camel.processor.SendDynamicProcessor;
+import org.apache.camel.spi.IdAware;
+import org.apache.camel.support.ServiceSupport;
+import org.apache.camel.util.AsyncProcessorHelper;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.ServiceHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Kubernetes based implementation of the the ServiceCall EIP where the service lookup is environment variable based.
+ */
+public class KubernetesEnvironmentServiceCallProcessor extends ServiceSupport implements AsyncProcessor, CamelContextAware, Traceable, IdAware {
+
+    private static final Logger LOG = LoggerFactory.getLogger(KubernetesClientServiceCallProcessor.class);
+
+    private CamelContext camelContext;
+    private String id;
+    private final String name;
+    private final String scheme;
+    private final String contextPath;
+    private final String namespace;
+    private final String uri;
+    private final ExchangePattern exchangePattern;
+    private final KubernetesServiceCallExpression serviceCallExpression;
+    private SendDynamicProcessor processor;
+    private String ip;
+    private long port;
+
+    public KubernetesEnvironmentServiceCallProcessor(String name, String namespace, String scheme, String uri, ExchangePattern exchangePattern) {
+        // setup from the provided name which can contain scheme and context-path information as well
+        String serviceName;
+        if (name.contains("/")) {
+            serviceName = ObjectHelper.before(name, "/");
+            this.contextPath = ObjectHelper.after(name, "/");
+        } else if (name.contains("?")) {
+            serviceName = ObjectHelper.before(name, "?");
+            this.contextPath = ObjectHelper.after(name, "?");
+        } else {
+            serviceName = name;
+            this.contextPath = null;
+        }
+        if (serviceName.contains(":")) {
+            this.scheme = ObjectHelper.before(serviceName, ":");
+            this.name = ObjectHelper.after(serviceName, ":");
+        } else {
+            this.scheme = scheme;
+            this.name = serviceName;
+        }
+
+        // if no namespace configured then resolve from environment variables
+        if (namespace == null) {
+            this.namespace = System.getenv("KUBERNETES_NAMESPACE");
+        } else {
+            this.namespace = namespace;
+        }
+        this.uri = uri;
+        this.exchangePattern = exchangePattern;
+        this.serviceCallExpression = new KubernetesServiceCallExpression(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) {
+        if (ip == null) {
+            exchange.setException(new RejectedExecutionException("No active services with name " + name + " in namespace " + namespace));
+        }
+        if (exchange.getException() != null) {
+            callback.done(true);
+            return true;
+        }
+
+        LOG.debug("Service {} active at server: {}:{}", name, ip, port);
+
+        // set selected server as header
+        exchange.getIn().setHeader(KubernetesConstants.KUBERNETES_SERVER_IP, ip);
+        exchange.getIn().setHeader(KubernetesConstants.KUBERNETES_SERVER_PORT, port);
+
+        // 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";
+    }
+
+    @Override
+    protected void doStart() throws Exception {
+        // lookup ENV on startup
+        ip = getCamelContext().resolvePropertyPlaceholders("{{service.host:" + name + "}}");
+        String num = getCamelContext().resolvePropertyPlaceholders("{{service.port:" + name + "}}");
+        port = getCamelContext().getTypeConverter().tryConvertTo(long.class, num);
+
+        ObjectHelper.notEmpty(name, "name", this);
+        ObjectHelper.notEmpty(namespace, "namespace", this);
+
+        LOG.info("KubernetesServiceCall at namespace: {} with service name: {} using {}:{}", namespace, name, ip, port);
+
+        processor = new SendDynamicProcessor(uri, serviceCallExpression);
+        processor.setCamelContext(getCamelContext());
+        if (exchangePattern != null) {
+            processor.setPattern(exchangePattern);
+        }
+        ServiceHelper.startServices(processor);
+    }
+
+    @Override
+    protected void doStop() throws Exception {
+        ServiceHelper.stopServices(processor);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesProcessorFactory.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesProcessorFactory.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesProcessorFactory.java
new file mode 100644
index 0000000..8c1324c
--- /dev/null
+++ b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesProcessorFactory.java
@@ -0,0 +1,208 @@
+/**
+ * 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 java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.Processor;
+import org.apache.camel.component.kubernetes.KubernetesConfiguration;
+import org.apache.camel.model.ProcessorDefinition;
+import org.apache.camel.model.remote.KubernetesConfigurationDefinition;
+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.ServiceCallLoadBalancer;
+import org.apache.camel.spi.ServiceCallServerListStrategy;
+import org.apache.camel.util.CamelContextHelper;
+import org.apache.camel.util.IntrospectionSupport;
+
+/**
+ * {@link ProcessorFactory} that creates the Kubernetes implementation of the ServiceCall EIP.
+ */
+public class KubernetesProcessorFactory implements ProcessorFactory {
+
+    @Override
+    public Processor createChildProcessor(RouteContext routeContext, ProcessorDefinition<?> definition, boolean mandatory) throws Exception {
+        // not in use
+        return null;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public Processor createProcessor(RouteContext routeContext, ProcessorDefinition<?> definition) throws Exception {
+        if (definition instanceof ServiceCallDefinition) {
+            ServiceCallDefinition sc = (ServiceCallDefinition) definition;
+
+            String name = sc.getName();
+            String uri = sc.getUri();
+            ExchangePattern mep = sc.getPattern();
+
+            KubernetesConfigurationDefinition config = (KubernetesConfigurationDefinition) sc.getServiceCallConfiguration();
+            KubernetesConfigurationDefinition configRef = null;
+            if (sc.getServiceCallConfigurationRef() != null) {
+                // lookup in registry first
+                configRef = CamelContextHelper.lookup(routeContext.getCamelContext(), sc.getServiceCallConfigurationRef(), KubernetesConfigurationDefinition.class);
+                if (configRef == null) {
+                    // and fallback as service configuration
+                    routeContext.getCamelContext().getServiceCallConfiguration(sc.getServiceCallConfigurationRef(), KubernetesConfigurationDefinition.class);
+                }
+            }
+
+            // if no configuration explicit configured then use default
+            if (config == null && configRef == null) {
+                config = routeContext.getCamelContext().getServiceCallConfiguration(null, KubernetesConfigurationDefinition.class);
+            }
+            if (config == null) {
+                // if no default then try to find if there configuration in the registry of the given type
+                Set<KubernetesConfigurationDefinition> set = routeContext.getCamelContext().getRegistry().findByType(KubernetesConfigurationDefinition.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
+            KubernetesConfiguration kc = new KubernetesConfiguration();
+            IntrospectionSupport.setProperties(kc, parameters);
+
+            // use namespace from config
+            String namespace = kc.getNamespace();
+
+            // lookup the load balancer to use (configured on EIP takes precedence vs configured on configuration)
+            ServiceCallLoadBalancer lb = configureLoadBalancer(routeContext, sc);
+            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, sc);
+            if (sl == null && config != null) {
+                sl = configureServerListStrategy(routeContext, config);
+            }
+            if (sl == null && configRef != null) {
+                sl = configureServerListStrategy(routeContext, configRef);
+            }
+
+            String lookup = config != null ? config.getLookup() : null;
+            if (lookup == null && configRef != null) {
+                lookup = configRef.getLookup();
+            }
+
+            // the component is used to configure what the default scheme to use (eg camel component name)
+            String component = config != null ? config.getComponent() : null;
+            if (component == null && configRef != null) {
+                component = configRef.getComponent();
+            }
+
+            if ("client".equals(lookup)) {
+                KubernetesClientServiceCallProcessor processor = new KubernetesClientServiceCallProcessor(name, namespace, component, uri, mep, kc);
+                processor.setLoadBalancer(lb);
+                processor.setServerListStrategy(sl);
+                return processor;
+            } else if ("dns".equals(lookup)) {
+                String dnsDomain = config != null ? config.getDnsDomain() : null;
+                if (dnsDomain == null && configRef != null) {
+                    dnsDomain = configRef.getDnsDomain();
+                }
+                return new KubernetesDnsServiceCallProcessor(name, namespace, component, uri, mep, dnsDomain);
+            } else {
+                // environment is default
+                return new KubernetesEnvironmentServiceCallProcessor(name, namespace, component, uri, mep);
+            }
+        } else {
+            return null;
+        }
+    }
+
+    private ServiceCallLoadBalancer configureLoadBalancer(RouteContext routeContext, ServiceCallDefinition sd) {
+        ServiceCallLoadBalancer lb = null;
+
+        if (sd != null) {
+            lb = sd.getLoadBalancer();
+            if (lb == null && sd.getLoadBalancerRef() != null) {
+                String ref = sd.getLoadBalancerRef();
+                // special for ref is referring to built-in
+                if ("random".equalsIgnoreCase(ref)) {
+                    lb = new RandomLoadBalancer();
+                } else if ("roundrobin".equalsIgnoreCase(ref)) {
+                    lb = new RoundRobinBalancer();
+                } else {
+                    lb = CamelContextHelper.mandatoryLookup(routeContext.getCamelContext(), ref, ServiceCallLoadBalancer.class);
+                }
+            }
+        }
+
+        return lb;
+    }
+
+    private ServiceCallLoadBalancer configureLoadBalancer(RouteContext routeContext, ServiceCallConfigurationDefinition config) {
+        ServiceCallLoadBalancer lb = config.getLoadBalancer();
+        if (lb == null && config.getLoadBalancerRef() != null) {
+            String ref = config.getLoadBalancerRef();
+            // special for ref is referring to built-in
+            if ("random".equalsIgnoreCase(ref)) {
+                lb = new RandomLoadBalancer();
+            } else if ("roundrobin".equalsIgnoreCase(ref)) {
+                lb = new RoundRobinBalancer();
+            } else {
+                lb = CamelContextHelper.mandatoryLookup(routeContext.getCamelContext(), ref, ServiceCallLoadBalancer.class);
+            }
+        }
+        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/4b81b4ae/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesServer.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesServer.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesServer.java
new file mode 100644
index 0000000..007e5c8
--- /dev/null
+++ b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesServer.java
@@ -0,0 +1,41 @@
+/**
+ * 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.spi.ServiceCallServer;
+
+/**
+ * Represents a model of a kubernetes server.
+ */
+public final class KubernetesServer implements ServiceCallServer {
+
+    private final String ip;
+    private final int port;
+
+    public KubernetesServer(String ip, int port) {
+        this.ip = ip;
+        this.port = port;
+    }
+
+    public String getIp() {
+        return ip;
+    }
+
+    public int getPort() {
+        return port;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesServiceCallExpression.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesServiceCallExpression.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesServiceCallExpression.java
new file mode 100644
index 0000000..dcb770f
--- /dev/null
+++ b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesServiceCallExpression.java
@@ -0,0 +1,40 @@
+/**
+ * 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.Exchange;
+import org.apache.camel.component.kubernetes.KubernetesConstants;
+import org.apache.camel.support.ServiceCallExpressionSupport;
+import org.apache.camel.util.ExchangeHelper;
+
+public class KubernetesServiceCallExpression extends ServiceCallExpressionSupport {
+
+    public KubernetesServiceCallExpression(String name, String scheme, String contextPath, String uri) {
+        super(name, scheme, contextPath, uri);
+    }
+
+    @Override
+    public String getIp(Exchange exchange) throws Exception {
+        return ExchangeHelper.getMandatoryHeader(exchange, KubernetesConstants.KUBERNETES_SERVER_IP, String.class);
+    }
+
+    @Override
+    public int getPort(Exchange exchange) throws Exception {
+        return ExchangeHelper.getMandatoryHeader(exchange, KubernetesConstants.KUBERNETES_SERVER_PORT, int.class);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesServiceCallServerListStrategy.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesServiceCallServerListStrategy.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesServiceCallServerListStrategy.java
new file mode 100644
index 0000000..f35cfed
--- /dev/null
+++ b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/KubernetesServiceCallServerListStrategy.java
@@ -0,0 +1,106 @@
+/**
+ * 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 java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import io.fabric8.kubernetes.api.model.EndpointAddress;
+import io.fabric8.kubernetes.api.model.EndpointPort;
+import io.fabric8.kubernetes.api.model.EndpointSubset;
+import io.fabric8.kubernetes.api.model.Endpoints;
+import io.fabric8.kubernetes.client.AutoAdaptableKubernetesClient;
+import org.apache.camel.spi.ServiceCallServerListStrategy;
+import org.apache.camel.support.ServiceSupport;
+import org.apache.camel.util.IOHelper;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Discovers where services are running on which servers in Kubernetes.
+ */
+public class KubernetesServiceCallServerListStrategy extends ServiceSupport implements ServiceCallServerListStrategy<KubernetesServer> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(KubernetesServiceCallServerListStrategy.class);
+    private static final int FIRST = 0;
+
+    private String name;
+    private String namespace;
+    private String portName;
+    private AutoAdaptableKubernetesClient client;
+
+    public KubernetesServiceCallServerListStrategy(String name, String namespace, String portName, AutoAdaptableKubernetesClient client) {
+        this.name = name;
+        this.namespace = namespace;
+        this.portName = portName;
+        this.client = client;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public Collection<KubernetesServer> getInitialListOfServers() {
+        return Collections.EMPTY_LIST;
+    }
+
+    public Collection<KubernetesServer> getUpdatedListOfServers() {
+        LOG.debug("Discovering endpoints from namespace: {} with name: {}", namespace, name);
+        Endpoints endpoints = client.endpoints().inNamespace(namespace).withName(name).get();
+        List<KubernetesServer> result = new ArrayList<>();
+        if (endpoints != null) {
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("Found {} endpoints in namespace: {} for name: {} and portName: {}", endpoints.getSubsets().size(), namespace, name, portName);
+            }
+            for (EndpointSubset subset : endpoints.getSubsets()) {
+                if (subset.getPorts().size() == 1) {
+                    EndpointPort port = subset.getPorts().get(FIRST);
+                    for (EndpointAddress address : subset.getAddresses()) {
+                        result.add(new KubernetesServer(address.getIp(), port.getPort()));
+                    }
+                } else {
+                    for (EndpointPort port : subset.getPorts()) {
+                        if (ObjectHelper.isEmpty(portName) || portName.endsWith(port.getName())) {
+                            for (EndpointAddress address : subset.getAddresses()) {
+                                result.add(new KubernetesServer(address.getIp(), port.getPort()));
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        return result;
+    }
+
+    @Override
+    protected void doStart() throws Exception {
+        // noop
+    }
+
+    @Override
+    protected void doStop() throws Exception {
+        if (client != null) {
+            IOHelper.close(client);
+        }
+    }
+
+    public String toString() {
+        return "KubernetesServiceDiscovery";
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/RandomLoadBalancer.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/RandomLoadBalancer.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/RandomLoadBalancer.java
new file mode 100644
index 0000000..1b55e75
--- /dev/null
+++ b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/RandomLoadBalancer.java
@@ -0,0 +1,40 @@
+/**
+ * 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 java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Random;
+
+import org.apache.camel.spi.ServiceCallLoadBalancer;
+
+public class RandomLoadBalancer implements ServiceCallLoadBalancer<KubernetesServer> {
+
+    @Override
+    public KubernetesServer chooseServer(Collection<KubernetesServer> servers) {
+        List<KubernetesServer> list = new ArrayList<>(servers);
+        int size = list.size();
+        int ran = new Random().nextInt(size);
+        return list.get(ran);
+    }
+
+    @Override
+    public String toString() {
+        return "RandomLoadBalancer";
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/RoundRobinBalancer.java
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/RoundRobinBalancer.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/RoundRobinBalancer.java
new file mode 100644
index 0000000..1cfa86d
--- /dev/null
+++ b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/processor/RoundRobinBalancer.java
@@ -0,0 +1,44 @@
+/**
+ * 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 java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.camel.spi.ServiceCallLoadBalancer;
+
+public class RoundRobinBalancer implements ServiceCallLoadBalancer<KubernetesServer> {
+
+    private int counter = -1;
+
+    @Override
+    public KubernetesServer chooseServer(Collection<KubernetesServer> servers) {
+        List<KubernetesServer> list = new ArrayList<>(servers);
+
+        int size = list.size();
+        if (++counter >= size) {
+            counter = 0;
+        }
+        return list.get(counter);
+    }
+
+    @Override
+    public String toString() {
+        return "RoundRobinBalancer";
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/components/camel-kubernetes/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition b/components/camel-kubernetes/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition
new file mode 100644
index 0000000..acf5be8
--- /dev/null
+++ b/components/camel-kubernetes/src/main/resources/META-INF/services/org/apache/camel/model/ServiceCallDefinition
@@ -0,0 +1,18 @@
+#
+# 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.kubernetes.processor.KubernetesProcessorFactory

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/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
new file mode 100644
index 0000000..b5e03e3
--- /dev/null
+++ b/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/ServiceCallClientRouteTest.java
@@ -0,0 +1,62 @@
+/**
+ * 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/4b81b4ae/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
new file mode 100644
index 0000000..9278b57
--- /dev/null
+++ b/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/ServiceCallEnvironmentRouteTest.java
@@ -0,0 +1,57 @@
+/**
+ * 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.impl.JndiRegistry;
+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/4b81b4ae/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
new file mode 100644
index 0000000..3e8fcba3
--- /dev/null
+++ b/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/SpringServiceCallClientRouteTest.java
@@ -0,0 +1,41 @@
+/**
+ * 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/4b81b4ae/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
new file mode 100644
index 0000000..bd09c31
--- /dev/null
+++ b/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/processor/SpringServiceCallEnvironmentRouteTest.java
@@ -0,0 +1,41 @@
+/**
+ * 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/4b81b4ae/components/camel-kubernetes/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/components/camel-kubernetes/src/test/resources/log4j.properties b/components/camel-kubernetes/src/test/resources/log4j.properties
index 255fe5c..f88e05c 100644
--- a/components/camel-kubernetes/src/test/resources/log4j.properties
+++ b/components/camel-kubernetes/src/test/resources/log4j.properties
@@ -20,7 +20,7 @@
 #
 log4j.rootLogger=INFO, file
 
-#log4j.logger.org.apache.camel=DEBUG
+log4j.logger.org.apache.camel.component.kubernetes=DEBUG
 
 # CONSOLE appender not used by default
 log4j.appender.out=org.apache.log4j.ConsoleAppender

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/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
new file mode 100644
index 0000000..87162d9
--- /dev/null
+++ b/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/processor/SpringServiceCallClientRouteTest.xml
@@ -0,0 +1,39 @@
+<?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/4b81b4ae/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
new file mode 100644
index 0000000..6f2f028
--- /dev/null
+++ b/components/camel-kubernetes/src/test/resources/org/apache/camel/component/kubernetes/processor/SpringServiceCallEnvironmentRouteTest.xml
@@ -0,0 +1,38 @@
+<?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/4b81b4ae/components/camel-ribbon/pom.xml
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/pom.xml b/components/camel-ribbon/pom.xml
new file mode 100644
index 0000000..94f68fe
--- /dev/null
+++ b/components/camel-ribbon/pom.xml
@@ -0,0 +1,89 @@
+<?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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.camel</groupId>
+    <artifactId>components</artifactId>
+    <version>2.18-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>camel-ribbon</artifactId>
+  <packaging>jar</packaging>
+  <name>Camel :: Ribbon</name>
+
+  <properties>
+    <camel.osgi.export.pkg>org.apache.camel.component.ribbon.*</camel.osgi.export.pkg>
+  </properties>
+
+  <dependencies>
+
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-core</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>com.netflix.ribbon</groupId>
+      <artifactId>ribbon-core</artifactId>
+      <version>${ribbon-version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.netflix.ribbon</groupId>
+      <artifactId>ribbon-loadbalancer</artifactId>
+      <version>${ribbon-version}</version>
+    </dependency>
+
+    <!-- testing -->
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-test-spring</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-http</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-jetty</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <!-- logging -->
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-log4j12</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>log4j</groupId>
+      <artifactId>log4j</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+</project>

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/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
new file mode 100644
index 0000000..4931a5b
--- /dev/null
+++ b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/RibbonConfiguration.java
@@ -0,0 +1,69 @@
+/**
+ * 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;
+
+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;
+
+    public String getNamespace() {
+        return namespace;
+    }
+
+    public void setNamespace(String namespace) {
+        this.namespace = namespace;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    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;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/4b81b4ae/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/RibbonConstants.java
----------------------------------------------------------------------
diff --git a/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/RibbonConstants.java b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/RibbonConstants.java
new file mode 100644
index 0000000..705d69f
--- /dev/null
+++ b/components/camel-ribbon/src/main/java/org/apache/camel/component/ribbon/RibbonConstants.java
@@ -0,0 +1,25 @@
+/**
+ * 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;
+
+public interface RibbonConstants {
+
+    // Service Call EIP
+    String RIBBON_SERVER_IP = "CamelRibbonServerIp";
+    String RIBBON_SERVER_PORT = "CamelRibbonServerPort";
+
+}