syntax = "proto3";

package conduit.public;

import "google/protobuf/duration.proto";

import "common/common.proto";
import "common/healthcheck/healthcheck.proto";

message Empty {}

message VersionInfo {
  string goVersion = 1;
  string buildDate = 2;
  string releaseVersion = 3;
}

message ListPodsResponse {
  repeated Pod pods = 1;
}

message Pod {
  string name = 1;
  string podIP = 2;
  string deployment = 3;
  string status = 4;
  bool added = 5; // true if this pod has a proxy sidecar (data plane)
  google.protobuf.Duration sinceLastReport = 6;
  string controllerNamespace = 7; // namespace of controller this pod reports to
  bool controlPlane = 8; // true if this pod is part of the control plane
}

message TapRequest {
  option deprecated = true;

  oneof target {
    string pod = 1;
    string deployment = 2;
  }
  // validation of these fields happens on the server
  float maxRps = 3;
  uint32 toPort = 4;
  string toIP = 5;
  uint32 fromPort = 6;
  string fromIP = 7;
  string scheme = 8;
  string method = 9;
  string authority = 10;
  string path = 11;
}

// A tap request over kubernetes resources.
message TapByResourceRequest {
  // Describes the kubernetes pods that should be tapped.
  ResourceSelection target = 1;

  // Selects over events to be reported.
  Match match = 2;

  // Limits the number of events to be inspected.
  float maxRps = 3;

  message Match {
    oneof match {
      // If empty, matches all messages.
      Seq all = 1;

      // If empty, matches no messages.
      Seq any = 2;

      // Inverts the inner match.
      Match not = 3;

      // Matches events being sent to any of the selected destinations.
      ResourceSelection destinations = 4;

      // Matches HTTP requests by their metadata.
      Http http = 5;
    }

    message Seq {
      repeated Match matches = 1;
    }

    message Http {
      oneof match {
        string scheme = 1;
        string method = 2;
        string authority = 3;
        string path = 4;
      }
    }
  }
}

message ApiError {
  string error = 1;
}

message Resource {
  // The namespace the resource is in.
  //
  // If empty, indicates all namespaces should be considered.
  string namespace = 1;

  // The type of Kubernetes resource.
  //
  // E.g. pod, deployment, service, ...
  //
  // If `all` refers, to all resource types.
  string type = 2;

  // An optional Kubernetes resource name.
  string name = 3;
}

message ResourceSelection {
  // Identifies a Kubernetes resource.
  Resource resource = 1;

  // A string-formatted Kubernetes label selector as passed to `kubectl get
  // --selector`.
  //
  // XXX in the future this may be superceded by a data structure that more
  // richly describes a parsed label selector.
  string label_selector = 2;
}

message ResourceError {
  Resource resource = 1;
  string error = 2;
}

message StatSummaryRequest {
  ResourceSelection selector = 1;
  string time_window = 2;

  oneof outbound {
    Empty none = 3;
    Resource to_resource   = 4;
    Resource from_resource = 5;
  }
}

message StatSummaryResponse {
  oneof response {
    Ok ok = 1;
    ResourceError error = 2;
  }

  message Ok {
    repeated StatTable stat_tables = 1;
  }
}

message BasicStats {
  uint64 success_count = 1;
  uint64 failure_count = 2;
  uint64 latency_ms_p50 = 3;
  uint64 latency_ms_p95 = 4;
  uint64 latency_ms_p99 = 5;
  // count of requests that are TLSed
  uint64 meshed_request_count = 6;
}

message StatTable {
  oneof table {
    PodGroup pod_group = 1;
  }

  message PodGroup {
    repeated Row rows = 1;

    message Row {
      Resource resource = 1;
      string time_window = 2;

      // number of pending or running pods in this resource that have conduit injected
      uint64 meshed_pod_count = 3;
      // number of pending or running pods in this resource
      uint64 running_pod_count = 4;
      // number of pods in this resource that have Phase PodFailed
      uint64 failed_pod_count = 6;

      BasicStats stats = 5;
    }
  }
}

service Api {
  rpc StatSummary(StatSummaryRequest) returns (StatSummaryResponse) {}

  rpc ListPods(Empty) returns (ListPodsResponse) {}

  // Superceded by `TapByResource`.
  rpc Tap(TapRequest) returns (stream common.TapEvent) { option deprecated = true; }

  // Executes tapping over Kubernetes resources.
  rpc TapByResource(TapByResourceRequest) returns (stream common.TapEvent) {}

  rpc Version(Empty) returns (VersionInfo) {}
  rpc SelfCheck(common.healthcheck.SelfCheckRequest) returns (common.healthcheck.SelfCheckResponse) {}
}
