// Copyright 2017-2018 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/api/field_behavior.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/wrappers.proto";

// $title: Virtual Service
// $description: Configuration affecting label/content routing, sni routing, etc.
// $location: https://istio.io/docs/reference/config/networking/virtual-service.html
// $aliases: [/docs/reference/config/networking/v1alpha3/virtual-service]

// Configuration affecting traffic routing. Here are a few terms useful to define
// in the context of traffic routing.
//
// `Service` a unit of application behavior bound to a unique name in a
// service registry. Services consist of multiple network *endpoints*
// implemented by workload instances running on pods, containers, VMs etc.
//
// `Service versions (a.k.a. subsets)` - In a continuous deployment
// scenario, for a given service, there can be distinct subsets of
// instances running different variants of the application binary. These
// variants are not necessarily different API versions. They could be
// iterative changes to the same service, deployed in different
// environments (prod, staging, dev, etc.). Common scenarios where this
// occurs include A/B testing, canary rollouts, etc. The choice of a
// particular version can be decided based on various criterion (headers,
// url, etc.) and/or by weights assigned to each version. Each service has
// a default version consisting of all its instances.
//
// `Source` - A downstream client calling a service.
//
// `Host` - The address used by a client when attempting to connect to a
// service.
//
// `Access model` - Applications address only the destination service
// (Host) without knowledge of individual service versions (subsets). The
// actual choice of the version is determined by the proxy/sidecar, enabling the
// application code to decouple itself from the evolution of dependent
// services.
//
// A `VirtualService` defines a set of traffic routing rules to apply when a host is
// addressed. Each routing rule defines matching criteria for traffic of a specific
// protocol. If the traffic is matched, then it is sent to a named destination service
// (or subset/version of it) defined in the registry.
//
// The source of traffic can also be matched in a routing rule. This allows routing
// to be customized for specific client contexts.
//
// The following example on Kubernetes, routes all HTTP traffic by default to
// pods of the reviews service with label "version: v1". In addition,
// HTTP requests with path starting with /wpcatalog/ or /consumercatalog/ will
// be rewritten to /newcatalog and sent to pods with label "version: v2".
//
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: VirtualService
// metadata:
//   name: reviews-route
// spec:
//   hosts:
//   - reviews.prod.svc.cluster.local
//   http:
//   - name: "reviews-v2-routes"
//     match:
//     - uri:
//         prefix: "/wpcatalog"
//     - uri:
//         prefix: "/consumercatalog"
//     rewrite:
//       uri: "/newcatalog"
//     route:
//     - destination:
//         host: reviews.prod.svc.cluster.local
//         subset: v2
//   - name: "reviews-v1-route"
//     route:
//     - destination:
//         host: reviews.prod.svc.cluster.local
//         subset: v1
// ```
//
// A subset/version of a route destination is identified with a reference
// to a named service subset which must be declared in a corresponding
// `DestinationRule`.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: DestinationRule
// metadata:
//   name: reviews-destination
// spec:
//   host: reviews.prod.svc.cluster.local
//   subsets:
//   - name: v1
//     labels:
//       version: v1
//   - name: v2
//     labels:
//       version: v2
// ```
//
package istio.networking.v1alpha3;

option go_package = "istio.io/api/networking/v1alpha3";

// Configuration affecting traffic routing.
//
// <!-- go code generation tags
// +kubetype-gen
// +kubetype-gen:groupVersion=networking.istio.io/v1alpha3
// +genclient
// +k8s:deepcopy-gen=true
// -->
message VirtualService {
  // The destination hosts to which traffic is being sent. Could
  // be a DNS name with wildcard prefix or an IP address.  Depending on the
  // platform, short-names can also be used instead of a FQDN (i.e. has no
  // dots in the name). In such a scenario, the FQDN of the host would be
  // derived based on the underlying platform.
  //
  // A single VirtualService can be used to describe all the traffic
  // properties of the corresponding hosts, including those for multiple
  // HTTP and TCP ports. Alternatively, the traffic properties of a host
  // can be defined using more than one VirtualService, with certain
  // caveats. Refer to the
  // [Operations Guide](https://istio.io/docs/ops/traffic-management/deploy-guidelines/#multiple-virtual-services-and-destination-rules-for-the-same-host)
  // for details.
  //
  // *Note for Kubernetes users*: When short names are used (e.g. "reviews"
  // instead of "reviews.default.svc.cluster.local"), Istio will interpret
  // the short name based on the namespace of the rule, not the service. A
  // rule in the "default" namespace containing a host "reviews" will be
  // interpreted as "reviews.default.svc.cluster.local", irrespective of
  // the actual namespace associated with the reviews service. _To avoid
  // potential misconfigurations, it is recommended to always use fully
  // qualified domain names over short names._
  //
  // The hosts field applies to both HTTP and TCP services. Service inside
  // the mesh, i.e., those found in the service registry, must always be
  // referred to using their alphanumeric names. IP addresses are allowed
  // only for services defined via the Gateway.
  repeated string hosts = 1 [(google.api.field_behavior) = REQUIRED];

  // The names of gateways and sidecars that should apply these routes. A
  // single VirtualService is used for sidecars inside the mesh as well as
  // for one or more gateways. The selection condition imposed by this
  // field can be overridden using the source field in the match conditions
  // of protocol-specific routes. The reserved word `mesh` is used to imply
  // all the sidecars in the mesh. When this field is omitted, the default
  // gateway (`mesh`) will be used, which would apply the rule to all
  // sidecars in the mesh. If a list of gateway names is provided, the
  // rules will apply only to the gateways. To apply the rules to both
  // gateways and sidecars, specify `mesh` as one of the gateway names.
  repeated string gateways = 2;

  // An ordered list of route rules for HTTP traffic. HTTP routes will be
  // applied to platform service ports named 'http-*'/'http2-*'/'grpc-*', gateway
  // ports with protocol HTTP/HTTP2/GRPC/ TLS-terminated-HTTPS and service
  // entry ports using HTTP/HTTP2/GRPC protocols.  The first rule matching
  // an incoming request is used.
  repeated HTTPRoute http = 3;

  // An ordered list of route rule for non-terminated TLS & HTTPS
  // traffic. Routing is typically performed using the SNI value presented
  // by the ClientHello message. TLS routes will be applied to platform
  // service ports named 'https-*', 'tls-*', unterminated gateway ports using
  // HTTPS/TLS protocols (i.e. with "passthrough" TLS mode) and service
  // entry ports using HTTPS/TLS protocols.  The first rule matching an
  // incoming request is used.  NOTE: Traffic 'https-*' or 'tls-*' ports
  // without associated virtual service will be treated as opaque TCP
  // traffic.
  repeated TLSRoute tls = 5;

  // An ordered list of route rules for opaque TCP traffic. TCP routes will
  // be applied to any port that is not a HTTP or TLS port. The first rule
  // matching an incoming request is used.
  repeated TCPRoute tcp = 4;

  // A list of namespaces to which this virtual service is exported. Exporting a
  // virtual service allows it to be used by sidecars and gateways defined in
  // other namespaces. This feature provides a mechanism for service owners
  // and mesh administrators to control the visibility of virtual services
  // across namespace boundaries.
  //
  // If no namespaces are specified then the virtual service is exported to all
  // namespaces by default.
  //
  // The value "." is reserved and defines an export to the same namespace that
  // the virtual service is declared in. Similarly the value "*" is reserved and
  // defines an export to all namespaces.
  //
  // NOTE: in the current release, the `exportTo` value is restricted to
  // "." or "*" (i.e., the current namespace or all namespaces).
  repeated string export_to = 6;
}

// Destination indicates the network addressable service to which the
// request/connection will be sent after processing a routing rule. The
// destination.host should unambiguously refer to a service in the service
// registry. Istio's service registry is composed of all the services found
// in the platform's service registry (e.g., Kubernetes services, Consul
// services), as well as services declared through the
// [ServiceEntry](https://istio.io/docs/reference/config/networking/service-entry/#ServiceEntry) resource.
//
// *Note for Kubernetes users*: When short names are used (e.g. "reviews"
// instead of "reviews.default.svc.cluster.local"), Istio will interpret
// the short name based on the namespace of the rule, not the service. A
// rule in the "default" namespace containing a host "reviews will be
// interpreted as "reviews.default.svc.cluster.local", irrespective of the
// actual namespace associated with the reviews service. _To avoid potential
// misconfigurations, it is recommended to always use fully qualified
// domain names over short names._
//
// The following Kubernetes example routes all traffic by default to pods
// of the reviews service with label "version: v1" (i.e., subset v1), and
// some to subset v2, in a Kubernetes environment.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: VirtualService
// metadata:
//   name: reviews-route
//   namespace: foo
// spec:
//   hosts:
//   - reviews # interpreted as reviews.foo.svc.cluster.local
//   http:
//   - match:
//     - uri:
//         prefix: "/wpcatalog"
//     - uri:
//         prefix: "/consumercatalog"
//     rewrite:
//       uri: "/newcatalog"
//     route:
//     - destination:
//         host: reviews # interpreted as reviews.foo.svc.cluster.local
//         subset: v2
//   - route:
//     - destination:
//         host: reviews # interpreted as reviews.foo.svc.cluster.local
//         subset: v1
// ```
//
// And the associated DestinationRule
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: DestinationRule
// metadata:
//   name: reviews-destination
//   namespace: foo
// spec:
//   host: reviews # interpreted as reviews.foo.svc.cluster.local
//   subsets:
//   - name: v1
//     labels:
//       version: v1
//   - name: v2
//     labels:
//       version: v2
// ```
//
// The following VirtualService sets a timeout of 5s for all calls to
// productpage.prod.svc.cluster.local service in Kubernetes. Notice that
// there are no subsets defined in this rule. Istio will fetch all
// instances of productpage.prod.svc.cluster.local service from the service
// registry and populate the sidecar's load balancing pool. Also, notice
// that this rule is set in the istio-system namespace but uses the fully
// qualified domain name of the productpage service,
// productpage.prod.svc.cluster.local. Therefore the rule's namespace does
// not have an impact in resolving the name of the productpage service.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: VirtualService
// metadata:
//   name: my-productpage-rule
//   namespace: istio-system
// spec:
//   hosts:
//   - productpage.prod.svc.cluster.local # ignores rule namespace
//   http:
//   - timeout: 5s
//     route:
//     - destination:
//         host: productpage.prod.svc.cluster.local
// ```
//
// To control routing for traffic bound to services outside the mesh, external
// services must first be added to Istio's internal service registry using the
// ServiceEntry resource. VirtualServices can then be defined to control traffic
// bound to these external services. For example, the following rules define a
// Service for wikipedia.org and set a timeout of 5s for http requests.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: ServiceEntry
// metadata:
//   name: external-svc-wikipedia
// spec:
//   hosts:
//   - wikipedia.org
//   location: MESH_EXTERNAL
//   ports:
//   - number: 80
//     name: example-http
//     protocol: HTTP
//   resolution: DNS
//
// apiVersion: networking.istio.io/v1alpha3
// kind: VirtualService
// metadata:
//   name: my-wiki-rule
// spec:
//   hosts:
//   - wikipedia.org
//   http:
//   - timeout: 5s
//     route:
//     - destination:
//         host: wikipedia.org
// ```
message Destination {
  // The name of a service from the service registry. Service
  // names are looked up from the platform's service registry (e.g.,
  // Kubernetes services, Consul services, etc.) and from the hosts
  // declared by [ServiceEntry](https://istio.io/docs/reference/config/networking/service-entry/#ServiceEntry). Traffic forwarded to
  // destinations that are not found in either of the two, will be dropped.
  //
  // *Note for Kubernetes users*: When short names are used (e.g. "reviews"
  // instead of "reviews.default.svc.cluster.local"), Istio will interpret
  // the short name based on the namespace of the rule, not the service. A
  // rule in the "default" namespace containing a host "reviews will be
  // interpreted as "reviews.default.svc.cluster.local", irrespective of
  // the actual namespace associated with the reviews service. _To avoid
  // potential misconfigurations, it is recommended to always use fully
  // qualified domain names over short names._
  string host = 1 [(google.api.field_behavior) = REQUIRED];

  // The name of a subset within the service. Applicable only to services
  // within the mesh. The subset must be defined in a corresponding
  // DestinationRule.
  string subset = 2;

  // Specifies the port on the host that is being addressed. If a service
  // exposes only a single port it is not required to explicitly select the
  // port.
  PortSelector port = 3;
}

// Describes match conditions and actions for routing HTTP/1.1, HTTP2, and
// gRPC traffic. See VirtualService for usage examples.
message HTTPRoute {
  // The name assigned to the route for debugging purposes. The
  // route's name will be concatenated with the match's name and will
  // be logged in the access logs for requests matching this
  // route/match.
  string name = 17;

  // Match conditions to be satisfied for the rule to be
  // activated. All conditions inside a single match block have AND
  // semantics, while the list of match blocks have OR semantics. The rule
  // is matched if any one of the match blocks succeed.
  repeated HTTPMatchRequest match = 1;

  // A http rule can either redirect or forward (default) traffic. The
  // forwarding target can be one of several versions of a service (see
  // glossary in beginning of document). Weights associated with the
  // service version determine the proportion of traffic it receives.
  repeated HTTPRouteDestination route = 2;

  // A http rule can either redirect or forward (default) traffic. If
  // traffic passthrough option is specified in the rule,
  // route/redirect will be ignored. The redirect primitive can be used to
  // send a HTTP 301 redirect to a different URI or Authority.
  HTTPRedirect redirect = 3;

  // Rewrite HTTP URIs and Authority headers. Rewrite cannot be used with
  // Redirect primitive. Rewrite will be performed before forwarding.
  HTTPRewrite rewrite = 4;

  // Deprecated. Websocket upgrades are done automatically starting from Istio 1.0.
  // $hide_from_docs
  bool websocket_upgrade = 5;

  // Timeout for HTTP requests.
  google.protobuf.Duration timeout = 6;

  // Retry policy for HTTP requests.
  HTTPRetry retries = 7;

  // Fault injection policy to apply on HTTP traffic at the client side.
  // Note that timeouts or retries will not be enabled when faults are
  // enabled on the client side.
  HTTPFaultInjection fault = 8;

  // Mirror HTTP traffic to a another destination in addition to forwarding
  // the requests to the intended destination. Mirrored traffic is on a
  // best effort basis where the sidecar/gateway will not wait for the
  // mirrored cluster to respond before returning the response from the
  // original destination.  Statistics will be generated for the mirrored
  // destination.
  Destination mirror = 9;

  // Percentage of the traffic to be mirrored by the `mirror` field.
  // If this field is absent, all the traffic (100%) will be mirrored.
  // Max value is 100.
  google.protobuf.UInt32Value mirror_percent = 18;

  // Cross-Origin Resource Sharing policy (CORS). Refer to
  // [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)
  // for further details about cross origin resource sharing.
  CorsPolicy cors_policy = 10;

  // $hide_from_docs
  map<string, string> append_headers = 11 [deprecated=true];

  // $hide_from_docs
  repeated string remove_response_headers = 12 [deprecated=true];

  // $hide_from_docs
  map<string, string> append_response_headers = 13 [deprecated=true];

  // $hide_from_docs
  repeated string remove_request_headers = 14 [deprecated=true];

  // $hide_from_docs
  map<string, string> append_request_headers = 15 [deprecated=true];

  // Header manipulation rules
  Headers headers = 16;
}

// Message headers can be manipulated when Envoy forwards requests to,
// or responses from, a destination service. Header manipulation rules can
// be specified for a specific route destination or for all destinations.
// The following VirtualService adds a `test` header with the value `true`
// to requests that are routed to any `reviews` service destination.
// It also romoves the `foo` response header, but only from responses
// coming from the `v1` subset (version) of the `reviews` service.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: VirtualService
// metadata:
//   name: reviews-route
// spec:
//   hosts:
//   - reviews.prod.svc.cluster.local
//   http:
//   - headers:
//       request:
//         set:
//           test: true
//     route:
//     - destination:
//         host: reviews.prod.svc.cluster.local
//         subset: v2
//       weight: 25
//     - destination:
//         host: reviews.prod.svc.cluster.local
//         subset: v1
//       headers:
//         response:
//           remove:
//           - foo
//       weight: 75
// ```
message Headers {
  // Header manipulation rules to apply before forwarding a request
  // to the destination service
  HeaderOperations request = 1;
  // Header manipulation rules to apply before returning a response
  // to the caller
  HeaderOperations response = 2;

  // HeaderOperations Describes the header manipulations to apply
  message HeaderOperations {
    // Overwrite the headers specified by key with the given values
    map<string, string> set = 1;
    // Append the given values to the headers specified by keys
    // (will create a comma-separated list of values)
    map<string, string> add = 2;
    // Remove a the specified headers
    repeated string remove = 3;
  }
}

// Describes match conditions and actions for routing unterminated TLS
// traffic (TLS/HTTPS) The following routing rule forwards unterminated TLS
// traffic arriving at port 443 of gateway called "mygateway" to internal
// services in the mesh based on the SNI value.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: VirtualService
// metadata:
//   name: bookinfo-sni
// spec:
//   hosts:
//   - "*.bookinfo.com"
//   gateways:
//   - mygateway
//   tls:
//   - match:
//     - port: 443
//       sniHosts:
//       - login.bookinfo.com
//     route:
//     - destination:
//         host: login.prod.svc.cluster.local
//   - match:
//     - port: 443
//       sniHosts:
//       - reviews.bookinfo.com
//     route:
//     - destination:
//         host: reviews.prod.svc.cluster.local
// ```
message TLSRoute {
  // Match conditions to be satisfied for the rule to be
  // activated. All conditions inside a single match block have AND
  // semantics, while the list of match blocks have OR semantics. The rule
  // is matched if any one of the match blocks succeed.
  repeated TLSMatchAttributes match = 1 [(google.api.field_behavior) = REQUIRED];

  // The destination to which the connection should be forwarded to.
  repeated RouteDestination route = 2;
}

// Describes match conditions and actions for routing TCP traffic. The
// following routing rule forwards traffic arriving at port 27017 for
// mongo.prod.svc.cluster.local to another Mongo server on port 5555.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: VirtualService
// metadata:
//   name: bookinfo-Mongo
// spec:
//   hosts:
//   - mongo.prod.svc.cluster.local
//   tcp:
//   - match:
//     - port: 27017
//     route:
//     - destination:
//         host: mongo.backup.svc.cluster.local
//         port:
//           number: 5555
// ```
message TCPRoute {
  // Match conditions to be satisfied for the rule to be
  // activated. All conditions inside a single match block have AND
  // semantics, while the list of match blocks have OR semantics. The rule
  // is matched if any one of the match blocks succeed.
  repeated L4MatchAttributes match = 1;

  // The destination to which the connection should be forwarded to.
  repeated RouteDestination route = 2;
}

// HttpMatchRequest specifies a set of criterion to be met in order for the
// rule to be applied to the HTTP request. For example, the following
// restricts the rule to match only requests where the URL path
// starts with /ratings/v2/ and the request contains a custom `end-user` header
// with value `jason`.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: VirtualService
// metadata:
//   name: ratings-route
// spec:
//   hosts:
//   - ratings.prod.svc.cluster.local
//   http:
//   - match:
//     - headers:
//         end-user:
//           exact: jason
//       uri:
//         prefix: "/ratings/v2/"
//       ignoreUriCase: true
//     route:
//     - destination:
//         host: ratings.prod.svc.cluster.local
// ```
//
// HTTPMatchRequest CANNOT be empty.
message HTTPMatchRequest {
  // The name assigned to a match. The match's name will be
  // concatenated with the parent route's name and will be logged in
  // the access logs for requests matching this route.
  string name = 11;

  // URI to match
  // values are case-sensitive and formatted as follows:
  //
  // - `exact: "value"` for exact string match
  //
  // - `prefix: "value"` for prefix-based match
  //
  // - `regex: "value"` for ECMAscript style regex-based match
  //
  // **Note:** Case-insensitive matching could be enabled via the
  // `ignore_uri_case` flag.
  StringMatch uri = 1;

  // URI Scheme
  // values are case-sensitive and formatted as follows:
  //
  // - `exact: "value"` for exact string match
  //
  // - `prefix: "value"` for prefix-based match
  //
  // - `regex: "value"` for ECMAscript style regex-based match
  //
  StringMatch scheme = 2;

  // HTTP Method
  // values are case-sensitive and formatted as follows:
  //
  // - `exact: "value"` for exact string match
  //
  // - `prefix: "value"` for prefix-based match
  //
  // - `regex: "value"` for ECMAscript style regex-based match
  //
  StringMatch method = 3;

  // HTTP Authority
  // values are case-sensitive and formatted as follows:
  //
  // - `exact: "value"` for exact string match
  //
  // - `prefix: "value"` for prefix-based match
  //
  // - `regex: "value"` for ECMAscript style regex-based match
  //
  StringMatch authority = 4;

  // The header keys must be lowercase and use hyphen as the separator,
  // e.g. _x-request-id_.
  //
  // Header values are case-sensitive and formatted as follows:
  //
  // - `exact: "value"` for exact string match
  //
  // - `prefix: "value"` for prefix-based match
  //
  // - `regex: "value"` for ECMAscript style regex-based match
  //
  // **Note:** The keys `uri`, `scheme`, `method`, and `authority` will be ignored.
  map<string, StringMatch> headers = 5;

  // Specifies the ports on the host that is being addressed. Many services
  // only expose a single port or label ports with the protocols they support,
  // in these cases it is not required to explicitly select the port.
  uint32 port = 6;

  // One or more labels that constrain the applicability of a rule to
  // workloads with the given labels. If the VirtualService has a list of
  // gateways specified at the top, it must include the reserved gateway
  // `mesh` for this field to be applicable.
  map<string, string> source_labels = 7;

  // $hide_from_docs
  repeated string gateways = 8;

  // Query parameters for matching.
  //
  // Ex:
  // - For a query parameter like "?key=true", the map key would be "key" and
  //   the string match could be defined as `exact: "true"`.
  // - For a query parameter like "?key", the map key would be "key" and the
  //   string match could be defined as `exact: ""`.
  // - For a query parameter like "?key=123", the map key would be "key" and the
  //   string match could be defined as `regex: "\d+$"`. Note that this
  //   configuration will only match values like "123" but not "a123" or "123a".
  //
  // **Note:** `prefix` matching is currently not supported.
  map<string, StringMatch> query_params = 9;

  // Flag to specify whether the URI matching should be case-insensitive.
  //
  // **Note:** The case will be ignored only in the case of `exact` and `prefix`
  // URI matches.
  bool ignore_uri_case = 10;
}

// Each routing rule is associated with one or more service versions (see
// glossary in beginning of document). Weights associated with the version
// determine the proportion of traffic it receives. For example, the
// following rule will route 25% of traffic for the "reviews" service to
// instances with the "v2" tag and the remaining traffic (i.e., 75%) to
// "v1".
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: VirtualService
// metadata:
//   name: reviews-route
// spec:
//   hosts:
//   - reviews.prod.svc.cluster.local
//   http:
//   - route:
//     - destination:
//         host: reviews.prod.svc.cluster.local
//         subset: v2
//       weight: 25
//     - destination:
//         host: reviews.prod.svc.cluster.local
//         subset: v1
//       weight: 75
// ```
//
// And the associated DestinationRule
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: DestinationRule
// metadata:
//   name: reviews-destination
// spec:
//   host: reviews.prod.svc.cluster.local
//   subsets:
//   - name: v1
//     labels:
//       version: v1
//   - name: v2
//     labels:
//       version: v2
// ```
//
// Traffic can also be split across two entirely different services without
// having to define new subsets. For example, the following rule forwards 25% of
// traffic to reviews.com to dev.reviews.com
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: VirtualService
// metadata:
//   name: reviews-route-two-domains
// spec:
//   hosts:
//   - reviews.com
//   http:
//   - route:
//     - destination:
//         host: dev.reviews.com
//       weight: 25
//     - destination:
//         host: reviews.com
//       weight: 75
// ```
message HTTPRouteDestination {
  // Destination uniquely identifies the instances of a service
  // to which the request/connection should be forwarded to.
  Destination destination = 1 [(google.api.field_behavior) = REQUIRED];

  // The proportion of traffic to be forwarded to the service
  // version. (0-100). Sum of weights across destinations SHOULD BE == 100.
  // If there is only one destination in a rule, the weight value is assumed to
  // be 100.
  int32 weight = 2;

  // Use of `remove_response_header` is deprecated. Use the `headers`
  // field instead.
  repeated string remove_response_headers = 3 [deprecated=true];

  // Use of `append_response_headers` is deprecated. Use the `headers`
  // field instead.
  map<string, string> append_response_headers = 4 [deprecated=true];

  // Use of `remove_request_headers` is deprecated. Use the `headers`
  // field instead.
  repeated string remove_request_headers = 5 [deprecated=true];

  // Use of `append_request_headers` is deprecated. Use the `headers`
  // field instead.
  map<string, string> append_request_headers = 6 [deprecated=true];

  // Header manipulation rules
  Headers headers = 7;
}

// L4 routing rule weighted destination.
message RouteDestination {
  // Destination uniquely identifies the instances of a service
  // to which the request/connection should be forwarded to.
  Destination destination = 1 [(google.api.field_behavior) = REQUIRED];

  // The proportion of traffic to be forwarded to the service
  // version. If there is only one destination in a rule, all traffic will be
  // routed to it irrespective of the weight.
  int32 weight = 2;
}

// L4 connection match attributes. Note that L4 connection matching support
// is incomplete.
message L4MatchAttributes {
  // IPv4 or IPv6 ip addresses of destination with optional subnet.  E.g.,
  // a.b.c.d/xx form or just a.b.c.d.
  repeated string destination_subnets = 1;

  // Specifies the port on the host that is being addressed. Many services
  // only expose a single port or label ports with the protocols they support,
  // in these cases it is not required to explicitly select the port.
  uint32 port = 2;

  // IPv4 or IPv6 ip address of source with optional subnet. E.g., a.b.c.d/xx
  // form or just a.b.c.d
  // $hide_from_docs
  string source_subnet = 3;

  // One or more labels that constrain the applicability of a rule to
  // workloads with the given labels. If the VirtualService has a list of
  // gateways specified at the top, it should include the reserved gateway
  // `mesh` in order for this field to be applicable.
  map<string, string> source_labels = 4;

  // Names of gateways where the rule should be applied to. Gateway names
  // at the top of the VirtualService (if any) are overridden. The gateway
  // match is independent of sourceLabels.
  repeated string gateways = 5;
}

// TLS connection match attributes.
message TLSMatchAttributes {
  // SNI (server name indicator) to match on. Wildcard prefixes
  // can be used in the SNI value, e.g., *.com will match foo.example.com
  // as well as example.com. An SNI value must be a subset (i.e., fall
  // within the domain) of the corresponding virtual serivce's hosts.
  repeated string sni_hosts = 1 [(google.api.field_behavior) = REQUIRED];

  // IPv4 or IPv6 ip addresses of destination with optional subnet.  E.g.,
  // a.b.c.d/xx form or just a.b.c.d.
  repeated string destination_subnets = 2;

  // Specifies the port on the host that is being addressed. Many services
  // only expose a single port or label ports with the protocols they
  // support, in these cases it is not required to explicitly select the
  // port.
  uint32 port = 3;

  // IPv4 or IPv6 ip address of source with optional subnet. E.g., a.b.c.d/xx
  // form or just a.b.c.d
  // $hide_from_docs
  string source_subnet = 4;

  // One or more labels that constrain the applicability of a rule to
  // workloads with the given labels. If the VirtualService has a list of
  // gateways specified at the top, it should include the reserved gateway
  // `mesh` in order for this field to be applicable.
  map<string, string> source_labels = 5;

  // Names of gateways where the rule should be applied to. Gateway names
  // at the top of the VirtualService (if any) are overridden. The gateway
  // match is independent of sourceLabels.
  repeated string gateways = 6;
}

// HTTPRedirect can be used to send a 301 redirect response to the caller,
// where the Authority/Host and the URI in the response can be swapped with
// the specified values. For example, the following rule redirects
// requests for /v1/getProductRatings API on the ratings service to
// /v1/bookRatings provided by the bookratings service.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: VirtualService
// metadata:
//   name: ratings-route
// spec:
//   hosts:
//   - ratings.prod.svc.cluster.local
//   http:
//   - match:
//     - uri:
//         exact: /v1/getProductRatings
//     redirect:
//       uri: /v1/bookRatings
//       authority: newratings.default.svc.cluster.local
//   ...
// ```
message HTTPRedirect {
  // On a redirect, overwrite the Path portion of the URL with this
  // value. Note that the entire path will be replaced, irrespective of the
  // request URI being matched as an exact path or prefix.
  string uri = 1;

  // On a redirect, overwrite the Authority/Host portion of the URL with
  // this value.
  string authority = 2;

  // On a redirect, Specifies the HTTP status code to use in the redirect
  // response. The default response code is MOVED_PERMANENTLY (301).
  uint32 redirect_code = 3;
}

// HTTPRewrite can be used to rewrite specific parts of a HTTP request
// before forwarding the request to the destination. Rewrite primitive can
// be used only with HTTPRouteDestination. The following example
// demonstrates how to rewrite the URL prefix for api call (/ratings) to
// ratings service before making the actual API call.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: VirtualService
// metadata:
//   name: ratings-route
// spec:
//   hosts:
//   - ratings.prod.svc.cluster.local
//   http:
//   - match:
//     - uri:
//         prefix: /ratings
//     rewrite:
//       uri: /v1/bookRatings
//     route:
//     - destination:
//         host: ratings.prod.svc.cluster.local
//         subset: v1
// ```
//
message HTTPRewrite {
  // rewrite the path (or the prefix) portion of the URI with this
  // value. If the original URI was matched based on prefix, the value
  // provided in this field will replace the corresponding matched prefix.
  string uri = 1;

  // rewrite the Authority/Host header with this value.
  string authority = 2;
}

// Describes how to match a given string in HTTP headers. Match is
// case-sensitive.
message StringMatch {
  oneof match_type {

    // exact string match
    string exact = 1;

    // prefix-based match
    string prefix = 2;

    // ECMAscript style regex-based match
    string regex = 3;
  }
}

// Describes the retry policy to use when a HTTP request fails. For
// example, the following rule sets the maximum number of retries to 3 when
// calling ratings:v1 service, with a 2s timeout per retry attempt.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: VirtualService
// metadata:
//   name: ratings-route
// spec:
//   hosts:
//   - ratings.prod.svc.cluster.local
//   http:
//   - route:
//     - destination:
//         host: ratings.prod.svc.cluster.local
//         subset: v1
//     retries:
//       attempts: 3
//       perTryTimeout: 2s
//       retryOn: gateway-error,connect-failure,refused-stream
// ```
//
message HTTPRetry {
  // Number of retries for a given request. The interval
  // between retries will be determined automatically (25ms+). Actual
  // number of retries attempted depends on the httpReqTimeout.
  int32 attempts = 1 [(google.api.field_behavior) = REQUIRED];

  // Timeout per retry attempt for a given request. format: 1h/1m/1s/1ms. MUST BE >=1ms.
  google.protobuf.Duration per_try_timeout = 2;

  // Specifies the conditions under which retry takes place.
  // One or more policies can be specified using a ‘,’ delimited list.
  // See the [retry policies](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/router_filter#x-envoy-retry-on)
  // and [gRPC retry policies](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/router_filter#x-envoy-retry-grpc-on) for more details.
  string retry_on = 3;
}

// Describes the Cross-Origin Resource Sharing (CORS) policy, for a given
// service. Refer to [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS)
// for further details about cross origin resource sharing. For example,
// the following rule restricts cross origin requests to those originating
// from example.com domain using HTTP POST/GET, and sets the
// `Access-Control-Allow-Credentials` header to false. In addition, it only
// exposes `X-Foo-bar` header and sets an expiry period of 1 day.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: VirtualService
// metadata:
//   name: ratings-route
// spec:
//   hosts:
//   - ratings.prod.svc.cluster.local
//   http:
//   - route:
//     - destination:
//         host: ratings.prod.svc.cluster.local
//         subset: v1
//     corsPolicy:
//       allowOrigin:
//       - example.com
//       allowMethods:
//       - POST
//       - GET
//       allowCredentials: false
//       allowHeaders:
//       - X-Foo-Bar
//       maxAge: "24h"
// ```
//
message CorsPolicy {
  // The list of origins that are allowed to perform CORS requests. The
  // content will be serialized into the Access-Control-Allow-Origin
  // header. Wildcard * will allow all origins.
  repeated string allow_origin = 1;

  // List of HTTP methods allowed to access the resource. The content will
  // be serialized into the Access-Control-Allow-Methods header.
  repeated string allow_methods = 2;

  // List of HTTP headers that can be used when requesting the
  // resource. Serialized to Access-Control-Allow-Headers header.
  repeated string allow_headers = 3;

  // A white list of HTTP headers that the browsers are allowed to
  // access. Serialized into Access-Control-Expose-Headers header.
  repeated string expose_headers = 4;

  // Specifies how long the results of a preflight request can be
  // cached. Translates to the `Access-Control-Max-Age` header.
  google.protobuf.Duration max_age = 5;

  // Indicates whether the caller is allowed to send the actual request
  // (not the preflight) using credentials. Translates to
  // `Access-Control-Allow-Credentials` header.
  google.protobuf.BoolValue allow_credentials = 6;
}

// HTTPFaultInjection can be used to specify one or more faults to inject
// while forwarding http requests to the destination specified in a route.
// Fault specification is part of a VirtualService rule. Faults include
// aborting the Http request from downstream service, and/or delaying
// proxying of requests. A fault rule MUST HAVE delay or abort or both.
//
// *Note:* Delay and abort faults are independent of one another, even if
// both are specified simultaneously.
message HTTPFaultInjection {
  // Delay requests before forwarding, emulating various failures such as
  // network issues, overloaded upstream service, etc.
  Delay delay = 1;

  // Abort Http request attempts and return error codes back to downstream
  // service, giving the impression that the upstream service is faulty.
  Abort abort = 2;

  // Delay specification is used to inject latency into the request
  // forwarding path. The following example will introduce a 5 second delay
  // in 1 out of every 1000 requests to the "v1" version of the "reviews"
  // service from all pods with label env: prod
  //
  // ```yaml
  // apiVersion: networking.istio.io/v1alpha3
  // kind: VirtualService
  // metadata:
  //   name: reviews-route
  // spec:
  //   hosts:
  //   - reviews.prod.svc.cluster.local
  //   http:
  //   - match:
  //     - sourceLabels:
  //         env: prod
  //     route:
  //     - destination:
  //         host: reviews.prod.svc.cluster.local
  //         subset: v1
  //     fault:
  //       delay:
  //         percentage:
  //           value: 0.1
  //         fixedDelay: 5s
  // ```
  //
  // The _fixedDelay_ field is used to indicate the amount of delay in seconds.
  // The optional _percentage_ field can be used to only delay a certain
  // percentage of requests. If left unspecified, all request will be delayed.
  message Delay {
    // Percentage of requests on which the delay will be injected (0-100).
    // Use of integer `percent` value is deprecated. Use the double `percentage`
    // field instead.
    int32 percent = 1 [deprecated=true];

    oneof http_delay_type {
      // Add a fixed delay before forwarding the request. Format:
      // 1h/1m/1s/1ms. MUST be >=1ms.
      google.protobuf.Duration fixed_delay = 2 [(google.api.field_behavior) = REQUIRED];

      // $hide_from_docs
      google.protobuf.Duration exponential_delay = 3 ;
    }

    // Percentage of requests on which the delay will be injected.
    Percent percentage = 5;
  }

  // Abort specification is used to prematurely abort a request with a
  // pre-specified error code. The following example will return an HTTP 400
  // error code for 1 out of every 1000 requests to the "ratings" service "v1".
  //
  // ```yaml
  // apiVersion: networking.istio.io/v1alpha3
  // kind: VirtualService
  // metadata:
  //   name: ratings-route
  // spec:
  //   hosts:
  //   - ratings.prod.svc.cluster.local
  //   http:
  //   - route:
  //     - destination:
  //         host: ratings.prod.svc.cluster.local
  //         subset: v1
  //     fault:
  //       abort:
  //         percentage:
  //           value: 0.1
  //         httpStatus: 400
  // ```
  //
  // The _httpStatus_ field is used to indicate the HTTP status code to
  // return to the caller. The optional _percentage_ field can be used to only
  // abort a certain percentage of requests. If not specified, all requests are
  // aborted.
  message Abort {
    // Percentage of requests to be aborted with the error code provided (0-100).
    // Use of integer `percent` value is deprecated. Use the double `percentage`
    // field instead.
    int32 percent = 1 [deprecated=true];

    oneof error_type {
      // HTTP status code to use to abort the Http request.
      int32 http_status = 2 [(google.api.field_behavior) = REQUIRED];

      // $hide_from_docs
      string grpc_status = 3;

      // $hide_from_docs
      string http2_error = 4;
    }

    // Percentage of requests to be aborted with the error code provided.
    Percent percentage = 5;
  }
}

// PortSelector specifies the number of a port to be used for
// matching or selection for final routing.
message PortSelector {
  // Valid port number
  uint32 number = 1;

  reserved 2;
  reserved "name";
}

// Percent specifies a percentage in the range of [0.0, 100.0].
message Percent {
  double value = 1;
}
