Skip to content

Commit

Permalink
Templates for kamelet adoc generation
Browse files Browse the repository at this point in the history
  • Loading branch information
djencks committed Dec 21, 2021
1 parent 779c9a7 commit dec651a
Show file tree
Hide file tree
Showing 5 changed files with 330 additions and 1 deletion.
5 changes: 4 additions & 1 deletion docs/antora.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
33 changes: 33 additions & 0 deletions docs/indexPages.yml
Original file line number Diff line number Diff line change
@@ -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`'
161 changes: 161 additions & 0 deletions docs/modules/ROOT/examples/js/kamelets.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/*
* 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}
return `= image:kamelets/${basename}-new.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,
},
}),
}

1 change: 1 addition & 0 deletions docs/modules/ROOT/examples/template/kamelet-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
131 changes: 131 additions & 0 deletions docs/modules/ROOT/examples/template/kamelet-options.adoc
Original file line number Diff line number Diff line change
@@ -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='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

0 comments on commit dec651a

Please sign in to comment.