syntax = "proto3";

package tidb_cloud_open_api.dedicated.v1beta1;

import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/api/visibility.proto";
import "google/protobuf/timestamp.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "tidb_cloud_open_api/common/v1beta1/clusterstate.proto";
import "tidb_cloud_open_api/common/v1beta1/region.proto";
import "tidb_cloud_open_api/common/v1beta1/tag.proto";

option go_package = "tidb_cloud_open_api/dedicated/v1beta1";

// Cluster represents a dedicated TiDB cluster.
message Cluster {
  option (google.api.resource) = {
    type: "tidb_cloud_open_api.dedicated.v1beta1/Cluster"
    pattern: "clusters/{cluster}"
  };

  string name = 1 [
    (google.api.field_behavior) = IDENTIFIER,
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      example: "\"clusters/1\""
      description: "The unique identifier for the TiDB cluster, which is generated by the API and follows the format `clusters/{clusterId}`."
    }
  ];

  string cluster_id = 2 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The ID of the cluster."
      example: "\"1\""
    }
  ];

  string display_name = 3 [
    (google.api.field_behavior) = REQUIRED,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      pattern: "^[A-Za-z0-9][-A-Za-z0-9]{2,62}[A-Za-z0-9]$"
      example: "\"foo-bar\""
      min_length: 4
      max_length: 64
      description: "The user-defined name of the cluster."
    }
  ];

  string region_id = 4 [
    (google.api.field_behavior) = REQUIRED,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      example: "\"aws-us-west-2\""
      description: "The region where the cluster is deployed, in the format of `{cloud_provider}-{region_code}`. For example, `aws-us-west-2`."
    }
  ];

  map<string, string> labels = 5 [
    (google.api.field_behavior) = OPTIONAL,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      example: "{\"tidb.cloud/project\": \"1\"}"
      description: "Key-value pairs used to label the cluster. If the `tidb.cloud/project` label is not specified, the cluster is associated with the default project in the creator's organization. \n\n**Note**: Currently, only the `tidb.cloud/project` label key can be specified when creating a new cluster."
      title: "map<string, string>"
    }
  ];

  TidbNodeSetting tidb_node_setting = 6 [
    (google.api.field_behavior) = REQUIRED,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The configuration for [TiDB nodes](https://docs.pingcap.com/tidbcloud/tidb-cloud-glossary/#tidb-node) in a TiDB Cloud Dedicated cluster.\n\nTo view available node specs for a specific region and cloud provider, use the [List node specs](#tag/RegionService/operation/RegionService_ListNodeSpecs) endpoint."
      title: "TidbNodeSetting"
    }
  ];

  StorageNodeSetting tikv_node_setting = 7 [
    (google.api.field_behavior) = REQUIRED,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The configuration for [TiKV nodes](https://docs.pingcap.com/tidbcloud/tidb-cloud-glossary/#tikv-node) in a TiDB Cloud Dedicated cluster.\n\nTo view available node specs for a specific region and cloud provider, use the [List node specs](#tag/RegionService/operation/RegionService_ListNodeSpecs) endpoint."
      title: "StorageNodeSetting"
    }
  ];

  StorageNodeSetting tiflash_node_setting = 8 [
    (google.api.field_behavior) = OPTIONAL,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The configuration for [TiFlash nodes](https://docs.pingcap.com/tidbcloud/tidb-cloud-glossary/#tiflash-node) in a TiDB Cloud Dedicated cluster. If not set, TiFlash is disabled.\n\nTo view available node specs for a specific region and cloud provider, use the [List node specs](#tag/RegionService/operation/RegionService_ListNodeSpecs) endpoint."
      title: "StorageNodeSetting"
      example: "{\"nodeCount\":3,\"nodeSpecKey\":\"16C128G\",\"storageSizeGi\":500,\"storageType\":\"Basic\"}"
    }
  ];

  int32 port = 10 [
    (google.api.field_behavior) = REQUIRED,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      example: "4000"
      default: "4000"
      minimum: 1024
      maximum: 65535
      description: "The port for cluster connections. All network endpoints in the cluster use this port."
    }
  ];

  string root_password = 11 [
    (google.api.field_behavior) = OPTIONAL,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      pattern: "^.{8,64}$"
      example: "\"my-shining-password\""
      min_length: 8
      max_length: 64
      description: "The root password of the cluster. It must be between 8 and 64 characters long and can contain letters, numbers, and special characters."
    }
  ];

  tidb_cloud_open_api.common.v1beta1.ClusterState state = 20 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      example: "\"ACTIVE\""
      description: "The current state of the cluster."
    }
  ];

  string version = 21 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      example: "\"8.5.2\""
      description: "The TiDB version of the cluster."
    }
  ];

  string created_by = 22 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      example: "\"test@example.com\""
      description: "The email address or public API key of the user who create the cluster."
    }
  ];

  google.protobuf.Timestamp create_time = 23 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The timestamp when the cluster was created, in the [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format."
      example: "\"2023-10-01T12:00:00Z\""
    }
  ];

  google.protobuf.Timestamp update_time = 24 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The timestamp when the cluster was last updated, in the [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format."
      example: "\"2023-10-01T12:00:00Z\""
    }
  ];

  PausePlan pause_plan = 25 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The pause plan configuration of the cluster."
      title: "PausePlan"
    }
  ];

  string region_display_name = 26 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The display name of the region where the cluster is located. For example, `N. Virginia (us-east-1)`."
      example: "\"N. Virginia (us-east-1)\""
    }
  ];

  common.v1beta1.Region.CloudProvider cloud_provider = 27 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The cloud provider where the cluster is located.\n\n- `\"aws\"`: Amazon Web Services\n\n- `\"gcp\"`: Google Cloud\n\n- `\"azure\"`: Microsoft Azure\n\n- `\"alicloud\"`: Alibaba Cloud"
      title: "CloudProvider"
      example: "\"aws\""
    }
  ];

  // OUTPUT_ONLY. The annotations for the cluster.
  // tidb.cloud/has-set-password. The annotation for whether the cluster has set password.
  // tidb.cloud/available-features. The annotation for the available features of the cluster.
  // tidb.cloud/insufficient-vm-resource. The annotation for insufficient virtual machine resources during creating or modifying the cluster.
  map<string, string> annotations = 28 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The annotations for the cluster. The following lists some predefined annotations:\n- `tidb.cloud/has-set-password`: indicates whether the cluster has a root password set.\n- `tidb.cloud/available-features`: lists available features of the cluster.\n- `tidb.cloud/insufficient-vm-resource`: indicates insufficient virtual machine resources during during cluster creation or modification."
      title: "map<string, string>"
      example: "{\"tidb.cloud/has-set-password\":\"false\"}"
    }
  ];

  repeated tidb_cloud_open_api.common.v1beta1.Tag tags = 29 [(google.api.field_behavior) = OPTIONAL];

  message TidbNodeSetting {
    // The homogeneous node spec key for all TiDB nodes in the cluster. If specified, all TiDB nodes in the cluster will use the same node spec.
    string node_spec_key = 1 [
      (google.api.field_behavior) = OPTIONAL,
      (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
        example: "\"8C32G\""
        description: "The node spec key of the TiDB nodes in the cluster. For example, `8C32G`. \n\nTo get the node spec available configurations of a specific region for a cloud provider, please refer to [List node specs](#tag/RegionService/operation/RegionService_ListNodeSpecs) API."
      }
    ];

    // The display name of the homogeneous node spec.
    string node_spec_display_name = 3 [
      (google.api.field_behavior) = OUTPUT_ONLY,
      (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
        example: "\"8 vCPU, 32 GiB\""
        description: "The display name of the node spec. For example, `8 vCPU, 32 GiB`."
      }
    ];

    // The version of homogeneous node spec.
    string node_spec_version = 4 [
      (google.api.field_behavior) = OUTPUT_ONLY,
      (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
        description: "The version tag of the node spec resource. The performance and price of the component may vary based on the version tag."
        example: "\"v1\""
      }
    ];

    repeated TidbNodeGroup tidb_node_groups = 2 [
      (google.api.field_behavior) = REQUIRED,
      (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
        description: "The [TiDB node groups](https://docs.pingcap.com/tidbcloud/tidb-node-group-overview/) in the cluster.\n\nWhen you create a cluster, this array must contain exactly one `TidbNodeGroup` object, and the `nodeCount` field must be set."
        title: "TidbNodeGroup"
      }
    ];
  }

  message StorageNodeSetting {
    int32 node_count = 1 [
      (google.api.field_behavior) = REQUIRED,
      (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
        example: "3"
        description: "The number of nodes in the cluster."
      }
    ];

    string node_spec_key = 2 [
      (google.api.field_behavior) = REQUIRED,
      (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
        example: "\"8C32G\""
        description: "The node spec key of the nodes in the cluster. For example, `8C32G`."
      }
    ];

    string node_spec_version = 6 [
      (google.api.field_behavior) = OUTPUT_ONLY,
      (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
        description: "The version tag of the node spec resource. The performance and price of the component may vary based on the version tag."
        example: "\"v1\""
      }
    ];

    // The storage size of the node in GiB.
    int32 storage_size_gi = 3 [
      (google.api.field_behavior) = REQUIRED,
      (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
        example: "500"
        description: "The storage size of each node in gibibytes (GiB). To view supported storage size ranges, use the [List node specs](#tag/RegionService/operation/RegionService_ListNodeSpecs) or [Get a node spec](#tag/RegionService/operation/RegionService_GetNodeSpec) endpoint."
      }
    ];

    StorageType storage_type = 4 [
      (google.api.field_behavior) = OPTIONAL,
      (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
        description: "The storage type of the node. For more information, see [TiKV node storage types](https://docs.pingcap.com/tidbcloud/size-your-cluster/#tikv-node-storage-types) and [TiFlash node storage types](https://docs.pingcap.com/tidbcloud/size-your-cluster/#tiflash-node-storage-types)."
        example: "\"Standard\""
      }
    ];

    optional int32 data_store_iops = 13 [
      (google.api.field_behavior) = OPTIONAL,
      (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
        example: "3000"
        description: "The IOPS (input/output operations per second) of the data store for the node. Only supported for AWS clusters with `Plus` TiKV storage type. If not specified, the default IOPS of the data store is used."
      }
    ];

    optional int32 raft_store_iops = 5 [
      (google.api.field_behavior) = OPTIONAL,
      (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
        example: "3000"
        description: "The IOPS (input/output operations per second) of the Raft store for the node. If not specified, the default IOPS of Raft store is used. It is recommended to leave it blank to use the default settings for optimal performance."
      }
    ];

    string node_spec_display_name = 11 [
      (google.api.field_behavior) = OUTPUT_ONLY,
      (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
        description: "The display name of the node spec. For example, `8 vCPU, 32 GiB`."
        example: "\"8 vCPU, 32 GiB\""
      }
    ];

    NodeChangingProgress node_changing_progress = 12 [
      (google.api.field_behavior) = OUTPUT_ONLY,
      (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
        description: "The progress of the node changing."
        title: "NodeChangingProgress"
      }
    ];

    enum StorageType {
      STORAGE_TYPE_UNSPECIFIED = 0;

      // Data disk: gp3; Raft log disk: none.
      Basic = 1;

      // Data disk: gp3; Raft log disk: gp3.
      Standard = 2;

      // Data disk: gp3; Raft log disk: io2.
      Performance = 3;

      // Data disk: io2; Raft log disk: none.
      Plus = 4;
    }
  }

  message NodeChangingProgress {
    // The number of nodes that match the specified node spec.
    int32 matching_node_spec_node_count = 1 [(google.api.field_behavior) = OUTPUT_ONLY];

    // The number of nodes pending deletion. This value appears only during node deletion operations.
    int32 remaining_deletion_node_count = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
  }

  message PausePlan {
    enum Type {
      TYPE_UNSPECIFIED = 0;

      // default pause plan
      NORMAL = 1;

      // not supported yet
      // LONG = 2; not export yet

      // old pause plan, will be removed
      DEPRECATE = 3;
    }

    Type pause_type = 1 [
      (google.api.field_behavior) = REQUIRED,
      (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
        description: "The type of the pause plan.\n\n- `\"NORMAL\"`: the default pause plan.\n- `\"DEPRECATE\"`: the legacy pause plan and will be removed in a future release."
        title: "PausePlanType"
      }
    ];

    // The scheduled time for the cluster to automatically resume from the `PAUSED` state, in the [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format.
    google.protobuf.Timestamp scheduled_resume_time = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
  }
}

// All fields are output only.
message NodeSpec {
  option (google.api.resource) = {
    type: "tidb_cloud_open_api.dedicated.v1beta1/NodeSpec"
    pattern: "regions/{region}/componentTypes/{component_type}/nodeSpecs/{node_spec_key}"
  };

  // The name of the node spec resource, in the format of `regions/{region_id}/componentTypes/{component_type}/nodeSpecs/{node_spec_key}`. For example, `regions/aws-us-west-2/componentTypes/TIKV/nodeSpecs/8C32G`.
  string name = 1 [(google.api.field_behavior) = IDENTIFIER];

  // The region ID of the node spec resource, in the format of `{cloud_provider}-{region_code}`. For example, `aws-us-west-2`.
  string region_id = 2;

  // The component type of the node spec.
  ComponentType component_type = 3;

  // The key of the node spec. For example, `8C32G`.
  string node_spec_key = 4;

  // The display name of the node spec. For example, `8 vCPU, 32 GiB`.
  string display_name = 5;

  // The number of virtual CPUs (vCPUs) allocated to the node spec. For example, `8`.
  int32 v_cpu = 6;

  // The amount of memory in gibibytes (GiB) allocated to the node spec. For example, `32`.
  int32 memory_size_gi = 7;

  // The default storage size of the node spec resource in GiB.
  int32 default_storage_size_gi = 8;

  // The maximum storage size of the node spec resource in GiB.
  int32 max_storage_size_gi = 9;

  // The minimum storage size of the node spec resource in GiB.
  int32 min_storage_size_gi = 10;

  // The default number of nodes for the node spec resource.
  int32 default_node_count = 11;

  // The storage types supported by the node spec resource.
  repeated Cluster.StorageNodeSetting.StorageType storage_types = 12;

  // The maximum IOPS for Raft log storage of the node spec resource. Currently, this parameter is only useful when overriding IOPS for Raft log storage.
  optional int32 max_raft_store_iops = 13;

  // The minimum IOPS for Raft log storage of the node spec resource. Currently, this parameter is only useful when overriding IOPS for Raft log storage.
  optional int32 min_raft_store_iops = 14;

  // The default IOPS for Raft log storage of the node spec resource. If not set, the default IOPS of Raft log storage will be used.
  optional int32 default_raft_store_iops = 15 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    description: "The default IOPS for Raft log storage of the node spec resource. Currently, this parameter is only useful when overriding IOPS for Raft log storage."
    example: "3000"
  }];

  string version = 16 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    description: "The version tag of the node spec resource. The performance and price of the component may vary based on the version tag."
    example: "\"v1\""
  }];

  // Indicates whether this is the default node spec.
  bool default = 20;

  // Detailed storage capabilities grouped by storage type enum string values. Currently, only Plus storage type is supported.
  map<string, StorageTypeDetail> storage_type_details = 21 [(google.api.field_behavior) = OUTPUT_ONLY];

  message Storage {
    // The default IOPS of the storage for the node spec resource.
    optional int32 default_iops = 1 [(google.api.field_behavior) = OUTPUT_ONLY];

    // The minimum IOPS of the storage for the node spec resource.
    optional int32 min_iops = 2 [(google.api.field_behavior) = OUTPUT_ONLY];

    // The maximum IOPS of the storage for the node spec resource.
    optional int32 max_iops = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
  }

  message StorageTypeDetail {
    Storage data_storage = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
    Storage raftlog_storage = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
  }
}

message TidbNodeGroup {
  option (google.api.resource) = {
    type: "tidb_cloud_open_api.dedicated.v1beta1/TidbNodeGroup"
    pattern: "tidbNodeGroups/{tidbNodeGroup}"
  };

  string name = 1 [
    (google.api.field_behavior) = IDENTIFIER,
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      example: "\"tidbNodeGroups/1\""
      description: "The resource name of the TiDB group, in the format of `tidbNodeGroups/{tidb_node_group_id}`."
    }
  ];

  string tidb_node_group_id = 2 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The unique ID of the TiDB group."
      example: "\"1\""
    }
  ];

  string cluster_id = 3 [
    (google.api.field_behavior) = OPTIONAL,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      example: "\"1\""
      description: "The ID of the cluster that the TiDB node group belongs to.\n\n- This field is **optional** when creating a cluster with the default TiDB group.\n\n- This field is **required** when creating a non-default TiDB group."
    }
  ];

  // The display name of the TiDB group.
  string display_name = 4 [
    (google.api.field_behavior) = OPTIONAL,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      example: "\"DefaultGroup\""
      description: "The display name of the TiDB group."
    }
  ];

  int32 node_count = 5 [
    (google.api.field_behavior) = REQUIRED,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      example: "2"
      minimum: 1
      description: "The number of TiDB nodes in the TiDB group. It must be greater than or equal to `1`."
    }
  ];

  repeated Endpoint endpoints = 10 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The endpoints of the TiDB group."
      title: "Endpoint"
      example: "[]"
    }
  ];

  // The heterogeneous node spec key of the TiDB group. Only takes effect when homogeneous `node_spec_key` in `tidb_node_setting` is not set.
  string node_spec_key = 11 [
    (google.api.field_behavior) = OPTIONAL,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      example: "\"8C32G\""
      description: "The node spec key of the TiDB group. For example, `8C32G`."
    }
  ];

  // The version tag of the node spec resource. The performance and price of the component may vary based on the version tag.
  string node_spec_version = 18 [(google.api.field_behavior) = OUTPUT_ONLY];

  string node_spec_display_name = 12 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      example: "\"8 vCPU, 32 GiB\""
      description: "The display name of the node spec of the TiDB group. For example, `8 vCPU, 32 GiB`."
    }
  ];

  bool is_default_group = 13 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "Indicates whether this is the default TiDB node group."
      example: "false"
    }
  ];

  // The current state of the TiDB group. For output only.
  State state = 14 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The current state of the TiDB group."
      example: "\"ACTIVE\""
    }
  ];

  Cluster.NodeChangingProgress node_changing_progress = 15 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The progress of node configuration changes."
      title: "NodeChangingProgress"
    }
  ];

  // Configures TiProxy settings for this TiDB group. If not specified, the default TiProxy settings is used.
  TiProxySetting tiproxy_setting = 16 [(google.api.field_behavior) = OPTIONAL];

  // The progress of TiProxy node configuration changes.
  Cluster.NodeChangingProgress tiproxy_node_changing_progress = 17 [(google.api.field_behavior) = OUTPUT_ONLY];

  message TiProxySetting {
    string node_spec_key = 1 [
      (google.api.field_behavior) = REQUIRED,
      (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
        example: "\"2C4G\""
        description: "The node spec key of the TiProxy nodes in the cluster. For example, `2C4G`.\n\nTo view available node specs, use the [List node specs](#tag/RegionService/operation/RegionService_ListNodeSpecs) endpoint."
      }
    ];

    string node_spec_version = 4 [(google.api.field_behavior) = OUTPUT_ONLY];

    optional int32 node_count = 2 [
      (google.api.field_behavior) = OPTIONAL,
      (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
        example: "2"
        description: "The number of TiProxy nodes in the TiDB group. If not specified or set to `0`, TiProxy is disabled."
      }
    ];

    // The display name of the node spec.
    string node_spec_display_name = 3 [
      (google.api.field_behavior) = OUTPUT_ONLY,
      (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
        example: "\"2 vCPU, 4 GiB\""
        description: "The display name of the TiProxy node spec. For example, `2 vCPU, 4 GiB`."
      }
    ];
  }

  message Endpoint {
    string host = 1 [
      (google.api.field_behavior) = OUTPUT_ONLY,
      (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "The hostname or IP address of the endpoint. For `PRIVATE_ENDPOINT` connection types, availability varies by cloud provider:\n\n- For clusters deployed on AWS, the `host` field is available after the private link service is ready.\n\n- For clusters deployed on Google Cloud or Azure, the `host` field is available after you create a `PrivateEndpointConnection`."}
    ];

    int32 port = 2 [
      (google.api.field_behavior) = OUTPUT_ONLY,
      (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "The port of the endpoint connection."}
    ];

    ConnectionType connection_type = 3 [
      (google.api.field_behavior) = OUTPUT_ONLY,
      (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
        description: "The connection type for TiDB node group endpoints.\n\n- `\"PUBLIC\"`: indicates that the endpoint is accessible over the public network.\n\n- `\"VPC_PEERING\"`: indicates that the endpoint is accessible over [VPC peering](https://docs.pingcap.com/tidbcloud/tidb-cloud-glossary/#vpc-peering).\n\n- `\"PRIVATE_ENDPOINT\"`: indicates that the endpoint is accessible over a private link."
        example: "\"PRIVATE_ENDPOINT\""
      }
    ];

    // The connection type for TiDB node group endpoints.
    enum ConnectionType {
      CONNECTION_TYPE_UNSPECIFIED = 0;

      // Indicates that the endpoint is accessible over the public network.
      PUBLIC = 1;

      // Indicates that the endpoint is accessible over [VPC peering](https://docs.pingcap.com/tidbcloud/tidb-cloud-glossary/#vpc-peering).
      VPC_PEERING = 2;

      // Indicates that the endpoint is accessible over a private link.
      PRIVATE_ENDPOINT = 3;
    }
  }

  enum State {
    STATE_UNSPECIFIED = 0;

    // Indicates the TiDB group is active and ready for use.
    ACTIVE = 1;

    // Indicates the TiDB group is being modified.
    MODIFYING = 2;

    // Indicates the TiDB group is paused.
    PAUSED = 3;
  }
}

// All fields are output only.
message NodeInstance {
  option (google.api.resource) = {
    type: "tidb_cloud_open_api.dedicated.v1beta1/NodeInstance"
    pattern: "clusters/{cluster}/nodeInstances/{node_instance}"
  };

  string name = 1 [
    (google.api.field_behavior) = IDENTIFIER,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The name of the node instance resource which is formatted as: `clusters/{cluster_id}/nodeInstances/{instance_id}`."
      example: "\"clusters/1/nodeInstances/tidb-0\""
    }
  ];

  string cluster_id = 2 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    description: "The ID of the cluster to which the node instance belongs."
    example: "\"1\""
  }];

  string instance_id = 3 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    description: "The ID of the node instance. It is formatted as:\n- `tidb-{index}` for TiDB instances in the default TiDB group\n- `{tidb_group_name}-tidb-{index}` for TiDB instances in non-default TiDB groups\n- `{component_type}-{index}` for other instances."
    example: "\"tidb-0\""
  }];

  ComponentType component_type = 4 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    description: "The component type of the node instance. It can be one of the following values:\n- `TIDB`: TiDB node instance.\n- `TIKV`: TiKV node instances.\n- `TIFLASH`: TiFlash node instances.\n- `PD`: PD node instances.\n- `PROXY`: Proxy node instances."
    example: "\"TIDB\""
  }];

  State state = 5 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    description: "The state of the node instance.\n- `CREATING`: indicates the node instance is being created.\n- `AVAILABLE`: indicates the node instance is available for use.\n- `DELETING`: indicates the node instance is being deleted.\n- `UNAVAILABLE`: indicates the node instance is not available."
    example: "\"AVAILABLE\""
  }];

  int32 v_cpu = 6 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    description: "The number of vCPUs of the node instance. e.g. `8`."
    example: "8"
  }];

  int32 memory_size_gi = 7 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    description: "The memory size of the node instance in GiB. e.g. `32`."
    example: "32"
  }];

  string availability_zone = 8 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The availability zone of the node instance, e.g. `us-west-2a`."
      example: "\"us-west-2a\""
    }
  ];

  int32 storage_size_gi = 9 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    description: "The storage size of the node instance in GiB. e.g. `200`."
    example: "200"
  }];

  // The ID of the TiDB node group that the node instance belongs to.
  optional string tidb_node_group_id = 10 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    description: "The ID of the TiDB node group that the node instance belongs to."
    example: "\"node_group_id\""
  }];

  optional string tidb_node_group_display_name = 11 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    description: "The display name of the TiDB node group that the node instance belongs to."
    example: "\"DefaultGroup\""
  }];

  optional bool is_default_tidb_node_group = 12 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    description: "Indicates whether the TiDB node group that the node instance belongs to is the default one."
    example: "true"
  }];

  // The IOPS of the data store of the node instance. Only available for AWS instances with `Plus` TiKV storage type.
  optional int32 data_store_iops = 19;

  // The IOPS of the raft store of the node instance. Only available for instances which have storage. If not set, the default IOPS of raft store will be used.
  optional int32 raft_store_iops = 14;

  optional Cluster.StorageNodeSetting.StorageType storage_type = 15 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    description: "The storage type of the node instance. Only available for instances which have storage."
    example: "\"Standard\""
  }];

  string node_spec_display_name = 16 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    description: "The display name of the node spec of the node instance. e.g. `8 vCPU, 32 GiB`."
    example: "\"8 vCPU, 32 GiB\""
  }];

  // The version tag of the node spec resource. The performance and price of the component may vary based on the version tag.
  string node_spec_version = 17;

  string node_spec_key = 18 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    description: "The node spec key of the node instance. e.g. `8C32G`."
    example: "\"8C32G\""
  }];

  enum State {
    STATE_UNSPECIFIED = 0;

    CREATING = 1;

    AVAILABLE = 2;

    DELETING = 3;

    UNAVAILABLE = 4;
  }
}

// (-- api-linter: core::0133::http-uri-resource=disabled
//     aip.dev/not-precedent: It is a singleton resource. Refer to https://google.aip.dev/156. --)
message PublicEndpointSetting {
  option (google.api.resource) = {
    type: "tidb_cloud_open_api.dedicated.v1beta1/PublicEndpointSetting"
    pattern: "tidbNodeGroups/{tidbNodeGroup}/publicEndpointSetting"
    singular: "publicEndpointSetting"
    plural: "publicEndpointSettings"
  };

  // The name of the public endpoint setting resource formatted as: `tidbNodeGroups/{tidb_node_group_id}/publicEndpointSetting`.
  string name = 1 [
    (google.api.field_behavior) = IDENTIFIER,
    (google.api.field_behavior) = OUTPUT_ONLY
  ];

  // The ID of the TiDB group to which the public endpoint setting belongs. If set to "-", the default TiDB group will be used.
  string tidb_node_group_id = 2 [(google.api.field_behavior) = REQUIRED];

  // Indicates whether the public endpoint is enabled for the TiDB group.
  optional bool enabled = 3 [(google.api.field_behavior) = OPTIONAL];

  repeated IpAccessList ip_access_list = 4 [
    (google.api.field_behavior) = OPTIONAL,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "A list of IP access control lists for the public endpoint. If not set, all IPs are allowed to access the public endpoint."
      title: "IpAccessList"
    }
  ];

  message IpAccessList {
    // The CIDR notation of the IP access control list.
    string cidr_notation = 1 [(google.api.field_behavior) = REQUIRED];

    // The description of the IP access control list.
    string description = 2 [(google.api.field_behavior) = OPTIONAL];
  }
}

// All fields are output only.
// (-- api-linter: core::0133::http-uri-resource=disabled
//     aip.dev/not-precedent: It is a singleton resource. Refer to https://google.aip.dev/156. --)
message PrivateLinkService {
  option (google.api.resource) = {
    type: "tidb_cloud_open_api.dedicated.v1beta1/PrivateLinkService"
    pattern: "tidbNodeGroups/{tidbNodeGroup}/privateLinkService"
    singular: "privateLinkService"
    plural: "privateLinkServices"
  };

  string name = 1 [
    (google.api.field_behavior) = IDENTIFIER,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      example: "\"tidbNodeGroups/1/privateLinkService\""
      description: "The name of the private link service."
    }
  ];

  string tidb_node_group_id = 2 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    example: "\"1\""
    description: "The ID of the TiDB group to which the private link service belongs."
  }];

  string service_name = 3 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    description: "The service name of the private link service, which varies by cloud provider:\n\n- AWS: the service name of the private link service.\n\n- Google Cloud: the resource name of the service attachment.\n\n- Azure: the resource ID of the private link service."
    example: "\"com.amazonaws.vpce.us-east-1.vpce-svc-1234567890\""
  }];

  string service_dns_name = 4 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    description: "The DNS name of the private link service, which varies by cloud provider:\n\n- AWS: the fully qualified domain name (FQDN) shared across all private endpoints, regardless of VPC location.\n\n- Google Cloud: the zone name (suffix of the FQDN) shared across all private endpoints in a single VPC network. The format of FQDN is `<endpoint_name>.<service_dns_name>`.\n\n- Azure: the zone name shared across public internet. The format of FQDN is `<endpoint_name>-<random_hash>.<service_dns_name>`."
    example: "\"privatelink-1234567890.muznnz1umf3p.clusters.staging.tidb-cloud.com\""
  }];

  repeated string available_zones = 6 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    description: "(AWS only) The availability zones where the private link service is available. For more information, see [`DescribeVpcEndpointServices`](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeVpcEndpointServices.html)."
    example: "[\"use1-az1\", \"use1-az4\", \"use1-az6\"]"
  }];

  State state = 7 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    description: "The state of the private link service.\n\n- `\"CREATING\"`: the private link service is being created.\n\n- `\"ACTIVE\"`: the private link service is ready to use.\n\n- `\"DELETING\"`: the private link service is being deleted."
    example: "\"ACTIVE\""
  }];

  string region_id = 8 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    description: "The ID of the region where the private link service is located, in the format of `{cloud_provider}-{region_code}`. For example, `aws-us-east-1`."
    example: "\"aws-us-east-1\""
  }];

  string region_display_name = 9 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    description: "The display name of the region where the private link service is located. For example, `N. Virginia (us-east-1)`."
    example: "\"N. Virginia (us-east-1)\""
  }];

  common.v1beta1.Region.CloudProvider cloud_provider = 10 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    description: "The cloud provider where the private link service is located.\n\n- `\"aws\"`: Amazon Web Services\n\n- `\"gcp\"`: Google Cloud\n\n- `\"azure\"`: Microsoft Azure\n\n- `\"alicloud\"`: Alibaba Cloud"
    example: "\"aws\""
  }];

  enum State {
    STATE_UNSPECIFIED = 0;

    // The private link service is being created.
    CREATING = 1;

    // The private link service is active and ready for use.
    ACTIVE = 2;

    // The private link service is being deleted.
    DELETING = 3;
  }
}

message PrivateEndpointConnection {
  option (google.api.resource) = {
    type: "tidb_cloud_open_api.dedicated.v1beta1/PrivateEndpointConnection"
    pattern: "tidbNodeGroups/{tidbNodeGroup}/privateEndpointConnections/{privateEndpointConnection}"
  };

  string name = 1 [
    (google.api.field_behavior) = IDENTIFIER,
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The name of the private endpoint connection, in the format of `tidbNodeGroups/{tidb_node_group_id}/privateEndpointConnections/{private_endpoint_connection_id}`."
      example: "\"tidbNodeGroups/1/privateEndpointConnections/1234567890\""
    }
  ];

  string tidb_node_group_id = 2 [
    (google.api.field_behavior) = REQUIRED,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The ID of the TiDB group to which the private endpoint connection belongs."
      example: "\"1\""
    }
  ];

  // The ID of the private endpoint connection.
  string private_endpoint_connection_id = 3 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The unique ID of the private endpoint connection."
      example: "\"1234567890\""
    }
  ];

  string cluster_id = 4 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The ID of the cluster to which the private endpoint connection belongs."
      example: "\"1\""
    }
  ];

  string cluster_display_name = 5 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The display name of the cluster to which the private endpoint connection belongs."
      example: "\"my-cluster\""
    }
  ];

  map<string, string> labels = 6 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The labels of the private link connection, including the mandatory `tidb.cloud/project` label identifying the project it belongs to."
      example: "{\"tidb.cloud/project\": \"1\"}"
      title: "map<string, string>"
    }
  ];

  string endpoint_id = 7 [
    (google.api.field_behavior) = REQUIRED,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The endpoint ID of the private link connection.\n\n- AWS: the VPC endpoint ID for [AWS PrivateLink\n](https://aws.amazon.com/privatelink/).\n\n- Google Cloud: the endpoint ID for [Private Service Connect](https://cloud.google.com/vpc/docs/private-service-connect).\n\n- Azure: the resource ID for [Azure Private Link](https://learn.microsoft.com/en-us/azure/private-link/private-link-overview)."
      example: "\"vpce-0a1b2c3d4e5f6g7h8\""
    }
  ];

  optional string private_ip_address = 8 [
    (google.api.field_behavior) = OPTIONAL,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "(Azure only) The private IP address of the private endpoint in your virtual network. TiDB Cloud automatically creates a public DNS record that resolves to this IP address, enabling you to connect using the DNS name."}
  ];

  EndpointState endpoint_state = 9 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The state of the private endpoint connection.\n\n- `\"PENDING\"`: TiDB Cloud is asynchronously accepting the endpoint connection.\n\n- `\"ACTIVE\"`: the private endpoint connection is ready to use.\n\n- `\"DELETING\"`: the private endpoint connection is being deleted.\n\n- `\"FAILED\"`: the private endpoint connection has failed.\n- `\"DISCOVERED\"`: the endpoint is created in your VPC but not registered with TiDB Cloud."
      example: "\"ACTIVE\""
    }
  ];

  string message = 10 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The detailed message when the `endpointState` field is `\"FAILED\"`."
      example: "\"\""
    }
  ];

  string region_id = 11 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The ID of the region where the private endpoint connection is located, in the format of `{cloud_provider}-{region_code}`. For example, `aws-us-east-1`."
      example: "\"aws-us-east-1\""
    }
  ];

  string region_display_name = 12 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The display name of the region where the private endpoint connection is located. For example, `N. Virginia (us-east-1)`."
      example: "\"N. Virginia (us-east-1)\""
    }
  ];

  common.v1beta1.Region.CloudProvider cloud_provider = 13 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The cloud provider where the private endpoint connection is located.\n\n- `\"aws\"`: Amazon Web Services\n\n- `\"gcp\"`: Google Cloud\n\n- `\"azure\"`: Microsoft Azure\n\n- `\"alicloud\"`: Alibaba Cloud"
      example: "\"aws\""
    }
  ];

  string private_link_service_name = 14 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The name of the private link service that the private endpoint connection is connected to."
      example: "\"com.amazonaws.vpce.us-east-1.vpce-svc-1234567890\""
    }
  ];

  PrivateLinkService.State private_link_service_state = 15 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The state of the private link service that the private endpoint connection is connected to."
      example: "\"ACTIVE\""
    }
  ];

  string tidb_node_group_display_name = 16 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The display name of the TiDB node group that the private endpoint connection is connected to."
      example: "\"DefaultGroup\""
    }
  ];

  // (Google Cloud only) The project name used to identify the Google Cloud project that the private service connection belongs to.
  optional string account_id = 17 [(google.api.field_behavior) = OUTPUT_ONLY];

  string host = 18 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The hostname for accessing the TiDB cluster through the private endpoint connection."
      example: "\"privatelink-1234567890.abcdefg.clusters.tidb-cloud.com\""
    }
  ];

  int32 port = 19 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The port used to connect to the TiDB cluster through the private endpoint connection."
      example: "4000"
    }
  ];

  optional IPAddressType ip_address_type = 20 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The IP address type configured on the private endpoint connection. This field is currently available only for AWS PrivateLink endpoints."
      example: "\"IP_ADDRESS_TYPE_IPV6\""
    }
  ];

  // The state of the private endpoint connection.
  enum EndpointState {
    STATE_UNSPECIFIED = 0;

    // TiDB Cloud is asynchronously accepting the endpoint connection.
    PENDING = 1;

    // The private endpoint connection is ready to use.
    ACTIVE = 2;

    // The private endpoint connection is being deleted.
    DELETING = 3;

    // The private endpoint connection has failed.
    FAILED = 4;

    // The endpoint is created in your VPC but not registered with TiDB Cloud.
    DISCOVERED = 5;
  }

  enum IPAddressType {
    IP_ADDRESS_TYPE_UNSPECIFIED = 0;

    IP_ADDRESS_TYPE_IPV4 = 1;
    IP_ADDRESS_TYPE_IPV6 = 2;
    IP_ADDRESS_TYPE_DUALSTACK = 3;
  }
}

message NetworkContainer {
  option (google.api.resource) = {
    type: "tidb_cloud_open_api.dedicated.v1beta1/NetworkContainer"
    pattern: "networkContainers/{networkContainer}"
  };

  // Format: networkContainers/{network_container_id}
  string name = 1 [
    (google.api.field_behavior) = IDENTIFIER,
    (google.api.field_behavior) = OUTPUT_ONLY
  ];

  string network_container_id = 2 [(google.api.field_behavior) = OUTPUT_ONLY];

  // The labels of the cluster.
  // If there is no "project_id" in labels, resource should be in the default project of the creator's organization.
  map<string, string> labels = 3 [(google.api.field_behavior) = OPTIONAL];

  // Format: {cloud_provider}-{region_code}
  string region_id = 4 [(google.api.field_behavior) = REQUIRED];

  // If not set, the default cidr of the region will be used.
  string cidr_notation = 5 [(google.api.field_behavior) = OPTIONAL];

  common.v1beta1.Region.CloudProvider cloud_provider = 6 [(google.api.field_behavior) = OUTPUT_ONLY];

  State state = 7 [(google.api.field_behavior) = OUTPUT_ONLY];

  string region_display_name = 8 [(google.api.field_behavior) = OUTPUT_ONLY];

  // For AWS, it is the vpc id.
  // For GCP, it is the network name.
  // For Azure, it is the vnet name.
  string vpc_id = 9 [(google.api.field_behavior) = OUTPUT_ONLY];

  enum State {
    STATE_UNSPECIFIED = 0;

    ACTIVE = 1;

    INACTIVE = 2;
  }
}

message VpcPeering {
  option (google.api.resource) = {
    type: "tidb_cloud_open_api.dedicated.v1beta1/VpcPeering"
    pattern: "vpcPeerings/{vpcPeering}"
  };

  // Format: vpcPeerings/{vpc_peering_id}
  string name = 1 [
    (google.api.field_behavior) = IDENTIFIER,
    (google.api.field_behavior) = OUTPUT_ONLY
  ];

  // Format {cloud_provider}-{random_suffix}
  string vpc_peering_id = 2 [(google.api.field_behavior) = OUTPUT_ONLY];

  // The labels of the vpc peering. It always contains the `project_id` label.
  map<string, string> labels = 3 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Format: {cloud_provider}-{region_code}
  string tidb_cloud_region_id = 4 [(google.api.field_behavior) = REQUIRED];

  // Format: {cloud_provider}-{region_code}
  // For AWS, it's required.
  // For GCP, it's optional. Since GCP does not require region_id when creating VPC peering.
  string customer_region_id = 5 [(google.api.field_behavior) = OPTIONAL];

  // In AWS, it is the account ID.
  // In GCP, it is the project name.
  string customer_account_id = 6 [(google.api.field_behavior) = REQUIRED];

  // In AWS, it is the VPC ID.
  // In GCP, it is the network name.
  string customer_vpc_id = 7 [(google.api.field_behavior) = REQUIRED];

  string customer_vpc_cidr = 8 [(google.api.field_behavior) = REQUIRED];

  common.v1beta1.Region.CloudProvider tidb_cloud_cloud_provider = 9 [(google.api.field_behavior) = OUTPUT_ONLY];

  // In AWS, it is the account ID.
  // In GCP, it is the project name.
  string tidb_cloud_account_id = 10 [(google.api.field_behavior) = OUTPUT_ONLY];

  // In AWS, it is the VPC ID.
  // In GCP, it is the network name.
  string tidb_cloud_vpc_id = 11 [(google.api.field_behavior) = OUTPUT_ONLY];

  string tidb_cloud_vpc_cidr = 12 [(google.api.field_behavior) = OUTPUT_ONLY];

  State state = 13 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Only for AWS vpc peerings.
  optional string aws_vpc_peering_connection_id = 14 [(google.api.field_behavior) = OUTPUT_ONLY];

  enum State {
    STATE_UNSPECIFIED = 0;

    PENDING = 1;

    FAILED = 2;

    ACTIVE = 3;
  }
}

enum ComponentType {
  COMPONENT_TYPE_UNSPECIFIED = 0;

  TIKV = 1;

  TIDB = 2;

  TIFLASH = 3;

  TIFLASH_LEARNER = 4 [(google.api.value_visibility).restriction = "DO_NOT_RELEASE"];

  PD = 5;

  TIPROXY = 6;
}

// MaintenanceWindow is a singleton resource that represents the maintenance window under a project.
message MaintenanceWindow {
  option (google.api.resource) = {
    type: "tidb_cloud_open_api.dedicated.v1beta1/MaintenanceWindow"
    pattern: "maintenanceWindows/{maintenanceWindow}"
  };

  // Format: maintenanceWindows/{maintenance_window_id}
  string name = 1 [
    (google.api.field_behavior) = IDENTIFIER,
    (google.api.field_behavior) = OUTPUT_ONLY
  ];

  // Format: project-{project_id}
  string maintenance_window_id = 2 [(google.api.field_behavior) = OUTPUT_ONLY];

  string project_id = 3 [(google.api.field_behavior) = REQUIRED];

  // 0-6, 0 is Sunday.
  int32 week_day = 4 [(google.api.field_behavior) = REQUIRED];

  // 0-23 in UTC.
  int32 day_hour = 5 [(google.api.field_behavior) = REQUIRED];

  // 0-59 in UTC.
  int32 hour_minute = 6 [(google.api.field_behavior) = REQUIRED];

  google.protobuf.Timestamp next_maintenance_date = 7 [(google.api.field_behavior) = OUTPUT_ONLY];

  repeated MaintenanceTask unchanged_maintenance_tasks = 8 [(google.api.field_behavior) = OUTPUT_ONLY];
}

// All fields are output only.
message MaintenanceTask {
  option (google.api.resource) = {
    type: "tidb_cloud_open_api.dedicated.v1beta1/MaintenanceTask"
    pattern: "maintenanceTasks/{maintenanceTask}"
  };

  // Format: maintenanceTasks/{maintenance_task_id}
  string name = 1 [(google.api.field_behavior) = IDENTIFIER];

  string maintenance_task_id = 2;

  string project_id = 3;

  string description = 4;

  State state = 5;

  // Timestamp when the task was created.
  google.protobuf.Timestamp create_time = 6;

  // Timestamp when the task run.
  google.protobuf.Timestamp scheduled_apply_time = 7;

  // Timestamp when the task will be expired.
  google.protobuf.Timestamp deadline = 8;

  enum State {
    STATE_UNSPECIFIED = 0;

    PENDING = 1;

    RUNNING = 2;

    DONE = 3;
  }
}

// (-- api-linter: core::0133::http-uri-resource=disabled
//     aip.dev/not-precedent: It is a singleton resource. Refer to https://google.aip.dev/156. --)
message AuditLogConfig {
  option (google.api.resource) = {
    type: "tidb_cloud_open_api.dedicated.v1beta1/AuditLogConfig"
    pattern: "clusters/{cluster}/auditLogConfig"
    singular: "auditLogConfig"
    plural: "auditLogConfigs"
  };

  // Format: clusters/{cluster_id}/auditLogConfig
  string name = 1 [
    (google.api.field_behavior) = IDENTIFIER,
    (google.api.field_behavior) = OUTPUT_ONLY
  ];

  string cluster_id = 2 [(google.api.field_behavior) = REQUIRED];

  // Default is disabled.
  bool enabled = 3 [(google.api.field_behavior) = OPTIONAL];

  // Required if bucket_manager is CUSTOMER.
  string bucket_uri = 4 [(google.api.field_behavior) = OPTIONAL];

  // Format: {cloud_provider}-{region_code}
  string bucket_region_id = 5 [(google.api.field_behavior) = OPTIONAL];

  string aws_role_arn = 6 [(google.api.field_behavior) = OPTIONAL];

  string azure_sas_token = 7 [(google.api.field_behavior) = OPTIONAL];

  // The bucket_manager field is used to indicate who manages the bucket.
  // If this field is not set, the bucket is managed by the customer by default.
  BucketManager bucket_manager = 9 [(google.api.field_behavior) = OPTIONAL];

  // Default is redacted.
  bool unredacted = 10 [(google.api.field_behavior) = OPTIONAL];

  // If unset, default to TEXT.
  Format format = 12 [(google.api.field_behavior) = OPTIONAL];

  // If unset, default to max_size_mib=10, max_age_second=86400 (1 day).
  RotationPolicy rotation_policy = 13 [(google.api.field_behavior) = OPTIONAL];

  // Available only when write check failed.
  BucketWriteCheck bucket_write_check = 8 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Default to false (and not shown), which means the legacy audit log implementation are not used.
  optional bool legacy = 15 [(google.api.field_behavior) = OUTPUT_ONLY];

  enum BucketManager {
    BUCKET_MANAGER_UNSPECIFIED = 0;

    CUSTOMER = 1;

    PINGCAP = 2;
  }

  enum Format {
    FORMAT_UNSPECIFIED = 0;

    TEXT = 1;

    JSON = 2;
  }

  message RotationPolicy {
    // Set the file size limitation for audit logs. A log rotation is triggered if the log file exceeds this limitation.
    // In the current version, If you set this variable to 0, TiDB automatically changes it to 10.
    int32 max_size_mib = 1 [
      (google.api.field_behavior) = OPTIONAL,
      (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
        default: "10"
        minimum: 1
        maximum: 100
      }
    ];

    // Set the time limitation for audit logs. A log rotation is triggered if the log file exceeds this limitation.
    // Setting this variable to 0 means to disable automatic log rotation by time.
    optional int32 max_age_second = 2 [
      (google.api.field_behavior) = OPTIONAL,
      (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
        default: "86400" // 1 day
        maximum: 2592000 // 30 days
      }
    ];
  }

  message BucketWriteCheck {
    bool writable = 1 [(google.api.field_behavior) = OUTPUT_ONLY];

    // The reason why the bucket is not writable. Output only when `writable` is false.
    string error_reason = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
  }
}

message AuditLogFilterRule {
  option (google.api.resource) = {
    type: "tidb_cloud_open_api.dedicated.v1beta1/AuditLogFilterRule"
    pattern: "clusters/{cluster}/auditLogFilterRules/{auditLogFilterRule}"
  };

  // Format: auditLogFilterRules/{audit_log_filter_rule_id}
  string name = 1 [
    (google.api.field_behavior) = IDENTIFIER,
    (google.api.field_behavior) = OUTPUT_ONLY
  ];

  // audit_log_filter_rule_id is a unique identifier for the rule. Currently, the value is the same as user_expr.
  // For legacy, the audit_log_filter_rule_id is a number.
  string audit_log_filter_rule_id = 2 [(google.api.field_behavior) = OUTPUT_ONLY];

  string cluster_id = 3 [(google.api.field_behavior) = REQUIRED];

  // Format: <user>@<host>.
  // The audit user <user>@<host> consists of the username and hostname with @ as separator, where @ and <host> are optional.
  // Both username and hostname can be identifiers with wildcards:
  //   - % for matching any username/hostname.
  //   - _ for matching any character.
  // For multiple filter rules, if their user_expr fields match the same username, that matches the longest username takes effect.
  // In general, this field is required. Only when `AuditLogConfig.legacy` is true, this field is optional.
  // For legacy, the express is a regex.
  string user_expr = 4 [(google.api.field_behavior) = OPTIONAL];

  // Default is enabled.
  bool disabled = 8 [(google.api.field_behavior) = OPTIONAL];

  // If empty, it means all events.
  repeated EventType event_types = 9 [(google.api.field_behavior) = OPTIONAL];

  // If not set, default to the value of `user_expr`.
  string display_name = 10 [(google.api.field_behavior) = OPTIONAL];

  // Deprecated. Only available when `AuditLogConfig.legacy` is true.
  // The express is a glob pattern. Refer to https://github.com/pingcap/tidb/blob/master/pkg/util/table-filter/README.md#wildcards.
  string db_expr = 5 [
    (google.api.field_behavior) = OPTIONAL,
    deprecated = true
  ];

  // Deprecated. Only available when `AuditLogConfig.legacy` is true.
  // The express is a glob pattern. Refer to https://github.com/pingcap/tidb/blob/master/pkg/util/table-filter/README.md#wildcards.
  string table_expr = 6 [
    (google.api.field_behavior) = OPTIONAL,
    deprecated = true
  ];

  // Deprecated. Only available when `AuditLogConfig.legacy` is true.
  repeated string access_type_list = 7 [
    (google.api.field_behavior) = OPTIONAL,
    deprecated = true
  ];

  // DB audit logging includes the following event types:
  //  - CONNECTION
  //    - CONNECT
  //    - DISCONNECT
  //    - CHANGE_USER
  //  - QUERY
  //    - TRANSACTION
  //    - EXECUTE
  //    - QUERY_DML
  //      - INSERT
  //      - REPLACE
  //      - UPDATE
  //      - DELETE
  //      - LOAD DATA
  //    - SELECT
  //    - QUERY_DDL
  enum EventType {
    EVENT_TYPE_UNSPECIFIED = 0;

    CONNECTION = 1;
    CONNECT = 2;
    DISCONNECT = 3;
    CHANGE_USER = 4;
    QUERY = 5;
    TRANSACTION = 6;
    EXECUTE = 7;
    QUERY_DML = 8;
    INSERT = 9;
    REPLACE = 10;
    UPDATE = 11;
    DELETE = 12;
    LOAD_DATA = 13;
    SELECT = 14;
    QUERY_DDL = 15;
  }
}

message CustomerManagedEncryptionKey {
  option (google.api.resource) = {
    type: "tidb_cloud_open_api.dedicated.v1beta1/CustomerManagedEncryptionKey"
    pattern: "cmeks/{customerManagedEncryptionKey}"
  };

  // Format: customerManagedEncryptionKeys/{customer_managed_encryption_key_id}
  string name = 1 [
    (google.api.field_behavior) = IDENTIFIER,
    (google.api.field_behavior) = OUTPUT_ONLY
  ];

  string customer_managed_encryption_key_id = 2 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Format: {cloud_provider}-{region_code}
  string region_id = 3 [(google.api.field_behavior) = REQUIRED];

  string project_id = 4 [(google.api.field_behavior) = OPTIONAL];

  oneof key {
    AwsKms aws_kms = 5 [(google.api.field_behavior) = OPTIONAL];

    AzureKeyVault azure_key_vault = 6 [(google.api.field_behavior) = OPTIONAL];
  }

  google.protobuf.Timestamp create_time = 7 [(google.api.field_behavior) = OUTPUT_ONLY];

  string region_display_name = 8 [(google.api.field_behavior) = OUTPUT_ONLY];
}

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

message AzureKeyVault {
  string key_vault_key = 1 [(google.api.field_behavior) = REQUIRED];
  string key_vault_name = 2 [(google.api.field_behavior) = REQUIRED];
  AzureAppRegistration app_registration = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
}

message AzureAppRegistration {
  string app_registration_id = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
  string app_registration_name = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
}

message LogRedactionPolicy {
  string cluster_id = 1 [
    (google.api.field_behavior) = REQUIRED,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "The ID of the cluster to which the log redaction policy applies."
      example: "\"1\""
    }
  ];

  optional bool redact_log = 2 [
    (google.api.field_behavior) = OPTIONAL,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "Indicates whether to redact sensitive information in logs.\n\nThe default policy is `true`, which means sensitive data is redacted in logs.\n\n**Note**: Disabling log redaction might expose sensitive information and increase the risk of data leakage. Ensure that you understand and acknowledge this risk before proceeding. Remember to re-enable it as soon as you complete your diagnostic or maintenance task."
      example: "true"
      default: "true"
    }
  ];
}

// PrivateLinkIPAddressTypeSetting represents the asynchronous PrivateLink IP address type setting of a TiDB Node Group.
// (-- api-linter: core::0133::http-uri-resource=disabled
//     aip.dev/not-precedent: It is a singleton resource. Refer to https://google.aip.dev/156. --)
message PrivateLinkIPAddressTypeSetting {
  option (google.api.resource) = {
    type: "tidb_cloud_open_api.dedicated.v1beta1/PrivateLinkIPAddressTypeSetting"
    pattern: "tidbNodeGroups/{tidb_node_group}/privateLinkIpAddressTypeSetting"
    singular: "privateLinkIpAddressTypeSetting"
    plural: "privateLinkIpAddressTypeSettings"
  };

  // The name of the setting resource formatted as: `tidbNodeGroups/{tidb_node_group_id}/privateLinkIpAddressTypeSetting`.
  string name = 1 [
    (google.api.field_behavior) = IDENTIFIER,
    (google.api.field_behavior) = OUTPUT_ONLY
  ];

  // The ID of the TiDB Node Group to which the setting belongs.
  string tidb_node_group_id = 2 [(google.api.field_behavior) = OUTPUT_ONLY];

  // The requested PrivateLink IP address type.
  IPAddressType desired = 3 [(google.api.field_behavior) = REQUIRED];

  // The PrivateLink IP address type strictly observed from the infrastructure.
  optional IPAddressType observed = 4 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Whether the desired type has been strictly observed and is ready.
  bool ready = 5 [(google.api.field_behavior) = OUTPUT_ONLY];

  // A human-readable status message. Clients must use state rather than parse this field.
  string message = 6 [(google.api.field_behavior) = OUTPUT_ONLY];

  // The asynchronous state of the setting.
  State state = 7 [(google.api.field_behavior) = OUTPUT_ONLY];

  enum IPAddressType {
    IP_ADDRESS_TYPE_UNSPECIFIED = 0;
    IPV4 = 1;
    DUALSTACK = 2;
  }

  enum State {
    STATE_UNSPECIFIED = 0;

    READY = 1;

    // The address update is running or being retried.
    CHANGING = 2;

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