Skip to content

Commit

Permalink
chore(knative): Add local Knative support
Browse files Browse the repository at this point in the history
- Support local mode when creating Knative broker
- Add capability for local Knative consumer service
- Enable/disable broker response verification
  • Loading branch information
christophd committed Feb 11, 2024
1 parent 436bda1 commit 6b0da6a
Show file tree
Hide file tree
Showing 18 changed files with 307 additions and 58 deletions.
20 changes: 10 additions & 10 deletions java/docs/steps-knative.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -264,11 +264,11 @@ As we are using the Http cloud event model we can also use Http property equival
[source,gherkin]
----
When send Knative event
| Ce-Specversion | 1.0 |
| Ce-Type | greeting |
| Ce-Source | https://github.com/citrusframework/yaks |
| Ce-Subject | hello |
| Ce-Id | say-hello-${id} |
| ce-specversion | 1.0 |
| ce-type | greeting |
| ce-source | https://github.com/citrusframework/yaks |
| ce-subject | hello |
| ce-id | say-hello-${id} |
| Content-Type | application/json;charset=UTF-8 |
| data | {"msg": "Hello Knative!"} |
----
Expand Down Expand Up @@ -409,11 +409,11 @@ As we are using the Http cloud event model we can also use Http property equival
[source,gherkin]
----
Then receive Knative event
| Ce-Specversion | 1.0 |
| Ce-Type | greeting |
| Ce-Source | https://github.com/citrusframework/yaks |
| Ce-Subject | hello |
| Ce-Id | say-hello-${id} |
| ce-specversion | 1.0 |
| ce-type | greeting |
| ce-source | https://github.com/citrusframework/yaks |
| ce-subject | hello |
| ce-id | say-hello-${id} |
| Content-Type | application/json;charset=UTF-8 |
| data | {"msg": "Hello Knative!"} |
----
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ default String operatorNamespace(TestContext context) {

/**
* Resolves cluster type from given test context using the stored test variable.
* Fallback to retreiving the cluster type from environment settings when no test variable is present.
* Fallback to retrieving the cluster type from environment settings when no test variable is present.
*
* @param context
* @return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

import org.citrusframework.context.TestContext;
import org.citrusframework.exceptions.ValidationException;
import org.citrusframework.yaks.YaksClusterType;
import org.citrusframework.yaks.YaksSettings;
import org.citrusframework.yaks.camelk.CamelKSettings;
import org.citrusframework.yaks.camelk.model.Kamelet;
import org.citrusframework.yaks.camelk.model.KameletList;
Expand Down Expand Up @@ -60,7 +60,7 @@ public void doExecute(TestContext context) {

@Override
public boolean isDisabled(TestContext context) {
return clusterType(context) == YaksClusterType.LOCAL;
return YaksSettings.isLocal(clusterType(context));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,13 @@ public class KnativeSettings {
private static final String AUTO_REMOVE_RESOURCES_ENV = KNATIVE_ENV_PREFIX + "AUTO_REMOVE_RESOURCES";
private static final String AUTO_REMOVE_RESOURCES_DEFAULT = "true";

private static final String VERIFY_BROKER_RESPONSE_PROPERTY = KNATIVE_PROPERTY_PREFIX + "verify.broker.resources";
private static final String VERIFY_BROKER_RESPONSE_ENV = KNATIVE_ENV_PREFIX + "VERIFY_BROKER_RESPONSE";
private static final String VERIFY_BROKER_RESPONSE_DEFAULT = "true";

private static final String BROKER_RESPONSE_STATUS_PROPERTY = KNATIVE_PROPERTY_PREFIX + "broker.response";
private static final String BROKER_RESPONSE_STATUS_ENV = KNATIVE_ENV_PREFIX + "BROKER_RESPONSE_STATUS";

private static final String DEFAULT_LABELS_PROPERTY = KNATIVE_PROPERTY_PREFIX + "default.labels";
private static final String DEFAULT_LABELS_ENV = KNATIVE_ENV_PREFIX + "DEFAULT_LABELS";

Expand Down Expand Up @@ -207,12 +214,28 @@ public static boolean isAutoRemoveResources() {
System.getenv(AUTO_REMOVE_RESOURCES_ENV) != null ? System.getenv(AUTO_REMOVE_RESOURCES_ENV) : AUTO_REMOVE_RESOURCES_DEFAULT));
}

public static boolean isVerifyBrokerResponse() {
return Boolean.parseBoolean(System.getProperty(VERIFY_BROKER_RESPONSE_PROPERTY,
System.getenv(VERIFY_BROKER_RESPONSE_ENV) != null ? System.getenv(VERIFY_BROKER_RESPONSE_ENV) : VERIFY_BROKER_RESPONSE_DEFAULT));
}

public static int getBrokerResponseStatus() {
String defaultResponseStatus;
if (YaksSettings.isLocal()) {
defaultResponseStatus = "204"; // NO_CONTENT
} else {
defaultResponseStatus = "202"; // ACCEPTED
}

return Integer.parseInt(System.getProperty(BROKER_RESPONSE_STATUS_PROPERTY,
System.getenv(BROKER_RESPONSE_STATUS_ENV) != null ? System.getenv(BROKER_RESPONSE_STATUS_ENV) : defaultResponseStatus));
}

public static String getKnativeMessagingGroup() {
return "messaging.knative.dev";
}

public static String getKnativeEventingGroup() {
return "eventing.knative.dev";
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
*/
public enum KnativeVariableNames {

CLUSTER_TYPE("YAKS_CLUSTER_TYPE"),
BROKER_NAME("KNATIVE_BROKER"),
BROKER_PORT("KNATIVE_BROKER_PORT"),
NAMESPACE("KNATIVE_NAMESPACE");

private final String variableName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
import io.cucumber.java.Scenario;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import org.citrusframework.http.server.HttpServer;
import org.citrusframework.yaks.YaksSettings;
import org.citrusframework.yaks.knative.ce.CloudEventMessage;
import org.citrusframework.yaks.knative.ce.CloudEventSupport;
import org.citrusframework.yaks.kubernetes.KubernetesSteps;
Expand Down Expand Up @@ -99,12 +101,28 @@ public void receiveEventJson(String json) {

@Given("^create Knative event consumer service ([^\\s]+)$")
public void createService(String serviceName) {
kubernetesSteps.createService(serviceName);
if (YaksSettings.isLocal() && context.getVariables().containsKey(KnativeVariableNames.BROKER_NAME.value()) &&
context.getReferenceResolver().isResolvable(context.getVariable(KnativeVariableNames.BROKER_NAME.value()))) {
HttpServer brokerServer = context.getReferenceResolver().resolve(context.getVariable(KnativeVariableNames.BROKER_NAME.value()), HttpServer.class);
context.getReferenceResolver().bind(serviceName, brokerServer);
setServiceName(serviceName);
setServicePort(String.valueOf(brokerServer.getPort()));
} else {
kubernetesSteps.createService(serviceName);
}
}

@Given("^create Knative event consumer service ([^\\s]+) with target port ([^\\s]+)$")
public void createService(String serviceName, String targetPort) {
kubernetesSteps.createService(serviceName, targetPort);
if (YaksSettings.isLocal() && context.getVariables().containsKey(KnativeVariableNames.BROKER_NAME.value()) &&
context.getReferenceResolver().isResolvable(context.getVariable(KnativeVariableNames.BROKER_NAME.value()))) {
HttpServer brokerServer = context.getReferenceResolver().resolve(context.getVariable(KnativeVariableNames.BROKER_NAME.value()), HttpServer.class);
context.getReferenceResolver().bind(serviceName, brokerServer);
setServiceName(serviceName);
setServicePort(String.valueOf(brokerServer.getPort()));
} else {
kubernetesSteps.createService(serviceName, targetPort);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.Objects;
import java.util.UUID;
import javax.net.ssl.SSLContext;

import io.cucumber.datatable.DataTable;
Expand Down Expand Up @@ -138,15 +139,15 @@ private void sendEvent(CloudEventMessage request) {
}

if (request.getEventId() == null) {
request.eventId("yaks-test-event");
request.eventId(UUID.randomUUID().toString());
}

if (request.getEventType() == null) {
request.eventType("yaks-test");
request.eventType("org.citrusframework.yaks.event.test");
}

if (request.getSource() == null) {
request.source("yaks-test-source");
request.source("yaks-test");
}

request.setHeader("Host", KnativeSettings.getBrokerHost());
Expand All @@ -162,10 +163,12 @@ private void sendEvent(CloudEventMessage request) {

runner.run(requestBuilder);

runner.run(http().client(httpClient)
.receive()
.response(HttpStatus.ACCEPTED)
.timeout(timeout));
if (KnativeSettings.isVerifyBrokerResponse()) {
runner.run(http().client(httpClient)
.receive()
.response(HttpStatus.valueOf(KnativeSettings.getBrokerResponseStatus()))
.timeout(timeout));
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
import org.citrusframework.actions.AbstractTestAction;
import io.fabric8.knative.client.KnativeClient;
import io.fabric8.kubernetes.client.KubernetesClient;
import org.citrusframework.context.TestContext;
import org.citrusframework.yaks.YaksClusterType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -35,11 +37,14 @@ public abstract class AbstractKnativeAction extends AbstractTestAction implement
private final KnativeClient knativeClient;
private final KubernetesClient kubernetesClient;

private final YaksClusterType clusterType;

public AbstractKnativeAction(String name, Builder<?, ?> builder) {
super("knative:" + name, builder);

this.knativeClient = builder.knativeClient;
this.kubernetesClient = builder.kubernetesClient;
this.clusterType = builder.clusterType;
}

@Override
Expand All @@ -52,6 +57,15 @@ public KnativeClient getKnativeClient() {
return knativeClient;
}

@Override
public YaksClusterType clusterType(TestContext context) {
if (clusterType != null) {
return clusterType;
}

return KnativeAction.super.clusterType(context);
}

/**
* Action builder.
*/
Expand All @@ -60,6 +74,8 @@ public static abstract class Builder<T extends KnativeAction, B extends Builder<
private KnativeClient knativeClient;
private KubernetesClient kubernetesClient;

private YaksClusterType clusterType;

/**
* Use a custom Kubernetes client.
*/
Expand All @@ -76,5 +92,13 @@ public B client(KnativeClient knativeClient) {
return self;
}

/**
* Explicitly set cluster type for this action.
*/
public B clusterType(YaksClusterType clusterType) {
this.clusterType = clusterType;
return self;
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@

package org.citrusframework.yaks.knative.actions;

import org.citrusframework.TestAction;
import org.citrusframework.context.TestContext;
import io.fabric8.knative.client.KnativeClient;
import io.fabric8.kubernetes.client.KubernetesClient;
import org.citrusframework.TestAction;
import org.citrusframework.context.TestContext;
import org.citrusframework.yaks.YaksClusterType;
import org.citrusframework.yaks.YaksSettings;
import org.citrusframework.yaks.knative.KnativeSettings;
import org.citrusframework.yaks.knative.KnativeVariableNames;

Expand Down Expand Up @@ -74,5 +76,26 @@ default String brokerName(TestContext context) {

return KnativeSettings.getBrokerName();
}

/**
* Resolves cluster type from given test context using the stored test variable.
* Fallback to retrieving the cluster type from environment settings when no test variable is present.
*
* @param context
* @return
*/
default YaksClusterType clusterType(TestContext context) {
if (context.getVariables().containsKey(KnativeVariableNames.CLUSTER_TYPE.value())) {
Object clusterType = context.getVariableObject(KnativeVariableNames.CLUSTER_TYPE.value());

if (clusterType instanceof YaksClusterType) {
return (YaksClusterType) clusterType;
} else {
return YaksClusterType.valueOf(clusterType.toString());
}
}

return YaksSettings.getClusterType();
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@

package org.citrusframework.yaks.knative.actions;

import org.citrusframework.TestActionBuilder;
import io.fabric8.knative.client.KnativeClient;
import io.fabric8.kubernetes.client.KubernetesClient;
import org.citrusframework.TestActionBuilder;
import org.citrusframework.yaks.knative.actions.eventing.CreateBrokerAction;
import org.citrusframework.yaks.knative.actions.eventing.CreateTriggerAction;
import org.citrusframework.yaks.knative.actions.eventing.DeleteBrokerAction;
import org.citrusframework.yaks.knative.actions.eventing.VerifyBrokerAction;
import org.citrusframework.yaks.knative.actions.messaging.CreateChannelAction;
import org.citrusframework.yaks.knative.actions.messaging.CreateSubscriptionAction;
Expand Down Expand Up @@ -222,12 +223,10 @@ public CreateBrokerAction.Builder create(String brokerName) {
* Delete broker instance.
* @param brokerName the name of the Knative broker.
*/
public DeleteKnativeResourceAction.Builder delete(String brokerName) {
DeleteKnativeResourceAction.Builder builder = new DeleteKnativeResourceAction.Builder()
public DeleteBrokerAction.Builder delete(String brokerName) {
DeleteBrokerAction.Builder builder = new DeleteBrokerAction.Builder()
.client(kubernetesClient)
.client(knativeClient)
.component("eventing")
.kind("brokers")
.name(brokerName);
delegate = builder;
return builder;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@

package org.citrusframework.yaks.knative.actions.eventing;

import org.citrusframework.context.TestContext;
import io.fabric8.knative.eventing.v1.Broker;
import io.fabric8.knative.eventing.v1.BrokerBuilder;
import org.citrusframework.context.TestContext;
import org.citrusframework.http.server.HttpServer;
import org.citrusframework.http.server.HttpServerBuilder;
import org.citrusframework.yaks.YaksSettings;
import org.citrusframework.yaks.knative.KnativeSettings;
import org.citrusframework.yaks.knative.KnativeSupport;
import org.citrusframework.yaks.knative.KnativeVariableNames;
import org.citrusframework.yaks.knative.actions.AbstractKnativeAction;

/**
Expand All @@ -39,12 +43,46 @@ public CreateBrokerAction(Builder builder) {

@Override
public void doExecute(TestContext context) {
if (YaksSettings.isLocal(clusterType(context))) {
createLocalBroker(context);
} else {
createBroker(context);
}
}

/**
* Creates Http server as a local Knative broker.
* @param context
*/
private void createLocalBroker(TestContext context) {
String resolvedBrokerName = context.replaceDynamicContentInString(brokerName);

if (!context.getReferenceResolver().isResolvable(resolvedBrokerName, HttpServer.class)) {
HttpServer brokerServer = new HttpServerBuilder()
.autoStart(true)
.port(Integer.parseInt(KnativeSettings.getServicePort()))
.referenceResolver(context.getReferenceResolver())
.build();

brokerServer.initialize();
context.getReferenceResolver()
.bind(resolvedBrokerName, brokerServer);

context.setVariable(KnativeVariableNames.BROKER_PORT.value(), brokerServer.getPort());
}
}

/**
* Creates Knative broker on current namespace.
* @param context
*/
private void createBroker(TestContext context) {
Broker broker = new BrokerBuilder()
.withApiVersion(String.format("%s/%s", KnativeSupport.knativeEventingGroup(), KnativeSupport.knativeApiVersion()))
.withNewMetadata()
.withNamespace(namespace(context))
.withName(context.replaceDynamicContentInString(brokerName))
.withLabels(KnativeSettings.getDefaultLabels())
.withNamespace(namespace(context))
.withName(context.replaceDynamicContentInString(brokerName))
.withLabels(KnativeSettings.getDefaultLabels())
.endMetadata()
.build();

Expand Down
Loading

0 comments on commit 6b0da6a

Please sign in to comment.