syntax = "proto3";

package global.serverless.v1;

import "global/common/v1/resources.proto";
import "global/common/v1/service_plan.proto";
import "global/serverless/v1/resources.proto";
import "google/api/field_behavior.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/timestamp.proto";
import "regional/serverless/v1/resources.proto";

service ServerlessService {
  rpc Create(ServerlessServiceCreateRequest) returns (ServerlessServiceCreateResponse) {}
  rpc Update(ServerlessServiceUpdateRequest) returns (ServerlessServiceUpdateResponse) {}
  rpc List(ServerlessServiceListRequest) returns (ServerlessServiceListResponse) {}
  rpc Delete(ServerlessServiceDeleteRequest) returns (ServerlessServiceDeleteResponse) {}
  rpc GetEncryptedCloudAdminPwd(ServerlessServiceGetEncryptedCloudAdminPwdRequest) returns (ServerlessServiceGetEncryptedCloudAdminPwdResponse) {}
  rpc CountClusters(ServerlessServiceCountClustersRequest) returns (ServerlessServiceCountClustersResponse) {}
  // rpc UpdateRootPassword(UpdateRootPasswordRequest) returns(ServerlessServiceUpdateRootPasswordResponse) {}
  // rpc GetProxyEndpoint() returns {}??
  // rpc GetPublicEndpoint(ServerlessServiceGetPublicEndpointRequest) returns (ServerlessServiceGetPublicEndpointResponse) {}
  // rpc GetPrivateEndpoint(ServerlessServiceGetPrivateEndpointRequest) returns (ServerlessServiceGetPrivateEndpointResponse) {}
  // rpc GetPrivateEndpointService(ServerlessServiceGetPrivateEndpointServiceRequest) returns (ServerlessServiceGetPrivateEndpointServiceResponse) {}
  rpc CheckCloudStoragePermission(CheckCloudStoragePermissionRequest) returns (CheckCloudStoragePermissionResponse) {}
  rpc UpdateAuditLogConfig(UpdateAuditLogConfigRequest) returns (UpdateAuditLogConfigResponse) {}
}

service SqlUserService {
  rpc ChangeSqlUserPasswd(ChangeSqlUserPasswdRequest) returns (ChangeSqlUserPasswdResponse) {}
  rpc RotateRootPassword(RotateRootPasswordRequest) returns (RotateRootPasswordResponse) {}
  rpc RedeemRootPassword(RedeemRootPasswordRequest) returns (RedeemRootPasswordResponse) {}
  rpc CreateSqlUser(SqlUserServiceCreateSqlUserRequest) returns (SqlUserServiceCreateSqlUserResponse) {}
  rpc UpdateSqlUser(SqlUserServiceUpdateSqlUserRequest) returns (SqlUserServiceUpdateSqlUserResponse) {}
  rpc DeleteSqlUser(SqlUserServiceDeleteSqlUserRequest) returns (SqlUserServiceDeleteSqlUserResponse) {}
  rpc GetSqlUser(SqlUserServiceGetSqlUserRequest) returns (SqlUserServiceGetSqlUserResponse) {}
  rpc IsSqlUserExisting(SqlUserServiceIsSqlUserExistingRequest) returns (SqlUserServiceIsSqlUserExistingResponse) {}
  rpc CreateSqlRole(SqlUserServiceCreateSqlRoleRequest) returns (SqlUserServiceCreateSqlRoleResponse) {}
  rpc UpdateSqlRole(SqlUserServiceUpdateSqlRoleRequest) returns (SqlUserServiceUpdateSqlRoleResponse) {}

  rpc ListSqlUsers(ListSqlUsersRequest) returns (ListSqlUsersResponse) {}
}

service CloudProviderService {
  rpc Register(CloudProviderServiceRegisterRequest) returns (common.v1.CloudProvider) {}
  rpc List(CloudProviderServiceListRequest) returns (CloudProviderServiceListResponse) {}
}

service RegionService {
  rpc Register(RegionServiceRegisterRequest) returns (common.v1.Region) {}
  rpc List(RegionServiceListRequest) returns (RegionServiceListResponse) {}
  rpc Update(RegionServiceUpdateRequest) returns (common.v1.Region) {}
  rpc Get(RegionServiceGetRequest) returns (common.v1.Region) {}
  rpc Delete(RegionServiceDeleteRequest) returns (google.protobuf.Empty) {}
}

// ServerlessPGBackupProxyService proxies PostgreSQL backup calls for
// serverless-service workers. It is Sys9-backed in serverless-global-service
// and mirrors the MySQL backup-source calling style.
service ServerlessPGBackupProxyService {
  // Create one on-demand backup.
  rpc CreatePGBackup(CreatePGBackupRequest) returns (CreatePGBackupResponse) {}

  // List backups after a cursor time with bounded count.
  rpc ListPGBackups(ListPGBackupsRequest) returns (ListPGBackupsResponse) {}

  // Get one backup by backup id.
  rpc GetPGBackup(GetPGBackupRequest) returns (GetPGBackupResponse) {}

  // Read backup policy from Sys9.
  rpc GetPGBackupPolicy(GetPGBackupPolicyRequest) returns (GetPGBackupPolicyResponse) {}

  // Update backup policy in Sys9.
  rpc UpdatePGBackupPolicy(UpdatePGBackupPolicyRequest) returns (UpdatePGBackupPolicyResponse) {}
}

service RegionalServerProxyService {
  rpc GetDataByIds(RegionalServerProxyServiceGetDataByIdsRequest) returns (RegionalServerProxyServiceGetDataByIdsResponse) {}
  rpc Delete(RegionalServerProxyServiceDeleteRequest) returns (RegionalServerProxyServiceDeleteResponse) {}
  rpc Set(RegionalServerProxyServiceSetRequest) returns (RegionalServerProxyServiceSetResponse) {}
  rpc BatchSet(RegionalServerProxyServiceBatchSetRequest) returns (RegionalServerProxyServiceBatchSetResponse) {}
  rpc DeleteAll(RegionalServerProxyServiceDeleteAllRequest) returns (RegionalServerProxyServiceDeleteAllResponse) {}
}

service ServerlessImportService {
  rpc CheckImportPermission(CheckImportPermissionRequest) returns (CheckImportPermissionResponse) {}
  rpc Precheck(PrecheckRequest) returns (PrecheckResponse) {}
}

service ServerlessDMService {
  rpc Precheck(ServerlessDMServicePrecheckRequest) returns (ServerlessDMServicePrecheckResponse) {}
  rpc CreateVpcEndpoint(CreateVpcEndpointRequest) returns (CreateVpcEndpointResponse) {}
  rpc DescribeVpcEndpoint(DescribeVpcEndpointRequest) returns (DescribeVpcEndpointResponse) {}
  rpc DeleteVpcEndpoint(DeleteVpcEndpointRequest) returns (google.protobuf.Empty) {}
  rpc ListVpcEndpointZones(ListVpcEndpointZonesRequest) returns (ListVpcEndpointZonesResponse) {}
  rpc RemoveZoneFromVpcEndpoint(RemoveZoneFromVpcEndpointRequest) returns (google.protobuf.Empty) {}
}

service ServerlessPrivateLinkConnectionService {
  rpc CreateAWSVpcEndpoint(CreateAWSVpcEndpointRequest) returns (CreateAWSVpcEndpointResponse) {}
  rpc DescribeAWSVpcEndpoint(DescribeAWSVpcEndpointRequest) returns (DescribeAWSVpcEndpointResponse) {}
  rpc DeleteAWSVpcEndpoint(DeleteAWSVpcEndpointRequest) returns (google.protobuf.Empty) {}
  rpc CreateAliCloudVpcEndpoint(CreateAliCloudVpcEndpointRequest) returns (CreateAliCloudVpcEndpointResponse) {}
  rpc DescribeAliCloudVpcEndpoint(DescribeAliCloudVpcEndpointRequest) returns (DescribeAliCloudVpcEndpointResponse) {}
  rpc DeleteAliCloudVpcEndpoint(DeleteAliCloudVpcEndpointRequest) returns (google.protobuf.Empty) {}
  rpc GetZoneIds(GetZoneIdsRequest) returns (GetZoneIdsResponse) {}
  rpc ListAliCloudVpcEndpointZones(ListAliCloudVpcEndpointZonesRequest) returns (ListAliCloudVpcEndpointZonesResponse) {}
  rpc RemoveAliCloudZoneFromVpcEndpoint(RemoveAliCloudZoneFromVpcEndpointRequest) returns (google.protobuf.Empty) {}

  rpc CreateAliCloudDNSRecord(CreateAliCloudDNSRecordRequest) returns (CreateAliCloudDNSRecordResponse) {}
  rpc DeleteAliCloudDNSRecord(DeleteAliCloudDNSRecordRequest) returns (google.protobuf.Empty) {}
  rpc CreateAWSRoute53Records(CreateAWSRoute53RecordsRequest) returns (CreateAWSRoute53RecordsResponse) {}
  rpc DeleteAWSRoute53Records(DeleteAWSRoute53RecordsRequest) returns (DeleteAWSRoute53RecordsResponse) {}
  rpc GetAWSRoute53Change(GetAWSRoute53ChangeRequest) returns (GetAWSRoute53ChangeResponse) {}
  rpc CreateAWSRoute53PrivateHostedZone(CreateAWSRoute53PrivateHostedZoneRequest) returns (CreateAWSRoute53PrivateHostedZoneResponse) {}
  rpc DeleteAWSRoute53PrivateHostedZone(DeleteAWSRoute53PrivateHostedZoneRequest) returns (DeleteAWSRoute53PrivateHostedZoneResponse) {}
  rpc CreateAliCloudDNSPrivateHostedZone(CreateAliCloudDNSPrivateHostedZoneRequest) returns (CreateAliCloudDNSPrivateHostedZoneResponse) {}
  rpc DeleteAliCloudDNSPrivateHostedZone(DeleteAliCloudDNSPrivateHostedZoneRequest) returns (DeleteAliCloudDNSPrivateHostedZoneResponse) {}
  rpc AttachVpcToAliCloudDNSPrivateHostedZone(AttachVpcToAliCloudDNSPrivateHostedZoneRequest) returns (AttachVpcToAliCloudDNSPrivateHostedZoneResponse) {}
  rpc DetachVpcFromAliCloudDNSPrivateHostedZone(DetachVpcFromAliCloudDNSPrivateHostedZoneRequest) returns (DetachVpcFromAliCloudDNSPrivateHostedZoneResponse) {}
  rpc CreateMSKVPCConnection(CreateMSKVPCConnectionRequest) returns (CreateMSKVPCConnectionResponse) {}
  rpc DeleteMSKVPCConnection(DeleteMSKVPCConnectionRequest) returns (DeleteMSKVPCConnectionResponse) {}
  rpc GetMSKVPCConnection(GetMSKVPCConnectionRequest) returns (GetMSKVPCConnectionResponse) {}
}

message ListVpcEndpointZonesRequest {
  string endpoint_id = 1;
  string cluster_id = 2;
}

message ListVpcEndpointZonesResponse {
  repeated regional.serverless.v1.VpcEndpointZone zones = 1;
}

message RemoveZoneFromVpcEndpointRequest {
  string endpoint_id = 1;
  string zone_id = 2;
  string cluster_id = 3;
}

message CreateVpcEndpointRequest {
  string cluster_id = 1;
  string service_name = 2;
}

message CreateVpcEndpointResponse {
  regional.serverless.v1.VpcEndpointDetails endpoint_details = 1;
}

message DescribeVpcEndpointRequest {
  string cluster_id = 1;
  string endpoint_id = 2;
}

message DescribeVpcEndpointResponse {
  regional.serverless.v1.VpcEndpointDetails endpoint_details = 1;
}

message DeleteVpcEndpointRequest {
  string cluster_id = 1;
  string endpoint_id = 2;
}

message ServerlessDMServicePrecheckRequest {
  regional.serverless.v1.DMPrecheck dm_precheck = 1;
  string cluster_id = 2;
}

message ServerlessDMServicePrecheckResponse {
  bytes result = 1;
}

enum BackupSourceState {
  BACKUP_SOURCE_STATE_UNSPECIFIED = 0;
  BACKUP_SOURCE_STATE_PENDING = 1;
  BACKUP_SOURCE_STATE_RUNNING = 2;
  BACKUP_SOURCE_STATE_SUCCEEDED = 3;
  BACKUP_SOURCE_STATE_FAILED = 4;
  BACKUP_SOURCE_STATE_DELETING = 5;
  BACKUP_SOURCE_STATE_DELETED = 6;
}

message PGPhysicalBackup {
  uint64 backup_id = 1;
  string backup_name = 2;
  google.protobuf.Timestamp backup_time = 3;
  // Opaque source metadata for debugging and replay.
  map<string, string> labels = 4;
}

message CreatePGBackupRequest {
  string cluster_id = 1;
}

message CreatePGBackupResponse {
  uint64 backup_id = 1;
}

message ListPGBackupsRequest {
  string cluster_id = 1;
  // Same semantics as MySQL mode backup-source request: return backups whose
  // backup_time is greater than last_backup_time.
  google.protobuf.Timestamp last_backup_time = 2;
  // Same semantics as MySQL mode backup-source request: max items per call.
  uint32 max_count = 3;
}

message ListPGBackupsResponse {
  repeated PGPhysicalBackup items = 1;
  bool has_more = 2;
}

message GetPGBackupRequest {
  string cluster_id = 1;
  uint64 backup_id = 2;
}

message GetPGBackupResponse {
  PGPhysicalBackup backup = 1;
}

message GetPGBackupPolicyRequest {
  string cluster_id = 1;
}

message GetPGBackupPolicyResponse {
  AutomatedBackupPolicy backup_policy = 1;
}

message UpdatePGBackupPolicyRequest {
  string cluster_id = 1;
  AutomatedBackupPolicy backup_policy = 2;
}

message UpdatePGBackupPolicyResponse {
  AutomatedBackupPolicy backup_policy = 1;
}

message PrecheckRequest {
  regional.serverless.v1.CloudStorage cloud_storage = 1;
  regional.serverless.v1.DatabaseCredential db_credential = 2;
  repeated regional.serverless.v1.FileRouteRule file_route_rules = 3;
  bool use_custom_file_mapping = 4;
  string cluster_id = 7;
}

message PrecheckResponse {
  repeated regional.serverless.v1.TableResult table_results = 1;
  regional.serverless.v1.ImportPrecheckStatus status = 2;
}

message CheckImportPermissionRequest {
  regional.serverless.v1.CloudStorage cloud_storage = 1;
  string cluster_id = 4;
}

message CheckImportPermissionResponse {}

message CheckCloudStoragePermissionRequest {
  regional.serverless.v1.CloudStorage cloud_storage = 1;
  string cluster_id = 2;
  FeatureName feature_name = 3;

  enum FeatureName {
    FEATURE_NAME_UNSPECIFIED = 0;
    FEATURE_NAME_AUDITLOG = 1;
    FEATURE_NAME_EXPORT = 2;
    FEATURE_NAME_CHANGEFEED = 3;
  }
}

message UpdateAuditLogConfigRequest {
  regional.serverless.v1.ServerlessRegionalServiceClusterInfo.AuditLogConfig audit_log_config = 1;
  string cluster_id = 2;
}

message UpdateAuditLogConfigResponse {}

message CheckCloudStoragePermissionResponse {}

// cluster
message ServerlessServiceCreateRequest {
  uint64 tenant_id = 1;
  string id = 2;
  uint64 project_id = 3;

  string cloud_provider = 4;
  string region = 5;

  optional SpendLimit spend_limit = 7;

  optional AutomatedBackupPolicy backup_policy = 8;
  optional regional.serverless.v1.Endpoints endpoints = 9;
  optional EncryptionConfig encryption_config = 10;
  optional string root_password = 11;
  optional bool restore_cluster = 12;
  bool zone_redundant_enabled = 13;
  regional.serverless.v1.ServerlessRegionalServiceClusterInfo.AuditLogConfig audit_log_config = 14;
  string kubernetes = 15;
  regional.serverless.v1.ServerlessRegionalServiceClusterInfo.AutoScaling auto_scaling = 16;
  uint64 original_project_id = 17;
  repeated string init_sqls = 18;
  int32 ru_version = 19;
  string engine_type = 20;

  bool validate_only = 30;
}

message ClusterFilter {
  repeated common.v1.CloudProvider.Name cloud_provider_names = 1;
  // TODO TBD: maybe we should use UserClusterStatus?
  repeated regional.serverless.v1.ClusterState states = 3;
  //  repeated internal_usage.serverless.regional.v1.ClusterState exclude_states = 4;
  repeated uint64 tenant_ids = 5;
  repeated uint64 project_ids = 6;
  repeated string cluster_ids = 7;
  optional bool deleted = 8;
  bool show_details = 9;
  bool refresh_cache = 10;
  repeated uint64 original_project_ids = 11;
  repeated string engine_types = 12;
}

message ServerlessServiceListRequest {
  ClusterFilter filter = 1;
  //optional Pager pager = 2;
  //repeated Sorter sorters = 4;
}

message ServerlessServiceListResponse {
  uint32 total = 1;
  repeated ServerlessServiceCluster items = 2;
}

message ServerlessServiceCountClustersRequest {
  ClusterFilter filter = 1;
}

message ServerlessServiceCountClustersResponse {
  int64 count = 1;
}

message ServerlessServiceCreateResponse {
  ServerlessServiceCluster cluster = 1;
}

message ServerlessServiceDeleteRequest {
  string cluster_id = 1;
  uint64 tenant_id = 2;
  uint64 project_id = 3;
  uint64 original_project_id = 4;

  bool validate_only = 30;
}

message ServerlessServiceDeleteResponse {
  ServerlessServiceCluster cluster = 1;
}

message UpdateRootPasswordRequest {
  string cluster_id = 1;
  string passwd = 2;
}

message ServerlessServiceUpdateRootPasswordResponse {}

message ServerlessServiceGetPublicEndpointRequest {
  string cluster_id = 1;
}

message ServerlessServiceGetPrivateEndpointRequest {
  string cluster_id = 1;
}

message ServerlessServiceGetPublicEndpointResponse {
  string address = 1;
  int32 port = 2;
  string token = 3;
}

message ServerlessServiceGetPrivateEndpointResponse {
  string address = 1;
  int32 port = 2;
  string token = 3;
}

message ServerlessServiceGetPrivateEndpointServiceRequest {
  string cluster_id = 1;
}

message ServerlessServiceGetPrivateEndpointServiceResponse {
  string cloud_provider = 1;
  string status = 2;
  optional AWSPrivateEndpointService aws = 21; // create required for aws
  optional GCPPrivateEndpointService gcp = 22; // create required for gcp
}

message ServerlessServiceGetEncryptedCloudAdminPwdRequest {
  string cluster_id = 1;
}

message ServerlessServiceGetEncryptedCloudAdminPwdResponse {
  string encrypted_passwd = 1;
}

// sql user service
message SqlUserServiceCreateSqlUserRequest {
  message Settings {
    bool ignore_exists = 1; // check the user whether exists and ignore if already exists before trying to create
  }
  SqlUserOperator operator = 1;
  string cluster_id = 2;

  SqlUser.Type user_type = 3;
  string username = 4;
  optional string email = 5; // required when creating delegate user
  SqlUser.AuthMethod auth_method = 6;
  // required if auth_method is PASSWORD.
  // * use encrypted and base64-encoded password if the auth_method is PASSWORD, refer to:
  //   https://github.com/tidbcloud/pkgv2/blob/main/secret/encrypt/encryptor.go#L24
  optional string credential = 7;
  SqlUser.BuiltinRole builtin_role = 8; // optional
  repeated string custom_roles = 9; // optional
  optional Settings settings = 10;
}

message SqlUserServiceCreateSqlUserResponse {}

message SqlUserServiceUpdateSqlUserRequest {
  SqlUserOperator operator = 1;
  string cluster_id = 2;

  string username = 3;
  optional SqlUser.BuiltinRole builtin_role = 4;
  repeated string custom_roles = 5; // optional
  optional string password = 12; // optional
  bool clear_custom_roles = 18; // optional
}

message SqlUserServiceUpdateSqlUserResponse {}

message ListSqlUsersRequest {
  SqlUserOperator operator = 1;
  string cluster_id = 2;
  ListSqlUsersFilter filter = 3;
}

message ListSqlUsersResponse {
  // key：the filed in mysql.user,such as  [USER, PLUGIN,ACCOUNT_LOCKED]
  map<string, SqlValues> result_map = 1;
  repeated SqlUser db_users = 2;
  // If the base_resp.Code == 150100033, we MAY provide the 'proxy_error' to explain what error happen when trying to execute this request.
  optional ClusterProxyError proxy_error = 100;
}

/* some  example for ListDBUsersFilter
    userFilter = core.ListDBUsersFilter{
       PasswordExpired: []string{"N"},
       AccountLocked:   []string{"N"},
       Plugin:          []string{"mysql_native_password"}}
   roleFilter = core.ListDBUsersFilter{
       PasswordExpired: []string{"Y"},
       AccountLocked:   []string{"Y"}}
*/

message ListSqlUsersFilter {
  repeated string plugin = 1;
  repeated string password_expired = 2;
  repeated string account_locked = 3;
  repeated string ignore_users = 4;
  repeated string users = 5;
}

message SqlValues {
  repeated string values = 1;
}

message SqlUserServiceDeleteSqlUserRequest {
  SqlUserOperator operator = 1;
  string cluster_id = 2;

  string username = 3;
}

message SqlUserServiceDeleteSqlUserResponse {}

message SqlUserServiceCreateSqlRoleRequest {
  SqlUserOperator operator = 1;
  string cluster_id = 2;

  string role_name = 3; // exclude `host` info. for example: please give `data_reader` if you want to create a role like `data_reader@'%'`.
  string grants = 4; // all grants should be granted to the current role `role_name`
  // all revocation should be revoked from the current role `role_name`
  // revocation will be executed after finished grant
  string revocation = 5;
}

message SqlUserServiceCreateSqlRoleResponse {}

message SqlUserServiceUpdateSqlRoleRequest {
  SqlUserOperator operator = 1;
  string cluster_id = 2;

  string role_name = 3;
  optional string grants = 4; // all grants should be granted to the current role `role_name`
  // all revocation should be revoked from the current role `role_name`
  // revocation will be executed after finished grant
  optional string revocation = 5;
}

message SqlUserServiceUpdateSqlRoleResponse {}

message SqlUserServiceGetSqlUserRequest {
  SqlUserOperator operator = 1;
  string cluster_id = 2;

  string username = 3;
}

message SqlUserServiceGetSqlUserResponse {
  SqlUser user = 1;
}

message SqlUserServiceIsSqlUserExistingRequest {
  SqlUserOperator operator = 1;
  string cluster_id = 2;

  string username = 3; // name of user or role
}

message SqlUserServiceIsSqlUserExistingResponse {
  bool existing = 1;
}

message ServerlessServiceUpdateRequest {
  ServerlessServiceCluster cluster = 1;
  bool validate_only = 30;
}

message ServerlessServiceUpdateResponse {
  ServerlessServiceCluster cluster = 1;
}

message ChangeSqlUserPasswdRequest {
  string cluster_id = 1;
  string user_name = 2;
  string passwd = 3;
}

message ChangeSqlUserPasswdResponse {}

message RotateRootPasswordRequest {
  string cluster_id = 1;
  string operation_token = 2;
}

message RotateRootPasswordResponse {
  bool rotating = 1;
}

message RedeemRootPasswordRequest {
  string cluster_id = 1;
}

message RedeemRootPasswordResponse {
  bool rotating = 1;
  string password = 2;
}

// cloud provider
message CloudProviderServiceListRequest {
  uint64 organization_id = 1 [(google.api.field_behavior) = OPTIONAL];
  common.v1.CloudProvider.Name cloud_provider_id = 2 [(google.api.field_behavior) = OPTIONAL];
  common.v1.ServicePlan service_plan = 3 [(google.api.field_behavior) = OPTIONAL];
}

message CloudProviderServiceListResponse {
  repeated common.v1.CloudProvider cloud_providers = 1;
  uint32 total = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
}

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

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

message RegionServiceListRequest {
  repeated common.v1.CloudProvider.Name cloud_provider_ids = 1 [(google.api.field_behavior) = OPTIONAL];
  uint64 organization_id = 2 [(google.api.field_behavior) = OPTIONAL];
  common.v1.ServicePlan service_plan = 3 [(google.api.field_behavior) = OPTIONAL];
  string engine_type = 4 [(google.api.field_behavior) = OPTIONAL];
}

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

  uint32 total = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
}

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

message RegionServiceGetRequest {
  common.v1.CloudProvider.Name cloud_provider_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];
  string engine_type = 4 [(google.api.field_behavior) = OPTIONAL];
}

message RegionServiceDeleteRequest {
  common.v1.CloudProvider.Name cloud_provider_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];
  string engine_type = 4 [(google.api.field_behavior) = OPTIONAL];
}

message RegionalServerProxyServiceGetDataByIdsRequest {
  repeated string ids = 1;
}

message RegionalServerProxyServiceGetDataByIdsResponse {
  bool exist = 1;
  repeated regional.serverless.v1.ServerlessRegionalServiceClusterInfo clusters = 2;
}

message RegionalServerProxyServiceDeleteRequest {
  string id = 1;
}

message RegionalServerProxyServiceDeleteResponse {
  bool ok = 1;
}

message RegionalServerProxyServiceSetRequest {
  string id = 1;
  regional.serverless.v1.ServerlessRegionalServiceClusterInfo cluster = 2;
}

message RegionalServerProxyServiceBatchSetRequest {
  repeated regional.serverless.v1.ServerlessRegionalServiceClusterInfo clusters = 1;
}

message RegionalServerProxyServiceSetResponse {
  bool ok = 1;
}

message RegionalServerProxyServiceBatchSetResponse {
  bool ok = 1;
}

message RegionalServerProxyServiceDeleteAllRequest {}

message RegionalServerProxyServiceDeleteAllResponse {
  bool ok = 1;
}

message CreateAWSVpcEndpointRequest {
  string cluster_id = 1;
  string endpoint_service_name = 2;
  // optional, use it when you want to connect to cross-region endpoint service
  string endpoint_service_region = 3;
}

message CreateAWSVpcEndpointResponse {
  regional.serverless.v1.AWSVpcEndpoint endpoint = 1;
}

message DescribeAWSVpcEndpointRequest {
  string endpoint_id = 1;
  string cluster_id = 2;
}

message DescribeAWSVpcEndpointResponse {
  regional.serverless.v1.AWSVpcEndpoint endpoint = 1;
}

message DeleteAWSVpcEndpointRequest {
  string endpoint_id = 1;
  string cluster_id = 2;
}

message CreateAliCloudVpcEndpointRequest {
  string endpoint_service_name = 1;
  string cluster_id = 2;
}

message CreateAliCloudVpcEndpointResponse {
  regional.serverless.v1.AliCloudVpcEndpoint endpoint = 1;
}

message DescribeAliCloudVpcEndpointRequest {
  string endpoint_id = 1;
  string cluster_id = 2;
}

message DescribeAliCloudVpcEndpointResponse {
  regional.serverless.v1.AliCloudVpcEndpoint endpoint = 1;
}

message DeleteAliCloudVpcEndpointRequest {
  string endpoint_id = 1;
  string cluster_id = 2;
}

message GetZoneIdsRequest {
  string cluster_id = 1;
  // Kubernetes identifier for direct regional routing. Requires region when
  // cluster_id is omitted; cluster_id remains supported for compatibility.
  string kubernetes = 2;
  // AWS region enum string, for example "AWS_US_WEST_2". Bare AWS region names
  // like "us-west-2" are accepted for compatibility.
  string region = 3;
  common.v1.CloudProvider.Name cloud_provider_id = 4;
  uint64 organization_id = 5;
  common.v1.ServicePlan service_plan = 6;
}

message GetZoneIdsResponse {
  repeated string zone_ids = 1;
  // The AWS account that creates the VPC connection from the endpoint VPC.
  // Customers should allowlist this account in the target MSK cluster policy.
  // It is populated for AWS; callers should keep their existing fallback for other providers.
  string account_id = 2;
}

message ListAliCloudVpcEndpointZonesRequest {
  string endpoint_id = 1;
  string cluster_id = 2;
}

message ListAliCloudVpcEndpointZonesResponse {
  repeated regional.serverless.v1.AliCloudVpcEndpointZone zones = 1;
}

message RemoveAliCloudZoneFromVpcEndpointRequest {
  string endpoint_id = 1;
  string zone_id = 2;
  string cluster_id = 3;
}

message CreateAliCloudDNSRecordRequest {
  string cluster_id = 1;
  string record = 2;
  string value = 3;
  // only used by tidb cloud managed hosted zone
  string hosted_zone_name = 4;
  string hosted_zone_id = 5;
}

message CreateAliCloudDNSRecordResponse {
  int64 record_id = 1;
}

message DeleteAliCloudDNSRecordRequest {
  string cluster_id = 1;
  int64 record_id = 2;
}

message CreateAWSRoute53RecordsRequest {
  string cluster_id = 1;
  map<string, string> records = 2;
  // only used by tidb cloud managed hosted zone
  string hosted_zone_name = 3;
  string hosted_zone_id = 4;
}

message CreateAWSRoute53RecordsResponse {
  string change_id = 1;
}

message DeleteAWSRoute53RecordsRequest {
  string cluster_id = 1;
  map<string, string> records = 2;
  // only used by tidb cloud managed hosted zone
  string hosted_zone_name = 3;
  string hosted_zone_id = 4;
}

message DeleteAWSRoute53RecordsResponse {
  string change_id = 1;
}

message GetAWSRoute53ChangeRequest {
  string cluster_id = 1;
  string change_id = 2;
}

message GetAWSRoute53ChangeResponse {
  string change_id = 1;
  regional.serverless.v1.Route53ChangeState.Enum state = 2;
}

message CreateAWSRoute53PrivateHostedZoneRequest {
  string cluster_id = 1;
  string hosted_zone_name = 2;
}

message CreateAWSRoute53PrivateHostedZoneResponse {
  string hosted_zone_id = 1;
}

message DeleteAWSRoute53PrivateHostedZoneRequest {
  string cluster_id = 1;
  string hosted_zone_id = 2;
}

message DeleteAWSRoute53PrivateHostedZoneResponse {}

message CreateAliCloudDNSPrivateHostedZoneRequest {
  string cluster_id = 1;
  string hosted_zone_name = 2;
}

message CreateAliCloudDNSPrivateHostedZoneResponse {
  string hosted_zone_id = 1;
}

message DeleteAliCloudDNSPrivateHostedZoneRequest {
  string cluster_id = 1;
  string hosted_zone_id = 2;
}

message DeleteAliCloudDNSPrivateHostedZoneResponse {}

message AttachVpcToAliCloudDNSPrivateHostedZoneRequest {
  string cluster_id = 1;
  string hosted_zone_id = 2;
}

message AttachVpcToAliCloudDNSPrivateHostedZoneResponse {}

message DetachVpcFromAliCloudDNSPrivateHostedZoneRequest {
  string cluster_id = 1;
  string hosted_zone_id = 2;
}

message DetachVpcFromAliCloudDNSPrivateHostedZoneResponse {}

message CreateMSKVPCConnectionRequest {
  string msk_arn = 1;
  // Deprecated for MSK routing. Prefer region+kubernetes so the global layer can
  // route to the regional service without depending on an owner cluster.
  string cluster_id = 2;
  string kubernetes = 3;
  // AWS region enum string, for example "AWS_US_WEST_2". Bare AWS region names
  // like "us-west-2" are accepted for compatibility. Required with kubernetes
  // when cluster_id is omitted.
  string region = 4;
  common.v1.CloudProvider.Name cloud_provider_id = 5;
  uint64 organization_id = 6;
  common.v1.ServicePlan service_plan = 7;
}

message CreateMSKVPCConnectionResponse {
  regional.serverless.v1.MSKVpcConnection msk_vpc_connection = 1;
}

message DeleteMSKVPCConnectionRequest {
  string msk_vpc_connection_arn = 1;
  // Deprecated for MSK routing. Prefer region+kubernetes so the global layer can
  // route to the regional service without depending on an owner cluster.
  string cluster_id = 2;
  string kubernetes = 3;
  // AWS region enum string, for example "AWS_US_WEST_2". Bare AWS region names
  // like "us-west-2" are accepted for compatibility. Required with kubernetes
  // when cluster_id is omitted.
  string region = 4;
  common.v1.CloudProvider.Name cloud_provider_id = 5;
  uint64 organization_id = 6;
  common.v1.ServicePlan service_plan = 7;
}

message DeleteMSKVPCConnectionResponse {}

message GetMSKVPCConnectionRequest {
  string msk_vpc_connection_arn = 1;
  // Deprecated for MSK routing. Prefer region+kubernetes so the global layer can
  // route to the regional service without depending on an owner cluster.
  string cluster_id = 2;
  string kubernetes = 3;
  // AWS region enum string, for example "AWS_US_WEST_2". Bare AWS region names
  // like "us-west-2" are accepted for compatibility. Required with kubernetes
  // when cluster_id is omitted.
  string region = 4;
  common.v1.CloudProvider.Name cloud_provider_id = 5;
  uint64 organization_id = 6;
  common.v1.ServicePlan service_plan = 7;
}

message GetMSKVPCConnectionResponse {
  regional.serverless.v1.MSKVpcConnection msk_vpc_connection = 1;
}
