// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

syntax = "proto3";

package hashicorp.consul.mesh.v2beta1;

import "google/protobuf/duration.proto";
import "google/protobuf/wrappers.proto";
import "pbcatalog/v2beta1/protocol.proto";
import "pbcatalog/v2beta1/selector.proto";
import "pbmesh/v2beta1/connection.proto";
import "pbmesh/v2beta1/routing.proto";
import "pbresource/annotations.proto";
import "pbresource/resource.proto";

message DestinationsConfiguration {
  option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE};

  // Selection of workloads these destinations should apply to.
  // These can be prefixes or specific workload names.
  hashicorp.consul.catalog.v2beta1.WorkloadSelector workloads = 1;

  // DefaultConfig applies to all destinations for the workloads selected by this resource.
  DestinationConfiguration default_config = 2;

  // ConfigOverrides provides per-destination or per-destination-port config overrides.
  repeated DestinationConfigOverrides config_overrides = 3;
}

// DestinationConfigOverrides allow to override destination configuration per destination_ref/port/datacenter.
// In that sense, those three fields (destination_ref, destination_port and datacenter) are treated
// sort of like map keys and config is a like a map value for that key.
message DestinationConfigOverrides {
  // DestinationRef is the reference to an destination service that this configuration applies to.
  // This has to be pbcatalog.Service type.
  hashicorp.consul.resource.Reference destination_ref = 1;

  // DestinationPort is the port of the destination service.
  //
  // For more details on potential values of this field, see documentation for Service.ServicePort.
  //
  // If not provided, this configuration will apply to all ports of an destination.
  string destination_port = 2;

  // Datacenter is the datacenter for where this destination service lives.
  string datacenter = 3;

  // Config is the configuration that should apply to this destination.
  DestinationConfiguration config = 4;
}

message DestinationConfiguration {
  // Protocol overrides destination's port protocol. If no port for an destination is specified
  // or if used in the default configuration, this protocol will be used for all ports
  // or for all ports of all destinations respectively.
  hashicorp.consul.catalog.v2beta1.Protocol protocol = 1;

  // ConnectTimeout is the timeout used when making a new
  // connection to this destination. Defaults to 5 seconds if not set.
  // +kubebuilder:validation:Format=duration
  google.protobuf.Duration connect_timeout = 2;

  // Limits are the set of limits that are applied to the proxy for a specific destination.
  DestinationLimits limits = 3;

  // PassiveHealthCheck configuration determines how destination proxy instances will
  // be monitored for removal from the load balancing pool.
  PassiveHealthCheck passive_health_check = 4;

  // BalanceOutboundConnections indicates how the proxy should attempt to distribute
  // connections across worker threads.
  BalanceConnections balance_outbound_connections = 5;

  // MeshGatewayMode is the Mesh Gateway routing mode.
  MeshGatewayMode mesh_gateway_mode = 6;
}

// UpstreamLimits describes the limits that are associated with a specific
// destination of a service instance.
message DestinationLimits {
  // MaxConnections is the maximum number of connections the local proxy can
  // make to the destination service.
  google.protobuf.UInt32Value max_connections = 1;

  // MaxPendingRequests is the maximum number of requests that will be queued
  // waiting for an available connection. This is mostly applicable to HTTP/1.1
  // clusters since all HTTP/2 requests are streamed over a single
  // connection.
  google.protobuf.UInt32Value max_pending_requests = 2;

  // MaxConcurrentRequests is the maximum number of in-flight requests that will be allowed
  // to the destination cluster at a point in time. This is mostly applicable to HTTP/2
  // clusters since all HTTP/1.1 requests are limited by MaxConnections.
  google.protobuf.UInt32Value max_concurrent_requests = 3;
}

message PassiveHealthCheck {
  // Interval between health check analysis sweeps. Each sweep may remove
  // hosts or return hosts to the pool.
  // +kubebuilder:validation:Format=duration
  google.protobuf.Duration interval = 1;

  // MaxFailures is the count of consecutive failures that results in a host
  // being removed from the pool.
  uint32 max_failures = 2;

  // EnforcingConsecutive5XX is the % chance that a host will be actually ejected
  // when an outlier status is detected through consecutive 5xx.
  // This setting can be used to disable ejection or to ramp it up slowly. Defaults to 100.
  uint32 enforcing_consecutive_5xx = 3;
}
