syntax = "proto3";

package global.nextgen.v1;

import "global/common/v1/resources.proto";
import "global/common/v1/service_plan.proto";
import "global/nextgen/v1/backup_common.proto";
import "global/nextgen/v1/cmek.proto";
import "global/nextgen/v1/endpoint.proto";
import "global/nextgen/v1/plan_replayer.proto";
import "global/nextgen/v1/reserved_capacity_template.proto";
import "google/api/field_behavior.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/timestamp.proto";

service ClusterService {
  rpc CreateCluster(CreateClusterRequest) returns (Cluster);
  rpc ListClusters(ListClustersRequest) returns (ListClustersResponse);
  rpc GetCluster(GetClusterRequest) returns (Cluster);
  rpc UpdateCluster(UpdateClusterRequest) returns (Cluster);
  rpc DeleteCluster(DeleteClusterRequest) returns (Cluster);
  rpc ChangeClusterPasswd(ChangeClusterPasswdRequest) returns (ChangeClusterPasswdResponse) {}
  // backup related apis, mirror to openapi
  rpc ListClusterBackups(ListClusterBackupsRequest) returns (ListClusterBackupsResponse);
  rpc DeleteClusterBackup(DeleteClusterBackupRequest) returns (google.protobuf.Empty);
  rpc RestoreCluster(RestoreClusterRequest) returns (google.protobuf.Empty);
  rpc TestClassicBackupAccess(TestClassicBackupAccessRequest) returns (TestClassicBackupAccessResponse);
  rpc RestoreStatus(RestoreStatusRequest) returns (RestoreStatusResponse);
  rpc StopRestoreCluster(StopRestoreClusterRequest) returns (google.protobuf.Empty);
  rpc GetBackupSetting(GetBackupSettingRequest) returns (BackupSetting);
  rpc UpdateBackupSetting(UpdateBackupSettingRequest) returns (BackupSetting);
  // provider role
  rpc GetProviderRole(GetProviderRoleRequest) returns (ProviderRole);
  rpc GetCaCertificateDownloadUrl(GetCaCertificateDownloadUrlRequest) returns (CaCertificateDownloadUrl);
  rpc UpdateClusterProject(UpdateClusterProjectRequest) returns (UpdateClusterProjectResponse);

  // Encryption change operations
  rpc UpdateClusterDualLayerEncryption(UpdateClusterDualLayerEncryptionRequest) returns (UpdateClusterDualLayerEncryptionResponse);
  rpc GetClusterEncryptionStatus(GetClusterEncryptionStatusRequest) returns (ClusterEncryptionStatus);

  // Gateway identity
  rpc ForceUpdateGatewayIdentity(ForceUpdateGatewayIdentityRequest) returns (google.protobuf.Empty);

  rpc EstimatePrice(EstimatePriceRequest) returns (EstimatePriceResponse);
}

message Cluster {
  // Metadata.
  uint64 cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
  uint64 organization_id = 2 [(google.api.field_behavior) = REQUIRED];

  google.protobuf.Timestamp create_time = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
  google.protobuf.Timestamp create_finished_time = 4 [(google.api.field_behavior) = OUTPUT_ONLY];
  google.protobuf.Timestamp update_time = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
  google.protobuf.Timestamp delete_time = 6 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Specs.
  common.v1.CloudProvider.Name cloud_provider_id = 7 [(google.api.field_behavior) = REQUIRED];
  common.v1.Region.Name region_id = 8 [(google.api.field_behavior) = REQUIRED];
  string root_password = 9 [
    (google.api.field_behavior) = OPTIONAL,
    (google.api.field_behavior) = INPUT_ONLY
  ];
  // Version of TiDB kernel.
  string version = 12 [(google.api.field_behavior) = OPTIONAL];

  bool has_root_password = 13 [(google.api.field_behavior) = OUTPUT_ONLY];
  State state = 14 [(google.api.field_behavior) = OUTPUT_ONLY];
  HealthState health_state = 15 [(google.api.field_behavior) = OUTPUT_ONLY];
  bool token_based_auth_enabled = 16 [(google.api.field_behavior) = OUTPUT_ONLY];
  string region_display_name = 17 [(google.api.field_behavior) = OUTPUT_ONLY];

  int64 min_rcu = 18 [(google.api.field_behavior) = OPTIONAL];
  int64 max_rcu = 19 [(google.api.field_behavior) = REQUIRED];
  common.v1.ServicePlan service_plan = 20 [(google.api.field_behavior) = REQUIRED];
  HighAvailabilityType high_availability_type = 21 [(google.api.field_behavior) = IMMUTABLE];
  string region_logical_name = 22 [(google.api.field_behavior) = OUTPUT_ONLY];
  repeated Endpoint endpoints = 23 [(google.api.field_behavior) = OUTPUT_ONLY];

  string shared_pool_id = 24 [(google.api.field_behavior) = OUTPUT_ONLY];
  string dataplane_id = 25 [(google.api.field_behavior) = OUTPUT_ONLY];

  // only used in restore to set cloud admin passwd
  uint64 source_cluster_id = 26 [(google.api.field_behavior) = OPTIONAL];

  // the previous cloud_admin is split into: platform_admin and maintenance_admin

  string encrypted_platform_admin_password = 27 [
    (google.api.field_behavior) = OPTIONAL,
    (google.api.field_behavior) = INPUT_ONLY
  ];
  string encrypted_maintenance_admin_password = 28 [
    (google.api.field_behavior) = OPTIONAL,
    (google.api.field_behavior) = INPUT_ONLY
  ];

  DualLayerDataEncryption dual_layer_data_encryption = 29 [(google.api.field_behavior) = OPTIONAL];
  string display_name = 30 [(google.api.field_behavior) = OPTIONAL];

  int64 project_id = 31 [(google.api.field_behavior) = REQUIRED];
  int32 ru_version = 32;
  google.protobuf.Timestamp capacity_updated_at = 33 [(google.api.field_behavior) = OUTPUT_ONLY];
  uint64 reserved_capacity_template_id = 35 [(google.api.field_behavior) = OPTIONAL];
  ReservedCapacityTemplate reserved_capacity_template = 36 [(google.api.field_behavior) = OUTPUT_ONLY];
  string resource_pool_display_name = 37 [(google.api.field_behavior) = OUTPUT_ONLY];
  PlanReplayerStatus plan_replayer_status = 38 [(google.api.field_behavior) = OUTPUT_ONLY];
  google.protobuf.Timestamp automatic_resume_at = 39 [(google.api.field_behavior) = OUTPUT_ONLY];

  message DualLayerDataEncryption {
    oneof key {
      google.protobuf.Empty no_encryption = 1;
      google.protobuf.Empty default_key = 2;
      CustomerManagedEncryptionKey cmek = 3;
    }
  }

  enum HighAvailabilityType {
    HIGH_AVAILABILITY_TYPE_UNSPECIFIED = 0;
    REGIONAL = 1;
    ZONAL = 2;
  }

  enum HealthState {
    HEALTH_STATE_UNSPECIFIED = 0;

    HEALTHY = 1;
    UNHEALTHY = 2;
  }

  enum State {
    STATE_UNSPECIFIED = 0;

    CREATING = 1;
    AVAILABLE = 2;
    MODIFYING = 3;
    UNAVAILABLE = 4;
    DELETED = 5;
    PAUSING = 6;
    PAUSED = 7;
    RESUMING = 8;
  }
}

// RestoreState enum for restore operations
enum RestoreState {
  RESTORE_STATE_UNSPECIFIED = 0;
  RESTORE_STATE_UNKNOWN = 1;
  RESTORE_STATE_PENDING = 2;
  RESTORE_STATE_RUNNING = 3;
  RESTORE_STATE_SUCCESS = 4;
  RESTORE_STATE_FAILED = 5;
  RESTORE_STATE_CANCELLED = 6;
}

// RestoreMode enum for restore operations
enum RestoreMode {
  RESTORE_MODE_UNSPECIFIED = 0;
  RESTORE_MODE_SNAPSHOT = 1;
  RESTORE_MODE_PITR = 2;
  RESTORE_MODE_DEDICATED_SNAPSHOT = 3;
  RESTORE_MODE_CLASSIC_SNAPSHOT = 4;
}

message ProviderRole {
  string cloud_iam_identity = 1 [(google.api.field_behavior) = OUTPUT_ONLY]; // aws role or gcp serviceaccount
  string node_role = 2 [(google.api.field_behavior) = OUTPUT_ONLY]; // e.g. eks-nodegroup-role
  string external_id = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
}

message CreateClusterRequest {
  Cluster cluster = 1 [(google.api.field_behavior) = REQUIRED];

  bool validate_only = 2 [(google.api.field_behavior) = OPTIONAL];
  optional uint64 resource_pool_id = 3 [(google.api.field_behavior) = OPTIONAL];
}

message ListClustersRequest {
  repeated uint64 cluster_ids = 1 [(google.api.field_behavior) = OPTIONAL];
  repeated uint64 organization_ids = 2 [(google.api.field_behavior) = OPTIONAL];
  repeated common.v1.CloudProvider.Name cloud_provider_ids = 3 [(google.api.field_behavior) = OPTIONAL];
  repeated common.v1.Region.Name region_ids = 4 [(google.api.field_behavior) = OPTIONAL];
  repeated Cluster.State states = 5 [(google.api.field_behavior) = OPTIONAL];
  repeated Cluster.State exclude_states = 6 [(google.api.field_behavior) = OPTIONAL];

  // Default to return non-deleted clusters only.
  bool show_deleted = 7 [(google.api.field_behavior) = OPTIONAL];
  // if show details is false, not return modify progress and network info
  bool show_details = 8 [(google.api.field_behavior) = OPTIONAL];
  repeated common.v1.ServicePlan service_plans = 9 [(google.api.field_behavior) = OPTIONAL];
  repeated uint64 resource_pool_ids = 10 [(google.api.field_behavior) = OPTIONAL];

  // Maximum number of clusters to return.
  uint32 page_size = 100 [(google.api.field_behavior) = OPTIONAL];
  uint32 page = 101 [(google.api.field_behavior) = OPTIONAL];
}

message ListClustersResponse {
  repeated Cluster clusters = 1;
  uint32 total = 2;
}

message GetClusterRequest {
  uint64 cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
  // Default to return non-deleted cluster only.
  bool show_deleted = 2 [(google.api.field_behavior) = OPTIONAL];
}

message DeleteClusterRequest {
  uint64 cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
  bool validate_only = 2 [(google.api.field_behavior) = OPTIONAL];
}

message UpdateClusterRequest {
  Cluster cluster = 1 [(google.api.field_behavior) = REQUIRED];

  // If set to true, only validate the request without making any changes.
  bool validate_only = 3 [(google.api.field_behavior) = OPTIONAL];
}

message ChangeClusterPasswdRequest {
  uint64 cluster_id = 1;
  string passwd = 2;
}

message ChangeClusterPasswdResponse {
  bool synced = 1; // whether the passwd is synced to cluster or only saved into metadb
}

message ListClusterBackupsRequest {
  // filter fields
  string cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
  // (-- api-linter: core::0216::state-field-output-only=disabled
  //     aip.dev/not-precedent: It in a input param --)
  repeated Backup.State states = 2 [(google.api.field_behavior) = OPTIONAL];
  repeated string region_ids = 3 [(google.api.field_behavior) = OPTIONAL];
  repeated Backup.TriggerType trigger_types = 4 [(google.api.field_behavior) = OPTIONAL];
  google.protobuf.Timestamp start_time = 5 [(google.api.field_behavior) = OPTIONAL];
  google.protobuf.Timestamp end_time = 6 [(google.api.field_behavior) = OPTIONAL];
  repeated string backup_ids = 7 [(google.api.field_behavior) = OPTIONAL];

  // page fileds
  int32 page_size = 100 [(google.api.field_behavior) = OPTIONAL];
  string page_token = 101 [(google.api.field_behavior) = OPTIONAL];
  int32 skip = 102 [(.google.api.field_behavior) = OPTIONAL];
}

message ListClusterBackupsResponse {
  repeated Backup backups = 1;

  // page fileds
  int32 total_size = 2;
  string next_page_token = 3;
}

message DeleteClusterBackupRequest {
  string cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
  string backup_id = 2 [(google.api.field_behavior) = REQUIRED];
}

message RestoreClusterRequest {
  string target_cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
  string source_cluster_id = 2 [(google.api.field_behavior) = OPTIONAL];
  RestoreMode restore_mode = 3 [(google.api.field_behavior) = REQUIRED];
  string backup_id = 4 [(google.api.field_behavior) = OPTIONAL];
  google.protobuf.Timestamp point_in_time = 5 [(google.api.field_behavior) = OPTIONAL];
  ClassicBackupStorage classic_backup_storage = 6 [(google.api.field_behavior) = OPTIONAL];
}

message ClassicBackupStorage {
  common.v1.CloudProvider.Name cloud_provider = 1 [(google.api.field_behavior) = REQUIRED];
  // only required when cloud_provider=alicloud
  string region = 2 [(google.api.field_behavior) = OPTIONAL];
  string bucket_uri = 3 [(google.api.field_behavior) = REQUIRED];
  BackupStorageAuth auth = 4 [(google.api.field_behavior) = REQUIRED];
}

message BackupStorageAuth {
  string access_key_id = 1 [(google.api.field_behavior) = REQUIRED];
  string access_key_secret = 2 [(google.api.field_behavior) = REQUIRED];
}

message TestClassicBackupAccessRequest {
  ClassicBackupStorage classic_backup_storage = 1 [(google.api.field_behavior) = REQUIRED];
  common.v1.ServicePlan service_plan = 2 [(google.api.field_behavior) = REQUIRED];
  uint64 organization_id = 3 [(google.api.field_behavior) = REQUIRED];
}

message TestClassicBackupAccessResponse {
  enum Status {
    STATUS_UNSPECIFIED = 0;
    SUCCESS = 1;
    NO_SUCH_BUCKET = 2;
    ILLEGAL_BACKUP = 3;
    ACCESS_DENIED = 4;
    INVALID_PARAMS = 5;
  }

  Status status = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
  string message = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
  // following fields only return when status is success
  common.v1.CloudProvider.Name cloud_provider = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
  string region = 4 [(google.api.field_behavior) = OUTPUT_ONLY];
  string version = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
  google.protobuf.Timestamp backup_time = 6 [(google.api.field_behavior) = OUTPUT_ONLY];
  uint64 data_size_bytes = 7 [(google.api.field_behavior) = OUTPUT_ONLY];
}

message StopRestoreClusterRequest {
  string target_cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
}

message RestoreStatusRequest {
  string cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
}

message RestoreStatusResponse {
  // The status of the restore operation
  RestoreState state = 1 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Error message provided if the restore failed
  string message = 2 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Progress percentage (0-100)
  int32 progress = 3 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Durable metadata for the restore operation.
  RestoreDetails details = 4 [(google.api.field_behavior) = OUTPUT_ONLY];
}

message GetBackupSettingRequest {
  string cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
}

message UpdateBackupSettingRequest {
  BackupSetting backup_setting = 1 [(google.api.field_behavior) = REQUIRED];
  bool validate_only = 100 [(google.api.field_behavior) = OPTIONAL];
}

message GetProviderRoleRequest {
  uint64 cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
}

message GetCaCertificateDownloadUrlRequest {
  uint64 cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
}

message CaCertificateDownloadUrl {
  string uri = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
}

// UpdateClusterProjectRequest is the request to update a cluster's project_id.
message UpdateClusterProjectRequest {
  uint64 cluster_id = 1;
  uint64 project_id = 2;
}

// UpdateClusterProjectResponse is the response for updating a cluster's project_id.
message UpdateClusterProjectResponse {}

message EstimatePriceRequest {
  uint64 organization_id = 1 [(google.api.field_behavior) = REQUIRED];
  common.v1.Region.Name region_id = 2 [(google.api.field_behavior) = REQUIRED];
  common.v1.ServicePlan service_plan = 3 [(google.api.field_behavior) = REQUIRED];
  int64 max_rcu = 4 [(google.api.field_behavior) = OPTIONAL];
  uint64 reserved_capacity_template_id = 7 [(google.api.field_behavior) = OPTIONAL];
}

message EstimatePriceResponse {
  string cloud_provider = 1;
  string region = 2;
  int64 rcu = 3;
  string rcu_cost_hourly = 4;
  string rcu_cost_monthly = 5;
}

message UpdateClusterDualLayerEncryptionRequest {
  uint64 cluster_id = 1 [(google.api.field_behavior) = REQUIRED];

  oneof target_encryption {
    CustomerManagedEncryptionKey cmek = 2;
    google.protobuf.Empty default_key = 3;
    google.protobuf.Empty no_encryption = 5;
  }

  bool validate_only = 4 [(google.api.field_behavior) = OPTIONAL];
}

message UpdateClusterDualLayerEncryptionResponse {
  uint64 cluster_id = 1;
}

message GetClusterEncryptionStatusRequest {
  uint64 cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
}

message ClusterEncryptionStatus {
  uint64 cluster_id = 1;

  enum State {
    STATE_UNSPECIFIED = 0;
    MODIFYING = 1;
    ENABLED = 2;
  }

  State state = 2;
  string message = 3;

  Cluster.DualLayerDataEncryption current_encryption = 4;
}

// ForceUpdateGatewayIdentityRequest is the request to force update gateway identity for a cluster.
message ForceUpdateGatewayIdentityRequest {
  uint64 cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
  string gateway_identity = 2 [(google.api.field_behavior) = REQUIRED];
}

message RestoreDetails {
  uint64 source_cluster_id = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
  RestoreMode restore_mode = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
  uint64 backup_id = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
  google.protobuf.Timestamp point_in_time = 4 [(google.api.field_behavior) = OUTPUT_ONLY];
  google.protobuf.Timestamp restore_requested_time = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
  google.protobuf.Timestamp restore_updated_time = 6 [(google.api.field_behavior) = OUTPUT_ONLY];
  uint64 expected_restore_data_size_bytes = 7 [(google.api.field_behavior) = OUTPUT_ONLY];
  string source_region_id = 8 [(google.api.field_behavior) = OUTPUT_ONLY];
  common.v1.CloudProvider.Name source_cloud_provider = 9 [(google.api.field_behavior) = OUTPUT_ONLY];
  common.v1.ServicePlan source_service_plan = 10 [(google.api.field_behavior) = OUTPUT_ONLY];
}
