// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

package google.spanner.admin.instance.v1;

import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/iam/v1/iam_policy.proto";
import "google/iam/v1/policy.proto";
import "google/longrunning/operations.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/field_mask.proto";
import "google/protobuf/timestamp.proto";

option csharp_namespace = "Google.Cloud.Spanner.Admin.Instance.V1";
option go_package = "google.golang.org/genproto/googleapis/spanner/admin/instance/v1;instance";
option java_multiple_files = true;
option java_outer_classname = "SpannerInstanceAdminProto";
option java_package = "com.google.spanner.admin.instance.v1";
option php_namespace = "Google\\Cloud\\Spanner\\Admin\\Instance\\V1";
option ruby_package = "Google::Cloud::Spanner::Admin::Instance::V1";

// Cloud Spanner Instance Admin API
//
// The Cloud Spanner Instance Admin API can be used to create, delete,
// modify and list instances. Instances are dedicated Cloud Spanner serving
// and storage resources to be used by Cloud Spanner databases.
//
// Each instance has a "configuration", which dictates where the
// serving resources for the Cloud Spanner instance are located (e.g.,
// US-central, Europe). Configurations are created by Google based on
// resource availability.
//
// Cloud Spanner billing is based on the instances that exist and their
// sizes. After an instance exists, there are no additional
// per-database or per-operation charges for use of the instance
// (though there may be additional network bandwidth charges).
// Instances offer isolation: problems with databases in one instance
// will not affect other instances. However, within an instance
// databases can affect each other. For example, if one database in an
// instance receives a lot of requests and consumes most of the
// instance resources, fewer resources are available for other
// databases in that instance, and their performance may suffer.
service InstanceAdmin {
  option (google.api.default_host) = "spanner.googleapis.com";
  option (google.api.oauth_scopes) =
      "https://www.googleapis.com/auth/cloud-platform,"
      "https://www.googleapis.com/auth/spanner.admin";

  // Lists the supported instance configurations for a given project.
  rpc ListInstanceConfigs(ListInstanceConfigsRequest) returns (ListInstanceConfigsResponse) {
    option (google.api.http) = {
      get: "/v1/{parent=projects/*}/instanceConfigs"
    };
    option (google.api.method_signature) = "parent";
  }

  // Gets information about a particular instance configuration.
  rpc GetInstanceConfig(GetInstanceConfigRequest) returns (InstanceConfig) {
    option (google.api.http) = {
      get: "/v1/{name=projects/*/instanceConfigs/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // Lists all instances in the given project.
  rpc ListInstances(ListInstancesRequest) returns (ListInstancesResponse) {
    option (google.api.http) = {
      get: "/v1/{parent=projects/*}/instances"
    };
    option (google.api.method_signature) = "parent";
  }

  // Gets information about a particular instance.
  rpc GetInstance(GetInstanceRequest) returns (Instance) {
    option (google.api.http) = {
      get: "/v1/{name=projects/*/instances/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // Creates an instance and begins preparing it to begin serving. The
  // returned [long-running operation][google.longrunning.Operation]
  // can be used to track the progress of preparing the new
  // instance. The instance name is assigned by the caller. If the
  // named instance already exists, `CreateInstance` returns
  // `ALREADY_EXISTS`.
  //
  // Immediately upon completion of this request:
  //
  //   * The instance is readable via the API, with all requested attributes
  //     but no allocated resources. Its state is `CREATING`.
  //
  // Until completion of the returned operation:
  //
  //   * Cancelling the operation renders the instance immediately unreadable
  //     via the API.
  //   * The instance can be deleted.
  //   * All other attempts to modify the instance are rejected.
  //
  // Upon completion of the returned operation:
  //
  //   * Billing for all successfully-allocated resources begins (some types
  //     may have lower than the requested levels).
  //   * Databases can be created in the instance.
  //   * The instance's allocated resource levels are readable via the API.
  //   * The instance's state becomes `READY`.
  //
  // The returned [long-running operation][google.longrunning.Operation] will
  // have a name of the format `<instance_name>/operations/<operation_id>` and
  // can be used to track creation of the instance.  The
  // [metadata][google.longrunning.Operation.metadata] field type is
  // [CreateInstanceMetadata][google.spanner.admin.instance.v1.CreateInstanceMetadata].
  // The [response][google.longrunning.Operation.response] field type is
  // [Instance][google.spanner.admin.instance.v1.Instance], if successful.
  rpc CreateInstance(CreateInstanceRequest) returns (google.longrunning.Operation) {
    option (google.api.http) = {
      post: "/v1/{parent=projects/*}/instances"
      body: "*"
    };
    option (google.api.method_signature) = "parent,instance_id,instance";
    option (google.longrunning.operation_info) = {
      response_type: "google.spanner.admin.instance.v1.Instance"
      metadata_type: "google.spanner.admin.instance.v1.CreateInstanceMetadata"
    };
  }

  // Updates an instance, and begins allocating or releasing resources
  // as requested. The returned [long-running
  // operation][google.longrunning.Operation] can be used to track the
  // progress of updating the instance. If the named instance does not
  // exist, returns `NOT_FOUND`.
  //
  // Immediately upon completion of this request:
  //
  //   * For resource types for which a decrease in the instance's allocation
  //     has been requested, billing is based on the newly-requested level.
  //
  // Until completion of the returned operation:
  //
  //   * Cancelling the operation sets its metadata's
  //     [cancel_time][google.spanner.admin.instance.v1.UpdateInstanceMetadata.cancel_time], and begins
  //     restoring resources to their pre-request values. The operation
  //     is guaranteed to succeed at undoing all resource changes,
  //     after which point it terminates with a `CANCELLED` status.
  //   * All other attempts to modify the instance are rejected.
  //   * Reading the instance via the API continues to give the pre-request
  //     resource levels.
  //
  // Upon completion of the returned operation:
  //
  //   * Billing begins for all successfully-allocated resources (some types
  //     may have lower than the requested levels).
  //   * All newly-reserved resources are available for serving the instance's
  //     tables.
  //   * The instance's new resource levels are readable via the API.
  //
  // The returned [long-running operation][google.longrunning.Operation] will
  // have a name of the format `<instance_name>/operations/<operation_id>` and
  // can be used to track the instance modification.  The
  // [metadata][google.longrunning.Operation.metadata] field type is
  // [UpdateInstanceMetadata][google.spanner.admin.instance.v1.UpdateInstanceMetadata].
  // The [response][google.longrunning.Operation.response] field type is
  // [Instance][google.spanner.admin.instance.v1.Instance], if successful.
  //
  // Authorization requires `spanner.instances.update` permission on
  // resource [name][google.spanner.admin.instance.v1.Instance.name].
  rpc UpdateInstance(UpdateInstanceRequest) returns (google.longrunning.Operation) {
    option (google.api.http) = {
      patch: "/v1/{instance.name=projects/*/instances/*}"
      body: "*"
    };
    option (google.api.method_signature) = "instance,field_mask";
    option (google.longrunning.operation_info) = {
      response_type: "google.spanner.admin.instance.v1.Instance"
      metadata_type: "google.spanner.admin.instance.v1.UpdateInstanceMetadata"
    };
  }

  // Deletes an instance.
  //
  // Immediately upon completion of the request:
  //
  //   * Billing ceases for all of the instance's reserved resources.
  //
  // Soon afterward:
  //
  //   * The instance and *all of its databases* immediately and
  //     irrevocably disappear from the API. All data in the databases
  //     is permanently deleted.
  rpc DeleteInstance(DeleteInstanceRequest) returns (google.protobuf.Empty) {
    option (google.api.http) = {
      delete: "/v1/{name=projects/*/instances/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // Sets the access control policy on an instance resource. Replaces any
  // existing policy.
  //
  // Authorization requires `spanner.instances.setIamPolicy` on
  // [resource][google.iam.v1.SetIamPolicyRequest.resource].
  rpc SetIamPolicy(google.iam.v1.SetIamPolicyRequest) returns (google.iam.v1.Policy) {
    option (google.api.http) = {
      post: "/v1/{resource=projects/*/instances/*}:setIamPolicy"
      body: "*"
    };
    option (google.api.method_signature) = "resource,policy";
  }

  // Gets the access control policy for an instance resource. Returns an empty
  // policy if an instance exists but does not have a policy set.
  //
  // Authorization requires `spanner.instances.getIamPolicy` on
  // [resource][google.iam.v1.GetIamPolicyRequest.resource].
  rpc GetIamPolicy(google.iam.v1.GetIamPolicyRequest) returns (google.iam.v1.Policy) {
    option (google.api.http) = {
      post: "/v1/{resource=projects/*/instances/*}:getIamPolicy"
      body: "*"
    };
    option (google.api.method_signature) = "resource";
  }

  // Returns permissions that the caller has on the specified instance resource.
  //
  // Attempting this RPC on a non-existent Cloud Spanner instance resource will
  // result in a NOT_FOUND error if the user has `spanner.instances.list`
  // permission on the containing Google Cloud Project. Otherwise returns an
  // empty set of permissions.
  rpc TestIamPermissions(google.iam.v1.TestIamPermissionsRequest) returns (google.iam.v1.TestIamPermissionsResponse) {
    option (google.api.http) = {
      post: "/v1/{resource=projects/*/instances/*}:testIamPermissions"
      body: "*"
    };
    option (google.api.method_signature) = "resource,permissions";
  }
}

message ReplicaInfo {
  // Indicates the type of replica.  See the [replica types
  // documentation](https://cloud.google.com/spanner/docs/replication#replica_types)
  // for more details.
  enum ReplicaType {
    // Not specified.
    TYPE_UNSPECIFIED = 0;

    // Read-write replicas support both reads and writes. These replicas:
    //
    // * Maintain a full copy of your data.
    // * Serve reads.
    // * Can vote whether to commit a write.
    // * Participate in leadership election.
    // * Are eligible to become a leader.
    READ_WRITE = 1;

    // Read-only replicas only support reads (not writes). Read-only replicas:
    //
    // * Maintain a full copy of your data.
    // * Serve reads.
    // * Do not participate in voting to commit writes.
    // * Are not eligible to become a leader.
    READ_ONLY = 2;

    // Witness replicas don't support reads but do participate in voting to
    // commit writes. Witness replicas:
    //
    // * Do not maintain a full copy of data.
    // * Do not serve reads.
    // * Vote whether to commit writes.
    // * Participate in leader election but are not eligible to become leader.
    WITNESS = 3;
  }

  // The location of the serving resources, e.g. "us-central1".
  string location = 1;

  // The type of replica.
  ReplicaType type = 2;

  // If true, this location is designated as the default leader location where
  // leader replicas are placed. See the [region types
  // documentation](https://cloud.google.com/spanner/docs/instances#region_types)
  // for more details.
  bool default_leader_location = 3;
}

// A possible configuration for a Cloud Spanner instance. Configurations
// define the geographic placement of nodes and their replication.
message InstanceConfig {
  option (google.api.resource) = {
    type: "spanner.googleapis.com/InstanceConfig"
    pattern: "projects/{project}/instanceConfigs/{instance_config}"
  };

  // A unique identifier for the instance configuration.  Values
  // are of the form
  // `projects/<project>/instanceConfigs/[a-z][-a-z0-9]*`
  string name = 1;

  // The name of this instance configuration as it appears in UIs.
  string display_name = 2;

  // The geographic placement of nodes in this instance configuration and their
  // replication properties.
  repeated ReplicaInfo replicas = 3;

  // Allowed values of the “default_leader” schema option for databases in
  // instances that use this instance configuration.
  repeated string leader_options = 4;
}

// An isolated set of Cloud Spanner resources on which databases can be hosted.
message Instance {
  option (google.api.resource) = {
    type: "spanner.googleapis.com/Instance"
    pattern: "projects/{project}/instances/{instance}"
  };

  // Indicates the current state of the instance.
  enum State {
    // Not specified.
    STATE_UNSPECIFIED = 0;

    // The instance is still being created. Resources may not be
    // available yet, and operations such as database creation may not
    // work.
    CREATING = 1;

    // The instance is fully created and ready to do work such as
    // creating databases.
    READY = 2;
  }

  // Required. A unique identifier for the instance, which cannot be changed
  // after the instance is created. Values are of the form
  // `projects/<project>/instances/[a-z][-a-z0-9]*[a-z0-9]`. The final
  // segment of the name must be between 2 and 64 characters in length.
  string name = 1;

  // Required. The name of the instance's configuration. Values are of the form
  // `projects/<project>/instanceConfigs/<configuration>`. See
  // also [InstanceConfig][google.spanner.admin.instance.v1.InstanceConfig] and
  // [ListInstanceConfigs][google.spanner.admin.instance.v1.InstanceAdmin.ListInstanceConfigs].
  string config = 2 [(google.api.resource_reference) = {
                       type: "spanner.googleapis.com/InstanceConfig"
                     }];

  // Required. The descriptive name for this instance as it appears in UIs.
  // Must be unique per project and between 4 and 30 characters in length.
  string display_name = 3;

  // Required. The number of nodes allocated to this instance. This may be zero
  // in API responses for instances that are not yet in state `READY`.
  //
  // See [the
  // documentation](https://cloud.google.com/spanner/docs/instances#node_count)
  // for more information about nodes.
  int32 node_count = 5;

  // The number of processing units allocated to this instance. At most one of
  // processing_units or node_count should be present in the message. This may
  // be zero in API responses for instances that are not yet in state `READY`.
  int32 processing_units = 9;

  // Output only. The current instance state. For
  // [CreateInstance][google.spanner.admin.instance.v1.InstanceAdmin.CreateInstance], the state must be
  // either omitted or set to `CREATING`. For
  // [UpdateInstance][google.spanner.admin.instance.v1.InstanceAdmin.UpdateInstance], the state must be
  // either omitted or set to `READY`.
  State state = 6 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Cloud Labels are a flexible and lightweight mechanism for organizing cloud
  // resources into groups that reflect a customer's organizational needs and
  // deployment strategies. Cloud Labels can be used to filter collections of
  // resources. They can be used to control how resource metrics are aggregated.
  // And they can be used as arguments to policy management rules (e.g. route,
  // firewall, load balancing, etc.).
  //
  //  * Label keys must be between 1 and 63 characters long and must conform to
  //    the following regular expression: `[a-z]([-a-z0-9]*[a-z0-9])?`.
  //  * Label values must be between 0 and 63 characters long and must conform
  //    to the regular expression `([a-z]([-a-z0-9]*[a-z0-9])?)?`.
  //  * No more than 64 labels can be associated with a given resource.
  //
  // See https://goo.gl/xmQnxf for more information on and examples of labels.
  //
  // If you plan to use labels in your own code, please note that additional
  // characters may be allowed in the future. And so you are advised to use an
  // internal label representation, such as JSON, which doesn't rely upon
  // specific characters being disallowed.  For example, representing labels
  // as the string:  name + "_" + value  would prove problematic if we were to
  // allow "_" in a future release.
  map<string, string> labels = 7;

  // Deprecated. This field is not populated.
  repeated string endpoint_uris = 8;
}

// The request for [ListInstanceConfigs][google.spanner.admin.instance.v1.InstanceAdmin.ListInstanceConfigs].
message ListInstanceConfigsRequest {
  // Required. The name of the project for which a list of supported instance
  // configurations is requested. Values are of the form
  // `projects/<project>`.
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "cloudresourcemanager.googleapis.com/Project"
    }
  ];

  // Number of instance configurations to be returned in the response. If 0 or
  // less, defaults to the server's maximum allowed page size.
  int32 page_size = 2;

  // If non-empty, `page_token` should contain a
  // [next_page_token][google.spanner.admin.instance.v1.ListInstanceConfigsResponse.next_page_token]
  // from a previous [ListInstanceConfigsResponse][google.spanner.admin.instance.v1.ListInstanceConfigsResponse].
  string page_token = 3;
}

// The response for [ListInstanceConfigs][google.spanner.admin.instance.v1.InstanceAdmin.ListInstanceConfigs].
message ListInstanceConfigsResponse {
  // The list of requested instance configurations.
  repeated InstanceConfig instance_configs = 1;

  // `next_page_token` can be sent in a subsequent
  // [ListInstanceConfigs][google.spanner.admin.instance.v1.InstanceAdmin.ListInstanceConfigs] call to
  // fetch more of the matching instance configurations.
  string next_page_token = 2;
}

// The request for
// [GetInstanceConfigRequest][google.spanner.admin.instance.v1.InstanceAdmin.GetInstanceConfig].
message GetInstanceConfigRequest {
  // Required. The name of the requested instance configuration. Values are of
  // the form `projects/<project>/instanceConfigs/<config>`.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "spanner.googleapis.com/InstanceConfig"
    }
  ];
}

// The request for [GetInstance][google.spanner.admin.instance.v1.InstanceAdmin.GetInstance].
message GetInstanceRequest {
  // Required. The name of the requested instance. Values are of the form
  // `projects/<project>/instances/<instance>`.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "spanner.googleapis.com/Instance"
    }
  ];

  // If field_mask is present, specifies the subset of [Instance][google.spanner.admin.instance.v1.Instance] fields that
  // should be returned.
  // If absent, all [Instance][google.spanner.admin.instance.v1.Instance] fields are returned.
  google.protobuf.FieldMask field_mask = 2;
}

// The request for [CreateInstance][google.spanner.admin.instance.v1.InstanceAdmin.CreateInstance].
message CreateInstanceRequest {
  // Required. The name of the project in which to create the instance. Values
  // are of the form `projects/<project>`.
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "cloudresourcemanager.googleapis.com/Project"
    }
  ];

  // Required. The ID of the instance to create.  Valid identifiers are of the
  // form `[a-z][-a-z0-9]*[a-z0-9]` and must be between 2 and 64 characters in
  // length.
  string instance_id = 2 [(google.api.field_behavior) = REQUIRED];

  // Required. The instance to create.  The name may be omitted, but if
  // specified must be `<parent>/instances/<instance_id>`.
  Instance instance = 3 [(google.api.field_behavior) = REQUIRED];
}

// The request for [ListInstances][google.spanner.admin.instance.v1.InstanceAdmin.ListInstances].
message ListInstancesRequest {
  // Required. The name of the project for which a list of instances is
  // requested. Values are of the form `projects/<project>`.
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "cloudresourcemanager.googleapis.com/Project"
    }
  ];

  // Number of instances to be returned in the response. If 0 or less, defaults
  // to the server's maximum allowed page size.
  int32 page_size = 2;

  // If non-empty, `page_token` should contain a
  // [next_page_token][google.spanner.admin.instance.v1.ListInstancesResponse.next_page_token] from a
  // previous [ListInstancesResponse][google.spanner.admin.instance.v1.ListInstancesResponse].
  string page_token = 3;

  // An expression for filtering the results of the request. Filter rules are
  // case insensitive. The fields eligible for filtering are:
  //
  //   * `name`
  //   * `display_name`
  //   * `labels.key` where key is the name of a label
  //
  // Some examples of using filters are:
  //
  //   * `name:*` --> The instance has a name.
  //   * `name:Howl` --> The instance's name contains the string "howl".
  //   * `name:HOWL` --> Equivalent to above.
  //   * `NAME:howl` --> Equivalent to above.
  //   * `labels.env:*` --> The instance has the label "env".
  //   * `labels.env:dev` --> The instance has the label "env" and the value of
  //                        the label contains the string "dev".
  //   * `name:howl labels.env:dev` --> The instance's name contains "howl" and
  //                                  it has the label "env" with its value
  //                                  containing "dev".
  string filter = 4;
}

// The response for [ListInstances][google.spanner.admin.instance.v1.InstanceAdmin.ListInstances].
message ListInstancesResponse {
  // The list of requested instances.
  repeated Instance instances = 1;

  // `next_page_token` can be sent in a subsequent
  // [ListInstances][google.spanner.admin.instance.v1.InstanceAdmin.ListInstances] call to fetch more
  // of the matching instances.
  string next_page_token = 2;
}

// The request for [UpdateInstance][google.spanner.admin.instance.v1.InstanceAdmin.UpdateInstance].
message UpdateInstanceRequest {
  // Required. The instance to update, which must always include the instance
  // name.  Otherwise, only fields mentioned in [field_mask][google.spanner.admin.instance.v1.UpdateInstanceRequest.field_mask] need be included.
  Instance instance = 1 [(google.api.field_behavior) = REQUIRED];

  // Required. A mask specifying which fields in [Instance][google.spanner.admin.instance.v1.Instance] should be updated.
  // The field mask must always be specified; this prevents any future fields in
  // [Instance][google.spanner.admin.instance.v1.Instance] from being erased accidentally by clients that do not know
  // about them.
  google.protobuf.FieldMask field_mask = 2 [(google.api.field_behavior) = REQUIRED];
}

// The request for [DeleteInstance][google.spanner.admin.instance.v1.InstanceAdmin.DeleteInstance].
message DeleteInstanceRequest {
  // Required. The name of the instance to be deleted. Values are of the form
  // `projects/<project>/instances/<instance>`
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "spanner.googleapis.com/Instance"
    }
  ];
}

// Metadata type for the operation returned by
// [CreateInstance][google.spanner.admin.instance.v1.InstanceAdmin.CreateInstance].
message CreateInstanceMetadata {
  // The instance being created.
  Instance instance = 1;

  // The time at which the
  // [CreateInstance][google.spanner.admin.instance.v1.InstanceAdmin.CreateInstance] request was
  // received.
  google.protobuf.Timestamp start_time = 2;

  // The time at which this operation was cancelled. If set, this operation is
  // in the process of undoing itself (which is guaranteed to succeed) and
  // cannot be cancelled again.
  google.protobuf.Timestamp cancel_time = 3;

  // The time at which this operation failed or was completed successfully.
  google.protobuf.Timestamp end_time = 4;
}

// Metadata type for the operation returned by
// [UpdateInstance][google.spanner.admin.instance.v1.InstanceAdmin.UpdateInstance].
message UpdateInstanceMetadata {
  // The desired end state of the update.
  Instance instance = 1;

  // The time at which [UpdateInstance][google.spanner.admin.instance.v1.InstanceAdmin.UpdateInstance]
  // request was received.
  google.protobuf.Timestamp start_time = 2;

  // The time at which this operation was cancelled. If set, this operation is
  // in the process of undoing itself (which is guaranteed to succeed) and
  // cannot be cancelled again.
  google.protobuf.Timestamp cancel_time = 3;

  // The time at which this operation failed or was completed successfully.
  google.protobuf.Timestamp end_time = 4;
}
