You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by dj...@apache.org on 2021/12/24 17:09:36 UTC
[camel-kamelets] 06/07: Templates for kamelet adoc generation
This is an automated email from the ASF dual-hosted git repository.
djencks pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-kamelets.git
commit eb0b675762f6080cabe481a19b57848502ad5111
Author: David Jencks <dj...@apache.org>
AuthorDate: Sun Nov 14 12:14:42 2021 -0800
Templates for kamelet adoc generation
---
docs/antora.yml | 5 +-
docs/indexPages.yml | 33 +++++
docs/modules/ROOT/examples/js/kamelets.js | 160 +++++++++++++++++++++
.../ROOT/examples/template/kamelet-icon.svg | 1 +
.../ROOT/examples/template/kamelet-options.adoc | 131 +++++++++++++++++
5 files changed, 329 insertions(+), 1 deletion(-)
diff --git a/docs/antora.yml b/docs/antora.yml
index 763c601..c14f4b4 100644
--- a/docs/antora.yml
+++ b/docs/antora.yml
@@ -24,7 +24,10 @@ display-version: Next (Pre-release)
nav:
- modules/ROOT/nav.adoc
-# Update to appropriate released camel-k version on release
asciidoc:
attributes:
+ requires: "'util=camel-website-util,kamelets=xref:js/kamelets.js'"
+ # Update to appropriate released camel-k version on release
camel-k-version: next
+ jsonpath-trace: true
+ jsonpath-debug: true
diff --git a/docs/indexPages.yml b/docs/indexPages.yml
new file mode 100644
index 0000000..178106d
--- /dev/null
+++ b/docs/indexPages.yml
@@ -0,0 +1,33 @@
+indexPages:
+ - query:
+ module: ROOT
+ family: example
+ relative: yaml/*
+ requires: 'kamelets=xref:js/kamelets.js'
+ content-as: json
+ template-id:
+ family: example
+ relative: template/kamelet-options.adoc
+ extract:
+ - path: 'src.relative'
+ match: 'yaml/(?<basename>*).kamelet.yaml'
+ target:
+ match: 'yaml/(?<basename>*).kamelet.yaml'
+ format: '`${basename}.adoc`'
+
+ - query:
+ module: ROOT
+ family: example
+ relative: yaml/*
+ requires: 'kamelets=xref:js/kamelets.js'
+ content-as: json
+ template-id:
+ family: example
+ relative: template/kamelet-icon.svg
+ extract:
+ - path: 'src.relative'
+ match: 'yaml/(?<basename>*).kamelet.yaml'
+ target:
+ family: image
+ match: 'yaml/(?<basename>*).kamelet.yaml'
+ format: '`kamelets/${basename}.svg`'
diff --git a/docs/modules/ROOT/examples/js/kamelets.js b/docs/modules/ROOT/examples/js/kamelets.js
new file mode 100644
index 0000000..549983c
--- /dev/null
+++ b/docs/modules/ROOT/examples/js/kamelets.js
@@ -0,0 +1,160 @@
+/*
+ * 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.
+ */
+
+const util = require('camel-website-util')
+
+const QUOTED_CHARS = /[$`"\\]/g
+
+const QUOTE_REPLACEMENTS = {
+ '$': '\\$',
+ '\`': '\\\`',
+ '"': '\\"',
+ '\\': '\\\\',
+}
+
+const svgb64Prefix = 'data:image/svg+xml;base64,'
+
+module.exports = {
+ binding: (binding, apiVersion, kind, metadata_, spec_, refKind, refApiVersion, refName) => {
+ const name = metadata_.name
+ const metadata = {name: `${name}-binding`}
+ const kamelet = {
+ ref: {
+ kind,
+ apiVersion,
+ name,
+ },
+ properties: kameletPropertyList(spec_.definition)
+ }
+ const platform = {
+ ref: {
+ kind: refKind,
+ apiVersion: refApiVersion,
+ name: refName,
+ },
+ }
+ const base = {
+ apiVersion,
+ kind: 'KameletBinding',
+ metadata,
+ }
+ const fn = kameletBindings[binding] || (() => `unrecognized binding ${binding}`)
+ return fn(base, kamelet, platform)
+ },
+
+ bindingCommand: (binding, name, definition, topic) => {
+ const namePrefix = { action: 'step-0', sink: 'sink', source: 'source' }[binding]
+ const quote = (string) => (typeof string === 'String')
+ ? string.replace(QUOTED_CHARS, (m) => QUOTE_REPLACEMENTS[m])
+ : string
+ const properties = Object.entries(kameletPropertyList(definition) || {})
+ .map(([name, value]) => `-p "${namePrefix}.${name}=${quote(value)}"`)
+ .join(' ')
+ return `kamel bind ${name} ${properties} ${topic}`
+ },
+
+ sort: function (list) {
+ function alphaSort (list) {
+ return list.sort((a, b) => a.name < b.name ? -1: a.name > b.name ? 1: 0)
+ }
+ const requiredNames = this.data.spec.definition.required || []
+ const { required, optional } = list.reduce((accum, item) => {
+ const name = item.path[4]
+ if (requiredNames.includes(name)) {
+ accum.required.push({name, value: Object.assign({ required: true }, item.value)} )
+ } else {
+ accum.optional.push({ name, value: item.value })
+ }
+ return accum
+ }, { required: [], optional: []})
+ return [...alphaSort(required), ...alphaSort(optional)]
+ },
+
+ icon: ($) => {
+ const b64 = $.metadata.annotations['camel.apache.org/kamelet.icon']
+ try {
+ if (b64.startsWith(svgb64Prefix)) {
+ data = b64.slice(svgb64Prefix.length)
+ return Buffer.from(data, 'base64').toString()
+ }
+ } catch (e) {
+ console.log(`icon problem ${b64}`, e)
+ }
+ return 'generic svg!'
+ },
+
+ templateHeader: (basename, $) => {
+ const title = $.spec.definition.title
+ const name = $.metadata.name
+ const provider = $.metadata.annotations["camel.apache.org/provider"]
+ const supportLevel = $.metadata.annotations["camel.apache.org/kamelet.support.level"]
+ const type = $.metadata.labels["camel.apache.org/kamelet.type"]
+ const propertyCount = Object.keys(($.spec.definition.properties || {})).length
+ return `= image:kamelets/${basename}.svg[] ${title}
+:name: ${name}
+:provider: ${provider}
+:support-level: ${supportLevel}
+:type: ${type}
+:propertycount: ${propertyCount}
+`
+ }
+}
+
+function kameletPropertyList (definition) {
+ return definition.required && definition.properties && Object.fromEntries(
+ Object.entries(definition.properties)
+ .filter(([name, value]) => definition.required.includes(name))
+ .sort(([name1, value1], [name2, value2]) => name1.localeCompare(name2))
+ .map(([name, value]) => [name, value.example ? value.example : `The ${value.title}`])
+ )
+}
+
+const kameletBindings = {
+ action: (base, kamelet, platform) => Object.assign(base, {
+ spec: {
+ source: {
+ ref: {
+ kind: 'Kamelet',
+ apiVersion: 'camel.apache.org/v1alpha1',
+ name: 'timer-source',
+ properties: {
+ message: 'Hello',
+ },
+ },
+ },
+ steps: [
+ kamelet,
+ ],
+ sink: platform,
+ },
+ }),
+
+ sink: (base, kamelet, platform) => Object.assign(base, {
+ spec: {
+ source: platform,
+ sink: kamelet,
+ },
+ }),
+
+ source: (base, kamelet, platform) => Object.assign(base, {
+ spec: {
+ source: kamelet,
+ sink: platform,
+ },
+ }),
+}
+
diff --git a/docs/modules/ROOT/examples/template/kamelet-icon.svg b/docs/modules/ROOT/examples/template/kamelet-icon.svg
new file mode 100644
index 0000000..533d8b4
--- /dev/null
+++ b/docs/modules/ROOT/examples/template/kamelet-icon.svg
@@ -0,0 +1 @@
+${kamelets.icon($)}
\ No newline at end of file
diff --git a/docs/modules/ROOT/examples/template/kamelet-options.adoc b/docs/modules/ROOT/examples/template/kamelet-options.adoc
new file mode 100644
index 0000000..150adf6
--- /dev/null
+++ b/docs/modules/ROOT/examples/template/kamelet-options.adoc
@@ -0,0 +1,131 @@
+${kamelets.templateHeader(basename, $)}
+
+*Provided by: "{provider}"*
+
+*Support Level for this Kamelet is: "{support-level}"*
+
+jsonpathExpression::example$yaml/${basename}.kamelet.yaml[query='$.spec.definition', format='description']
+
+== Configuration Options
+
+ifeval::[{propertycount} == 0]
+The \`{name}\` Kamelet does not specify any configuration options.
+endif::[]
+
+ifeval::[{propertycount} != 0]
+The following table summarizes the configuration options available for the \`{name}\` Kamelet:
+
+[width="100%",cols="2,^2,3,^2,^2,^3",options="header"]
+|===
+| Property| Name| Description| Type| Default| Example
+|===
+
+jsonpathTable::example$yaml/${basename}.kamelet.yaml[query='nodes$.spec.definition.properties.*',cellformats='util.boldLink(name)|value.title|util.description(value)|util.valueAsString(value.type)|util.valueAsString(value.default)|util.valueAsString(value.example)',{requires},transform=kamelets.sort]
+
+endif::[]
+
+== Dependencies
+
+At runtime, the \`{name}\` Kamelet relies upon the presence of the following dependencies:
+
+jsonpathList::example$yaml/${basename}.kamelet.yaml[query='nodes$.spec.dependencies.*',format='value']
+
+== Usage
+
+This section describes how you can use the \`{name}\`.
+
+=== Knative {type}
+
+ifeval::['{type}' == 'action']
+You can use the \`{name}\` Kamelet as an intermediate step in a Knative binding.
+endif::[]
+ifeval::['{type}' != 'action']
+You can use the \`{name}\` Kamelet as a Knative {type} by binding it to a Knative object.
+endif::[]
+
+:ref-api-version: messaging.knative.dev/v1
+:ref-kind: Channel
+:ref-name: mychannel
+
+.{name}-binding.yaml
+[source,yaml,subs='+attributes,macros']
+----
+jsonpathExpression::example$yaml/${basename}.kamelet.yaml[query='$', format='kamelets.binding("{type}", apiVersion, kind, metadata, spec, "{ref-kind}", "{ref-api-version}", "{ref-name}")', outputFormat=yml, requires={requires}]
+----
+
+==== *Prerequisite*
+
+You have xref:{camel-k-version}@camel-k::installation/installation.adoc[Camel K installed] on the cluster.
+
+==== *Procedure for using the cluster CLI*
+
+. Save the \`{name}-binding.yaml\` file to your local drive, and then edit it as needed for your configuration.
+
+. Run the {type} by using the following command:
++
+[source,shell,subs=+attributes]
+----
+kubectl apply -f {name}-binding.yaml
+----
+
+==== *Procedure for using the Kamel CLI*
+
+Configure and run the {type} by using the following command:
+
+[source,shell,subs='+attributes,macros']
+----
+jsonpathExpression:example$yaml/${basename}.kamelet.yaml[query='$.spec', format='kamelets.bindingCommand("{type}", "{name}", definition, "channel:mychannel")', requires={requires}]
+----
+
+This command creates the KameletBinding in the current namespace on the cluster.
+
+=== Kafka {type}
+
+ifeval::['{type}' == 'action']
+You can use the \`{name}\` Kamelet as an intermediate step in a Kafka binding.
+endif::[]
+ifeval::['{type}' != 'action']
+You can use the \`{name}\` Kamelet as a Kafka {type} by binding it to a Kafka topic.
+endif::[]
+
+:ref-api-version: kafka.strimzi.io/v1beta1
+:ref-kind: KafkaTopic
+:ref-name: my-topic
+
+.{name}-binding.yaml
+[source,yaml,subs='+attributes,macros']
+----
+jsonpathExpression::example$yaml/${basename}.kamelet.yaml[query='$', format='kamelets.binding("{type}", apiVersion, kind, metadata, spec, "{ref-kind}", "{ref-api-version}", "{ref-name}")', outputFormat=yml, requires={requires}]
+----
+
+==== *Prerequisites*
+
+* You've installed https://strimzi.io/[Strimzi].
+* You've created a topic named \`my-topic\` in the current namespace.
+* You have xref:{camel-k-version}@camel-k::installation/installation.adoc[Camel K installed] on the cluster.
+
+==== *Procedure for using the cluster CLI*
+
+. Save the \`{name}-binding.yaml\` file to your local drive, and then edit it as needed for your configuration.
+
+. Run the {type} by using the following command:
++
+[source,shell,subs=+attributes]
+----
+kubectl apply -f {name}-binding.yaml
+----
+
+==== *Procedure for using the Kamel CLI*
+
+Configure and run the {type} by using the following command:
+
+[source,shell,subs='+attributes,macros']
+----
+jsonpathExpression::example$yaml/${basename}.kamelet.yaml[query='$.spec', format='kamelets.bindingCommand("{type}", "{name}", definition, "kafka.strimzi.io/v1beta1:KafkaTopic:my-topic")', requires={requires}]
+----
+
+This command creates the KameletBinding in the current namespace on the cluster.
+
+== Kamelet source file
+
+https://github.com/apache/camel-kamelets/blob/main/{name}.kamelet.yaml