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 2022/04/15 15:21:39 UTC

[camel] branch main updated: CAMEL-17261: camel-jbang - Bind goal

This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 43269cb306d CAMEL-17261: camel-jbang - Bind goal
43269cb306d is described below

commit 43269cb306d4c3590679b5fee9c8821bbe66d664
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Fri Apr 15 17:21:17 2022 +0200

    CAMEL-17261: camel-jbang - Bind goal
---
 .../apache/camel/dsl/jbang/core/commands/Bind.java | 155 +++++++++++++++++++++
 .../dsl/jbang/core/commands/CamelJBangMain.java    |   1 +
 .../templates/binding-kamelet-kamelet.yaml.tmpl    |  17 +++
 .../templates/binding-kamelet-uri.yaml.tmpl        |  15 ++
 .../templates/binding-uri-kamelet.yaml.tmpl        |  15 ++
 .../resources/templates/binding-uri-uri.yaml.tmpl  |  13 ++
 6 files changed, 216 insertions(+)

diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Bind.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Bind.java
new file mode 100644
index 00000000000..f306b09a2d4
--- /dev/null
+++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Bind.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.dsl.jbang.core.commands;
+
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.concurrent.Callable;
+
+import org.apache.camel.github.GitHubResourceResolver;
+import org.apache.camel.util.FileUtil;
+import org.apache.camel.util.IOHelper;
+import org.snakeyaml.engine.v2.api.LoadSettings;
+import org.snakeyaml.engine.v2.api.YamlUnicodeReader;
+import org.snakeyaml.engine.v2.composer.Composer;
+import org.snakeyaml.engine.v2.nodes.Node;
+import org.snakeyaml.engine.v2.parser.Parser;
+import org.snakeyaml.engine.v2.parser.ParserImpl;
+import org.snakeyaml.engine.v2.scanner.StreamReader;
+import picocli.CommandLine;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
+
+import static org.apache.camel.dsl.yaml.common.YamlDeserializerSupport.asStringSet;
+import static org.apache.camel.dsl.yaml.common.YamlDeserializerSupport.asText;
+import static org.apache.camel.dsl.yaml.common.YamlDeserializerSupport.nodeAt;
+
+@Command(name = "bind", description = "Bind Kubernetes resources, such as Kamelets, in an integration flow")
+class Bind implements Callable<Integer> {
+
+    @CommandLine.Parameters(description = "Source such as a Kamelet or Camel endpoint uri", arity = "1")
+    private String source;
+
+    @CommandLine.Parameters(description = "Sink such as a Kamelet or Camel endpoint uri", arity = "1")
+    private String sink;
+
+    @CommandLine.Parameters(description = "Name of binding file", arity = "1")
+    private String file;
+
+    //CHECKSTYLE:OFF
+    @Option(names = { "-h", "--help" }, usageHelp = true, description = "Display the help and sub-commands")
+    private boolean helpRequested = false;
+    //CHECKSTYLE:ON
+
+    @Override
+    public Integer call() throws Exception {
+        // the kamelet binding source and sink can either be a kamelet or an uri
+        String in = "kamelet";
+        String out = "kamelet";
+        if (source.contains(":")) {
+            in = "uri";
+        }
+        if (sink.contains(":")) {
+            out = "uri";
+        }
+
+        InputStream is = Bind.class.getClassLoader().getResourceAsStream("templates/binding-" + in + "-" + out + ".yaml.tmpl");
+        String context = IOHelper.loadText(is);
+        IOHelper.close(is);
+
+        String name = FileUtil.onlyName(file, false);
+        context = context.replaceFirst("\\{\\{ \\.Name }}", name);
+        context = context.replaceFirst("\\{\\{ \\.Source }}", source);
+        context = context.replaceFirst("\\{\\{ \\.Sink }}", sink);
+
+        if ("kamelet".equals(in)) {
+            String props = kameletProperties(source);
+            context = context.replaceFirst("\\{\\{ \\.SourceProperties }}", props);
+        }
+        if ("kamelet".equals(out)) {
+            String props = kameletProperties(sink);
+            context = context.replaceFirst("\\{\\{ \\.SinkProperties }}", props);
+        }
+
+        IOHelper.writeText(context, new FileOutputStream(file, false));
+        return 0;
+    }
+
+    protected String kameletProperties(String kamelet) throws Exception {
+        StringBuilder sb = new StringBuilder();
+
+        String loc = new GitHubResourceResolver()
+                .resolve(
+                        "github:apache:camel-kamelets:main:kamelets/" + kamelet + ".kamelet.yaml")
+                .getLocation();
+        if (loc != null) {
+            try {
+                InputStream is = new URL(loc).openStream();
+                LoadSettings local = LoadSettings.builder().setLabel(loc).build();
+                final StreamReader reader = new StreamReader(local, new YamlUnicodeReader(is));
+                final Parser parser = new ParserImpl(local, reader);
+                final Composer composer = new Composer(local, parser);
+                Node root = composer.getSingleNode().orElse(null);
+                if (root != null) {
+                    Set<String> required = asStringSet(nodeAt(root, "/spec/definition/required"));
+                    if (required != null && !required.isEmpty()) {
+                        sb.append("properties:\n");
+                        Iterator<String> it = required.iterator();
+                        while (it.hasNext()) {
+                            String req = it.next();
+                            String type = asText(nodeAt(root, "/spec/definition/properties/" + req + "/type"));
+                            String example = asText(nodeAt(root, "/spec/definition/properties/" + req + "/example"));
+                            sb.append("      ").append(req).append(": ");
+                            if (example != null) {
+                                if ("string".equals(type)) {
+                                    sb.append("\"");
+                                }
+                                sb.append(example);
+                                if ("string".equals(type)) {
+                                    sb.append("\"");
+                                }
+                            } else {
+                                sb.append("\"value\"");
+                            }
+                            if (it.hasNext()) {
+                                sb.append("\n");
+                            }
+                        }
+                    }
+                }
+                IOHelper.close(is);
+            } catch (FileNotFoundException e) {
+                System.err.println("Kamelet not found on github: " + loc);
+            } catch (Exception e) {
+                e.printStackTrace();
+                System.err.println("Error parsing Kamelet: " + loc + " due to: " + e.getMessage());
+            }
+        }
+
+        // create a dummy placeholder, so it is easier to add new properties manually
+        if (sb.length() == 0) {
+            sb.append("#properties:\n      #key: \"value\"");
+        }
+
+        return sb.toString();
+    }
+
+}
diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java
index d38e39889c4..cadf1230879 100644
--- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java
+++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java
@@ -30,6 +30,7 @@ public class CamelJBangMain implements Callable<Integer> {
         commandLine = new CommandLine(new CamelJBangMain())
                 .addSubcommand("run", new Run())
                 .addSubcommand("init", new CommandLine(new Init()))
+                .addSubcommand("bind", new CommandLine(new Bind()))
                 .addSubcommand("search", new CommandLine(new Search())
                         .addSubcommand("kamelets", new SearchKamelets())
                         .addSubcommand("components", new SearchComponents())
diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/binding-kamelet-kamelet.yaml.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/binding-kamelet-kamelet.yaml.tmpl
new file mode 100644
index 00000000000..37f8aba61f1
--- /dev/null
+++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/binding-kamelet-kamelet.yaml.tmpl
@@ -0,0 +1,17 @@
+apiVersion: camel.apache.org/v1alpha1
+kind: KameletBinding
+metadata:
+  name: {{ .Name }}
+spec:
+  source:
+    ref:
+      kind: Kamelet
+      apiVersion: camel.apache.org/v1
+      name: {{ .Source }}
+    {{ .SourceProperties }}
+  sink:
+    ref:
+      kind: Kamelet
+      apiVersion: camel.apache.org/v1
+      name: {{ .Sink }}
+    {{ .SinkProperties }}
diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/binding-kamelet-uri.yaml.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/binding-kamelet-uri.yaml.tmpl
new file mode 100644
index 00000000000..216a8f5a1a0
--- /dev/null
+++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/binding-kamelet-uri.yaml.tmpl
@@ -0,0 +1,15 @@
+apiVersion: camel.apache.org/v1alpha1
+kind: KameletBinding
+metadata:
+  name: {{ .Name }}
+spec:
+  source:
+    ref:
+      kind: Kamelet
+      apiVersion: camel.apache.org/v1
+      name: {{ .Source }}
+    {{ .SourceProperties }}
+  sink:
+    uri: {{ .Sink }}
+    #properties:
+      #key: "value"
diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/binding-uri-kamelet.yaml.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/binding-uri-kamelet.yaml.tmpl
new file mode 100644
index 00000000000..db036588ef3
--- /dev/null
+++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/binding-uri-kamelet.yaml.tmpl
@@ -0,0 +1,15 @@
+apiVersion: camel.apache.org/v1alpha1
+kind: KameletBinding
+metadata:
+  name: {{ .Name }}
+spec:
+  source:
+    uri: {{ .Source }}
+    #properties:
+      #key: "value"
+  sink:
+    ref:
+      kind: Kamelet
+      apiVersion: camel.apache.org/v1
+      name: {{ .Sink }}
+    {{ .SinkProperties }}
diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/binding-uri-uri.yaml.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/binding-uri-uri.yaml.tmpl
new file mode 100644
index 00000000000..f56d14a3c4a
--- /dev/null
+++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/binding-uri-uri.yaml.tmpl
@@ -0,0 +1,13 @@
+apiVersion: camel.apache.org/v1alpha1
+kind: KameletBinding
+metadata:
+  name: {{ .Name }}
+spec:
+  source:
+    uri: {{ .Source }}
+    #properties:
+      #key: "value"
+  sink:
+    uri: {{ .Sink }}
+    #properties:
+      #key: "value"