// Copyright 2017 Istio 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.
syntax = "proto3";

import "google/protobuf/any.proto";
import "google/protobuf/duration.proto";
import "routing/v1alpha1/route_rule.proto";

package istio.routing.v1alpha1;

option go_package = "istio.io/api/routing/v1alpha1";

// DestinationPolicy defines client/caller-side policies that determine how
// to handle traffic bound to a particular destination service. The policy
// specifies configuration for load balancing and circuit breakers. For
// example, a simple load balancing policy for the ratings service would
// look as follows:
//
//     metadata:
//       name: ratings-lb-policy
//       namespace: default # optional (default is "default")
//     spec:
//       destination:
//         name: ratings
//       loadBalancing:
//         name: ROUND_ROBIN
//
// The FQDN of the destination service is composed from the destination name and meta namespace fields, along with
// a platform-specific domain suffix
// (e.g. on Kubernetes, "reviews" + "default" + "svc.cluster.local" -> "reviews.default.svc.cluster.local").
//
// A destination policy can be restricted to a particular version of a
// service or applied to all versions. It can also be restricted to calls from
// a particular source. For example, the following load balancing policy
// applies to version v1 of the ratings service running in the prod
// environment but only when called from version v2 of the reviews service:
//
//     metadata:
//       name: ratings-lb-policy
//       namespace: default
//     spec:
//       source:
//         name: reviews
//         labels:
//           version: v2
//       destination:
//         name: ratings
//         labels:
//           env: prod
//           version: v1
//       loadBalancing:
//         name: ROUND_ROBIN
//
// *Note:* Destination policies will be applied only if the corresponding
// tagged instances are explicitly routed to. In other words, for every
// destination policy defined, at least one route rule must refer to the
// service version indicated in the destination policy.
message DestinationPolicy {
  // Optional: Destination uniquely identifies the destination service associated
  // with this policy.
  IstioService destination = 1;

  // Optional: Source uniquely identifies the source service associated
  // with this policy.
  IstioService source = 2;

  // Load balancing policy.
  LoadBalancing load_balancing = 3;

  // Circuit breaker policy.
  CircuitBreaker circuit_breaker = 4;

  //(-- Other custom policy implementations --)
  google.protobuf.Any custom = 100;
}

// Load balancing policy to use when forwarding traffic. These policies
// directly correlate to [load balancer
// types](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/load_balancing)
// supported by Envoy. Example,
//
//     metadata:
//       name: reviews-lb-policy
//       namespace: default
//     spec:
//       destination:
//         name: reviews
//       loadBalancing:
//         name: RANDOM
//
message LoadBalancing {
  // Load balancing algorithms supported by Envoy.
  enum SimpleLBPolicy {

    // Simple round robin policy.
    ROUND_ROBIN = 0;

    // The least request load balancer uses an O(1) algorithm which selects
    // two random healthy hosts and picks the host which has fewer active
    // requests.
    LEAST_CONN = 1;

    // The random load balancer selects a random healthy host. The random
    // load balancer generally performs better than round robin if no health
    // checking policy is configured.
    RANDOM = 2;
  }
  oneof lb_policy {
    // Load balancing policy name (as defined in SimpleLBPolicy below)
    SimpleLBPolicy name = 1;
    //(-- Custom LB policy implementations --)
    google.protobuf.Any custom = 2 ;
  }
}

// Circuit breaker configuration for Envoy. The circuit breaker
// implementation is fine-grained in that it tracks the success/failure
// rates of individual hosts in the load balancing pool. Hosts that
// continually return errors for API calls are ejected from the pool for a
// pre-defined period of time.
// See Envoy's
// [circuit breaker](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/circuit_breaking)
// and [outlier detection](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/outlier)
// for more details.
message CircuitBreaker {
  // A simple circuit breaker can be set based on a number of criteria such as
  // connection and request limits. For example, the following destination
  // policy sets a limit of 100 connections to "reviews" service version
  // "v1" backends.
  //
  //     metadata:
  //       name: reviews-cb-policy
  //       namespace: default
  //     spec:
  //       destination:
  //         name: reviews
  //         labels:
  //           version: v1
  //       circuitBreaker:
  //         simpleCb:
  //           maxConnections: 100
  //
  // The following destination policy sets a limit of 100 connections and
  // 1000 concurrent requests, with no more than 10 req/connection to
  // "reviews" service version "v1" backends. In addition, it configures
  // hosts to be scanned every 5 mins, such that any host that fails 7
  // consecutive times with 5XX error code will be ejected for 15 minutes.
  //
  //     metadata:
  //       name: reviews-cb-policy
  //       namespace: default
  //     spec:
  //       destination:
  //         name: reviews
  //         labels:
  //           version: v1
  //       circuitBreaker:
  //         simpleCb:
  //           maxConnections: 100
  //           httpMaxRequests: 1000
  //           httpMaxRequestsPerConnection: 10
  //           httpConsecutiveErrors: 7
  //           sleepWindow: 15m
  //           httpDetectionInterval: 5m
  //
  message SimpleCircuitBreakerPolicy {
    // Maximum number of connections to a backend.
    int32 max_connections = 1;

    // Maximum number of pending requests to a backend. Default 1024
    int32 http_max_pending_requests = 2;

    // Maximum number of requests to a backend. Default 1024
    int32 http_max_requests = 3;

    // Minimum time the circuit will be open. format: 1h/1m/1s/1ms. MUST
    // BE >=1ms. Default is 30s.
    google.protobuf.Duration sleep_window = 4;

    // Number of 5XX errors before circuit is opened. Defaults to 5.
    int32 http_consecutive_errors = 5;

    // Time interval between ejection sweep analysis. format:
    // 1h/1m/1s/1ms. MUST BE >=1ms. Default is 10s.
    google.protobuf.Duration http_detection_interval = 6;

    // Maximum number of requests per connection to a backend. Setting this
    // parameter to 1 disables keep alive.
    int32 http_max_requests_per_connection = 7;

    // Maximum % of hosts in the load balancing pool for the destination
    // service that can be ejected by the circuit breaker. Defaults to
    // 10%.
    int32 http_max_ejection_percent = 8;

    // Maximum number of retries that can be outstanding to all hosts in a
    // cluster at a given time. Defaults to 3.
    int32 http_max_retries = 9;
  }
  oneof cb_policy {
    SimpleCircuitBreakerPolicy simple_cb = 1;
    //(-- For proxies that support custom circuit breaker policies. --)
    google.protobuf.Any custom = 2 ;
  }
}
