zregvart commented on a change in pull request #2:
URL: https://github.com/apache/camel-kamelets/pull/2#discussion_r575317959
##########
File path: docs/generator/generator.go
##########
@@ -0,0 +1,307 @@
+package main
+
+import (
+ "encoding/base64"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "sort"
+ "strings"
+
+ camel "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+ "k8s.io/apimachinery/pkg/runtime/serializer"
+ "k8s.io/apimachinery/pkg/util/yaml"
+)
+
+func main() {
+ if len(os.Args) != 3 {
+ println("usage: generator kamelets-path doc-root")
+ os.Exit(1)
+ }
+
+ dir := os.Args[1]
+ out := os.Args[2]
+
+ kamelets := listKamelets(dir)
+
+ links := make([]string, 0)
+ for _, k := range kamelets {
+ img := saveImage(k, out)
+ produceDoc(k, out, img)
+
+ links = append(links, fmt.Sprintf("** xref:ROOT:%s.adoc[%s
%s]", k.Name, img, k.Spec.Definition.Title))
+ }
+
+ saveNav(links, out)
+}
+
+func saveNav(links []string, out string) {
+ content := "// THIS FILE IS AUTOMATICALLY GENERATED: DO NOT EDIT\n"
+ content += "* xref:ROOT:index.adoc[Kamelet Catalog]\n"
+ for _, l := range links {
+ content += l + "\n"
+ }
+ content += "// THIS FILE IS AUTOMATICALLY GENERATED: DO NOT EDIT\n"
+ dest := filepath.Join(out, "nav.adoc")
+ if _, err := os.Stat(dest); err == nil {
+ err = os.Remove(dest)
+ handleGeneralError(fmt.Sprintf("cannot remove file %q", dest),
err)
+ }
+ err := ioutil.WriteFile(dest, []byte(content), 0666)
+ handleGeneralError(fmt.Sprintf("cannot write file %q", dest), err)
+ fmt.Printf("%q written\n", dest)
+}
+
+func saveImage(k camel.Kamelet, out string) string {
+ if ic, ok := k.ObjectMeta.Annotations["camel.apache.org/kamelet.icon"];
ok {
+ svgb64Prefix := "data:image/svg+xml;base64,"
+ if strings.HasPrefix(ic, svgb64Prefix) {
+ data := ic[len(svgb64Prefix):]
+ decoder := base64.NewDecoder(base64.StdEncoding,
strings.NewReader(data))
+ iconContent, err := ioutil.ReadAll(decoder)
+ handleGeneralError(fmt.Sprintf("cannot decode icon from
Kamelet %s", k.Name), err)
+ dest := filepath.Join(out, "assets", "images",
"kamelets", fmt.Sprintf("%s.svg", k.Name))
+ if _, err := os.Stat(dest); err == nil {
+ err = os.Remove(dest)
+ handleGeneralError(fmt.Sprintf("cannot remove
file %q", dest), err)
+ }
+ err = ioutil.WriteFile(dest, iconContent, 0666)
+ handleGeneralError(fmt.Sprintf("cannot write file %q",
dest), err)
+ fmt.Printf("%q written\n", dest)
+ return fmt.Sprintf("image:kamelets/%s.svg[]", k.Name)
+ }
+ }
+ return ""
+}
+
+func produceDoc(k camel.Kamelet, out string, image string) {
+ docFile := filepath.Join(out, "pages", k.Name + ".adoc")
+
+ content := "// THIS FILE IS AUTOMATICALLY GENERATED: DO NOT EDIT\n"
+ content += "= " + image + " " + k.Spec.Definition.Title + "\n"
+ content += "\n"
+ if prov, ok := k.Annotations["camel.apache.org/provider"]; ok {
+ content += fmt.Sprintf("*Provided by: %q*\n", prov)
+ content += "\n"
+ }
+ content += k.Spec.Definition.Description + "\n"
+ content += "\n"
+ content += "== Configuration Options\n"
+ content += "\n"
+
+ required := make(map[string]bool)
+ keys := make([]string, 0, len(k.Spec.Definition.Properties))
+
+ if len(k.Spec.Definition.Properties) > 0 {
+ for _, r := range k.Spec.Definition.Required {
+ required[r] = true
+ }
+
+ for key := range k.Spec.Definition.Properties {
+ keys = append(keys, key)
+ }
+ sort.Slice(keys, func(i, j int) bool {
+ ri := required[keys[i]]
+ rj := required[keys[j]]
+ if ri && !rj {
+ return true
+ } else if !ri && rj {
+ return false
+ }
+ return keys[i] < keys[j]
+ })
+
+ content += fmt.Sprintf("The following table summarizes the
configuration options available for the `%s` Kamelet:\n", k.Name)
+
+ content +=
`[width="100%",cols="2,^2,3,^2,^2,^3",options="header"]` + "\n"
+ content += "|===\n"
+ content += tableLine("Property", "Name", "Description", "Type",
"Default", "Example")
+
+ for _, key := range keys {
+ prop := k.Spec.Definition.Properties[key]
+ name := key
+ if required[key] {
+ name = "*" + name + " {empty}* *"
+ }
+ def := ""
+ if prop.Default != nil {
+ b, err := prop.Default.MarshalJSON()
+ handleGeneralError(fmt.Sprintf("cannot marshal
property %q default value in Kamelet %s", key, k.Name), err)
+ def = "`" + strings.ReplaceAll(string(b), "`",
"'") + "`"
+ }
+ ex := ""
+ if prop.Example != nil {
+ b, err := prop.Example.MarshalJSON()
+ handleGeneralError(fmt.Sprintf("cannot marshal
property %q example value in Kamelet %s", key, k.Name), err)
+ ex = "`" + strings.ReplaceAll(string(b), "`",
"'") + "`"
+ }
+ content += tableLine(name, prop.Title,
prop.Description, prop.Type, def, ex)
+ }
+
+ content += "|===\n"
+ content += "\n"
+ content += "NOTE: Fields marked with ({empty}*) are
mandatory.\n"
+
+ } else {
+ content += "The Kamelet does not specify any configuration
option.\n"
+ }
+
+ content += "\n"
+ content += "== Usage\n"
+ content += "\n"
+ content += fmt.Sprintf("This section summarizes how the `%s` can be
used in various contexts.\n", k.Name)
+ content += "\n"
+
+ tp := k.ObjectMeta.Labels["camel.apache.org/kamelet.type"]
+ if tp != "" {
+ content += fmt.Sprintf("=== Knative %s\n", strings.Title(tp))
+ content += "\n"
+
+ content += fmt.Sprintf("The `%s` Kamelet can be used as Knative
%s by binding it to a Knative object.\n", k.Name, tp)
+ content += "\n"
+
+ sampleConfig := make([]string, 0)
+ for _, key := range keys {
+ if !required[key] {
+ continue
+ }
+ prop := k.Spec.Definition.Properties[key]
+ if prop.Default == nil {
+ ex := ""
+ if prop.Example != nil {
+ b, err := prop.Example.MarshalJSON()
+ handleGeneralError(fmt.Sprintf("cannot
marshal property %q example value in Kamelet %s", key, k.Name), err)
+ ex = string(b)
+ }
+ if ex == "" {
+ ex = `"The ` + prop.Title + `"`
+ }
+ sampleConfig = append(sampleConfig,
fmt.Sprintf("%s: %s", key, ex))
+ }
+ }
+ props := ""
+ if len(sampleConfig) > 0 {
+ props += " properties:\n"
+ for _, p := range sampleConfig {
+ props += fmt.Sprintf(" %s\n", p)
+ }
+ }
+
+ kameletRef := fmt.Sprintf(` ref:
+ kind: Kamelet
+ apiVersion: camel.apache.org/v1alpha1
+ name: %s
+%s`, k.Name, props)
+
+ knativeRef := ` ref:
+ kind: InMemoryChannel
+ apiVersion: messaging.knative.dev/v1
+ name: mychannel
+`
+
+ sourceRef := kameletRef
+ sinkRef := knativeRef
+ if tp == "sink" {
+ sourceRef = knativeRef
+ sinkRef = kameletRef
+ }
+
+ binding := fmt.Sprintf(`apiVersion: camel.apache.org/v1alpha1
+kind: KameletBinding
+metadata:
+ name: %s-binding
+spec:
+ source:
+%s sink:
+%s
+`, k.Name, sourceRef, sinkRef)
+
+ content += fmt.Sprintf(".%s-binding.yaml\n", k.Name)
+ content += "[source,yaml]\n"
+ content += "----\n"
+ content += binding
+ content += "----\n"
+
+ content += "\n"
+ content += "Make sure you have
https://camel.apache.org/camel-k/latest/installation/installation.html[Camel K
installed] into the Kubernetes cluster you're connected to.\n"
Review comment:
We need a `xref` link here, otherwise link checker will not be able to
verify the link and the [HTML
validation](https://github.com/apache/camel-website/blob/32188349a4e0f3c411d6e97ca92b6f733d67849c/.htmlvalidate.json#L17)
not allowing absolute URLs to camel.apache.org will fail.
```suggestion
content += "Make sure you have
xref:latest@camel-k::installation/installation.html[Camel K installed] into the
Kubernetes cluster you're connected to.\n"
```
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]