测试指南 Camel K


Red Hat build of Apache Camel K 1.10.7

在本地和云基础架构中测试您的 Camel K 集成

摘要

如何使用 jBang 在本地测试红帽构建的 Apache Camel K,并在云基础架构上使用 YAKS。

前言

使开源包含更多

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。我们从这四个术语开始:master、slave、黑名单和白名单。由于此项工作十分艰巨,这些更改将在即将推出的几个发行版本中逐步实施。详情请查看 CTO Chris Wright 的信息

第 1 章 本地测试 Camel K 集成

本章详细介绍了如何使用 Camel jBang 在本地测试 Camel K 集成。

1.1. 使用 Camel jBang 本地测试 Camel K 集成

测试是构建任何应用程序时重复执行的主要操作之一。随着 Camel JBang 的出现,我们有一个统一的位置,可用于在本地执行测试和微调,然后再移至更高的环境。

测试或调优直接连接到 云原生 环境的集成是一个繁琐。您必须连接到集群,或者需要在计算机上运行的本地 Kubernetes 集群(Minikube、Kind 等)。大多数时候,集群调优所固有的特性都在开发后期。

因此,最好在本地测试应用程序,并进入一个部署阶段,我们将这个调整应用到云原生环境。

kamel local 是过去本地测试集成的命令。但是,它重叠了 Camel 社区所完成的工作,使单个 CLI 用于独立测试本地 Camel 应用程序,这将部署的位置。

1.1.1. Camel JBang 安装

首先,我们需要安装并熟悉 jbangcamel CLI。您可以按照 Camel JBang 的官方文档 将 CLI 安装到本地环境中。之后,我们可以了解如何使用 Camel JBang 测试 Camel K 集成。

1.1.2. 简单的应用程序开发

我们开发的第一个应用程序是一个简单的,它定义了在测试 Kubernetes 中最终通过 Camel K 部署的任何集成时必须遵循的流程。验证 Camel K 安装中的 Camel 的目标版本。通过这些信息,我们可以确保针对以后在集群中部署的相同版本进行本地测试。

$ kamel version -a -v | grep Runtime
Runtime Version: 3.8.1

$ kubectl get camelcatalog camel-catalog-3.8.1 -o yaml | grep camel\.version
      camel.version: 3.8.1

以上命令可用于查找集群 Camel K 安装中运行时使用的 Camel 版本。我们的目标是 Camel 版本 3.18.3。

初始化 Camel 路由的最简单方法是运行 camel init 命令:

$ camel init HelloJBang.java

在这个阶段,我们可使用集成所需的逻辑编辑该文件,或者只运行它:

$ camel run HelloJBang.java
2022-11-23 12:11:05.407  INFO 52841 --- [           main] org.apache.camel.main.MainSupport        : Apache Camel (JBang) 3.18.1 is starting
2022-11-23 12:11:05.470  INFO 52841 --- [           main] org.apache.camel.main.MainSupport        : Using Java 11.0.17 with PID 52841. Started by squake in /home/squake/workspace/jbang/camel-blog
2022-11-23 12:11:07.537  INFO 52841 --- [           main] e.camel.impl.engine.AbstractCamelContext : Apache Camel 3.18.1 (CamelJBang) is starting
2022-11-23 12:11:07.675  INFO 52841 --- [           main] e.camel.impl.engine.AbstractCamelContext : Routes startup (started:1)
2022-11-23 12:11:07.676  INFO 52841 --- [           main] e.camel.impl.engine.AbstractCamelContext :     Started java (timer://java)
2022-11-23 12:11:07.676  INFO 52841 --- [           main] e.camel.impl.engine.AbstractCamelContext : Apache Camel 3.18.1 (CamelJBang) started in 397ms (build:118ms init:140ms start:139ms JVM-uptime:3s)
2022-11-23 12:11:08.705  INFO 52841 --- [ - timer://java] HelloJBang.java:14                       : Hello Camel from java
2022-11-23 12:11:09.676  INFO 52841 --- [ - timer://java] HelloJBang.java:14                       : Hello Camel from java
...

本地 java 进程以正在运行的 Camel 应用程序开头。不需要创建 Maven 项目,所有 boilerplate 都位于 Camel JBang!但是,您可能会注意到使用的 Camel 版本与您要目标的 Camel 版本不同。这是因为您的 Camel JBang 使用不同的 Camel 版本。不小心,我们可以重新运行这个应用程序,但指定要运行的 Camel 版本:

$ jbang run -Dcamel.jbang.version=3.18.3 camel@apache/camel run HelloJBang.java
...
[1] 2022-11-23 11:13:02,825 INFO  [org.apa.cam.imp.eng.AbstractCamelContext] (main) Apache Camel 3.18.3 (camel-1) started in 70ms (build:0ms init:61ms start:9ms)
...
注意

Camel JBang 使用默认的 Camel 版本,如果您希望使用 -Dcamel.jbang.version 选项来明确设置 Camel 版本覆盖默认值。

下一步是在安装 Camel K 的 Kubernetes 集群中运行它。

我们在这里使用 Camel K 插件进行 Camel JBang,而不是 kamel CLI。这样,您可以使用相同的 JBang 工具在本地和 K8s 集群中使用 Operator 运行 Camel K 集成。JBang 插件文档可在此处找到: Camel JBang Kubernetes

您会看到 Camel K 操作员需要谨慎进行必要的转换,并根据预期生命周期构建集成和相关资源。当它处于活动状态后,您可以跟踪通常在部署的集成上执行的操作。

这个过程的好处是,在在本地使用 Integration 调整后,您不需要担心远程集群。

1.1.3. 对云的微调

集成就绪后,您必须注意与集群部署相关的调整类型。因此,您不必担心开发早期的部署详情。或者您甚至可以有单独的角色,域专家可以在本地开发集成,并且集群专家可以在后续阶段进行部署。

让我们来看看如何开发一个集成的示例,以便稍后在集群中进行一些微调。

import org.apache.camel.builder.RouteBuilder;

public class MyJBangRoute extends RouteBuilder {

    @Override
    public void configure() throws Exception {
        from("file:/tmp/input")
            .convertBodyTo(String.class)
            .log("Processing file ${headers.CamelFileName} with content: ${body}")
            /*
            .filter(simple("${body} !contains 'checked'"))
                .log("WARN not checked: ${body}")
                .to("file:/tmp/discarded")
            .end()
            .to("file:/tmp/output");
            */
            .choice()
                .when(simple("${body} !contains 'checked'"))
                    .log("WARN not checked!")
                    .to("file:/tmp/discarded")
                .otherwise()
                    .to("file:/tmp/output")
            .end();
    }
}

有一个进程负责将文件写入到目录中。您必须根据其内容过滤这些文件。我们的目的是将代码注释保留下来,因为它是我们迭代开发的方式。我们通过 Camel JBang 在本地测试某个内容,直到我们进入集成的最终版本。我们已测试了 Filter EIP,但在测试时,我们需要一个 基于内容的路由器 EIP。它必须听起来非常熟悉的过程,因为每次开发某项时都会发生。

现在我们已准备好,我们通过 Camel JBang 在本地运行最后一轮测试:

$ jbang run -Dcamel.jbang.version=3.18.3 camel@apache/camel run MyJBangRoute.java
2022-11-23 12:19:11.516  INFO 55909 --- [           main] org.apache.camel.main.MainSupport        : Apache Camel (JBang) 3.18.3 is starting
2022-11-23 12:19:11.592  INFO 55909 --- [           main] org.apache.camel.main.MainSupport        : Using Java 11.0.17 with PID 55909. Started by squake in /home/squake/workspace/jbang/camel-blog
2022-11-23 12:19:14.020  INFO 55909 --- [           main] e.camel.impl.engine.AbstractCamelContext : Apache Camel 3.18.3 (CamelJBang) is starting
2022-11-23 12:19:14.220  INFO 55909 --- [           main] e.camel.impl.engine.AbstractCamelContext : Routes startup (started:1)
2022-11-23 12:19:14.220  INFO 55909 --- [           main] e.camel.impl.engine.AbstractCamelContext :     Started route1 (file:///tmp/input)
2022-11-23 12:19:14.220  INFO 55909 --- [           main] e.camel.impl.engine.AbstractCamelContext : Apache Camel 3.18.3 (CamelJBang) started in 677ms (build:133ms init:344ms start:200ms JVM-uptime:3s)
2022-11-23 12:19:27.757  INFO 55909 --- [le:///tmp/input] MyJBangRoute.java:11                     : Processing file file_1669202367381 with content: some entry

2022-11-23 12:19:27.758  INFO 55909 --- [le:///tmp/input] MyJBangRoute:21                          : WARN not checked!
2022-11-23 12:19:32.276  INFO 55909 --- [le:///tmp/input] MyJBangRoute.java:11                     : Processing file file_1669202372252 with content: some entry checked

我们已测试在输入目录中添加文件。准备推广至我的开发集群!

使用此处的 Camel K JBang 插件在 K8s 上运行集成,因此您不需要切换工具。

运行以下命令:

camel k run MyJBangRoute.java

集成正常启动,但我们使用了文件系统,这是运行集成的 Pod 的本地文件系统。

1.1.3.1. Kubernetes 调优

现在,让我们为云配置应用程序。云原生开发必须考虑一系列在这种新范式工作方式中隐式存在的挑战(作为参考,请参见 12 个因素)。

Kubernetes 有时可能很难进行微调。许多要编辑和检查的资源。Camel K 提供了一种用户友好的方式,可以在 kamel run 命令中(或在 模式行中)直接应用大多数调整应用程序。您必须熟悉 Camel K Traits

在这种情况下,我们想要使用集群中已提供的某些卷。我们可以使用-- volume 选项( 挂载特征的syntactic sugar )并轻松启用它们。我们可以从其他一些 Pod 中读取和写入这些卷:它取决于我们的集成流程的架构。

$ kamel run MyJBangRoute.java --volume my-pv-claim-input:/tmp/input --volume my-pv-claim-output:/tmp/output --volume my-pv-claim-discarded:/tmp/discarded --dev
...
[1] 2022-11-23 11:39:26,281 INFO  [route1] (Camel (camel-1) thread #1 - file:///tmp/input) Processing file file_1669203565971 with content: some entry
[1]
[1] 2022-11-23 11:39:26,303 INFO  [route1] (Camel (camel-1) thread #1 - file:///tmp/input) WARN not checked!
[1] 2022-11-23 11:39:32,322 INFO  [route1] (Camel (camel-1) thread #1 - file:///tmp/input) Processing file file_1669203571981 with content: some entry checked

您还必须迭代此调优,但至少要使路由的内部内部已在本地进行监控,您必须只专注于部署方面。一旦您准备好这样做,请利用 kamel promote 的优势在开发的不同阶段移动您的集成

1.1.4. 如何在本地测试 Kamelet?

Camel JBang 的另一个优点在于能够在本地测试 Kamelet。到目前为止,测试 Kamelet 的最简单方法是上传到 Kubernetes 集群,并通过 Camel K 运行一些集成。

让我们开发了此范围的简单 Kamelet。这是一个 Coffee 源,我们用来生成随机的 coffee 事件。

apiVersion: camel.apache.org/v1
kind: Kamelet
metadata:
  name: coffee-source
  annotations:
    camel.apache.org/kamelet.support.level: "Stable"
    camel.apache.org/catalog.version: "4.7.0-SNAPSHOT"
    camel.apache.org/kamelet.icon: "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iOTJwdCIgd2lkdGg9IjkycHQiIHZlcnNpb249IjEuMCIgeG1sbnM6Y2M9Imh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL25zIyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyI+Cgk8ZGVmcz4KCQk8bGluZWFyR3JhZGllbnQgaWQ9ImEiPgoJCQk8c3RvcCBzdG9wLWNvbG9yPSIjZmZmZmZmIiBzdG9wLW9wYWNpdHk9Ii41IiBvZmZzZXQ9IjAiLz4KCQkJPHN0b3Agc3RvcC1jb2xvcj0iI2ZmZmZmZiIgc3RvcC1vcGFjaXR5PSIuMSIgb2Zmc2V0PSIxIi8+CgkJPC9saW5lYXJHcmFkaWVudD4KCQk8bGluZWFyR3JhZGllbnQgaWQ9ImQiIHkyPSI2Mi4yOTkiIHhsaW5rOmhyZWY9IiNhIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeTE9IjMzLjYxIiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KC43ODQ3OSAwIDAgMS4yNzQyIC0yNS42OTEgLTguNTYzNSkiIHgyPSI5NS42ODkiIHgxPSI1OS4wOTkiLz4KCQk8bGluZWFyR3JhZGllbnQgaWQ9ImMiIHkyPSIyNDEuMDkiIHhsaW5rOmhyZWY9IiNhIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeTE9IjIwOC4wNCIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgxLjk3NzcgMCAwIC41MDU2MyAtMjUuNjkxIC04LjU2MzUpIiB4Mj0iMjguMTc5IiB4MT0iMTcuNDAyIi8+CgkJPGxpbmVhckdyYWRpZW50IGlkPSJiIiB5Mj0iODAuOTA5IiB4bGluazpocmVmPSIjYSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHkxPSI1NS45ODgiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoMS41NDY5IDAgMCAuNjQ2NDcgLTI1LjY5MSAtOC41NjM1KSIgeDI9Ijg3LjA3NCIgeDE9IjcwLjA2MyIvPgoJPC9kZWZzPgoJPHBhdGggc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgZD0ibTEyLjQ2MyAyNC44ODZjMi4zNTIgMS4yMjYgMjIuMzY4IDUuNDg4IDMzLjk3MiA1LjIyNiAxNi41MjcgMC4yNjIgMzAuMzEzLTYuMDQ5IDMyLjkyNy03LjA1NSAwIDEuNDMzLTIuMzA3IDEwLjI3My0yLjYxNCAxNS42NzkgMCA1LjQ0OCAxLjgzIDI4LjQxNSAyLjA5MSAzMy43MTEgMC44NjggNi4xNzggMi43MDQgMTMuODYxIDQuNDQzIDE5LjA3NyAxLjgyOSAzLjU1My0yMy41NjMgOS44NTYtMzQuNzU3IDEwLjQ1Ni0xMi42MDIgMC43OC0zOC45MzctNC4zNzUtMzcuMzY5LTguMzY2IDAtMy45NjggMy42NTktMTMuMzgzIDMuNjU5LTE5LjU5OSAwLjUyMi02LjAyNS0wLjI2Mi0yMy4yNzMtMC4yNjItMzAuODM2LTAuMjYxLTYuNzgtMS4wNTMtMTIuNTYxLTIuMDktMTguMjkzeiIgZmlsbC1ydWxlPSJldmVub2RkIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMXB0IiBmaWxsPSIjZmJkOTAwIi8+Cgk8cGF0aCBkPSJtMTAuNjMzIDk0LjY1OWMtNS41ODUxLTEuMzMxLTcuODc4NiAxMC4xMTEtMS44Mjg4IDEyLjAyMSA2LjM2NzggMy43NSAyOS43MDMgNy4wNiAzOS4xOTkgNi4yNyAxMS4xMDEtMC4yNiAzMS4xOTItNC40NCAzNS44MDEtOC4zNiA2LjEzNC0zLjkyIDUuNDY2LTEzLjA2NiAwLTEyLjAyMS0zLjI3OCAzLjY1OC0yNi42OTkgOC44ODEtMzYuNTg1IDkuNDExLTkuMjIzIDAuNzgtMzAuNzQ5LTIuNTMtMzYuNTg2LTcuMzIxeiIgZmlsbC1ydWxlPSJldmVub2RkIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMXB0IiBmaWxsPSIjZmJmM2JmIi8+Cgk8cGF0aCBzdHJva2UtbGluZWpvaW49ImJldmVsIiBkPSJtNzcuMzgyIDM0LjA0NmMxLjI0NS0zLjIxMiA5LjYzOS02Ljk3MiAxMi4zNjQtNy41MTYgNC42ODYtMS4wNSAxMi4zODQtMS4zODggMTYuNzY0IDQuMjggNy45NCAxMC4zMjMgNi43NiAyOC42MjYgMi44NiAzNC42MzgtMi43OCA1LjEwNC05LjM3MSAxMC4yODItMTQuNjM1IDExLjg3OC01LjE1MSAxLjUzMy0xMi43MDcgMi42NjEtMTQuMzMzIDMuNzExLTAuMzUtMS4yOTYtMS4zMjctNy4zODgtMS4zOC05LjA3MSAxLjk1IDAuMTI4IDcuNDg5LTAuODkzIDExLjY5NS0xLjg2OCAzLjkwMi0wLjg5OSA2LjQ1LTMuMjc0IDkuMzMzLTYuMjIyIDUtNC43IDQuMzUtMjEuMTYgMC41NC0yNS4wNTctMi4yMzMtMi4yNjItNi44NDktMy45MDQtOS45MTUtMy4zMjMtNC45OTIgMS4wMzItMTMuNjc3IDcuMzY2LTEzLjY3NyA2Ljk4LTAuNTA4LTIuMDgtMC4yNS02LjE1OSAwLjM4NC04LjQzeiIgZmlsbC1ydWxlPSJldmVub2RkIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMS4yNSIgZmlsbD0iI2ZiZjNiZiIvPgoJPHBhdGggc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgZD0ibTMyLjAyMiAzOC4zNjhjMS42NTUgMS4yMDYtMS4zNTUgMTYuOTU1LTAuOTQyIDI4LjEzMSAwLjQxNCAxNC4yOTUgMS40NDQgMjMuNTI4LTAuNTIxIDI0LjYzNS0zLjEwOCAxLjY3NS05LjkwMS0wLjEzNS0xMi4wNDYtMi40Mi0xLjI3My0xLjUwNyAxLjgwNi0xMC4yNCAyLjAxMy0xNi40MjktMC40MTQtOC43MTEtMS43MDMtMzMuMzAzLTAuNDYxLTM0Ljc3OCAyLjI1Mi0yLjA1MyA5LjY4MS0xLjE1MiAxMS45NTcgMC44NjF6IiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjI1IiBmaWxsPSIjZmJlNjAwIi8+Cgk8cGF0aCBkPSJtNDAuNjEyIDM5LjAzN2MtMS40NzggMS40MjQtMC4wNjMgMTkuNjI1LTAuMDYzIDIyLjU1OSAwLjMwNSAzLjgwOC0xLjEwMSAyNy40NTItMC4xNzggMjguOTU0IDEuODQ4IDIuMTIyIDEwLjIxNiAyLjQ0MiAxMy4wMDEtMC4zNTYgMS41MDUtMS44NzUtMC40NzgtMjIuNTQ0LTAuNDc4LTI3LjY4IDAtNS41MSAxLjQwNy0yMi4wNTItMC40NC0yMy41OC0yLjAzMy0yLjE0OS04LjQ0LTMuMTgtMTEuODQyIDAuMTAzeiIgZmlsbC1ydWxlPSJldmVub2RkIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMXB0IiBmaWxsPSIjZmJlNjAwIi8+Cgk8cGF0aCBzdHJva2UtbGluZWpvaW49InJvdW5kIiBkPSJtNjAuMzAxIDM3LjU5M2MtMS42NTggMS4yNTYgMS4xNzkgMTUuOCAxLjE5NCAyNi45ODIgMC4xMzcgMTQuMjk5LTEuMjQ1IDI0LjY2MiAwLjgyNCAyNS43MDkgMy4yNjggMS41NzggMTAuODgxLTEuNTQyIDEzLTMuODkxIDEuMjUzLTEuNTQ1LTEuNDExLTEwLjE3OS0yLjA4Mi0xNi4zNTgtMC45ODQtOC4xNjQgMC4xNDgtMzMuMTI4LTEuMTg5LTM0LjU2NC0yLjQwMi0xLjk4NC05LjQ4MiAwLjA0LTExLjc0NyAyLjEyMnoiIGZpbGwtcnVsZT0iZXZlbm9kZCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuMjUiIGZpbGw9IiNmYmU2MDAiLz4KCTxwYXRoIGQ9Im01My41ODIgMzEuMTJjLTQuOTg5IDEuMTA5LTM2LjU4OC0zLjE0MS0zOS43MjktNC44MDQgMC45MjQgNC42MiAzLjE0MSA0NS4yNzIgMS42NjMgNDkuODkyIDAuMTg1IDIuMDMyLTMuODggMTUuMTUyLTMuNjk1IDE3LjkyNCAxNy4xODQtNjguMzcgMzkuNzI4LTQ4Ljk2OCA0MS43NjEtNjMuMDEyeiIgZmlsbC1ydWxlPSJldmVub2RkIiBmaWxsPSJ1cmwoI2QpIi8+Cgk8cGF0aCBkPSJtMTAuMDI3IDk1LjMwOWMtMy4wNTE1LTAuODk3LTUuMjA1MyA2LjgyMS0yLjg3MiA5LjE1MSA1Ljc0MyAyLjY5IDEzLjI4Mi0yLjMzIDM4LjIzLTEuNjEtMTIuNzQzLTAuMzYtMzEuNTg5LTIuODc0LTM1LjM1OC03LjU0MXoiIGZpbGwtcnVsZT0iZXZlbm9kZCIgZmlsbD0idXJsKCNjKSIvPgoJPHBhdGggZD0ibTc4LjU5IDMzLjU2N2M0LjQ4Ny00LjQ4OCA4Ljc5NC01LjU2NCAxMy45OTktNi40NjIgOC43OTEtMi4zMzMgMTQuOTAxIDMuNzY5IDE2Ljg3MSAxMS44NDYtNC40OS03LjE3OS0xMC4yMy04LjI1Ni0xNC4xNzgtOC40MzYtNC4xMjggMC43MTgtMTUuNzk1IDcuODk4LTE2Ljg3MiA5LjE1NHMtMC43MTgtNC4xMjggMC4xOC02LjEwMnoiIGZpbGwtcnVsZT0iZXZlbm9kZCIgZmlsbD0idXJsKCNiKSIvPgoJPHBhdGggc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgZD0ibTExLjQwOCA3Ny4zNGMyLjM4MzIgMS4xNTkgNC4yODExLTEuNTY5MyAzLjQ2NDktMy4wMzAzIDAuOTE1MDMgMC4wODY1OCAxLjc5NDgtMC4zMjU0IDEuNzk0OC0xLjc5NDggMC43MjA0NC0wLjcyMDQ0LTAuMzY0NjEtMS44NTQ0LTAuMzY0NjEtMi43MzU3LTAuOTkzNTQtMC45OTM1NCAwLjAwNTYtMi4xNjUgMC4wMDU2LTMuNzI1NyAwLTEuNTUzNSAwLjg5NzQyLTIuNTAyNCAwLjg5NzQyLTQuMTI4MSAwLTIuMzYxMSAyLjA1OTQtMS4xODA3IDAuODk3NDItNC42NjY2IDEuMDg4Mi0wLjQyNDU1IDIuMjc0MS0xLjQ4NDUgMC44OTc0Mi0yLjY5MjMgMi4xNjAxLTAuMjM5NTIgMy4yMTg2LTIuMzU0MiAwLjUzODQ1LTQuNjY2NiA0LjA3MzQgMC00LjIzMDItOC43MzA1IDIuNjkyMy02Ljk5OTkgMi4yMjItMC41NTU1MSAxLjc5NDgtMi4yMTUxIDEuNzk0OC00LjMwNzYgMi44NzE3IDMuOTQ4NyA2Ljg5NTQgMi42MjEzIDcuNTM4MyAwIDEuMzQ4NiA0LjM5OTggMTAuNTkgMi41ODY5IDEwLjU5LTIuODcxNyAwLjE3OTQ4IDYuNzUwMiA3LjExNzcgMy40MDQ2IDguNDM1OCAzLjk0ODYtMS42MTU0IDEuODY2MiAxLjU4NDEgOS4wNzk2IDQuMzA3NiA5LjE1MzctNi4zMDk3IDQuNzMyMy01LjE3MjkgMTMuMDAxIDIuNTEyOCAxNC41MzggMy44OTM4IDAgNS4zODQ1LTMuMjc4NSA1LjM4NDUtNy44OTczIDEuMjU2NCAyLjY0NDcgNi45NzIgNC4yNzk3IDYuOTk5OS0wLjE3OTQ4IDIuODcxNyA1LjU0NDYgNi40OTU5LTEuNDcwNCA0LjMwNzYtMi4xNTM4IDUuMDI1NiAxLjkwNTcgMy4yMTI4LTYuOTgxMSAxLjM3ODUtOS4wNTYgMi44NzE4LTAuOTE0NDggMS44MzQ2LTcuNjE4NCAwLjA1NzQtOS43ODk4IDIuNjIxMiAyLjY2NTIgNi43Mzg1LTAuODMxMTIgNi4yODItNS45MjMgMS4yMjggMy40NjcxIDkuMTQ3NS0wLjM2ODI4IDMuNzY5Mi04LjQzNTggMC0xLjU0NTEtNC40ODcxLTEuNzQ4OC01LjU2NC0wLjUzODQ1LTAuMDE1NDEtNS40NDYxLTQuMDk5Ny05LjY5MjEtNi45OTk5LTguNjE1MiAxLjc5OS0yLjY5MzItOS4wNDgtNC44OTk5LTExLjMwOC0wLjUzOSAxLjM1MS01LjcwMTItMTMuODEtOS4zMzM2LTE0LjE3OS02LjEwMjktMS43NDgtMi41MTI4LTExLjc3MS0yLjU1ODYtMTQuNzE4IDYuMjgxOSAwLTQuODYwNi0xNi4zMDktNi45OTk5LTE1Ljk3NCAwLjM1ODk3LTMuNDg5OS0yLjQzMzEtOS4yMjc0IDAuMzU4OTctOC43OTQ3IDMuMjMwNy01LjM4NDUtMi43MDM0LTcuODQyIDkuNTYxMS0zLjQxMDIgMTAuMjMxLTIuNTEyOCAyLjI2MjQtMi42OTIzIDExLjMxMSAwLjUzODQ1IDExLjEyOC0xLjk3NDMgMi4xMjk3LTAuODk3NDIgOC40MzY2IDEuMjU2NCA4LjYxNTItMS42Nzk0IDIuMzIwNiAwLjI0NTcgMTMuNjc0IDcuMTc5NCAxMS44NDYgMCAyLjUyMzQgMC43MDg3NyA0LjY5NDEtMC4xNzk0OCA3LjM1ODggMCAxLjU0NTUtMC44OTc0MiAyLjg1MjgtMC44OTc0MiA0LjQ4NzEgMC4zNzIwNiAwLjc0NDEyLTEuMjU5NyAyLjcyNDQgMC41Mzg0NSAzLjk0ODYtNC4yMTY3IDEuNzU5My0zLjMwMjQgNC40NjQyLTEuNjcwMSA1LjcyMjZ6IiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxcHQiIGZpbGw9IiNmZmZmZmYiLz4KCTxwYXRoIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGQ9Im0xMS4zMTcgMzIuNTc0Yy0xLjUwOTgtMS42NSAxLjIyMS03LjA0IDQuMjQyLTYuNzYzIDAuNjg5LTIuNDc0IDIuNTg2LTIuODkyIDQuNjg4LTIuMTg3LTEuMDQ4LTIuMDQ1IDEuNTAzLTMuOTkyIDMuNzUtMS42ODIgMS41MTctMi42MjIgNC42NzctNC42NDUgNi4zNTYtMy4yMzEtMC4xMzItMy4zNzMgNi4wNjMtNi43OTQgOC4zMzEtMy44MzcgMCAwLjYwNi0wLjM2MiAxLjg3NSAwIDEuODc1IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIxcHQiIGZpbGw9Im5vbmUiLz4KCTxwYXRoIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGQ9Im00OC4zNzIgMjIuMzc0Yy0wLjEwNC00LjcyMSAxNC4wMDktOC41OTEgMTEuMjUtMC4zMTMgMS4yNjktMC42MzQgNi44NzUtMS4yOTkgNS44NDQgMi4zMTQgNC4xMjMtMC40NjYgMTAuMzkgMS4xMDQgNi42NjIgNi42ODggMi4zOTYgMS44MDYgMS4zMzEgNi42OTYtMC4zMTkgNS4wNjEiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2Utd2lkdGg9IjFwdCIgZmlsbD0ibm9uZSIvPgo8L3N2Zz4K"
    camel.apache.org/provider: "Apache Software Foundation"
    camel.apache.org/kamelet.group: "Coffees"
    camel.apache.org/kamelet.namespace: "Dataset"
  labels:
    camel.apache.org/kamelet.type: "source"
spec:
  definition:
    title: "Coffee Source"
    description: "Produces periodic events about coffees!"
    type: object
    properties:
      period:
        title: Period
        description: The time interval between two events
        type: integer
        default: 5000
  types:
    out:
      mediaType: application/json
  dependencies:
    - "camel:timer"
    - "camel:http"
    - "camel:kamelet"
  template:
    from:
      uri: "timer:coffee"
      parameters:
        period: "{{period}}"
      steps:
        - to: https://random-data-api.com/api/coffee/random_coffee
        - removeHeaders:
            pattern: '*'
        - to: "kamelet:sink"

要对其进行测试,我们可以使用简单的集成来记录其内容:

- from:
    uri: "kamelet:coffee-source?period=5000"
    steps:
      - log: "${body}"

现在,我们可以运行:

$ camel run --local-kamelet-dir=</path/to/local/kamelets/dir> coffee-integration.yaml
2022-11-24 11:27:29.634  INFO 39527 --- [           main] org.apache.camel.main.MainSupport        : Apache Camel (JBang) 3.18.1 is starting
2022-11-24 11:27:29.706  INFO 39527 --- [           main] org.apache.camel.main.MainSupport        : Using Java 11.0.17 with PID 39527. Started by squake in /home/squake/workspace/jbang/camel-blog
2022-11-24 11:27:31.391  INFO 39527 --- [           main] e.camel.impl.engine.AbstractCamelContext : Apache Camel 3.18.1 (CamelJBang) is starting
2022-11-24 11:27:31.590  INFO 39527 --- [           main] org.apache.camel.main.BaseMainSupport    : Property-placeholders summary
2022-11-24 11:27:31.590  INFO 39527 --- [           main] org.apache.camel.main.BaseMainSupport    :     [coffee-source.kamelet.yaml]     period=5000
2022-11-24 11:27:31.590  INFO 39527 --- [           main] org.apache.camel.main.BaseMainSupport    :     [coffee-source.kamelet.yaml]     templateId=coffee-source
2022-11-24 11:27:31.591  INFO 39527 --- [           main] e.camel.impl.engine.AbstractCamelContext : Routes startup (started:2)
2022-11-24 11:27:31.591  INFO 39527 --- [           main] e.camel.impl.engine.AbstractCamelContext :     Started route1 (kamelet://coffee-source)
2022-11-24 11:27:31.591  INFO 39527 --- [           main] e.camel.impl.engine.AbstractCamelContext :     Started coffee-source-1 (timer://coffee)
2022-11-24 11:27:31.591  INFO 39527 --- [           main] e.camel.impl.engine.AbstractCamelContext : Apache Camel 3.18.1 (CamelJBang) started in 1s143ms (build:125ms init:819ms start:199ms JVM-uptime:2s)
2022-11-24 11:27:33.297  INFO 39527 --- [ - timer://coffee] coffee-integration.yaml:4                  : {"id":3648,"uid":"712d4f54-3314-4129-844e-9915002ecbb7","blend_name":"Winter Cowboy","origin":"Lekempti, Ethiopia","variety":"Agaro","notes":"delicate, juicy, sundried tomato, fresh bread, lemonade","intensifier":"juicy"}

这是在编程 Kamelet 时的提升,因为您可以快速反馈而无需集群。准备就绪后,您可以继续将 Kamelet 上传到集群并使用 Camel K 集成。

第 2 章 在本地和云基础架构中测试 Camel K

本章论述了测试与 YAKS 的 Camel K 集成的步骤,包括本地和云基础架构(Kubernetes 平台)。

2.1. 使用 YAKS 测试 Camel K

2.1.1. 什么是 YAKS?

YAKS 是一个开源测试自动化平台,它利用行为驱动开发概念在本地和云基础架构上运行测试(例如: KubernetesOpenShift)。这意味着测试工具能够将您的测试作为本地测试运行,并在 Kubernetes 上原生运行。该框架专为验证 Serverless 和 microservice 应用程序而设计,旨在集成测试下测试并在类似于生产环境的环境中运行的应用程序。典型的 YAKS 测试使用与不同消息传递传输过程中的应用相同的基础架构(例如:Http REST、Knative 事件、Kafka、JMS 等)。

因为 YAKS 本身以 Java 编写,运行时将使用 Java 虚拟机以及 Maven 等构建工具,并与 JUnitCucumberCitrus 等已知 Java 测试框架集成来运行测试。

2.1.2. 了解 Camel K 示例

以下是我们想要测试的 Camel K 集成示例:该集成会向用户公开 Http 服务。该服务接受添加 fruit 模型对象的客户端 Http POST 请求。Camel K 路由应用基于内容的路由,将有问题的路由存储在不同的 AWS S3 存储桶中。

测试场景

在测试场景中,YAKS 将调用 Camel K 服务,并验证消息内容是否已发送到正确的 AWS S3 存储桶。

以下是可能存储在 AWS S3 中的模糊模型对象示例:

{
  "id": 1000,
  "name": "Pineapple",
  "category":{
    "id": "1",
    "name":"tropical"
  },
  "nutrition":{
    "calories": 50,
    "sugar": 9
  },
  "status": "AVAILABLE",
  "price": 1.59,
  "tags": ["sweet"]
}

以下是 Camel K 集成路由:

from('platform-http:/fruits')
    .log('received fruit ${body}')
    .unmarshal().json()
    .removeHeaders("*")
    .setHeader("CamelAwsS3Key", constant("fruit.json"))
    .choice()
        .when().simple('${body[nutrition][sugar]} <= 5')
            .setHeader("CamelAwsS3BucketName", constant("low-sugar"))
        .when().simple('${body[nutrition][sugar]} > 5 && ${body[nutrition][sugar]} <= 10')
            .setHeader("CamelAwsS3BucketName", constant("medium-sugar"))
        .otherwise()
            .setHeader("CamelAwsS3BucketName", constant("high-sugar"))
    .end()
    .marshal().json()
    .log('sending ${body}')
    .to("aws2-s3://noop?$parameters")

路由使用基于内容的路由 EAP,基于给定模糊的 nutrition sugar 评级,将模糊应用到不同的 AWS S3 存储桶(low-sugar, medium-sugar, high-sugar)。

在进行此集成的测试案例中,需要使用不同的模糊调用公开的服务并验证其在 AWS S3 上的结果。

2.1.3. 如何使用 YAKS 本地测试

开始时,让我们只编写测试并在本地运行它。现在,我们不关心如何在云基础架构中进行测试,因为所有内容在使用 JBang 的计算机上运行。

JBang 是仅开始编码和运行 Java 代码以及 Camel K 集成(也看到此前文中关于 JBang 与 Camel K 集成)的好方法。

YAKS 作为框架提供了一组现成的域特定语言(XML、YAML、Groovy、BDD Cucumber 步骤),用于编写测试以验证部署的服务。

此后,通过 Cucumber 使用行为驱动开发集成。因此,YAKS 测试是使用 BDD Gherkin 语法的单一功能文件,如下所示:

Feature: Camel K Fruit Store

  Background:
    Given URL: http://localhost:8080

  Scenario: Create infrastructure
    # Start AWS S3 container
    Given Enable service S3
    Given start LocalStack container

    # Create Camel K integration
    Given Camel K integration property file aws-s3-credentials.properties
    When load Camel K integration fruit-service.groovy
    Then Camel K integration fruit-service should print Started route1 (platform-http:///fruits)

  Scenario: Verify fruit service
    # Invoke Camel K service
    Given HTTP request body: yaks:readFile('pineapple.json')
    And HTTP request header Content-Type="application/json"
    When send POST /fruits
    Then receive HTTP 200 OK

    # Verify uploaded S3 file
    Given New global Camel context
    Given load to Camel registry amazonS3Client.groovy
    Given Camel exchange message header CamelAwsS3Key="fruit.json"
    Given receive Camel exchange from("aws2-s3://medium-sugar?amazonS3Client=#amazonS3Client&deleteAfterRead=true") with body: yaks:readFile('pineapple.json')

逐步浏览测试步骤。首先,功能文件使用常见的 Given-When-Then BDD 语法来给出上下文,描述操作并验证结果。每个步骤都调用框架开箱即用的特定 YAKS 操作。用户可以从 大量的步骤 中选择,它们会自动执行诸如发送/接收 Http 请求/响应、启动 Testcontainers、运行 Camel 路由、连接到数据库、在 Kafka 或 Knative 代理上的事件等操作。

在第一个场景中,测试会自动准备一些所需的基础架构。YAKS 测试启动 Localstack Testcontainer 来运行 AWS S3 测试实例(Given start LocalStack 容器)。然后,测试会加载并启动 Camel K integration in test (当加载 Camel K integration fruit-service.groovy),并等待它正确启动。本地测试中,此步骤使用 JBang 启动 Camel K 集成。之后,后期还会在 Kubernetes 环境中运行测试。

现在,基础架构已启动并运行,测试能够加载 fruit 模型对象作为 Http 请求正文(Given HTTP request body: yaks:readFile ('pineapple.json')),并调用 Camel K 服务(发送 POST /fruits)。该测试会等待 Http 响应,并验证其 200 OK 状态。

在最后一步中,测试会验证 fruit 对象是否已添加到正确的 AWS S3 存储桶(medium-sugar)。因为 YAKS 本身无法连接到 AWS S3,因此测试将 Apache Camel 用于这一步。该测试会创建一个 Camel 上下文,加载 AWS 客户端,并使用临时 Camel 路由连接到 AWS S3 (Given 接收 Camel 交换来自("aws2-s3://medium-sugar?amazonS3Client=45amazonS3Client&deleteAfterRead=true"))。使用这个 Apache Camel 集成 YAKS,可以使用完整的 300+ Camel 组件来发送和接收信息到各种消息传递传输。Camel Exchange body 必须是与初始 Http 请求中发布的相同模糊模型对象(yaks:readFile ('pineapple.json')。

YAKS 使用 Citrus 提供的强大的消息有效负载验证功能进行此消息内容验证。验证能够比较类型为 XML、Json、纯文本等消息内容。

该操作将完成测试案例。现在,您可以使用 Cucumber 和 JUnit 实例运行此测试。直接使用 YAKS 运行测试的最简单方法是使用 YAKS 命令行客户端。您不需要使用 Maven 依赖项设置整个项目,等等。只需编写测试文件并使用以下方法运行:

$ yaks run fruit-service.feature --local

您应该看到一些日志输出,如下所示:

INFO |
INFO | ------------------------------------------------------------------------
INFO |        .__  __
INFO |   ____ |__|/  |________ __ __  ______
INFO | _/ ___\|  \   __\_  __ \  |  \/  ___/
INFO | \  \___|  ||  |  |  | \/  |  /\___ \
INFO |  \___  >__||__|  |__|  |____//____  >
INFO |      \/                           \/
INFO |
INFO | C I T R U S  T E S T S  3.4.0
INFO |
INFO | ------------------------------------------------------------------------
INFO |

Scenario: Create infrastructure # fruit-service.feature:6
  Given URL: http://localhost:8080
  Given Enable service S3
  [...]

Scenario: Verify fruit service # fruit-service.feature:20
  Given URL: http://localhost:8080
  Given HTTP request body: yaks:readFile('pineapple.json')
  [...]

Scenario: Remove infrastructure  # fruit-service.feature:31
  Given URL: http://localhost:8080
  Given delete Camel K integration fruit-service
  Given stop LocalStack container

3 Scenarios (3 passed)
18 Steps (18 passed)
0m18,051s


INFO | ------------------------------------------------------------------------
INFO |
INFO | CITRUS TEST RESULTS
INFO |
INFO |  Create infrastructure .......................................... SUCCESS
INFO |  Verify fruit service ........................................... SUCCESS
INFO |  Remove infrastructure .......................................... SUCCESS
INFO |
INFO | TOTAL: 3
INFO | FAILED: 0 (0.0%)
INFO | SUCCESS:    3 (100.0%)
INFO |
INFO | ------------------------------------------------------------------------

3 Scenarios (3 passed)
18 Steps (18 passed)
0m18,051s


Test results: Total: 0, Passed: 1, Failed: 0, Errors: 0, Skipped: 0
    fruit-service (fruit-service.feature): Passed

2.1.4. 在云中运行 YAKS

YAKS 能够在本地和 Kubernetes 集群一部分运行测试。在 Cloud infrastructure YAKS 上运行测试时,利用 Operator SDK 并提供一个特定的 operator 来管理集群中的测试问题单资源。每次以 自定义资源 的形式声明测试时,YAKS 操作器会自动处理准备正确的运行时,以便将测试作为 Kubernetes Pod 执行。

为什么您要在 Kubernetes 平台上作为云原生资源运行测试?

Kubernetes 已成为 Serverless 和 microservices 架构的标准目标平台。

使用 Camel K 为实例编写 Serverless 或 microservices 应用程序非常声明性。作为您刚刚编写 Camel 路由的开发者,并通过 Camel K operator 直接在集群中运行它。Serverless 应用程序的声明方法以及 Serverless 应用程序的性质使得我们依赖于给定的运行时基础架构,对于验证该基础架构上的应用程序也至关重要。因此,只有将验证测试移到这种非常相同的云基础架构中才会自然。这就是为什么 YAKS 也将测试引入云基础架构,以进行集成和端到端测试。

下面是它的运作方式。您可以运行与 Kubernetes 中本地运行的相同 YAKS 测试。

YAKS 提供 Kubernetes operator 和一组需要安装到的 CRD (自定义资源)。安装 YAKS 的最佳方法是使用 OperatorHub 或 yaks CLI 工具,您可以从 YAKS GitHub 发行页 下载。

使用 yaks-client 二进制文件只运行这个 install 命令:

$ yaks install

此命令会准备您的 Kubernetes 集群,以使用 YAKS 运行测试。它将负责安装 YAKS 自定义资源定义,设置角色权限并在全局 operator 命名空间中创建 YAKS Operator。

重要

您需要是一个集群管理员来安装自定义资源定义。此操作只需要为整个集群执行一次。

现在,YAKS 操作器已经启动并在运行,您可以在云基础架构上从本地测试运行相同的测试。需要完成的唯一操作是将 Camel K 集成的 Http 端点 URL 从 http://localhost:8080 调整为 http://fruit-service.${YAKS_NAMESPACE}

$ yaks run fruit-service.feature
注意

我们刚刚跳过了 本地的 CLI 选项。

YAKS CLI 连接到 Kubernetes 集群,而不是使用本地 JBang 工具在本地运行测试,以作为自定义资源创建测试。从 中,YAKS 操作器负责准备测试运行时并将测试作为 Pod 运行。

测试已准备一些基础架构,特别是 Camel K 集成和 AWS S3 Localstack Testcontainer 实例。这如何在 Kubernetes 内工作?YAKS 完全负责它。Camel K 集成与在同一 Kubernetes 集群上运行的 Camel K operator 运行。然后 Testcontainer AWS S3 实例会在 Kubernetes 中自动作为 Pod 运行。即使连接设置也会自动处理。它只是工作!

远程运行测试时,您将看到一些类似的测试日志输出,测试将执行其操作及其验证与本地的完全相同。

您还可以使用以下方法查看测试 Pod 结果:

$ yaks ls

这是一个输出示例,您应该获得:

NAME           PHASE   TOTAL  PASSED  FAILED  SKIPPED  ERRORS
fruit-service  Passed  3      3       0       0        0

2.1.5. Demostration

GitHub 存储库 上提供了整个演示代码。它还介绍了如何在 GitHub CI 操作工作流中集成测试,以便您可以使用每个代码更改自动运行测试。

2.1.6. Apache Camel K 步骤

Apache Camel K 是由 Apache Camel 构建的轻量级集成框架,可在 Kubernetes 上原生运行,专为无服务器和微服务架构而设计。

Camel K 用户可以在首选云(Kubernetes 或 OpenShift)上立即运行使用 Camel DSL 编写的集成代码。

如果测试中的主题是 Camel K 集成,您可以利用 YAKS Camel K 绑定来提供 Camel K 集成的有效步骤。

使用 Camel K 集成

Given create Camel K integration helloworld.groovy
"""
from('timer:tick?period=1000')
  .setBody().constant('Hello world from Camel K!')
  .to('log:info')
"""
Given Camel K integration helloworld is running
Then Camel K integration helloworld should print Hello world from Camel K!

YAKS 框架默认提供 Camel K 扩展库。您可以创建新的 Camel K 集成并检查集成的状态(例如,运行)。

以下小节详细介绍了可用的 Camel K 步骤。

2.1.6.1. API 版本

用于创建和管理资源的默认 Camel K API 版本是 v1。您可以使用 YAKS 配置中设置的环境变量覆盖这个版本。

覆盖 Camel K API 版本

YAKS_CAMELK_API_VERSION=v1alpha1

这会为所有操作设置 Camel K API 版本。

2.1.6.2. 创建 Camel K 集成

@given ("^(?:create|new) Camel K integration {name}.{type}$")

Given create Camel K integration {name}.groovy
"""
<<Camel DSL>>
"""

创建新的 Camel K 与指定路由 DSL 集成。集成会自动启动,并可在其他步骤中通过其 {name} 引用。

@given ("^(?:create|new) Camel K integration {name}.{type} with configuration:$")

Given create Camel K integration {name}.groovy with configuration:
  | dependencies | mvn:org.foo:foo:1.0,mvn:org.bar:bar:0.9 |
  | traits       | quarkus.native=true,quarkus.enabled=true,route.enabled=true |
  | properties   | foo.key=value,bar.key=value |
  | source       | <<Camel DSL>> |

您可以在 Camel K 集成中添加可选配置,如依赖项、特征和属性。

路由 DSL,作为 Camel K 集成的源。

依赖项

Maven 协调列表,它将作为库添加到集成运行时中。

遍历

将添加到集成规格中的特征配置列表。每个特征配置值都必须采用 traitname.key=value 格式。

属性

添加到集成中的属性绑定列表。每个值都必须采用 key=value 格式。

2.1.6.3. 加载 Camel K 集成

@given ("^load Camel K integration {name}.{type}$")

Given load Camel K integration {name}.groovy

将文件 {name}.groovy 载入为 Camel K 集成。

2.1.6.4. 删除 Camel K 集成

@given ("^delete Camel K integration {name}$")

Given delete Camel K integration {name}

删除与给定 {name} 的 Camel K 集成。

2.1.6.5. 验证集成状态

Camel K 集成在普通的 Kubernetes pod 中运行。pod 的状态为,处于一个阶段(如 running, stopped)。您可以使用预期验证状态。

@given ("^Camel K integration {name} is running/stopped$")

Given Camel K integration {name} is running

检查 Camel K 与给定 {name} 集成是否处于运行状态,并且副本数为 > 0。步骤轮询给定次数的集成状态,并在尝试之间具有给定延迟的尝试。您可以使用以下方法调整轮询设置:

@given Camel K 资源轮询配置

Given Camel K resource polling configuration
    | maxAttempts          | 10   |
    | delayBetweenAttempts | 1000 |
2.1.6.6. 观察 Camel K 集成日志

@given ("^Camel K integration {name} should print (.)$")*

Given Camel K integration {name} should print {log-message}

监视 Camel K 集成的日志输出并等待日志中存在给定的 {log-message}。步骤轮询指定时间的日志。您可以使用以下方法调整轮询配置:

@given Camel K 资源轮询配置

Given Camel K resource polling configuration
    | maxAttempts          | 10   |
    | delayBetweenAttempts | 1000 |

您还可以等待输出中不存在日志消息。只使用这个步骤:

@given ("^Camel K integration {name} should not print (.)$")*

Given Camel K integration {name} should not print {log-message}

您可以启用 YAKS 在测试运行时将日志打印到测试日志输出中。可以使用环境变量设置 'YAKS_CAMELK_PRINT_POD_LOGS=true/false 来启用/禁用日志

要在测试控制台日志记录中看到日志输出,您必须将日志级别设置为 INFO (例如: yaks-config.yaml)。

config: runtime: settings: loggers: - name: INTEGRATION_STATUS level: INFO - name: INTEGRATION_LOGS level: INFO

2.1.6.7. 管理 Camel K 资源

Camel K 步骤可以创建集成等资源。默认情况下,这些资源会在测试场景后自动删除。

可以按照以下步骤关闭自动删除 Camel K 资源。

@given ("^Disable auto removal of Camel K resources$")

Given Disable auto removal of Camel K resources

通常,此步骤 功能文件中所有场景的背景步骤。这样,多个场景可以在非常相同的 Camel K 资源上工作并共享集成。

还有一个单独的步骤来显式启用自动移除。

@given ("^Enable auto removal of Camel K resources$")

Given Enable auto removal of Camel K resources

默认情况下,所有 Camel K 资源都会在每次场景后自动删除。

2.1.6.7.1. 使用环境变量启用和禁用自动删除

您可以通过环境变量设置启用/禁用自动移除。

环境变量称为 YAKS_CAMELK_AUTO_REMOVE_RESOURCES=true/false,必须在 test 套件中为所有测试设置。

另外,有一个名为 yaks.camelk.auto.remove.resources=true/false 的系统属性,您必须在 yaks.properties 文件中设置。

2.1.7. kamelet 步骤

kamelets 是 Camel K 中实施的预定义 Camel 路由模板的形式。通常是一个 Kamelet 封装某个功能(例如,发送消息到端点)。Additionaly Kamelets 定义一组用户在使用 Kamelet 时提供的属性。

YAKS 提供管理 Kamelets 的步骤。

2.1.7.1. API 版本

用于创建和管理资源的默认 Kamelet API 版本为 v1。(例如,您可以使用上述环境变量将版本调整为 v1alpha1。)您可以使用 YAKS 配置中设置的环境变量覆盖这个版本。

覆盖 Kamelet API 版本

YAKS_KAMELET_API_VERSION=v1

这会为所有操作设置 Kamelet API 版本。

2.1.7.2. create Kamelets

Kamelets 定义了一组属性和规格,您可以使用功能中的独立步骤设置它们。以下步骤在 Kamelet 中设置特定的属性。使用 Kamelet 规格完成后,您可以在当前命名空间中创建 Kamelet。

首先,您可以在 Kamelet 中指定可用插槽(in、out 和 error)的介质类型。

@given ("^Kamelet dataType (in|out|error) (?:=| is)\"{mediaType}\"$")

Given Kamelet dataType in="{mediaType}"

Kamelet 可以使用您在以下步骤中设置的标题。

@given ("^Kamelet title \"{title}\"$")

Given Kamelet title "{title}"

每个模板都使用端点 uri,并定义了一组在 Kamelet 处理发生时调用的步骤。以下步骤在当前 Kamelet 上定义了一个模板。

@given ("^Kamelet template$")

Given Kamelet template
"""
from:
  uri: timer:tick
  parameters:
    period: "#property:period"
  steps:
  - set-body:
      constant: "{{message}}"
  - to: "kamelet:sink"
"""

该模板使用两个属性 {{message}}{{period}}。这些占位符需要由 Kamelet 用户提供。下一步详细定义了 属性信息

@given ("^Kamelet 属性定义 {name}$")

Given Kamelet property definition message
  | type     | string        |
  | required | true          |
  | example  | "hello world" |
  | default  | "hello"       |

属性接收规格,如 type、required 和 example。除了示例外,您还可以为属性设置默认值。

除了在 Kamelet 上使用模板外,您还可以将多个源添加到 Kamelet 中。

@given ("^Kamelet source {name}.{language}$")

Given Kamelet source timer.yaml
"""
<<YAML>>
"""

前面的步骤定义了所有属性和 Kamelet 规格,现在您已准备好在当前命名空间中创建 Kamelet。

@Given("^(?:create|new) Kamelet {name}$")

Given create Kamelet {name}

Kamelet 需要 唯一名称。创建一个 Kamelet 意味着会创建一个类型为 Kamelet 的新自定义资源。作为变体,您也可以在创建 Kamelet 时设置模板。

@given ("^(?:create|new) Kamelet {name} with template")

Given create Kamelet {name} with template
"""
<<YAML>>
"""

这会在当前命名空间中创建 Kamelet。

2.1.7.3. Load Kamelets

您可以通过在外部 YAML 文件中提供完整的规格来创建新的 Kamelets。此步骤加载文件内容,并在当前命名空间中创建 Kamelet。

@given ("^load Kamelet {name}.kamelet.yaml$")

Given load Kamelet {name}.kamelet.yaml

将文件 {name}.kamelet.yaml 载入为 Kamelet。目前只支持 kamelet.yaml 源文件扩展。

2.1.7.4. delete Kamelets

@Given("^delete Kamelet {name}$")

Given delete Kamelet {name}

从当前命名空间中删除给定 {name} 的 Kamelet。

2.1.7.5. 验证 Kamelet 可用

@given ("^Kamelet {name} is available$$")

Given Kamelet {name} is available$

验证 Kamelet 自定义资源是否在当前命名空间中可用。

2.1.8. 管道步骤

您可以将 Kamelet 绑定到 sink。这个概念在管道中进行了描述。YAKS 作为框架能够与 Kamelets 结合使用创建和验证 Pipes。

注意

管道自 Camel K 中的 API 版本 v1 开始提供。YAKS 还支持 KameletBinding 资源,它们代表与 Pipes 等效的 v1alpha1。因此,如果您需要使用 KameletBindings,您需要明确将 Kamelet API 版本明确设置为 v1alpha1 (例如,通过环境变量设置 YAKS_KAMELET_API_VERSION)。

2.1.8.1. 创建管道

YAKS 提供将 Kamelet 源绑定到 sink 的多个步骤。管道(pipeline)会将源处理的所有信息转发到 sink。

2.1.8.1.1. 绑定到 Http URI

@given ("^bind Kamelet {kamelet} to uri {uri}$")

Given bind Kamelet {name} to uri {uri}

这将带有给定 Kamelet 名称的 Pipe 定义为给定 Http URI 作为接收器的源。

2.1.8.1.2. 绑定到 Kafka 主题

您可以将 Kamelet 源绑定到 Kafka 主题接收器。所有消息都将转发到主题。

@given ("^bind Kamelet {kamelet} to Kafka topic {topic}$")

Given bind Kamelet {kamelet} to Kafka topic {topic}
2.1.8.1.3. 绑定到 Knative 频道

频道是 Knative 中事件的一部分。与 Kafka 中的主题类似,频道会保存订阅者信息。

@given ("^bind Kamelet {kamelet} to Knative channel {channel}$")

Given bind Kamelet {kamelet} to Knative channel {channel}

可使用不同的实现支持频道。您可以明确设置要在管道中使用的频道类型。

@given ("^bind Kamelet {kamelet} to Knative channel {channel} of kind {kind}$")

Given bind Kamelet {kamelet} to Knative channel {channel} of kind {kind}
2.1.8.1.4. 指定 source/sink 属性

Pipe 可能需要为源和接收器指定属性。这些属性在 instance 的 Kamelet 源规格中定义。

您可以使用以下步骤中的值设置属性:

@given ("^Pipe source properties$")

Given Pipe source properties
  | {property}  | {value} |

上述示例中使用的 Kamelet 源定义了属性 消息。您可以按照如下所示,在管道上设置属性:

Given Pipe source properties
  | message  | "Hello world" |

相同的方法适用于 sink 属性。

@given ("^Pipe sink properties$")

Given Pipe sink properties
  | {property}  | {value} |
2.1.8.1.5. 创建管道

前面的步骤定义了 Pipe 规格的 source 和 sink。现在,您已准备好在当前命名空间中创建 Pipe。

@Given("^(?:create|new) Pipe {name}$")

Given create Pipe {name}

Pipe 接收 唯一名称,并使用之前指定的源和接收器。创建 Pipe 表示在当前命名空间中创建类型为 Pipe 的新自定义资源。

2.1.8.2. 加载管道

您可以通过在外部 YAML 文件中提供完整的规格来创建新的 Pipes。步骤加载文件内容,并在当前命名空间中创建 Pipe。

@given ("^load Pipe {name}.yaml$")

Given load Pipe {name}.yaml

将文件 {name}.yaml 载入为 Pipe。目前,YAKS 只支持 .yaml 源文件。

2.1.8.3. 删除管道

@given ("^delete Pipe {name}$")

Given delete Pipe {name}

从当前命名空间中删除给定 {name} 的 Pipe。

2.1.8.4. 验证 Pipe 是否可用

@given ("^Pipe {name} 可用$$")

Given Pipe {name} is available$

验证 Pipe 自定义资源是否在当前命名空间中可用。

2.1.8.5. 管理 Kamelet 和 Pipe 资源

描述的步骤可以在当前 Kubernetes 命名空间中创建 Kamelet 资源。默认情况下,这些资源会在测试场景后自动删除。

可以按照以下步骤关闭 Auto removal of Kamelet 资源。

@given ("^Disable auto removal of Kamelet resources$")

Given Disable auto removal of Kamelet resources

通常,此步骤 功能文件中所有场景的背景步骤。这样,多个场景可以在非常相同的 Kamelet 资源上工作,并共享集成。

还有一个单独的步骤来显式启用自动移除。

@given ("^Enable auto removal of Kamelet resources$")

Given Enable auto removal of Kamelet resources

默认情况下,所有 Kamelet 资源都会在每次场景后自动删除。

2.1.8.5.1. 使用环境变量启用和禁用自动删除

您可以通过环境变量设置启用/禁用自动移除。

环境变量称为 YAKS_CAMELK_AUTO_REMOVE_RESOURCES=true/false,必须在 test 套件中为所有测试设置。

另外,有一个名为 yaks.camelk.auto.remove.resources=true/false 的系统属性,您必须在 yaks.properties 文件中设置。

法律通告

Copyright © 2024 Red Hat, Inc.
The text of and illustrations in this document are licensed by Red Hat under a Creative Commons Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). An explanation of CC-BY-SA is available at http://creativecommons.org/licenses/by-sa/3.0/. In accordance with CC-BY-SA, if you distribute this document or an adaptation of it, you must provide the URL for the original version.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, Red Hat Enterprise Linux, the Shadowman logo, the Red Hat logo, JBoss, OpenShift, Fedora, the Infinity logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries.
Linux® is the registered trademark of Linus Torvalds in the United States and other countries.
Java® is a registered trademark of Oracle and/or its affiliates.
XFS® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States and/or other countries.
MySQL® is a registered trademark of MySQL AB in the United States, the European Union and other countries.
Node.js® is an official trademark of Joyent. Red Hat is not formally related to or endorsed by the official Joyent Node.js open source or commercial project.
The OpenStack® Word Mark and OpenStack logo are either registered trademarks/service marks or trademarks/service marks of the OpenStack Foundation, in the United States and other countries and are used with the OpenStack Foundation's permission. We are not affiliated with, endorsed or sponsored by the OpenStack Foundation, or the OpenStack community.
All other trademarks are the property of their respective owners.
返回顶部
Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。 了解我们当前的更新.

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

Theme

© 2025 Red Hat, Inc.