# frozen_string_literal: true # Copyright 2018 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 # # https://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. require "google/cloud/bigtable/version" require "google/cloud/bigtable/errors" require "google/cloud/bigtable/credentials" require "google/cloud/bigtable/admin/v2/bigtable_instance_admin_client" require "google/cloud/bigtable/admin/v2/bigtable_table_admin_client" require "google/cloud/bigtable/v2/bigtable_client" module Google module Cloud module Bigtable # @private # gRPC Cloud Bigtable service, including API methods. class Service # @private attr_accessor :project_id, :credentials, :host, :timeout, :client_config # @private # Creates a new Service instance. # # @param project_id [String] Project identifier # @param credentials [Google::Auth::Credentials, String, Hash, GRPC::Core::Channel, # GRPC::Core::ChannelCredentials, Proc] # The means for authenticating requests made by the client. This parameter can be one of the following types. # `Google::Auth::Credentials` uses the properties of its represented keyfile for authenticating requests made # by this client. # `String` will be treated as the path to the keyfile to use to construct credentials for this client. # `Hash` will be treated as the contents of a keyfile to use to construct credentials for this client. # `GRPC::Core::Channel` will be used to make calls through. # `GRPC::Core::ChannelCredentials` will be used to set up the gRPC client. The channel credentials should # already be composed with a `GRPC::Core::CallCredentials` object. # `Proc` will be used as an updater_proc for the gRPC channel. The proc transforms the metadata for requests, # generally, to give OAuth credentials. # @param timeout [Integer] # The default timeout, in seconds, for calls made through this client. # @param client_config [Hash] # A hash for call options for each method. See Google::Gax#construct_settings for the structure of this data. # Falls back to the default config if not specified or the specified config is missing data points. # def initialize project_id, credentials, host: nil, timeout: nil, client_config: nil @project_id = project_id @credentials = credentials @host = host @timeout = timeout @client_config = client_config || {} end def channel default_host require "grpc" GRPC::Core::Channel.new((host || default_host), chan_args, chan_creds) end def chan_args { "grpc.max_send_message_length" => -1, "grpc.max_receive_message_length" => -1, "grpc.service_config_disable_resolution" => 1 } end def chan_creds return credentials if insecure? require "grpc" GRPC::Core::ChannelCredentials.new.compose GRPC::Core::CallCredentials.new credentials.client.updater_proc end ## # Creates or returns an instance of an instance admin client. # # @return [Google::Cloud::Bigtable::Admin::V2::BigtableInstanceAdminClient] # def instances return mocked_instances if mocked_instances @instances ||= Admin::V2::BigtableInstanceAdminClient.new( credentials: channel(Admin::V2::BigtableInstanceAdminClient::SERVICE_ADDRESS), timeout: timeout, client_config: client_config, lib_name: "gccl", lib_version: Google::Cloud::Bigtable::VERSION ) end attr_accessor :mocked_instances ## # Creates or returns an instance of a table admin client. # # @return [Google::Cloud::Bigtable::Admin::V2::BigtableTableAdminClient] # def tables return mocked_tables if mocked_tables @tables ||= Admin::V2::BigtableTableAdminClient.new( credentials: channel(Admin::V2::BigtableTableAdminClient::SERVICE_ADDRESS), timeout: timeout, client_config: client_config, lib_name: "gccl", lib_version: Google::Cloud::Bigtable::VERSION ) end attr_accessor :mocked_tables ## # Creates an instance of a data client. # # @return [Google::Cloud::Bigtable::V2::BigtableClient] # def client return mocked_client if mocked_client @client ||= V2::BigtableClient.new( credentials: channel(V2::BigtableClient::SERVICE_ADDRESS), timeout: timeout, client_config: client_config, lib_name: "gccl", lib_version: Google::Cloud::Bigtable::VERSION ) end attr_accessor :mocked_client def insecure? credentials == :this_channel_is_insecure end ## # Creates an instance within a project. # # @param instance_id [String] # The permanent identifier to be used for the new instance. # # @param instance [Google::Bigtable::Admin::V2::Instance | Hash] # @param clusters [Hash{String => Google::Bigtable::Admin::V2::Cluster | Hash}] # The clusters to be created in the instance. # Note that the cluster ID is the last segment of a cluster name. In the # following cluster name, 'mycluster' is the cluster ID: # +projects/myproject/instances/myinstance/clusters/mycluster+. # Alternatively, provide a hash in the form of `Google::Bigtable::Admin::V2::Cluster` # @return [Google::Gax::Operation] # def create_instance instance_id, instance, clusters execute do instances.create_instance project_path, instance_id, instance, clusters end end ## # Lists the instances in a project. # # @param token [String] # The value of +next_page_token+ returned by a previous call. # @return [Google::Bigtable::Admin::V2::ListInstancesResponse] # def list_instances token: nil execute do instances.list_instances project_path, page_token: token end end ## # Gets information about an instance. # # @param instance_id [String] # Unique ID of the requested instance. # @return [Google::Bigtable::Admin::V2::Instance] # def get_instance instance_id execute do instances.get_instance instance_path(instance_id) end end ## # Partially updates an instance. # # @param instance [Google::Bigtable::Admin::V2::Instance | Hash] # The instance that will (partially) replace the current value. # Alternatively, provide a hash in the form of `Google::Bigtable::Admin::V2::Instance. # @param update_mask [Google::Protobuf::FieldMask | Hash] # List of instance properties to be replaced. # Must be explicitly set. # Alternatively, provide a hash in the form of `Google::Protobuf::FieldMask`. # @return [Google::Gax::Operation] # def partial_update_instance instance, update_mask execute do instances.partial_update_instance instance, update_mask end end ## # Deletes an instance from a project. # # @param instance_id [String] # Unique ID of the instance to be deleted. # def delete_instance instance_id execute do instances.delete_instance( instance_path(instance_id) ) end end ## # Creates a cluster within an instance. # # @param instance_id [String] # Unique ID of the instance in which to create the new cluster # @param cluster_id [String] # Unique permanent identifier for the new cluster # @param cluster [Google::Bigtable::Admin::V2::Cluster | Hash] # The cluster to be created. # Alternatively, provide a hash in the form of `Google::Bigtable::Admin::V2::Cluster` # # @return [Google::Gax::Operation] # def create_cluster instance_id, cluster_id, cluster cluster.location = location_path cluster.location unless cluster.location == "" execute do instances.create_cluster instance_path(instance_id), cluster_id, cluster end end ## # Lists information about clusters in an instance. # # @param instance_id [String] # Unique ID of the instance for which a list of clusters is requested. # @param token [String] # The value of +next_page_token+ returned by a previous call. # @return [Google::Bigtable::Admin::V2::ListClustersResponse] # def list_clusters instance_id, token: nil execute do instances.list_clusters instance_path(instance_id), page_token: token end end ## # Gets information about a cluster. # # @param instance_id [String] # Unique ID of the instance the cluster is in. # @param cluster_id [String] # Unique ID of the requested cluster. # @return [Google::Bigtable::Admin::V2::Cluster] # def get_cluster instance_id, cluster_id execute do instances.get_cluster cluster_path(instance_id, cluster_id) end end ## # Updates a cluster within an instance. # # @param instance_id [String] # Unique ID of the instance the cluster is in. # @param cluster_id [String] # Unique ID of the cluster. # @param location [String] # Location of this cluster's nodes and storage. For best # performance, clients should be located as close as possible to this # cluster. Requird format for the location string: # +projects/<project>/locations/<zone>+. # @param serve_nodes [Integer] # The number of nodes allocated to this cluster. More nodes enable higher # throughput and more consistent performance. # @return [Google::Gax::Operation] # def update_cluster instance_id, cluster_id, location, serve_nodes execute do instances.update_cluster cluster_path(instance_id, cluster_id), location, serve_nodes end end ## # Deletes a cluster from an instance. # # @param instance_id [String] # Unique ID of the instance the cluster is in. # @param cluster_id [String] # Unique ID of the cluster to be deleted. # def delete_cluster instance_id, cluster_id execute do instances.delete_cluster cluster_path(instance_id, cluster_id) end end ## # Creates a new table in the specified instance. # Optionally, creates the table with a full set of initial column families. # # @param instance_id [String] # Unique ID of the instance to create the table in. # @param table_id [String] # Unique, permanent identifier for the new table. # @param table [Google::Bigtable::Admin::V2::Table | Hash] # The table to create. # Alternatively, provide a hash in the form of `Google::Bigtable::Admin::V2::Table`. # @param initial_splits [Array<Google::Bigtable::Admin::V2::CreateTableRequest::Split | Hash>] # The optional list of row keys that will be used to initially split the # table into several tablets (tablets are similar to HBase regions). # Given two split keys, +s1+ and +s2+, three tablets will be created, # spanning the key ranges: +[, s1), [s1, s2), [s2, )+. # # Example: # # * Row keys := +["a", "apple", "custom", "customer_1", "customer_2",+ # +"other", "zz"]+ # * initial_split_keys := +["apple", "customer_1", "customer_2", "other"]+ # * Key assignment: # * Tablet 1 +[, apple) => {"a"}.+ # * Tablet 2 +[apple, customer_1) => {"apple", "custom"}.+ # * Tablet 3 +[customer_1, customer_2) => {"customer_1"}.+ # * Tablet 4 +[customer_2, other) => {"customer_2"}.+ # * Tablet 5 +[other, ) => {"other", "zz"}.+ # Alternatively, provide a hash in the form of # `Google::Bigtable::Admin::V2::CreateTableRequest::Split` # @return [Google::Bigtable::Admin::V2::Table] # def create_table instance_id, table_id, table, initial_splits: nil initial_splits = initial_splits.map { |key| { key: key } } if initial_splits execute do tables.create_table instance_path(instance_id), table_id, table, initial_splits: initial_splits end end ## # Lists all tables in an instance. # # @param instance_id [String] # Unique ID of the instance for which tables should be listed. # @param view [Google::Bigtable::Admin::V2::Table::View] # View to be applied to the returned tables' fields. # Defaults to +NAME_ONLY+ if unspecified; no others are currently supported. # @return [Google::Gax::PagedEnumerable<Google::Bigtable::Admin::V2::Table>] # An enumerable of Google::Bigtable::Admin::V2::Table instances. # See Google::Gax::PagedEnumerable documentation for other # operations such as per-page iteration or access to the response. # def list_tables instance_id, view: nil execute do tables.list_tables instance_path(instance_id), view: view end end ## # Gets metadata about the specified table. # # @param instance_id [String] # Unique ID of the instance the table is in. # @param table_id [String] # Unique ID of the requested table. # @param view [Google::Bigtable::Admin::V2::Table::View] # View to be applied to the returned table's fields. # Defaults to +SCHEMA_VIEW+ if unspecified. # @return [Google::Bigtable::Admin::V2::Table] # def get_table instance_id, table_id, view: nil execute do tables.get_table table_path(instance_id, table_id), view: view end end ## # Permanently deletes a table and all of its data. # # @param instance_id [String] # Unique ID of the instance the table is in. # @param table_id [String] # Unique ID of the table to be deleted. # def delete_table instance_id, table_id execute do tables.delete_table table_path(instance_id, table_id) end end ## # Performs a series of column family modifications on the specified table. # Either all or none of the modifications will occur before this method # returns. Data requests received prior to completion of this method may reach a table # in which only some modifications have taken effect. # # @param instance_id [String] # Unique ID of the instance the table is in. # @param table_id [String] # Unique ID of the table whose families should be modified. # @param modifications [Array<Google::Bigtable::Admin::V2::ModifyColumnFamiliesRequest::Modification | Hash>] # Modifications to be atomically applied to the specified table's families. # Entries are applied in order, meaning that earlier modifications can be # masked by later ones (in the case of repeated updates to the same family, # for example). # Alternatively, provide a hash in the form of # `Google::Bigtable::Admin::V2::ModifyColumnFamiliesRequest::Modification`. # @return [Google::Bigtable::Admin::V2::Table] # def modify_column_families instance_id, table_id, modifications execute do tables.modify_column_families table_path(instance_id, table_id), modifications end end ## # Generates a consistency token for a table. # The consistency token can be be used in CheckConsistency to check whether # mutations to the table that finished before this call started have been replicated. # The token will be available for 90 days. # # @param instance_id [String] # Unique ID of the instance the table is in. # @param table_id [String] # Unique ID of the table the consistency token is for. # @return [Google::Bigtable::Admin::V2::GenerateConsistencyTokenResponse] # def generate_consistency_token instance_id, table_id execute do tables.generate_consistency_token table_path(instance_id, table_id) end end ## # Checks replication consistency based on a consistency token. # Determines if replication has caught up, based on the conditions in the token # and the check request. # # @param instance_id [String] # Unique ID of the instance the table is in. # @param table_id [String] # Unique ID of the table to check for replication consistency. # @param token [String] Consistency token # The token created for the table using GenerateConsistencyToken. # @return [Google::Bigtable::Admin::V2::CheckConsistencyResponse] # def check_consistency instance_id, table_id, token execute do tables.check_consistency table_path(instance_id, table_id), token end end ## # Permanently deletes a row range from a table. The request can # specify whether to delete all rows in a table or only rows that match a # particular row key prefix. # # @param instance_id [String] # Unique ID of the instance the table is in. # @param table_id [String] # Unique ID of the table to delete a range of rows from. # @param row_key_prefix [String] # All rows whose row keys start with this row key prefix will be deleted. # Prefix cannot be zero length. # @param delete_all_data_from_table [true, false] # If true, delete all rows in the table. Setting this to false is a no-op. # @param timeout [Integer] # Sets the API call timeout if deadline exceeds exception. # def drop_row_range instance_id, table_id, row_key_prefix: nil, delete_all_data_from_table: nil, timeout: nil call_options = nil # Pass a timeout with a larger value if the drop operation throws # an error for timeout time. if timeout retry_options = Google::Gax::RetryOptions.new( [], Google::Gax::BackoffSettings.new(0, 0, 0, timeout * 1000, 0, 0, 0) ) call_options = Google::Gax::CallOptions.new retry_options: retry_options end execute do tables.drop_row_range( table_path(instance_id, table_id), row_key_prefix: row_key_prefix, delete_all_data_from_table: delete_all_data_from_table, options: call_options ) end end ## # Creates an app profile within an instance. # # @param instance_id [String] # Unique ID of the instance. # @param app_profile_id [String] # The permanent identifier for the new app profile within its # instance. # @param app_profile [Google::Bigtable::Admin::V2::AppProfile | Hash] # The app profile to be created. # Alternatively, provide a hash in the form of `Google::Bigtable::Admin::V2::AppProfile`. # @param ignore_warnings [Boolean] # If true, ignore safety checks when creating the app profile. # @return [Google::Bigtable::Admin::V2::AppProfile] # def create_app_profile instance_id, app_profile_id, app_profile, ignore_warnings: nil execute do instances.create_app_profile( instance_path(instance_id), app_profile_id, app_profile, ignore_warnings: ignore_warnings ) end end ## # Gets information about an app profile. # # @param instance_id [String] # Unique ID of the instance. # @param app_profile_id [String] # Unique ID of the requested app profile. # @return [Google::Bigtable::Admin::V2::AppProfile] # def get_app_profile instance_id, app_profile_id execute do instances.get_app_profile app_profile_path(instance_id, app_profile_id) end end ## # Lists information about app profiles in an instance. # # @param instance_id [String] # Unique ID of the instance # @return [Google::Gax::PagedEnumerable<Google::Bigtable::Admin::V2::AppProfile>] # An enumerable of Google::Bigtable::Admin::V2::AppProfile instances. # See Google::Gax::PagedEnumerable documentation for other # operations such as per-page iteration or access to the response # object. # def list_app_profiles instance_id execute do instances.list_app_profiles instance_path(instance_id) end end ## # Updates an app profile within an instance. # # @param app_profile [Google::Bigtable::Admin::V2::AppProfile | Hash] # The app profile that will (partially) replace the current value. # Alternatively, provide a hash in the form of # `Google::Bigtable::Admin::V2::AppProfile`. # @param update_mask [Google::Protobuf::FieldMask | Hash] # The subset of app profile fields that should be replaced. # If unset, all fields will be replaced. # Alternatively, provide a hash similar to `Google::Protobuf::FieldMask`. # @param ignore_warnings [Boolean] # If true, ignore safety checks when updating the app profile. # @return [Google::Longrunning::Operation] # def update_app_profile app_profile, update_mask, ignore_warnings: nil execute do instances.update_app_profile app_profile, update_mask, ignore_warnings: ignore_warnings end end ## # Deletes an app profile from an instance. # # @param instance_id [String] # Unique ID of the instance. # @param app_profile_id [String] # Unique ID of the app profile to be deleted. # @param ignore_warnings [Boolean] # If true, ignore safety checks when deleting the app profile. # def delete_app_profile instance_id, app_profile_id, ignore_warnings: nil execute do instances.delete_app_profile app_profile_path(instance_id, app_profile_id), ignore_warnings end end ## # Gets the access control policy for an instance resource. Returns an empty # policy if an instance exists but does not have a policy set. # # @param instance_id [String] # Unique ID of the instance for which the policy is being requested. # @return [Google::Iam::V1::Policy] # def get_instance_policy instance_id execute do instances.get_iam_policy instance_path(instance_id) end end ## # Sets the access control policy on an instance resource. Replaces any # existing policy. # # @param instance_id [String] # Unique ID of the instance the policy is for. # @param policy [Google::Iam::V1::Policy | Hash] # REQUIRED: The complete policy to be applied to the +resource+. The size of # the policy is limited to a few 10s of KB. An empty policy is valid # for Cloud Bigtable, but certain Cloud Platform services (such as Projects) # might reject an empty policy. # Alternatively, provide a hash similar to `Google::Iam::V1::Policy`. # @return [Google::Iam::V1::Policy] # def set_instance_policy instance_id, policy execute do instances.set_iam_policy instance_path(instance_id), policy end end ## # Returns permissions that the caller has for the specified instance resource. # # @param instance_id [String] # The instance ID that the policy detail is being requested for. # @param permissions [Array<String>] # The set of permissions to check for the +resource+. Permissions with # wildcards (such as '*' or 'storage.*') are not allowed. For more # information see # [IAM Overview](https://cloud.google.com/iam/docs/overview#permissions). # @return [Google::Iam::V1::TestIamPermissionsResponse] # def test_instance_permissions instance_id, permissions execute do instances.test_iam_permissions instance_path(instance_id), permissions end end def read_rows instance_id, table_id, app_profile_id: nil, rows: nil, filter: nil, rows_limit: nil # execute is not used because error handling is in ReadOperations#read_rows client.read_rows table_path(instance_id, table_id), rows: rows, filter: filter, rows_limit: rows_limit, app_profile_id: app_profile_id end def sample_row_keys table_name, app_profile_id: nil execute do client.sample_row_keys table_name, app_profile_id: app_profile_id end end def mutate_row table_name, row_key, mutations, app_profile_id: nil execute do client.mutate_row table_name, row_key, mutations, app_profile_id: app_profile_id end end def mutate_rows table_name, entries, app_profile_id: nil execute do client.mutate_rows table_name, entries, app_profile_id: app_profile_id end end def check_and_mutate_row table_name, row_key, app_profile_id: nil, predicate_filter: nil, true_mutations: nil, false_mutations: nil execute do client.check_and_mutate_row table_name, row_key, app_profile_id: app_profile_id, predicate_filter: predicate_filter, true_mutations: true_mutations, false_mutations: false_mutations end end def read_modify_write_row table_name, row_key, rules, app_profile_id: nil execute do client.read_modify_write_row table_name, row_key, rules, app_profile_id: app_profile_id end end ## # Executes the API call and wrap errors to {Google::Cloud::Error}. # # @raise [Google::Cloud::Error] # def execute yield rescue Google::Gax::GaxError => e raise Google::Cloud::Error.from_error(e.cause) rescue GRPC::BadStatus => e raise Google::Cloud::Error.from_error(e) end ## # Creates a formatted project path. # # @return [String] # Formatted project path # +projects/<project>+ # def project_path Admin::V2::BigtableInstanceAdminClient.project_path project_id end ## # Creates a formatted instance path. # # @param instance_id [String] # @return [String] # Formatted instance path # +projects/<project>/instances/[a-z][a-z0-9\\-]+[a-z0-9]+. # def instance_path instance_id Admin::V2::BigtableInstanceAdminClient.instance_path project_id, instance_id end ## # Creates a formatted cluster path. # # @param instance_id [String] # @param cluster_id [String] # @return [String] # Formatted cluster path # +projects/<project>/instances/<instance>/clusters/<cluster>+. # def cluster_path instance_id, cluster_id Admin::V2::BigtableInstanceAdminClient.cluster_path project_id, instance_id, cluster_id end ## # Creates a formatted location path. # # @param location [String] # zone name i.e us-east1-b # @return [String] # Formatted location path # +projects/<project_id>/locations/<location>+. # def location_path location Admin::V2::BigtableInstanceAdminClient.location_path project_id, location end ## # Creates a formatted table path. # # @param table_id [String] # @return [String] # Formatted table path # +projects/<project>/instances/<instance>/tables/<table>+ # def table_path instance_id, table_id Admin::V2::BigtableTableAdminClient.table_path project_id, instance_id, table_id end ## # Creates a formatted app profile path. # # @param instance_id [String] # @param app_profile_id [String] # @return [String] # Formatted snapshot path # +projects/<project>/instances/<instance>/appProfiles/<app_profile>+ # def app_profile_path instance_id, app_profile_id Admin::V2::BigtableInstanceAdminClient.app_profile_path project_id, instance_id, app_profile_id end ## # Inspects the service object. # @return [String] # def inspect "#{self.class}(#{@project_id})" end end end end end