// SPDX-License-Identifier: Apache-2.0
// Copyright Authors of Hubble

syntax = "proto3";

import "google/protobuf/any.proto";
import "google/protobuf/wrappers.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/field_mask.proto";
import public "cilium/hubble/flow/flow.proto";
import "cilium/hubble/relay/relay.proto";

package observer;

option go_package = "github.com/cilium/cilium/api/v1/observer";

option java_multiple_files = true;
option java_package = "io.cilium.api.observer";

// Observer returns a stream of Flows depending on which filter the user want
// to observe.
service Observer {
    // GetFlows returning structured data, meant to eventually obsolete GetLastNFlows.
    rpc GetFlows(GetFlowsRequest) returns (stream GetFlowsResponse) {}

    // GetAgentEvents returns Cilium agent events.
    rpc GetAgentEvents(GetAgentEventsRequest) returns (stream GetAgentEventsResponse) {}

    // GetDebugEvents returns Cilium datapath debug events.
    rpc GetDebugEvents(GetDebugEventsRequest) returns (stream GetDebugEventsResponse) {}

    // GetNodes returns information about nodes in a cluster.
    rpc GetNodes(GetNodesRequest) returns (GetNodesResponse) {}

    // GetNamespaces returns information about namespaces in a cluster.
    // The namespaces returned are namespaces which have had network flows in
    // the last hour. The namespaces are returned sorted by cluster name and
    // namespace in ascending order.
    rpc GetNamespaces(GetNamespacesRequest) returns (GetNamespacesResponse) {}

    // ServerStatus returns some details about the running hubble server.
    rpc ServerStatus(ServerStatusRequest) returns (ServerStatusResponse) {}
}

message ServerStatusRequest {}

message ServerStatusResponse {
    // number of currently captured flows
    // In a multi-node context, this is the cumulative count of all captured
    // flows.
    uint64 num_flows = 1;

    // maximum capacity of the ring buffer
    // In a multi-node context, this is the aggregation of all ring buffers
    // capacities.
    uint64 max_flows = 2;

    // total amount of flows observed since the observer was started
    // In a multi-node context, this is the aggregation of all flows that have
    // been seen.
    uint64 seen_flows = 3;

    // uptime of this observer instance in nanoseconds
    // In a multi-node context, this field corresponds to the uptime of the
    // longest living instance.
    uint64 uptime_ns = 4;

    // number of nodes for which a connection is established
    google.protobuf.UInt32Value num_connected_nodes = 5;

    // number of nodes for which a connection cannot be established
    google.protobuf.UInt32Value num_unavailable_nodes = 6;

    // list of nodes that are unavailable
    // This list may not be exhaustive.
    repeated string unavailable_nodes = 7;

    // Version is the version of Cilium/Hubble.
    string version = 8;

    // Approximate rate of flows seen by Hubble per second over the last minute.
    // In a multi-node context, this is the sum of all flows rates.
    double flows_rate = 9;
}

message GetFlowsRequest {
    // Number of flows that should be returned. Incompatible with `since/until`.
    // Defaults to the most recent (last) `number` flows, unless `first` is
    // true, then it will return the earliest `number` flows.
    uint64 number = 1;

    // first specifies if we should look at the first `number` flows or the
    // last `number` of flows. Incompatible with `follow`.
    bool first = 9;

    reserved 2; // removed, do not use

    // follow sets when the server should continue to stream flows after
    // printing the last N flows.
    bool follow = 3;

    // blacklist defines a list of filters which have to match for a flow to be
    // excluded from the result.
    // If multiple blacklist filters are specified, only one of them has to
    // match for a flow to be excluded.
    repeated flow.FlowFilter blacklist = 5;

    // whitelist defines a list of filters which have to match for a flow to be
    // included in the result.
    // If multiple whitelist filters are specified, only one of them has to
    // match for a flow to be included.
    // The whitelist and blacklist can both be specified. In such cases, the
    // set of the returned flows is the set difference `whitelist - blacklist`.
    // In other words, the result will contain all flows matched by the
    // whitelist that are not also simultaneously matched by the blacklist.
    repeated flow.FlowFilter whitelist = 6;

    // Since this time for returned flows. Incompatible with `number`.
    google.protobuf.Timestamp since = 7;

    // Until this time for returned flows. Incompatible with `number`.
    google.protobuf.Timestamp until = 8;

    // FieldMask allows clients to limit flow's fields that will be returned.
    // For example, {paths: ["source.id", "destination.id"]} will return flows
    // with only these two fields set.
    google.protobuf.FieldMask field_mask = 10;

    // Experimental contains fields that are not stable yet. Support for
    // experimental features is always optional and subject to change.
    message Experimental {
        // FieldMask allows clients to limit flow's fields that will be returned.
        // For example, {paths: ["source.id", "destination.id"]} will return flows
        // with only these two fields set.
        // Deprecated in favor of top-level field_mask. This field will be
        // removed in v1.17.
        google.protobuf.FieldMask field_mask = 1 [deprecated=true];
    }
    Experimental experimental = 999;

    // extensions can be used to add arbitrary additional metadata to GetFlowsRequest.
    // This can be used to extend functionality for other Hubble compatible
    // APIs, or experiment with new functionality without needing to change the public API.
    google.protobuf.Any extensions = 150000;
}

// GetFlowsResponse contains either a flow or a protocol message.
message GetFlowsResponse {
    oneof response_types{
        flow.Flow flow = 1;
        // node_status informs clients about the state of the nodes
        // participating in this particular GetFlows request.
        relay.NodeStatusEvent node_status = 2;
        // lost_events informs clients about events which got dropped due to
        // a Hubble component being unavailable
        flow.LostEvent lost_events = 3;
    }
    // Name of the node where this event was observed.
    string node_name = 1000;
    // Timestamp at which this event was observed.
    google.protobuf.Timestamp time = 1001;
}

message GetAgentEventsRequest {
    // Number of flows that should be returned. Incompatible with `since/until`.
    // Defaults to the most recent (last) `number` events, unless `first` is
    // true, then it will return the earliest `number` events.
    uint64 number = 1;

    // first specifies if we should look at the first `number` events or the
    // last `number` of events. Incompatible with `follow`.
    bool first = 9;

    // follow sets when the server should continue to stream agent events after
    // printing the last N agent events.
    bool follow = 2;

    // TODO: do we want to be able to specify blocklist/allowlist (previously
    // known as blacklist/whitelist)?

    // Since this time for returned agent events. Incompatible with `number`.
    google.protobuf.Timestamp since = 7;

    // Until this time for returned agent events. Incompatible with `number`.
    google.protobuf.Timestamp until = 8;
}

// GetAgentEventsResponse contains an event received from the Cilium agent.
message GetAgentEventsResponse {
    flow.AgentEvent agent_event = 1;
    // Name of the node where this event was observed.
    string node_name = 1000;
    // Timestamp at which this event was observed.
    google.protobuf.Timestamp time = 1001;
}

message GetDebugEventsRequest {
    // Number of events that should be returned. Incompatible with `since/until`.
    // Defaults to the most recent (last) `number` events, unless `first` is
    // true, then it will return the earliest `number` events.
    uint64 number = 1;

    // first specifies if we should look at the first `number` events or the
    // last `number` of events. Incompatible with `follow`.
    bool first = 9;

    // follow sets when the server should continue to stream debug events after
    // printing the last N debug events.
    bool follow = 2;

    // TODO: do we want to be able to specify blocklist/allowlist (previously
    // known as blacklist/whitelist)?

    // Since this time for returned debug events. Incompatible with `number`.
    google.protobuf.Timestamp since = 7;

    // Until this time for returned debug events. Incompatible with `number`.
    google.protobuf.Timestamp until = 8;
}

// GetDebugEventsResponse contains a Cilium datapath debug events.
message GetDebugEventsResponse {
    flow.DebugEvent debug_event = 1;
    // Name of the node where this event was observed.
    string node_name = 1000;
    // Timestamp at which this event was observed.
    google.protobuf.Timestamp time = 1001;
}

message GetNodesRequest {}

// GetNodesResponse contains the list of nodes.
message GetNodesResponse {
    // Nodes is an exhaustive list of nodes.
    repeated Node nodes = 1;
}

// Node represents a cluster node.
message Node {
    // Name is the name of the node.
    string name = 1;
    // Version is the version of Cilium/Hubble as reported by the node.
    string version = 2;

    // Address is the network address of the API endpoint.
    string address = 3;

    // State represents the known state of the node.
    relay.NodeState state = 4;

    // TLS reports TLS related information.
    TLS tls = 5;

    // UptimeNS is the uptime of this instance in nanoseconds
    uint64 uptime_ns = 6;

    // number of currently captured flows
    uint64 num_flows = 7;

    // maximum capacity of the ring buffer
    uint64 max_flows = 8;

    // total amount of flows observed since the observer was started
    uint64 seen_flows = 9;
}

// TLS represents TLS information.
message TLS {
    // Enabled reports whether TLS is enabled or not.
    bool enabled = 1;
    // ServerName is the TLS server name that can be used as part of the TLS
    // cert validation process.
    string server_name = 2;
}

message GetNamespacesRequest {}

// GetNamespacesResponse contains the list of namespaces.
message GetNamespacesResponse {
    // Namespaces is a list of namespaces with flows
    repeated Namespace namespaces = 1;
}

message Namespace {
  string cluster = 1;
  string namespace = 2;
}

// ExportEvent contains an event to be exported. Not to be used outside of the
// exporter feature.
message ExportEvent {
    oneof response_types{
        flow.Flow flow = 1;
        // node_status informs clients about the state of the nodes
        // participating in this particular GetFlows request.
        relay.NodeStatusEvent node_status = 2;
        // lost_events informs clients about events which got dropped due to
        // a Hubble component being unavailable
        flow.LostEvent lost_events = 3;
        // agent_event informs clients about an event received from the Cilium
        // agent.
        flow.AgentEvent agent_event = 4;
        // debug_event contains Cilium datapath debug events
        flow.DebugEvent debug_event = 5;
    }
    // Name of the node where this event was observed.
    string node_name = 1000;
    // Timestamp at which this event was observed.
    google.protobuf.Timestamp time = 1001;
}
