syntax = "proto3";

package envoy.extensions.filters.network.kafka_mesh.v3alpha;

import "xds/annotations/v3/status.proto";

import "udpa/annotations/status.proto";
import "validate/validate.proto";

option java_package = "io.envoyproxy.envoy.extensions.filters.network.kafka_mesh.v3alpha";
option java_outer_classname = "KafkaMeshProto";
option java_multiple_files = true;
option go_package = "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/kafka_mesh/v3alpha";
option (udpa.annotations.file_status).package_version_status = ACTIVE;
option (xds.annotations.v3.file_status).work_in_progress = true;

// [#protodoc-title: Kafka Mesh]
// Kafka Mesh :ref:`configuration overview <config_network_filters_kafka_mesh>`.
// [#extension: envoy.filters.network.kafka_mesh]

// [#next-free-field: 6]
message KafkaMesh {
  enum ConsumerProxyMode {
    // Records received are going to be distributed amongst downstream consumer connections.
    // In this mode Envoy uses librdkafka consumers pointing at upstream Kafka clusters, what means that these
    // consumers' position is meaningful and affects what records are received from upstream.
    // Users might want to take a look into these consumers' custom configuration to manage their auto-committing
    // capabilities, as it will impact Envoy's behaviour in case of restarts.
    StatefulConsumerProxy = 0;
  }

  // Envoy's host that's advertised to clients.
  // Has the same meaning as corresponding Kafka broker properties.
  // Usually equal to filter chain's listener config, but needs to be reachable by clients
  // (so 0.0.0.0 will not work).
  string advertised_host = 1 [(validate.rules).string = {min_len: 1}];

  // Envoy's port that's advertised to clients.
  int32 advertised_port = 2 [(validate.rules).int32 = {gt: 0}];

  // Upstream clusters this filter will connect to.
  repeated KafkaClusterDefinition upstream_clusters = 3;

  // Rules that will decide which cluster gets which request.
  repeated ForwardingRule forwarding_rules = 4;

  // How the consumer proxying should behave - this relates mostly to Fetch request handling.
  ConsumerProxyMode consumer_proxy_mode = 5;
}

// [#next-free-field: 6]
message KafkaClusterDefinition {
  // Cluster name.
  string cluster_name = 1 [(validate.rules).string = {min_len: 1}];

  // Kafka cluster address.
  string bootstrap_servers = 2 [(validate.rules).string = {min_len: 1}];

  // Default number of partitions present in this cluster.
  // This is especially important for clients that do not specify partition in their payloads and depend on this value for hashing.
  // The same number of partitions is going to be used by upstream-pointing Kafka consumers for consumer proxying scenarios.
  int32 partition_count = 3 [(validate.rules).int32 = {gt: 0}];

  // Custom configuration passed to Kafka producer.
  map<string, string> producer_config = 4;

  // Custom configuration passed to Kafka consumer.
  map<string, string> consumer_config = 5;
}

message ForwardingRule {
  // Cluster name.
  string target_cluster = 1;

  oneof trigger {
    // Intended place for future types of forwarding rules.
    string topic_prefix = 2;
  }
}
