// Copyright 2024 Google LLC
//
// 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";

package google.cloud.managedkafka.v1;

import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/protobuf/timestamp.proto";

option csharp_namespace = "Google.Cloud.ManagedKafka.V1";
option go_package = "cloud.google.com/go/managedkafka/apiv1/managedkafkapb;managedkafkapb";
option java_multiple_files = true;
option java_outer_classname = "ResourcesProto";
option java_package = "com.google.cloud.managedkafka.v1";
option php_namespace = "Google\\Cloud\\ManagedKafka\\V1";
option ruby_package = "Google::Cloud::ManagedKafka::V1";
option (google.api.resource_definition) = {
  type: "cloudkms.googleapis.com/CryptoKey"
  pattern: "projects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{crypto_key}"
};

// An Apache Kafka cluster deployed in a location.
message Cluster {
  option (google.api.resource) = {
    type: "managedkafka.googleapis.com/Cluster"
    pattern: "projects/{project}/locations/{location}/clusters/{cluster}"
    plural: "clusters"
    singular: "cluster"
  };

  // The state of the cluster.
  enum State {
    // A state was not specified.
    STATE_UNSPECIFIED = 0;

    // The cluster is being created.
    CREATING = 1;

    // The cluster is active.
    ACTIVE = 2;

    // The cluster is being deleted.
    DELETING = 3;
  }

  // Platform specific configuration properties for a Kafka cluster.
  oneof platform_config {
    // Required. Configuration properties for a Kafka cluster deployed to Google
    // Cloud Platform.
    GcpConfig gcp_config = 9 [(google.api.field_behavior) = REQUIRED];
  }

  // Identifier. The name of the cluster. Structured like:
  // projects/{project_number}/locations/{location}/clusters/{cluster_id}
  string name = 1 [(google.api.field_behavior) = IDENTIFIER];

  // Output only. The time when the cluster was created.
  google.protobuf.Timestamp create_time = 2
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. The time when the cluster was last updated.
  google.protobuf.Timestamp update_time = 3
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Optional. Labels as key value pairs.
  map<string, string> labels = 4 [(google.api.field_behavior) = OPTIONAL];

  // Required. Capacity configuration for the Kafka cluster.
  CapacityConfig capacity_config = 5 [(google.api.field_behavior) = REQUIRED];

  // Optional. Rebalance configuration for the Kafka cluster.
  RebalanceConfig rebalance_config = 8 [(google.api.field_behavior) = OPTIONAL];

  // Output only. The current state of the cluster.
  State state = 10 [(google.api.field_behavior) = OUTPUT_ONLY];
}

// A capacity configuration of a Kafka cluster.
message CapacityConfig {
  // Required. The number of vCPUs to provision for the cluster. Minimum: 3.
  int64 vcpu_count = 1 [(google.api.field_behavior) = REQUIRED];

  // Required. The memory to provision for the cluster in bytes.
  // The CPU:memory ratio (vCPU:GiB) must be between 1:1 and 1:8.
  // Minimum: 3221225472 (3 GiB).
  int64 memory_bytes = 2 [(google.api.field_behavior) = REQUIRED];
}

// Defines rebalancing behavior of a Kafka cluster.
message RebalanceConfig {
  // The partition rebalance mode for the cluster.
  enum Mode {
    // A mode was not specified. Do not use.
    MODE_UNSPECIFIED = 0;

    // Do not rebalance automatically.
    NO_REBALANCE = 1;

    // Automatically rebalance topic partitions among brokers when the
    // cluster is scaled up.
    AUTO_REBALANCE_ON_SCALE_UP = 2;
  }

  // Optional. The rebalance behavior for the cluster.
  // When not specified, defaults to `NO_REBALANCE`.
  Mode mode = 1 [(google.api.field_behavior) = OPTIONAL];
}

// The configuration of a Virtual Private Cloud (VPC) network that can access
// the Kafka cluster.
message NetworkConfig {
  // Required. Name of the VPC subnet in which to create Private Service Connect
  // (PSC) endpoints for the Kafka brokers and bootstrap address. Structured
  // like: projects/{project}/regions/{region}/subnetworks/{subnet_id}
  //
  // The subnet must be located in the same region as the Kafka cluster. The
  // project may differ. Multiple subnets from the same parent network must not
  // be specified.
  //
  // The CIDR range of the subnet must be within the IPv4 address ranges for
  // private networks, as specified in RFC 1918.
  string subnet = 2 [(google.api.field_behavior) = REQUIRED];
}

// The configuration of access to the Kafka cluster.
message AccessConfig {
  // Required. Virtual Private Cloud (VPC) networks that must be granted direct
  // access to the Kafka cluster. Minimum of 1 network is required. Maximum 10
  // networks can be specified.
  repeated NetworkConfig network_configs = 1
      [(google.api.field_behavior) = REQUIRED];
}

// Configuration properties for a Kafka cluster deployed to Google Cloud
// Platform.
message GcpConfig {
  // Required. Access configuration for the Kafka cluster.
  AccessConfig access_config = 3 [(google.api.field_behavior) = REQUIRED];

  // Optional. Immutable. The Cloud KMS Key name to use for encryption. The key
  // must be located in the same region as the cluster and cannot be changed.
  // Structured like:
  // projects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{crypto_key}.
  string kms_key = 2 [
    (google.api.field_behavior) = OPTIONAL,
    (google.api.field_behavior) = IMMUTABLE,
    (google.api.resource_reference) = {
      type: "cloudkms.googleapis.com/CryptoKey"
    }
  ];
}

// A Kafka topic in a given cluster.
message Topic {
  option (google.api.resource) = {
    type: "managedkafka.googleapis.com/Topic"
    pattern: "projects/{project}/locations/{location}/clusters/{cluster}/topics/{topic}"
    plural: "topics"
    singular: "topic"
  };

  // Identifier. The name of the topic. The `topic` segment is used when
  // connecting directly to the cluster. Structured like:
  // projects/{project}/locations/{location}/clusters/{cluster}/topics/{topic}
  string name = 1 [(google.api.field_behavior) = IDENTIFIER];

  // Required. The number of partitions this topic has. The partition count can
  // only be increased, not decreased. Please note that if partitions are
  // increased for a topic that has a key, the partitioning logic or the
  // ordering of the messages will be affected.
  int32 partition_count = 2 [(google.api.field_behavior) = REQUIRED];

  // Required. Immutable. The number of replicas of each partition. A
  // replication factor of 3 is recommended for high availability.
  int32 replication_factor = 3 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.field_behavior) = IMMUTABLE
  ];

  // Optional. Configurations for the topic that are overridden from the cluster
  // defaults. The key of the map is a Kafka topic property name, for example:
  // `cleanup.policy`, `compression.type`.
  map<string, string> configs = 4 [(google.api.field_behavior) = OPTIONAL];
}

// Metadata for a consumer group corresponding to a specific topic.
message ConsumerTopicMetadata {
  // Optional. Metadata for this consumer group and topic for all partition
  // indexes it has metadata for.
  map<int32, ConsumerPartitionMetadata> partitions = 1
      [(google.api.field_behavior) = OPTIONAL];
}

// Metadata for a consumer group corresponding to a specific partition.
message ConsumerPartitionMetadata {
  // Required. The current offset for this partition, or 0 if no offset has been
  // committed.
  int64 offset = 1 [(google.api.field_behavior) = REQUIRED];

  // Optional. The associated metadata for this partition, or empty if it does
  // not exist.
  string metadata = 2 [(google.api.field_behavior) = OPTIONAL];
}

// A Kafka consumer group in a given cluster.
message ConsumerGroup {
  option (google.api.resource) = {
    type: "managedkafka.googleapis.com/ConsumerGroup"
    pattern: "projects/{project}/locations/{location}/clusters/{cluster}/consumerGroups/{consumer_group}"
    plural: "consumerGroups"
    singular: "consumerGroup"
  };

  // Identifier. The name of the consumer group. The `consumer_group` segment is
  // used when connecting directly to the cluster. Structured like:
  // projects/{project}/locations/{location}/clusters/{cluster}/consumerGroups/{consumer_group}
  string name = 1 [(google.api.field_behavior) = IDENTIFIER];

  // Optional. Metadata for this consumer group for all topics it has metadata
  // for. The key of the map is a topic name, structured like:
  // projects/{project}/locations/{location}/clusters/{cluster}/topics/{topic}
  map<string, ConsumerTopicMetadata> topics = 2
      [(google.api.field_behavior) = OPTIONAL];
}

// Represents the metadata of the long-running operation.
message OperationMetadata {
  // Output only. The time the operation was created.
  google.protobuf.Timestamp create_time = 1
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. The time the operation finished running.
  google.protobuf.Timestamp end_time = 2
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Server-defined resource path for the target of the operation.
  string target = 3 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Name of the verb executed by the operation.
  string verb = 4 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Human-readable status of the operation, if any.
  string status_message = 5 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Identifies whether the user has requested cancellation
  // of the operation. Operations that have been cancelled successfully
  // have [Operation.error][] value with a
  // [google.rpc.Status.code][google.rpc.Status.code] of 1, corresponding to
  // `Code.CANCELLED`.
  bool requested_cancellation = 6 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. API version used to start the operation.
  string api_version = 7 [(google.api.field_behavior) = OUTPUT_ONLY];
}
