diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index 6169a8c0b9..fb4ee9d93d 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -21,6 +21,7 @@ ** xref:traits/camel.adoc[Camel] ** xref:traits/classpath.adoc[Classpath] ** xref:traits/container.adoc[Container] +** xref:traits/cron.adoc[Cron] ** xref:traits/debug.adoc[Debug] ** xref:traits/dependencies.adoc[Dependencies] ** xref:traits/deployer.adoc[Deployer] diff --git a/docs/modules/ROOT/pages/traits/cron.adoc b/docs/modules/ROOT/pages/traits/cron.adoc new file mode 100755 index 0000000000..5875145ca3 --- /dev/null +++ b/docs/modules/ROOT/pages/traits/cron.adoc @@ -0,0 +1,83 @@ += Cron Trait + +// Start of autogenerated code - DO NOT EDIT! (description) +The Cron trait can be used to customize the behaviour of periodic timer/cron based integrations. + +While normally an integration requires a pod to be always up and running, some periodic tasks, such as batch jobs, +require to be activated at specific hours of the day or with a periodic delay of minutes. +For such tasks, the cron trait can materialize the integration as a Kubernetes CronJob instead of a standard deployment, +in order to save resources when the integration does not need to be executed. + +Integrations that start from the following components are evaluated by the cron trait: `timer`, `cron`, `quartz`. + +The rules for using a Kubernetes CronJob are the following: +- `timer`: when periods can be written as cron expressions. E.g. `timer:tick?period=1m`. +- `cron`, `quartz`: when the cron expression does not contain seconds (or the "seconds" part is set to 0). E.g. + `cron:tab?schedule=0/2+*+*+*+?` or `quartz:trigger?cron=0+0/2+*+*+*+?`. + + +This trait is available in the following profiles: **Kubernetes, Knative, OpenShift**. + +// End of autogenerated code - DO NOT EDIT! (description) + +== Examples + +The following route is materialized into a Kubernetes CronJob by the `cron` trait: + +.cron.groovy +[source,groovy] +---- +from('timer:groovy?period=1m') // Setting the period e.g. to '1s' restores the default behavior + .setBody() + .simple('Hello World from Camel K in a CronJob') + .to('log:info?showAll=false') +---- + +// Start of autogenerated code - DO NOT EDIT! (configuration) +== Configuration + +Trait properties can be specified when running any integration with the CLI: +``` +kamel run --trait cron.[key]=[value] integration.groovy +``` +The following configuration options are available: + +[cols="2,1,5a"] +|=== +|Property | Type | Description + +| cron.enabled +| bool +| Can be used to enable or disable a trait. All traits share this common property. + +| cron.schedule +| string +| The CronJob schedule for the whole integration. If multiple routes are declared, they must have the same schedule for this +mechanism to work correctly. + +| cron.schedule +| string +| A comma separated list of the Camel components that need to be customized in order for them to work when the schedule is triggered externally by Kubernetes. +A specific customizer is activated for each specified component. E.g. for the `timer` component, the `cron-timer` customizer is +activated (it's present in the `org.apache.camel.k:camel-k-runtime-cron` library). + +Supported components are currently: `cron`, `timer` and `quartz`. + +| cron.fallback +| bool +| Use the default Camel implementation of the `cron` endpoint (`quartz`) instead of trying to materialize the integration +as Kubernetes CronJob. + +| cron.auto +| bool +| Automatically deploy the integration as CronJob when all routes are +either starting from a periodic consumer (only `cron`, `timer` and `quartz` are supported) or a passive consumer (e.g. `direct` is a passive consumer). + +It's required that all periodic consumers have the same period and it can be expressed as cron schedule (e.g. `1m` can be expressed as `0/1 * * * *`, +while `35m` or `50s` cannot). + +|=== + +// End of autogenerated code - DO NOT EDIT! (configuration) + +== Examples diff --git a/docs/modules/ROOT/pages/traits/deployer.adoc b/docs/modules/ROOT/pages/traits/deployer.adoc index 44976b6bd7..f1427acc76 100755 --- a/docs/modules/ROOT/pages/traits/deployer.adoc +++ b/docs/modules/ROOT/pages/traits/deployer.adoc @@ -29,7 +29,7 @@ The following configuration options are available: | deployer.kind | string -| Allows to explicitly select the desired deployment kind between `deployment` or `knative-service` when creating the resources for running the integration. +| Allows to explicitly select the desired deployment kind between `deployment`, `cron-job` or `knative-service` when creating the resources for running the integration. |=== diff --git a/docs/modules/ROOT/pages/traits/traits.adoc b/docs/modules/ROOT/pages/traits/traits.adoc index 1312b4d343..44bc59e30a 100644 --- a/docs/modules/ROOT/pages/traits/traits.adoc +++ b/docs/modules/ROOT/pages/traits/traits.adoc @@ -39,6 +39,7 @@ See the trait description pages for more information on a specific trait: * xref:traits/camel.adoc[Camel Trait] * xref:traits/classpath.adoc[Classpath Trait] * xref:traits/container.adoc[Container Trait] +* xref:traits/cron.adoc[Cron Trait] * xref:traits/debug.adoc[Debug Trait] * xref:traits/dependencies.adoc[Dependencies Trait] * xref:traits/deployer.adoc[Deployer Trait] diff --git a/e2e/cron_test.go b/e2e/cron_test.go index 3c0cc0d2e1..0c7730c221 100644 --- a/e2e/cron_test.go +++ b/e2e/cron_test.go @@ -42,6 +42,15 @@ func TestRunCronExample(t *testing.T) { Expect(kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil()) }) + t.Run("cron-timer", func(t *testing.T) { + RegisterTestingT(t) + + Expect(kamel("run", "-n", ns, "files/cron-timer.groovy").Execute()).Should(BeNil()) + Eventually(integrationCronJob(ns, "cron-timer"), 5*time.Minute).ShouldNot(BeNil()) + Eventually(integrationLogs(ns, "cron-timer"), 5*time.Minute).Should(ContainSubstring("Magicstring!")) + Expect(kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil()) + }) + t.Run("cron-fallback", func(t *testing.T) { RegisterTestingT(t) diff --git a/e2e/files/cron-timer.groovy b/e2e/files/cron-timer.groovy new file mode 100644 index 0000000000..965181bb14 --- /dev/null +++ b/e2e/files/cron-timer.groovy @@ -0,0 +1,23 @@ +/* + * 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. + */ + +from('timer:tick?period=1m') + .routeId('groovy') + .setHeader("m").constant("string!") + .setBody() + .simple('Magic${header.m}') + .to('log:info?showAll=false') diff --git a/pkg/trait/cron.go b/pkg/trait/cron.go index 61fe1f5579..42da57d171 100644 --- a/pkg/trait/cron.go +++ b/pkg/trait/cron.go @@ -37,6 +37,18 @@ import ( // The Cron trait can be used to customize the behaviour of periodic timer/cron based integrations. // +// While normally an integration requires a pod to be always up and running, some periodic tasks, such as batch jobs, +// require to be activated at specific hours of the day or with a periodic delay of minutes. +// For such tasks, the cron trait can materialize the integration as a Kubernetes CronJob instead of a standard deployment, +// in order to save resources when the integration does not need to be executed. +// +// Integrations that start from the following components are evaluated by the cron trait: `timer`, `cron`, `quartz`. +// +// The rules for using a Kubernetes CronJob are the following: +// - `timer`: when periods can be written as cron expressions. E.g. `timer:tick?period=1m`. +// - `cron`, `quartz`: when the cron expression does not contain seconds (or the "seconds" part is set to 0). E.g. +// `cron:tab?schedule=0/2+*+*+*+?` or `quartz:trigger?cron=0+0/2+*+*+*+?`. +// // +camel-k:trait=cron type cronTrait struct { BaseTrait `property:",squash"`