diff --git a/java/pom.xml b/java/pom.xml
index 77e6a6fd..fd9e4854 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -98,9 +98,10 @@
3.25.3
4.2.1
2.25.53
+ 2.3.3
4.2.1
2.12.0
- 7.16.1
+ 7.18.0
3.0.21
2.17.1
4.13.2
@@ -454,6 +455,13 @@
test
+
+
+ org.apache.camel.k
+ camel-k-crds
+ ${camel.k.crds.version}
+
+
com.fasterxml.jackson.core
jackson-core
diff --git a/java/steps/pom.xml b/java/steps/pom.xml
index 9acb5d12..41ca3dd6 100644
--- a/java/steps/pom.xml
+++ b/java/steps/pom.xml
@@ -21,6 +21,7 @@
org.citrusframework.yaks
yaks-parent
0.20.0-SNAPSHOT
+ ../pom.xml
4.0.0
diff --git a/java/steps/yaks-camel-k/pom.xml b/java/steps/yaks-camel-k/pom.xml
index 0312d871..7536a1ac 100644
--- a/java/steps/yaks-camel-k/pom.xml
+++ b/java/steps/yaks-camel-k/pom.xml
@@ -67,6 +67,11 @@
kubernetes-client
+
+ org.apache.camel.k
+ camel-k-crds
+
+
com.squareup.okhttp3
okhttp
diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/CamelKSteps.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/CamelKSteps.java
index b340a74b..cc8438ae 100644
--- a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/CamelKSteps.java
+++ b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/CamelKSteps.java
@@ -35,7 +35,6 @@
import org.citrusframework.context.TestContext;
import org.citrusframework.exceptions.ActionTimeoutException;
import org.citrusframework.exceptions.CitrusRuntimeException;
-import org.citrusframework.spi.Resource;
import org.citrusframework.util.FileUtils;
import org.citrusframework.yaks.camelk.actions.integration.CreateIntegrationAction;
import org.citrusframework.yaks.kubernetes.KubernetesSupport;
@@ -320,12 +319,7 @@ private void createIntegration(String name, String language, String source, Map<
String openApiSpec = configuration.getOrDefault("openapi", "");
if (!openApiSpec.isEmpty()) {
- try {
- Resource file = ResourceUtils.resolve(openApiSpec, context);
- create.openApi(FileUtils.getFileName(file.getLocation()), FileUtils.readToString(file));
- } catch (IOException e) {
- throw new CitrusRuntimeException(String.format("Failed to read openapi spec form file path %s", openApiSpec));
- }
+ create.openApi(openApiSpec);
}
runner.run(create);
diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/KameletBindingSteps.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/KameletBindingSteps.java
new file mode 100644
index 00000000..a3b465de
--- /dev/null
+++ b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/KameletBindingSteps.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright the original author or authors.
+ *
+ * Licensed 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.
+ */
+
+package org.citrusframework.yaks.camelk;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import io.cucumber.java.Before;
+import io.cucumber.java.Scenario;
+import io.cucumber.java.en.Given;
+import io.cucumber.java.en.Then;
+import io.fabric8.kubernetes.client.KubernetesClient;
+import org.apache.camel.v1alpha1.KameletBindingBuilder;
+import org.apache.camel.v1alpha1.kameletbindingspec.SinkBuilder;
+import org.apache.camel.v1alpha1.kameletbindingspec.SourceBuilder;
+import org.apache.camel.v1alpha1.kameletbindingspec.source.Ref;
+import org.apache.camel.v1alpha1.kameletbindingspec.source.RefBuilder;
+import org.citrusframework.Citrus;
+import org.citrusframework.TestCaseRunner;
+import org.citrusframework.annotations.CitrusFramework;
+import org.citrusframework.annotations.CitrusResource;
+import org.citrusframework.context.TestContext;
+import org.citrusframework.spi.Resource;
+import org.citrusframework.yaks.kafka.KafkaSettings;
+import org.citrusframework.yaks.knative.KnativeSettings;
+import org.citrusframework.yaks.kubernetes.KubernetesSupport;
+import org.citrusframework.yaks.util.ResourceUtils;
+
+import static org.citrusframework.container.FinallySequence.Builder.doFinally;
+import static org.citrusframework.yaks.camelk.actions.CamelKActionBuilder.camelk;
+
+public class KameletBindingSteps {
+
+ @CitrusResource
+ private TestCaseRunner runner;
+
+ @CitrusFramework
+ private Citrus citrus;
+
+ @CitrusResource
+ private TestContext context;
+
+ private KubernetesClient k8sClient;
+
+ // Binding endpoints
+ private SourceBuilder source;
+ private SinkBuilder sink;
+
+ private Map sourceProperties;
+ private Map sinkProperties;
+
+ @Before
+ public void before(Scenario scenario) {
+ if (k8sClient == null) {
+ k8sClient = KubernetesSupport.getKubernetesClient(citrus);
+ }
+
+ initializeKameletBindingBuilder();
+ }
+
+ @Given("^KameletBinding source properties$")
+ public void setKameletBindingSourceProperties(Map properties) {
+ this.sourceProperties.putAll(properties);
+ }
+
+ @Given("^KameletBinding sink properties$")
+ public void setKameletBindingSinkProperties(Map properties) {
+ this.sinkProperties.putAll(properties);
+ }
+
+ @Given("^KameletBinding event source Kamelet ([a-z0-9-]+)$")
+ public void setKameletEventSource(String kameletName) {
+ Ref kameletRef = new RefBuilder()
+ .withName(kameletName)
+ .withApiVersion(CamelKSupport.CAMELK_CRD_GROUP + "/" + getKameletApiVersion())
+ .withKind("Kamelet")
+ .withNamespace(getNamespace())
+ .build();
+ source = new SourceBuilder().withRef(kameletRef);
+ }
+
+ @Given("^KameletBinding event sink uri ([^\\s]+)$")
+ public void setEventSinkUri(String uri) {
+ sink = new SinkBuilder().withUri(uri);
+ }
+
+ @Given("^KameletBinding event sink Kafka topic ([^\\s]+)$")
+ public void setEventSinkKafkaTopic(String topic) {
+ org.apache.camel.v1alpha1.kameletbindingspec.sink.Ref sinkRef =
+ new org.apache.camel.v1alpha1.kameletbindingspec.sink.RefBuilder()
+ .withName(topic)
+ .withApiVersion("kafka.strimzi.io/" + KafkaSettings.getApiVersion())
+ .withKind("KafkaTopic")
+ .withNamespace(KafkaSettings.getNamespace())
+ .build();
+ sink = new SinkBuilder().withRef(sinkRef);
+ }
+
+ @Given("^KameletBinding event sink Knative channel ([^\\s]+)$")
+ public void setEventSinkKnativeChannel(String channel) {
+ setEventSinkKnativeChannel(channel, "InMemoryChannel");
+ }
+
+ @Given("^KameletBinding event sink Knative channel ([^\\s]+) of kind ([^\\s]+)$")
+ public void setEventSinkKnativeChannel(String channel, String channelKind) {
+ org.apache.camel.v1alpha1.kameletbindingspec.sink.Ref sinkRef =
+ new org.apache.camel.v1alpha1.kameletbindingspec.sink.RefBuilder()
+ .withName(channel)
+ .withApiVersion("messaging.knative.dev/" + KnativeSettings.getApiVersion())
+ .withKind(channelKind)
+ .withNamespace(KnativeSettings.getNamespace())
+ .build();
+ sink = new SinkBuilder().withRef(sinkRef);
+ }
+
+ @Given("^KameletBinding event sink Knative broker ([^\\s]+)$")
+ public void setEventSinkKnativeBroker(String broker) {
+ org.apache.camel.v1alpha1.kameletbindingspec.sink.Ref sinkRef =
+ new org.apache.camel.v1alpha1.kameletbindingspec.sink.RefBuilder()
+ .withName(broker)
+ .withApiVersion("eventing.knative.dev/" + KnativeSettings.getApiVersion())
+ .withKind("Broker")
+ .withNamespace(KnativeSettings.getNamespace())
+ .build();
+ sink = new SinkBuilder().withRef(sinkRef);
+ }
+
+ @Given("^load KameletBinding ([a-z0-9-]+).yaml$")
+ public void loadKameletBindingFromFile(String fileName) {
+ Resource resource = ResourceUtils.resolve(fileName + ".yaml", context);
+ runner.run(camelk()
+ .client(k8sClient)
+ .createKameletBinding(fileName)
+ .resource(resource));
+
+ if (isAutoRemoveResources()) {
+ runner.then(doFinally()
+ .actions(camelk().client(k8sClient)
+ .deleteKameletBinding(fileName)));
+ }
+ }
+
+ @Given("^(?:create|new) KameletBinding ([a-z0-9-]+)$")
+ public void createNewKameletBinding(String name) {
+ KameletBindingBuilder builder = new KameletBindingBuilder();
+
+ builder.withNewMetadata()
+ .withName(name)
+ .endMetadata();
+
+ source.editOrNewProperties().addToAdditionalProperties(sourceProperties);
+ sink.editOrNewProperties().addToAdditionalProperties(sinkProperties);
+
+ builder.withNewSpec()
+ .withSource(source.build())
+ .withSink(sink.build())
+ .endSpec();
+
+ runner.run(camelk()
+ .client(k8sClient)
+ .createKameletBinding(name)
+ .fromBuilder(builder));
+
+ initializeKameletBindingBuilder();
+
+ if (isAutoRemoveResources()) {
+ runner.then(doFinally()
+ .actions(camelk().client(k8sClient)
+ .deleteKameletBinding(name)));
+ }
+ }
+
+ @Given("^delete KameletBinding ([a-z0-9-]+)$")
+ public void deleteKameletBinding(String name) {
+ runner.run(camelk()
+ .client(k8sClient)
+ .deleteKameletBinding(name));
+ }
+
+ @Given("^KameletBinding ([a-z0-9-]+) is available$")
+ @Then("^KameletBinding ([a-z0-9-]+) should be available$")
+ public void bindingShouldBeAvailable(String name) {
+ runner.run(camelk()
+ .client(k8sClient)
+ .verifyKameletBinding(name)
+ .isAvailable());
+ }
+
+ private void initializeKameletBindingBuilder() {
+ source = null;
+ sink = null;
+ sourceProperties = new HashMap<>();
+ sinkProperties = new HashMap<>();
+ }
+
+ private String getKameletApiVersion() {
+ if (context.getVariables().containsKey(VariableNames.KAMELET_API_VERSION.value())) {
+ return context.getVariable(VariableNames.KAMELET_API_VERSION.value());
+ }
+
+ return KameletSettings.getKameletApiVersion();
+ }
+
+ private String getNamespace() {
+ if (context.getVariables().containsKey(VariableNames.KAMELET_NAMESPACE.value())) {
+ return context.getVariable(VariableNames.KAMELET_NAMESPACE.value());
+ }
+
+ return KameletSettings.getNamespace();
+ }
+
+ private boolean isAutoRemoveResources() {
+ if (context.getVariables().containsKey(VariableNames.AUTO_REMOVE_RESOURCES.value())) {
+ return context.getVariable(VariableNames.AUTO_REMOVE_RESOURCES.value(), Boolean.class);
+ }
+
+ return CamelKSettings.isAutoRemoveResources();
+ }
+}
diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/KameletSteps.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/KameletSteps.java
index 1e5ebc75..bec2f8cb 100644
--- a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/KameletSteps.java
+++ b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/KameletSteps.java
@@ -23,7 +23,17 @@
import io.cucumber.java.Scenario;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
+import io.fabric8.kubernetes.api.model.AnyTypeBuilder;
import io.fabric8.kubernetes.client.KubernetesClient;
+import org.apache.camel.v1.KameletBuilder;
+import org.apache.camel.v1.KameletSpecBuilder;
+import org.apache.camel.v1.kameletspec.DataTypes;
+import org.apache.camel.v1.kameletspec.DefinitionBuilder;
+import org.apache.camel.v1.kameletspec.SourcesBuilder;
+import org.apache.camel.v1.kameletspec.TemplateBuilder;
+import org.apache.camel.v1.kameletspec.datatypes.TypesBuilder;
+import org.apache.camel.v1.kameletspec.definition.Properties;
+import org.apache.camel.v1.kameletspec.definition.PropertiesBuilder;
import org.citrusframework.Citrus;
import org.citrusframework.TestCaseRunner;
import org.citrusframework.annotations.CitrusFramework;
@@ -31,12 +41,6 @@
import org.citrusframework.context.TestContext;
import org.citrusframework.exceptions.CitrusRuntimeException;
import org.citrusframework.spi.Resource;
-import org.citrusframework.yaks.camelk.model.Kamelet;
-import org.citrusframework.yaks.camelk.model.KameletSpec;
-import org.citrusframework.yaks.camelk.model.Pipe;
-import org.citrusframework.yaks.camelk.model.PipeSpec;
-import org.citrusframework.yaks.kafka.KafkaSettings;
-import org.citrusframework.yaks.knative.KnativeSettings;
import org.citrusframework.yaks.kubernetes.KubernetesSupport;
import org.citrusframework.yaks.util.ResourceUtils;
import org.springframework.util.StringUtils;
@@ -61,15 +65,10 @@ public class KameletSteps {
private String kameletApiVersion = KameletSettings.getKameletApiVersion();
// Kamelet builder
- private Kamelet.Builder kamelet;
- private KameletSpec.Definition definition;
-
- // Pipe endpoints
- private PipeSpec.Endpoint source;
- private PipeSpec.Endpoint sink;
-
- private Map sourceProperties;
- private Map sinkProperties;
+ private KameletBuilder kamelet;
+ private KameletSpecBuilder kameletSpecBuilder;
+ private Map dataTypes;
+ private DefinitionBuilder definition;
private String namespace = KameletSettings.getNamespace();
@@ -83,17 +82,22 @@ public void before(Scenario scenario) {
}
initializeKameletBuilder();
- initializePipeBuilder();
}
@Given("^Disable auto removal of Kamelet resources$")
public void disableAutoRemove() {
autoRemoveResources = false;
+
+ // update the test variable
+ runner.run(createVariable(VariableNames.AUTO_REMOVE_RESOURCES.value(), "false"));
}
@Given("^Enable auto removal of Kamelet resources$")
public void enableAutoRemove() {
autoRemoveResources = true;
+
+ // update the test variable
+ runner.run(createVariable(VariableNames.AUTO_REMOVE_RESOURCES.value(), "true"));
}
@Given("^Disable variable support in Kamelet sources$")
@@ -124,27 +128,41 @@ public void setNamespace(String namespace) {
@Given("^Kamelet dataType (in|out|error)(?:=| is )\"(.+)\"$")
public void addType(String slot, String format) {
+ DataTypes dt;
+ if (dataTypes.containsKey(slot)) {
+ dt = dataTypes.get(slot);
+ } else {
+ dt = new DataTypes();
+ dataTypes.put(slot, dt);
+ }
+
+ if (dt.getTypes() == null) {
+ dt.setTypes(new HashMap<>());
+ }
+
if (format.contains(":")) {
String[] schemeAndFormat = format.split(":");
- kamelet.addDataType(slot, schemeAndFormat[0], schemeAndFormat[1]);
+ dt.getTypes().put(schemeAndFormat[1], new TypesBuilder().withScheme(schemeAndFormat[0]).withFormat(schemeAndFormat[1]).build());
} else {
- kamelet.addDataType(slot, "camel", format);
+ dt.getTypes().put(format, new TypesBuilder().withScheme("camel").withFormat(format).build());
}
}
@Given("^Kamelet title \"(.+)\"$")
public void setTitle(String title) {
- definition.setTitle(title);
+ definition.withTitle(title);
}
@Given("^Kamelet source ([a-z0-9-]+).([a-z0-9-]+)$")
public void setSource(String name, String language, String content) {
- kamelet.source(name, language, content);
+ kameletSpecBuilder.withSources(new SourcesBuilder().withName(name).withLanguage(language).withContent(content).build());
}
@Given("^Kamelet template")
public void setFlow(String template) {
- kamelet.template(template);
+ kameletSpecBuilder.withTemplate(new TemplateBuilder()
+ .withAdditionalProperties(KubernetesSupport.yaml().load(context.replaceDynamicContentInString(template)))
+ .build());
}
@Given("^Kamelet property definition$")
@@ -165,58 +183,19 @@ public void addPropertyDefinition(String propertyName, Map prope
String required = propertyConfiguration.getOrDefault("required", Boolean.FALSE).toString();
if (Boolean.parseBoolean(required)) {
- definition.getRequired().add(propertyName);
+ definition.addToRequired(propertyName);
}
- definition.getProperties().put(propertyName,
- new KameletSpec.Definition.PropertyConfig(title, type, defaultValue, example));
- }
-
- @Given("^(?:Pipe|KameletBinding) source properties$")
- public void setPipeSourceProperties(Map properties) {
- this.sourceProperties.putAll(properties);
- }
-
- @Given("^(?:Pipe|KameletBinding) sink properties$")
- public void setPipeSinkProperties(Map properties) {
- this.sinkProperties.putAll(properties);
- }
-
- @Given("^bind Kamelet ([a-z0-9-]+) to uri ([^\\s]+)$")
- public void bindKameletToUri(String kameletName, String uri) {
- PipeSpec.Endpoint.ObjectReference sourceRef =
- new PipeSpec.Endpoint.ObjectReference(CamelKSupport.CAMELK_CRD_GROUP + "/" + kameletApiVersion, "Kamelet", namespace, kameletName);
- source = new PipeSpec.Endpoint(sourceRef);
-
- sink = new PipeSpec.Endpoint(uri);
- }
-
- @Given("^bind Kamelet ([a-z0-9-]+) to Kafka topic ([^\\s]+)$")
- public void bindKameletToKafka(String kameletName, String topic) {
- PipeSpec.Endpoint.ObjectReference sourceRef =
- new PipeSpec.Endpoint.ObjectReference(CamelKSupport.CAMELK_CRD_GROUP + "/" + kameletApiVersion, "Kamelet", namespace, kameletName);
- source = new PipeSpec.Endpoint(sourceRef);
-
- PipeSpec.Endpoint.ObjectReference sinkRef =
- new PipeSpec.Endpoint.ObjectReference("KafkaTopic", KafkaSettings.getNamespace(), topic);
- sink = new PipeSpec.Endpoint(sinkRef);
- }
-
- @Given("^bind Kamelet ([a-z0-9-]+) to Knative channel ([^\\s]+)$")
- public void bindKameletToKnativeChannel(String kameletName, String channel) {
- bindKameletToKnativeChannel(kameletName, channel, "InMemoryChannel");
- }
-
- @Given("^bind Kamelet ([a-z0-9-]+) to Knative channel ([^\\s]+) of kind ([^\\s]+)$")
- public void bindKameletToKnativeChannel(String kameletName, String channel, String channelKind) {
- PipeSpec.Endpoint.ObjectReference sourceRef =
- new PipeSpec.Endpoint.ObjectReference(CamelKSupport.CAMELK_CRD_GROUP + "/" + kameletApiVersion, "Kamelet", namespace, kameletName);
- source = new PipeSpec.Endpoint(sourceRef);
+ Properties property = new PropertiesBuilder().withTitle(title).withType(type).build();
+ if (example != null) {
+ property.setExample(new AnyTypeBuilder().withValue(example).build());
+ }
- PipeSpec.Endpoint.ObjectReference sinkRef =
- new PipeSpec.Endpoint.ObjectReference(channelKind, KnativeSettings.getNamespace(), channel);
- sink = new PipeSpec.Endpoint(sinkRef);
- }
+ if (defaultValue != null) {
+ property.set_default(new AnyTypeBuilder().withValue(defaultValue).build());
+ }
+ definition.addToProperties(propertyName, property);
+ }
@Given("^load Kamelet ([a-z0-9-]+).kamelet.yaml$")
public void loadKameletFromFile(String fileName) {
@@ -224,6 +203,7 @@ public void loadKameletFromFile(String fileName) {
runner.run(camelk()
.client(k8sClient)
.createKamelet(fileName)
+ .namespace(namespace)
.apiVersion(kameletApiVersion)
.supportVariables(supportVariablesInSources)
.resource(resource));
@@ -236,31 +216,20 @@ public void loadKameletFromFile(String fileName) {
}
}
- @Given("^load (?:Pipe|KameletBinding) ([a-z0-9-]+).yaml$")
- public void loadPipeFromFile(String fileName) {
- Resource resource = ResourceUtils.resolve(fileName + ".yaml", context);
- runner.run(camelk()
- .client(k8sClient)
- .createPipe(fileName)
- .resource(resource));
-
- if (autoRemoveResources) {
- runner.then(doFinally()
- .actions(camelk().client(k8sClient)
- .deletePipe(fileName)
- .apiVersion(kameletApiVersion)));
- }
- }
-
@Given("^(?:create|new) Kamelet ([a-z0-9-]+)$")
public void createNewKamelet(String name) {
- kamelet.name(name);
+ kamelet.withNewMetadata()
+ .withName(name)
+ .endMetadata();
if (definition.getTitle() == null || definition.getTitle().isEmpty()) {
- definition.setTitle(StringUtils.capitalize(name));
+ definition.withTitle(StringUtils.capitalize(name));
}
- kamelet.definition(definition);
+ kameletSpecBuilder.withDefinition(definition.build());
+ kameletSpecBuilder.withDataTypes(dataTypes);
+
+ kamelet.withSpec(kameletSpecBuilder.build());
runner.run(camelk()
.client(k8sClient)
@@ -286,37 +255,12 @@ public void createNewKameletWithFlow(String name, String flow) {
@Given("^(?:create|new) Kamelet ([a-z0-9-]+) with template")
public void createNewKameletWithTemplate(String name, String template) {
- kamelet.template(template);
+ kameletSpecBuilder.withTemplate(new TemplateBuilder()
+ .withAdditionalProperties(KubernetesSupport.yaml().load(context.replaceDynamicContentInString(template)))
+ .build());
createNewKamelet(name);
}
- @Given("^(?:create|new) (?:Pipe|KameletBinding) ([a-z0-9-]+)$")
- public void createNewPipe(String name) {
- Pipe.Builder pipe = new Pipe.Builder();
- pipe.name(name);
-
- source.getProperties().putAll(sourceProperties);
- sink.getProperties().putAll(sinkProperties);
-
- pipe.source(source);
- pipe.sink(sink);
-
- runner.run(camelk()
- .client(k8sClient)
- .createPipe(name)
- .apiVersion(kameletApiVersion)
- .fromBuilder(pipe));
-
- initializePipeBuilder();
-
- if (autoRemoveResources) {
- runner.then(doFinally()
- .actions(camelk().client(k8sClient)
- .deletePipe(name)
- .apiVersion(kameletApiVersion)));
- }
- }
-
@Given("^delete Kamelet ([a-z0-9-]+)$")
public void deleteKamelet(String name) {
runner.run(camelk()
@@ -325,14 +269,6 @@ public void deleteKamelet(String name) {
.apiVersion(kameletApiVersion));
}
- @Given("^delete (?:Pipe|KameletBinding) ([a-z0-9-]+)$")
- public void deletePipe(String name) {
- runner.run(camelk()
- .client(k8sClient)
- .deletePipe(name)
- .apiVersion(kameletApiVersion));
- }
-
@Given("^Kamelet ([a-z0-9-]+) is available$")
@Then("^Kamelet ([a-z0-9-]+) should be available$")
public void kameletShouldBeAvailable(String name) {
@@ -354,25 +290,10 @@ public void kameletShouldBeAvailable(String name, String namespace) {
.isAvailable());
}
- @Given("^(?:Pipe|KameletBinding) ([a-z0-9-]+) is available$")
- @Then("^(?:Pipe|KameletBinding) ([a-z0-9-]+) should be available$")
- public void pipeShouldBeAvailable(String name) {
- runner.run(camelk()
- .client(k8sClient)
- .verifyPipe(name)
- .apiVersion(kameletApiVersion)
- .isAvailable());
- }
-
private void initializeKameletBuilder() {
- kamelet = new Kamelet.Builder();
- definition = new KameletSpec.Definition();
- }
-
- private void initializePipeBuilder() {
- source = null;
- sink = null;
- sourceProperties = new HashMap<>();
- sinkProperties = new HashMap<>();
+ kamelet = new KameletBuilder();
+ definition = new DefinitionBuilder();
+ kameletSpecBuilder = new KameletSpecBuilder();
+ dataTypes = new HashMap<>();
}
}
diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/PipeSteps.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/PipeSteps.java
new file mode 100644
index 00000000..c98a4c07
--- /dev/null
+++ b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/PipeSteps.java
@@ -0,0 +1,262 @@
+/*
+ * Copyright the original author or authors.
+ *
+ * Licensed 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.
+ */
+
+package org.citrusframework.yaks.camelk;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import io.cucumber.java.Before;
+import io.cucumber.java.Scenario;
+import io.cucumber.java.en.Given;
+import io.cucumber.java.en.Then;
+import io.fabric8.kubernetes.client.KubernetesClient;
+import org.apache.camel.v1.PipeBuilder;
+import org.apache.camel.v1.pipespec.SinkBuilder;
+import org.apache.camel.v1.pipespec.SourceBuilder;
+import org.apache.camel.v1.pipespec.source.Ref;
+import org.apache.camel.v1.pipespec.source.RefBuilder;
+import org.citrusframework.Citrus;
+import org.citrusframework.TestCaseRunner;
+import org.citrusframework.annotations.CitrusFramework;
+import org.citrusframework.annotations.CitrusResource;
+import org.citrusframework.context.TestContext;
+import org.citrusframework.spi.Resource;
+import org.citrusframework.yaks.kafka.KafkaSettings;
+import org.citrusframework.yaks.knative.KnativeSettings;
+import org.citrusframework.yaks.kubernetes.KubernetesSupport;
+import org.citrusframework.yaks.util.ResourceUtils;
+
+import static org.citrusframework.container.FinallySequence.Builder.doFinally;
+import static org.citrusframework.yaks.camelk.actions.CamelKActionBuilder.camelk;
+
+public class PipeSteps {
+
+ @CitrusResource
+ private TestCaseRunner runner;
+
+ @CitrusFramework
+ private Citrus citrus;
+
+ @CitrusResource
+ private TestContext context;
+
+ private KubernetesClient k8sClient;
+
+ // Pipe endpoints
+ private SourceBuilder source;
+ private SinkBuilder sink;
+
+ private Map sourceProperties;
+ private Map sinkProperties;
+
+ @Before
+ public void before(Scenario scenario) {
+ if (k8sClient == null) {
+ k8sClient = KubernetesSupport.getKubernetesClient(citrus);
+ }
+
+ initializePipeBuilder();
+ }
+
+ @Given("^Pipe source properties$")
+ public void setPipeSourceProperties(Map properties) {
+ this.sourceProperties.putAll(properties);
+ }
+
+ @Given("^Pipe sink properties$")
+ public void setPipeSinkProperties(Map properties) {
+ this.sinkProperties.putAll(properties);
+ }
+
+ @Given("^Pipe event source Kamelet ([a-z0-9-]+)$")
+ public void setKameletEventSource(String kameletName) {
+ Ref kameletRef = new RefBuilder()
+ .withName(kameletName)
+ .withApiVersion(CamelKSupport.CAMELK_CRD_GROUP + "/" + getKameletApiVersion())
+ .withKind("Kamelet")
+ .withNamespace(getNamespace())
+ .build();
+ source = new SourceBuilder().withRef(kameletRef);
+ }
+
+ @Given("^Pipe event sink uri ([^\\s]+)$")
+ public void setEventSinkUri(String uri) {
+ sink = new SinkBuilder().withUri(uri);
+ }
+
+ @Given("^Pipe event sink Kafka topic ([^\\s]+)$")
+ public void setEventSinkKafkaTopic(String topic) {
+ org.apache.camel.v1.pipespec.sink.Ref sinkRef =
+ new org.apache.camel.v1.pipespec.sink.RefBuilder()
+ .withName(topic)
+ .withApiVersion("kafka.strimzi.io/" + KafkaSettings.getApiVersion())
+ .withKind("KafkaTopic")
+ .withNamespace(KafkaSettings.getNamespace())
+ .build();
+ sink = new SinkBuilder().withRef(sinkRef);
+ }
+
+ @Given("^Pipe event sink Knative channel ([^\\s]+)$")
+ public void setEventSinkKnativeChannel(String channel) {
+ setEventSinkKnativeChannel(channel, "InMemoryChannel");
+ }
+
+ @Given("^Pipe event sink Knative channel ([^\\s]+) of kind ([^\\s]+)$")
+ public void setEventSinkKnativeChannel(String channel, String channelKind) {
+ org.apache.camel.v1.pipespec.sink.Ref sinkRef =
+ new org.apache.camel.v1.pipespec.sink.RefBuilder()
+ .withName(channel)
+ .withApiVersion("messaging.knative.dev/" + KnativeSettings.getApiVersion())
+ .withKind(channelKind)
+ .withNamespace(KnativeSettings.getNamespace())
+ .build();
+ sink = new SinkBuilder().withRef(sinkRef);
+ }
+
+ @Given("^Pipe event sink Knative broker ([^\\s]+)$")
+ public void setEventSinkKnativeBroker(String broker) {
+ org.apache.camel.v1.pipespec.sink.Ref sinkRef =
+ new org.apache.camel.v1.pipespec.sink.RefBuilder()
+ .withName(broker)
+ .withApiVersion("eventing.knative.dev/" + KnativeSettings.getApiVersion())
+ .withKind("Broker")
+ .withNamespace(KnativeSettings.getNamespace())
+ .build();
+ sink = new SinkBuilder().withRef(sinkRef);
+ }
+
+ @Given("^bind Kamelet ([a-z0-9-]+) to uri ([^\\s]+)$")
+ public void bindKameletToUri(String kameletName, String uri) {
+ setKameletEventSource(kameletName);
+ setEventSinkUri(uri);
+ }
+
+ @Given("^bind Kamelet ([a-z0-9-]+) to Kafka topic ([^\\s]+)$")
+ public void bindKameletToKafka(String kameletName, String topic) {
+ setKameletEventSource(kameletName);
+ setEventSinkKafkaTopic(topic);
+ }
+
+ @Given("^bind Kamelet ([a-z0-9-]+) to Knative channel ([^\\s]+)$")
+ public void bindKameletToKnativeChannel(String kameletName, String channel) {
+ bindKameletToKnativeChannel(kameletName, channel, "InMemoryChannel");
+ }
+
+ @Given("^bind Kamelet ([a-z0-9-]+) to Knative channel ([^\\s]+) of kind ([^\\s]+)$")
+ public void bindKameletToKnativeChannel(String kameletName, String channel, String channelKind) {
+ setKameletEventSource(kameletName);
+ setEventSinkKnativeChannel(channel, channelKind);
+ }
+
+ @Given("^bind Kamelet ([a-z0-9-]+) to Knative broker ([^\\s]+)$")
+ public void bindKameletToKnativeBroker(String kameletName, String broker) {
+ setKameletEventSource(kameletName);
+ setEventSinkKnativeBroker(broker);
+ }
+
+ @Given("^load Pipe ([a-z0-9-]+).yaml$")
+ public void loadPipeFromFile(String fileName) {
+ Resource resource = ResourceUtils.resolve(fileName + ".yaml", context);
+ runner.run(camelk()
+ .client(k8sClient)
+ .createPipe(fileName)
+ .resource(resource));
+
+ if (isAutoRemoveResources()) {
+ runner.then(doFinally()
+ .actions(camelk().client(k8sClient)
+ .deletePipe(fileName)));
+ }
+ }
+
+ @Given("^(?:create|new) Pipe ([a-z0-9-]+)$")
+ public void createNewPipe(String name) {
+ PipeBuilder pipe = new PipeBuilder();
+
+ pipe.withNewMetadata()
+ .withName(name)
+ .endMetadata();
+
+ source.editOrNewProperties().addToAdditionalProperties(sourceProperties);
+ sink.editOrNewProperties().addToAdditionalProperties(sinkProperties);
+
+ pipe.withNewSpec()
+ .withSource(source.build())
+ .withSink(sink.build())
+ .endSpec();
+
+ runner.run(camelk()
+ .client(k8sClient)
+ .createPipe(name)
+ .fromBuilder(pipe));
+
+ initializePipeBuilder();
+
+ if (isAutoRemoveResources()) {
+ runner.then(doFinally()
+ .actions(camelk().client(k8sClient)
+ .deletePipe(name)));
+ }
+ }
+
+ @Given("^delete Pipe ([a-z0-9-]+)$")
+ public void deletePipe(String name) {
+ runner.run(camelk()
+ .client(k8sClient)
+ .deletePipe(name));
+ }
+
+ @Given("^Pipe ([a-z0-9-]+) is available$")
+ @Then("^Pipe ([a-z0-9-]+) should be available$")
+ public void pipeShouldBeAvailable(String name) {
+ runner.run(camelk()
+ .client(k8sClient)
+ .verifyPipe(name)
+ .isAvailable());
+ }
+
+ private void initializePipeBuilder() {
+ source = null;
+ sink = null;
+ sourceProperties = new HashMap<>();
+ sinkProperties = new HashMap<>();
+ }
+
+ private String getKameletApiVersion() {
+ if (context.getVariables().containsKey(VariableNames.KAMELET_API_VERSION.value())) {
+ return context.getVariable(VariableNames.KAMELET_API_VERSION.value());
+ }
+
+ return KameletSettings.getKameletApiVersion();
+ }
+
+ private String getNamespace() {
+ if (context.getVariables().containsKey(VariableNames.KAMELET_NAMESPACE.value())) {
+ return context.getVariable(VariableNames.KAMELET_NAMESPACE.value());
+ }
+
+ return KameletSettings.getNamespace();
+ }
+
+ private boolean isAutoRemoveResources() {
+ if (context.getVariables().containsKey(VariableNames.AUTO_REMOVE_RESOURCES.value())) {
+ return context.getVariable(VariableNames.AUTO_REMOVE_RESOURCES.value(), Boolean.class);
+ }
+
+ return CamelKSettings.isAutoRemoveResources();
+ }
+}
diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/VariableNames.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/VariableNames.java
index ae07df55..6f465f29 100644
--- a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/VariableNames.java
+++ b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/VariableNames.java
@@ -26,7 +26,8 @@ public enum VariableNames {
KAMELET_API_VERSION("KAMELET_API_VERSION"),
KAMELET_NAMESPACE("KAMELET_NAMESPACE"),
- OPERATOR_NAMESPACE("CAMELK_OPERATOR_NAMESPACE");
+ OPERATOR_NAMESPACE("CAMELK_OPERATOR_NAMESPACE"),
+ AUTO_REMOVE_RESOURCES("CAMELK_AUTO_REMOVE_RESOURCES");
private final String variableName;
diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/CamelKActionBuilder.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/CamelKActionBuilder.java
index 1dfd3e14..75beb9b3 100644
--- a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/CamelKActionBuilder.java
+++ b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/CamelKActionBuilder.java
@@ -16,16 +16,19 @@
package org.citrusframework.yaks.camelk.actions;
-import org.citrusframework.TestActionBuilder;
import io.fabric8.kubernetes.client.KubernetesClient;
+import org.citrusframework.TestActionBuilder;
import org.citrusframework.yaks.camelk.actions.integration.CreateIntegrationAction;
import org.citrusframework.yaks.camelk.actions.integration.DeleteIntegrationAction;
import org.citrusframework.yaks.camelk.actions.integration.VerifyIntegrationAction;
import org.citrusframework.yaks.camelk.actions.kamelet.CreateKameletAction;
+import org.citrusframework.yaks.camelk.actions.kamelet.CreateKameletBindingAction;
import org.citrusframework.yaks.camelk.actions.kamelet.CreatePipeAction;
import org.citrusframework.yaks.camelk.actions.kamelet.DeleteKameletAction;
+import org.citrusframework.yaks.camelk.actions.kamelet.DeleteKameletBindingAction;
import org.citrusframework.yaks.camelk.actions.kamelet.DeletePipeAction;
import org.citrusframework.yaks.camelk.actions.kamelet.VerifyKameletAction;
+import org.citrusframework.yaks.camelk.actions.kamelet.VerifyKameletBindingAction;
import org.citrusframework.yaks.camelk.actions.kamelet.VerifyPipeAction;
import org.springframework.util.Assert;
@@ -127,6 +130,30 @@ public DeletePipeAction.Builder deletePipe(String pipeName) {
return builder;
}
+ /**
+ * Create binding CRD in current namespace.
+ * @param bindingName the name of the binding.
+ */
+ public CreateKameletBindingAction.Builder createKameletBinding(String bindingName) {
+ CreateKameletBindingAction.Builder builder = new CreateKameletBindingAction.Builder()
+ .client(kubernetesClient)
+ .binding(bindingName);
+ this.delegate = builder;
+ return builder;
+ }
+
+ /**
+ * Delete binding CRD from current namespace.
+ * @param bindingName the name of the binding.
+ */
+ public DeleteKameletBindingAction.Builder deleteKameletBinding(String bindingName) {
+ DeleteKameletBindingAction.Builder builder = new DeleteKameletBindingAction.Builder()
+ .client(kubernetesClient)
+ .binding(bindingName);
+ this.delegate = builder;
+ return builder;
+ }
+
/**
* Verify that given integration is running.
* @param integrationName the name of the Camel K integration.
@@ -163,6 +190,18 @@ public VerifyPipeAction.Builder verifyPipe(String pipeName) {
return builder;
}
+ /**
+ * Verify that given binding CRD is available in current namespace.
+ * @param bindingName the name of the binding.
+ */
+ public VerifyKameletBindingAction.Builder verifyKameletBinding(String bindingName) {
+ VerifyKameletBindingAction.Builder builder = new VerifyKameletBindingAction.Builder()
+ .client(kubernetesClient)
+ .isAvailable(bindingName);
+ this.delegate = builder;
+ return builder;
+ }
+
@Override
public CamelKAction build() {
Assert.notNull(delegate, "Missing delegate action to build");
diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/integration/CreateIntegrationAction.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/integration/CreateIntegrationAction.java
index e439f962..16cb9719 100644
--- a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/integration/CreateIntegrationAction.java
+++ b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/integration/CreateIntegrationAction.java
@@ -23,7 +23,6 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
-import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
@@ -32,17 +31,20 @@
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.dsl.Updatable;
+import org.apache.camel.v1.Integration;
+import org.apache.camel.v1.IntegrationBuilder;
+import org.apache.camel.v1.IntegrationSpecBuilder;
+import org.apache.camel.v1.integrationspec.ConfigurationBuilder;
+import org.apache.camel.v1.integrationspec.SourcesBuilder;
+import org.apache.camel.v1.integrationspec.Traits;
import org.citrusframework.context.TestContext;
import org.citrusframework.exceptions.CitrusRuntimeException;
-import org.citrusframework.util.FileUtils;
import org.citrusframework.variable.VariableUtils;
import org.citrusframework.yaks.YaksSettings;
import org.citrusframework.yaks.camelk.actions.AbstractCamelKAction;
import org.citrusframework.yaks.camelk.jbang.CamelJBangSettings;
import org.citrusframework.yaks.camelk.jbang.ProcessAndOutput;
-import org.citrusframework.yaks.camelk.model.Integration;
import org.citrusframework.yaks.camelk.model.IntegrationList;
-import org.citrusframework.yaks.camelk.model.IntegrationSpec;
import org.citrusframework.yaks.kubernetes.KubernetesSupport;
import org.citrusframework.yaks.util.ResourceUtils;
import org.slf4j.Logger;
@@ -72,7 +74,7 @@ public class CreateIntegrationAction extends AbstractCamelKAction {
private final List properties;
private final List propertyFiles;
private final List traits;
- private final Map openApis;
+ private final List openApis;
private final boolean supportVariables;
/**
@@ -109,22 +111,31 @@ public void doExecute(TestContext context) {
resolvedSource = source;
}
- final Integration.Builder integrationBuilder = new Integration.Builder()
- .name(name)
- .source(context.replaceDynamicContentInString(fileName), resolvedSource);
+ final IntegrationBuilder integrationBuilder = new IntegrationBuilder()
+ .withNewMetadata()
+ .withName(name)
+ .endMetadata();
+
+ IntegrationSpecBuilder specBuilder = new IntegrationSpecBuilder();
+ specBuilder.addToSources(new SourcesBuilder().withName(context.replaceDynamicContentInString(fileName)).withContent(resolvedSource).build());
List resolvedDependencies = resolveDependencies(resolvedSource, context.resolveDynamicValuesInList(dependencies));
if (!resolvedDependencies.isEmpty()) {
- integrationBuilder.dependencies(resolvedDependencies);
+ specBuilder.addAllToDependencies(resolvedDependencies);
}
- addPropertyConfigurationSpec(integrationBuilder, context);
- addBuildPropertyConfigurationSpec(integrationBuilder, resolvedSource, context);
- addEnvVarConfigurationSpec(integrationBuilder, resolvedSource, context);
- addRuntimeConfigurationSpec(integrationBuilder, resolvedSource, context);
- addTraitSpec(integrationBuilder, resolvedSource, context);
- addOpenApiSpec(integrationBuilder, resolvedSource, context);
+ Map> traitConfigMap = new HashMap<>();
+ addPropertyConfigurationSpec(specBuilder, context);
+ addRuntimeConfigurationSpec(specBuilder, resolvedSource, context);
+ addBuildPropertyConfigurationSpec(traitConfigMap, resolvedSource, context);
+ addEnvVarConfigurationSpec(traitConfigMap, resolvedSource, context);
+ addOpenApiSpec(traitConfigMap, resolvedSource, context);
+ addTraitSpec(traitConfigMap, resolvedSource, context);
+
+ specBuilder.withTraits(KubernetesSupport.json().convertValue(traitConfigMap, Traits.class));
- final Integration integration = integrationBuilder.build();
+ final Integration integration = integrationBuilder
+ .withSpec(specBuilder.build())
+ .build();
if (YaksSettings.isLocal(clusterType(context))) {
createLocalIntegration(integration, integration.getMetadata().getName(), context);
} else {
@@ -142,7 +153,7 @@ public void doExecute(TestContext context) {
*/
private static void createIntegration(KubernetesClient k8sClient, String namespace, Integration integration) {
if (LOG.isDebugEnabled()) {
- LOG.debug(KubernetesSupport.yaml().dumpAsMap(integration));
+ LOG.debug(KubernetesSupport.yaml(new IntegrationValuePropertyMapper()).dumpAsMap(integration));
}
k8sClient.resources(Integration.class, IntegrationList.class)
@@ -159,7 +170,7 @@ private static void createIntegration(KubernetesClient k8sClient, String namespa
*/
private static void createLocalIntegration(Integration integration, String name, TestContext context) {
try {
- String integrationYaml = KubernetesSupport.yaml().dumpAsMap(integration);
+ String integrationYaml = KubernetesSupport.yaml(new IntegrationValuePropertyMapper()).dumpAsMap(integration);
if (LOG.isDebugEnabled()) {
LOG.debug(integrationYaml);
@@ -202,39 +213,35 @@ private static void createLocalIntegration(Integration integration, String name,
private static String[] camelRunArgs(Integration integration) {
List args = new ArrayList<>();
- if (integration.getSpec().getResources() != null) {
- List openApiResources = integration.getSpec().getResources()
- .stream()
- .filter(r -> "openapi".equals(r.getType()))
- .toList();
-
- for (IntegrationSpec.Resource resource : openApiResources) {
+ if (integration.getSpec().getTraits().getOpenapi() != null) {
+ for (String openApi : integration.getSpec().getTraits().getOpenapi().getConfigmaps()) {
args.add("--open-api");
- args.add(resource.getName());
+ if (openApi.startsWith("configmap:")) {
+ args.add(openApi.substring("configmap:".length()));
+ } else {
+ args.add(openApi);
+ }
}
}
return args.toArray(String[]::new);
}
- private void addOpenApiSpec(Integration.Builder integrationBuilder, String source, TestContext context) {
+ private void addOpenApiSpec(Map> traitConfigMap, String source, TestContext context) {
+ String traitName = "openapi.configmaps";
Pattern pattern = getModelinePattern("open-api");
Matcher depMatcher = pattern.matcher(source);
while (depMatcher.find()) {
String openApiSpecFile = depMatcher.group(1);
- try {
- integrationBuilder.openApi(openApiSpecFile, FileUtils.readToString(FileUtils.getFileResource(openApiSpecFile, context)));
- } catch (IOException e) {
- throw new CitrusRuntimeException(String.format("Failed to load OpenAPI spec from file '%s'", openApiSpecFile), e);
- }
+ addTraitSpec("%s=%s".formatted(traitName, context.replaceDynamicContentInString(openApiSpecFile)), traitConfigMap);
}
- openApis.forEach((k, v) -> integrationBuilder.openApi(k, context.replaceDynamicContentInString(v)));
+ for (String openApi : openApis) {
+ addTraitSpec("%s=%s".formatted(traitName, context.replaceDynamicContentInString(openApi)), traitConfigMap);
+ }
}
- private void addTraitSpec(Integration.Builder integrationBuilder, String source, TestContext context) {
- final Map traitConfigMap = new HashMap<>();
-
+ private void addTraitSpec(Map> traitConfigMap, String source, TestContext context) {
if (traits != null && !traits.isEmpty()) {
for (String t : context.resolveDynamicValuesInList(traits)) {
addTraitSpec(t, traitConfigMap);
@@ -246,36 +253,34 @@ private void addTraitSpec(Integration.Builder integrationBuilder, String source,
while (depMatcher.find()) {
addTraitSpec(depMatcher.group(1), traitConfigMap);
}
-
- if (!traitConfigMap.isEmpty()) {
- integrationBuilder.traits(traitConfigMap);
- }
}
- private void addTraitSpec(String traitExpression, Map configMap) {
+ private void addTraitSpec(String traitExpression, Map> traitConfigMap) {
//traitName.key=value
final String[] trait = traitExpression.split("\\.",2);
final String[] traitConfig = trait[1].split("=", 2);
final String traitKey = traitConfig[0];
final Object traitValue = resolveTraitValue(traitKey, traitConfig[1].trim());
- if (configMap.containsKey(trait[0])) {
- IntegrationSpec.TraitConfig config = configMap.get(trait[0]);
+ if (traitConfigMap.containsKey(trait[0])) {
+ Map config = traitConfigMap.get(trait[0]);
- if (config.getConfiguration().containsKey(traitKey)) {
- Object existingValue = config.getConfiguration().get(traitKey);
+ if (config.containsKey(traitKey)) {
+ Object existingValue = config.get(traitKey);
if (existingValue instanceof List) {
List values = (List) existingValue;
values.add(traitValue.toString());
} else {
- config.add(traitKey, Arrays.asList(existingValue.toString(), traitValue));
+ config.put(traitKey, Arrays.asList(existingValue.toString(), traitValue));
}
} else {
- config.add(traitKey, initializeTraitValue(traitValue));
+ config.put(traitKey, initializeTraitValue(traitValue));
}
} else {
- configMap.put(trait[0], new IntegrationSpec.TraitConfig(traitKey, initializeTraitValue(traitValue)));
+ Map config = new HashMap<>();
+ config.put(traitKey, initializeTraitValue(traitValue));
+ traitConfigMap.put(trait[0], config);
}
}
@@ -316,15 +321,14 @@ private Object resolveTraitValue(String traitKey, String value) {
}
}
- private void addPropertyConfigurationSpec(Integration.Builder integrationBuilder, TestContext context) {
- final List configurationList = new ArrayList<>();
+ private void addPropertyConfigurationSpec(IntegrationSpecBuilder specBuilder, TestContext context) {
if (properties != null && !properties.isEmpty()) {
for (String p : context.resolveDynamicValuesInList(properties)){
//key=value
if (isValidPropertyFormat(p)) {
final String[] property = p.split("=",2);
- configurationList.add(
- new IntegrationSpec.Configuration("property", createPropertySpec(property[0], property[1], context)));
+ specBuilder.addToConfiguration(
+ new ConfigurationBuilder().withType("property").withValue(createPropertySpec(property[0], property[1], context)).build());
} else {
throw new IllegalArgumentException("Property " + p + " does not match format key=value");
}
@@ -336,22 +340,17 @@ private void addPropertyConfigurationSpec(Integration.Builder integrationBuilder
try {
Properties props = new Properties();
props.load(ResourceUtils.resolve(pf, context).getInputStream());
- props.forEach((key, value) -> configurationList.add(
- new IntegrationSpec.Configuration("property", createPropertySpec(key.toString(), value.toString(), context))));
+ props.forEach((key, value) -> specBuilder.addToConfiguration(
+ new ConfigurationBuilder().withType("property").withValue(createPropertySpec(key.toString(), value.toString(), context)).build()));
} catch (IOException e) {
throw new CitrusRuntimeException("Failed to load property file", e);
}
}
}
-
- if (!configurationList.isEmpty()) {
- integrationBuilder.configuration(configurationList);
- }
}
- private void addBuildPropertyConfigurationSpec(Integration.Builder integrationBuilder, String source, TestContext context) {
+ private void addBuildPropertyConfigurationSpec(Map> traitConfigMap, String source, TestContext context) {
final String traitName = "builder.properties";
- final Map traitConfigMap = new HashMap<>();
if (buildProperties != null && !buildProperties.isEmpty()) {
for (String p : context.resolveDynamicValuesInList(buildProperties)){
@@ -384,15 +383,10 @@ private void addBuildPropertyConfigurationSpec(Integration.Builder integrationBu
while (depMatcher.find()) {
addTraitSpec(String.format("%s=%s", traitName, depMatcher.group(1)), traitConfigMap);
}
-
- if (!traitConfigMap.isEmpty()) {
- integrationBuilder.traits(traitConfigMap);
- }
}
- private void addEnvVarConfigurationSpec(Integration.Builder integrationBuilder, String source, TestContext context) {
+ private void addEnvVarConfigurationSpec(Map> traitConfigMap, String source, TestContext context) {
final String traitName = "environment.vars";
- final Map traitConfigMap = new HashMap<>();
if (envVars != null && !envVars.isEmpty()) {
for (String v : context.resolveDynamicValuesInList(envVars)){
@@ -425,29 +419,19 @@ private void addEnvVarConfigurationSpec(Integration.Builder integrationBuilder,
while (depMatcher.find()) {
addTraitSpec(String.format("%s=%s", traitName, depMatcher.group(1)), traitConfigMap);
}
-
- if (!traitConfigMap.isEmpty()) {
- integrationBuilder.traits(traitConfigMap);
- }
}
- private void addRuntimeConfigurationSpec(Integration.Builder integrationBuilder, String source, TestContext context) {
- final List configurationList = new ArrayList<>();
-
+ private void addRuntimeConfigurationSpec(IntegrationSpecBuilder specBuilder, String source, TestContext context) {
Pattern pattern = getModelinePattern("config");
Matcher depMatcher = pattern.matcher(source);
while (depMatcher.find()) {
String[] config = depMatcher.group(1).split(":", 2);
if (config.length == 2) {
- configurationList.add(new IntegrationSpec.Configuration(config[0], config[1]));
+ specBuilder.addToConfiguration(new ConfigurationBuilder().withType(config[0]).withValue(context.replaceDynamicContentInString(config[1])).build());
} else {
- configurationList.add(new IntegrationSpec.Configuration("property", depMatcher.group(1)));
+ specBuilder.addToConfiguration(new ConfigurationBuilder().withType("property").withValue(context.replaceDynamicContentInString(depMatcher.group(1))).build());
}
}
-
- if (!configurationList.isEmpty()) {
- integrationBuilder.configuration(configurationList);
- }
}
private String createPropertySpec(String key, String value, TestContext context) {
@@ -525,7 +509,7 @@ public static final class Builder extends AbstractCamelKAction.Builder properties = new ArrayList<>();
private final List propertyFiles = new ArrayList<>();
private final List traits = new ArrayList<>();
- private final Map openApis = new LinkedHashMap<>();
+ private final List openApis = new ArrayList<>();
private boolean supportVariables = true;
public Builder integration(String integrationName) {
@@ -559,8 +543,8 @@ public Builder source(String fileName, String source) {
return this;
}
- public Builder openApi(String fileName, String content) {
- this.openApis.put(fileName, content);
+ public Builder openApi(String configMap) {
+ this.openApis.add(configMap);
return this;
}
diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/integration/DeleteIntegrationAction.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/integration/DeleteIntegrationAction.java
index 9b72b360..65ed6775 100644
--- a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/integration/DeleteIntegrationAction.java
+++ b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/integration/DeleteIntegrationAction.java
@@ -16,12 +16,12 @@
package org.citrusframework.yaks.camelk.actions.integration;
+import io.fabric8.kubernetes.client.KubernetesClient;
+import org.apache.camel.v1.Integration;
import org.citrusframework.context.TestContext;
import org.citrusframework.exceptions.CitrusRuntimeException;
-import io.fabric8.kubernetes.client.KubernetesClient;
import org.citrusframework.yaks.YaksSettings;
import org.citrusframework.yaks.camelk.actions.AbstractCamelKAction;
-import org.citrusframework.yaks.camelk.model.Integration;
import org.citrusframework.yaks.camelk.model.IntegrationList;
import static org.citrusframework.yaks.camelk.jbang.CamelJBang.camel;
diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/integration/IntegrationValuePropertyMapper.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/integration/IntegrationValuePropertyMapper.java
new file mode 100644
index 00000000..38ee8ca0
--- /dev/null
+++ b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/integration/IntegrationValuePropertyMapper.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright the original author or authors.
+ *
+ * Licensed 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.
+ */
+
+package org.citrusframework.yaks.camelk.actions.integration;
+
+import java.util.Collections;
+
+import org.citrusframework.yaks.kubernetes.KubernetesSupport;
+import org.yaml.snakeyaml.introspector.Property;
+
+/**
+ * Helper to properly handle additional properties on Integration additional properties.
+ */
+class IntegrationValuePropertyMapper implements KubernetesSupport.PropertyValueMapper {
+ @Override
+ public Object map(Property property, Object propertyValue) {
+ if (propertyValue == null) {
+ return null;
+ }
+
+ if (property.getName().equals("additionalProperties")) {
+ return Collections.emptyMap();
+ }
+
+ if (propertyValue instanceof org.apache.camel.v1.integrationspec.Flows flowsProps) {
+ return flowsProps.getAdditionalProperties();
+ }
+
+ return propertyValue;
+ }
+}
diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/integration/VerifyIntegrationAction.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/integration/VerifyIntegrationAction.java
index 6cea50ba..92118d3e 100644
--- a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/integration/VerifyIntegrationAction.java
+++ b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/integration/VerifyIntegrationAction.java
@@ -22,6 +22,9 @@
import io.fabric8.kubernetes.api.model.PodCondition;
import io.fabric8.kubernetes.api.model.PodList;
import io.fabric8.kubernetes.client.dsl.PodResource;
+import org.apache.camel.v1.Integration;
+import org.apache.camel.v1.IntegrationStatus;
+import org.apache.camel.v1.integrationstatus.Conditions;
import org.citrusframework.context.TestContext;
import org.citrusframework.exceptions.ActionTimeoutException;
import org.citrusframework.exceptions.CitrusRuntimeException;
@@ -29,9 +32,7 @@
import org.citrusframework.yaks.camelk.CamelKSettings;
import org.citrusframework.yaks.camelk.actions.AbstractCamelKAction;
import org.citrusframework.yaks.camelk.jbang.ProcessAndOutput;
-import org.citrusframework.yaks.camelk.model.Integration;
import org.citrusframework.yaks.camelk.model.IntegrationList;
-import org.citrusframework.yaks.camelk.model.IntegrationStatus;
import org.citrusframework.yaks.kubernetes.KubernetesSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -338,7 +339,7 @@ private Pod getIntegrationPod(final String integration, final String phase, fina
}
private String getReadyConditionErrorDetails(IntegrationStatus status) {
- for (IntegrationStatus.Condition condition : status.getConditions()) {
+ for (Conditions condition : status.getConditions()) {
if ("Ready".equals(condition.getType()) && "False".equalsIgnoreCase(condition.getStatus())) {
return "%s: %s".formatted(condition.getReason(), condition.getMessage());
}
diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/kamelet/CreateKameletAction.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/kamelet/CreateKameletAction.java
index c0bc146f..ec294fd9 100644
--- a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/kamelet/CreateKameletAction.java
+++ b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/kamelet/CreateKameletAction.java
@@ -25,15 +25,26 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import io.fabric8.kubernetes.client.dsl.Updatable;
+import org.apache.camel.v1.Kamelet;
+import org.apache.camel.v1.KameletBuilder;
+import org.apache.camel.v1.KameletSpecBuilder;
+import org.apache.camel.v1.kameletspec.DataTypes;
+import org.apache.camel.v1.kameletspec.DataTypesBuilder;
+import org.apache.camel.v1.kameletspec.Definition;
+import org.apache.camel.v1.kameletspec.Sources;
+import org.apache.camel.v1.kameletspec.SourcesBuilder;
+import org.apache.camel.v1.kameletspec.TemplateBuilder;
+import org.apache.camel.v1.kameletspec.datatypes.Types;
+import org.apache.camel.v1.kameletspec.datatypes.TypesBuilder;
+import org.apache.camel.v1.kameletspec.definition.Properties;
import org.citrusframework.context.TestContext;
import org.citrusframework.exceptions.CitrusRuntimeException;
import org.citrusframework.spi.Resource;
import org.citrusframework.util.FileUtils;
+import org.citrusframework.util.IsJsonPredicate;
import org.citrusframework.yaks.camelk.CamelKSettings;
import org.citrusframework.yaks.camelk.KameletSettings;
-import org.citrusframework.yaks.camelk.model.Kamelet;
import org.citrusframework.yaks.camelk.model.KameletList;
-import org.citrusframework.yaks.camelk.model.KameletSpec;
import org.citrusframework.yaks.camelk.model.v1alpha1.KameletV1Alpha1;
import org.citrusframework.yaks.camelk.model.v1alpha1.KameletV1Alpha1List;
import org.citrusframework.yaks.kubernetes.KubernetesSupport;
@@ -49,10 +60,10 @@ public class CreateKameletAction extends AbstractKameletAction {
private final String name;
private final String template;
- private final KameletSpec.Source source;
- private final KameletSpec.Definition definition;
+ private final Sources source;
+ private final Definition definition;
private final List dependencies;
- private final Map dataTypes;
+ private final Map dataTypes;
private final Resource resource;
private final boolean supportVariables;
@@ -89,7 +100,13 @@ private void createKamelet(TestContext context) {
resolvedSource = FileUtils.readToString(resource);
}
- kamelet = KubernetesSupport.yaml().loadAs(resolvedSource, Kamelet.class);
+ if (IsJsonPredicate.getInstance().test(resolvedSource)) {
+ kamelet = KubernetesSupport.json().readValue(resolvedSource, Kamelet.class);
+ } else {
+ // need to make a detour over Json to support additional properties set on Pipe
+ Map raw = KubernetesSupport.yaml().load(resolvedSource);
+ kamelet = KubernetesSupport.json().convertValue(raw, Kamelet.class);
+ }
} catch (IOException e) {
throw new CitrusRuntimeException(String.format("Failed to load Kamelet from resource %s", name + ".kamelet.yaml"), e);
}
@@ -105,27 +122,36 @@ private void createKamelet(TestContext context) {
definition.setProperties(context.resolveDynamicValuesInMap(definition.getProperties()));
definition.setRequired(context.resolveDynamicValuesInList(definition.getRequired()));
- final Kamelet.Builder builder = new Kamelet.Builder()
- .name(context.replaceDynamicContentInString(name))
- .definition(definition);
+ final KameletBuilder builder = new KameletBuilder()
+ .withNewMetadata()
+ .withName(context.replaceDynamicContentInString(name))
+ .endMetadata();
+
+ KameletSpecBuilder specBuilder = new KameletSpecBuilder()
+ .withDefinition(definition);
if (template != null) {
- builder.template(context.replaceDynamicContentInString(template));
+ specBuilder.withTemplate(new TemplateBuilder()
+ .withAdditionalProperties(KubernetesSupport.yaml().load(context.replaceDynamicContentInString(template)))
+ .build());
}
if (source != null) {
- builder.source(source.getName(), context.replaceDynamicContentInString(source.getContent()));
+ specBuilder.withSources(new SourcesBuilder()
+ .withName(source.getName())
+ .withContent(context.replaceDynamicContentInString(source.getContent()))
+ .build());
}
if (dependencies != null && !dependencies.isEmpty()) {
- builder.dependencies(context.resolveDynamicValuesInList(dependencies));
+ specBuilder.withDependencies(context.resolveDynamicValuesInList(dependencies));
}
if (dataTypes != null && !dataTypes.isEmpty()) {
- builder.dataTypes(context.resolveDynamicValuesInMap(dataTypes));
+ specBuilder.withDataTypes(dataTypes);
}
- kamelet = builder.build();
+ kamelet = builder.withSpec(specBuilder.build()).build();
}
if (!kamelet.getMetadata().getLabels().containsKey(KameletSettings.KAMELET_TYPE_LABEL)) {
@@ -150,12 +176,7 @@ private void createKamelet(TestContext context) {
}
if (getApiVersion(context).equals(CamelKSettings.V1ALPHA1)) {
- KameletV1Alpha1 kameletV1Alpha1;
- if (kamelet instanceof KameletV1Alpha1) {
- kameletV1Alpha1 = (KameletV1Alpha1) kamelet;
- } else {
- kameletV1Alpha1 = new KameletV1Alpha1.Builder().from(kamelet).build();
- }
+ KameletV1Alpha1 kameletV1Alpha1 = KameletV1Alpha1.from(kamelet);
getKubernetesClient().resources(KameletV1Alpha1.class, KameletV1Alpha1List.class)
.inNamespace(kameletNamespace(context))
@@ -178,10 +199,10 @@ public static final class Builder extends AbstractKameletAction.Builder dependencies = new ArrayList<>();
- private KameletSpec.Definition definition = new KameletSpec.Definition();
- private final Map dataTypes = new HashMap<>();
+ private Definition definition = new Definition();
+ private final Map dataTypes = new HashMap<>();
private Resource resource;
@@ -204,12 +225,18 @@ public Builder title(String title) {
}
public Builder source(String name, String language, String content) {
- this.source = new KameletSpec.Source(name + "." + language, content);
+ this.source = new SourcesBuilder()
+ .withName(name + "." + language)
+ .withContent(content)
+ .build();
return this;
}
public Builder source(String name, String content) {
- this.source = new KameletSpec.Source(name, content);
+ this.source = new SourcesBuilder()
+ .withName(name)
+ .withContent(content)
+ .build();
return this;
}
@@ -239,12 +266,12 @@ public Builder dependency(String dependency) {
return this;
}
- public Builder definition(KameletSpec.Definition definition) {
+ public Builder definition(Definition definition) {
this.definition = definition;
return this;
}
- public Builder addProperty(String name, KameletSpec.Definition.PropertyConfig propertyConfig) {
+ public Builder addProperty(String name, Properties propertyConfig) {
this.definition.getProperties().put(name, propertyConfig);
return this;
}
@@ -263,30 +290,36 @@ public Builder errorType(String scheme, String format) {
public Builder addDataType(String slot, String scheme, String format) {
if (dataTypes.containsKey(slot)) {
- this.dataTypes.get(slot).getTypes().put(format, new KameletSpec.DataTypeSpec(scheme, format));
+ this.dataTypes.get(slot).getTypes().put(format, new TypesBuilder().withScheme(scheme).withFormat(format).build());
} else {
- this.dataTypes.put(slot, new KameletSpec.DataTypesSpec(format, new KameletSpec.DataTypeSpec(scheme, format)));
+ Map dataTypes = new HashMap<>();
+ dataTypes.put(format, new TypesBuilder().withScheme(scheme).withFormat(format).build());
+ this.dataTypes.put(slot, new DataTypesBuilder().withTypes(dataTypes).build());
}
return this;
}
- public Builder fromBuilder(Kamelet.Builder builder) {
+ public Builder fromBuilder(KameletBuilder builder) {
Kamelet kamelet = builder.build();
name = kamelet.getMetadata().getName();
definition = kamelet.getSpec().getDefinition();
- dependencies.addAll(kamelet.getSpec().getDependencies());
- dataTypes.putAll(kamelet.getSpec().getDataTypes());
+
+ if (kamelet.getSpec().getDependencies() != null) {
+ dependencies.addAll(kamelet.getSpec().getDependencies());
+ }
+
+ if (kamelet.getSpec().getDataTypes() != null) {
+ dataTypes.putAll(kamelet.getSpec().getDataTypes());
+ }
if (kamelet.getSpec().getSources() != null && !kamelet.getSpec().getSources().isEmpty()) {
source = kamelet.getSpec().getSources().get(0);
}
if (kamelet.getSpec().getTemplate() != null) {
- template = KubernetesSupport.yaml().dumpAsMap(kamelet.getSpec().getTemplate());
- } else if (kamelet.getSpec().getFlow() != null) {
- template = KubernetesSupport.yaml().dumpAsMap(kamelet.getSpec().getFlow());
+ template = KubernetesSupport.yaml(new KameletValuePropertyMapper()).dumpAsMap(kamelet.getSpec().getTemplate());
}
return this;
diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/kamelet/CreateKameletBindingAction.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/kamelet/CreateKameletBindingAction.java
new file mode 100644
index 00000000..450c7e9b
--- /dev/null
+++ b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/kamelet/CreateKameletBindingAction.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright the original author or authors.
+ *
+ * Licensed 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.
+ */
+
+package org.citrusframework.yaks.camelk.actions.kamelet;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.util.Map;
+
+import io.fabric8.kubernetes.client.KubernetesClient;
+import io.fabric8.kubernetes.client.dsl.Updatable;
+import org.apache.camel.v1alpha1.KameletBinding;
+import org.apache.camel.v1alpha1.KameletBindingBuilder;
+import org.apache.camel.v1alpha1.KameletBindingSpecBuilder;
+import org.apache.camel.v1alpha1.kameletbindingspec.Integration;
+import org.apache.camel.v1alpha1.kameletbindingspec.Sink;
+import org.apache.camel.v1alpha1.kameletbindingspec.SinkBuilder;
+import org.apache.camel.v1alpha1.kameletbindingspec.Source;
+import org.apache.camel.v1alpha1.kameletbindingspec.SourceBuilder;
+import org.apache.camel.v1alpha1.kameletbindingspec.source.Ref;
+import org.citrusframework.context.TestContext;
+import org.citrusframework.exceptions.CitrusRuntimeException;
+import org.citrusframework.spi.Resource;
+import org.citrusframework.util.FileUtils;
+import org.citrusframework.util.IsJsonPredicate;
+import org.citrusframework.yaks.YaksSettings;
+import org.citrusframework.yaks.camelk.CamelKSettings;
+import org.citrusframework.yaks.camelk.jbang.CamelJBangSettings;
+import org.citrusframework.yaks.camelk.jbang.ProcessAndOutput;
+import org.citrusframework.yaks.camelk.model.v1alpha1.KameletBindingList;
+import org.citrusframework.yaks.kubernetes.KubernetesSupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.citrusframework.yaks.camelk.jbang.CamelJBang.camel;
+
+/**
+ * Test action creates new Camel K binding with given name and source code. Uses given Kubernetes client to
+ * create a custom resource of type binding.
+ *
+ * @author Christoph Deppisch
+ */
+public class CreateKameletBindingAction extends AbstractKameletAction {
+
+ /** Logger */
+ private static final Logger LOG = LoggerFactory.getLogger(CreateKameletBindingAction.class);
+
+ private final String bindingName;
+ private final Integration integration;
+ private final Source source;
+ private final Sink sink;
+ private final Resource resource;
+
+ /**
+ * Constructor using given builder.
+ * @param builder
+ */
+ public CreateKameletBindingAction(Builder builder) {
+ super("create-binding", builder);
+ this.bindingName = builder.bindingName;
+ this.integration = builder.integration;
+ this.source = builder.source;
+ this.sink = builder.sink;
+ this.resource = builder.resource;
+ }
+
+ @Override
+ public void doExecute(TestContext context) {
+ final KameletBinding binding;
+
+ String bindingName = context.replaceDynamicContentInString(this.bindingName);
+ LOG.info(String.format("Creating Camel K binding '%s'", bindingName));
+
+ if (resource != null) {
+ try {
+ String yamlOrJson = context.replaceDynamicContentInString(FileUtils.readToString(resource));
+ if (IsJsonPredicate.getInstance().test(yamlOrJson)) {
+ binding = KubernetesSupport.json().readValue(yamlOrJson, KameletBinding.class);
+ } else {
+ // need to make a detour over Json to support additional properties set on Pipe
+ Map raw = KubernetesSupport.yaml().load(yamlOrJson);
+ binding = KubernetesSupport.json().convertValue(raw, KameletBinding.class);
+ }
+ } catch (IOException e) {
+ throw new CitrusRuntimeException(String.format("Failed to load binding from resource %s", bindingName + ".yaml"), e);
+ }
+ } else {
+ final KameletBindingBuilder builder = new KameletBindingBuilder()
+ .withNewMetadata()
+ .withName(bindingName)
+ .endMetadata();
+
+ KameletBindingSpecBuilder specBuilder = new KameletBindingSpecBuilder();
+ if (integration != null) {
+ specBuilder.withIntegration(integration);
+ }
+
+ if (source != null) {
+ if (source.getProperties() != null && source.getProperties().getAdditionalProperties() != null) {
+ context.resolveDynamicValuesInMap(source.getProperties().getAdditionalProperties());
+ }
+ specBuilder.withSource(source);
+ }
+
+ if (sink != null) {
+ if (sink.getUri() != null) {
+ sink.setUri(context.replaceDynamicContentInString(sink.getUri()));
+ }
+
+ if (sink.getProperties() != null && sink.getProperties().getAdditionalProperties() != null) {
+ context.resolveDynamicValuesInMap(sink.getProperties().getAdditionalProperties());
+ }
+ specBuilder.withSink(sink);
+ }
+
+ binding = builder.withSpec(specBuilder.build()).build();
+ }
+
+ if (YaksSettings.isLocal(clusterType(context))) {
+ createLocal(KubernetesSupport.yaml(new KameletBindingValuePropertyMapper()).dumpAsMap(binding), bindingName, context);
+ } else {
+ createKameletBinding(getKubernetesClient(), namespace(context), binding, context);
+ }
+
+ LOG.info(String.format("Successfully created binding '%s'", binding.getMetadata().getName()));
+ }
+
+ /**
+ * Creates the Kamelet binding as a custom resource in given namespace.
+ * @param k8sClient
+ * @param namespace
+ * @param binding
+ * @param context
+ */
+ private void createKameletBinding(KubernetesClient k8sClient, String namespace, KameletBinding binding, TestContext context) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(KubernetesSupport.yaml(new KameletBindingValuePropertyMapper()).dumpAsMap(binding));
+ }
+
+ k8sClient.resources(KameletBinding.class, KameletBindingList.class)
+ .inNamespace(namespace)
+ .resource(binding)
+ .createOr(Updatable::update);
+ }
+
+ /**
+ * Creates the binding with local JBang runtime.
+ * @param yaml
+ * @param name
+ * @param context
+ */
+ private void createLocal(String yaml, String name, TestContext context) {
+ try {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(yaml);
+ }
+
+ Path workDir = CamelJBangSettings.getWorkDir();
+ Files.createDirectories(workDir);
+ Path file = workDir.resolve(String.format("i-%s.yaml", name));
+ Files.writeString(file, yaml,
+ StandardOpenOption.WRITE,
+ StandardOpenOption.CREATE,
+ StandardOpenOption.TRUNCATE_EXISTING);
+ ProcessAndOutput pao = camel().run(name, file);
+
+ if (!pao.getProcess().isAlive()) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(pao.getOutput());
+ }
+
+ throw new CitrusRuntimeException(String.format("Failed to create binding - exit code %s", pao.getProcess().exitValue()));
+ }
+
+ Long pid = pao.getCamelProcessId();
+ context.setVariable(name + ":pid", pid);
+ context.setVariable(name + ":process:" + pid, pao);
+ } catch (IOException e) {
+ throw new CitrusRuntimeException("Failed to create binding file", e);
+ }
+ }
+
+ /**
+ * Action builder.
+ */
+ public static final class Builder extends AbstractKameletAction.Builder {
+
+ private String bindingName;
+ private Integration integration;
+ private Source source;
+ private Sink sink;
+ private Resource resource;
+
+ public Builder binding(String bindingName) {
+ apiVersion(CamelKSettings.V1ALPHA1);
+ this.bindingName = bindingName;
+ return this;
+ }
+
+ public Builder integration(Integration integration) {
+ this.integration = integration;
+ return this;
+ }
+
+ public Builder source(Source source) {
+ this.source = source;
+ return this;
+ }
+
+ public Builder source(String uri) {
+ return source(new SourceBuilder().withUri(uri).build());
+ }
+
+ public Builder source(Ref ref, String properties) {
+ Map props = null;
+ if (properties != null && !properties.isEmpty()) {
+ props = KubernetesSupport.yaml().load(properties);
+ }
+
+ return source(new SourceBuilder().withRef(ref)
+ .withNewProperties()
+ .addToAdditionalProperties(props)
+ .endProperties().build());
+ }
+
+ public Builder sink(Sink sink) {
+ this.sink = sink;
+ return this;
+ }
+
+ public Builder sink(String uri) {
+ return sink(new SinkBuilder().withUri(uri).build());
+ }
+
+ public Builder sink(org.apache.camel.v1alpha1.kameletbindingspec.sink.Ref ref, String properties) {
+ Map props = null;
+ if (properties != null && !properties.isEmpty()) {
+ props = KubernetesSupport.yaml().load(properties);
+ }
+
+ return sink(new SinkBuilder().withRef(ref)
+ .withNewProperties()
+ .addToAdditionalProperties(props)
+ .endProperties()
+ .build());
+ }
+
+ public Builder fromBuilder(KameletBindingBuilder builder) {
+ KameletBinding binding = builder.build();
+
+ bindingName = binding.getMetadata().getName();
+ integration = binding.getSpec().getIntegration();
+ source = binding.getSpec().getSource();
+ sink = binding.getSpec().getSink();
+
+ return this;
+ }
+
+ public Builder resource(Resource resource) {
+ this.resource = resource;
+ return this;
+ }
+
+ @Override
+ public CreateKameletBindingAction build() {
+ return new CreateKameletBindingAction(this);
+ }
+ }
+
+}
diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/kamelet/CreatePipeAction.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/kamelet/CreatePipeAction.java
index 67351ebb..a868845b 100644
--- a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/kamelet/CreatePipeAction.java
+++ b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/kamelet/CreatePipeAction.java
@@ -17,7 +17,6 @@
package org.citrusframework.yaks.camelk.actions.kamelet;
import java.io.IOException;
-import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
@@ -25,20 +24,24 @@
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.dsl.Updatable;
+import org.apache.camel.v1.Pipe;
+import org.apache.camel.v1.PipeBuilder;
+import org.apache.camel.v1.PipeSpecBuilder;
+import org.apache.camel.v1.pipespec.Integration;
+import org.apache.camel.v1.pipespec.Sink;
+import org.apache.camel.v1.pipespec.SinkBuilder;
+import org.apache.camel.v1.pipespec.Source;
+import org.apache.camel.v1.pipespec.SourceBuilder;
+import org.apache.camel.v1.pipespec.source.Ref;
import org.citrusframework.context.TestContext;
import org.citrusframework.exceptions.CitrusRuntimeException;
import org.citrusframework.spi.Resource;
import org.citrusframework.util.FileUtils;
+import org.citrusframework.util.IsJsonPredicate;
import org.citrusframework.yaks.YaksSettings;
-import org.citrusframework.yaks.camelk.CamelKSettings;
import org.citrusframework.yaks.camelk.jbang.CamelJBangSettings;
import org.citrusframework.yaks.camelk.jbang.ProcessAndOutput;
-import org.citrusframework.yaks.camelk.model.IntegrationSpec;
-import org.citrusframework.yaks.camelk.model.Pipe;
import org.citrusframework.yaks.camelk.model.PipeList;
-import org.citrusframework.yaks.camelk.model.PipeSpec;
-import org.citrusframework.yaks.camelk.model.v1alpha1.KameletBinding;
-import org.citrusframework.yaks.camelk.model.v1alpha1.KameletBindingList;
import org.citrusframework.yaks.kubernetes.KubernetesSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -57,9 +60,9 @@ public class CreatePipeAction extends AbstractKameletAction {
private static final Logger LOG = LoggerFactory.getLogger(CreatePipeAction.class);
private final String pipeName;
- private final IntegrationSpec integration;
- private final PipeSpec.Endpoint source;
- private final PipeSpec.Endpoint sink;
+ private final Integration integration;
+ private final Source source;
+ private final Sink sink;
private final Resource resource;
/**
@@ -84,27 +87,33 @@ public void doExecute(TestContext context) {
if (resource != null) {
try {
- if (getApiVersion(context).equals(CamelKSettings.V1ALPHA1)) {
- pipe = KubernetesSupport.yaml().loadAs(
- context.replaceDynamicContentInString(FileUtils.readToString(resource)), KameletBinding.class);
+ String yamlOrJson = context.replaceDynamicContentInString(FileUtils.readToString(resource));
+ if (IsJsonPredicate.getInstance().test(yamlOrJson)) {
+ pipe = KubernetesSupport.json().readValue(yamlOrJson, Pipe.class);
} else {
- pipe = KubernetesSupport.yaml().loadAs(
- context.replaceDynamicContentInString(FileUtils.readToString(resource)), Pipe.class);
+ // need to make a detour over Json to support additional properties set on Pipe
+ Map raw = KubernetesSupport.yaml().load(yamlOrJson);
+ pipe = KubernetesSupport.json().convertValue(raw, Pipe.class);
}
} catch (IOException e) {
throw new CitrusRuntimeException(String.format("Failed to load pipe from resource %s", pipeName + ".yaml"), e);
}
} else {
- final Pipe.Builder builder = new Pipe.Builder()
- .name(pipeName);
+ final PipeBuilder builder = new PipeBuilder()
+ .withNewMetadata()
+ .withName(pipeName)
+ .endMetadata();
+ PipeSpecBuilder specBuilder = new PipeSpecBuilder();
if (integration != null) {
- builder.integration(integration);
+ specBuilder.withIntegration(integration);
}
if (source != null) {
- source.setProperties(context.resolveDynamicValuesInMap(source.getProperties()));
- builder.source(source);
+ if (source.getProperties() != null && source.getProperties().getAdditionalProperties() != null) {
+ context.resolveDynamicValuesInMap(source.getProperties().getAdditionalProperties());
+ }
+ specBuilder.withSource(source);
}
if (sink != null) {
@@ -112,15 +121,17 @@ public void doExecute(TestContext context) {
sink.setUri(context.replaceDynamicContentInString(sink.getUri()));
}
- sink.setProperties(context.resolveDynamicValuesInMap(sink.getProperties()));
- builder.sink(sink);
+ if (sink.getProperties() != null && sink.getProperties().getAdditionalProperties() != null) {
+ context.resolveDynamicValuesInMap(sink.getProperties().getAdditionalProperties());
+ }
+ specBuilder.withSink(sink);
}
- pipe = builder.build();
+ pipe = builder.withSpec(specBuilder.build()).build();
}
if (YaksSettings.isLocal(clusterType(context))) {
- createLocalPipe(pipe, pipeName, context);
+ createLocal(KubernetesSupport.yaml(new PipeValuePropertyMapper()).dumpAsMap(pipe), pipeName, context);
} else {
createPipe(getKubernetesClient(), namespace(context), pipe, context);
}
@@ -137,60 +148,31 @@ public void doExecute(TestContext context) {
*/
private void createPipe(KubernetesClient k8sClient, String namespace, Pipe pipe, TestContext context) {
if (LOG.isDebugEnabled()) {
- LOG.debug(KubernetesSupport.yaml().dumpAsMap(pipe));
+ LOG.debug(KubernetesSupport.yaml(new PipeValuePropertyMapper()).dumpAsMap(pipe));
}
- if (getApiVersion(context).equals(CamelKSettings.V1ALPHA1)) {
- KameletBinding kb;
- if (pipe instanceof KameletBinding) {
- kb = (KameletBinding) pipe;
- } else {
- kb = new KameletBinding.Builder().from(pipe).build();
- }
-
- k8sClient.resources(KameletBinding.class, KameletBindingList.class)
- .inNamespace(namespace)
- .resource(kb)
- .createOr(Updatable::update);
- } else {
- k8sClient.resources(Pipe.class, PipeList.class)
- .inNamespace(namespace)
- .resource(pipe)
- .createOr(Updatable::update);
- }
+ k8sClient.resources(Pipe.class, PipeList.class)
+ .inNamespace(namespace)
+ .resource(pipe)
+ .createOr(Updatable::update);
}
/**
* Creates the pipe with local JBang runtime.
- * @param pipe
+ * @param yaml
* @param name
* @param context
*/
- private void createLocalPipe(Pipe pipe, String name, TestContext context) {
+ private void createLocal(String yaml, String name, TestContext context) {
try {
- String pipeYaml;
-
- if (getApiVersion(context).equals(CamelKSettings.V1ALPHA1)) {
- KameletBinding kb;
- if (pipe instanceof KameletBinding) {
- kb = (KameletBinding) pipe;
- } else {
- kb = new KameletBinding.Builder().from(pipe).build();
- }
-
- pipeYaml = KubernetesSupport.yaml().dumpAsMap(kb);
- } else {
- pipeYaml = KubernetesSupport.yaml().dumpAsMap(pipe);
- }
-
if (LOG.isDebugEnabled()) {
- LOG.debug(pipeYaml);
+ LOG.debug(yaml);
}
Path workDir = CamelJBangSettings.getWorkDir();
Files.createDirectories(workDir);
Path file = workDir.resolve(String.format("i-%s.yaml", name));
- Files.write(file, pipeYaml.getBytes(StandardCharsets.UTF_8),
+ Files.writeString(file, yaml,
StandardOpenOption.WRITE,
StandardOpenOption.CREATE,
StandardOpenOption.TRUNCATE_EXISTING);
@@ -218,64 +200,65 @@ private void createLocalPipe(Pipe pipe, String name, TestContext context) {
public static final class Builder extends AbstractKameletAction.Builder {
private String pipeName;
- private IntegrationSpec integration;
- private PipeSpec.Endpoint source;
- private PipeSpec.Endpoint sink;
+ private Integration integration;
+ private Source source;
+ private Sink sink;
private Resource resource;
- public Builder binding(String pipeName) {
- apiVersion(CamelKSettings.V1ALPHA1);
- this.pipeName = pipeName;
- return this;
- }
-
public Builder pipe(String pipeName) {
this.pipeName = pipeName;
return this;
}
- public Builder integration(IntegrationSpec integration) {
+ public Builder integration(Integration integration) {
this.integration = integration;
return this;
}
- public Builder source(PipeSpec.Endpoint source) {
+ public Builder source(Source source) {
this.source = source;
return this;
}
public Builder source(String uri) {
- return source(new PipeSpec.Endpoint(uri));
+ return source(new SourceBuilder().withUri(uri).build());
}
- public Builder source(PipeSpec.Endpoint.ObjectReference ref, String properties) {
+ public Builder source(Ref ref, String properties) {
Map props = null;
if (properties != null && !properties.isEmpty()) {
props = KubernetesSupport.yaml().load(properties);
}
- return source(new PipeSpec.Endpoint(ref, props));
+ return source(new SourceBuilder().withRef(ref)
+ .withNewProperties()
+ .addToAdditionalProperties(props)
+ .endProperties().build());
}
- public Builder sink(PipeSpec.Endpoint sink) {
+ public Builder sink(Sink sink) {
this.sink = sink;
return this;
}
public Builder sink(String uri) {
- return sink(new PipeSpec.Endpoint(uri));
+ return sink(new SinkBuilder().withUri(uri).build());
}
- public Builder sink(PipeSpec.Endpoint.ObjectReference ref, String properties) {
+ public Builder sink(org.apache.camel.v1.pipespec.sink.Ref ref, String properties) {
Map props = null;
if (properties != null && !properties.isEmpty()) {
props = KubernetesSupport.yaml().load(properties);
}
- return sink(new PipeSpec.Endpoint(ref, props));
+ return sink(new SinkBuilder().withRef(ref)
+ .withNewProperties()
+ .addToAdditionalProperties(props)
+ .endProperties()
+ .build());
}
- public Builder fromBuilder(Pipe.Builder builder) {
+ public Builder fromBuilder(PipeBuilder builder) {
Pipe pipe = builder.build();
pipeName = pipe.getMetadata().getName();
@@ -296,4 +279,5 @@ public CreatePipeAction build() {
return new CreatePipeAction(this);
}
}
+
}
diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/kamelet/DeleteKameletAction.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/kamelet/DeleteKameletAction.java
index 544eba7b..eb6451ac 100644
--- a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/kamelet/DeleteKameletAction.java
+++ b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/kamelet/DeleteKameletAction.java
@@ -16,9 +16,9 @@
package org.citrusframework.yaks.camelk.actions.kamelet;
+import org.apache.camel.v1.Kamelet;
import org.citrusframework.context.TestContext;
import org.citrusframework.yaks.camelk.CamelKSettings;
-import org.citrusframework.yaks.camelk.model.Kamelet;
import org.citrusframework.yaks.camelk.model.KameletList;
import org.citrusframework.yaks.camelk.model.v1alpha1.KameletV1Alpha1;
import org.citrusframework.yaks.camelk.model.v1alpha1.KameletV1Alpha1List;
diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/kamelet/DeleteKameletBindingAction.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/kamelet/DeleteKameletBindingAction.java
new file mode 100644
index 00000000..bae2df62
--- /dev/null
+++ b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/kamelet/DeleteKameletBindingAction.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright the original author or authors.
+ *
+ * Licensed 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.
+ */
+
+package org.citrusframework.yaks.camelk.actions.kamelet;
+
+import io.fabric8.kubernetes.client.KubernetesClient;
+import org.apache.camel.v1alpha1.KameletBinding;
+import org.citrusframework.context.TestContext;
+import org.citrusframework.exceptions.CitrusRuntimeException;
+import org.citrusframework.yaks.YaksSettings;
+import org.citrusframework.yaks.camelk.CamelKSettings;
+import org.citrusframework.yaks.camelk.model.v1alpha1.KameletBindingList;
+
+import static org.citrusframework.yaks.camelk.jbang.CamelJBang.camel;
+
+/**
+ * @author Christoph Deppisch
+ */
+public class DeleteKameletBindingAction extends AbstractKameletAction {
+
+ private final String bindingName;
+
+ public DeleteKameletBindingAction(Builder builder) {
+ super("delete-binding", builder);
+
+ this.bindingName = builder.bindingName;
+ }
+
+ @Override
+ public void doExecute(TestContext context) {
+ String binding = context.replaceDynamicContentInString(bindingName);
+
+ LOG.info(String.format("Deleting binding '%s'", binding));
+
+ if (YaksSettings.isLocal(clusterType(context))) {
+ deleteLocalBinding(binding, context);
+ } else {
+ deleteBinding(getKubernetesClient(), namespace(context), binding, context);
+ }
+
+ LOG.info(String.format("Successfully deleted binding '%s'", binding));
+ }
+
+ private void deleteBinding(KubernetesClient k8sClient, String namespace, String name, TestContext context) {
+ k8sClient.resources(KameletBinding.class, KameletBindingList.class)
+ .inNamespace(namespace)
+ .withName(name)
+ .delete();
+ }
+
+ /**
+ * Deletes the Camel K integration from local JBang runtime.
+ * @param name
+ * @param context
+ */
+ private static void deleteLocalBinding(String name, TestContext context) {
+ Long pid;
+ if (context.getVariables().containsKey(name + ":pid")) {
+ pid = context.getVariable(name + ":pid", Long.class);
+ } else {
+ pid = camel().getAll().stream()
+ .filter(props -> name.equals(props.get("NAME")) && !props.getOrDefault("PID", "").isBlank())
+ .map(props -> Long.valueOf(props.get("PID"))).findFirst()
+ .orElseThrow(() -> new CitrusRuntimeException(String.format("Unable to retrieve binding process id %s:pid", name)));
+ }
+
+ camel().stop(pid);
+ }
+
+ /**
+ * Action builder.
+ */
+ public static class Builder extends AbstractKameletAction.Builder {
+
+ private String bindingName;
+
+ public Builder binding(String name) {
+ apiVersion(CamelKSettings.V1ALPHA1);
+ this.bindingName = name;
+ return this;
+ }
+
+ @Override
+ public DeleteKameletBindingAction build() {
+ return new DeleteKameletBindingAction(this);
+ }
+ }
+}
diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/kamelet/DeletePipeAction.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/kamelet/DeletePipeAction.java
index 0f38fe97..0a247a21 100644
--- a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/kamelet/DeletePipeAction.java
+++ b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/kamelet/DeletePipeAction.java
@@ -16,14 +16,11 @@
package org.citrusframework.yaks.camelk.actions.kamelet;
+import io.fabric8.kubernetes.client.KubernetesClient;
+import org.apache.camel.v1.Pipe;
import org.citrusframework.context.TestContext;
import org.citrusframework.exceptions.CitrusRuntimeException;
-import io.fabric8.kubernetes.client.KubernetesClient;
import org.citrusframework.yaks.YaksSettings;
-import org.citrusframework.yaks.camelk.CamelKSettings;
-import org.citrusframework.yaks.camelk.model.v1alpha1.KameletBinding;
-import org.citrusframework.yaks.camelk.model.v1alpha1.KameletBindingList;
-import org.citrusframework.yaks.camelk.model.Pipe;
import org.citrusframework.yaks.camelk.model.PipeList;
import static org.citrusframework.yaks.camelk.jbang.CamelJBang.camel;
@@ -48,26 +45,19 @@ public void doExecute(TestContext context) {
LOG.info(String.format("Deleting pipe '%s'", pipe));
if (YaksSettings.isLocal(clusterType(context))) {
- deleteLocalBinding(pipe, context);
+ deleteLocalPipe(pipe, context);
} else {
- deleteBinding(getKubernetesClient(), namespace(context), pipe, context);
+ deletePipe(getKubernetesClient(), namespace(context), pipe, context);
}
LOG.info(String.format("Successfully deleted pipe '%s'", pipe));
}
- private void deleteBinding(KubernetesClient k8sClient, String namespace, String name, TestContext context) {
- if (getApiVersion(context).equals(CamelKSettings.V1ALPHA1)) {
- k8sClient.resources(KameletBinding.class, KameletBindingList.class)
- .inNamespace(namespace)
- .withName(name)
- .delete();
- } else {
- k8sClient.resources(Pipe.class, PipeList.class)
+ private void deletePipe(KubernetesClient k8sClient, String namespace, String name, TestContext context) {
+ k8sClient.resources(Pipe.class, PipeList.class)
.inNamespace(namespace)
.withName(name)
.delete();
- }
}
/**
@@ -75,7 +65,7 @@ private void deleteBinding(KubernetesClient k8sClient, String namespace, String
* @param name
* @param context
*/
- private static void deleteLocalBinding(String name, TestContext context) {
+ private static void deleteLocalPipe(String name, TestContext context) {
Long pid;
if (context.getVariables().containsKey(name + ":pid")) {
pid = context.getVariable(name + ":pid", Long.class);
@@ -96,12 +86,6 @@ public static class Builder extends AbstractKameletAction.Builder {
LOG.info(String.format("Verify Kamlet '%s' exists in namespace '%s'", name, namespace));
- Kamelet kamelet;
+ HasMetadata kamelet;
if (getApiVersion(context).equals(CamelKSettings.V1ALPHA1)) {
kamelet = getKubernetesClient().resources(KameletV1Alpha1.class, KameletV1Alpha1List.class)
.inNamespace(namespace)
@@ -91,7 +92,7 @@ private boolean findKamelet(String name, TestContext context, String ... namespa
LOG.debug(String.format("Kamelet '%s' is not present in namespace '%s'", name, namespace));
} else {
LOG.debug(String.format("Found Kamelet in namespace '%s'", namespace));
- LOG.debug(KubernetesSupport.yaml().dumpAsMap(kamelet));
+ LOG.debug(KubernetesSupport.yaml(new KameletValuePropertyMapper()).dumpAsMap(kamelet));
}
}
diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/kamelet/VerifyKameletBindingAction.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/kamelet/VerifyKameletBindingAction.java
new file mode 100644
index 00000000..da412cf9
--- /dev/null
+++ b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/kamelet/VerifyKameletBindingAction.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright the original author or authors.
+ *
+ * Licensed 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.
+ */
+
+package org.citrusframework.yaks.camelk.actions.kamelet;
+
+import java.util.Map;
+
+import org.apache.camel.v1alpha1.KameletBinding;
+import org.citrusframework.context.TestContext;
+import org.citrusframework.exceptions.ValidationException;
+import org.citrusframework.yaks.YaksSettings;
+import org.citrusframework.yaks.camelk.CamelKSettings;
+import org.citrusframework.yaks.camelk.model.v1alpha1.KameletBindingList;
+import org.citrusframework.yaks.kubernetes.KubernetesSupport;
+
+import static org.citrusframework.yaks.camelk.jbang.CamelJBang.camel;
+
+/**
+ * Test action verifies Camel K binding is present in given namespace.
+ *
+ * @author Christoph Deppisch
+ */
+public class VerifyKameletBindingAction extends AbstractKameletAction {
+
+ private final String bindingName;
+
+ private final int maxAttempts;
+ private final long delayBetweenAttempts;
+
+ /**
+ * Constructor using given builder.
+ * @param builder
+ */
+ public VerifyKameletBindingAction(Builder builder) {
+ super("verify-binding", builder);
+ this.bindingName = builder.bindingName;
+ this.maxAttempts = builder.maxAttempts;
+ this.delayBetweenAttempts = builder.delayBetweenAttempts;
+ }
+
+ @Override
+ public void doExecute(TestContext context) {
+ String name = context.replaceDynamicContentInString(this.bindingName);
+
+ LOG.info(String.format("Verify binding '%s'", name));
+
+ if (YaksSettings.isLocal(clusterType(context))) {
+ verifyLocalKameletBinding(name, context);
+ } else {
+ verifyKameletBinding(namespace(context), name, context);
+ }
+
+ LOG.info(String.format("Successfully verified binding '%s' - All values OK!", name));
+ }
+
+ private void verifyLocalKameletBinding(String name, TestContext context) {
+ Long pid = context.getVariable(name + ":pid", Long.class);
+
+ for (int i = 0; i < maxAttempts; i++) {
+ Map properties = camel().get(pid);
+ if ((!properties.isEmpty() && properties.get("STATUS").equals("Running"))) {
+ LOG.info(String.format("Verified binding '%s' state 'Running' - All values OK!", name));
+ return;
+ }
+
+ LOG.info(String.format("Waiting for binding '%s' to be in state 'Running'- retry in %s ms", name, delayBetweenAttempts));
+ try {
+ Thread.sleep(delayBetweenAttempts);
+ } catch (InterruptedException e) {
+ LOG.warn("Interrupted while waiting for binding", e);
+ }
+ }
+
+ throw new ValidationException(String.format("Failed to retrieve binding '%s' in state 'Running'", name));
+ }
+
+ private void verifyKameletBinding(String namespace, String name, TestContext context) {
+ KameletBinding binding = null;
+ for (int i = 0; i < maxAttempts; i++) {
+ binding = getKubernetesClient().resources(KameletBinding.class, KameletBindingList.class)
+ .inNamespace(namespace)
+ .withName(name)
+ .get();
+
+ if (binding == null) {
+ LOG.info(String.format("Waiting for binding '%s' - retry in %s ms", name, delayBetweenAttempts));
+ try {
+ Thread.sleep(delayBetweenAttempts);
+ } catch (InterruptedException e) {
+ LOG.warn("Interrupted while waiting for binding", e);
+ }
+ } else {
+ break;
+ }
+ }
+
+ if (binding == null) {
+ throw new ValidationException(String.format("Failed to retrieve binding '%s' in namespace '%s'", name, namespace));
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(KubernetesSupport.yaml(new KameletBindingValuePropertyMapper()).dumpAsMap(binding));
+ }
+ }
+
+ /**
+ * Action builder.
+ */
+ public static final class Builder extends AbstractKameletAction.Builder {
+
+ private String bindingName;
+
+ private int maxAttempts = CamelKSettings.getMaxAttempts();
+ private long delayBetweenAttempts = CamelKSettings.getDelayBetweenAttempts();
+
+ public Builder isAvailable() {
+ return this;
+ }
+
+ public Builder isAvailable(String name) {
+ this.bindingName = name;
+ return this;
+ }
+
+ public Builder maxAttempts(int maxAttempts) {
+ this.maxAttempts = maxAttempts;
+ return this;
+ }
+
+ public Builder delayBetweenAttempts(long delayBetweenAttempts) {
+ this.delayBetweenAttempts = delayBetweenAttempts;
+ return this;
+ }
+
+ @Override
+ public VerifyKameletBindingAction build() {
+ return new VerifyKameletBindingAction(this);
+ }
+ }
+}
diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/kamelet/VerifyPipeAction.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/kamelet/VerifyPipeAction.java
index 7df3db96..013c1ca3 100644
--- a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/kamelet/VerifyPipeAction.java
+++ b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/actions/kamelet/VerifyPipeAction.java
@@ -18,20 +18,18 @@
import java.util.Map;
+import org.apache.camel.v1.Pipe;
import org.citrusframework.context.TestContext;
import org.citrusframework.exceptions.ValidationException;
import org.citrusframework.yaks.YaksSettings;
import org.citrusframework.yaks.camelk.CamelKSettings;
-import org.citrusframework.yaks.camelk.model.v1alpha1.KameletBinding;
-import org.citrusframework.yaks.camelk.model.v1alpha1.KameletBindingList;
-import org.citrusframework.yaks.camelk.model.Pipe;
import org.citrusframework.yaks.camelk.model.PipeList;
import org.citrusframework.yaks.kubernetes.KubernetesSupport;
import static org.citrusframework.yaks.camelk.jbang.CamelJBang.camel;
/**
- * Test action verifies Camel K binding is present in given namespace.
+ * Test action verifies Camel K pipe is present in given namespace.
*
* @author Christoph Deppisch
*/
@@ -92,17 +90,10 @@ private void verifyLocalPipe(String name, TestContext context) {
private void verifyPipe(String namespace, String name, TestContext context) {
Pipe pipe = null;
for (int i = 0; i < maxAttempts; i++) {
- if (getApiVersion(context).equals(CamelKSettings.V1ALPHA1)) {
- pipe = getKubernetesClient().resources(KameletBinding.class, KameletBindingList.class)
- .inNamespace(namespace)
- .withName(name)
- .get();
- } else {
- pipe = getKubernetesClient().resources(Pipe.class, PipeList.class)
- .inNamespace(namespace)
- .withName(name)
- .get();
- }
+ pipe = getKubernetesClient().resources(Pipe.class, PipeList.class)
+ .inNamespace(namespace)
+ .withName(name)
+ .get();
if (pipe == null) {
LOG.info(String.format("Waiting for pipe '%s' - retry in %s ms", name, delayBetweenAttempts));
@@ -121,7 +112,7 @@ private void verifyPipe(String namespace, String name, TestContext context) {
}
if (LOG.isDebugEnabled()) {
- LOG.debug(KubernetesSupport.yaml().dumpAsMap(pipe));
+ LOG.debug(KubernetesSupport.yaml(new PipeValuePropertyMapper()).dumpAsMap(pipe));
}
}
@@ -135,7 +126,6 @@ public static final class Builder extends AbstractKameletAction.Builder implements Namespaced {
-
- public Integration() {
- super();
- this.spec = new IntegrationSpec();
- this.status = null;
- }
-
- @Override
- public String getApiVersion() {
- return CamelKSupport.CAMELK_CRD_GROUP + "/" + CamelKSettings.getApiVersion();
- }
-
- /**
- * Fluent builder
- */
- public static class Builder {
- private final Map traits = new LinkedHashMap<>();
- private final List resources = new ArrayList<>();
- private final List dependencies = new ArrayList<>();
- private final List configuration = new ArrayList<>();
- private String source;
- private String fileName;
- private String name;
-
- public Builder name(String name) {
- this.name = name;
-
- if (fileName == null) {
- this.fileName = name;
- }
-
- return this;
- }
-
- public Builder source(String source) {
- this.source = source;
- return this;
- }
-
- public Builder source(String fileName, String source) {
- this.source = source;
- this.fileName = fileName;
- return this;
- }
-
- public Builder openApi(String fileName, String content) {
- this.resources.add(new IntegrationSpec.Resource("openapi", null, fileName, content));
- return this;
- }
-
- public Builder dependencies(List dependencies) {
- this.dependencies.addAll(dependencies);
- return this;
- }
-
- public Builder traits(Map traits) {
- this.traits.putAll(traits);
- return this;
- }
-
- public Builder trait(String name, IntegrationSpec.TraitConfig config) {
- this.traits.put(name ,config);
- return this;
- }
-
- public Builder configuration(List configuration) {
- this.configuration.addAll(configuration);
- return this;
- }
-
- public Integration build() {
- Integration i = new Integration();
- i.getMetadata().setName(sanitizeIntegrationName(name));
- i.getSpec().setSources(Collections.singletonList(new IntegrationSpec.Source(fileName, source)));
-
- if (!dependencies.isEmpty()) {
- i.getSpec().setDependencies(dependencies);
- }
-
- if (!traits.isEmpty()) {
- i.getSpec().setTraits(traits);
- }
-
- if (!configuration.isEmpty()) {
- i.getSpec().setConfiguration(configuration);
- }
-
- if (!resources.isEmpty()) {
- i.getSpec().setResources(resources);
- }
-
- return i;
- }
-
- private String sanitizeIntegrationName(String name) {
- String sanitized;
-
- if (name.contains(".")) {
- sanitized = name.substring(0, name.indexOf("."));
- } else {
- sanitized = name;
- }
-
- sanitized = sanitized.replaceAll("([a-z])([A-Z]+)", "$1-$2").toLowerCase();
- return sanitized.replaceAll("[^a-z0-9-]", "");
- }
- }
-}
diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/IntegrationList.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/IntegrationList.java
index 4b58dc2a..b4167a39 100644
--- a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/IntegrationList.java
+++ b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/IntegrationList.java
@@ -17,6 +17,7 @@
package org.citrusframework.yaks.camelk.model;
import io.fabric8.kubernetes.api.model.DefaultKubernetesResourceList;
+import org.apache.camel.v1.Integration;
/**
* @author Christoph Deppisch
diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/IntegrationSpec.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/IntegrationSpec.java
deleted file mode 100644
index c6c505c0..00000000
--- a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/IntegrationSpec.java
+++ /dev/null
@@ -1,413 +0,0 @@
-/*
- * Copyright the original author or authors.
- *
- * Licensed 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.
- */
-
-package org.citrusframework.yaks.camelk.model;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonPropertyOrder;
-import com.fasterxml.jackson.databind.JsonDeserializer;
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-import io.fabric8.kubernetes.api.model.KubernetesResource;
-
-@JsonDeserialize(using = JsonDeserializer.None.class)
-@JsonInclude(JsonInclude.Include.NON_NULL)
-@JsonPropertyOrder({"replicas", "flows", "sources", "resources", "kit", "dependencies", "profile", "traits",
- "configuration", "repositories", "serviceAccountName"})
-public class IntegrationSpec implements KubernetesResource {
-
- @JsonProperty("replicas")
- private Integer replicas;
- @JsonProperty("flows")
- @JsonInclude(JsonInclude.Include.NON_EMPTY)
- private List