diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index e3d322eb24..d8bc86f44b 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -18,11 +18,14 @@ * xref:cli/cli.adoc[CLI] ** xref:cli/modeline.adoc[Modeline] * xref:configuration/configuration.adoc[Configuration] -** xref:configuration/maven.adoc[Maven] +** xref:configuration/build-time-properties.adoc[Build time properties] ** xref:configuration/components.adoc[Components] ** xref:configuration/logging.adoc[Logging] ** xref:configuration/dependencies.adoc[Dependencies] -** xref:configuration/configmap-secret.adoc[ConfigMap/Secret] +** xref:configuration/runtime-properties.adoc[Properties] +** xref:configuration/runtime-config.adoc[Runtime configuration] +** xref:configuration/runtime-resources.adoc[Runtime resources] +** xref:configuration/maven.adoc[Maven] * Observability ** xref:observability/monitoring.adoc[Monitoring] *** xref:observability/operator.adoc[Operator] diff --git a/docs/modules/ROOT/pages/cli/cli.adoc b/docs/modules/ROOT/pages/cli/cli.adoc index 34a2b2e4a1..08668d0f2e 100644 --- a/docs/modules/ROOT/pages/cli/cli.adoc +++ b/docs/modules/ROOT/pages/cli/cli.adoc @@ -69,9 +69,9 @@ While each command has a dedicated set of flags, there are global flags that are |=== |Flag |Description |Example -|`--config PATH` +|`--kube-config PATH` |Path to the config file to use for CLI requests -|kamel install --config ~/.kube/config +|kamel install --kube-config ~/.kube/config |`-h` or `--help` |Help for `kamel`, or the command diff --git a/docs/modules/ROOT/pages/configuration/build-time-properties.adoc b/docs/modules/ROOT/pages/configuration/build-time-properties.adoc new file mode 100644 index 0000000000..4898ab060e --- /dev/null +++ b/docs/modules/ROOT/pages/configuration/build-time-properties.adoc @@ -0,0 +1,56 @@ +[[build-time-props]] += Build time properties + +You may be required to provide certain *build-time properties* that are needed only during the process of `Integration` building. Since Camel K version 1.5, we introduced a `--build-property` flag that will be handful in such circumstances. The property value may be also used inside Camel K integrations using the *property placeholder* mechanism. + +[[build-time-single-prop]] +== Single property + +You will find this feature very useful when dealing with configuration that affects how `Quarkus` builds the `Integration`. For example, let's see how to override the default `quarkus.application.name` expected by any `Quarkus` application: + +[source,groovy] +.build-property-route.groovy +---- +from('timer:build-property') + .log('The application name: {{quarkus.application.name}}') +---- + +In order to give a value to the `quarkus.application.name` property you can pass it using the command line with the `--build-property` flag: + +---- +kamel run --build-property=quarkus.application.name=my-super-application build-property-route.groovy --dev +---- + +You can provide more than one single `build-property` at once by just adding the flag repeatedly (ie, `--build-property=prop1=val1 --build-property=prop2=val2 ...`) + +[[build-time-props-file]] +== Property File + +Repeating the property flag when you have many *build time configuration* may be cumbersome. Usually you deal with property files instead. You will be able to use the _file_ syntax available for `--build-property` flag. Here, as an example you have a property files with 2 `Quarkus` properties: + +[source,properties] +.quarkus.properties +---- +quarkus.application.name = my-super-application +quarkus.banner.enabled = true +---- + +[source,groovy] +.build-property-route.groovy +---- +from('timer:build-property') + .log('The application name: {{quarkus.application.name}}') +---- + +The `quarkus.banner.enabled` is configured to show the banner during the `Integration` startup. Let's use `--build-property` flag in conjunction with file: + +---- +kamel run --build-property=file:quarkus.properties build-property-file-route.groovy --dev +---- + +The property file is parsed and its properties configured on the `Integration`. As soon as the application starts, you will see the log with the expected configuration. + +[[build-time-runtime-conf]] +== Run time properties + +If you're looking for *runtime properties configuration* you can look at the xref:configuration/runtime-properties.adoc[runtime properties] section. \ No newline at end of file diff --git a/docs/modules/ROOT/pages/configuration/configmap-secret.adoc b/docs/modules/ROOT/pages/configuration/configmap-secret.adoc deleted file mode 100644 index 9748b5ccca..0000000000 --- a/docs/modules/ROOT/pages/configuration/configmap-secret.adoc +++ /dev/null @@ -1,127 +0,0 @@ -= Configuration via ConfigMap or Secret - -Camel K allows defining property values using Kubernetes ConfigMap or Secrets. - -For the sake of example, consider the following integration: - -[source,groovy] -.props.groovy ----- -from('timer:props?period=1000') - .log('{{my.message}}') ----- - -In addition to xref:configuration/configuration.adoc[command line property configuration], Camel K provides the following configuration mechanisms. - -== Configuration via ConfigMap - -You can create a ConfigMap containing your configuration properties, and link it to a Camel K integration. - -For example, you can define the following ConfigMap: - -[source,yaml] -.my-config.yaml ----- -apiVersion: v1 -kind: ConfigMap -metadata: - name: my-config -data: - application.properties: | - my.message=Hello World - logging.level.org.apache.camel=DEBUG ----- - -In the ConfigMap above, we've set both the value of the property `my.message`, and also the xref:configuration/logging.adoc[logging level] for the `org.apache.camel` package. - -You need to create the ConfigMap first (in the same Kubernetes namespace): - -[source,console] ----- -$ kubectl apply -f my-config.yaml ----- - -You can now run the integration with the following command to reference the ConfigMap: - -[source, console] ----- -$ kamel run --configmap=my-config props.groovy ----- - -== Configuration via Secret - -Configuration via a Secret is similar to the configuration via a ConfigMap. -The difference is that you may need to _base64_ encode the content of the -`application.properties` file inside the Secret. - -For example, the following Secret is equivalent to the previous ConfigMap: - -[source,yaml] -.my-secret.yaml ----- -apiVersion: v1 -kind: Secret -metadata: - name: my-secret -data: - application.properties: | - bXkubWVzc2FnZT1IZWxsbyBXb3JsZAogICAgbG9nZ2luZy5sZXZlbC5vcmcuYXBhY2hlLmNhbWVs - PURFQlVHCg== ----- - -You need to create the Secret first (in the same Kubernetes namespace): - -[source, console] ----- -$ kubectl apply -f my-secret.yaml ----- - -You can now run the integration with the following command to reference the Secret: - -[source,console] ----- -$ kamel run --secret=my-secret props.groovy ----- - -== Reference a Secret from properties - -Suppose you have an existing Secret, that contains sensitive information that your integration requires. -You might want to reference the values from this Secret in your configuration properties. - -For example, a Secret named `secret-message`: - -[source,yaml] -.secret-message.yaml ----- -apiVersion: v1 -kind: Secret -metadata: - name: secret-message -data: - MESSAGE: SGVsbG8gV29ybGQK -type: Opaque ----- - -You can reference this Secret from the configuration properties, using the `{{secret:secret-name/key-name}}` syntax. - -For example, the following configuration stored in a ConfigMap references the Secret defined previously: - -[source,yaml] -.my-config.yaml ----- -apiVersion: v1 -kind: ConfigMap -metadata: - name: my-config -data: - application.properties: | - my.message={{secret:secret-message/MESSAGE}} ----- - -You can now run the integration with the following commands to include both the Secret and ConfigMap: - -[source,console] ----- -$ kubectl apply -f my-config.yaml -f secret-message.yaml -$ kamel run --secret=secret-message --configmap=my-config props.groovy ----- diff --git a/docs/modules/ROOT/pages/configuration/configuration.adoc b/docs/modules/ROOT/pages/configuration/configuration.adoc index 0a1a86bbac..2a5aa6e436 100644 --- a/docs/modules/ROOT/pages/configuration/configuration.adoc +++ b/docs/modules/ROOT/pages/configuration/configuration.adoc @@ -1,7 +1,7 @@ [[configuration]] = Configure Integrations -Properties associated to an integration can be configured either using a ConfigMap/Secret or by setting using the `--property` flag when running the integration. +Runtime properties associated to an integration can be configured using the `--property` flag when running the integration. If the property is a *build time property* (ie, certain `Quarkus` configuration), then, you can use xref:configuration/build-time-properties.adoc[`--build-property`] instead. The property value can be used inside Camel K integrations using the *property placeholder* mechanism. @@ -20,4 +20,4 @@ In order to give a value to the `my.message` property you can pass it using the kamel run --property my.message="Hello World" examples/props.js ``` -An alternative, is to provide a value using a Kubernetes xref:configuration/configmap-secret.adoc[ConfigMap or Secret] \ No newline at end of file +For more details and advanced use cases, see the xref:configuration/runtime-properties.adoc[runtime properties] section. \ No newline at end of file diff --git a/docs/modules/ROOT/pages/configuration/runtime-config.adoc b/docs/modules/ROOT/pages/configuration/runtime-config.adoc new file mode 100644 index 0000000000..019ddf2645 --- /dev/null +++ b/docs/modules/ROOT/pages/configuration/runtime-config.adoc @@ -0,0 +1,135 @@ +[[runtime-config]] += Runtime configuration + +When you develop an integration with `Camel-K` there are many ways you can provide a *configuration* resource to the runtime `Integration`. The most familiar way is to handle local file, but since we are dealing with `Kubernetes` you may need also to use `Configmap` or `Secret`. The `kamel run` command is provided with a `--config` flag that help you setting any configuration resource your `Integration` need. + +The *runtime configuration* are expected to be `ÙTF-8` resources as they are processed by runtime `Camel Context` and tried to be parsed as property files. These resources are materialized as files in a well known path in the `Ìntegration` `Pod`. They are also made available on the classpath in order to ease their usage directly from the `Route`. If you need to provide a non `UTF-8` (ie, a binary resource) you may look for `--resource` flag instead. + +NOTE: the scope of `--config` global option had different meaning prior Camel K version 1.5. The old global `--config` has been replaced with `--kube-config` since Camel K version 1.5. + +[[runtime-config-file]] +== Runtime file configuration + +The most classic way to provide a configuration is probably to have a file where you have certain text data stored. In this case you can use the `--config file:/path/to/file` flag that will copy that file and made available at classpath level. + +[source,txt] +.resources-data.txt +---- +the file body +---- + +[source,groovy] +.config-file-route.groovy +---- +from('timer:config-file') + .setBody() + .simple("resource:classpath:resources-data.txt") + .log('resource file content is: ${body}') +---- + +We are referring to the file expected to be copied somewhere in the classpath, with the same name as the source file. In order to use it, we'll execute the following `--config` _file_ flag command: + +---- +kamel run --config file:resources-data.txt config-file-route.groovy --dev +---- + +You can provide more than one single `config` at once by just adding the flag repeatedly (ie, `--config file:file1.txt ---config file:file2.txt ...`). + +[[runtime-config-configmap]] +== Runtime configmap configuration + +In a `Kubernetes` world we're dealing with `Configmap` that are containing configuration previously stored in the platform. When you need to materialize a `Configmap` into a file configuration available at your `Integration`, you can use the `--config` _configmap_ syntax. + +As an example, let's create a `Configmap` named _my-cm_ containing certain information. You can alternatively use any `Configmap` you've already stored in your cluster: + +---- +kubectl create configmap my-cm --from-literal=my-configmap-key="configmap content" +---- + +We want to use the materialized file in an integration: + +[source,groovy] +.config-configmap-route.groovy +---- +from('timer:configmap') + .setBody() + .simple("resource:classpath:my-configmap-key") + .log('configmap content is: ${body}') +---- + +You can see that we're expecting to use a _my-configmap-key_ file stored somewhere in the classpath. In order to materialize the `Configmap` will be as easy as running the `--config` _configmap_ syntax: + +---- +kamel run --config configmap:my-cm config-configmap-route.groovy --dev +---- + +As soon as the `Integration` starts, the `Camel-K` operator will take care to mount a volume with the `Configmap`'s content. + +NOTE: you can provide a `Configmap` which is not yet available on the cluster. The `Integration` won't start until the resource will be made available. + +[[runtime-config-secret]] +== Runtime secret configuration + +We can apply the very same concept seen in the previous section for the Kubernetes `Secret`s. + +As an example, let's create a `Secret` named _my-sec_ containing certain information. You can alternatively use any `Secret` you've already stored in your cluster: + +---- +kubectl create secret generic my-sec --from-literal=my-secret-key="very top secret" +---- + +We want to use the materialized secret file in an integration: + +[source,groovy] +.config-secret-route.groovy +---- +from('timer:secret') + .setBody() + .simple("resource:classpath:my-secret-key") + .log('secret content is: ${body}') +---- + +You can see that we're expecting to use a _my-secret-key_ file stored somewhere in the classpath. In order to materialize the `Secret` will be as easy as running the `--config` _secret_ syntax: + +---- +kamel run --config secret:my-sec config-secret-route.groovy --dev +---- + +As soon as the `Integration` starts, the `Camel-K` operator will take care to mount a volume with the `Secret`'s content. + +NOTE: you can provide a `Secret` which is not yet available on the cluster. The `Integration` won't start until the resource will be made available. + +[[runtime-config-keys]] +== Configmap/Secret key filtering + +When you deal with `Configmap` or `Secret`, you may want to limit the quantity of information to recover from such resources. Both `Configmap` and `Secret` can hold more than one resource in the same unit. For this reason you will find a _key_ filtering feature available in the `--config` flag. In order to use it, you can add a _/key_ notation after the `Configmap` or `Secret` name (ie, `--config configmap:my-cm/my-key`). + +Let's see an example with multiple `Secret` in action. The very same concept can be easily applied to `Configmap`. We start creating a `Secret` containing multiple resources: + +---- +kubectl create secret generic my-sec-multi --from-literal=my-secret-key="very top secret" --from-literal=my-secret-key-2="even more secret" +---- + +In our `Integration` we plan to use only one of the resources of the `Secret`: + +[source,groovy] +.config-secret-key-route.groovy +---- +from('timer:secret') + .setBody() + .simple("resource:classpath:my-secret-key-2") + .log('secret content is: ${body}') +---- + +Let's use the _key_ filtering: + +---- +kamel run --config secret:my-sec-multi/my-secret-key-2 config-secret-key-route.groovy --dev +---- + +You may check in the `Integration` `Pod` that only the _my-secret-key-2_ file has been mounted. + +[[runtime-config-resources]] +== Runtime resources + +If you're looking for *runtime resources* (ie, binary resources) you can look at the xref:configuration/runtime-resources.adoc[runtime resources] section. \ No newline at end of file diff --git a/docs/modules/ROOT/pages/configuration/runtime-properties.adoc b/docs/modules/ROOT/pages/configuration/runtime-properties.adoc new file mode 100644 index 0000000000..8ef5c9fc48 --- /dev/null +++ b/docs/modules/ROOT/pages/configuration/runtime-properties.adoc @@ -0,0 +1,57 @@ +[[runtime-props]] += Runtime properties + +During the execution of an `Integration` you can provide a single property or a property file that will be made available at runtime. + +[[runtime-single-prop]] +== Single property + +Imagine you have a generic `Route` and you set a placeholder for certain information (ie, _my.message_ variable): + +[source,groovy] +.property-route.groovy +---- +from('timer:property') + .log('property content is: {{my.message}}') +---- + +The simplest way to replace that variable with a real value is to use the `--property` flag (also shortcut by `-p`): + +---- +kamel run -p my.message=test-property property-route.groovy --dev +---- + +At runtime, that variable will be substituted by the value you've provided. You can provide more than one single `property` at once by just adding the flag repeatedly (ie, `--property prop1=val1 --property prop2=val2 ...`) + +[[runtime-props-file]] +== Property File + +Another way to provide more property configuration at once is to use a *property file*. + +[source,properties] +.my.properties +---- +my.key.1=hello +my.key.2=world +---- + +[source,groovy] +.build-property-route.groovy +---- +from('timer:property-file') + .routeId('property-file') + .log('property file content is: {{my.key.1}} {{my.key.2}}') +---- + +You'll need to provide a `property` _file_ flag when launching the application: + +---- +// kamel run --property file:my.properties property-file-route.groovy --dev +---- + +The property file is parsed and its properties configured on the `Integration`. As soon as the application starts, you will see the log with the expected configuration. + +[[runtime-build-time-conf]] +== Build time properties + +If you're looking for *build-time properties configuration* you can look at the xref:configuration/build-time-properties.adoc[build-time properties] section. \ No newline at end of file diff --git a/docs/modules/ROOT/pages/configuration/runtime-resources.adoc b/docs/modules/ROOT/pages/configuration/runtime-resources.adoc new file mode 100644 index 0000000000..aab28b3b68 --- /dev/null +++ b/docs/modules/ROOT/pages/configuration/runtime-resources.adoc @@ -0,0 +1,148 @@ +[[runtime-resources]] += Runtime resources + +When you develop an integration with `Camel-K` there are many ways you can provide a *resource* to the runtime `Integration`. The most familiar way is to handle local file, but since we are dealing with `Kubernetes` you may need also to use `Configmap` or `Secret`. The `kamel run` command is provided with a `--resource` flag that help you setting any resource your `Integration` may need. + +The *runtime resources* are expected to be any resource type (text or binary content). These resources are materialized as files in the `Ìntegration` `Pod`. The destination path can be either a default location or any path specified by the user. Only default resource directory is available within the `Ìntegration` classpath. + +NOTE: you'll find `--resource` is very similar to the `--config` run flag. The main difference is that a `resource` can have a binary content and it won't be parsed by the Camel Context. + +[[runtime-resource-file]] +== Runtime file resource + +Most of the time you will deal with the need to provide your `Integration` with resource files you have stored in your local machine. In this case you can use the `--resource file:/path/to/file` flag that will copy that file under the _/etc/camel/resources/_ directory. You can look at the _resource destination path_ section at the bottom of this page to specify the destination file location. + +Let's see an example. We want to create an `Integration` unzipping and reading the content of a file we'll provide (ie, _resources-data.zip_): + +[source,groovy] +.resource-file-binary-route.groovy +---- +from('file:/etc/camel/resources/?fileName=resources-data.zip&noop=true&idempotent=false') + .unmarshal().zipFile() + .log('resource file unzipped content is: ${body}') +---- + +We have this file available locally, so we can use the `--resource` _file_ flag command to copy this file in the `Integration`: + +---- +kamel run --resource file:resources-data.zip resource-file-binary-route.groovy -d camel-zipfile --dev +---- + +NOTE: when you're providing a resource file, we try to recognize if it's a binary file and process it accordingly creating a binary representation that will be decoded transparently in the `Integration`. + +You can provide more than one single `resource` at once by just adding the flag repeatedly (ie, `--resource file:file1.txt ---resource file:file2.txt ...`). + +[[runtime-resource-configmap]] +== Runtime configmap resource + +In a `Kubernetes` world we're dealing with `Configmap` that are containing configuration previously stored in the platform. When you need to materialize a `Configmap` into a file resource available at your `Integration`, you can use the `--resource` _configmap_ syntax. + +As an example, let's create a `Configmap` named _my-cm_ containing certain information. You can alternatively use any `Configmap` you've already stored in your cluster: + +---- +kubectl create configmap my-cm --from-literal=my-configmap-key="configmap content" +---- + +We want to use the materialized file in an integration: + +[source,groovy] +.resource-configmap-route.groovy +---- +from('file:/etc/camel/resources/my-cm/?fileName=my-configmap-key&noop=true&idempotent=false') + .log('resource file content is: ${body}') +---- + +You can see that we're expecting to use a _my-configmap-key_ file stored in the default resource location (_/etc/camel/resources/_). In order to materialize the `Configmap` will be as easy as running the `--resource` _configmap_ syntax: + +---- +kamel run --resource configmap:my-cm resource-configmap-route.groovy --dev +---- + +As soon as the `Integration` starts, the `Camel-K` operator will take care to mount a volume with the `Configmap`'s content. + +NOTE: you can provide a `Configmap` which is not yet available on the cluster. The `Integration` won't start until the resource will be made available. + +[[runtime-resource-secret]] +== Runtime secret resource + +We can apply the very same concept seen in the previous section for the Kubernetes `Secret`s. + +As an example, let's create a `Secret` named _my-sec_ containing certain information. You can alternatively use any `Secret` you've already stored in your cluster: + +---- +kubectl create secret generic my-sec --from-literal=my-secret-key="very top secret" +---- + +We want to use the materialized secret file in an integration: + +[source,groovy] +.resource-secret-route.groovy +---- +from('file:/etc/camel/resources/my-sec/?fileName=my-secret-key&noop=true&idempotent=false') + .log('resource file content is: ${body}') +---- + +You can see that we're expecting to use a _my-secret-key_ file stored in the default resource location (_/etc/camel/resources/_). In order to materialize the `Secret` will be as easy as running the `--resource` _secret_ syntax: + +---- +kamel run --resource secret:my-sec resource-secret-route.groovy --dev +---- + +As soon as the `Integration` starts, the `Camel-K` operator will take care to mount a volume with the `Secret`'s content. + +NOTE: you can provide a `Secret` which is not yet available on the cluster. The `Integration` won't start until the resource will be made available. + +[[runtime-resource-path]] +== Resource destination path + +When you are programming an `Integration` you may find yourself in the situation to specify where exactly a resource has to be mounted. For such purpose you can specify the location where a file is expected with the `--resource` _@path_ syntax. + +Let's see an example where your integration expect a text file to be consumed under a specific filesystem location: + +[source,groovy] +.resource-file-location-route.groovy +---- +from('file:/tmp/?fileName=input.txt&noop=true&idempotent=false') + .log('resource file content is: ${body}') +---- + +When running the `Integration`, you can specify where to mount the resource content (either a `File`, `Configmap` or `Secret`) with the _@path_ syntax: + +---- +kamel run --resource file:resources-data.txt@/tmp/input.txt resource-file-location-route.groovy --dev +---- + +You may check in the `Integration` `Pod` and verify the file was mounted in the _tmp/input.txt_ destination. + +[[runtime-resource-keys]] +== Configmap/Secret key filtering + +When you deal with `Configmap` or `Secret`, you may want to limit the quantity of information to recover from such resources. Both `Configmap` and `Secret` can hold more than one resource in the same unit. For this reason you will find a _key_ filtering feature available in the `--resource` flag. In order to use it, you can add a _/key_ notation after the `Configmap` or `Secret` name (ie, `--resource configmap:my-cm/my-key`). + +Let's see an example with multiple `Configmap` in action. The very same concept can be easily applied to `Secret`. We start creating a `Configmap` containing multiple resources: + +---- +kubectl create configmap my-cm-multi --from-literal=my-configmap-key="configmap content" --from-literal=my-configmap-key-2="another content" +---- + +In our `Integration` we plan to use only one of the resources of the `Secret`: + +[source,groovy] +.resource-configmap-key-location-route.groovy +---- +from('file:/tmp/app/data/?fileName=my-configmap-key-2&noop=true&idempotent=false') + .log('resource file content is: ${body} consumed from ${header.CamelFileName}') +---- + +Let's use the _key_ filtering. Also notice that we're combining with the _@path_ syntax to declare where to mount the file: + +---- +kamel run --resource configmap:my-cm-multi/my-configmap-key-2@/tmp/app/data resource-configmap-key-location-route.groovy --dev +---- + +You may check in the `Integration` `Pod` that only the _my-configmap-key-2_ file has been mounted under _/tmp/app/data_ directory. + +[[runtime-resources-config]] +== Runtime config + +If you're looking for *runtime configuration* you can look at the xref:configuration/runtime-config.adoc[runtime configuration] section. \ No newline at end of file diff --git a/examples/README.md b/examples/README.md index a7db7090fe..c6fe58d19d 100644 --- a/examples/README.md +++ b/examples/README.md @@ -25,7 +25,9 @@ In this section you can find a few examples of certain [`Camel` components](http |---|---|---| | AMQP | Component usage | [see examples](./amqp/)| | Caffeine | Component usage | [see examples](./caffeine/)| +| Databases | Component usage | [see examples](./databases/)| | DNS | Component usage | [see examples](./dns/)| +| HTTP/HTTPS | Component usage | [see examples](./http/)| | Kafka | Component usage | [see examples](./kafka/)| | Knative | Component usage | [see examples](./knative/)| diff --git a/examples/databases/PostgresDB.java b/examples/databases/PostgresDB.java new file mode 100644 index 0000000000..2c236a2f1d --- /dev/null +++ b/examples/databases/PostgresDB.java @@ -0,0 +1,46 @@ +/* + * 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. + */ + +// You can use the sample postgres database available at /postgres-deploy/README.md +// +// kamel run PostgresDB.java --dev -d mvn:org.postgresql:postgresql:42.2.21 -d mvn:org.apache.commons:commons-dbcp2:2.8.0 + +import org.apache.camel.builder.RouteBuilder; +import org.apache.commons.dbcp2.BasicDataSource; + +public class PostgresDB extends RouteBuilder { + @Override + public void configure() throws Exception { + registerDatasource(); + + from("timer://foo?period=10000") + .setBody(constant("select * from test")) + .to("jdbc:myPostgresDS") + .to("log:info"); + } + + private void registerDatasource() throws Exception { + BasicDataSource ds = new BasicDataSource(); + ds.setUsername("postgresadmin"); + ds.setDriverClassName("org.postgresql.Driver"); + ds.setPassword("admin123"); + ds.setUrl("jdbc:postgresql://postgres:5432/test"); + + this.getContext().getRegistry().bind("myPostgresDS", ds); + } + +} \ No newline at end of file diff --git a/examples/databases/PostgresDBAutoDatasource.java b/examples/databases/PostgresDBAutoDatasource.java new file mode 100644 index 0000000000..6984e33eed --- /dev/null +++ b/examples/databases/PostgresDBAutoDatasource.java @@ -0,0 +1,45 @@ +/* + * 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. + */ + +// kamel run PostgresDBAutoDatasource.java --dev +// --build-property quarkus.datasource.camel.db-kind=postgresql +// -p quarkus.datasource.camel.jdbc.url=jdbc:postgresql://postgres:5432/test +// -p quarkus.datasource.camel.username=postgresadmin +// -p quarkus.datasource.camel.password=admin123 +// -d mvn:io.quarkus:quarkus-jdbc-postgresql:1.13.7.Final +// +// Alternatively, you can bundle your credentials as a secret properties file: +// +// kubectl create secret generic my-datasource --from-file=datasource.properties +// +// kamel run PostgresDBAutoDatasource.java --dev +// --build-property quarkus.datasource.camel.db-kind=postgresql +// --config secret:my-datasource +// -d mvn:io.quarkus:quarkus-jdbc-postgresql:1.13.7.Final + +import org.apache.camel.builder.RouteBuilder; + +public class PostgresDBAutoDatasource extends RouteBuilder { + @Override + public void configure() throws Exception { + from("timer://foo?period=10000") + .setBody(constant("select * from test")) + .to("jdbc:camel") + .to("log:info"); + } + +} \ No newline at end of file diff --git a/examples/databases/README.md b/examples/databases/README.md new file mode 100644 index 0000000000..301a077f4f --- /dev/null +++ b/examples/databases/README.md @@ -0,0 +1,3 @@ +# Examples showing how to connect Camel K with databases + +Find useful examples about how to develop a Camel K integration connecting to a database. \ No newline at end of file diff --git a/examples/databases/datasource.properties b/examples/databases/datasource.properties new file mode 100644 index 0000000000..587ca7fcfc --- /dev/null +++ b/examples/databases/datasource.properties @@ -0,0 +1,3 @@ +quarkus.datasource.camel.jdbc.url=jdbc:postgresql://postgres:5432/test +quarkus.datasource.camel.username=postgresadmin +quarkus.datasource.camel.password=admin123 \ No newline at end of file diff --git a/examples/databases/postgres-deploy/README.md b/examples/databases/postgres-deploy/README.md new file mode 100644 index 0000000000..0b095b43c8 --- /dev/null +++ b/examples/databases/postgres-deploy/README.md @@ -0,0 +1,30 @@ +# How to deploy a simple Postgres DB to Kubernetes cluster + +This is a very simple example to show how to create a Postgres database. **Note**, this is not ready for any production purposes. + +## Create a Kubernetes Deployment +``` +kubectl create -f postgres-configmap.yaml +kubectl create -f postgres-storage.yaml +kubectl create -f postgres-deployment.yaml +kubectl create -f postgres-service.yaml +``` +## Thest the connection + +Connection credentials available in the _postgres-configmap.yaml_ descriptor. + +``` +kubectl get svc postgres +psql -h -U postgresadmin1 --password -p postgresdb +``` +## Create a test database and table +``` +CREATE DATABASE test; +CREATE TABLE test (data TEXT PRIMARY KEY); +INSERT INTO test(data) VALUES ('hello'), ('world'); +``` +### Read the test database and table +``` +SELECT * FROM test; +``` + diff --git a/examples/databases/postgres-deploy/postgres-configmap.yaml b/examples/databases/postgres-deploy/postgres-configmap.yaml new file mode 100644 index 0000000000..c94b6ad16a --- /dev/null +++ b/examples/databases/postgres-deploy/postgres-configmap.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: postgres-config + labels: + app: postgres +data: + POSTGRES_DB: postgresdb + POSTGRES_USER: postgresadmin + POSTGRES_PASSWORD: admin123 \ No newline at end of file diff --git a/examples/databases/postgres-deploy/postgres-deployment.yaml b/examples/databases/postgres-deploy/postgres-deployment.yaml new file mode 100644 index 0000000000..001d2eca4c --- /dev/null +++ b/examples/databases/postgres-deploy/postgres-deployment.yaml @@ -0,0 +1,30 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: postgres +spec: + replicas: 1 + selector: + matchLabels: + app: postgres + template: + metadata: + labels: + app: postgres + spec: + containers: + - name: postgres + image: postgres:10.4 + imagePullPolicy: "IfNotPresent" + ports: + - containerPort: 5432 + envFrom: + - configMapRef: + name: postgres-config + volumeMounts: + - mountPath: /var/lib/postgresql/data + name: postgredb + volumes: + - name: postgredb + persistentVolumeClaim: + claimName: postgres-pv-claim \ No newline at end of file diff --git a/examples/databases/postgres-deploy/postgres-service.yaml b/examples/databases/postgres-deploy/postgres-service.yaml new file mode 100644 index 0000000000..f3ed357579 --- /dev/null +++ b/examples/databases/postgres-deploy/postgres-service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: postgres + labels: + app: postgres +spec: + type: NodePort + ports: + - port: 5432 + selector: + app: postgres \ No newline at end of file diff --git a/examples/databases/postgres-deploy/postgres-storage.yaml b/examples/databases/postgres-deploy/postgres-storage.yaml new file mode 100644 index 0000000000..36a8db28d2 --- /dev/null +++ b/examples/databases/postgres-deploy/postgres-storage.yaml @@ -0,0 +1,29 @@ +kind: PersistentVolume +apiVersion: v1 +metadata: + name: postgres-pv-volume + labels: + type: local + app: postgres +spec: + storageClassName: manual + capacity: + storage: 5Gi + accessModes: + - ReadWriteMany + hostPath: + path: "/mnt/data" +--- +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: postgres-pv-claim + labels: + app: postgres +spec: + storageClassName: manual + accessModes: + - ReadWriteMany + resources: + requests: + storage: 5Gi \ No newline at end of file diff --git a/examples/http/NettySecureServer.java b/examples/http/NettySecureServer.java new file mode 100644 index 0000000000..a31dc19627 --- /dev/null +++ b/examples/http/NettySecureServer.java @@ -0,0 +1,55 @@ +/* + * 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. + */ + +// kamel run NettySecureServer.java --resource file:KeyStore.jks@/etc/ssl/keystore.jks +// --resource file:truststore.jks@/etc/ssl/truststore.jks -t container.port=8443 --dev +// +// recover the service location. If you're running on minikube, "minikube service netty-secure-server --url=true --https=true" +// curl https:///hello +// + +import org.apache.camel.builder.RouteBuilder; + +import org.apache.camel.support.jsse.*; + +public class NettySecureServer extends RouteBuilder { + @Override + public void configure() throws Exception { + registerSslContextParameter(); + from("netty-http:https://0.0.0.0:8443/hello?sslContextParameters=#sslContextParameters&ssl=true") + .transform().constant("Hello Secure World"); + } + + private void registerSslContextParameter() throws Exception { + KeyStoreParameters ksp = new KeyStoreParameters(); + ksp.setResource("/etc/ssl/keystore.jks"); + ksp.setPassword("changeit"); + KeyManagersParameters kmp = new KeyManagersParameters(); + kmp.setKeyPassword("changeit"); + kmp.setKeyStore(ksp); + KeyStoreParameters tsp = new KeyStoreParameters(); + tsp.setResource("/etc/ssl/truststore.jks"); + tsp.setPassword("changeit"); + TrustManagersParameters tmp = new TrustManagersParameters(); + tmp.setKeyStore(tsp); + SSLContextParameters sslContextParameters = new SSLContextParameters(); + sslContextParameters.setKeyManagers(kmp); + sslContextParameters.setTrustManagers(tmp); + + this.getContext().getRegistry().bind("sslContextParameters", sslContextParameters); + } +} \ No newline at end of file diff --git a/examples/http/NettyServer.java b/examples/http/NettyServer.java new file mode 100644 index 0000000000..050e889aa0 --- /dev/null +++ b/examples/http/NettyServer.java @@ -0,0 +1,32 @@ +/* + * 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. + */ + +// kamel run NettyServer.java --dev +// +// recover the service location. If you're running on minikube, minikube service netty-server --url=true +// curl http:///hello +// + +import org.apache.camel.builder.RouteBuilder; + +public class NettyServer extends RouteBuilder { + @Override + public void configure() throws Exception { + from("netty-http:http://0.0.0.0:8080/hello") + .transform().constant("Hello World"); + } +} \ No newline at end of file diff --git a/examples/http/PlatformHttpServer.java b/examples/http/PlatformHttpServer.java new file mode 100644 index 0000000000..42b50d832f --- /dev/null +++ b/examples/http/PlatformHttpServer.java @@ -0,0 +1,31 @@ +/* + * 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. + */ + +// kamel run PlatformHttpServer.java --dev -t service.enabled=true +// +// recover the service location. If you're running on minikube, minikube service platform-http-server --url=true +// curl -H "name:World" http:///hello +// + +import org.apache.camel.builder.RouteBuilder; + +public class PlatformHttpServer extends RouteBuilder { + @Override + public void configure() throws Exception { + from("platform-http:/hello?httpMethodRestrict=GET").setBody(simple("Hello ${header.name}")); + } +} \ No newline at end of file diff --git a/examples/http/PlatformHttpsServer.java b/examples/http/PlatformHttpsServer.java new file mode 100644 index 0000000000..cf07fc82da --- /dev/null +++ b/examples/http/PlatformHttpsServer.java @@ -0,0 +1,47 @@ +/* + * 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. + */ + +// Self signed certificate generation: +// +// openssl genrsa -out server.key 2048 +// openssl req -new -key server.key -out server.csr +// openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt + +// Storing certificate and keys in a secret +// kubectl create secret generic my-self-signed-ssl --from-file=server.key --from-file=server.crt + +// Integration execution +// +// kamel run PlatformHttpsServer.java -p quarkus.http.ssl.certificate.file=/etc/ssl/my-self-signed-ssl/server.crt \ +// -p quarkus.http.ssl.certificate.key-file=/etc/ssl/my-self-signed-ssl/server.key \ +// --resource secret:my-self-signed-ssl@/etc/ssl/my-self-signed-ssl \ +// -t container.port=8443 --dev + +// Test +// +// recover the service location. If you're running on minikube, minikube service platform-https-server --url=true +// curl -H "name:World" -k https:///hello +// + +import org.apache.camel.builder.RouteBuilder; + +public class PlatformHttpsServer extends RouteBuilder { + @Override + public void configure() throws Exception { + from("platform-http:/hello?httpMethodRestrict=GET").setBody(simple("Hello ${header.name}")); + } +} \ No newline at end of file diff --git a/examples/http/README.md b/examples/http/README.md new file mode 100644 index 0000000000..361ce9face --- /dev/null +++ b/examples/http/README.md @@ -0,0 +1,3 @@ +# Examples showing how to interact with HTTP/HTTPS protocol + +Find useful examples about how to develop a Camel K integration leveraging `Http`/`Https` protocol. \ No newline at end of file diff --git a/examples/modeline/modeline-resource-file-route.groovy b/examples/modeline/modeline-resource-file-route.groovy index e02777a4db..7bdcaf6328 100644 --- a/examples/modeline/modeline-resource-file-route.groovy +++ b/examples/modeline/modeline-resource-file-route.groovy @@ -23,5 +23,5 @@ // camel-k: resource=file:resources-data.txt -from('file:/etc/camel/data/resources/?fileName=resources-data.txt&noop=true&idempotent=false') +from('file:/etc/camel/resources/?fileName=resources-data.txt&noop=true&idempotent=false') .log('resource file content is: ${body}')