syntax = "proto3";

package global.dedicated.v1;

import "global/common/v1/resources.proto";
import "global/dedicated/v1/resources.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) {}

  // DeleteCluster deletes the cluster but keeps the backup records. The cluster can be restored from the backup.
  rpc DeleteCluster(DeleteClusterRequest) returns (Cluster) {}

  rpc ScaleCluster(ScaleClusterRequest) returns (Cluster) {}

  rpc ScaleClusterWithMultiComponent(ScaleClusterWithMultiComponentRequest) returns (Cluster) {}

  rpc PauseCluster(PauseClusterRequest) returns (Cluster) {}

  rpc ResumeCluster(ResumeClusterRequest) returns (Cluster) {}

  rpc GetComponentNodeInfo(GetComponentNodeInfoRequest) returns (GetComponentNodeInfoResponse) {}

  rpc SetClientCaCertificate(SetClientCaCertificateRequest) returns (google.protobuf.Empty) {}

  rpc GetClientCaCertificate(GetClientCaCertificateRequest) returns (GetClientCaCertificateResponse) {}

  rpc ApplyCluster(ApplyClusterRequest) returns (Cluster) {}

  rpc ApplyGKEHeterogeneousDeploy(ApplyGKEHeterogeneousDeployRequest) returns (GKEHeterogeneousDeploy) {}

  rpc GetGKEHeterogeneousDeploy(GetGKEHeterogeneousDeployRequest) returns (GKEHeterogeneousDeploy) {}

  rpc DeleteGKEHeterogeneousDeploy(DeleteGKEHeterogeneousDeployRequest) returns (google.protobuf.Empty) {}

  rpc GetBillableClustersCount(GetBillableClustersCountRequest) returns (GetBillableClustersCountResponse);

  rpc GetClusterConfidentialInfo(GetClusterConfidentialInfoRequest) returns (GetClusterConfidentialInfoResponse) {}

  rpc CreateClusterSnapshot(CreateClusterSnapshotRequest) returns (CreateClusterSnapshotResponse) {}

  rpc ListClusterSnapshots(ListClusterSnapshotsRequest) returns (ListClusterSnapshotsResponse) {}

  rpc ListTenantQuota(ListTenantQuotaRequest) returns (ListTenantQuotaResponse) {}

  rpc UpdateTenantQuota(UpdateTenantQuotaRequest) returns (UpdateTenantQuotaResponse) {}

  rpc ChangeClusterPasswd(ChangeClusterPasswdRequest) returns (ChangeClusterPasswdResponse) {}

  rpc GetDefaultTidbVersion(GetDefaultTidbVersionRequest) returns (GetDefaultTidbVersionResponse) {}

  rpc GetLogRedactionPolicy(GetLogRedactionPolicyRequest) returns (LogRedactionPolicy) {}

  rpc UpdateLogRedactionPolicy(UpdateLogRedactionPolicyRequest) returns (LogRedactionPolicy) {}

  // BuildDesiredComponents builds the desired components for a cluster based on the provided parameters.
  // It returns the current and desired components, and also the default components derived from SKUs.
  // One can use this RPC to diff component changes.
  rpc BuildDesiredComponents(BuildDesiredComponentsRequest) returns (BuildDesiredComponentsResponse) {}

  rpc GetClusterCustomParams(GetClusterCustomParamsRequest) returns (GetClusterCustomParamsResponse) {}

  rpc SyncSystemVariables(SyncSystemVariablesRequest) returns (google.protobuf.Empty) {}

  rpc SyncPdOnlineConfig(SyncPdOnlineConfigRequest) returns (google.protobuf.Empty) {}

  rpc ShutdownUpgradeCluster(ShutdownUpgradeClusterRequest) returns (google.protobuf.Empty) {}

  rpc EnableClusterConfigBackup(EnableClusterConfigBackupRequest) returns (ClusterConfigBackupPolicy) {}

  rpc DisableClusterConfigBackup(DisableClusterConfigBackupRequest) returns (ClusterConfigBackupPolicy) {}

  rpc ListClusterConfigBackup(ListClusterConfigBackupRequest) returns (ListClusterConfigBackupResponse) {}
}

service RegionService {
  rpc ListCloudProviders(ListCloudProvidersRequest) returns (ListCloudProvidersResponse) {}

  rpc RegisterCloudProvider(RegisterCloudProviderRequest) returns (common.v1.CloudProvider) {}

  rpc ListRegions(ListRegionsRequest) returns (ListRegionsResponse) {}

  rpc SelectRegionByOrgId(SelectRegionByOrgIdRequest) returns (common.v1.Region) {}

  rpc GetRegionByLogicalName(GetRegionByLogicalNameRequest) returns (common.v1.Region) {}

  rpc RegisterRegion(RegisterRegionRequest) returns (common.v1.Region) {}

  rpc UpdateRegion(UpdateRegionRequest) returns (common.v1.Region) {}

  rpc CheckRegionStatus(CheckRegionStatusRequest) returns (google.protobuf.Empty) {}

  rpc DeleteRegion(DeleteRegionRequest) returns (google.protobuf.Empty) {}
}

service SpuService {
  rpc ListSpus(ListSpusRequest) returns (ListSpusResponse) {}

  rpc GetSpu(GetSpuRequest) returns (Spu) {}

  rpc BatchUpsertSpus(BatchUpsertSpusRequest) returns (BatchUpsertSpusResponse) {}

  rpc GetInstanceMu(GetInstanceMuRequest) returns (InstanceMu) {}

  rpc GetStorageMu(GetStorageMuRequest) returns (StorageMu) {}

  rpc ListInstanceMus(ListInstanceMusRequest) returns (ListInstanceMusResponse) {}

  rpc ListStorageMus(ListStorageMusRequest) returns (ListStorageMusResponse) {}

  rpc BatchUpsertInstanceMus(BatchUpsertInstanceMusRequest) returns (BatchUpsertInstanceMusResponse) {}

  rpc BatchUpsertStorageMus(BatchUpsertStorageMusRequest) returns (BatchUpsertStorageMusResponse) {}

  rpc GetSku(GetSkuRequest) returns (Sku) {}

  rpc ListSkus(ListSkusRequest) returns (ListSkusResponse) {}

  rpc BatchUpsertSkus(BatchUpsertSkusRequest) returns (BatchUpsertSkusResponse) {}
}

service TidbNodeGroupService {
  rpc CreateTidbNodeGroup(CreateTidbNodeGroupRequest) returns (TidbNodeGroup) {}

  rpc UpdateTidbNodeGroup(UpdateTidbNodeGroupRequest) returns (TidbNodeGroup) {}

  rpc DeleteTidbNodeGroup(DeleteTidbNodeGroupRequest) returns (google.protobuf.Empty) {}

  rpc ListTidbNodeGroups(ListTidbNodeGroupsRequest) returns (ListTidbNodeGroupsResponse) {}

  rpc DisableTidbGroupDNS(DisableTidbGroupDNSRequest) returns (google.protobuf.Empty) {}

  rpc EnableTidbGroupDNS(EnableTidbGroupDNSRequest) returns (google.protobuf.Empty) {}

  rpc GetPrivateLinkIPAddressType(GetPrivateLinkIPAddressTypeRequest) returns (TidbGroupPrivateLinkIPAddressTypeStatus) {}

  rpc SetPrivateLinkIPAddressType(SetPrivateLinkIPAddressTypeRequest) returns (TidbGroupPrivateLinkIPAddressTypeStatus) {}
}

service VpcService {
  rpc ListVpcs(ListVpcsRequest) returns (ListVpcsResponse) {}

  rpc DeleteVpc(DeleteVpcRequest) returns (google.protobuf.Empty) {}

  rpc DeleteVpcPeering(DeleteVpcPeeringRequest) returns (google.protobuf.Empty) {}

  rpc ListVpcPeerings(ListVpcPeeringsRequest) returns (ListVpcPeeringsResponse) {}

  rpc GetVpcPeering(GetVpcPeeringRequest) returns (VpcPeering) {}

  rpc CreateVpcPeering(CreateVpcPeeringRequest) returns (CreateVpcPeeringResponse) {}

  rpc CreateCidr(CreateCidrRequest) returns (CreateCidrResponse) {}

  rpc QueryCidrs(QueryCidrsRequest) returns (QueryCidrsResponse) {}

  rpc UpdateCidr(UpdateCidrRequest) returns (UpdateCidrResponse) {}

  rpc DeleteCidr(DeleteCidrRequest) returns (google.protobuf.Empty) {}

  rpc GetDefaultCidr(GetDefaultCidrRequest) returns (GetDefaultCidrResponse) {}

  rpc AddSecondaryCidr(AddSecondaryCidrRequest) returns (Vpc) {}
}

service PrivateLinkConnectionService {
  rpc CreatePrivateLinkService(CreatePrivateLinkServiceRequest) returns (CreatePrivateLinkServiceResponse) {}

  rpc DeletePrivateLinkService(DeletePrivateLinkServiceRequest) returns (google.protobuf.Empty) {}

  // Deprecated: This method only returns the private link service of the default Tidb node group.
  rpc GetPrivateLinkService(GetPrivateLinkServiceRequest) returns (GetPrivateLinkServiceResponse) {
    option deprecated = true;
  }

  rpc CreatePrivateLinkEndpoint(CreatePrivateLinkEndpointRequest) returns (CreatePrivateLinkEndpointResponse) {}

  rpc DeletePrivateLinkEndpoint(DeletePrivateLinkEndpointRequest) returns (google.protobuf.Empty) {}

  // only list endpoints of default Tidb node group
  rpc ListPrivateLinkEndpoints(ListPrivateLinkEndpointsRequest) returns (ListPrivateLinkEndpointsResponse) {}

  rpc ListTidbNodeGroupPrivateLinkEndpoints(ListTidbNodeGroupPrivateLinkEndpointsRequest) returns (ListTidbNodeGroupPrivateLinkEndpointsResponse) {}

  rpc RejectVpcEndpointConnections(RejectVpcEndpointConnectionsRequest) returns (google.protobuf.Empty) {}

  rpc PausePrivateLinkService(PausePrivateLinkServiceRequest) returns (google.protobuf.Empty) {}

  rpc PurgePrivateLinkServiceMetadata(PurgePrivateLinkServiceMetadataRequest) returns (google.protobuf.Empty) {}
}

service CustomerManagedEncryptionService {
  rpc CreateCustomerManagedEncryptionKey(CreateCustomerManagedEncryptionKeyRequest) returns (CustomerManagedEncryptionKey) {}

  rpc GetCustomerManagedEncryptionKey(GetCustomerManagedEncryptionKeyRequest) returns (CustomerManagedEncryptionKey) {}

  rpc ListCustomerManagedEncryptionKeys(ListCustomerManagedEncryptionKeysRequest) returns (ListCustomerManagedEncryptionKeysResponse) {}

  rpc DeleteCustomerManagedEncryptionKey(DeleteCustomerManagedEncryptionKeyRequest) returns (google.protobuf.Empty) {}

  rpc GetCmekAccessIamPrincipal(GetCmekAccessIamPrincipalRequest) returns (GetCmekAccessIamPrincipalResponse) {}
}

service DatabaseAuditLogService {
  rpc GetAuditLogConfig(GetAuditLogConfigRequest) returns (AuditLogConfig) {}
  rpc UpdateAuditLogConfig(UpdateAuditLogConfigRequest) returns (AuditLogConfig) {}
  rpc PrecheckAuditLogConfig(PrecheckAuditLogConfigRequest) returns (PrecheckAuditLogConfigResponse) {}

  rpc ListAuditLogFilterRules(ListAuditLogFilterRulesRequest) returns (ListAuditLogFilterRulesResponse) {}
  rpc CreateAuditLogFilterRule(CreateAuditLogFilterRuleRequest) returns (AuditLogFilterRule) {}
  rpc DeleteAuditLogFilterRule(DeleteAuditLogFilterRuleRequest) returns (google.protobuf.Empty) {}
  rpc ReplaceAuditLogFilterRule(ReplaceAuditLogFilterRuleRequest) returns (AuditLogFilterRule) {}

  rpc GetAccount(GetAccountRequest) returns (GetAccountResponse) {}

  rpc QueryAuditLogFiles(QueryAuditLogFilesRequest) returns (QueryAuditLogFilesResponse) {}
  rpc GenerateAuditLogFileDownloadAddress(GenerateAuditLogFileDownloadAddressRequest) returns (GenerateAuditLogFileDownloadAddressResponse) {}
}

service MeteringService {
  rpc CalcClusterFee(CalcClusterFeeRequest) returns (CalcClusterFeeResponse) {}
}

message Pager {
  int64 page = 1; // start from 1
  int64 page_size = 2;
}

message Sorter {
  string order_by = 1;
  Sort sort = 2;

  enum Sort {
    SORT_UNSPECIFIED = 0;
    ASC = 1;
    DESC = 2;
  }
}

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

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

  ClusterConfiguration cluster_configuration = 3 [(google.api.field_behavior) = OPTIONAL];

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

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

  // Default to return non-deleted clusters only.
  bool show_deleted = 8 [(google.api.field_behavior) = OPTIONAL];
  // if show details is false, not return modify progress and network info
  bool show_details = 9 [(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];

  // When true, skip fetching modify progress and network info from Regional Server.
  // Default false (unset) preserves current behavior (Regional enrichment enabled).
  // Domain maps BFF/OpenAPI global_meta_only to this field.
  optional bool ignore_details = 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 ScaleClusterRequest {
  uint64 cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
  Cluster.ClusterComponent cluster_component = 2 [(google.api.field_behavior) = REQUIRED];

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

  // The storage change only takes effect when force_scale is set to true, otherwise, the storage change will be ignored.
  // Cluster state will be ignored, too.
  bool force_scale = 4 [(google.api.field_behavior) = OPTIONAL];
}

message ScaleClusterWithMultiComponentRequest {
  uint64 cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
  repeated Cluster.ClusterComponent cluster_components = 2 [(google.api.field_behavior) = REQUIRED];

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

  // The storage change only takes effect when force_scale is set to true, otherwise, the storage change will be ignored.
  // Cluster state will be ignored, too.
  bool force_scale = 4 [(google.api.field_behavior) = OPTIONAL];

  // Carries the upstream operation source for cluster events.
  string source_operation = 5 [(google.api.field_behavior) = OPTIONAL];

  // Carries the upstream requested fields for cluster events.
  repeated string requested_fields = 6 [(google.api.field_behavior) = OPTIONAL];
}

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

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

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

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

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

message GetComponentNodeInfoResponse {
  ComponentNodeInfo component_node_info = 1;
}

message SetClientCaCertificateRequest {
  uint64 cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
  string ca_certificate = 3 [(google.api.field_behavior) = REQUIRED];
}

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

message GetClientCaCertificateResponse {
  string ca_certificate = 1;
}

message ApplyClusterRequest {
  uint64 cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
  ClusterApplyMask cluster_apply_mask = 2 [(google.api.field_behavior) = REQUIRED];

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

message ApplyGKEHeterogeneousDeployRequest {
  reserved 7;
  reserved "count";
  uint64 tenant_id = 1 [(google.api.field_behavior) = REQUIRED];
  uint64 project_id = 2 [(google.api.field_behavior) = REQUIRED];
  uint64 cluster_id = 3 [(google.api.field_behavior) = REQUIRED];
  ComponentType component_type = 4 [(google.api.field_behavior) = REQUIRED];
  string current_instance_type = 5 [(google.api.field_behavior) = REQUIRED];
  string alternative_instance_type = 6 [(google.api.field_behavior) = REQUIRED];
  uint64 tidb_group_id = 8 [(google.api.field_behavior) = OPTIONAL];
}

message GetGKEHeterogeneousDeployRequest {
  uint64 cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
  ComponentType component_type = 2 [(google.api.field_behavior) = REQUIRED];
  uint64 tidb_group_id = 3 [(google.api.field_behavior) = OPTIONAL];
  uint64 tenant_id = 4 [(google.api.field_behavior) = REQUIRED];
  uint64 project_id = 5 [(google.api.field_behavior) = REQUIRED];
}

message DeleteGKEHeterogeneousDeployRequest {
  uint64 cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
  ComponentType component_type = 2 [(google.api.field_behavior) = REQUIRED];
  uint64 tidb_group_id = 3 [(google.api.field_behavior) = OPTIONAL];
  uint64 tenant_id = 4 [(google.api.field_behavior) = REQUIRED];
  uint64 project_id = 5 [(google.api.field_behavior) = REQUIRED];
}

message GKEHeterogeneousDeploy {
  reserved 5;
  reserved "count";
  bool enabled = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
  ComponentType component_type = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
  string current_instance_type = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
  string alternative_instance_type = 4 [(google.api.field_behavior) = OUTPUT_ONLY];
  uint64 tidb_group_id = 6 [(google.api.field_behavior) = OUTPUT_ONLY];
  string status = 7 [(google.api.field_behavior) = OUTPUT_ONLY];
  repeated GKEHeterogeneousDeployPodCount pod_counts = 8 [(google.api.field_behavior) = OUTPUT_ONLY];
}

message GetBillableClustersCountRequest {
  uint64 project_id = 1 [(google.api.field_behavior) = REQUIRED];
  google.protobuf.Timestamp start_time = 2 [(google.api.field_behavior) = REQUIRED];
  google.protobuf.Timestamp end_time = 3 [(google.api.field_behavior) = REQUIRED];
}

message GetBillableClustersCountResponse {
  uint32 billable_clusters_count = 1;
}

message SimulatedSelectSkuRequest {
  Cluster cluster = 1 [(google.api.field_behavior) = REQUIRED];
  ScaleClusterWithMultiComponentRequest request = 2 [(google.api.field_behavior) = REQUIRED];
}

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

message GetClusterConfidentialInfoResponse {
  string encrypted_cloud_admin_password = 1;
}

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

message CreateClusterSnapshotResponse {
  uint64 snapshot_id = 1;
}

message ListClusterSnapshotsRequest {
  ClusterSnapshotFilter filter = 1 [(google.api.field_behavior) = OPTIONAL];

  Pager pager = 2 [(google.api.field_behavior) = OPTIONAL];
  repeated Sorter sorters = 4 [(google.api.field_behavior) = OPTIONAL];

  message ClusterSnapshotFilter {
    repeated uint64 tenant_ids = 1;
    repeated uint64 project_ids = 2;
    repeated uint64 cluster_ids = 3;
    repeated uint64 snapshot_ids = 4;
  }
}

message ListClusterSnapshotsResponse {
  repeated ClusterSnapshot snapshots = 1;
}

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

message ListTenantQuotaResponse {
  repeated TenantQuota tenant_quotas = 1;
}

message UpdateTenantQuotaRequest {
  uint64 tenant_id = 1 [(google.api.field_behavior) = REQUIRED];
  ComponentType component = 2 [(google.api.field_behavior) = REQUIRED];
  uint32 quota = 3 [(google.api.field_behavior) = REQUIRED];
}

message UpdateTenantQuotaResponse {
  TenantQuota tenant_quota = 1;
}

message ChangeClusterPasswdRequest {
  uint64 cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
  string passwd = 2 [(google.api.field_behavior) = REQUIRED];
}

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

message GetDefaultTidbVersionRequest {
  common.v1.CloudProvider.Name cloud_provider = 1 [(google.api.field_behavior) = REQUIRED];
  common.v1.Region.Name region = 2 [(google.api.field_behavior) = REQUIRED];
  uint64 tenant_id = 3 [(google.api.field_behavior) = REQUIRED];
}

message GetDefaultTidbVersionResponse {
  string version = 1;
}

message ListCloudProvidersRequest {
  uint64 organization_id = 1 [(google.api.field_behavior) = OPTIONAL];
  uint64 project_id = 2 [(google.api.field_behavior) = OPTIONAL];

  bool ignore_spu_check = 3 [(google.api.field_behavior) = OPTIONAL];
}

message ListCloudProvidersResponse {
  repeated common.v1.CloudProvider cloud_providers = 1;
  uint32 total = 2;
}

message RegisterCloudProviderRequest {
  common.v1.CloudProvider cloud_provider = 1 [(google.api.field_behavior) = REQUIRED];
}

message RegisterRegionRequest {
  common.v1.Region region = 1 [(google.api.field_behavior) = REQUIRED];
}

message SelectRegionByOrgIdRequest {
  uint64 organization_id = 1 [(google.api.field_behavior) = REQUIRED];
  common.v1.CloudProvider.Name cloud_provider_id = 2 [(google.api.field_behavior) = REQUIRED];
  common.v1.Region.Name region_id = 3 [(google.api.field_behavior) = REQUIRED];
}

message GetRegionByLogicalNameRequest {
  common.v1.CloudProvider.Name cloud_provider_id = 1 [(google.api.field_behavior) = REQUIRED];
  string region_logical_name = 2 [(google.api.field_behavior) = REQUIRED];
}

message UpdateRegionRequest {
  common.v1.Region region = 1 [(google.api.field_behavior) = REQUIRED];
}

message CheckRegionStatusRequest {
  common.v1.CloudProvider.Name cloud_provider_id = 1 [(google.api.field_behavior) = REQUIRED];
  string region_logical_name = 2 [(google.api.field_behavior) = REQUIRED];
}

message DeleteRegionRequest {
  common.v1.CloudProvider.Name cloud_provider_id = 1 [(google.api.field_behavior) = REQUIRED];
  string region_logical_name = 2 [(google.api.field_behavior) = REQUIRED];
}

message ListRegionsRequest {
  repeated common.v1.CloudProvider.Name cloud_provider_ids = 1 [(google.api.field_behavior) = OPTIONAL];
  // If not specified, list all regions ignoring whether sku exist.
  uint64 organization_id = 2 [(google.api.field_behavior) = OPTIONAL];
  // If organization_id is specified, project_id is required, too.
  uint64 project_id = 3 [(google.api.field_behavior) = OPTIONAL];

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

message ListRegionsResponse {
  repeated common.v1.Region regions = 1;

  uint32 total = 2;
}

message ListVpcsRequest {
  uint64 organization_id = 1 [(google.api.field_behavior) = OPTIONAL];
  uint64 project_id = 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];
}

message ListVpcsResponse {
  repeated Vpc vpcs = 1;

  uint32 total = 2;
}

message DeleteVpcRequest {
  string vpc_id = 1 [(google.api.field_behavior) = REQUIRED];
  common.v1.Region.Name region_id = 2 [(google.api.field_behavior) = REQUIRED];
  common.v1.CloudProvider.Name cloud_provider_id = 3 [(google.api.field_behavior) = REQUIRED];
  uint64 organization_id = 4 [(google.api.field_behavior) = OPTIONAL];
  uint64 project_id = 5 [(google.api.field_behavior) = OPTIONAL];
}

message DeleteVpcPeeringRequest {
  uint64 vpc_peering_id = 1 [(google.api.field_behavior) = REQUIRED];
  common.v1.CloudProvider.Name cloud_provider = 3 [(google.api.field_behavior) = REQUIRED];
}

message ListVpcPeeringsRequest {
  uint64 organization_id = 1 [(google.api.field_behavior) = OPTIONAL];
  repeated uint64 project_ids = 2 [(google.api.field_behavior) = OPTIONAL];
  repeated common.v1.CloudProvider.Name cloud_providers = 3 [(google.api.field_behavior) = OPTIONAL];
  repeated common.v1.Region.Name regions = 4 [(google.api.field_behavior) = OPTIONAL];
  repeated VpcPeering.State states = 5 [(google.api.field_behavior) = OPTIONAL];
  repeated VpcPeering.Type types = 6 [(google.api.field_behavior) = OPTIONAL];
  repeated uint64 ids = 7 [(google.api.field_behavior) = OPTIONAL];

  Pager pager = 8 [(google.api.field_behavior) = OPTIONAL];
  Sorter sorter = 9 [(google.api.field_behavior) = OPTIONAL];
}

message ListVpcPeeringsResponse {
  repeated VpcPeering vpc_peerings = 1;
}

message GetVpcPeeringRequest {
  common.v1.CloudProvider.Name cloud_provider = 1 [(google.api.field_behavior) = REQUIRED];
  uint64 vpc_peering_id = 2 [(google.api.field_behavior) = REQUIRED];
}

message CreateVpcPeeringRequest {
  VpcPeering peering = 1 [(google.api.field_behavior) = REQUIRED];
  uint64 operator_user_id = 2 [
    (google.api.field_behavior) = OPTIONAL,
    deprecated = true
  ];
}

message CreateVpcPeeringResponse {
  uint64 peering_id = 1;
}

message CreateCidrRequest {
  uint64 project_id = 1 [(google.api.field_behavior) = REQUIRED];
  string cidr = 2 [(google.api.field_behavior) = REQUIRED];
  string cloud_provider_name = 3 [(google.api.field_behavior) = REQUIRED];
  string region_name = 4 [(google.api.field_behavior) = REQUIRED];

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

message CreateCidrResponse {
  uint64 id = 1;
  repeated CidrOverlap overlaps = 2; // Only output when validate_only is true.
  uint32 max_node_ip = 3; // Only output when validate_only is true. The max node IP of the CIDR.
}

message QueryCidrsRequest {
  QueryCidrsFilter filter = 1 [(google.api.field_behavior) = OPTIONAL];

  // When true, skip Regional Server enrichment and return global-layer CIDR metadata only
  // (state is STATE_UNSPECIFIED, vpc_id empty). Default false preserves current behavior
  // (Regional ListVpcs used to derive state and vpc_id).
  optional bool global_meta_only = 2 [(google.api.field_behavior) = OPTIONAL];

  message QueryCidrsFilter {
    repeated uint64 ids = 1;
    repeated uint64 project_ids = 2;
    string cloud_provider_name = 3;
  }
}

message QueryCidrsResponse {
  repeated Cidr items = 1;
}

message UpdateCidrRequest {
  uint64 id = 1 [(google.api.field_behavior) = REQUIRED];
  uint64 project_id = 2 [(google.api.field_behavior) = REQUIRED];
  string cidr = 3 [(google.api.field_behavior) = REQUIRED];

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

message UpdateCidrResponse {
  repeated CidrOverlap overlaps = 1; // Only output when validate_only is true.
  uint32 max_node_ip = 2; // Only output when validate_only is true. The max node IP of the CIDR.
}

message DeleteCidrRequest {
  uint64 id = 1 [(google.api.field_behavior) = REQUIRED];
  uint64 project_id = 2 [(google.api.field_behavior) = REQUIRED];
}

message GetDefaultCidrRequest {
  string cloud_provider_name = 1 [(google.api.field_behavior) = REQUIRED];
  string region_name = 2 [(google.api.field_behavior) = REQUIRED];
  uint64 project_id = 3 [(google.api.field_behavior) = REQUIRED];
}

message GetDefaultCidrResponse {
  DefaultCidr default_cidr = 1;

  message DefaultCidr {
    string name = 1;
    string cloud_provider_name = 2;
    string region_name = 3;
    string region_display_name = 4;
    string cidr = 5;
    uint64 project_id = 6;
  }
}

message CreatePrivateLinkServiceRequest {
  uint64 org_id = 1;
  uint64 project_id = 2;
  uint64 cluster_id = 3;

  PrivateLinkService private_link_service = 4 [
    (google.api.field_behavior) = OPTIONAL,
    deprecated = true
  ];

  // When false (default), the downstream PrivateLinkService.Id is set to the
  // tidb_group_id, preserving the existing behavior.
  // When true, a new unique id is generated via Sonyflake and used as the
  // downstream PrivateLinkService.Id.
  // This is required by scenarios such as Dedicated -> Premium migration:
  // Dedicated clusters need to rebuild endpoints to avoid conflicts with previous ones.
  bool generate_unique_service_id = 5 [(google.api.field_behavior) = OPTIONAL];
}

message CreatePrivateLinkServiceResponse {
  PrivateLinkService private_link_service = 1;
}

message DeletePrivateLinkServiceRequest {
  uint64 org_id = 1;
  uint64 project_id = 2;
  uint64 cluster_id = 3;
}

// Deprecated: This method only returns the private link service of the default Tidb node group.
message GetPrivateLinkServiceRequest {
  option deprecated = true;

  uint64 org_id = 1;
  uint64 project_id = 2;
  uint64 cluster_id = 3;
}

// Deprecated: This method only returns the private link service of the default Tidb node group.
message GetPrivateLinkServiceResponse {
  option deprecated = true;

  PrivateLinkService private_link_service = 1;
}

message ListPrivateLinkEndpointsRequest {
  repeated uint64 org_ids = 1 [(google.api.field_behavior) = OPTIONAL];
  repeated uint64 project_ids = 2 [(google.api.field_behavior) = OPTIONAL];
  repeated uint64 cluster_ids = 3 [(google.api.field_behavior) = OPTIONAL];
}

message ListPrivateLinkEndpointsResponse {
  repeated PrivateLinkEndpoint endpoints = 1;
}

message ListTidbNodeGroupPrivateLinkEndpointsRequest {
  uint64 tidb_group_id = 1 [(google.api.field_behavior) = REQUIRED];
  uint64 cluster_id = 2 [(google.api.field_behavior) = REQUIRED];
  repeated PrivateLinkEndpoint.Type exclude_types = 3 [(google.api.field_behavior) = OPTIONAL];
}

message ListTidbNodeGroupPrivateLinkEndpointsResponse {
  repeated PrivateLinkEndpoint endpoints = 1;
  PrivateLinkService private_link_service = 2;
}

message CreatePrivateLinkEndpointRequest {
  uint64 org_id = 1;
  uint64 project_id = 2;
  uint64 cluster_id = 3;

  PrivateLinkEndpoint private_link_endpoint = 4;

  uint64 tidb_group_id = 5;

  // Default is false. If true, the request will not be applied and only validation will be performed.
  // At present, this field is only available for Azure provider.
  bool validate_only = 6;
}

message CreatePrivateLinkEndpointResponse {
  PrivateLinkEndpoint private_link_endpoint = 1;
}

message DeletePrivateLinkEndpointRequest {
  uint64 org_id = 1;
  uint64 project_id = 2;
  uint64 cluster_id = 3;
  string endpoint_id = 4;
  uint64 tidb_group_id = 5;
}

message RejectVpcEndpointConnectionsRequest {
  uint64 cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
  uint64 tidb_group_id = 2 [(google.api.field_behavior) = REQUIRED];
  repeated string endpoint_ids = 3 [(google.api.field_behavior) = REQUIRED];
}

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

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

message ListSpusRequest {
  oneof request {
    FilterWithSku with_sku = 1;
    FilterWithoutSku without_sku = 2;
  }

  message FilterWithoutSku {
    repeated ComponentType component_types = 1 [(google.api.field_behavior) = OPTIONAL];
    string name = 2 [(google.api.field_behavior) = OPTIONAL];
    repeated string versions = 3 [(google.api.field_behavior) = OPTIONAL];
  }

  // FilterWithSku means each returned spu must have at least a sku that pass select desired comp process.
  message FilterWithSku {
    common.v1.CloudProvider.Name cloud_provider = 1 [(google.api.field_behavior) = REQUIRED];
    common.v1.Region.Name region = 2 [(google.api.field_behavior) = REQUIRED];
    uint64 tenant_id = 3 [(google.api.field_behavior) = REQUIRED];
    uint64 project_id = 4 [(google.api.field_behavior) = REQUIRED];
    // If specified, only return spus that available for scale up/down the existing cluster.
    uint64 existing_cluster_id = 5 [(google.api.field_behavior) = OPTIONAL];
  }
}

message ListSpusResponse {
  repeated Spu spus = 1 [(google.api.field_behavior) = REQUIRED];
}

message ListInstanceMusRequest {
  common.v1.CloudProvider.Name cloud_provider = 1 [(google.api.field_behavior) = OPTIONAL];
  repeated common.v1.Region.Name regions = 2 [(google.api.field_behavior) = OPTIONAL];
  repeated InstanceMu.CpuArch cpu_archs = 3 [(google.api.field_behavior) = OPTIONAL];
}

message ListInstanceMusResponse {
  // Sorted by num of cpu then memory size.
  repeated InstanceMu instance_mus = 1;
}

message ListStorageMusRequest {
  common.v1.CloudProvider.Name cloud_provider = 1 [(google.api.field_behavior) = REQUIRED];
  repeated common.v1.Region.Name regions = 2 [(google.api.field_behavior) = OPTIONAL];
  repeated StorageMu.VolumeType volume_types = 3 [(google.api.field_behavior) = OPTIONAL];
}

message ListStorageMusResponse {
  // Sorted by volume type.
  repeated StorageMu storage_mus = 1;
}

message BatchUpsertInstanceMusRequest {
  repeated InstanceMu adds = 1 [(google.api.field_behavior) = OPTIONAL];
  repeated uint64 deletes = 2 [(google.api.field_behavior) = OPTIONAL];
}

message BatchUpsertInstanceMusResponse {
  repeated InstanceMu adds = 1;
}

message BatchUpsertStorageMusRequest {
  repeated StorageMu adds = 1 [(google.api.field_behavior) = OPTIONAL];
  repeated uint64 deletes = 2 [(google.api.field_behavior) = OPTIONAL];
}

message BatchUpsertStorageMusResponse {
  repeated StorageMu adds = 1;
}

message ListSkusRequest {
  repeated common.v1.CloudProvider.Name cloud_providers = 1 [(google.api.field_behavior) = OPTIONAL];
  repeated ComponentType component_types = 2 [(google.api.field_behavior) = OPTIONAL];
}

message ListSkusResponse {
  repeated Sku skus = 1;
}

message BatchUpsertSkusRequest {
  repeated Sku adds = 1 [(google.api.field_behavior) = OPTIONAL];
  repeated uint64 deletes = 2 [(google.api.field_behavior) = OPTIONAL];
  repeated Update updates = 3 [(google.api.field_behavior) = OPTIONAL];

  message Update {
    uint64 id = 1 [(google.api.field_behavior) = REQUIRED];
    int32 default_node_count = 2 [(google.api.field_behavior) = OPTIONAL];
    int32 priority = 3 [(google.api.field_behavior) = OPTIONAL];
    Storage data_storage = 4 [(google.api.field_behavior) = OPTIONAL];
    Storage raftlog_storage = 5 [(google.api.field_behavior) = OPTIONAL];
    repeated Sku.Condition conditions = 6 [(google.api.field_behavior) = OPTIONAL];

    message Storage {
      int32 size_gi_default = 1 [(google.api.field_behavior) = OPTIONAL];
      int32 size_gi_max = 2 [(google.api.field_behavior) = OPTIONAL];
      int32 size_gi_min = 3 [(google.api.field_behavior) = OPTIONAL];

      int32 iops_max = 4 [(google.api.field_behavior) = OPTIONAL];
      int32 iops_min = 5 [(google.api.field_behavior) = OPTIONAL];

      int32 throughput_mibps_max = 6 [(google.api.field_behavior) = OPTIONAL];
      int32 throughput_mibps_min = 7 [(google.api.field_behavior) = OPTIONAL];

      oneof iops {
        IopsFixed iops_fixed = 8;
        IopsDynamic iops_dynamic = 9;
      }

      oneof throughput {
        ThroughputFixed throughput_fixed = 10;
        ThroughputDynamic throughput_dynamic = 11;
      }

      message IopsFixed {
        int32 iops = 1 [(google.api.field_behavior) = OPTIONAL];
      }

      message IopsDynamic {
        float iops_per_size_gi = 1 [(google.api.field_behavior) = OPTIONAL];
      }

      message ThroughputFixed {
        int32 throughput_mibps = 1 [(google.api.field_behavior) = OPTIONAL];
      }

      message ThroughputDynamic {
        float throughput_mibps_per_size_gi = 1 [(google.api.field_behavior) = OPTIONAL];
        float throughput_mibps_per_iops = 2 [(google.api.field_behavior) = OPTIONAL];
      }
    }
  }
}

message BatchUpsertSkusResponse {
  repeated Sku adds = 1;
  repeated Sku updates = 2;
}

message BatchUpsertSpusRequest {
  repeated Spu adds = 1 [(google.api.field_behavior) = OPTIONAL];
  repeated uint64 deletes = 2 [(google.api.field_behavior) = OPTIONAL];
  repeated Update updates = 3 [(google.api.field_behavior) = OPTIONAL];

  message Update {
    uint64 id = 1 [(google.api.field_behavior) = REQUIRED];
    string display_name = 3 [(google.api.field_behavior) = OPTIONAL];
    // Override the whole mapping list.
    repeated Spu.Mapping mappings = 6 [(google.api.field_behavior) = OPTIONAL];
  }
}

message BatchUpsertSpusResponse {
  repeated Spu adds = 1;
  repeated Spu updates = 2;
}

message GetSpuRequest {
  // Either by_id or by_attributes must be set. ID takes precedence if both are set.
  uint64 id = 1 [(google.api.field_behavior) = OPTIONAL];
  // Either by_id or by_attributes must be set. ID takes precedence if both are set.
  ByAttributes by_attributes = 2 [(google.api.field_behavior) = OPTIONAL];

  message ByAttributes {
    common.v1.CloudProvider.Name cloud_provider = 1 [(google.api.field_behavior) = REQUIRED];
    common.v1.Region.Name region = 2 [(google.api.field_behavior) = REQUIRED];
    ComponentType component_type = 3 [(google.api.field_behavior) = REQUIRED];
    string spu_name = 4 [(google.api.field_behavior) = REQUIRED];
    uint64 tenant_id = 5 [(google.api.field_behavior) = REQUIRED];
    uint64 project_id = 6 [(google.api.field_behavior) = REQUIRED];
    uint64 existing_cluster_id = 7 [(google.api.field_behavior) = OPTIONAL];
  }
}

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

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

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

message CreateTidbNodeGroupRequest {
  TidbNodeGroup tidb_node_group = 1 [(google.api.field_behavior) = REQUIRED];
  bool validate_only = 2 [(google.api.field_behavior) = OPTIONAL];
}

message UpdateTidbNodeGroupRequest {
  TidbNodeGroup tidb_node_group = 1 [(google.api.field_behavior) = REQUIRED];
  bool validate_only = 2 [(google.api.field_behavior) = OPTIONAL];
}

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

message ListTidbNodeGroupsRequest {
  repeated uint64 cluster_ids = 2 [(google.api.field_behavior) = REQUIRED];
  repeated uint64 ids = 1 [(google.api.field_behavior) = OPTIONAL];
  // if show details is false, not return PublicEndpoint, VpcPeeringEndpoint, PrivateEndpoint fields
  bool show_details = 3 [(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 ListTidbNodeGroupsResponse {
  repeated TidbNodeGroup tidb_node_groups = 1;
  uint32 total = 2;
}

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

message EnableTidbGroupDNSRequest {
  uint64 cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
  uint64 tidb_group_id = 2 [(google.api.field_behavior) = REQUIRED];
  // The DNS identity to set for the TiDB group.
  // If not provided, a random DNS identity will be generated.
  string dns_identity = 3 [(google.api.field_behavior) = OPTIONAL];
}

message CreateCustomerManagedEncryptionKeyRequest {
  CustomerManagedEncryptionKey customer_managed_encryption_key = 1 [(google.api.field_behavior) = REQUIRED];

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

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

message ListCustomerManagedEncryptionKeysRequest {
  uint64 organization_id = 1 [(google.api.field_behavior) = OPTIONAL];
  repeated uint64 project_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];
}

message ListCustomerManagedEncryptionKeysResponse {
  repeated CustomerManagedEncryptionKey customer_managed_encryption_keys = 1;
  uint32 total = 2;
}

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

message GetCmekAccessIamPrincipalRequest {
  uint64 organization_id = 1 [(google.api.field_behavior) = REQUIRED];
  uint64 project_id = 2 [(google.api.field_behavior) = REQUIRED];
  common.v1.CloudProvider.Name cloud_provider_id = 3 [(google.api.field_behavior) = REQUIRED];
  common.v1.Region.Name region_id = 4 [(google.api.field_behavior) = REQUIRED];
}

message GetCmekAccessIamPrincipalResponse {
  oneof principal {
    string iam_principal = 1;
    AzureCmekPrincipal azure_cmek_principal = 2;
  }
}

message AzureCmekPrincipal {
  AzureAppRegistration azure_app_registration = 1;
  string azure_key_vault_key_suffix = 2;
}

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

message UpdateAuditLogConfigRequest {
  AuditLogConfig audit_log_config = 6 [(google.api.field_behavior) = REQUIRED];
  bool validate_only = 7 [(google.api.field_behavior) = OPTIONAL];
}

message PrecheckAuditLogConfigRequest {
  AuditLogConfig audit_log_config = 2 [(google.api.field_behavior) = REQUIRED];
}

message PrecheckAuditLogConfigResponse {
  bool valid = 1;
  string message = 2;
}

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

message ListAuditLogFilterRulesResponse {
  repeated AuditLogFilterRule rules = 1;
}

message CreateAuditLogFilterRuleRequest {
  AuditLogFilterRule rule = 1 [(google.api.field_behavior) = REQUIRED];
}

message DeleteAuditLogFilterRuleRequest {
  uint64 cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
  oneof uk {
    uint64 id = 2 [(google.api.field_behavior) = OPTIONAL];
    string user_expr = 3 [(google.api.field_behavior) = OPTIONAL];
  }
}

message ReplaceAuditLogFilterRuleRequest {
  AuditLogFilterRule rule = 1 [(google.api.field_behavior) = REQUIRED];
}

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

message GetAccountResponse {
  string account = 1;
}

message QueryAuditLogFilesRequest {
  uint64 cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
  google.protobuf.Timestamp start_time = 2 [(google.api.field_behavior) = OPTIONAL];
  google.protobuf.Timestamp end_time = 3 [(google.api.field_behavior) = OPTIONAL];
  Pager pager = 4 [(google.api.field_behavior) = OPTIONAL];
}

message QueryAuditLogFilesResponse {
  repeated AuditLogFile audit_log_files = 1;
  uint32 total = 2;

  message AuditLogFile {
    string filename = 1;
    string uri = 2;
    string bucket = 3;
    int32 size_byte = 4;
    google.protobuf.Timestamp create_time = 5;
  }
}

message GenerateAuditLogFileDownloadAddressRequest {
  uint64 cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
  string audit_log_file_uri = 2 [(google.api.field_behavior) = REQUIRED];
}

message GenerateAuditLogFileDownloadAddressResponse {
  string download_address = 1;
}

message CalcClusterFeeRequest {
  uint64 tenant_id = 1;
  uint64 project_id = 2;
  string cloud_provider_name = 3;
  string region_name = 4;
  int64 duration = 5;
  repeated Cluster.ClusterComponent components = 7;
  bool is_cluster_paused = 8; // true indicate that calculate charge fee of paused cluster
  // [https://pingcap.feishu.cn/wiki/SWfnwtCBZid1bdk5a7FcamQcn5g#share-E8Uddcpw2onjx1xnUVuc9pcanSh](price promotion until 2025/May)
  // Default to false, i.e., use the new storage sku.
  bool promoted = 9 [(google.api.field_behavior) = OPTIONAL];
}

message CalcClusterFeeResponse {
  message ComponentCost {
    ComponentType component_type = 1;
    double compute = 2;
    double storage = 3;
    double raw_compute = 11;
    double raw_storage = 12;
  }

  repeated ComponentCost costs = 1;
}

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

message UpdateLogRedactionPolicyRequest {
  LogRedactionPolicy log_redaction_policy = 1 [(google.api.field_behavior) = REQUIRED];
}

message BuildDesiredComponentsRequest {
  oneof target {
    // Simulates a new cluster creation scenario. Only "desired_*" fields in response are available.
    Create create_cluster = 1;
    // Simulates a cluster modification scenario.
    // "current_*" fields in response are always available. "desired_*" fields are available only for modified components.
    Modify modify_cluster = 2;
    // Scan filtered clusters. Used by OPS portal or Clinic. Only "current_*" in response fields are available.
    Scan scan = 3;
  }

  message Create {
    uint64 tenant_id = 1 [(google.api.field_behavior) = REQUIRED];
    uint64 project_id = 2 [(google.api.field_behavior) = REQUIRED];
    common.v1.CloudProvider.Name cloud_provider = 3 [(google.api.field_behavior) = REQUIRED];
    common.v1.Region.Name region = 4 [(google.api.field_behavior) = REQUIRED];
    repeated Cluster.ClusterComponent cluster_components = 5 [(google.api.field_behavior) = REQUIRED];
  }

  message Modify {
    uint64 cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
    repeated Cluster.ClusterComponent requested_cluster_components = 2 [(google.api.field_behavior) = REQUIRED];
  }

  message Scan {
    repeated uint64 tenant_ids = 1 [(google.api.field_behavior) = OPTIONAL];
    repeated uint64 project_ids = 2 [(google.api.field_behavior) = OPTIONAL];
    repeated common.v1.CloudProvider.Name cloud_providers = 3 [(google.api.field_behavior) = OPTIONAL];
    repeated common.v1.Region.Name regions = 4 [(google.api.field_behavior) = OPTIONAL];
    repeated uint64 cluster_ids = 5 [(google.api.field_behavior) = OPTIONAL];
  }
}

message BuildDesiredComponentsResponse {
  repeated ClusterDiff cluster_diffs = 1;

  message ClusterDiff {
    // Only available when modify or scan.
    uint64 cluster_id = 1;

    // Current and desired are derived from whether the cluster is modified or not.
    // Effective and default are derived from whether the provisioned value is customized or SKU default.

    repeated Cluster.ClusterComponent current_default_components = 2;

    repeated Cluster.ClusterComponent current_effective_components = 3;

    repeated Cluster.ClusterComponent desired_default_components = 4;

    repeated Cluster.ClusterComponent desired_effective_components = 5;
  }
}

message AddSecondaryCidrRequest {
  // Required. The ID of the project.
  uint64 project_id = 1 [(google.api.field_behavior) = REQUIRED];

  // Required. The ID of the organization.
  uint64 organization_id = 2 [(google.api.field_behavior) = REQUIRED];

  // Required. The CIDR setting by user.
  string secondary_cidr = 3 [(google.api.field_behavior) = REQUIRED];

  // Required. The name of the cloud provider.
  string cloud_provider_name = 4 [(google.api.field_behavior) = REQUIRED];

  // Required. The region of the CIDR.
  string region_name = 5 [(google.api.field_behavior) = REQUIRED];

  // Required. The VPC ID of the secondary CIDR.
  string vpc_id = 6 [(google.api.field_behavior) = REQUIRED];

  // Optional. If true, only validate the CIDR, do not create it.
  bool validate_only = 7 [(google.api.field_behavior) = OPTIONAL];
}

message SyncSystemVariablesRequest {
  uint64 source_cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
  uint64 target_cluster_id = 2 [(google.api.field_behavior) = REQUIRED];
  bool allow_fallback_to_backup = 3 [(google.api.field_behavior) = OPTIONAL];
  bool skip = 4 [(google.api.field_behavior) = OPTIONAL];
}

message SyncPdOnlineConfigRequest {
  uint64 source_cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
  uint64 target_cluster_id = 2 [(google.api.field_behavior) = REQUIRED];
  bool allow_fallback_to_backup = 3 [(google.api.field_behavior) = OPTIONAL];
  bool skip_pd_config = 4 [(google.api.field_behavior) = OPTIONAL];
  bool skip_pd_server_config = 5 [(google.api.field_behavior) = OPTIONAL];
  bool skip_placement_rules = 6 [(google.api.field_behavior) = OPTIONAL];
  bool skip_store_limits = 7 [(google.api.field_behavior) = OPTIONAL];
}

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

message GetClusterCustomParamsResponse {
  ClusterConfiguration cluster_configuration = 1 [(google.api.field_behavior) = REQUIRED];
}

message ShutdownUpgradeClusterRequest {
  uint64 cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
  // the version to shutdown upgrade to
  // the version should be in the format of x.x.x
  string target_version = 2 [(google.api.field_behavior) = REQUIRED];
  // if true, only validate the request, do not perform the actual shutdown upgrade
  bool validate_only = 3 [(google.api.field_behavior) = OPTIONAL];
  string tidb_image_tag = 4 [(google.api.field_behavior) = OPTIONAL];
  string tikv_image_tag = 5 [(google.api.field_behavior) = OPTIONAL];
  string pd_image_tag = 6 [(google.api.field_behavior) = OPTIONAL];
  string tiflash_image_tag = 7 [(google.api.field_behavior) = OPTIONAL];
}

message ClusterConfigBackupPolicy {
  uint64 id = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
  uint64 cluster_id = 2 [(google.api.field_behavior) = REQUIRED];
  bool enabled = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
  int32 interval_sec = 4 [(google.api.field_behavior) = OUTPUT_ONLY];
  google.protobuf.Timestamp next_run_at = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
  google.protobuf.Timestamp last_backup_at = 6 [(google.api.field_behavior) = OUTPUT_ONLY];
  google.protobuf.Timestamp last_success_at = 7 [(google.api.field_behavior) = OUTPUT_ONLY];
  string last_error = 8 [(google.api.field_behavior) = OUTPUT_ONLY];
}

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

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

message ListClusterConfigBackupRequest {
  ClusterConfigBackupFilter filter = 1 [(google.api.field_behavior) = OPTIONAL];
  Pager pager = 2 [(google.api.field_behavior) = OPTIONAL];
  repeated Sorter sorters = 3 [(google.api.field_behavior) = OPTIONAL];

  message ClusterConfigBackupFilter {
    repeated uint64 cluster_ids = 1 [(google.api.field_behavior) = OPTIONAL];
    optional bool enabled = 2 [(google.api.field_behavior) = OPTIONAL];
    optional bool has_error = 3 [(google.api.field_behavior) = OPTIONAL];
    google.protobuf.Timestamp last_backup_at_from = 4 [(google.api.field_behavior) = OPTIONAL];
    google.protobuf.Timestamp last_backup_at_to = 5 [(google.api.field_behavior) = OPTIONAL];
    google.protobuf.Timestamp last_success_at_from = 6 [(google.api.field_behavior) = OPTIONAL];
    google.protobuf.Timestamp last_success_at_to = 7 [(google.api.field_behavior) = OPTIONAL];
  }
}

message ListClusterConfigBackupResponse {
  repeated ClusterConfigBackupPolicy items = 1;
  uint32 total = 2;
}

message GetPrivateLinkIPAddressTypeRequest {
  uint64 organization_id = 1 [(google.api.field_behavior) = REQUIRED];
  uint64 project_id = 2 [(google.api.field_behavior) = REQUIRED];
  uint64 cluster_id = 3 [(google.api.field_behavior) = REQUIRED];
  uint64 tidb_group_id = 4 [(google.api.field_behavior) = REQUIRED];
}

message SetPrivateLinkIPAddressTypeRequest {
  uint64 organization_id = 1 [(google.api.field_behavior) = REQUIRED];
  uint64 project_id = 2 [(google.api.field_behavior) = REQUIRED];
  uint64 cluster_id = 3 [(google.api.field_behavior) = REQUIRED];
  uint64 tidb_group_id = 4 [(google.api.field_behavior) = REQUIRED];
  PrivateLinkIPAddressType ip_address_type = 5 [(google.api.field_behavior) = REQUIRED];
}

message TidbGroupPrivateLinkIPAddressTypeStatus {
  PrivateLinkIPAddressType desired = 1;
  PrivateLinkIPAddressType observed = 2;
  bool ready = 3;
  string message = 4;
  State state = 5;

  enum State {
    STATE_UNSPECIFIED = 0;

    READY = 1;

    // The address workflow is running or being retried by Fastflow.
    CHANGING = 2;

    // The infrastructure is not strictly ready and no active address operation
    // can be proven.
    UNKNOWN = 3;
  }
}
