You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by as...@apache.org on 2016/08/22 19:38:30 UTC

camel git commit: Camel CDI Kubernetes example improvements

Repository: camel
Updated Branches:
  refs/heads/master 5b873ffba -> cf03bfbc0


Camel CDI Kubernetes example improvements

- Add onException handler to deal with KubernetesClientException
- Enable to fallback on KUBERNETES_MASTER environment variable to discover Kubernetes master
- Enable to fallback on the current login token when the oauthToken is empty
- Format output to emulate that of 'kubectl get pods' command
- Remove dependency on DeltaSpike


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

Branch: refs/heads/master
Commit: cf03bfbc0cba6645d02af338536eb520bc28029a
Parents: 5b873ff
Author: Antonin Stefanutti <an...@stefanutti.fr>
Authored: Mon Aug 22 21:34:59 2016 +0200
Committer: Antonin Stefanutti <an...@stefanutti.fr>
Committed: Mon Aug 22 21:34:59 2016 +0200

----------------------------------------------------------------------
 examples/camel-example-cdi-kubernetes/README.md | 55 ++++++++------
 examples/camel-example-cdi-kubernetes/pom.xml   | 13 ----
 .../example/cdi/kubernetes/Application.java     | 80 ++++++++++++--------
 .../META-INF/apache-deltaspike.properties       | 18 -----
 .../src/main/resources/application.properties   | 24 ++++++
 5 files changed, 106 insertions(+), 84 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/cf03bfbc/examples/camel-example-cdi-kubernetes/README.md
----------------------------------------------------------------------
diff --git a/examples/camel-example-cdi-kubernetes/README.md b/examples/camel-example-cdi-kubernetes/README.md
index ebad46d..09dce01 100644
--- a/examples/camel-example-cdi-kubernetes/README.md
+++ b/examples/camel-example-cdi-kubernetes/README.md
@@ -4,19 +4,27 @@
 
 This example illustrates the integration between Camel, CDI and Kubernetes.
 
-The example get the list of pods from a Kubernetes cluster and print name and status of each one of the pods returned.
+The example gets the list of pods from a Kubernetes cluster and emulates
+the output of the `kubectl get pods` command.
 
-The `camel-cdi`, `camel-core` and `camel-kubernetes` components are used in this example.
+The `camel-cdi` and `camel-kubernetes` components are used in this example.
 The example assumes you have a running Kubernetes cluster in your environment. 
-For example you can use [minikube](https://github.com/kubernetes/minikube) or the [vagrant openshift image](https://github.com/fabric8io/fabric8-installer/tree/master/vagrant/openshift) from [Fabric8 Team](http://fabric8.io/).
-Remember to edit the apache-deltaspike.properties file to use the correct Kubernetes Master URL and OAuth token for your environment.
+For example you can use [minikube](https://github.com/kubernetes/minikube)
+or the [vagrant openshift image](https://github.com/fabric8io/fabric8-installer/tree/master/vagrant/openshift) from
+[Fabric8 team](http://fabric8.io/).
+
+By default, the example use the `KUBERNETES_MASTER` environment variable
+to retrieve the Kubernetes master URL. Besides, it tries to find the current
+login token and namespace by parsing the users `~/.kube/config` file.
+However, you can edit the `application.properties` file to override the default
+and provide the Kubernetes master URL and OAuth token for your environment.
 
 ### Build
 
-You will need to build this example first:
+You can build this example using:
 
 ```sh
-$ mvn install
+$ mvn package
 ```
 
 ### Run
@@ -24,28 +32,29 @@ $ mvn install
 You can run this example using:
 
 ```sh
-$ mvn compile camel:run
+$ mvn camel:run
 ```
 
-When the Camel application runs, you should see the Pods name and status. For example:
+When the Camel application runs, you should see the pods list being logged
+periodically, e.g.:
 ```
-We currently have 13 pods
-Pod name docker-registry-1-c6ie5 with status Running
-Pod name fabric8-docker-registry-pgo5y with status Running
-Pod name fabric8-forge-wvyw7 with status Running
-Pod name fabric8-tr0b9 with status Running
-Pod name gogs-2p4mn with status Running
-Pod name grafana-754y7 with status Running
-Pod name infinispan-client-a7z3k with status Running
-Pod name infinispan-client-iubag with status Running
-Pod name infinispan-server-wl0in with status Running
-Pod name jenkins-cr2ez with status Running
-Pod name nexus-aarks with status Running
-Pod name prometheus-mp0kr with status Running
-Pod name router-1-dkjsb with status Running
+2016-08-22 18:29:46,449 [ timer://client] INFO kubernetes-client - We currently have 11 pods:
+NAME                                READY     STATUS    RESTARTS   AGE
+content-repository-yhg9u            1/1       Running   34         49d
+docker-registry-1-bv5vk             1/1       Running   34         49d
+fabric8-docker-registry-9jd9z       1/1       Running   34         49d
+fabric8-forge-8gnro                 1/1       Running   11         17d
+fabric8-kw532                       1/1       Running   34         49d
+gogs-2exwf                          1/1       Running   22         32d
+jenkins-kixdv                       1/1       Running   12         18d
+mysql-5-f8trz                       1/1       Running   8          13d
+nexus-5j60s                         1/1       Running   71         49d
+router-1-7eiu5                      2/2       Running   26         49d
+spring-boot-camel-rest-s-13-559vm   1/1       Running   0          6h
+
 ```
 
-The timer has a repeatCount option equals to 3. So you should see this output 3 times.
+The timer has a `period` option equals to `10s`.
 
 The Camel application can be stopped pressing <kbd>ctrl</kbd>+<kbd>c</kbd> in the shell.
 

http://git-wip-us.apache.org/repos/asf/camel/blob/cf03bfbc/examples/camel-example-cdi-kubernetes/pom.xml
----------------------------------------------------------------------
diff --git a/examples/camel-example-cdi-kubernetes/pom.xml b/examples/camel-example-cdi-kubernetes/pom.xml
index d25dc00..bf4ecc2 100755
--- a/examples/camel-example-cdi-kubernetes/pom.xml
+++ b/examples/camel-example-cdi-kubernetes/pom.xml
@@ -51,19 +51,6 @@
       <artifactId>camel-kubernetes</artifactId>
     </dependency>
 
-    <!-- DeltaSpike -->
-    <dependency>
-      <groupId>org.apache.deltaspike.core</groupId>
-      <artifactId>deltaspike-core-api</artifactId>
-      <version>${deltaspike-version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.deltaspike.core</groupId>
-      <artifactId>deltaspike-core-impl</artifactId>
-      <version>${deltaspike-version}</version>
-      <scope>runtime</scope>
-    </dependency>
-    
     <!-- logging -->
     <dependency>
       <groupId>org.apache.logging.log4j</groupId>

http://git-wip-us.apache.org/repos/asf/camel/blob/cf03bfbc/examples/camel-example-cdi-kubernetes/src/main/java/org/apache/camel/example/cdi/kubernetes/Application.java
----------------------------------------------------------------------
diff --git a/examples/camel-example-cdi-kubernetes/src/main/java/org/apache/camel/example/cdi/kubernetes/Application.java b/examples/camel-example-cdi-kubernetes/src/main/java/org/apache/camel/example/cdi/kubernetes/Application.java
index d3fca08..dfeaafd 100644
--- a/examples/camel-example-cdi-kubernetes/src/main/java/org/apache/camel/example/cdi/kubernetes/Application.java
+++ b/examples/camel-example-cdi-kubernetes/src/main/java/org/apache/camel/example/cdi/kubernetes/Application.java
@@ -16,25 +16,27 @@
  */
 package org.apache.camel.example.cdi.kubernetes;
 
-import java.util.Iterator;
+import java.time.Duration;
+import java.time.ZonedDateTime;
 import java.util.List;
-import java.util.Properties;
-
 import javax.enterprise.context.ApplicationScoped;
 import javax.enterprise.inject.Produces;
 import javax.inject.Named;
 
+import io.fabric8.kubernetes.api.model.ContainerStatus;
 import io.fabric8.kubernetes.api.model.Pod;
-
+import io.fabric8.kubernetes.client.KubernetesClientException;
+import org.apache.camel.LoggingLevel;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.cdi.ContextName;
-import org.apache.camel.component.properties.DefaultPropertiesParser;
 import org.apache.camel.component.properties.PropertiesComponent;
-import org.apache.camel.component.properties.PropertiesParser;
-import org.apache.deltaspike.core.api.config.ConfigResolver;
 
 /**
- * Example application
+ * This example periodically polls the list of pods that are deployed to the
+ * configured Kubernetes cluster.
+ *
+ * It relies on the Camel Kubernetes component and emulates the output of the
+ * {@code kubectl get pods} command.
  */
 public class Application {
 
@@ -43,37 +45,55 @@ public class Application {
 
         @Override
         public void configure() {
-            from("timer:stream?repeatCount=3")
-                .to("kubernetes://{{kubernetes-master-url}}?oauthToken={{kubernetes-oauth-token}}&category=pods&operation=listPods")
+            from("timer:client?period=10s").routeId("kubernetes-client")
+                .onException(KubernetesClientException.class).handled(true)
+                    .log(LoggingLevel.ERROR, "${exception.message}")
+                    .log("Stopping the Kubernetes route...")
+                    // Let's stop the route (we may want to implement a way to exit the container)
+                    .to("controlbus:route?routeId=kubernetes-client&action=stop&async=true&loggingLevel=DEBUG")
+                    .end()
+                .to("kubernetes://{{kubernetes-master-url:{{env:KUBERNETES_MASTER}}}}?oauthToken={{kubernetes-oauth-token:}}&category=pods&operation=listPods")
+                .log("We currently have ${body.size()} pods:")
                 .process(exchange -> {
-                    List<Pod> list = exchange.getIn().getBody(List.class);
-                    System.out.println("We currently have " + list.size() + " pods");
-                    Iterator<Pod> it = list.iterator();
-                    while (it.hasNext()) {
-                        Pod pod = it.next();
-                        System.out.println("Pod name " + pod.getMetadata().getName() + " with status " + pod.getStatus().getPhase());
-                    }
+                    List<Pod> pods = exchange.getIn().getBody(List.class);
+                    // Compute the length of the longer pod name
+                    String tty = "%-" + (pods.stream().mapToInt(pod -> pod.getMetadata().getName().length()).max().orElse(30) + 2) + "s %-9s %-9s %-10s %s";
+                    // Emulates the output of 'kubectl get pods'
+                    System.out.println(String.format(tty, "NAME", "READY", "STATUS", "RESTARTS", "AGE"));
+                    pods.stream()
+                        .map(pod -> String.format(tty, pod.getMetadata().getName(),
+                            pod.getStatus().getContainerStatuses().stream()
+                                .filter(ContainerStatus::getReady)
+                                .count() + "/" + pod.getStatus().getContainerStatuses().size(),
+                            pod.getStatus().getPhase(),
+                            pod.getStatus().getContainerStatuses().stream()
+                                .mapToInt(ContainerStatus::getRestartCount).sum(),
+                            formatDuration(Duration.between(ZonedDateTime.parse(pod.getStatus().getStartTime()), ZonedDateTime.now()))))
+                        .forEach(System.out::println);
                 });
         }
     }
-    
+
+    // Let's format duration the kubectl way!
+    static String formatDuration(Duration duration) {
+        if (Duration.ofDays(1).compareTo(duration) < 0) {
+            return duration.toDays() + "d";
+        } else if (Duration.ofHours(1).compareTo(duration) < 0) {
+            return duration.toHours() + "h";
+        } else if (Duration.ofMinutes(1).compareTo(duration) < 0) {
+            return duration.toMinutes() + "m";
+        } else {
+            return duration.getSeconds() + "s";
+        }
+    }
+
     @Produces
     @ApplicationScoped
     @Named("properties")
     // "properties" component bean that Camel uses to lookup properties
-    PropertiesComponent properties(PropertiesParser parser) {
+    PropertiesComponent properties() {
         PropertiesComponent component = new PropertiesComponent();
-        // Use DeltaSpike as configuration source for Camel CDI
-        component.setPropertiesParser(parser);
+        component.setLocation("classpath:application.properties");
         return component;
     }
-
-    // PropertiesParser bean that uses DeltaSpike to resolve properties
-    static class DeltaSpikeParser extends DefaultPropertiesParser {
-
-        @Override
-        public String parseProperty(String key, String value, Properties properties) {
-            return ConfigResolver.getPropertyValue(key);
-        }
-    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/cf03bfbc/examples/camel-example-cdi-kubernetes/src/main/resources/META-INF/apache-deltaspike.properties
----------------------------------------------------------------------
diff --git a/examples/camel-example-cdi-kubernetes/src/main/resources/META-INF/apache-deltaspike.properties b/examples/camel-example-cdi-kubernetes/src/main/resources/META-INF/apache-deltaspike.properties
deleted file mode 100644
index f08b386..0000000
--- a/examples/camel-example-cdi-kubernetes/src/main/resources/META-INF/apache-deltaspike.properties
+++ /dev/null
@@ -1,18 +0,0 @@
-## ---------------------------------------------------------------------------
-## Licensed to the Apache Software Foundation (ASF) under one or more
-## contributor license agreements.  See the NOTICE file distributed with
-## this work for additional information regarding copyright ownership.
-## The ASF licenses this file to You under the Apache License, Version 2.0
-## (the "License"); you may not use this file except in compliance with
-## the License.  You may obtain a copy of the License at
-## 
-## http://www.apache.org/licenses/LICENSE-2.0
-## 
-## Unless required by applicable law or agreed to in writing, software
-## distributed under the License is distributed on an "AS IS" BASIS,
-## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-## See the License for the specific language governing permissions and
-## limitations under the License.
-## ------------------------------------------------------------------------
-kubernetes-master-url=https://172.28.128.4:8443
-kubernetes-oauth-token=XXxnZi2YghQyke-eARXBZ38K-p5zIpco0ShdzO8gK6U
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/cf03bfbc/examples/camel-example-cdi-kubernetes/src/main/resources/application.properties
----------------------------------------------------------------------
diff --git a/examples/camel-example-cdi-kubernetes/src/main/resources/application.properties b/examples/camel-example-cdi-kubernetes/src/main/resources/application.properties
new file mode 100644
index 0000000..05b680a
--- /dev/null
+++ b/examples/camel-example-cdi-kubernetes/src/main/resources/application.properties
@@ -0,0 +1,24 @@
+## ---------------------------------------------------------------------------
+## 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 URL of the Kubernetes master, falls back to the KUBERNETES_MASTER
+# environment variable
+#kubernetes-master-url=
+
+# The OAuth authorization token, falls back to the current login token
+# and namespace by parsing the users ~/.kube/config file.
+#kubernetes-oauth-token=