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..2883c901 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,16 @@ 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.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 +40,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 +64,11 @@ 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 kameletTemplate; 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,39 @@ 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); + kameletTemplate = template; } @Given("^Kamelet property definition$") @@ -165,58 +181,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 +201,7 @@ public void loadKameletFromFile(String fileName) { runner.run(camelk() .client(k8sClient) .createKamelet(fileName) + .namespace(namespace) .apiVersion(kameletApiVersion) .supportVariables(supportVariablesInSources) .resource(resource)); @@ -236,36 +214,26 @@ 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) .createKamelet(name) .supportVariables(supportVariablesInSources) + .template(kameletTemplate) .fromBuilder(kamelet)); initializeKameletBuilder(); @@ -286,37 +254,10 @@ 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); + kameletTemplate = template; 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 +266,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 +287,11 @@ 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<>(); + kameletTemplate = null; } } 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..27dcc2ac 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(new KameletValuePropertyMapper()).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> flows; - @JsonProperty("sources") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private List sources; - @JsonProperty("resources") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private List resources; - @JsonProperty("kit") - private String kit; - @JsonProperty("dependencies") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private List dependencies; - @JsonProperty("profile") - private String profile; - @JsonProperty("traits") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private Map traits; - @JsonProperty("configuration") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private List configuration; - @JsonProperty("repositories") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private List repositories; - @JsonProperty("serviceAccountName") - private String serviceAccountName; - - public Integer getReplicas() { - return replicas; - } - - public void setReplicas(Integer replicas) { - this.replicas = replicas; - } - - public List> getFlows() { - return flows; - } - - public void setFlows(List> flows) { - this.flows = flows; - } - - public List getSources() { - return sources; - } - - public void setSources(List sources) { - this.sources = sources; - } - - public List getResources() { - return resources; - } - - public void setResources(List resources) { - this.resources = resources; - } - - public String getKit() { - return kit; - } - - public void setKit(String kit) { - this.kit = kit; - } - - public List getDependencies() { - return dependencies; - } - - public void setDependencies(List dependencies) { - this.dependencies = dependencies; - } - - public String getProfile() { - return profile; - } - - public void setProfile(String profile) { - this.profile = profile; - } - - public Map getTraits() { - return traits; - } - - public void setTraits(Map traits) { - this.traits = traits; - } - - public List getConfiguration() { - return configuration; - } - - public void setConfiguration(List configuration) { - this.configuration = configuration; - } - - public List getRepositories() { - return repositories; - } - - public void setRepositories(List repositories) { - this.repositories = repositories; - } - - public String getServiceAccountName() { - return serviceAccountName; - } - - public void setServiceAccountName(String serviceAccountName) { - this.serviceAccountName = serviceAccountName; - } - - @JsonDeserialize(using = JsonDeserializer.None.class) - @JsonInclude(JsonInclude.Include.NON_NULL) - @JsonPropertyOrder({"type", "value"}) - public static class Configuration implements KubernetesResource { - @JsonProperty("type") - private String type; - @JsonProperty("value") - private String value; - - public Configuration() { - super(); - } - - public Configuration(String type, String value) { - this.type = type; - this.value = value; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getValue() { - return value; - } - - public void setValue(String defaultValue) { - this.value = defaultValue; - } - } - - @JsonDeserialize(using = JsonDeserializer.None.class) - @JsonInclude(JsonInclude.Include.NON_NULL) - @JsonPropertyOrder({"configuration"}) - public static class TraitConfig implements KubernetesResource { - @JsonProperty("configuration") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private Map configuration = new HashMap<>(); - - public TraitConfig() { - // default constructor - } - - public TraitConfig(String key, Object value) { - add(key, value); - } - - public Map getConfiguration() { - return configuration; - } - - public void setConfiguration(Map configuration) { - this.configuration = configuration; - } - - public void add(String key, Object value) { - this.configuration.put(key, value); - } - } - - @JsonDeserialize(using = JsonDeserializer.None.class) - @JsonInclude(JsonInclude.Include.NON_NULL) - @JsonPropertyOrder({"language", "loader", "type", "name", "path", "rawContent", "content", - "contentType", "contentRef", "contentKey", "compression", "property-names", "interceptors"}) - public static class Source extends DataSpec implements KubernetesResource { - @JsonProperty("language") - private String language; - @JsonProperty("loader") - private String loader; - @JsonProperty("type") - private String type; - @JsonProperty("interceptors") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private List interceptors; - @JsonProperty("property-names") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private List propertyNames; - - public Source() { - super(); - } - - public Source(String name, String content) { - super(name, content); - } - - public String getLanguage() { - return language; - } - - public void setLanguage(String language) { - this.language = language; - } - - public String getLoader() { - return loader; - } - - public void setLoader(String loader) { - this.loader = loader; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public List getInterceptors() { - return interceptors; - } - - public void setInterceptors(List interceptors) { - this.interceptors = interceptors; - } - - public List getPropertyNames() { - return propertyNames; - } - - public void setPropertyNames(List propertyNames) { - this.propertyNames = propertyNames; - } - } - - @JsonDeserialize(using = JsonDeserializer.None.class) - @JsonInclude(JsonInclude.Include.NON_NULL) - @JsonPropertyOrder({"type", "mountPath", "name", "path", "rawContent", "content", - "contentType", "contentRef", "contentKey", "compression"}) - public static class Resource extends DataSpec implements KubernetesResource { - @JsonProperty("type") - private String type; - @JsonProperty("mountPath") - private String mountPath; - - public Resource() { - super(); - } - - public Resource(String type, String mountPath, String name, String content) { - super(name, content); - this.mountPath = mountPath; - this.type = type; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getMountPath() { - return mountPath; - } - - public void setMountPath(String mountPath) { - this.mountPath = mountPath; - } - } - - private static class DataSpec { - @JsonProperty("name") - private String name; - @JsonProperty("path") - private String path; - @JsonProperty("content") - private String content; - @JsonProperty("contentRef") - private String contentRef; - @JsonProperty("contentType") - private String contentType; - @JsonProperty("contentKey") - private String contentKey; - @JsonProperty("compression") - private String compression; - @JsonProperty("rawContent") - private String rawContent; - - public DataSpec() { - super(); - } - - public DataSpec(String name, String content) { - this.content = content; - this.name = name; - } - - public String getContent() { - return content; - } - - public void setContent(String content) { - this.content = content; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public String getContentType() { - return contentType; - } - - public void setContentType(String contentType) { - this.contentType = contentType; - } - - public String getContentRef() { - return contentRef; - } - - public void setContentRef(String contentRef) { - this.contentRef = contentRef; - } - - public String getContentKey() { - return contentKey; - } - - public void setContentKey(String contentKey) { - this.contentKey = contentKey; - } - - public String getCompression() { - return compression; - } - - public void setCompression(String compression) { - this.compression = compression; - } - - public String getRawContent() { - return rawContent; - } - - public void setRawContent(String rawContent) { - this.rawContent = rawContent; - } - } -} diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/IntegrationStatus.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/IntegrationStatus.java deleted file mode 100644 index 22687280..00000000 --- a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/IntegrationStatus.java +++ /dev/null @@ -1,617 +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.List; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -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({"phase", "digest", "image", "dependencies", "profile", "integrationKit", "kit", "lastInitTimestamp", "platform", "generatedSources", "generatedResources", - "failure", "runtimeProvider", "configuration", "conditions", "version", "replicas", "selector", "capabilities", "observedGeneration"}) -public class IntegrationStatus implements KubernetesResource { - - @JsonProperty("phase") - private String phase; - @JsonProperty("digest") - private String digest; - @JsonProperty("image") - private String image; - @JsonProperty("dependencies") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private List dependencies; - @JsonProperty("profile") - private String profile; - @JsonProperty("integrationKit") - private IntegrationKit integrationKit; - @JsonProperty("kit") - private String kit; - @JsonProperty("lastInitTimestamp") - private String lastInitTimestamp; - @JsonProperty("platform") - private String platform; - @JsonProperty("generatedSources") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private List generatedSources; - @JsonProperty("generatedResources") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private List generatedResources; - @JsonProperty("failure") - private String failure; - @JsonProperty("runtimeVersion") - private String runtimeVersion; - @JsonProperty("runtimeProvider") - private String runtimeProvider; - @JsonProperty("configuration") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private List configuration; - @JsonProperty("conditions") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private List conditions; - @JsonProperty("version") - private String version; - @JsonProperty("replicas") - private int replicas; - @JsonProperty("selector") - private String selector; - @JsonProperty("capabilities") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private List capabilities; - @JsonProperty("observedGeneration") - private Integer observedGeneration; - - public String getPhase() { - return phase; - } - - public void setPhase(String phase) { - this.phase = phase; - } - - public String getDigest() { - return digest; - } - - public void setDigest(String digest) { - this.digest = digest; - } - - public String getImage() { - return image; - } - - public void setImage(String image) { - this.image = image; - } - - public List getDependencies() { - return dependencies; - } - - public void setDependencies(List dependencies) { - this.dependencies = dependencies; - } - - public String getProfile() { - return profile; - } - - public void setProfile(String profile) { - this.profile = profile; - } - - @Deprecated - public String getKit() { - return kit; - } - - @Deprecated - public void setKit(String kit) { - this.kit = kit; - } - - public IntegrationKit getIntegrationKit() { - return integrationKit; - } - - public void setIntegrationKit(IntegrationKit integrationKit) { - this.integrationKit = integrationKit; - } - - public String getLastInitTimestamp() { - return lastInitTimestamp; - } - - public void setLastInitTimestamp(String lastInitTimestamp) { - this.lastInitTimestamp = lastInitTimestamp; - } - - public String getPlatform() { - return platform; - } - - public void setPlatform(String platform) { - this.platform = platform; - } - - public List getGeneratedSources() { - return generatedSources; - } - - public void setGeneratedSources(List generatedSources) { - this.generatedSources = generatedSources; - } - - public List getGeneratedResources() { - return generatedResources; - } - - public void setGeneratedResources(List generatedResources) { - this.generatedResources = generatedResources; - } - - public String getFailure() { - return failure; - } - - public void setFailure(String failure) { - this.failure = failure; - } - - public String getRuntimeVersion() { - return runtimeVersion; - } - - public void setRuntimeVersion(String runtimeVersion) { - this.runtimeVersion = runtimeVersion; - } - - public String getRuntimeProvider() { - return runtimeProvider; - } - - public void setRuntimeProvider(String runtimeProvider) { - this.runtimeProvider = runtimeProvider; - } - - public List getConfiguration() { - return configuration; - } - - public void setConfiguration(List configuration) { - this.configuration = configuration; - } - - public List getConditions() { - return conditions; - } - - public void setConditions(List conditions) { - this.conditions = conditions; - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - public int getReplicas() { - return replicas; - } - - public void setReplicas(int replicas) { - this.replicas = replicas; - } - - public String getSelector() { - return selector; - } - - public void setSelector(String selector) { - this.selector = selector; - } - - public List getCapabilities() { - return capabilities; - } - - public void setCapabilities(List capabilities) { - this.capabilities = capabilities; - } - - public Integer getObservedGeneration() { - return observedGeneration; - } - - public void setObservedGeneration(Integer observedGeneration) { - this.observedGeneration = observedGeneration; - } - - @JsonDeserialize(using = JsonDeserializer.None.class) - @JsonInclude(JsonInclude.Include.NON_NULL) - @JsonPropertyOrder({"type", "status", "lastUpdateTime", "lastTransitionTime", "reason", "message"}) - @JsonIgnoreProperties(ignoreUnknown = true) - public static class Condition implements KubernetesResource { - @JsonProperty("type") - private String type; - @JsonProperty("status") - private String status; - @JsonProperty("lastUpdateTime") - private String lastUpdateTime; - @JsonProperty("lastTransitionTime") - private String lastTransitionTime; - @JsonProperty("reason") - private String reason; - @JsonProperty("message") - private String message; - - public Condition() { - super(); - } - - public Condition(String type, String status, String reason, String message) { - this.type = type; - this.status = status; - this.reason = reason; - this.message = message; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getStatus() { - return status; - } - - public void setStatus(String status) { - this.status = status; - } - - public String getLastUpdateTime() { - return lastUpdateTime; - } - - public void setLastUpdateTime(String lastUpdateTime) { - this.lastUpdateTime = lastUpdateTime; - } - - public String getLastTransitionTime() { - return lastTransitionTime; - } - - public void setLastTransitionTime(String lastTransitionTime) { - this.lastTransitionTime = lastTransitionTime; - } - - public String getReason() { - return reason; - } - - public void setReason(String reason) { - this.reason = reason; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - } - - @JsonDeserialize(using = JsonDeserializer.None.class) - @JsonInclude(JsonInclude.Include.NON_NULL) - @JsonPropertyOrder({"type", "value"}) - public static class Configuration implements KubernetesResource { - @JsonProperty("type") - private String type; - @JsonProperty("value") - private String value; - - public Configuration() { - super(); - } - - public Configuration(String type, String value) { - this.type = type; - this.value = value; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getValue() { - return value; - } - - public void setValue(String defaultValue) { - this.value = value; - } - } - - @JsonDeserialize(using = JsonDeserializer.None.class) - @JsonInclude(JsonInclude.Include.NON_NULL) - @JsonPropertyOrder({"language", "loader", "type", "name", "content", "contentRef", "contentKey", "compression", - "property-names", "interceptors"}) - public static class Source extends DataSpec implements KubernetesResource { - @JsonProperty("language") - private String language; - @JsonProperty("loader") - private String loader; - @JsonProperty("type") - private String type; - @JsonProperty("interceptors") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private List interceptors; - @JsonProperty("property-names") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private List propertyNames; - - public Source() { - super(); - } - - public Source(String name, String content) { - super(name, content); - } - - public String getLanguage() { - return language; - } - - public void setLanguage(String language) { - this.language = language; - } - - public String getLoader() { - return loader; - } - - public void setLoader(String loader) { - this.loader = loader; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public List getInterceptors() { - return interceptors; - } - - public void setInterceptors(List interceptors) { - this.interceptors = interceptors; - } - - public List getPropertyNames() { - return propertyNames; - } - - public void setPropertyNames(List propertyNames) { - this.propertyNames = propertyNames; - } - } - - @JsonDeserialize(using = JsonDeserializer.None.class) - @JsonInclude(JsonInclude.Include.NON_NULL) - @JsonPropertyOrder({"type", "mountPath", "name", "content", "contentRef", "contentKey", "compression"}) - public static class Resource extends DataSpec implements KubernetesResource { - @JsonProperty("type") - private String type; - @JsonProperty("mountPath") - private String mountPath; - - public Resource() { - super(); - } - - public Resource(String type, String mountPath, String name, String content) { - super(name, content); - this.mountPath = mountPath; - this.type = type; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getMountPath() { - return mountPath; - } - - public void setMountPath(String mountPath) { - this.mountPath = mountPath; - } - } - - private static class DataSpec { - @JsonProperty("name") - private String name; - @JsonProperty("content") - private String content; - @JsonProperty("contentRef") - private String contentRef; - @JsonProperty("contentKey") - private String contentKey; - @JsonProperty("compression") - private String compression; - - public DataSpec() { - super(); - } - - public DataSpec(String name, String content) { - this.content = content; - this.name = name; - } - - public String getContent() { - return content; - } - - public void setContent(String content) { - this.content = content; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getContentRef() { - return contentRef; - } - - public void setContentRef(String contentRef) { - this.contentRef = contentRef; - } - - public String getContentKey() { - return contentKey; - } - - public void setContentKey(String contentKey) { - this.contentKey = contentKey; - } - - public String getCompression() { - return compression; - } - - public void setCompression(String compression) { - this.compression = compression; - } - } - - @JsonDeserialize(using = JsonDeserializer.None.class) - @JsonInclude(JsonInclude.Include.NON_NULL) - @JsonPropertyOrder({"apiVersion", "fieldPath", "kind", "name", "namespace", "resourceVersion", "uid"}) - public static class IntegrationKit implements KubernetesResource { - @JsonProperty("apiVersion") - private String apiVersion; - @JsonProperty("fieldPath") - private String fieldPath; - @JsonProperty("kind") - private String kind; - @JsonProperty("name") - private String name; - @JsonProperty("namespace") - private String namespace; - @JsonProperty("resourceVersion") - private String resourceVersion; - @JsonProperty("uid") - private String uid; - - public IntegrationKit() { - super(); - } - - public IntegrationKit(String apiVersion, String kind, String name) { - this.apiVersion = apiVersion; - this.kind = kind; - this.name = name; - } - - public String getApiVersion() { - return apiVersion; - } - - public void setApiVersion(String apiVersion) { - this.apiVersion = apiVersion; - } - - public String getFieldPath() { - return fieldPath; - } - - public void setFieldPath(String fieldPath) { - this.fieldPath = fieldPath; - } - - public String getKind() { - return kind; - } - - public void setKind(String kind) { - this.kind = kind; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getNamespace() { - return namespace; - } - - public void setNamespace(String namespace) { - this.namespace = namespace; - } - - public String getResourceVersion() { - return resourceVersion; - } - - public void setResourceVersion(String resourceVersion) { - this.resourceVersion = resourceVersion; - } - - public String getUid() { - return uid; - } - - public void setUid(String uid) { - this.uid = uid; - } - } -} diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/Kamelet.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/Kamelet.java deleted file mode 100644 index 908acd84..00000000 --- a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/Kamelet.java +++ /dev/null @@ -1,157 +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.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import com.fasterxml.jackson.annotation.JsonInclude; -import io.fabric8.kubernetes.api.model.Namespaced; -import io.fabric8.kubernetes.client.CustomResource; -import io.fabric8.kubernetes.model.annotation.Group; -import io.fabric8.kubernetes.model.annotation.Version; -import org.citrusframework.yaks.camelk.CamelKSettings; -import org.citrusframework.yaks.camelk.CamelKSupport; -import org.citrusframework.yaks.kubernetes.KubernetesSupport; -import org.springframework.util.StringUtils; - -/** - * @author Christoph Deppisch - */ -@JsonInclude(JsonInclude.Include.NON_NULL) -@Group(CamelKSupport.CAMELK_CRD_GROUP) -@Version(CamelKSettings.V1) -public class Kamelet extends CustomResource implements Namespaced { - - public Kamelet() { - super(); - this.spec = new KameletSpec(); - this.status = null; - } - - /** - * Fluent builder - */ - public static class Builder { - protected String name; - private String template; - private KameletSpec.Definition definition = new KameletSpec.Definition(); - private final Map dataTypes = new HashMap<>(); - private List dependencies = new ArrayList<>(); - private KameletSpec.Source source; - - private final Map labels = new LinkedHashMap<>(); - private final Map annotations = new LinkedHashMap<>(); - - public Builder name(String name) { - this.name = name; - definition.setTitle(StringUtils.capitalize(name)); - return this; - } - - public Builder definition(KameletSpec.Definition definition) { - this.definition = definition; - return this; - } - - public Builder source(String name, String language, String content) { - this.source = new KameletSpec.Source(name + "." + language, content); - return this; - } - - public Builder source(String name, String content) { - this.source = new KameletSpec.Source(name, content); - return this; - } - - public Builder template(String template) { - this.template = template; - return this; - } - - @Deprecated - public Builder flow(String flow) { - this.template = flow; - return this; - } - - public Builder dependencies(List dependencies) { - this.dependencies = Collections.unmodifiableList(dependencies); - return this; - } - - public Builder dataTypes(Map types) { - this.dataTypes.putAll(types); - return this; - } - - 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)); - } else { - this.dataTypes.put(slot, new KameletSpec.DataTypesSpec(format, new KameletSpec.DataTypeSpec(scheme, format))); - } - - return this; - } - - public Builder labels(Map labels) { - this.labels.putAll(labels); - return this; - } - - public Builder addLabel(String name, String value) { - this.labels.put(name, value); - return this; - } - - public Builder annotations(Map annotations) { - this.annotations.putAll(annotations); - return this; - } - - public Builder addAnnotation(String name, String value) { - this.annotations.put(name, value); - return this; - } - - public Kamelet build() { - Kamelet kamelet = new Kamelet(); - kamelet.getMetadata().setName(name); - kamelet.getSpec().setDefinition(definition); - - kamelet.getMetadata().getAnnotations().putAll(annotations); - kamelet.getMetadata().getLabels().putAll(labels); - - if (template != null && !template.isEmpty()) { - kamelet.getSpec().setTemplate(KubernetesSupport.yaml().load(template)); - } - - if (source != null) { - kamelet.getSpec().setSources(Collections.singletonList(source)); - } - - kamelet.getSpec().setDependencies(dependencies); - kamelet.getSpec().setDataTypes(dataTypes); - return kamelet; - } - } -} diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/KameletList.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/KameletList.java index d4c83877..2133a6f7 100644 --- a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/KameletList.java +++ b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/KameletList.java @@ -17,6 +17,7 @@ package org.citrusframework.yaks.camelk.model; import io.fabric8.kubernetes.api.model.DefaultKubernetesResourceList; +import org.apache.camel.v1.Kamelet; /** * @author Christoph Deppisch diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/KameletSpec.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/KameletSpec.java deleted file mode 100644 index 6237b394..00000000 --- a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/KameletSpec.java +++ /dev/null @@ -1,497 +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.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -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 com.fasterxml.jackson.module.jsonSchema.types.ObjectSchema; -import io.fabric8.kubernetes.api.model.KubernetesResource; - -@JsonDeserialize(using = JsonDeserializer.None.class) -@JsonInclude(JsonInclude.Include.NON_NULL) -@JsonPropertyOrder({"definition", "dataTypes", "dependencies", "sources", "authorization", "flow", "template"}) -public class KameletSpec implements KubernetesResource { - - @JsonProperty("definition") - private Definition definition; - @JsonProperty("dataTypes") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private Map dataTypes; - @JsonProperty("dependencies") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private List dependencies; - @JsonProperty("sources") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private List sources; - @JsonProperty("authorization") - private AuthorizationSpec authorization; - @JsonProperty("flow") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private Map flow; - @JsonProperty("template") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private Map template; - - public Definition getDefinition() { - return definition; - } - - public void setDefinition(Definition definition) { - this.definition = definition; - } - - public List getSources() { - return sources; - } - - public void setSources(List sources) { - this.sources = sources; - } - - public AuthorizationSpec getAuthorization() { - return authorization; - } - - public void setAuthorization(AuthorizationSpec authorization) { - this.authorization = authorization; - } - - public List getDependencies() { - return dependencies; - } - - public void setDependencies(List dependencies) { - this.dependencies = dependencies; - } - - public Map getDataTypes() { - return dataTypes; - } - - public void setDataTypes(Map dataTypes) { - this.dataTypes = dataTypes; - } - - @Deprecated - public Map getFlow() { - return flow; - } - - @Deprecated - public void setFlow(Map flow) { - this.flow = flow; - } - - public Map getTemplate() { - return template; - } - - public void setTemplate(Map template) { - this.template = template; - } - - @JsonDeserialize(using = JsonDeserializer.None.class) - @JsonInclude(JsonInclude.Include.NON_NULL) - @JsonPropertyOrder({"name", "content"}) - public static class Source implements KubernetesResource { - @JsonProperty("content") - private String content; - @JsonProperty("name") - private String name; - - public Source() { - super(); - } - - public Source(String name, String content) { - this.content = content; - this.name = name; - } - - public String getContent() { - return content; - } - - public void setContent(String content) { - this.content = content; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - } - - @JsonDeserialize(using = JsonDeserializer.None.class) - @JsonInclude(JsonInclude.Include.NON_NULL) - @JsonPropertyOrder({"default", "types", "headers"}) - public static class DataTypesSpec implements KubernetesResource { - @JsonProperty("default") - private String defaultType; - - @JsonProperty("types") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private Map types = new HashMap<>(); - - @JsonProperty("headers") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private Map headers = new HashMap<>(); - - public DataTypesSpec() { - super(); - } - - public DataTypesSpec(String defaultType, DataTypeSpec... types) { - this.defaultType = defaultType; - for (DataTypeSpec spec : types) { - this.types.put(spec.format, spec); - } - } - - public Map getTypes() { - return types; - } - - public void setTypes(Map types) { - this.types = types; - } - - public String getDefaultType() { - return defaultType; - } - - public void setDefaultType(String defaultType) { - this.defaultType = defaultType; - } - - public Map getHeaders() { - return headers; - } - - public void setHeaders(Map headers) { - this.headers = headers; - } - } - - @JsonDeserialize(using = JsonDeserializer.None.class) - @JsonInclude(JsonInclude.Include.NON_NULL) - @JsonPropertyOrder({"scheme", "format", "description", "mediaType", "headers", "dependencies", "schema"}) - public static class DataTypeSpec implements KubernetesResource { - @JsonProperty("scheme") - private String scheme; - - @JsonProperty("format") - private String format; - - @JsonProperty("description") - private String description; - - @JsonProperty("mediaType") - private String mediaType; - - @JsonProperty("headers") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private Map headers; - - @JsonProperty("dependencies") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private List dependencies; - - @JsonProperty("schema") - private ObjectSchema schema; - - public DataTypeSpec() { - super(); - } - - public DataTypeSpec(String scheme, String format) { - this.scheme = scheme; - this.format = format; - } - - public String getScheme() { - return scheme; - } - - public void setScheme(String scheme) { - this.scheme = scheme; - } - - public String getFormat() { - return format; - } - - public void setFormat(String format) { - this.format = format; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public String getMediaType() { - return mediaType; - } - - public void setMediaType(String mediaType) { - this.mediaType = mediaType; - } - - public ObjectSchema getSchema() { - return schema; - } - - public void setSchema(ObjectSchema schema) { - this.schema = schema; - } - - public Map getHeaders() { - return headers; - } - - public void setHeaders(Map headers) { - this.headers = headers; - } - - public List getDependencies() { - return dependencies; - } - - public void setDependencies(List dependencies) { - this.dependencies = dependencies; - } - } - - @JsonDeserialize(using = JsonDeserializer.None.class) - @JsonInclude(JsonInclude.Include.NON_NULL) - @JsonPropertyOrder({"type", "title", "description", "required", "default"}) - public static class HeaderSpec implements KubernetesResource { - @JsonProperty("type") - private String type; - - @JsonProperty("title") - private String title; - - @JsonProperty("description") - private String description; - - @JsonProperty("required") - private boolean required; - - @JsonProperty("default") - private String defaultValue; - - public HeaderSpec() { - super(); - } - - public HeaderSpec(String type, String title, boolean required, String defaultValue) { - this.type = type; - this.title = title; - this.required = required; - this.defaultValue = defaultValue; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public boolean isRequired() { - return required; - } - - public void setRequired(boolean required) { - this.required = required; - } - - public String getDefaultValue() { - return defaultValue; - } - - public void setDefaultValue(String defaultValue) { - this.defaultValue = defaultValue; - } - } - - @JsonDeserialize(using = JsonDeserializer.None.class) - @JsonInclude(JsonInclude.Include.NON_NULL) - @JsonPropertyOrder({"title", "description", "required", "properties", "type"}) - @JsonIgnoreProperties(ignoreUnknown = true) - public static class Definition implements KubernetesResource { - @JsonProperty("title") - private String title; - @JsonProperty("description") - private String description; - @JsonProperty("type") - private String type; - @JsonProperty("required") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private List required = new ArrayList<>(); - @JsonProperty("properties") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private Map properties = new HashMap<>(); - - public void setTitle(String title) { - this.title = title; - } - - public String getTitle() { - return title; - } - - public void setDescription(String description) { - this.description = description; - } - - public String getDescription() { - return description; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public List getRequired() { - return required; - } - - public void setRequired(List required) { - this.required = required; - } - - public Map getProperties() { - return properties; - } - - public void setProperties(Map properties) { - this.properties = properties; - } - - @JsonDeserialize(using = JsonDeserializer.None.class) - @JsonInclude(JsonInclude.Include.NON_NULL) - @JsonPropertyOrder({"title", "description", "type", "default", "example"}) - @JsonIgnoreProperties(ignoreUnknown = true) - public static class PropertyConfig implements KubernetesResource { - @JsonProperty("title") - private String title; - @JsonProperty("description") - private String description; - @JsonProperty("type") - private String type; - @JsonProperty("default") - private Object defaultValue; - @JsonProperty("example") - private Object example; - - public PropertyConfig() { - super(); - } - - public PropertyConfig(String title, String type, Object defaultValue, Object example) { - this.title = title; - this.type = type; - this.defaultValue = defaultValue; - this.example = example; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public Object getDefault() { - return defaultValue; - } - - public void setDefault(Object defaultValue) { - this.defaultValue = defaultValue; - } - - public Object getExample() { - return example; - } - - public void setExample(Object example) { - this.example = example; - } - } - } - - @JsonDeserialize(using = JsonDeserializer.None.class) - @JsonInclude(JsonInclude.Include.NON_NULL) - public static class AuthorizationSpec implements KubernetesResource { - } -} diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/KameletStatus.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/KameletStatus.java deleted file mode 100644 index 24a22807..00000000 --- a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/KameletStatus.java +++ /dev/null @@ -1,189 +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.List; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -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({"phase", "conditions", "properties", "observedGeneration"}) -public class KameletStatus implements KubernetesResource { - - @JsonProperty("phase") - private String phase; - @JsonProperty("conditions") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private List conditions; - @JsonProperty("properties") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private List properties; - @JsonProperty("observedGeneration") - private Integer observedGeneration; - - @JsonDeserialize(using = JsonDeserializer.None.class) - @JsonInclude(JsonInclude.Include.NON_NULL) - @JsonPropertyOrder({"type", "status", "lastUpdateTime", "lastTransitionTime", "reason", "message"}) - @JsonIgnoreProperties(ignoreUnknown = true) - public static class Condition implements KubernetesResource { - @JsonProperty("type") - private String type; - @JsonProperty("status") - private String status; - @JsonProperty("lastUpdateTime") - private String lastUpdateTime; - @JsonProperty("lastTransitionTime") - private String lastTransitionTime; - @JsonProperty("reason") - private String reason; - @JsonProperty("message") - private String message; - - public Condition() { - super(); - } - - public Condition(String type, String status, String reason, String message) { - this.type = type; - this.status = status; - this.reason = reason; - this.message = message; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getStatus() { - return status; - } - - public void setStatus(String status) { - this.status = status; - } - - public String getLastUpdateTime() { - return lastUpdateTime; - } - - public void setLastUpdateTime(String lastUpdateTime) { - this.lastUpdateTime = lastUpdateTime; - } - - public String getLastTransitionTime() { - return lastTransitionTime; - } - - public void setLastTransitionTime(String lastTransitionTime) { - this.lastTransitionTime = lastTransitionTime; - } - - public String getReason() { - return reason; - } - - public void setReason(String reason) { - this.reason = reason; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - } - - @JsonDeserialize(using = JsonDeserializer.None.class) - @JsonInclude(JsonInclude.Include.NON_NULL) - @JsonPropertyOrder({"name", "default"}) - public static class Property implements KubernetesResource { - @JsonProperty("name") - private String name; - @JsonProperty("default") - private String defaultValue; - - public Property() { - super(); - } - - public Property(String name, String defaultValue) { - this.name = name; - this.defaultValue = defaultValue; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getDefaultValue() { - return defaultValue; - } - - public void setDefaultValue(String defaultValue) { - this.defaultValue = defaultValue; - } - } - - public String getPhase() { - return phase; - } - - public void setPhase(String phase) { - this.phase = phase; - } - - public List getProperties() { - return properties; - } - - public void setProperties(List properties) { - this.properties = properties; - } - - public List getConditions() { - return conditions; - } - - public void setConditions(List conditions) { - this.conditions = conditions; - } - - public Integer getObservedGeneration() { - return observedGeneration; - } - - public void setObservedGeneration(Integer observedGeneration) { - this.observedGeneration = observedGeneration; - } -} diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/Pipe.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/Pipe.java deleted file mode 100644 index 208453df..00000000 --- a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/Pipe.java +++ /dev/null @@ -1,159 +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.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import com.fasterxml.jackson.annotation.JsonInclude; -import io.fabric8.kubernetes.api.model.Namespaced; -import io.fabric8.kubernetes.client.CustomResource; -import io.fabric8.kubernetes.model.annotation.Group; -import io.fabric8.kubernetes.model.annotation.Version; -import org.citrusframework.yaks.camelk.CamelKSettings; -import org.citrusframework.yaks.camelk.CamelKSupport; -import org.citrusframework.yaks.kubernetes.KubernetesSupport; - -/** - * @author Christoph Deppisch - */ -@JsonInclude(JsonInclude.Include.NON_NULL) -@Group(CamelKSupport.CAMELK_CRD_GROUP) -@Version(CamelKSettings.V1) -public class Pipe extends CustomResource implements Namespaced { - - public Pipe() { - super(); - this.spec = new PipeSpec(); - this.status = null; - } - - /** - * Fluent builder - */ - public static class Builder { - protected String name; - private int replicas; - private IntegrationSpec integration; - private PipeSpec.Endpoint source; - private PipeSpec.Endpoint sink; - private final List steps = new ArrayList<>(); - - public Builder name(String name) { - this.name = name; - return this; - } - - public Builder integration(IntegrationSpec integration) { - this.integration = integration; - return this; - } - - public Builder source(PipeSpec.Endpoint source) { - this.source = source; - return this; - } - - public Builder source(String uri) { - return source(new PipeSpec.Endpoint(uri)); - } - - public Builder source(PipeSpec.Endpoint.ObjectReference ref, String properties) { - Map props = null; - if (properties != null && !properties.isEmpty()) { - props = KubernetesSupport.yaml().load(properties); - } - - return source(new PipeSpec.Endpoint(ref, props)); - } - - public Builder sink(PipeSpec.Endpoint sink) { - this.sink = sink; - return this; - } - - public Builder sink(String uri) { - return sink(new PipeSpec.Endpoint(uri)); - } - - public Builder sink(PipeSpec.Endpoint.ObjectReference ref, String properties) { - Map props = null; - if (properties != null && !properties.isEmpty()) { - props = KubernetesSupport.yaml().load(properties); - } - - return sink(new PipeSpec.Endpoint(ref, props)); - } - - public Builder steps(PipeSpec.Endpoint... step) { - this.steps.addAll(Arrays.asList(step)); - return this; - } - - public Builder addStep(PipeSpec.Endpoint step) { - this.steps.add(step); - return this; - } - - public Builder addStep(String uri) { - return addStep(new PipeSpec.Endpoint(uri)); - } - - public Builder addStep(PipeSpec.Endpoint.ObjectReference ref, String properties) { - Map props = null; - if (properties != null && !properties.isEmpty()) { - props = KubernetesSupport.yaml().load(properties); - } - - return addStep(new PipeSpec.Endpoint(ref, props)); - } - - public Builder replicas(int replicas) { - this.replicas = replicas; - return this; - } - - public Pipe build() { - Pipe pipe = new Pipe(); - pipe.getMetadata().setName(name); - - if (replicas > 0) { - pipe.getSpec().setReplicas(replicas); - } - - if (integration != null) { - pipe.getSpec().setIntegration(integration); - } - - if (source != null) { - pipe.getSpec().setSource(source); - } - - if (sink != null) { - pipe.getSpec().setSink(sink); - } - - if (!steps.isEmpty()) { - pipe.getSpec().setSteps(steps.toArray(new PipeSpec.Endpoint[]{})); - } - - return pipe; - } - } -} diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/PipeList.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/PipeList.java index 6fc8177a..0c9cd7a9 100644 --- a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/PipeList.java +++ b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/PipeList.java @@ -17,6 +17,7 @@ package org.citrusframework.yaks.camelk.model; import io.fabric8.kubernetes.api.model.DefaultKubernetesResourceList; +import org.apache.camel.v1.Pipe; /** * @author Christoph Deppisch diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/PipeSpec.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/PipeSpec.java deleted file mode 100644 index e70e53dc..00000000 --- a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/PipeSpec.java +++ /dev/null @@ -1,285 +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.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({"integration", "replicas", "source", "steps", "sink"}) -public class PipeSpec implements KubernetesResource { - - @JsonProperty("integration") - private IntegrationSpec integration; - - @JsonProperty("source") - private Endpoint source; - - @JsonProperty("sink") - private Endpoint sink; - - @JsonProperty("steps") - private Endpoint[] steps; - - @JsonProperty("replicas") - private Integer replicas; - - public void setReplicas(Integer replicas) { - this.replicas = replicas; - } - - public Integer getReplicas() { - return replicas; - } - - public void setSource(Endpoint source) { - this.source = source; - } - - public Endpoint getSource() { - return source; - } - - public void setSink(Endpoint sink) { - this.sink = sink; - } - - public Endpoint getSink() { - return sink; - } - - public Endpoint[] getSteps() { - return steps; - } - - public void setSteps(Endpoint[] steps) { - this.steps = steps; - } - - public void setIntegration(IntegrationSpec integration) { - this.integration = integration; - } - - public IntegrationSpec getIntegration() { - return integration; - } - - @JsonDeserialize(using = JsonDeserializer.None.class) - @JsonInclude(JsonInclude.Include.NON_NULL) - @JsonPropertyOrder({"ref", "uri", "properties", "dataTypes"}) - public static class Endpoint implements KubernetesResource { - @JsonProperty("ref") - private ObjectReference ref; - - @JsonProperty("uri") - private String uri; - - @JsonProperty("properties") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private Map properties = new HashMap<>(); - - @JsonProperty("dataTypes") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private Map dataTypes = new HashMap<>(); - - public Endpoint() { - } - - public Endpoint(ObjectReference ref) { - this.ref = ref; - } - - public Endpoint(ObjectReference ref, Map properties) { - this.ref = ref; - this.properties = properties; - } - - public Endpoint(String uri) { - this.uri = uri; - } - - public ObjectReference getRef() { - return ref; - } - - public void setRef(ObjectReference ref) { - this.ref = ref; - } - - public String getUri() { - return uri; - } - - public void setUri(String uri) { - this.uri = uri; - } - - public Map getProperties() { - return properties; - } - - public void setProperties(Map properties) { - this.properties = properties; - } - - public Map getDataTypes() { - return dataTypes; - } - - public void setDataTypes(Map dataTypes) { - this.dataTypes = dataTypes; - } - - @JsonDeserialize(using = JsonDeserializer.None.class) - @JsonInclude(JsonInclude.Include.NON_NULL) - @JsonPropertyOrder({"scheme", "format"}) - public static class DataTypeRef implements KubernetesResource { - @JsonProperty("scheme") - private String scheme; - - @JsonProperty("format") - private String format; - - public DataTypeRef() { - super(); - } - - public DataTypeRef(String scheme, String format) { - this.scheme = scheme; - this.format = format; - } - - public String getScheme() { - return scheme; - } - - public void setScheme(String scheme) { - this.scheme = scheme; - } - - public String getFormat() { - return format; - } - - public void setFormat(String format) { - this.format = format; - } - } - - @JsonDeserialize(using = JsonDeserializer.None.class) - @JsonInclude(JsonInclude.Include.NON_NULL) - @JsonPropertyOrder({"name", "kind", "namespace", "uid", "apiVersion", "resourceVersion", "fieldPath"}) - public static class ObjectReference implements KubernetesResource { - @JsonProperty("name") - private String name; - @JsonProperty("kind") - private String kind; - @JsonProperty("namespace") - private String namespace; - @JsonProperty("uid") - private String uid; - @JsonProperty("apiVersion") - private String apiVersion; - @JsonProperty("resourceVersion") - private String resourceVersion; - @JsonProperty("fieldPath") - private String fieldPath; - - public ObjectReference() { - super(); - } - - public ObjectReference(String apiVersion, String kind, String namespace, String name) { - this.apiVersion = apiVersion; - this.kind = kind; - this.namespace = namespace; - this.name = name; - } - - public ObjectReference(String kind, String namespace, String name) { - this.kind = kind; - this.namespace = namespace; - this.name = name; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getKind() { - return kind; - } - - public void setKind(String kind) { - this.kind = kind; - } - - public String getNamespace() { - return namespace; - } - - public void setNamespace(String namespace) { - this.namespace = namespace; - } - - public String getUid() { - return uid; - } - - public void setUid(String uid) { - this.uid = uid; - } - - public String getApiVersion() { - return apiVersion; - } - - public void setApiVersion(String apiVersion) { - this.apiVersion = apiVersion; - } - - public String getResourceVersion() { - return resourceVersion; - } - - public void setResourceVersion(String resourceVersion) { - this.resourceVersion = resourceVersion; - } - - public String getFieldPath() { - return fieldPath; - } - - public void setFieldPath(String fieldPath) { - this.fieldPath = fieldPath; - } - } - } - -} diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/PipeStatus.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/PipeStatus.java deleted file mode 100644 index 1a02880f..00000000 --- a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/PipeStatus.java +++ /dev/null @@ -1,143 +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.List; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -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({"phase", "conditions", "observedGeneration"}) -public class PipeStatus implements KubernetesResource { - - @JsonProperty("phase") - private String phase; - @JsonProperty("conditions") - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private List conditions; - @JsonProperty("observedGeneration") - private Integer observedGeneration; - - @JsonDeserialize(using = JsonDeserializer.None.class) - @JsonInclude(JsonInclude.Include.NON_NULL) - @JsonPropertyOrder({"type", "status", "lastUpdateTime", "lastTransitionTime", "reason", "message"}) - @JsonIgnoreProperties(ignoreUnknown = true) - public static class Condition implements KubernetesResource { - @JsonProperty("type") - private String type; - @JsonProperty("status") - private String status; - @JsonProperty("lastUpdateTime") - private String lastUpdateTime; - @JsonProperty("lastTransitionTime") - private String lastTransitionTime; - @JsonProperty("reason") - private String reason; - @JsonProperty("message") - private String message; - - public Condition() { - super(); - } - - public Condition(String type, String status, String reason, String message) { - this.type = type; - this.status = status; - this.reason = reason; - this.message = message; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getStatus() { - return status; - } - - public void setStatus(String status) { - this.status = status; - } - - public String getLastUpdateTime() { - return lastUpdateTime; - } - - public void setLastUpdateTime(String lastUpdateTime) { - this.lastUpdateTime = lastUpdateTime; - } - - public String getLastTransitionTime() { - return lastTransitionTime; - } - - public void setLastTransitionTime(String lastTransitionTime) { - this.lastTransitionTime = lastTransitionTime; - } - - public String getReason() { - return reason; - } - - public void setReason(String reason) { - this.reason = reason; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - } - - public String getPhase() { - return phase; - } - - public void setPhase(String phase) { - this.phase = phase; - } - - public List getConditions() { - return conditions; - } - - public void setConditions(List conditions) { - this.conditions = conditions; - } - - public Integer getObservedGeneration() { - return observedGeneration; - } - - public void setObservedGeneration(Integer observedGeneration) { - this.observedGeneration = observedGeneration; - } -} diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/v1alpha1/KameletBinding.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/v1alpha1/KameletBinding.java deleted file mode 100644 index 1fb62d0b..00000000 --- a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/v1alpha1/KameletBinding.java +++ /dev/null @@ -1,139 +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.v1alpha1; - -import com.fasterxml.jackson.annotation.JsonInclude; -import io.fabric8.kubernetes.model.annotation.Group; -import io.fabric8.kubernetes.model.annotation.Version; -import org.citrusframework.yaks.camelk.CamelKSettings; -import org.citrusframework.yaks.camelk.CamelKSupport; -import org.citrusframework.yaks.camelk.model.IntegrationSpec; -import org.citrusframework.yaks.camelk.model.Pipe; -import org.citrusframework.yaks.camelk.model.PipeSpec; - -/** - * @author Christoph Deppisch - */ -@JsonInclude(JsonInclude.Include.NON_NULL) -@Group(CamelKSupport.CAMELK_CRD_GROUP) -@Version(CamelKSettings.V1ALPHA1) -public class KameletBinding extends Pipe { - - /** - * Fluent builder - */ - public static class Builder extends Pipe.Builder { - - Pipe.Builder delegate = new Pipe.Builder(); - - public Builder name(String name) { - this.name = name; - delegate.name(name); - return this; - } - - public Builder integration(IntegrationSpec integration) { - delegate.integration(integration); - return this; - } - - public Builder source(PipeSpec.Endpoint source) { - delegate.source(source); - return this; - } - - public Builder source(String uri) { - delegate.source(uri); - return this; - } - - public Builder source(PipeSpec.Endpoint.ObjectReference ref, String properties) { - delegate.source(ref, properties); - return this; - } - - public Builder sink(PipeSpec.Endpoint sink) { - delegate.sink(sink); - return this; - } - - public Builder sink(String uri) { - delegate.sink(uri); - return this; - } - - public Builder sink(PipeSpec.Endpoint.ObjectReference ref, String properties) { - delegate.sink(ref, properties); - return this; - } - - public Builder steps(PipeSpec.Endpoint... step) { - delegate.steps(step); - return this; - } - - public Builder addStep(PipeSpec.Endpoint step) { - delegate.addStep(step); - return this; - } - - public Builder addStep(String uri) { - delegate.addStep(new PipeSpec.Endpoint(uri)); - return this; - } - - public Builder addStep(PipeSpec.Endpoint.ObjectReference ref, String properties) { - delegate.addStep(ref, properties); - return this; - } - - public Builder replicas(int replicas) { - delegate.replicas(replicas); - return this; - } - - public Builder from(Pipe pipe) { - delegate.name(pipe.getMetadata().getName()); - delegate.source(pipe.getSpec().getSource()); - delegate.sink(pipe.getSpec().getSink()); - - if (pipe.getSpec().getSteps() != null) { - delegate.steps(pipe.getSpec().getSteps()); - } - - delegate.integration(pipe.getSpec().getIntegration()); - - if (pipe.getSpec().getReplicas() != null) { - delegate.replicas(pipe.getSpec().getReplicas()); - } - - return this; - } - - public KameletBinding build() { - Pipe b = this.delegate.build(); - - KameletBinding binding = new KameletBinding(); - binding.setMetadata(b.getMetadata()); - - binding.setSpec(b.getSpec()); - binding.setStatus(b.getStatus()); - - return binding; - } - } -} diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/v1alpha1/KameletBindingList.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/v1alpha1/KameletBindingList.java index 7ea3da3e..320d32e5 100644 --- a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/v1alpha1/KameletBindingList.java +++ b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/v1alpha1/KameletBindingList.java @@ -17,6 +17,7 @@ package org.citrusframework.yaks.camelk.model.v1alpha1; import io.fabric8.kubernetes.api.model.DefaultKubernetesResourceList; +import org.apache.camel.v1alpha1.KameletBinding; /** * @author Christoph Deppisch diff --git a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/v1alpha1/KameletV1Alpha1.java b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/v1alpha1/KameletV1Alpha1.java index 2f56bcde..68b71fe4 100644 --- a/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/v1alpha1/KameletV1Alpha1.java +++ b/java/steps/yaks-camel-k/src/main/java/org/citrusframework/yaks/camelk/model/v1alpha1/KameletV1Alpha1.java @@ -16,126 +16,25 @@ package org.citrusframework.yaks.camelk.model.v1alpha1; -import java.util.List; -import java.util.Map; - -import com.fasterxml.jackson.annotation.JsonInclude; -import io.fabric8.kubernetes.api.model.Namespaced; -import io.fabric8.kubernetes.model.annotation.Group; -import io.fabric8.kubernetes.model.annotation.Kind; -import io.fabric8.kubernetes.model.annotation.Version; -import org.citrusframework.yaks.camelk.CamelKSettings; -import org.citrusframework.yaks.camelk.CamelKSupport; -import org.citrusframework.yaks.camelk.model.Kamelet; -import org.citrusframework.yaks.camelk.model.KameletSpec; +import com.fasterxml.jackson.core.JsonProcessingException; +import org.apache.camel.v1alpha1.Kamelet; +import org.citrusframework.exceptions.CitrusRuntimeException; +import org.citrusframework.yaks.kubernetes.KubernetesSupport; /** * @author Christoph Deppisch */ -@JsonInclude(JsonInclude.Include.NON_NULL) -@Group(CamelKSupport.CAMELK_CRD_GROUP) -@Kind("Kamelet") -@Version(CamelKSettings.V1ALPHA1) -public class KameletV1Alpha1 extends Kamelet implements Namespaced { - - public KameletV1Alpha1() { - super(); - this.spec = new KameletSpec(); - this.status = null; - } - - /** - * Fluent builder - */ - public static class Builder extends Kamelet.Builder { - - Kamelet.Builder delegate = new Kamelet.Builder(); - - public Builder name(String name) { - this.name = name; - delegate.name(name); - return this; - } - - public Builder definition(KameletSpec.Definition definition) { - delegate.definition(definition); - return this; - } - - public Builder source(String name, String language, String content) { - delegate.source(name, language, content); - return this; - } - - public Builder source(String name, String content) { - delegate.source(name, content); - return this; - } - - public Builder template(String template) { - delegate.template(template); - return this; - } - - @Deprecated - public Builder flow(String flow) { - delegate.flow(flow); - return this; - } - - public Builder dependencies(List dependencies) { - delegate.dependencies(dependencies); - return this; - } - - public Builder dataTypes(Map types) { - delegate.dataTypes(types); - return this; - } - - public Builder addDataType(String slot, String scheme, String format) { - delegate.addDataType(slot, scheme, format); - return this; - } - - public Builder from(Kamelet kamelet) { - delegate.name(kamelet.getMetadata().getName()); - - delegate.annotations(kamelet.getMetadata().getAnnotations()); - delegate.labels(kamelet.getMetadata().getLabels()); - - if (kamelet.getSpec() != null) { - if (kamelet.getSpec().getDefinition() != null) { - delegate.definition(kamelet.getSpec().getDefinition()); - } - - if (kamelet.getSpec().getSources() != null && !kamelet.getSpec().getSources().isEmpty()) { - KameletSpec.Source source = kamelet.getSpec().getSources().get(0); - delegate.source(source.getName(), source.getContent()); - } - - if (kamelet.getSpec().getDependencies() != null) { - delegate.dependencies(kamelet.getSpec().getDependencies()); - } - - if (kamelet.getSpec().getDataTypes() != null) { - delegate.dataTypes(kamelet.getSpec().getDataTypes()); - } - } - - return this; - } - - public KameletV1Alpha1 build() { - Kamelet k = delegate.build(); +public class KameletV1Alpha1 extends Kamelet { - KameletV1Alpha1 kamelet = new KameletV1Alpha1(); - kamelet.setMetadata(k.getMetadata()); + public static KameletV1Alpha1 from(org.apache.camel.v1.Kamelet kamelet) { + try { + String kameletJson = KubernetesSupport.json().writerFor(org.apache.camel.v1.Kamelet.class).writeValueAsString(kamelet); - kamelet.setSpec(k.getSpec()); - kamelet.setStatus(k.getStatus()); + kameletJson = kameletJson.replaceAll("v1", "v1alpha1"); - return kamelet; + return KubernetesSupport.json().readValue(kameletJson, KameletV1Alpha1.class); + } catch (JsonProcessingException e) { + throw new CitrusRuntimeException("Failed to convert Kamelet to version 'v1alpha1'", e); } } } diff --git a/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/CamelKTestSteps.java b/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/CamelKTestSteps.java index aa2ccace..fc2eaa9d 100644 --- a/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/CamelKTestSteps.java +++ b/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/CamelKTestSteps.java @@ -18,17 +18,17 @@ import java.util.Collections; -import org.citrusframework.Citrus; -import org.citrusframework.annotations.CitrusFramework; import io.cucumber.java.Before; import io.cucumber.java.Scenario; import io.cucumber.java.en.Given; import io.fabric8.kubernetes.api.model.Pod; import io.fabric8.kubernetes.api.model.PodBuilder; import io.fabric8.kubernetes.client.KubernetesClient; -import org.citrusframework.yaks.camelk.model.Integration; +import org.apache.camel.v1.Integration; +import org.apache.camel.v1.IntegrationBuilder; +import org.citrusframework.Citrus; +import org.citrusframework.annotations.CitrusFramework; import org.citrusframework.yaks.camelk.model.IntegrationList; -import org.citrusframework.yaks.camelk.model.IntegrationStatus; import org.citrusframework.yaks.kubernetes.KubernetesSupport; /** @@ -55,14 +55,15 @@ public void createIntegrationPod(String integrationName) { @Given("^Camel K integration pod ([a-z0-9-]+) in phase (Running|Stopped)$") public void createIntegrationPod(String integrationName, String phase) { - Integration integration = new Integration.Builder() - .name(integrationName) + Integration integration = new IntegrationBuilder() + .withNewMetadata() + .withName(integrationName) + .endMetadata() + .withNewStatus() + .withPhase(phase) + .endStatus() .build(); - IntegrationStatus status = new IntegrationStatus(); - status.setPhase(phase); - integration.setStatus(status); - k8sClient.resources(Integration.class, IntegrationList.class).inNamespace(CamelKSettings.getNamespace()).resource(integration).create(); Pod pod = new PodBuilder() diff --git a/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/IntegrationBuilderTest.java b/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/IntegrationBuilderTest.java deleted file mode 100644 index 712961a4..00000000 --- a/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/IntegrationBuilderTest.java +++ /dev/null @@ -1,109 +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; - -import java.io.IOException; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.citrusframework.spi.Resources; -import org.citrusframework.util.FileUtils; -import org.citrusframework.yaks.camelk.model.Integration; -import org.citrusframework.yaks.camelk.model.IntegrationSpec; -import org.citrusframework.yaks.kubernetes.KubernetesSupport; -import org.junit.Assert; -import org.junit.Test; -import org.springframework.util.StringUtils; - -public class IntegrationBuilderTest { - - @Test - public void shouldSanitizeIntegrationNames() { - Integration i = new Integration.Builder() - .name("SomeCamelCaseSource.java") - .source("from(\"timer:x\").log('${body}')") - .build(); - - Assert.assertEquals(i.getMetadata().getName(), "some-camel-case-source"); - Assert.assertEquals(i.getSpec().getSources().get(0).getName(), "SomeCamelCaseSource.java"); - - i = new Integration.Builder() - .name("ThisIsATest%&/$_!.java") - .source("from(\"timer:x\").log('${body}')") - .build(); - - Assert.assertEquals(i.getMetadata().getName(), "this-is-atest"); - } - - @Test - public void shouldSupportExplicitIntegrationNames() { - Integration i = new Integration.Builder() - .name("some-integration") - .source("SomeCamelCaseSource.java", "from(\"timer:x\").log('${body}')") - .build(); - - Assert.assertEquals(i.getMetadata().getName(), "some-integration"); - Assert.assertEquals(i.getSpec().getSources().get(0).getName(), "SomeCamelCaseSource.java"); - - i = new Integration.Builder() - .name("ThisIsATest%&/$_!.java") - .source("from(\"timer:x\").log('${body}')") - .build(); - - Assert.assertEquals(i.getMetadata().getName(), "this-is-atest"); - } - - @Test - public void buildComplexIntegrationTest() throws IOException { - Map traits = new HashMap<>(); - IntegrationSpec.TraitConfig quarkus = new IntegrationSpec.TraitConfig("enabled", true); - quarkus.add("native", "true"); - traits.put("quarkus", quarkus); - traits.put("route", new IntegrationSpec.TraitConfig("enabled", true)); - - IntegrationSpec.TraitConfig builder = new IntegrationSpec.TraitConfig("properties", Arrays.asList("quarkus.foo=bar", "quarkus.verbose=true")); - builder.add("verbose", true); - traits.put("builder", builder); - - List dependencies = Arrays.asList("mvn:fake.dependency:id:version-1", "camel:jackson"); - Integration i = new Integration.Builder() - .name("bar.groovy") - .source("from(\"timer:x\").log('${body}')") - .traits(traits) - .dependencies(dependencies) - .build(); - - final String json = KubernetesSupport.json().writeValueAsString(i); - Assert.assertEquals(StringUtils.trimAllWhitespace( - FileUtils.readToString(Resources.create("integration.json", IntegrationBuilderTest.class))), json); - } - - @Test - public void buildOpenApiIntegrationTest() throws IOException { - Integration i = new Integration.Builder() - .name("openapi.groovy") - .source("from(\"timer:x\").log('${body}')") - .openApi("openapi.yaml", FileUtils.readToString(FileUtils.getFileResource("classpath:openapi.yaml"))) - .build(); - - final String json = StringUtils.trimAllWhitespace(KubernetesSupport.json().writeValueAsString(i)); - Assert.assertEquals(StringUtils.trimAllWhitespace( - FileUtils.readToString(Resources.create("integration-api.json", IntegrationBuilderTest.class))), json); - } -} diff --git a/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/KameletBuilderTest.java b/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/KameletBuilderTest.java deleted file mode 100644 index e96049b0..00000000 --- a/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/KameletBuilderTest.java +++ /dev/null @@ -1,80 +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; - -import java.io.IOException; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.citrusframework.spi.Resources; -import org.citrusframework.util.FileUtils; -import org.citrusframework.yaks.camelk.model.Kamelet; -import org.citrusframework.yaks.camelk.model.KameletSpec; -import org.citrusframework.yaks.kubernetes.KubernetesSupport; -import org.junit.Assert; -import org.junit.Test; -import org.springframework.util.StringUtils; - -public class KameletBuilderTest { - - @Test - public void buildComplexKamelet() throws IOException { - Map dataTypes = new HashMap<>(); - dataTypes.put("out", new KameletSpec.DataTypesSpec("text", - new KameletSpec.DataTypeSpec("camel", "binary"), - new KameletSpec.DataTypeSpec("camel", "text"))); - - KameletSpec.Definition definition = new KameletSpec.Definition(); - definition.setTitle("Timer Source"); - definition.getProperties().put("period", new KameletSpec.Definition.PropertyConfig("Period", "integer", 1000, null)); - definition.getProperties().put("message", new KameletSpec.Definition.PropertyConfig("Message", "string", null, "hello world")); - definition.getRequired().add("message"); - - Kamelet kamelet = new Kamelet.Builder() - .name("time-source") - .addLabel(KameletSettings.KAMELET_TYPE_LABEL, "source") - .definition(definition) - .dataTypes(dataTypes) - .dependencies(Collections.singletonList("mvn:fake.dependency:id:version-1")) - .template("from:\n" + - " uri: timer:tick\n" + - " parameters:\n" + - " period: \"#property:period\"\n" + - " steps:\n" + - " - set-body:\n" + - " constant: \"{{message}}\"\n" + - " - to: \"kamelet:sink\"") - .build(); - - final String json = KubernetesSupport.json().writeValueAsString(kamelet); - Assert.assertEquals(StringUtils.trimAllWhitespace( - FileUtils.readToString(Resources.create("kamelet.json", KameletBuilderTest.class))), - StringUtils.trimAllWhitespace(json)); - } - - @Test - public void shouldDeserializeKamelet() throws IOException { - Kamelet deserialized = new ObjectMapper().readValue( - FileUtils.readToString(Resources.create("timer-source.kamelet.json")), Kamelet.class); - - Assert.assertNull(deserialized.getSpec().getFlow()); - Assert.assertNotNull(deserialized.getSpec().getTemplate()); - Assert.assertEquals(1L, deserialized.getSpec().getTemplate().size()); - } -} diff --git a/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/PipeBuilderTest.java b/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/PipeBuilderTest.java deleted file mode 100644 index 89fa0977..00000000 --- a/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/PipeBuilderTest.java +++ /dev/null @@ -1,93 +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; - -import java.io.IOException; - -import org.citrusframework.spi.Resources; -import org.citrusframework.util.FileUtils; -import org.citrusframework.yaks.camelk.model.Pipe; -import org.citrusframework.yaks.camelk.model.PipeSpec; -import org.citrusframework.yaks.camelk.model.v1alpha1.KameletBinding; -import org.citrusframework.yaks.kafka.KafkaSettings; -import org.citrusframework.yaks.kubernetes.KubernetesSupport; -import org.junit.Assert; -import org.junit.Test; -import org.springframework.util.StringUtils; - -public class PipeBuilderTest { - - @Test - public void buildComplexBinding() throws IOException { - PipeSpec.Endpoint.ObjectReference sourceRef = new PipeSpec.Endpoint.ObjectReference(); - sourceRef.setName("timer-source"); - sourceRef.setKind("Kamelet"); - sourceRef.setNamespace(CamelKSettings.getNamespace()); - - PipeSpec.Endpoint source = new PipeSpec.Endpoint(sourceRef); - source.getProperties().put("message", "Hello World"); - source.getDataTypes().put("out", new PipeSpec.Endpoint.DataTypeRef("camel", "string")); - - PipeSpec.Endpoint.ObjectReference sinkRef = new PipeSpec.Endpoint.ObjectReference(); - sinkRef.setName("hello-topic"); - sinkRef.setKind("KafkaTopic"); - sinkRef.setNamespace(KafkaSettings.getNamespace()); - - PipeSpec.Endpoint sink = new PipeSpec.Endpoint(sinkRef); - - KameletBinding pipe = new KameletBinding.Builder() - .name("time-source-kafka") - .source(source) - .sink(sink) - .build(); - - final String json = KubernetesSupport.json().writeValueAsString(pipe); - Assert.assertEquals(StringUtils.trimAllWhitespace( - FileUtils.readToString(Resources.create("kamelet-binding.json", PipeBuilderTest.class))), - StringUtils.trimAllWhitespace(json)); - } - - @Test - public void buildComplexPipe() throws IOException { - PipeSpec.Endpoint.ObjectReference sourceRef = new PipeSpec.Endpoint.ObjectReference(); - sourceRef.setName("timer-source"); - sourceRef.setKind("Kamelet"); - sourceRef.setNamespace(CamelKSettings.getNamespace()); - - PipeSpec.Endpoint source = new PipeSpec.Endpoint(sourceRef); - source.getProperties().put("message", "Hello World"); - source.getDataTypes().put("out", new PipeSpec.Endpoint.DataTypeRef("camel", "string")); - - PipeSpec.Endpoint.ObjectReference sinkRef = new PipeSpec.Endpoint.ObjectReference(); - sinkRef.setName("hello-topic"); - sinkRef.setKind("KafkaTopic"); - sinkRef.setNamespace(KafkaSettings.getNamespace()); - - PipeSpec.Endpoint sink = new PipeSpec.Endpoint(sinkRef); - - Pipe pipe = new Pipe.Builder() - .name("time-source-kafka") - .source(source) - .sink(sink) - .build(); - - final String json = KubernetesSupport.json().writeValueAsString(pipe); - Assert.assertEquals(StringUtils.trimAllWhitespace( - FileUtils.readToString(Resources.create("pipe.json", PipeBuilderTest.class))), - StringUtils.trimAllWhitespace(json)); - } -} diff --git a/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/actions/integration/CreateIntegrationActionTest.java b/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/actions/integration/CreateIntegrationActionTest.java index 2e0e955e..0d5aae00 100644 --- a/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/actions/integration/CreateIntegrationActionTest.java +++ b/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/actions/integration/CreateIntegrationActionTest.java @@ -16,23 +16,21 @@ package org.citrusframework.yaks.camelk.actions.integration; -import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; -import org.citrusframework.context.TestContext; -import org.citrusframework.context.TestContextFactory; import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.server.mock.KubernetesCrudDispatcher; import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer; import io.fabric8.mockwebserver.Context; import okhttp3.mockwebserver.MockWebServer; +import org.apache.camel.v1.Integration; +import org.citrusframework.context.TestContext; +import org.citrusframework.context.TestContextFactory; import org.citrusframework.yaks.YaksClusterType; import org.citrusframework.yaks.camelk.jbang.ProcessAndOutput; -import org.citrusframework.yaks.camelk.model.Integration; import org.citrusframework.yaks.kubernetes.KubernetesSettings; import org.junit.Assert; import org.junit.Test; @@ -63,22 +61,20 @@ public void shouldCreateIntegrationWithTraits() { .client(kubernetesClient) .integration("helloworld") .source("from('timer:tick?period=1000').setBody().constant('Hello world from Camel K!').to('log:info')") - .traits("quarkus.enabled=true,quarkus.native=true,route.enabled=true,openapi.configmaps=[spec]") + .traits("quarkus.enabled=true,quarkus.nativeBaseImage=java-native,route.enabled=true,openapi.configmaps=[spec]") .build(); action.execute(context); Integration integration = kubernetesClient.resources(Integration.class).inNamespace(KubernetesSettings.getNamespace()).withName("helloworld").get(); - Assert.assertTrue(integration.getSpec().getTraits().containsKey("quarkus")); - Assert.assertEquals(2, integration.getSpec().getTraits().get("quarkus").getConfiguration().size()); - Assert.assertEquals(true, integration.getSpec().getTraits().get("quarkus").getConfiguration().get("enabled")); - Assert.assertEquals("true", integration.getSpec().getTraits().get("quarkus").getConfiguration().get("native")); - Assert.assertTrue(integration.getSpec().getTraits().containsKey("route")); - Assert.assertEquals(1, integration.getSpec().getTraits().get("route").getConfiguration().size()); - Assert.assertEquals(true, integration.getSpec().getTraits().get("route").getConfiguration().get("enabled")); - Assert.assertTrue(integration.getSpec().getTraits().containsKey("openapi")); - Assert.assertEquals(1, integration.getSpec().getTraits().get("openapi").getConfiguration().size()); - Assert.assertEquals(Collections.singletonList("spec"), integration.getSpec().getTraits().get("openapi").getConfiguration().get("configmaps")); + Assert.assertNotNull(integration.getSpec().getTraits().getQuarkus()); + Assert.assertTrue(integration.getSpec().getTraits().getQuarkus().getEnabled()); + Assert.assertEquals("java-native", integration.getSpec().getTraits().getQuarkus().getNativeBaseImage()); + Assert.assertNotNull(integration.getSpec().getTraits().getRoute()); + Assert.assertTrue(integration.getSpec().getTraits().getRoute().getEnabled()); + Assert.assertNotNull(integration.getSpec().getTraits().getOpenapi()); + Assert.assertEquals(1L, integration.getSpec().getTraits().getOpenapi().getConfigmaps().size()); + Assert.assertEquals("spec", integration.getSpec().getTraits().getOpenapi().getConfigmaps().get(0)); } @Test @@ -88,7 +84,7 @@ public void shouldCreateIntegrationWithTraitModeline() { .integration("foo") .fileName("foo.groovy") .source("// camel-k: trait=quarkus.enabled=true\n" + - "// camel-k: trait=quarkus.native=true\n" + + "// camel-k: trait=quarkus.nativeBaseImage=native-java\n" + "// camel-k: trait=route.enabled=true\n" + "// camel-k: trait=container.port=8443\n" + "from('timer:tick?period=1000').setBody().constant('Hello world from Camel K!').to('log:info')") @@ -97,15 +93,12 @@ public void shouldCreateIntegrationWithTraitModeline() { action.execute(context); Integration integration = kubernetesClient.resources(Integration.class).inNamespace(KubernetesSettings.getNamespace()).withName("foo").get(); - Assert.assertTrue(integration.getSpec().getTraits().containsKey("quarkus")); - Assert.assertEquals(2, integration.getSpec().getTraits().get("quarkus").getConfiguration().size()); - Assert.assertEquals(true, integration.getSpec().getTraits().get("quarkus").getConfiguration().get("enabled")); - Assert.assertEquals("true", integration.getSpec().getTraits().get("quarkus").getConfiguration().get("native")); - Assert.assertTrue(integration.getSpec().getTraits().containsKey("route")); - Assert.assertEquals(1, integration.getSpec().getTraits().get("route").getConfiguration().size()); - Assert.assertEquals(true, integration.getSpec().getTraits().get("route").getConfiguration().get("enabled")); - Assert.assertEquals(1, integration.getSpec().getTraits().get("container").getConfiguration().size()); - Assert.assertEquals(8443, integration.getSpec().getTraits().get("container").getConfiguration().get("port")); + Assert.assertNotNull(integration.getSpec().getTraits().getQuarkus()); + Assert.assertTrue(integration.getSpec().getTraits().getQuarkus().getEnabled()); + Assert.assertEquals("native-java", integration.getSpec().getTraits().getQuarkus().getNativeBaseImage()); + Assert.assertNotNull(integration.getSpec().getTraits().getRoute()); + Assert.assertTrue(integration.getSpec().getTraits().getRoute().getEnabled()); + Assert.assertEquals(8443L, integration.getSpec().getTraits().getContainer().getPort().longValue()); } @Test @@ -122,11 +115,8 @@ public void shouldCreateIntegrationWithBuildProperties() { action.execute(context); Integration integration = kubernetesClient.resources(Integration.class).inNamespace(KubernetesSettings.getNamespace()).withName("helloworld").get(); - Assert.assertEquals(1, integration.getSpec().getTraits().size()); - Assert.assertTrue(integration.getSpec().getTraits().containsKey("builder")); - Assert.assertEquals(1, integration.getSpec().getTraits().get("builder").getConfiguration().size()); - Assert.assertEquals(ArrayList.class, integration.getSpec().getTraits().get("builder").getConfiguration().get("properties").getClass()); - List values = (List) integration.getSpec().getTraits().get("builder").getConfiguration().get("properties"); + Assert.assertNotNull(integration.getSpec().getTraits().getBuilder()); + List values = integration.getSpec().getTraits().getBuilder().getProperties(); Assert.assertEquals(2, values.size()); Assert.assertEquals("quarkus.foo=bar", values.get(0)); Assert.assertEquals("quarkus.verbose=true", values.get(1)); @@ -146,11 +136,8 @@ public void shouldCreateIntegrationWithBuildPropertyModeline() { action.execute(context); Integration integration = kubernetesClient.resources(Integration.class).inNamespace(KubernetesSettings.getNamespace()).withName("foo").get(); - Assert.assertEquals(1, integration.getSpec().getTraits().size()); - Assert.assertTrue(integration.getSpec().getTraits().containsKey("builder")); - Assert.assertEquals(1, integration.getSpec().getTraits().get("builder").getConfiguration().size()); - Assert.assertEquals(ArrayList.class, integration.getSpec().getTraits().get("builder").getConfiguration().get("properties").getClass()); - List values = (List) integration.getSpec().getTraits().get("builder").getConfiguration().get("properties"); + Assert.assertNotNull(integration.getSpec().getTraits().getBuilder()); + List values = integration.getSpec().getTraits().getBuilder().getProperties(); Assert.assertEquals(2, values.size()); Assert.assertEquals("quarkus.foo=bar", values.get(0)); Assert.assertEquals("quarkus.verbose=true", values.get(1)); @@ -170,11 +157,8 @@ public void shouldCreateIntegrationWithEnvVars() { action.execute(context); Integration integration = kubernetesClient.resources(Integration.class).inNamespace(KubernetesSettings.getNamespace()).withName("helloworld").get(); - Assert.assertEquals(1, integration.getSpec().getTraits().size()); - Assert.assertTrue(integration.getSpec().getTraits().containsKey("environment")); - Assert.assertEquals(1, integration.getSpec().getTraits().get("environment").getConfiguration().size()); - Assert.assertEquals(ArrayList.class, integration.getSpec().getTraits().get("environment").getConfiguration().get("vars").getClass()); - List values = (List) integration.getSpec().getTraits().get("environment").getConfiguration().get("vars"); + Assert.assertNotNull(integration.getSpec().getTraits().getEnvironment()); + List values = integration.getSpec().getTraits().getEnvironment().getVars(); Assert.assertEquals(2, values.size()); Assert.assertEquals("QUARKUS_FOO=bar", values.get(0)); Assert.assertEquals("QUARKUS_VERBOSE=true", values.get(1)); @@ -194,11 +178,8 @@ public void shouldCreateIntegrationWithEnvVarModeline() { action.execute(context); Integration integration = kubernetesClient.resources(Integration.class).inNamespace(KubernetesSettings.getNamespace()).withName("foo").get(); - Assert.assertEquals(1, integration.getSpec().getTraits().size()); - Assert.assertTrue(integration.getSpec().getTraits().containsKey("environment")); - Assert.assertEquals(1, integration.getSpec().getTraits().get("environment").getConfiguration().size()); - Assert.assertEquals(ArrayList.class, integration.getSpec().getTraits().get("environment").getConfiguration().get("vars").getClass()); - List values = (List) integration.getSpec().getTraits().get("environment").getConfiguration().get("vars"); + Assert.assertNotNull(integration.getSpec().getTraits().getEnvironment()); + List values = integration.getSpec().getTraits().getEnvironment().getVars(); Assert.assertEquals(2, values.size()); Assert.assertEquals("QUARKUS_FOO=bar", values.get(0)); Assert.assertEquals("QUARKUS_VERBOSE=true", values.get(1)); @@ -226,7 +207,7 @@ public void shouldCreateIntegrationWithConfigModeline() { } @Test - public void shouldCreateLocalJBangIntegration() { + public void shouldCreateLocalIntegration() { camel().version(); CreateIntegrationAction action = new CreateIntegrationAction.Builder() .client(kubernetesClient) diff --git a/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/actions/kamelet/CreateKameletBindingActionTest.java b/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/actions/kamelet/CreateKameletBindingActionTest.java new file mode 100644 index 00000000..cfa0ae4f --- /dev/null +++ b/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/actions/kamelet/CreateKameletBindingActionTest.java @@ -0,0 +1,122 @@ +/* + * 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.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.server.mock.KubernetesCrudDispatcher; +import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer; +import io.fabric8.mockwebserver.Context; +import okhttp3.mockwebserver.MockWebServer; +import org.apache.camel.v1alpha1.KameletBinding; +import org.citrusframework.context.TestContext; +import org.citrusframework.context.TestContextFactory; +import org.citrusframework.spi.Resources; +import org.citrusframework.yaks.YaksClusterType; +import org.citrusframework.yaks.camelk.CamelKSettings; +import org.citrusframework.yaks.camelk.actions.integration.CreateIntegrationActionTest; +import org.citrusframework.yaks.kubernetes.KubernetesSettings; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static org.awaitility.Awaitility.await; +import static org.citrusframework.yaks.camelk.jbang.CamelJBang.camel; + +public class CreateKameletBindingActionTest { + + /** Logger */ + private static final Logger LOG = LoggerFactory.getLogger(CreateIntegrationActionTest.class); + + private final KubernetesMockServer k8sServer = new KubernetesMockServer(new Context(), new MockWebServer(), + new HashMap<>(), new KubernetesCrudDispatcher(), false); + + private final KubernetesClient kubernetesClient = k8sServer.createClient(); + + private final TestContext context = TestContextFactory.newInstance().getObject(); + + @BeforeClass + public static void setup() { + camel().version(); + } + + @Test + public void shouldCreateBinding() { + CreateKameletBindingAction action = new CreateKameletBindingAction.Builder() + .client(kubernetesClient) + .apiVersion(CamelKSettings.V1ALPHA1) + .binding("kafka-source-binding") + .resource(Resources.fromClasspath("kafka-source-binding.yaml")) + .build(); + + context.setVariable("YAKS_NAMESPACE", "default"); + context.setVariable("bootstrap.server.host", "my-cluster-kafka-bootstrap"); + context.setVariable("bootstrap.server.port", "9092"); + context.setVariable("topic", "my-topic"); + + action.execute(context); + + KameletBinding binding = kubernetesClient.resources(KameletBinding.class).inNamespace(KubernetesSettings.getNamespace()).withName("kafka-source-binding").get(); + Assert.assertNotNull(binding.getSpec().getSource().getRef()); + Assert.assertEquals("kafka-source", binding.getSpec().getSource().getRef().getName()); + Assert.assertNotNull(binding.getSpec().getSource().getProperties()); + Assert.assertEquals(6L, binding.getSpec().getSource().getProperties().getAdditionalProperties().size()); + Assert.assertNotNull(binding.getSpec().getSink().getUri()); + } + + @Test + public void shouldCreateLocalBinding() { + System.setProperty("yaks.jbang.camel.dump.integration.output", "true"); + + CreateKameletBindingAction action = new CreateKameletBindingAction.Builder() + .client(kubernetesClient) + .apiVersion(CamelKSettings.V1ALPHA1) + .binding("timer-to-log-binding") + .clusterType(YaksClusterType.LOCAL) + .resource(Resources.fromClasspath("timer-to-log-binding.yaml")) + .build(); + + action.execute(context); + + Assert.assertNotNull(context.getVariable("timer-to-log-binding:pid")); + + Long pid = context.getVariable("timer-to-log-binding:pid", Long.class); + + try { + await().atMost(30000L, TimeUnit.MILLISECONDS).until(() -> { + Map integration = camel().get(pid); + + if (integration.isEmpty() || integration.get("STATUS").equals("Starting")) { + LOG.info("Waiting for Camel integration to start ..."); + return false; + } + + Assert.assertEquals("timer-to-log-binding", integration.get("NAME")); + Assert.assertEquals("Running", integration.get("STATUS")); + + return true; + }); + } finally { + camel().stop(pid); + } + } +} diff --git a/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/actions/kamelet/CreatePipeActionTest.java b/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/actions/kamelet/CreatePipeActionTest.java index 7bdd6e38..9a936464 100644 --- a/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/actions/kamelet/CreatePipeActionTest.java +++ b/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/actions/kamelet/CreatePipeActionTest.java @@ -20,19 +20,18 @@ import java.util.Map; import java.util.concurrent.TimeUnit; -import org.citrusframework.context.TestContext; -import org.citrusframework.context.TestContextFactory; import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.server.mock.KubernetesCrudDispatcher; import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer; import io.fabric8.mockwebserver.Context; import okhttp3.mockwebserver.MockWebServer; +import org.apache.camel.v1.Pipe; +import org.citrusframework.context.TestContext; +import org.citrusframework.context.TestContextFactory; import org.citrusframework.spi.Resources; import org.citrusframework.yaks.YaksClusterType; import org.citrusframework.yaks.camelk.CamelKSettings; import org.citrusframework.yaks.camelk.actions.integration.CreateIntegrationActionTest; -import org.citrusframework.yaks.camelk.model.v1alpha1.KameletBinding; -import org.citrusframework.yaks.camelk.model.Pipe; import org.citrusframework.yaks.kubernetes.KubernetesSettings; import org.junit.Assert; import org.junit.BeforeClass; @@ -61,41 +60,22 @@ public static void setup() { } @Test - public void shouldCreateBinding() { - CreatePipeAction action = new CreatePipeAction.Builder() - .client(kubernetesClient) - .apiVersion(CamelKSettings.V1ALPHA1) - .binding("kafka-source-binding") - .resource(Resources.fromClasspath("kafka-source-binding.yaml")) - .build(); - - context.setVariable("YAKS_NAMESPACE", "default"); - context.setVariable("bootstrap.server.host", "my-cluster-kafka-bootstrap"); - context.setVariable("bootstrap.server.port", "9092"); - context.setVariable("topic", "my-topic"); - - action.execute(context); + public void shouldCreateLocalPipe() { + System.setProperty("yaks.jbang.camel.dump.integration.output", "true"); - KameletBinding binding = kubernetesClient.resources(KameletBinding.class).inNamespace(KubernetesSettings.getNamespace()).withName("kafka-source-binding").get(); - Assert.assertNotNull(binding.getSpec().getSource().getRef()); - Assert.assertNotNull(binding.getSpec().getSink().getUri()); - } - - @Test - public void shouldCreateLocalJBangBinding() { CreatePipeAction action = new CreatePipeAction.Builder() .client(kubernetesClient) - .apiVersion(CamelKSettings.V1ALPHA1) - .binding("timer-to-log-binding") + .apiVersion(CamelKSettings.V1) + .pipe("timer-to-log-pipe") .clusterType(YaksClusterType.LOCAL) - .resource(Resources.fromClasspath("timer-to-log-binding.yaml")) + .resource(Resources.fromClasspath("timer-to-log-pipe.yaml")) .build(); action.execute(context); - Assert.assertNotNull(context.getVariable("timer-to-log-binding:pid")); + Assert.assertNotNull(context.getVariable("timer-to-log-pipe:pid")); - Long pid = context.getVariable("timer-to-log-binding:pid", Long.class); + Long pid = context.getVariable("timer-to-log-pipe:pid", Long.class); try { await().atMost(30000L, TimeUnit.MILLISECONDS).until(() -> { @@ -106,7 +86,7 @@ public void shouldCreateLocalJBangBinding() { return false; } - Assert.assertEquals("timer-to-log-binding", integration.get("NAME")); + Assert.assertEquals("timer-to-log-pipe", integration.get("NAME")); Assert.assertEquals("Running", integration.get("STATUS")); return true; @@ -135,6 +115,9 @@ public void shouldCreatePipe() { Pipe pipe = kubernetesClient.resources(Pipe.class).inNamespace(KubernetesSettings.getNamespace()).withName("kafka-source-pipe").get(); Assert.assertNotNull(pipe); Assert.assertNotNull(pipe.getSpec().getSource().getRef()); + Assert.assertEquals("kafka-source", pipe.getSpec().getSource().getRef().getName()); + Assert.assertNotNull(pipe.getSpec().getSource().getProperties()); + Assert.assertEquals(6L, pipe.getSpec().getSource().getProperties().getAdditionalProperties().size()); Assert.assertNotNull(pipe.getSpec().getSink().getUri()); } } diff --git a/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/actions/kamelet/DeleteKameletBindingActionTest.java b/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/actions/kamelet/DeleteKameletBindingActionTest.java new file mode 100644 index 00000000..adacd633 --- /dev/null +++ b/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/actions/kamelet/DeleteKameletBindingActionTest.java @@ -0,0 +1,103 @@ +/* + * 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.Path; +import java.util.HashMap; +import java.util.concurrent.TimeUnit; + +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.server.mock.KubernetesCrudDispatcher; +import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer; +import io.fabric8.mockwebserver.Context; +import okhttp3.mockwebserver.MockWebServer; +import org.citrusframework.context.TestContext; +import org.citrusframework.context.TestContextFactory; +import org.citrusframework.yaks.YaksClusterType; +import org.citrusframework.yaks.camelk.CamelKSettings; +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.core.io.ClassPathResource; + +import static org.awaitility.Awaitility.await; +import static org.citrusframework.yaks.camelk.jbang.CamelJBang.camel; + +public class DeleteKameletBindingActionTest { + + private final KubernetesMockServer k8sServer = new KubernetesMockServer(new Context(), new MockWebServer(), + new HashMap<>(), new KubernetesCrudDispatcher(), false); + + private final KubernetesClient kubernetesClient = k8sServer.createClient(); + + private final TestContext context = TestContextFactory.newInstance().getObject(); + + private static Path sampleBinding; + + @BeforeClass + public static void setup() throws IOException { + sampleBinding = new ClassPathResource("timer-to-log-binding.yaml").getFile().toPath(); + camel().version(); + } + + @Test + public void shouldDeleteLocalBinding() { + Long pid = camel().run("timer-to-log-binding.yaml", sampleBinding).getCamelProcessId(); + + try { + await().atMost(30000L, TimeUnit.MILLISECONDS).until(() -> !camel().get(pid).isEmpty()); + + DeleteKameletBindingAction action = new DeleteKameletBindingAction.Builder() + .client(kubernetesClient) + .apiVersion(CamelKSettings.V1ALPHA1) + .binding("timer-to-log-binding.yaml") + .clusterType(YaksClusterType.LOCAL) + .build(); + + context.setVariable("timer-to-log-binding.yaml:pid", pid); + + action.execute(context); + + await().atMost(15000L, TimeUnit.MILLISECONDS).until(() -> camel().get(pid).isEmpty()); + } finally { + camel().stop(pid); + } + } + + @Test + public void shouldDeleteLocalBindingByName() { + Long pid = camel().run("timer-to-log-binding.yaml", sampleBinding).getCamelProcessId(); + + try { + await().atMost(30000L, TimeUnit.MILLISECONDS).until(() -> !camel().get(pid).isEmpty()); + + DeleteKameletBindingAction action = new DeleteKameletBindingAction.Builder() + .client(kubernetesClient) + .apiVersion(CamelKSettings.V1ALPHA1) + .binding("timer-to-log-binding.yaml") + .clusterType(YaksClusterType.LOCAL) + .build(); + + action.execute(context); + + await().atMost(15000L, TimeUnit.MILLISECONDS).until(() -> camel().get(pid).isEmpty()); + } finally { + camel().stop(pid); + } + } +} diff --git a/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/actions/kamelet/DeletePipeActionTest.java b/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/actions/kamelet/DeletePipeActionTest.java index 4a2b1064..9953321b 100644 --- a/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/actions/kamelet/DeletePipeActionTest.java +++ b/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/actions/kamelet/DeletePipeActionTest.java @@ -47,17 +47,17 @@ public class DeletePipeActionTest { private final TestContext context = TestContextFactory.newInstance().getObject(); - private static Path sampleBinding; + private static Path samplePipe; @BeforeClass public static void setup() throws IOException { - sampleBinding = new ClassPathResource("timer-to-log-binding.yaml").getFile().toPath(); + samplePipe = new ClassPathResource("timer-to-log-pipe.yaml").getFile().toPath(); camel().version(); } @Test - public void shouldDeleteLocalJBangBinding() { - Long pid = camel().run("timer-to-log-binding.yaml", sampleBinding).getCamelProcessId(); + public void shouldDeleteLocalPipe() { + Long pid = camel().run("timer-to-log-pipe.yaml", samplePipe).getCamelProcessId(); try { await().atMost(30000L, TimeUnit.MILLISECONDS).until(() -> !camel().get(pid).isEmpty()); @@ -65,11 +65,11 @@ public void shouldDeleteLocalJBangBinding() { DeletePipeAction action = new DeletePipeAction.Builder() .client(kubernetesClient) .apiVersion(CamelKSettings.V1ALPHA1) - .binding("timer-to-log-binding.yaml") + .pipe("timer-to-log-pipe.yaml") .clusterType(YaksClusterType.LOCAL) .build(); - context.setVariable("timer-to-log-binding.yaml:pid", pid); + context.setVariable("timer-to-log-pipe.yaml:pid", pid); action.execute(context); @@ -80,8 +80,8 @@ public void shouldDeleteLocalJBangBinding() { } @Test - public void shouldDeleteLocalJBangBindingByName() { - Long pid = camel().run("timer-to-log-binding.yaml", sampleBinding).getCamelProcessId(); + public void shouldDeleteLocalPipeByName() { + Long pid = camel().run("timer-to-log-pipe.yaml", samplePipe).getCamelProcessId(); try { await().atMost(30000L, TimeUnit.MILLISECONDS).until(() -> !camel().get(pid).isEmpty()); @@ -89,7 +89,7 @@ public void shouldDeleteLocalJBangBindingByName() { DeletePipeAction action = new DeletePipeAction.Builder() .client(kubernetesClient) .apiVersion(CamelKSettings.V1ALPHA1) - .binding("timer-to-log-binding.yaml") + .pipe("timer-to-log-pipe.yaml") .clusterType(YaksClusterType.LOCAL) .build(); diff --git a/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/actions/kamelet/VerifyKameletBindingActionTest.java b/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/actions/kamelet/VerifyKameletBindingActionTest.java new file mode 100644 index 00000000..63803860 --- /dev/null +++ b/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/actions/kamelet/VerifyKameletBindingActionTest.java @@ -0,0 +1,76 @@ +/* + * 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.Path; +import java.util.HashMap; + +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.server.mock.KubernetesCrudDispatcher; +import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer; +import io.fabric8.mockwebserver.Context; +import okhttp3.mockwebserver.MockWebServer; +import org.citrusframework.context.TestContext; +import org.citrusframework.context.TestContextFactory; +import org.citrusframework.yaks.YaksClusterType; +import org.citrusframework.yaks.camelk.jbang.ProcessAndOutput; +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.core.io.ClassPathResource; + +import static org.citrusframework.yaks.camelk.jbang.CamelJBang.camel; + +public class VerifyKameletBindingActionTest { + + private final KubernetesMockServer k8sServer = new KubernetesMockServer(new Context(), new MockWebServer(), + new HashMap<>(), new KubernetesCrudDispatcher(), false); + + private final KubernetesClient kubernetesClient = k8sServer.createClient(); + + private final TestContext context = TestContextFactory.newInstance().getObject(); + + private static Path sampleBinding; + + @BeforeClass + public static void setup() throws IOException { + sampleBinding = new ClassPathResource("timer-to-log-binding.yaml").getFile().toPath(); + camel().version(); + } + + @Test + public void shouldVerifyLocalBinding() { + ProcessAndOutput pao = camel().run("timer-to-log-binding", sampleBinding); + Long pid = pao.getCamelProcessId(); + + try { + VerifyKameletBindingAction action = new VerifyKameletBindingAction.Builder() + .client(kubernetesClient) + .isAvailable("timer-to-log-binding") + .clusterType(YaksClusterType.LOCAL) + .maxAttempts(10) + .build(); + + context.setVariable("timer-to-log-binding:pid", pid); + context.setVariable("timer-to-log-binding:process:" + pid, pao); + + action.execute(context); + } finally { + camel().stop(pid); + } + } +} diff --git a/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/actions/kamelet/VerifyPipeActionTest.java b/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/actions/kamelet/VerifyPipeActionTest.java index 355c4bbb..91582aa0 100644 --- a/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/actions/kamelet/VerifyPipeActionTest.java +++ b/java/steps/yaks-camel-k/src/test/java/org/citrusframework/yaks/camelk/actions/kamelet/VerifyPipeActionTest.java @@ -44,29 +44,29 @@ public class VerifyPipeActionTest { private final TestContext context = TestContextFactory.newInstance().getObject(); - private static Path sampleBinding; + private static Path samplePipe; @BeforeClass public static void setup() throws IOException { - sampleBinding = new ClassPathResource("timer-to-log-binding.yaml").getFile().toPath(); + samplePipe = new ClassPathResource("timer-to-log-pipe.yaml").getFile().toPath(); camel().version(); } @Test - public void shouldVerifyLocalJBangIntegration() { - ProcessAndOutput pao = camel().run("timer-to-log-binding", sampleBinding); + public void shouldVerifyLocalPipe() { + ProcessAndOutput pao = camel().run("timer-to-log-pipe", samplePipe); Long pid = pao.getCamelProcessId(); try { VerifyPipeAction action = new VerifyPipeAction.Builder() .client(kubernetesClient) - .isAvailable("timer-to-log-binding") + .isAvailable("timer-to-log-pipe") .clusterType(YaksClusterType.LOCAL) .maxAttempts(10) .build(); - context.setVariable("timer-to-log-binding:pid", pid); - context.setVariable("timer-to-log-binding:process:" + pid, pao); + context.setVariable("timer-to-log-pipe:pid", pid); + context.setVariable("timer-to-log-pipe:process:" + pid, pao); action.execute(context); } finally { diff --git a/java/steps/yaks-camel-k/src/test/resources/kafka-source-pipe.yaml b/java/steps/yaks-camel-k/src/test/resources/kafka-source-pipe.yaml index 6697c7d7..fb0de789 100644 --- a/java/steps/yaks-camel-k/src/test/resources/kafka-source-pipe.yaml +++ b/java/steps/yaks-camel-k/src/test/resources/kafka-source-pipe.yaml @@ -22,7 +22,7 @@ spec: source: ref: kind: Kamelet - apiVersion: camel.apache.org/v1alpha1 + apiVersion: camel.apache.org/v1 name: kafka-source properties: bootstrapServers: ${bootstrap.server.host}.${YAKS_NAMESPACE}:${bootstrap.server.port} diff --git a/java/steps/yaks-camel-k/src/test/resources/org/citrusframework/yaks/camelk/camelk.kamelet.feature b/java/steps/yaks-camel-k/src/test/resources/org/citrusframework/yaks/camelk/camelk.kamelet.feature index 2a46e4ae..2bad9d17 100644 --- a/java/steps/yaks-camel-k/src/test/resources/org/citrusframework/yaks/camelk/camelk.kamelet.feature +++ b/java/steps/yaks-camel-k/src/test/resources/org/citrusframework/yaks/camelk/camelk.kamelet.feature @@ -48,29 +48,3 @@ from: Given load Kamelet timer-source.kamelet.yaml And load Camel K integration timer-to-log.groovy Then Kamelet timer-source should be available - - Scenario: Bind Kamelet to Kafka - Given KameletBinding source properties - | message | Hello World | - And bind Kamelet timer-source to Kafka topic hello-topic - When create KameletBinding timer-source-kafka - Then KameletBinding timer-source-kafka should be available - - Scenario: Bind Kamelet to Knative - Given KameletBinding source properties - | message | Hello World | - And bind Kamelet timer-source to Knative channel hello-topic of kind InMemoryChannel - When create KameletBinding timer-source-knative - Then KameletBinding timer-source-knative should be available - - Scenario: Bind Kamelet to Uri - Given KameletBinding source properties - | message | Hello World | - And bind Kamelet timer-source to uri https://greeting-service.svc.cluster.local - When create KameletBinding timer-source-uri - Then KameletBinding timer-source-uri should be available - - Scenario: Create KameletBinding from file - Given load KameletBinding kamelet-binding.yaml - Then KameletBinding timer-source-binding should be available - diff --git a/java/steps/yaks-camel-k/src/test/resources/org/citrusframework/yaks/camelk/camelk.kameletbinding.feature b/java/steps/yaks-camel-k/src/test/resources/org/citrusframework/yaks/camelk/camelk.kameletbinding.feature new file mode 100644 index 00000000..1119b1da --- /dev/null +++ b/java/steps/yaks-camel-k/src/test/resources/org/citrusframework/yaks/camelk/camelk.kameletbinding.feature @@ -0,0 +1,30 @@ +Feature: KameletBinding + + Scenario: Bind Kamelet to Kafka + Given KameletBinding source properties + | message | Hello World | + Given KameletBinding event source Kamelet timer-source + And KameletBinding event sink Kafka topic hello-topic + When create KameletBinding timer-source-kafka + Then KameletBinding timer-source-kafka should be available + + Scenario: Bind Kamelet to Knative channel + Given KameletBinding source properties + | message | Hello World | + Given KameletBinding event source Kamelet timer-source + And KameletBinding event sink Knative channel hello-topic of kind InMemoryChannel + When create KameletBinding timer-source-knative + Then KameletBinding timer-source-knative should be available + + Scenario: Bind Kamelet to Uri + Given KameletBinding source properties + | message | Hello World | + Given KameletBinding event source Kamelet timer-source + And KameletBinding event sink uri https://greeting-service.svc.cluster.local + When create KameletBinding timer-source-uri + Then KameletBinding timer-source-uri should be available + + Scenario: Create KameletBinding from file + Given load KameletBinding kamelet-binding.yaml + Then KameletBinding timer-source-binding should be available + diff --git a/java/steps/yaks-camel-k/src/test/resources/org/citrusframework/yaks/camelk/camelk.pipe.feature b/java/steps/yaks-camel-k/src/test/resources/org/citrusframework/yaks/camelk/camelk.pipe.feature new file mode 100644 index 00000000..2b001464 --- /dev/null +++ b/java/steps/yaks-camel-k/src/test/resources/org/citrusframework/yaks/camelk/camelk.pipe.feature @@ -0,0 +1,28 @@ +Feature: Pipe + + Scenario: Bind Kamelet to Kafka + Given Pipe source properties + | message | Hello World | + And bind Kamelet timer-source to Kafka topic hello-topic + When create Pipe timer-source-kafka + Then Pipe timer-source-kafka should be available + + Scenario: Bind Kamelet to Knative + Given Pipe source properties + | message | Hello World | + And bind Kamelet timer-source to Knative channel hello-topic of kind InMemoryChannel + When create Pipe timer-source-knative + Then Pipe timer-source-knative should be available + + Scenario: Bind Kamelet to Uri + Given Pipe source properties + | message | Hello World | + And bind Kamelet timer-source to uri https://greeting-service.svc.cluster.local + When create Pipe timer-source-uri + Then Pipe timer-source-uri should be available + + Scenario: Create Pipe from file + Given Kamelet API version v1alpha1 + Given load Pipe pipe.yaml + Then Pipe timer-source-pipe should be available + diff --git a/java/steps/yaks-camel-k/src/test/resources/org/citrusframework/yaks/camelk/integration.json b/java/steps/yaks-camel-k/src/test/resources/org/citrusframework/yaks/camelk/integration.json deleted file mode 100644 index 342189ca..00000000 --- a/java/steps/yaks-camel-k/src/test/resources/org/citrusframework/yaks/camelk/integration.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "apiVersion": "camel.apache.org/v1", - "kind": "Integration", - "metadata": { - "name": "bar" - }, - "spec": { - "sources": [ - { - "name": "bar.groovy", - "content": "from(\"timer:x\").log('${body}')" - } - ], - "dependencies": [ - "mvn:fake.dependency:id:version-1", - "camel:jackson" - ], - "traits": { - "route": { - "configuration": { - "enabled": true - } - }, - "quarkus": { - "configuration": { - "native": "true", - "enabled": true - } - }, - "builder":{ - "configuration": { - "properties": ["quarkus.foo=bar","quarkus.verbose=true"], - "verbose": true - } - } - } - } -} diff --git a/java/steps/yaks-camel-k/src/test/resources/org/citrusframework/yaks/camelk/kamelet-binding.json b/java/steps/yaks-camel-k/src/test/resources/org/citrusframework/yaks/camelk/kamelet-binding.json deleted file mode 100644 index 4983af69..00000000 --- a/java/steps/yaks-camel-k/src/test/resources/org/citrusframework/yaks/camelk/kamelet-binding.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "apiVersion": "camel.apache.org/v1alpha1", - "kind": "KameletBinding", - "metadata": { - "name": "time-source-kafka" - }, - "spec": { - "source": { - "ref": { - "name": "timer-source", - "kind": "Kamelet", - "namespace": "default" - }, - "properties": { - "message": "Hello World" - }, - "dataTypes": { - "out": { - "scheme": "camel", - "format": "string" - } - } - }, - "sink": { - "ref": { - "name": "hello-topic", - "kind": "KafkaTopic", - "namespace": "default" - } - } - } -} diff --git a/java/steps/yaks-camel-k/src/test/resources/org/citrusframework/yaks/camelk/kamelet.json b/java/steps/yaks-camel-k/src/test/resources/org/citrusframework/yaks/camelk/kamelet.json deleted file mode 100644 index 09f4d1fd..00000000 --- a/java/steps/yaks-camel-k/src/test/resources/org/citrusframework/yaks/camelk/kamelet.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "apiVersion": "camel.apache.org/v1", - "kind": "Kamelet", - "metadata": { - "labels": { - "camel.apache.org/kamelet.type": "source" - }, - "name": "time-source" - }, - "spec": { - "definition": { - "title": "Timer Source", - "required": [ - "message" - ], - "properties": { - "period": { - "title": "Period", - "type": "integer", - "default": 1000 - }, - "message": { - "title": "Message", - "type": "string", - "example": "hello world" - } - } - }, - "dataTypes": { - "out": { - "default": "text", - "types": { - "binary": { - "scheme": "camel", - "format": "binary" - }, - "text": { - "scheme": "camel", - "format": "text" - } - } - } - }, - "dependencies": [ - "mvn:fake.dependency:id:version-1" - ], - "template": { - "from": { - "uri": "timer:tick", - "parameters": { - "period": "#property:period" - }, - "steps": [ - { - "set-body": { - "constant": "{{message}}" - } - }, - { - "to": "kamelet:sink" - } - ] - } - } - } -} diff --git a/java/steps/yaks-camel-k/src/test/resources/org/citrusframework/yaks/camelk/pipe.json b/java/steps/yaks-camel-k/src/test/resources/org/citrusframework/yaks/camelk/pipe.json deleted file mode 100644 index ad53e06f..00000000 --- a/java/steps/yaks-camel-k/src/test/resources/org/citrusframework/yaks/camelk/pipe.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "apiVersion": "camel.apache.org/v1", - "kind": "Pipe", - "metadata": { - "name": "time-source-kafka" - }, - "spec": { - "source": { - "ref": { - "name": "timer-source", - "kind": "Kamelet", - "namespace": "default" - }, - "properties": { - "message": "Hello World" - }, - "dataTypes": { - "out": { - "scheme": "camel", - "format": "string" - } - } - }, - "sink": { - "ref": { - "name": "hello-topic", - "kind": "KafkaTopic", - "namespace": "default" - } - } - } -} diff --git a/java/steps/yaks-camel-k/src/test/resources/pipe.yaml b/java/steps/yaks-camel-k/src/test/resources/pipe.yaml new file mode 100644 index 00000000..8a7958e5 --- /dev/null +++ b/java/steps/yaks-camel-k/src/test/resources/pipe.yaml @@ -0,0 +1,33 @@ +# --------------------------------------------------------------------------- +# 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. +# --------------------------------------------------------------------------- + +apiVersion: camel.apache.org/v1 +kind: Pipe +metadata: + name: timer-source-pipe +spec: + source: + ref: + kind: Kamelet + apiVersion: camel.apache.org/v1 + name: timer-source + properties: + message: "Hello world!" + sink: + ref: + kind: KafkaTopic + apiVersion: kafka.strimzi.io/v1beta1 + name: hello-topic diff --git a/java/steps/yaks-camel-k/src/test/resources/timer-source.kamelet.yaml b/java/steps/yaks-camel-k/src/test/resources/timer-source.kamelet.yaml index 82cf5c3e..87745416 100644 --- a/java/steps/yaks-camel-k/src/test/resources/timer-source.kamelet.yaml +++ b/java/steps/yaks-camel-k/src/test/resources/timer-source.kamelet.yaml @@ -14,7 +14,7 @@ # limitations under the License. # --------------------------------------------------------------------------- -apiVersion: camel.apache.org/v1alpha1 +apiVersion: camel.apache.org/v1 kind: Kamelet metadata: name: timer-source diff --git a/java/steps/yaks-camel-k/src/test/resources/timer-to-log-pipe.yaml b/java/steps/yaks-camel-k/src/test/resources/timer-to-log-pipe.yaml index 3fa2366d..7fa04b66 100644 --- a/java/steps/yaks-camel-k/src/test/resources/timer-to-log-pipe.yaml +++ b/java/steps/yaks-camel-k/src/test/resources/timer-to-log-pipe.yaml @@ -22,7 +22,7 @@ spec: source: ref: kind: Kamelet - apiVersion: camel.apache.org/v1alpha1 + apiVersion: camel.apache.org/v1 name: timer-source properties: message: "Hello world!" diff --git a/java/steps/yaks-kafka/src/main/java/org/citrusframework/yaks/kafka/KafkaSettings.java b/java/steps/yaks-kafka/src/main/java/org/citrusframework/yaks/kafka/KafkaSettings.java index 677c0c0b..98706abc 100644 --- a/java/steps/yaks-kafka/src/main/java/org/citrusframework/yaks/kafka/KafkaSettings.java +++ b/java/steps/yaks-kafka/src/main/java/org/citrusframework/yaks/kafka/KafkaSettings.java @@ -34,6 +34,10 @@ public class KafkaSettings { private static final String ENDPOINT_NAME_ENV = KAFKA_ENV_PREFIX + "ENDPOINT_NAME"; private static final String ENDPOINT_NAME_DEFAULT = "yaks-kafka-endpoint"; + private static final String API_VERSION_PROPERTY = KAFKA_PROPERTY_PREFIX + "api.version"; + private static final String API_VERSION_ENV = KAFKA_ENV_PREFIX + "API_VERSION"; + private static final String API_VERSION_DEFAULT = "v1beta1"; + static final String NAMESPACE_PROPERTY = KAFKA_PROPERTY_PREFIX + "namespace"; static final String NAMESPACE_ENV = KAFKA_ENV_PREFIX + "NAMESPACE"; @@ -67,4 +71,13 @@ public static String getNamespace() { return System.getProperty(NAMESPACE_PROPERTY, System.getenv(NAMESPACE_ENV) != null ? System.getenv(NAMESPACE_ENV) : YaksSettings.getDefaultNamespace()); } + + /** + * Api version for current Kafka Strimzi installation. + * @return + */ + public static String getApiVersion() { + return System.getProperty(API_VERSION_PROPERTY, + System.getenv(API_VERSION_ENV) != null ? System.getenv(API_VERSION_ENV) : API_VERSION_DEFAULT); + } } diff --git a/java/steps/yaks-kubernetes/src/main/java/org/citrusframework/yaks/kubernetes/KubernetesSupport.java b/java/steps/yaks-kubernetes/src/main/java/org/citrusframework/yaks/kubernetes/KubernetesSupport.java index 111a8458..94f4d97f 100644 --- a/java/steps/yaks-kubernetes/src/main/java/org/citrusframework/yaks/kubernetes/KubernetesSupport.java +++ b/java/steps/yaks-kubernetes/src/main/java/org/citrusframework/yaks/kubernetes/KubernetesSupport.java @@ -37,6 +37,7 @@ import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.KubernetesClientBuilder; import io.fabric8.kubernetes.client.KubernetesClientException; +import io.fabric8.kubernetes.client.dsl.Updatable; import io.fabric8.kubernetes.client.dsl.base.ResourceDefinitionContext; import org.citrusframework.Citrus; import org.citrusframework.context.TestContext; @@ -70,6 +71,11 @@ private KubernetesSupport() { // prevent instantiation of utility class } + // Optional property value mapper used to customize YAML dumper. + public interface PropertyValueMapper { + Object map(Property property, Object propertyValue); + } + /** * Retrieve current Kubernetes client if set in Citrus context as bean reference. * Otherwise, create new default instance. @@ -133,6 +139,25 @@ protected NodeTuple representJavaBeanProperty(Object javaBean, Property property return new Yaml(representer); } + public static Yaml yaml(PropertyValueMapper mapper) { + Representer representer = new Representer(new DumperOptions()) { + @Override + protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) { + Object propertyValueMapped = mapper.map(property, propertyValue); + + // if value of property is null, ignore it. + if (propertyValueMapped == null || (propertyValueMapped instanceof Collection && ((Collection) propertyValueMapped).isEmpty()) || + (propertyValueMapped instanceof Map && ((Map) propertyValueMapped).isEmpty())) { + return null; + } else { + return super.representJavaBeanProperty(javaBean, property, propertyValueMapped, customTag); + } + } + }; + representer.getPropertyUtils().setSkipMissingProperties(true); + return new Yaml(representer); + } + public static ObjectMapper json() { return OBJECT_MAPPER; } @@ -167,7 +192,7 @@ public static void createResource(KubernetesClient k8sClient, String namespa public static void createResource(KubernetesClient k8sClient, String namespace, ResourceDefinitionContext context, String yaml) { k8sClient.genericKubernetesResources(context).inNamespace(namespace) - .load(new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8))).createOrReplace(); + .load(new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8))).createOr(Updatable::update); } public static void deleteResource(KubernetesClient k8sClient, String namespace, @@ -223,5 +248,4 @@ public static Optional getServiceClusterIp(Citrus citrus, String service return Optional.empty(); } - }