// Copyright 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/protobuf/struct.proto";
import "policy/v1beta1/value_type.proto";

package istio.policy.v1beta1;

option go_package="istio.io/api/policy/v1beta1";

// AttributeManifest describes a set of Attributes produced by some component
// of an Istio deployment.
message AttributeManifest {
  // Optional. The revision of this document. Assigned by server.
  string revision = 1;
  // Required. Name of the component producing these attributes. This can be
  // the proxy (with the canonical name "istio-proxy") or the name of an
  // `attributes` kind adapter in Mixer.
  string name = 2;

  // AttributeInfo describes the schema of an Istio `Attribute`.
  //
  // # Istio Attributes
  //
  // Istio uses `attributes` to describe runtime activities of Istio services.
  // An Istio attribute carries a specific piece of information about an activity,
  // such as the error code of an API request, the latency of an API request, or the
  // original IP address of a TCP connection. The attributes are often generated
  // and consumed by different services. For example, a frontend service can
  // generate an authenticated user attribute and pass it to a backend service for
  // access control purpose.
  //
  // To simplify the system and improve developer experience, Istio uses
  // shared attribute definitions across all components. For example, the same
  // authenticated user attribute will be used for logging, monitoring, analytics,
  // billing, access control, auditing. Many Istio components provide their
  // functionality by collecting, generating, and operating on attributes.
  // For example, the proxy collects the error code attribute, and the logging
  // stores it into a log.
  //
  // # Design
  //
  // Each Istio attribute must conform to an `AttributeInfo` in an
  // `AttributeManifest` in the current Istio deployment at runtime. An
  // [`AttributeInfo`][istio.policy.v1beta1] is used to define an attribute's
  // metadata: the type of its value and a detailed description that explains
  // the semantics of the attribute type. Each attribute's name is globally unique;
  // in other words an attribute name can only appear once across all manifests.
  //
  // The runtime presentation of an attribute is intentionally left out of this
  // specification, because passing attribute using JSON, XML, or Protocol Buffers
  // does not change the semantics of the attribute. Different implementations
  // can choose different representations based on their needs.
  //
  // # HTTP Mapping
  //
  // Because many systems already have REST APIs, it makes sense to define a
  // standard HTTP mapping for Istio attributes that are compatible with typical
  // REST APIs. The design is to map one attribute to one HTTP header, the
  // attribute name and value becomes the HTTP header name and value. The actual
  // encoding scheme will be decided later.
  message AttributeInfo {
    // Optional. A human-readable description of the attribute's purpose.
    string description = 1;

    // Required. The type of data carried by this attribute.
    istio.policy.v1beta1.ValueType value_type = 2;
  }
  // The set of attributes this Istio component will be responsible for producing at runtime.
  // We map from attribute name to the attribute's specification. The name of an attribute,
  // which is how attributes are referred to in aspect configuration, must conform to:
  //
  //     Name = IDENT { SEPARATOR IDENT };
  //
  // Where `IDENT` must match the regular expression `[a-z][a-z0-9]+` and `SEPARATOR` must
  // match the regular expression `[\.-]`.
  //
  // Attribute names must be unique within a single Istio deployment. The set of canonical
  // attributes are described at https://istio.io/docs/reference/attribute-vocabulary.html.
  // Attributes not in that list should be named with a component-specific suffix such as
  // request.count-my.component.
  map<string, AttributeInfo> attributes = 3;
}

// A Rule is a selector and a set of intentions to be executed when the
// selector is `true`
//
// The following example instructs Mixer to invoke 'prometheus-handler' handler for all services and pass it the
// instance constructed using the 'RequestCountByService' instance.
//
// ```yaml
// - match: destination.service == "*"
//   actions:
//   - handler: prometheus-handler
//     instances:
//     - RequestCountByService
// ```
message Rule {
  // Required. Match is an attribute based predicate. When Mixer receives a
  // request it evaluates the match expression and executes all the associated `actions`
  // if the match evaluates to true.
  //
  // A few example match:
  //
  // * an empty match evaluates to `true`
  // * `true`, a boolean literal; a rule with this match will always be executed
  // * `destination.service == ratings*` selects any request targeting a service whose
  // name starts with "ratings"
  // * `attr1 == "20" && attr2 == "30"` logical AND, OR, and NOT are also available
  string match = 1;

  // Optional. The actions that will be executed when match evaluates to `true`.
  repeated Action actions = 2;
}

// Action describes which [Handler][istio.policy.v1beta1.Handler] to invoke and what data to pass to it for processing.
//
// The following example instructs Mixer to invoke 'prometheus-handler' handler and pass it the object
// constructed using the instance 'RequestCountByService'.
//
// ```yaml
//   handler: prometheus-handler
//   instances:
//   - RequestCountByService
// ```
message Action {
  // Required. Fully qualified name of the handler to invoke.
  // Must match the `name` of a [Handler][istio.policy.v1beta1.Handler.name].
  string handler = 2;

  // Required. Each value must match the fully qualified name of the
  // [Instance][istio.policy.v1beta1.Instance.name]s.
  // Referenced instances are evaluated by resolving the attributes/literals for all the fields.
  // The constructed objects are then passed to the `handler` referenced within this action.
  repeated string instances = 3;
}

// An Instance tells Mixer how to create instances for particular template.
//
// Instance is defined by the operator. Instance is defined relative to a known
// template. Their purpose is to tell Mixer how to use attributes or literals to produce
// instances of the specified template at runtime.
//
// The following example instructs Mixer to construct an instance associated with template
// 'istio.mixer.adapter.metric.Metric'. It provides a mapping from the template's fields to expressions.
// Instances produced with this instance can be referenced by [Actions][istio.policy.v1beta1.Action] using name
// 'RequestCountByService'
//
// ```yaml
// - name: RequestCountByService
//   template: istio.mixer.adapter.metric.Metric
//   params:
//     value: 1
//     dimensions:
//       source: source.service
//       destination_ip: destination.ip
// ```
message Instance {
  // Required. The name of this instance
  //
  // Must be unique amongst other Instances in scope. Used by [Action][istio.policy.v1beta1.Action] to refer
  // to an instance produced by this instance.
  string name = 1;

  // Required. The name of the compiled in template this instance creates instances for. For referencing non compiled-in
  // templates, use the `template` field instead.
  //
  // The value must match the name of the available template Mixer is built with.
  string compiled_template = 67794676;

  // Required. The name of the template this instance creates instances for. For referencing compiled-in
  // templates, use the `compiled_template` field instead.
  //
  // The value must match the name of the available template in scope.
  string template = 2;

  // Required. Depends on referenced template. Struct representation of a
  // proto defined by the template; this varies depending on the value of field `template`.
  google.protobuf.Struct params = 3;
}

// Handler allows the operator to configure a specific adapter implementation.
// Each adapter implementation defines its own `params` proto.
//
// In the following example we define a `metrics` handler for the `prometheus` adapter.
// The example is in the form of a kubernetes resource:
// * The `metadata.name` is the name of the handler
// * The `kind` refers to the adapter name
// * The `spec` block represents adapter-specific configuration as well as the connection information
//
// ```yaml
// # Sample-1: No connection specified (for compiled in adapters)
// # Note: if connection information is not specified, the adapter configuration is directly inside
// # `spec` block. This is going to be DEPRECATED in favor of Sample-2
// apiVersion: "config.istio.io/v1alpha2"
// kind: prometheus
// metadata:
//   name: handler
//   namespace: istio-system
// spec:
//   metrics:
//   - name: request_count
//     instance_name: requestcount.metric.istio-system
//     kind: COUNTER
//     label_names:
//     - source_service
//     - source_version
//     - destination_service
//     - destination_version
// ---
// # Sample-2: With connection information (for out-of-process adapters)
// # Note: Unlike sample-1, the adapter configuration is parallel to `connection` and is nested inside `param` block.
// apiVersion: "config.istio.io/v1alpha2"
// kind: prometheus
// metadata:
//   name: handler
//   namespace: istio-system
// spec:
//   param:
//     metrics:
//     - name: request_count
//       instance_name: requestcount.metric.istio-system
//       kind: COUNTER
//       label_names:
//       - source_service
//       - source_version
//       - destination_service
//       - destination_version
//   connection:
//     address: localhost:8090
// ---
// ```
message Handler {
  // Required. Must be unique in the entire mixer configuration. Used by [Actions][istio.policy.v1beta1.Action.handler]
  // to refer to this handler.
  string name = 1;

  // Required. The name of the compiled in adapter this handler instantiates. For referencing non compiled-in
  // adapters, use the `adapter` field instead.
  //
  // The value must match the name of the available adapter Mixer is built with. An adapter's name is typically a
  // constant in its code.
  string compiled_adapter = 67794676;

  // Required. The name of a specific adapter implementation. For referencing compiled-in
  // adapters, use the `compiled_adapter` field instead.
  //
  // An adapter's implementation name is typically a constant in its code.
  string adapter = 2;

  // Optional. Depends on adapter implementation. Struct representation of a
  // proto defined by the adapter implementation; this varies depending on the value of field `adapter`.
  google.protobuf.Struct params = 3;

  // Optional. Information on how to connect to the out-of-process adapter.
  // This is used if the adapter is not compiled into Mixer binary and is running as a separate process.
  Connection connection = 4;
}

// Connection allows the operator to specify the endpoint for out-of-process infrastructure backend.
// Connection is part of the handler custom resource and is specified alongside adapter specific configuration.
message Connection {
  // The address of the backend.
  string address = 2;

  // TODO: Add auth related fields.
}
