Search in sources :

Example 1 with ConnectorConfiguration

use of org.bf2.cos.fleetshard.operator.connector.ConnectorConfiguration in project cos-fleetshard by bf2fc6cc711aee1a0c2a.

the class DebeziumOperandControllerTest method reify.

@Test
void reify() {
    KubernetesClient kubernetesClient = Mockito.mock(KubernetesClient.class);
    DebeziumOperandController controller = new DebeziumOperandController(kubernetesClient, CONFIGURATION);
    final String kcsB64 = Base64.getEncoder().encodeToString("kcs".getBytes(StandardCharsets.UTF_8));
    final String pwdB64 = Base64.getEncoder().encodeToString("orderpw".getBytes(StandardCharsets.UTF_8));
    var spec = Serialization.jsonMapper().createObjectNode().put("database.hostname", "orderdb").put("database.port", "5432").put("database.user", "orderuser").put("database.dbname", "orderdb").put("database.server.name", "dbserver1").put("schema.include.list", "purchaseorder").put("table.include.list", "purchaseorder.outboxevent").put("tombstones.on.delete", "false").put("key.converter", "org.apache.kafka.connect.storage.StringConverter").put("value.converter", "org.apache.kafka.connect.storage.StringConverter").put("transforms", "saga").put("transforms.saga.type", "io.debezium.transforms.outbox.EventRouter").put("transforms.saga.route.topic.replacement", "${routedByValue}.request").put("poll.interval.ms", "100").put("consumer.interceptor.classes", "io.opentracing.contrib.kafka.TracingConsumerInterceptor").put("producer.interceptor.classes", "io.opentracing.contrib.kafka.TracingProducerInterceptor");
    spec.with("data_shape").put("key", "JSON").put("value", "JSON");
    spec.with("database.password").put("kind", "base64").put("value", pwdB64);
    var resources = controller.doReify(new ManagedConnectorBuilder().withMetadata(new ObjectMetaBuilder().withName(DEFAULT_MANAGED_CONNECTOR_ID).build()).withSpec(new ManagedConnectorSpecBuilder().withConnectorId(DEFAULT_MANAGED_CONNECTOR_ID).withDeploymentId(DEFAULT_DEPLOYMENT_ID).withDeployment(new DeploymentSpecBuilder().withConnectorTypeId(DEFAULT_CONNECTOR_TYPE_ID).withSecret("secret").withKafka(new KafkaSpecBuilder().withUrl(DEFAULT_KAFKA_SERVER).build()).withConnectorResourceVersion(DEFAULT_CONNECTOR_REVISION).withDeploymentResourceVersion(DEFAULT_DEPLOYMENT_REVISION).withDesiredState(DESIRED_STATE_READY).build()).build()).build(), new org.bf2.cos.fleetshard.operator.debezium.DebeziumShardMetadataBuilder().withContainerImage(DEFAULT_CONNECTOR_IMAGE).withConnectorClass(PG_CLASS).build(), new ConnectorConfiguration<>(spec, ObjectNode.class), new ServiceAccountSpecBuilder().withClientId(DEFAULT_KAFKA_CLIENT_ID).withClientSecret(kcsB64).build());
    assertThat(resources).anyMatch(DebeziumOperandSupport::isKafkaConnect).anyMatch(DebeziumOperandSupport::isKafkaConnector).anyMatch(DebeziumOperandSupport::isSecret);
    assertThat(resources).filteredOn(DebeziumOperandSupport::isKafkaConnect).hasSize(1).first().isInstanceOfSatisfying(KafkaConnect.class, kc -> {
        assertThat(kc.getSpec().getImage()).isEqualTo(DEFAULT_CONNECTOR_IMAGE);
    });
    assertThat(resources).filteredOn(DebeziumOperandSupport::isKafkaConnector).hasSize(1).first().isInstanceOfSatisfying(KafkaConnector.class, kc -> {
        assertThat(kc.getSpec().getConfig()).containsEntry("database.password", "${file:/opt/kafka/external-configuration/" + DebeziumConstants.EXTERNAL_CONFIG_DIRECTORY + "/" + EXTERNAL_CONFIG_FILE + ":database.password}");
    });
}
Also used : DeploymentSpecBuilder(org.bf2.cos.fleetshard.api.DeploymentSpecBuilder) KubernetesClient(io.fabric8.kubernetes.client.KubernetesClient) ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) ManagedConnectorSpecBuilder(org.bf2.cos.fleetshard.api.ManagedConnectorSpecBuilder) ObjectMetaBuilder(io.fabric8.kubernetes.api.model.ObjectMetaBuilder) ManagedConnectorBuilder(org.bf2.cos.fleetshard.api.ManagedConnectorBuilder) KafkaSpecBuilder(org.bf2.cos.fleetshard.api.KafkaSpecBuilder) ServiceAccountSpecBuilder(org.bf2.cos.fleetshard.api.ServiceAccountSpecBuilder) Test(org.junit.jupiter.api.Test) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 2 with ConnectorConfiguration

use of org.bf2.cos.fleetshard.operator.connector.ConnectorConfiguration in project cos-fleetshard by bf2fc6cc711aee1a0c2a.

the class CamelOperandSupport method createSteps.

public static List<ProcessorKamelet> createSteps(ManagedConnector connector, ConnectorConfiguration<ObjectNode> connectorConfiguration, CamelShardMetadata shardMetadata, Map<String, String> props) {
    String consumes = Optional.ofNullable(connectorConfiguration.getDataShapeSpec()).map(spec -> spec.at("/consumes/format")).filter(node -> !node.isMissingNode()).map(JsonNode::asText).orElse(shardMetadata.getConsumes());
    String produces = Optional.ofNullable(connectorConfiguration.getDataShapeSpec()).map(spec -> spec.at("/produces/format")).filter(node -> !node.isMissingNode()).map(JsonNode::asText).orElse(shardMetadata.getProduces());
    final ArrayNode steps = connectorConfiguration.getProcessorsSpec();
    final List<ProcessorKamelet> stepDefinitions = new ArrayList<>(steps.size() + 2);
    int i = 0;
    if (consumes != null) {
        switch(consumes) {
            case "application/json":
                {
                    String stepName = stepName(i, "cos-decoder-json-action");
                    stepDefinitions.add(new ProcessorKamelet("cos-decoder-json-action", stepName));
                    if (shardMetadata.getConsumesClass() != null) {
                        props.put(kameletProperty("cos-decoder-json-action", stepName, "contentClass"), shardMetadata.getConsumesClass());
                    }
                    i++;
                }
                break;
            case "avro/binary":
                {
                    String stepName = stepName(i, "cos-decoder-avro-action");
                    stepDefinitions.add(new ProcessorKamelet("cos-decoder-avro-action", stepName));
                    if (shardMetadata.getConsumesClass() != null) {
                        props.put(kameletProperty("cos-decoder-avro-action", stepName, "contentClass"), shardMetadata.getConsumesClass());
                    }
                    i++;
                }
                break;
            case "application/x-java-object":
                {
                    String stepName = stepName(i, "cos-decoder-pojo-action");
                    stepDefinitions.add(new ProcessorKamelet("cos-decoder-pojo-action", stepName));
                    if (produces != null) {
                        props.put(kameletProperty("cos-decoder-pojo-action", stepName, "mimeType"), produces);
                    }
                    i++;
                }
                break;
            case "text/plain":
            case "application/octet-stream":
                break;
            default:
                throw new IllegalArgumentException("Unsupported value format " + consumes);
        }
    }
    for (JsonNode step : steps) {
        var element = step.fields().next();
        String templateId = shardMetadata.getKamelets().getProcessors().get(element.getKey());
        if (templateId == null) {
            throw new IllegalArgumentException("Unknown processor: " + element.getKey());
        }
        stepDefinitions.add(new ProcessorKamelet(templateId, stepName(i, templateId)));
        configureStep(props, (ObjectNode) element.getValue(), i, shardMetadata.getKamelets().getProcessors().get(element.getKey()));
        i++;
    }
    if (produces != null) {
        switch(produces) {
            case "application/json":
                {
                    String stepName = stepName(i, "cos-encoder-json-action");
                    stepDefinitions.add(new ProcessorKamelet("cos-encoder-json-action", stepName));
                    if (shardMetadata.getProducesClass() != null) {
                        props.put(kameletProperty("cos-encoder-json-action", stepName, "contentClass"), shardMetadata.getProducesClass());
                    }
                }
                break;
            case "avro/binary":
                {
                    String stepName = stepName(i, "cos-encoder-avro-action");
                    stepDefinitions.add(new ProcessorKamelet("cos-encoder-avro-action", stepName));
                    if (shardMetadata.getProducesClass() != null) {
                        props.put(kameletProperty("cos-encoder-avro-action", stepName, "contentClass"), shardMetadata.getProducesClass());
                    }
                }
                break;
            case "text/plain":
                {
                    stepDefinitions.add(new ProcessorKamelet("cos-encoder-string-action", stepName(i, "cos-encoder-string-action")));
                }
                break;
            case "application/octet-stream":
                {
                    stepDefinitions.add(new ProcessorKamelet("cos-encoder-bytearray-action", stepName(i, "cos-encoder-bytearray-action")));
                }
                break;
            default:
                throw new IllegalArgumentException("Unsupported value format " + produces);
        }
    }
    // If it is a sink, then it consumes from kafka
    if (isSink(shardMetadata)) {
        props.put(String.format("camel.kamelet.%s.valueDeserializer", shardMetadata.getKamelets().getKafka().getName()), "org.bf2.cos.connector.camel.serdes.bytes.ByteArrayDeserializer");
        if ("application/json".equals(consumes) && hasSchemaRegistry(connector)) {
            props.put(String.format("camel.kamelet.%s.valueDeserializer", shardMetadata.getKamelets().getKafka().getName()), "org.bf2.cos.connector.camel.serdes.json.JsonDeserializer");
        }
        if ("avro/binary".equals(produces) && hasSchemaRegistry(connector)) {
            props.put(String.format("camel.kamelet.%s.valueDeserializer", shardMetadata.getKamelets().getKafka().getName()), "org.bf2.cos.connector.camel.serdes.avro.AvroDeserializer");
        }
    }
    // If it is a source, then it produces to kafka
    if (isSource(shardMetadata)) {
        props.put(String.format("camel.kamelet.%s.valueSerializer", shardMetadata.getKamelets().getKafka().getName()), "org.bf2.cos.connector.camel.serdes.bytes.ByteArraySerializer");
        if ("application/json".equals(produces) && hasSchemaRegistry(connector)) {
            props.put(String.format("camel.kamelet.%s.valueSerializer", shardMetadata.getKamelets().getKafka().getName()), "org.bf2.cos.connector.camel.serdes.json.JsonSerializer");
        }
        if ("avro/binary".equals(produces) && hasSchemaRegistry(connector)) {
            props.put(String.format("camel.kamelet.%s.valueSerializer", shardMetadata.getKamelets().getKafka().getName()), "org.bf2.cos.connector.camel.serdes.avro.AvroSerializer");
        }
    }
    return stepDefinitions;
}
Also used : ConnectorStatusSpec(org.bf2.cos.fleetshard.api.ConnectorStatusSpec) ERROR_HANDLER_LOG_TYPE(org.bf2.cos.fleetshard.operator.camel.CamelConstants.ERROR_HANDLER_LOG_TYPE) StringUtils(org.apache.commons.lang3.StringUtils) KameletBindingStatus(org.bf2.cos.fleetshard.operator.camel.model.KameletBindingStatus) ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) ArrayList(java.util.ArrayList) ERROR_HANDLER_STOP_URI(org.bf2.cos.fleetshard.operator.camel.CamelConstants.ERROR_HANDLER_STOP_URI) Serialization(io.fabric8.kubernetes.client.utils.Serialization) Locale(java.util.Locale) Map(java.util.Map) JsonNode(com.fasterxml.jackson.databind.JsonNode) ERROR_HANDLER_SINK_CHANNEL_TYPE(org.bf2.cos.fleetshard.operator.camel.CamelConstants.ERROR_HANDLER_SINK_CHANNEL_TYPE) ManagedConnector(org.bf2.cos.fleetshard.api.ManagedConnector) ConnectorConfiguration(org.bf2.cos.fleetshard.operator.connector.ConnectorConfiguration) ERROR_HANDLER_DEAD_LETTER_CHANNEL_KAMELET(org.bf2.cos.fleetshard.operator.camel.CamelConstants.ERROR_HANDLER_DEAD_LETTER_CHANNEL_KAMELET) CamelShardMetadata(org.bf2.cos.fleetshard.operator.camel.model.CamelShardMetadata) Iterator(java.util.Iterator) ProcessorKamelet(org.bf2.cos.fleetshard.operator.camel.model.ProcessorKamelet) CaseUtils(org.apache.commons.text.CaseUtils) ServiceAccountSpec(org.bf2.cos.fleetshard.api.ServiceAccountSpec) KameletBinding(org.bf2.cos.fleetshard.operator.camel.model.KameletBinding) StandardCharsets(java.nio.charset.StandardCharsets) ArrayNode(com.fasterxml.jackson.databind.node.ArrayNode) Base64(java.util.Base64) List(java.util.List) Condition(io.fabric8.kubernetes.api.model.Condition) CONNECTOR_TYPE_SOURCE(org.bf2.cos.fleetshard.operator.camel.CamelConstants.CONNECTOR_TYPE_SOURCE) ERROR_HANDLER_DEAD_LETTER_CHANNEL_KAMELET_ID(org.bf2.cos.fleetshard.operator.camel.CamelConstants.ERROR_HANDLER_DEAD_LETTER_CHANNEL_KAMELET_ID) KubernetesClient(io.fabric8.kubernetes.client.KubernetesClient) Optional(java.util.Optional) CONNECTOR_TYPE_SINK(org.bf2.cos.fleetshard.operator.camel.CamelConstants.CONNECTOR_TYPE_SINK) Kamelets(org.bf2.cos.fleetshard.operator.camel.model.Kamelets) JacksonUtil.iterator(org.bf2.cos.fleetshard.support.json.JacksonUtil.iterator) ProcessorKamelet(org.bf2.cos.fleetshard.operator.camel.model.ProcessorKamelet) ArrayList(java.util.ArrayList) JsonNode(com.fasterxml.jackson.databind.JsonNode) ArrayNode(com.fasterxml.jackson.databind.node.ArrayNode)

Example 3 with ConnectorConfiguration

use of org.bf2.cos.fleetshard.operator.connector.ConnectorConfiguration in project cos-fleetshard by bf2fc6cc711aee1a0c2a.

the class AbstractOperandController method reify.

@Override
public List<HasMetadata> reify(ManagedConnector connector, Secret secret) {
    LOGGER.debug("Reifying connector: {} and secret.metadata: {}", connector, secret.getMetadata());
    final ServiceAccount serviceAccountSettings = extract(secret, SECRET_ENTRY_SERVICE_ACCOUNT, ServiceAccount.class);
    LOGGER.debug("Extracted serviceAccount {}", serviceAccountSettings == null ? "is null" : "with clientId: " + serviceAccountSettings.getClientId());
    ServiceAccountSpec sas = serviceAccountSettings == null ? new ServiceAccountSpecBuilder().build() : new ServiceAccountSpecBuilder().withClientId(serviceAccountSettings.getClientId()).withClientSecret(serviceAccountSettings.getClientSecret()).build();
    ConnectorConfiguration<S, D> connectorConfig;
    try {
        connectorConfig = new ConnectorConfiguration<>(extract(secret, SECRET_ENTRY_CONNECTOR, ObjectNode.class), connectorSpecType, dataShapeType);
    } catch (IncompleteConnectorSpecException e) {
        throw new RuntimeException("Incomplete connectorSpec for connector \"" + connector.getSpec().getConnectorId() + "@" + connector.getSpec().getDeploymentId() + "#" + connector.getSpec().getDeployment().getDeploymentResourceVersion() + "\": " + e.getLocalizedMessage(), e);
    }
    return doReify(connector, extract(secret, SECRET_ENTRY_META, metadataType), connectorConfig, sas);
}
Also used : IncompleteConnectorSpecException(org.bf2.cos.fleetshard.operator.connector.IncompleteConnectorSpecException) ServiceAccount(org.bf2.cos.fleet.manager.model.ServiceAccount) ServiceAccountSpec(org.bf2.cos.fleetshard.api.ServiceAccountSpec) ServiceAccountSpecBuilder(org.bf2.cos.fleetshard.api.ServiceAccountSpecBuilder)

Example 4 with ConnectorConfiguration

use of org.bf2.cos.fleetshard.operator.connector.ConnectorConfiguration in project cos-fleetshard by bf2fc6cc711aee1a0c2a.

the class CamelOperandController method doReify.

@SuppressFBWarnings("HARD_CODE_PASSWORD")
@Override
protected List<HasMetadata> doReify(ManagedConnector connector, CamelShardMetadata shardMetadata, ConnectorConfiguration<ObjectNode, ObjectNode> connectorConfiguration, ServiceAccountSpec serviceAccountSpec) {
    final Map<String, String> properties = createSecretsData(connector, connectorConfiguration, serviceAccountSpec, configuration);
    final ObjectNode errorHandler = createErrorHandler(shardMetadata, connector, connectorConfiguration.getErrorHandlerSpec());
    final List<KameletEndpoint> stepDefinitions;
    final KameletEndpoint source;
    final KameletEndpoint sink;
    // 
    switch(shardMetadata.getConnectorType()) {
        case CONNECTOR_TYPE_SOURCE:
            source = KameletEndpoint.kamelet(shardMetadata.getKamelets().getAdapter().getName());
            source.getProperties().put("id", connector.getSpec().getDeploymentId() + "-source");
            configureKameletProperties(source.getProperties(), connectorConfiguration.getConnectorSpec(), shardMetadata.getKamelets().getAdapter());
            sink = KameletEndpoint.kamelet(shardMetadata.getKamelets().getKafka().getName());
            sink.getProperties().put("id", connector.getSpec().getDeploymentId() + "-sink");
            sink.getProperties().put("bootstrapServers", connector.getSpec().getDeployment().getKafka().getUrl());
            sink.getProperties().put("user", SA_CLIENT_ID_PLACEHOLDER);
            sink.getProperties().put("password", SA_CLIENT_SECRET_PLACEHOLDER);
            configureKameletProperties(sink.getProperties(), connectorConfiguration.getConnectorSpec(), shardMetadata.getKamelets().getKafka());
            if (hasSchemaRegistry(connector)) {
                sink.getProperties().put("registryUrl", connector.getSpec().getDeployment().getSchemaRegistry().getUrl());
            }
            stepDefinitions = createSteps(connector, connectorConfiguration, shardMetadata, sink);
            break;
        case CONNECTOR_TYPE_SINK:
            source = KameletEndpoint.kamelet(shardMetadata.getKamelets().getKafka().getName());
            source.getProperties().put("id", connector.getSpec().getDeploymentId() + "-source");
            source.getProperties().put("consumerGroup", connector.getSpec().getDeploymentId());
            source.getProperties().put("bootstrapServers", connector.getSpec().getDeployment().getKafka().getUrl());
            source.getProperties().put("user", SA_CLIENT_ID_PLACEHOLDER);
            source.getProperties().put("password", SA_CLIENT_SECRET_PLACEHOLDER);
            configureKameletProperties(source.getProperties(), connectorConfiguration.getConnectorSpec(), shardMetadata.getKamelets().getKafka());
            if (hasSchemaRegistry(connector)) {
                source.getProperties().put("registryUrl", connector.getSpec().getDeployment().getSchemaRegistry().getUrl());
            }
            sink = KameletEndpoint.kamelet(shardMetadata.getKamelets().getAdapter().getName());
            sink.getProperties().put("id", connector.getSpec().getDeploymentId() + "-sink");
            configureKameletProperties(sink.getProperties(), connectorConfiguration.getConnectorSpec(), shardMetadata.getKamelets().getAdapter());
            stepDefinitions = createSteps(connector, connectorConfiguration, shardMetadata, source);
            break;
        default:
            throw new IllegalArgumentException("Unknown connector type: " + shardMetadata.getConnectorType());
    }
    final Secret secret = new Secret();
    secret.setMetadata(new ObjectMeta());
    secret.getMetadata().setName(connector.getMetadata().getName() + Resources.CONNECTOR_SECRET_SUFFIX);
    secret.setData(Map.of(APPLICATION_PROPERTIES, asBytesBase64(properties)));
    final ObjectNode integration = createIntegrationSpec(secret.getMetadata().getName(), configuration, Map.of("CONNECTOR_SECRET_NAME", secret.getMetadata().getName(), "CONNECTOR_SECRET_CHECKSUM", Secrets.computeChecksum(secret), "CONNECTOR_ID", connector.getSpec().getConnectorId(), "CONNECTOR_DEPLOYMENT_ID", connector.getSpec().getDeploymentId()));
    final KameletBinding binding = new KameletBinding();
    binding.setMetadata(new ObjectMeta());
    binding.getMetadata().setName(connector.getMetadata().getName());
    binding.getMetadata().setAnnotations(new TreeMap<>());
    binding.setSpec(new KameletBindingSpec());
    binding.getSpec().setSource(source);
    binding.getSpec().setSink(sink);
    binding.getSpec().setErrorHandler(errorHandler);
    binding.getSpec().setSteps(stepDefinitions);
    binding.getSpec().setIntegration(integration);
    Map<String, String> annotations = binding.getMetadata().getAnnotations();
    if (shardMetadata.getAnnotations() != null) {
        annotations.putAll(shardMetadata.getAnnotations());
    }
    if (configuration.labelSelection().enabled()) {
        Operator assigned = connector.getStatus().getConnectorStatus().getAssignedOperator();
        if (assigned != null && assigned.getId() != null) {
            annotations.putIfAbsent(KAMEL_OPERATOR_ID, assigned.getId());
        }
    }
    annotations.putIfAbsent(TRAIT_CAMEL_APACHE_ORG_CONTAINER_IMAGE, shardMetadata.getConnectorImage());
    annotations.putIfAbsent(TRAIT_CAMEL_APACHE_ORG_KAMELETS_ENABLED, "false");
    annotations.putIfAbsent(TRAIT_CAMEL_APACHE_ORG_JVM_ENABLED, "false");
    annotations.putIfAbsent(TRAIT_CAMEL_APACHE_ORG_LOGGING_JSON, "false");
    annotations.putIfAbsent(TRAIT_CAMEL_APACHE_ORG_OWNER_TARGET_LABELS, LABELS_TO_TRANSFER);
    annotations.putIfAbsent(TRAIT_CAMEL_APACHE_ORG_PROMETHEUS_ENABLED, "true");
    annotations.putIfAbsent(TRAIT_CAMEL_APACHE_ORG_PROMETHEUS_POD_MONITOR, "false");
    // health check annotations
    annotations.putIfAbsent(TRAIT_CAMEL_APACHE_ORG_HEALTH_ENABLED, "true");
    annotations.putIfAbsent(TRAIT_CAMEL_APACHE_ORG_HEALTH_READINESS_PROBE_ENABLED, "true");
    annotations.putIfAbsent(TRAIT_CAMEL_APACHE_ORG_HEALTH_LIVENESS_PROBE_ENABLED, "true");
    CamelOperandConfiguration.Health health = configuration.health();
    if (health != null) {
        annotations.putIfAbsent(TRAIT_CAMEL_APACHE_ORG_HEALTH_READINESS_SUCCESS_THRESHOLD, health.readinessSuccessThreshold());
        annotations.putIfAbsent(TRAIT_CAMEL_APACHE_ORG_HEALTH_READINESS_FAILURE_THRESHOLD, health.readinessFailureThreshold());
        annotations.putIfAbsent(TRAIT_CAMEL_APACHE_ORG_HEALTH_READINESS_PERIOD, health.readinessPeriodSeconds());
        annotations.putIfAbsent(TRAIT_CAMEL_APACHE_ORG_HEALTH_READINESS_TIMEOUT, health.readinessTimeoutSeconds());
        annotations.putIfAbsent(TRAIT_CAMEL_APACHE_ORG_HEALTH_LIVENESS_SUCCESS_THRESHOLD, health.livenessSuccessThreshold());
        annotations.putIfAbsent(TRAIT_CAMEL_APACHE_ORG_HEALTH_LIVENESS_FAILURE_THRESHOLD, health.livenessFailureThreshold());
        annotations.putIfAbsent(TRAIT_CAMEL_APACHE_ORG_HEALTH_LIVENESS_PERIOD, health.livenessPeriodSeconds());
        annotations.putIfAbsent(TRAIT_CAMEL_APACHE_ORG_HEALTH_LIVENESS_TIMEOUT, health.livenessTimeoutSeconds());
    }
    if (configuration.connectors() != null) {
        if (configuration.connectors().traits() != null) {
            annotations.putAll(configuration.connectors().traits());
        }
        if (configuration.connectors().types() != null) {
            final String typeId = connector.getSpec().getDeployment().getConnectorTypeId();
            final CamelOperandConfiguration.ConnectorConfiguration typeConfig = configuration.connectors().types().get(typeId);
            if (typeConfig != null && typeConfig.traits() != null) {
                annotations.putAll(typeConfig.traits());
            }
        }
    }
    return List.of(secret, binding);
}
Also used : Operator(org.bf2.cos.fleetshard.api.Operator) ObjectMeta(io.fabric8.kubernetes.api.model.ObjectMeta) KameletBindingSpec(org.bf2.cos.fleetshard.operator.camel.model.KameletBindingSpec) ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) KameletEndpoint(org.bf2.cos.fleetshard.operator.camel.model.KameletEndpoint) Secret(io.fabric8.kubernetes.api.model.Secret) KameletBinding(org.bf2.cos.fleetshard.operator.camel.model.KameletBinding) SuppressFBWarnings(edu.umd.cs.findbugs.annotations.SuppressFBWarnings)

Example 5 with ConnectorConfiguration

use of org.bf2.cos.fleetshard.operator.connector.ConnectorConfiguration in project cos-fleetshard by bf2fc6cc711aee1a0c2a.

the class CamelOperandSupport method createSteps.

public static List<KameletEndpoint> createSteps(ManagedConnector connector, ConnectorConfiguration<ObjectNode, ObjectNode> connectorConfiguration, CamelShardMetadata shardMetadata, KameletEndpoint kafkaEndpoint) {
    String consumes = Optional.ofNullable(connectorConfiguration.getDataShapeSpec()).map(spec -> spec.at("/consumes/format")).filter(node -> !node.isMissingNode()).map(JsonNode::asText).orElse(shardMetadata.getConsumes());
    String produces = Optional.ofNullable(connectorConfiguration.getDataShapeSpec()).map(spec -> spec.at("/produces/format")).filter(node -> !node.isMissingNode()).map(JsonNode::asText).orElse(shardMetadata.getProduces());
    final ArrayNode steps = connectorConfiguration.getProcessorsSpec();
    final List<KameletEndpoint> stepDefinitions = new ArrayList<>(steps.size() + 2);
    if (consumes != null) {
        switch(consumes) {
            case "application/json":
                stepDefinitions.add(kamelet("cos-decoder-json-action", properties -> {
                    if (shardMetadata.getConsumesClass() != null) {
                        properties.put("contentClass", shardMetadata.getConsumesClass());
                    }
                }));
                break;
            case "avro/binary":
                stepDefinitions.add(kamelet("cos-decoder-avro-action", properties -> {
                    if (shardMetadata.getConsumesClass() != null) {
                        properties.put("contentClass", shardMetadata.getConsumesClass());
                    }
                }));
                break;
            case "application/x-java-object":
                stepDefinitions.add(kamelet("cos-decoder-pojo-action", properties -> {
                    if (shardMetadata.getConsumesClass() != null) {
                        properties.put("mimeType", produces);
                    }
                }));
                break;
            case "text/plain":
            case "application/octet-stream":
                break;
            default:
                throw new IllegalArgumentException("Unsupported value format " + consumes);
        }
    }
    for (JsonNode step : steps) {
        var element = step.fields().next();
        String templateId = shardMetadata.getKamelets().getProcessors().get(element.getKey());
        if (templateId == null) {
            throw new IllegalArgumentException("Unknown processor: " + element.getKey());
        }
        stepDefinitions.add(configureStep(templateId, (ObjectNode) element.getValue()));
    }
    if (produces != null) {
        switch(produces) {
            case "application/json":
                stepDefinitions.add(kamelet("cos-encoder-json-action", properties -> {
                    if (shardMetadata.getProducesClass() != null) {
                        properties.put("contentClass", shardMetadata.getProducesClass());
                    }
                }));
                break;
            case "avro/binary":
                stepDefinitions.add(kamelet("cos-encoder-avro-action", properties -> {
                    if (shardMetadata.getProducesClass() != null) {
                        properties.put("contentClass", shardMetadata.getProducesClass());
                    }
                }));
                break;
            case "text/plain":
                stepDefinitions.add(kamelet("cos-encoder-string-action"));
                break;
            case "application/octet-stream":
                stepDefinitions.add(kamelet("cos-encoder-bytearray-action"));
                break;
            default:
                throw new IllegalArgumentException("Unsupported value format " + produces);
        }
    }
    // If it is a sink, then it consumes from kafka
    if (isSink(shardMetadata)) {
        String valueDeserializer = "org.bf2.cos.connector.camel.serdes.bytes.ByteArrayDeserializer";
        if ("application/json".equals(consumes) && hasSchemaRegistry(connector)) {
            valueDeserializer = "org.bf2.cos.connector.camel.serdes.json.JsonDeserializer";
        } else if ("avro/binary".equals(produces) && hasSchemaRegistry(connector)) {
            valueDeserializer = "org.bf2.cos.connector.camel.serdes.avro.AvroDeserializer";
        }
        kafkaEndpoint.getProperties().put("valueDeserializer", valueDeserializer);
    }
    // If it is a source, then it produces to kafka
    if (isSource(shardMetadata)) {
        String valueSerializer = "org.bf2.cos.connector.camel.serdes.bytes.ByteArraySerializer";
        if ("application/json".equals(produces) && hasSchemaRegistry(connector)) {
            valueSerializer = "org.bf2.cos.connector.camel.serdes.json.JsonSerializer";
        } else if ("avro/binary".equals(produces) && hasSchemaRegistry(connector)) {
            valueSerializer = "org.bf2.cos.connector.camel.serdes.avro.AvroSerializer";
        }
        kafkaEndpoint.getProperties().put("valueSerializer", valueSerializer);
    }
    return stepDefinitions;
}
Also used : SA_CLIENT_ID_PROPERTY(org.bf2.cos.fleetshard.operator.camel.CamelConstants.SA_CLIENT_ID_PROPERTY) ConnectorStatusSpec(org.bf2.cos.fleetshard.api.ConnectorStatusSpec) LoggerFactory(org.slf4j.LoggerFactory) ERROR_HANDLER_LOG_TYPE(org.bf2.cos.fleetshard.operator.camel.CamelConstants.ERROR_HANDLER_LOG_TYPE) KameletEndpoint(org.bf2.cos.fleetshard.operator.camel.model.KameletEndpoint) StringUtils(org.apache.commons.lang3.StringUtils) KameletBindingStatus(org.bf2.cos.fleetshard.operator.camel.model.KameletBindingStatus) ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) ArrayList(java.util.ArrayList) EndpointKamelet(org.bf2.cos.fleetshard.operator.camel.model.EndpointKamelet) SA_CLIENT_SECRET_PLACEHOLDER(org.bf2.cos.fleetshard.operator.camel.CamelConstants.SA_CLIENT_SECRET_PLACEHOLDER) ERROR_HANDLER_STOP_URI(org.bf2.cos.fleetshard.operator.camel.CamelConstants.ERROR_HANDLER_STOP_URI) ERROR_HANDLER_TYPE_DLQ(org.bf2.cos.fleetshard.operator.camel.CamelConstants.ERROR_HANDLER_TYPE_DLQ) Serialization(io.fabric8.kubernetes.client.utils.Serialization) Locale(java.util.Locale) Map(java.util.Map) SA_CLIENT_ID_PLACEHOLDER(org.bf2.cos.fleetshard.operator.camel.CamelConstants.SA_CLIENT_ID_PLACEHOLDER) JsonNode(com.fasterxml.jackson.databind.JsonNode) ERROR_HANDLER_SINK_CHANNEL_TYPE(org.bf2.cos.fleetshard.operator.camel.CamelConstants.ERROR_HANDLER_SINK_CHANNEL_TYPE) ManagedConnector(org.bf2.cos.fleetshard.api.ManagedConnector) ConnectorConfiguration(org.bf2.cos.fleetshard.operator.connector.ConnectorConfiguration) ERROR_HANDLER_DEAD_LETTER_CHANNEL_KAMELET(org.bf2.cos.fleetshard.operator.camel.CamelConstants.ERROR_HANDLER_DEAD_LETTER_CHANNEL_KAMELET) CamelShardMetadata(org.bf2.cos.fleetshard.operator.camel.model.CamelShardMetadata) Logger(org.slf4j.Logger) Iterator(java.util.Iterator) ERROR_HANDLER_TYPE_LOG(org.bf2.cos.fleetshard.operator.camel.CamelConstants.ERROR_HANDLER_TYPE_LOG) KameletEndpoint.kamelet(org.bf2.cos.fleetshard.operator.camel.model.KameletEndpoint.kamelet) CaseUtils(org.apache.commons.text.CaseUtils) ERROR_HANDLER_TYPE_STOP(org.bf2.cos.fleetshard.operator.camel.CamelConstants.ERROR_HANDLER_TYPE_STOP) ServiceAccountSpec(org.bf2.cos.fleetshard.api.ServiceAccountSpec) KameletBinding(org.bf2.cos.fleetshard.operator.camel.model.KameletBinding) StandardCharsets(java.nio.charset.StandardCharsets) Kamelet(org.bf2.cos.fleetshard.operator.camel.model.Kamelet) ArrayNode(com.fasterxml.jackson.databind.node.ArrayNode) Base64(java.util.Base64) List(java.util.List) Condition(io.fabric8.kubernetes.api.model.Condition) CONNECTOR_TYPE_SOURCE(org.bf2.cos.fleetshard.operator.camel.CamelConstants.CONNECTOR_TYPE_SOURCE) TreeMap(java.util.TreeMap) KubernetesClient(io.fabric8.kubernetes.client.KubernetesClient) Optional(java.util.Optional) SA_CLIENT_SECRET_PROPERTY(org.bf2.cos.fleetshard.operator.camel.CamelConstants.SA_CLIENT_SECRET_PROPERTY) CONNECTOR_TYPE_SINK(org.bf2.cos.fleetshard.operator.camel.CamelConstants.CONNECTOR_TYPE_SINK) JacksonUtil.iterator(org.bf2.cos.fleetshard.support.json.JacksonUtil.iterator) ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) KameletEndpoint(org.bf2.cos.fleetshard.operator.camel.model.KameletEndpoint) ArrayList(java.util.ArrayList) JsonNode(com.fasterxml.jackson.databind.JsonNode) ArrayNode(com.fasterxml.jackson.databind.node.ArrayNode)

Aggregations

ObjectNode (com.fasterxml.jackson.databind.node.ObjectNode)6 KubernetesClient (io.fabric8.kubernetes.client.KubernetesClient)5 ObjectMetaBuilder (io.fabric8.kubernetes.api.model.ObjectMetaBuilder)4 ServiceAccountSpec (org.bf2.cos.fleetshard.api.ServiceAccountSpec)4 KameletBinding (org.bf2.cos.fleetshard.operator.camel.model.KameletBinding)4 Secret (io.fabric8.kubernetes.api.model.Secret)3 List (java.util.List)3 Map (java.util.Map)3 TreeMap (java.util.TreeMap)3 ManagedConnector (org.bf2.cos.fleetshard.api.ManagedConnector)3 CONNECTOR_TYPE_SINK (org.bf2.cos.fleetshard.operator.camel.CamelConstants.CONNECTOR_TYPE_SINK)3 CONNECTOR_TYPE_SOURCE (org.bf2.cos.fleetshard.operator.camel.CamelConstants.CONNECTOR_TYPE_SOURCE)3 CamelShardMetadata (org.bf2.cos.fleetshard.operator.camel.model.CamelShardMetadata)3 KameletEndpoint (org.bf2.cos.fleetshard.operator.camel.model.KameletEndpoint)3 ConnectorConfiguration (org.bf2.cos.fleetshard.operator.connector.ConnectorConfiguration)3 JsonNode (com.fasterxml.jackson.databind.JsonNode)2 ArrayNode (com.fasterxml.jackson.databind.node.ArrayNode)2 Condition (io.fabric8.kubernetes.api.model.Condition)2 SecretBuilder (io.fabric8.kubernetes.api.model.SecretBuilder)2 Serialization (io.fabric8.kubernetes.client.utils.Serialization)2