google-cloud-bigtable 2.12.0 → 2.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d532accadd2ab9206259a83bc75b52a460d8e15e2253c81ee9f7124fdefbfa83
4
- data.tar.gz: d1bee0fb74cf2522095176d827323731d347e6a60575f3b2beb1f664879aa616
3
+ metadata.gz: 95305d13ed4a835f5f0568999568f9b7ffb0034776d9fd626bf9df8dc00ae241
4
+ data.tar.gz: 97be595610413344edd7b183dc30d79e08139d785578a6aa643a8a27c9078b29
5
5
  SHA512:
6
- metadata.gz: 3c7164cb81c2f57bbfadb426cc1038fe1fe817cb102e6305e468c41034e0f081e4e13183c6490b49c93203b8390b4415e8288e84a3c2a330beb2a0f4b80b0fae
7
- data.tar.gz: e8c61bb38bc9a0297cbf2954323239bd4ebd95a4578627b1a1707683b7e40b35e50bfd3e5f2dd8d90389330cad1562e88cd0de946006a71500db0060d4d00143
6
+ metadata.gz: d7e0b410f8cc24923495e7b6fdf754f353139228fbd79b121ba5f92da514b10388c9debe69b82aea68a2572612a5ad3a3bb8627dbb873e8176ab681de3e98fc2
7
+ data.tar.gz: 5f5cbc2a3e60ae44725321079ae07028c1932ca8847b19b0715429adf8158c3f294cf0236d94bcac7629c70ed36ab06508d48ce3963f0bad674f5d845251ae43
data/AUTHENTICATION.md CHANGED
@@ -46,6 +46,12 @@ code.
46
46
 
47
47
  **Credentials** are discovered in the following order:
48
48
 
49
+ > [!WARNING]
50
+ > If you accept a credential configuration (JSON file or Hash) from an
51
+ > external source for authentication to Google Cloud, you must validate it before
52
+ > providing it to a Google API client library. Providing an unvalidated credential
53
+ > configuration to Google APIs can compromise the security of your systems and data.
54
+
49
55
  1. Specify credentials in method arguments
50
56
  2. Specify credentials in configuration
51
57
  3. Discover credentials path in environment variables
@@ -99,11 +105,16 @@ The **Project ID** and the path to the **Credentials JSON** file can be configur
99
105
  instead of placing them in environment variables or providing them as arguments.
100
106
 
101
107
  ```ruby
108
+ require "googleauth"
102
109
  require "google/cloud/bigtable"
103
110
 
111
+ credentials = ::Google::Auth::ServiceAccountCredentials.make_creds(
112
+ json_key_io: ::File.open("/path/to/keyfile.json")
113
+ )
114
+
104
115
  Google::Cloud::Bigtable.configure do |config|
105
116
  config.project_id = "my-project-id"
106
- config.credentials = "path/to/keyfile.json"
117
+ config.credentials = credentials
107
118
  end
108
119
 
109
120
  client = Google::Cloud::Bigtable.new
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Release History
2
2
 
3
+ ### 2.12.2 (2025-11-04)
4
+
5
+ #### Documentation
6
+
7
+ * add warning about loading unvalidated credentials ([#32121](https://github.com/googleapis/google-cloud-ruby/issues/32121))
8
+
9
+ ### 2.12.1 (2025-08-12)
10
+
11
+ #### Bug Fixes
12
+
13
+ * Fix mutate rows logic to handle errors ([#30766](https://github.com/googleapis/google-cloud-ruby/issues/30766))
14
+
3
15
  ### 2.12.0 (2025-02-25)
4
16
 
5
17
  #### Features
@@ -94,12 +94,23 @@ module Google
94
94
  # or if family name or column qualifier are empty
95
95
  #
96
96
  def validate_new_row
97
- raise_if row.key, "A new row cannot have existing state"
98
- raise_if chunk.row_key.empty?, "A row key must be set"
99
- raise_if chunk.reset_row, "A new row cannot be reset"
100
- raise_if last_key == chunk.row_key, "A commit happened but the same key followed"
101
- raise_if chunk.family_name.nil?, "A family must be set"
102
- raise_if chunk.qualifier.nil?, "A column qualifier must be set"
97
+ validations = [
98
+ [row.key, "A new row cannot have existing state"],
99
+ [chunk.row_key.empty?, "A row key must be set"],
100
+ [chunk.reset_row, "A new row cannot be reset"],
101
+ [last_key == chunk.row_key, "A commit happened but the same key followed"],
102
+ [
103
+ last_key && chunk.row_key < last_key,
104
+ "Out of order row key, must be strictly increasing. " \
105
+ "New key: '#{chunk.row_key}', Previous key: '#{last_key}'"
106
+ ],
107
+ [chunk.family_name.nil?, "A family must be set"],
108
+ [chunk.qualifier.nil?, "A column qualifier must be set"]
109
+ ]
110
+
111
+ validations.each do |condition, message|
112
+ raise_if condition, message
113
+ end
103
114
  end
104
115
 
105
116
  ##
@@ -39,6 +39,10 @@ module Google
39
39
  RETRY_LIMIT = 3
40
40
 
41
41
  # @private
42
+ # The prefix for routing cookies. Used to dynamically find cookie
43
+ # headers in metadata.
44
+ COOKIE_KEY_PREFIX = "x-goog-cbt-cookie"
45
+
42
46
  #
43
47
  # Creates a mutate rows instance.
44
48
  #
@@ -57,18 +61,20 @@ module Google
57
61
  #
58
62
  def apply_mutations
59
63
  @req_entries = @entries.map(&:to_grpc)
60
- statuses = mutate_rows @req_entries
64
+ statuses, delay, cookies = mutate_rows @req_entries
61
65
 
62
- # Collects retryable mutations indices.
63
66
  indices = statuses.each_with_object [] do |e, r|
64
67
  r << e.index if @entries[e.index].retryable? && RETRYABLE_CODES[e.status.code]
65
68
  end
66
69
 
67
70
  return statuses if indices.empty?
68
71
 
69
- (RETRY_LIMIT - 1).times do
72
+ RETRY_LIMIT.times do
70
73
  break if indices.empty?
71
- indices = retry_entries statuses, indices
74
+
75
+ sleep delay if delay
76
+
77
+ indices, delay, cookies = retry_entries statuses, indices, cookies
72
78
  end
73
79
 
74
80
  statuses
@@ -80,13 +86,35 @@ module Google
80
86
  # Mutates rows.
81
87
  #
82
88
  # @param entries [Array<Google::Cloud::Bigtable::MutationEntry>]
83
- # @return [Array<Google::Cloud::Bigtable::V2::MutateRowsResponse::Entry>]
89
+ # @param cookies [Hash]
90
+ # @return [Array<Google::Cloud::Bigtable::V2::MutateRowsResponse::Entry>, Float|nil, Hash]
84
91
  #
85
- def mutate_rows entries
86
- response = @table.service.mutate_rows @table.path, entries, app_profile_id: @table.app_profile_id
87
- response.each_with_object [] do |res, statuses|
88
- statuses.concat res.entries
92
+ def mutate_rows entries, cookies = {}
93
+ call_options = Gapic::CallOptions.new(metadata: cookies) unless cookies.empty?
94
+
95
+ response = @table.service.mutate_rows(
96
+ @table.path,
97
+ entries,
98
+ app_profile_id: @table.app_profile_id,
99
+ call_options: call_options
100
+ )
101
+ [response.flat_map(&:entries), nil, cookies]
102
+ rescue GRPC::BadStatus => e
103
+ info = e.status_details.find { |d| d.is_a? Google::Rpc::RetryInfo }
104
+ delay = if info&.retry_delay
105
+ info.retry_delay.seconds + (info.retry_delay.nanos / 1_000_000_000.0)
106
+ end
107
+
108
+ cookies.merge!(e.metadata.select { |k, _| k.start_with? COOKIE_KEY_PREFIX })
109
+
110
+ status = Google::Rpc::Status.new code: e.code, message: e.message
111
+ statuses = entries.map.with_index do |_, i|
112
+ Google::Cloud::Bigtable::V2::MutateRowsResponse::Entry.new(
113
+ index: i,
114
+ status: status
115
+ )
89
116
  end
117
+ [statuses, delay, cookies]
90
118
  end
91
119
 
92
120
  ##
@@ -94,18 +122,19 @@ module Google
94
122
  #
95
123
  # @param statuses [Array<Google::Cloud::Bigtable::V2::MutateRowsResponse::Entry>]
96
124
  # @param indices [Array<Integer>]
97
- # Retry entries position mapping list
98
- # @return [Array<Integer>]
99
- # New list of failed entries positions
125
+ # @param cookies [Hash]
126
+ # @return [Array<Integer>, Float|nil, Hash]
100
127
  #
101
- def retry_entries statuses, indices
128
+ def retry_entries statuses, indices, cookies
102
129
  entries = indices.map { |i| @req_entries[i] }
103
- retry_statuses = mutate_rows entries
130
+ retry_statuses, delay, cookies = mutate_rows entries, cookies
104
131
 
105
- retry_statuses.each_with_object [] do |e, next_indices|
106
- next_indices << indices[e.index] if RETRYABLE_CODES[e.status.code]
107
- statuses[indices[e.index]].status = e.status
132
+ next_indices = retry_statuses.each_with_object [] do |e, list|
133
+ next_index = indices[e.index]
134
+ statuses[next_index].status = e.status
135
+ list << next_index if RETRYABLE_CODES[e.status.code]
108
136
  end
137
+ [next_indices, delay, cookies]
109
138
  end
110
139
  end
111
140
  end
@@ -92,6 +92,10 @@ module Google
92
92
  yield row
93
93
  @rows_count += 1
94
94
  end
95
+
96
+ if res.last_scanned_row_key && !res.last_scanned_row_key.empty?
97
+ @chunk_processor.last_key = res.last_scanned_row_key
98
+ end
95
99
  end
96
100
 
97
101
  @chunk_processor.validate_last_row_complete
@@ -689,14 +689,13 @@ module Google
689
689
  )
690
690
  end
691
691
 
692
- def mutate_rows table_name, entries, app_profile_id: nil
693
- client(table_name, app_profile_id).mutate_rows(
694
- **{
695
- table_name: table_name,
696
- app_profile_id: app_profile_id,
697
- entries: entries
698
- }.compact
699
- )
692
+ def mutate_rows table_name, entries, app_profile_id: nil, call_options: nil
693
+ request = {
694
+ table_name: table_name,
695
+ app_profile_id: app_profile_id,
696
+ entries: entries
697
+ }.compact
698
+ client(table_name, app_profile_id).mutate_rows request, call_options
700
699
  end
701
700
 
702
701
  def check_and_mutate_row table_name,
@@ -16,7 +16,7 @@
16
16
  module Google
17
17
  module Cloud
18
18
  module Bigtable
19
- VERSION = "2.12.0".freeze
19
+ VERSION = "2.12.2".freeze
20
20
  end
21
21
  end
22
22
  end
@@ -43,15 +43,14 @@ module Google
43
43
  # be one of the following types:
44
44
  # `Google::Auth::Credentials` uses the properties of its represented keyfile for
45
45
  # authenticating requests made by this client.
46
- # `String` will be treated as the path to the keyfile to use to construct
47
- # credentials for this client.
48
- # `Hash` will be treated as the contents of a keyfile to use to construct
49
- # credentials for this client.
50
46
  # `GRPC::Core::Channel` will be used to make calls through.
51
47
  # `GRPC::Core::ChannelCredentials` for the setting up the gRPC client. The channel credentials
52
48
  # should already be composed with a `GRPC::Core::CallCredentials` object.
53
49
  # `Proc` will be used as an updater_proc for the gRPC channel. The proc transforms the
54
50
  # metadata for requests, generally, to give OAuth credentials.
51
+ # @note Warning: Passing a `String` to a keyfile path or a `Hash` of credentials
52
+ # is deprecated. Providing an unvalidated credential configuration to
53
+ # Google APIs can compromise the security of your systems and data.
55
54
  # @param universe_domain [String] Override of the universe domain. Optional.
56
55
  # @param endpoint [String] Override of the endpoint host name. Optional.
57
56
  # If the param is nil, uses the default endpoint.
@@ -40,29 +40,33 @@ module Google
40
40
  # updater_proc is supplied.
41
41
  # @param timeout [Integer]
42
42
  # The default timeout, in seconds, for calls made through this client.
43
- # @param credentials [Google::Auth::Credentials, String, Hash, GRPC::Core::Channel,
43
+ # @param credentials [Google::Auth::Credentials, GRPC::Core::Channel,
44
44
  # GRPC::Core::ChannelCredentials, Proc]
45
- # Provides the means for authenticating requests made by the client. This parameter can
45
+ # The means for authenticating requests made by the client. This parameter can
46
46
  # be one of the following types.
47
47
  # `Google::Auth::Credentials` uses the properties of its represented keyfile for
48
48
  # authenticating requests made by this client.
49
- # `String` will be treated as the path to the keyfile to use to construct
50
- # credentials for this client.
51
- # `Hash` will be treated as the contents of a keyfile to use to construct
52
- # credentials for this client.
53
49
  # `GRPC::Core::Channel` will be used to make calls through.
54
50
  # `GRPC::Core::ChannelCredentials` will be used to set up the gRPC client. The channel credentials
55
51
  # should already be composed with a `GRPC::Core::CallCredentials` object.
56
52
  # `Proc` will be used as an updater_proc for the gRPC channel. The proc transforms the
57
53
  # metadata for requests, generally, to give OAuth credentials.
58
- # @return [Google::Cloud::Bigtable::Project]
54
+ # @note Warning: Passing a `String` to a keyfile path or a `Hash` of credentials
55
+ # is deprecated. Providing an unvalidated credential configuration to
56
+ # Google APIs can compromise the security of your systems and data.
59
57
  #
60
- # @example
61
- # require "google/cloud/bigtable"
58
+ # @example
59
+ #
60
+ # # The recommended way to provide credentials is to use the `make_creds` method
61
+ # # on the appropriate credentials class for your environment.
62
+ #
63
+ # credentials = ::Google::Auth::ServiceAccountCredentials.make_creds(
64
+ # json_key_io: ::File.open("/path/to/keyfile.json")
65
+ # )
62
66
  #
63
- # gcloud = Google::Cloud.new
67
+ # gcloud = Google::Cloud.new
64
68
  #
65
- # bigtable = gcloud.bigtable
69
+ # bigtable = gcloud.bigtable credentials: credentials
66
70
  #
67
71
  def bigtable scope: nil, timeout: nil, credentials: nil
68
72
  credentials ||= @keyfile
@@ -83,21 +87,32 @@ module Google
83
87
  # Project identifier for the Bigtable service you
84
88
  # are connecting to. If not present, the default project for the
85
89
  # credentials is used.
86
- # @param credentials [Google::Auth::Credentials, String, Hash, GRPC::Core::Channel,
90
+ # @param credentials [Google::Auth::Credentials, GRPC::Core::Channel,
87
91
  # GRPC::Core::ChannelCredentials, Proc]
88
92
  # The means for authenticating requests made by the client. This parameter can
89
93
  # be one of the following types.
90
94
  # `Google::Auth::Credentials` uses the properties of its represented keyfile for
91
95
  # authenticating requests made by this client.
92
- # `String` will be treated as the path to the keyfile to use to construct
93
- # credentials for this client.
94
- # `Hash` will be treated as the contents of a keyfile to use to construct
95
- # credentials for this client.
96
96
  # `GRPC::Core::Channel` will be used to make calls through.
97
97
  # `GRPC::Core::ChannelCredentials` will be used to set up the gRPC client. The channel credentials
98
98
  # should already be composed with a `GRPC::Core::CallCredentials` object.
99
99
  # `Proc` will be used as an updater_proc for the gRPC channel. The proc transforms the
100
100
  # metadata for requests, generally, to give OAuth credentials.
101
+ # @note Warning: Passing a `String` to a keyfile path or a `Hash` of credentials
102
+ # is deprecated. Providing an unvalidated credential configuration to
103
+ # Google APIs can compromise the security of your systems and data.
104
+ #
105
+ # @example
106
+ #
107
+ # # The recommended way to provide credentials is to use the `make_creds` method
108
+ # # on the appropriate credentials class for your environment.
109
+ #
110
+ # credentials = ::Google::Auth::ServiceAccountCredentials.make_creds(
111
+ # json_key_io: ::File.open("/path/to/keyfile.json")
112
+ # )
113
+ #
114
+ # client = Google::Cloud.bigtable credentials: credentials
115
+ #
101
116
  # @param scope [Array<String>]
102
117
  # The OAuth 2.0 scopes controlling the set of resources and operations
103
118
  # that the connection can access. See [Using OAuth 2.0 to Access Google
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: google-cloud-bigtable
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.12.0
4
+ version: 2.12.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Google LLC
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-02-25 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: concurrent-ruby
@@ -149,7 +149,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
149
149
  - !ruby/object:Gem::Version
150
150
  version: '0'
151
151
  requirements: []
152
- rubygems_version: 3.6.5
152
+ rubygems_version: 3.6.9
153
153
  specification_version: 4
154
154
  summary: API Client library for Cloud Bigtable API
155
155
  test_files: []