google-cloud-spanner 1.15.0 → 1.16.0

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.
@@ -15,6 +15,8 @@
15
15
 
16
16
  require "google/cloud/spanner/database/job"
17
17
  require "google/cloud/spanner/database/list"
18
+ require "google/cloud/spanner/database/restore_info"
19
+ require "google/cloud/spanner/backup"
18
20
  require "google/cloud/spanner/policy"
19
21
 
20
22
  module Google
@@ -114,6 +116,13 @@ module Google
114
116
  state == :READY
115
117
  end
116
118
 
119
+ ##
120
+ # The database is fully created from backup and optimizing.
121
+ # @return [Boolean]
122
+ def ready_optimizing?
123
+ state == :READY_OPTIMIZING
124
+ end
125
+
117
126
  ##
118
127
  # Retrieve the Data Definition Language (DDL) statements that define
119
128
  # database structures. DDL statements are used to create, update,
@@ -220,6 +229,257 @@ module Google
220
229
  true
221
230
  end
222
231
 
232
+
233
+ # @private
234
+ DATBASE_OPERATION_METADAT_FILTER_TEMPLATE = [
235
+ "(metadata.@type:CreateDatabaseMetadata AND " \
236
+ "metadata.database:%<database_id>s)",
237
+ "(metadata.@type:RestoreDatabaseMetadata AND "\
238
+ "metadata.name:%<database_id>s)",
239
+ "(metadata.@type:UpdateDatabaseDdl AND "\
240
+ "metadata.database:%<database_id>s)"
241
+ ].join(" OR ")
242
+
243
+ ##
244
+ # Retrieves the list of database operations for the given database.
245
+ #
246
+ # @param filter [String]
247
+ # A filter expression that filters what operations are returned in the
248
+ # response.
249
+ #
250
+ # The response returns a list of
251
+ # {Google::Longrunning::Operation long-running operations} whose names
252
+ # are prefixed by a database name within the specified instance.
253
+ # The long-running operation
254
+ # {Google::Longrunning::Operation#metadata metadata} field type
255
+ # `metadata.type_url` describes the type of the metadata.
256
+ #
257
+ # The filter expression must specify the field name,
258
+ # a comparison operator, and the value that you want to use for
259
+ # filtering. The value must be a string, a number, or a boolean.
260
+ # The comparison operator must be
261
+ # <, >, <=, >=, !=, =, or :. Colon ':' represents a HAS operator
262
+ # which is roughly synonymous with equality. Filter rules are case
263
+ # insensitive.
264
+ #
265
+ # The long-running operation fields eligible for filtering are:
266
+ # * `name` --> The name of the long-running operation
267
+ # * `done` --> False if the operation is in progress, else true.
268
+ # * `metadata.type_url` (using filter string `metadata.@type`) and
269
+ # fields in `metadata.value` (using filter string
270
+ # `metadata.<field_name>`, where <field_name> is a field in
271
+ # metadata.value) are eligible for filtering.
272
+ # * `error` --> Error associated with the long-running operation.
273
+ # * `response.type_url` (using filter string `response.@type`) and
274
+ # fields in `response.value` (using filter string
275
+ # `response.<field_name>`, where <field_name> is a field in
276
+ # response.value)are eligible for filtering.
277
+ #
278
+ # To filter on multiple expressions, provide each separate
279
+ # expression within parentheses. By default, each expression
280
+ # is an AND expression. However, you can include AND, OR, and NOT
281
+ # expressions explicitly.
282
+ #
283
+ # Some examples of using filters are:
284
+ #
285
+ # * `done:true` --> The operation is complete.
286
+ # * `(metadata.@type:type.googleapis.com/google.spanner.admin.\
287
+ # database.v1.RestoreDatabaseMetadata)
288
+ # AND (metadata.source_type:BACKUP)
289
+ # AND (metadata.backup_info.backup:backup_howl)
290
+ # AND (metadata.name:restored_howl)
291
+ # AND (metadata.progress.start_time < \"2018-03-28T14:50:00Z\")
292
+ # AND (error:*)`
293
+ # --> Return RestoreDatabase operations from backups whose name
294
+ # contains "backup_howl", where the created database name
295
+ # contains the string "restored_howl", the start_time of the
296
+ # restore operation is before 2018-03-28T14:50:00Z,
297
+ # and the operation returned an error.
298
+ # @param page_size [Integer]
299
+ # The maximum number of resources contained in the underlying API
300
+ # response. If page streaming is performed per-resource, this
301
+ # parameter does not affect the return value. If page streaming is
302
+ # performed per-page, this determines the maximum number of
303
+ # resources in a page.
304
+ #
305
+ # @return [Array<Google::Cloud::Spanner::Database::Job>] List
306
+ # representing the long-running, asynchronous processing
307
+ # of a database operations.
308
+ # (See {Google::Cloud::Spanner::Database::Job::List})
309
+ #
310
+ # @example
311
+ # require "google/cloud/spanner"
312
+ #
313
+ # spanner = Google::Cloud::Spanner.new
314
+ #
315
+ # database = spanner.database "my-instance", "my-database"
316
+ #
317
+ # jobs = database.database_operations
318
+ # jobs.each do |job|
319
+ # if job.error?
320
+ # p job.error
321
+ # else
322
+ # p job.database.database_id
323
+ # end
324
+ # end
325
+ #
326
+ # @example Retrieve all
327
+ # require "google/cloud/spanner"
328
+ #
329
+ # spanner = Google::Cloud::Spanner.new
330
+ #
331
+ # database = spanner.database "my-instance", "my-database"
332
+ #
333
+ # jobs = database.database_operations
334
+ # jobs.all do |job|
335
+ # if job.error?
336
+ # p job.error
337
+ # else
338
+ # puts job.database.database_id
339
+ # end
340
+ # end
341
+ #
342
+ # @example List by page size
343
+ # require "google/cloud/spanner"
344
+ #
345
+ # spanner = Google::Cloud::Spanner.new
346
+ #
347
+ # database = spanner.database "my-instance", "my-database"
348
+ #
349
+ # jobs = database.database_operations page_size: 10
350
+ # jobs.each do |job|
351
+ # if job.error?
352
+ # p job.error
353
+ # else
354
+ # puts job.database.database_id
355
+ # end
356
+ # end
357
+ #
358
+ # @example Filter and list
359
+ # require "google/cloud/spanner"
360
+ #
361
+ # spanner = Google::Cloud::Spanner.new
362
+ #
363
+ # database = spanner.database "my-instance", "my-database"
364
+ #
365
+ # jobs = database.database_operations filter: "done:true"
366
+ # jobs.each do |job|
367
+ # if job.error?
368
+ # p job.error
369
+ # else
370
+ # puts job.database.database_id
371
+ # end
372
+ # end
373
+ #
374
+ def database_operations filter: nil, page_size: nil
375
+ database_filter = format(
376
+ DATBASE_OPERATION_METADAT_FILTER_TEMPLATE,
377
+ database_id: database_id
378
+ )
379
+
380
+ if filter
381
+ database_filter = format(
382
+ "(%<filter>s) AND (%<database_filter>s)",
383
+ filter: filter, database_filter: database_filter
384
+ )
385
+ end
386
+
387
+ grpc = service.list_database_operations \
388
+ instance_id,
389
+ filter: database_filter,
390
+ page_size: page_size
391
+ Database::Job::List.from_grpc grpc, service
392
+ end
393
+
394
+ ##
395
+ # Creates a database backup.
396
+ #
397
+ # @param [String] backup_id The unique identifier for the backup.
398
+ # Values are of the form `[a-z][a-z0-9_\-]*[a-z0-9]` and must be
399
+ # between 2 and 60 characters in length. Required.
400
+ # @param [Time] expire_time The expiration time of the backup, with
401
+ # microseconds granularity that must be at least 6 hours and at most
402
+ # 366 days from the time the request is received. Required.
403
+ # Once the `expire_time` has passed, Cloud Spanner will delete the
404
+ # backup and free the resources used by the backup. Required.
405
+ # @return [Google::Cloud::Spanner::Backup::Job] The job representing
406
+ # the long-running, asynchronous processing of a backup create
407
+ # operation.
408
+ #
409
+ # @example Create backup with expiration time
410
+ # require "google/cloud/spanner"
411
+ #
412
+ # spanner = Google::Cloud::Spanner.new
413
+ # database = spanner.database "my-instance", "my-database"
414
+ #
415
+ # job = database.create_backup "my-backup", Time.now + 36000
416
+ #
417
+ # job.done? #=> false
418
+ # job.reload! # API call
419
+ # job.done? #=> true
420
+ #
421
+ # if job.error?
422
+ # status = job.error
423
+ # else
424
+ # backup = job.backup
425
+ # end
426
+ #
427
+ def create_backup backup_id, expire_time
428
+ ensure_service!
429
+ grpc = service.create_backup \
430
+ instance_id,
431
+ database_id,
432
+ backup_id,
433
+ expire_time
434
+ Backup::Job.from_grpc grpc, service
435
+ end
436
+
437
+ ##
438
+ # Retrieves backups belonging to the database.
439
+ #
440
+ # @param [Integer] page_size Optional. Number of backups to be returned
441
+ # in the response. If 0 or less, defaults to the server's maximum
442
+ # allowed page size.
443
+ # @return [Array<Google::Cloud::Spanner::Backup>] Enumerable list of
444
+ # backups. (See {Google::Cloud::Spanner::Backup::List})
445
+ #
446
+ # @example
447
+ # require "google/cloud/spanner"
448
+ #
449
+ # spanner = Google::Cloud::Spanner.new
450
+ # database = spanner.database "my-instance", "my-database"
451
+ #
452
+ # database.backups.all.each do |backup|
453
+ # puts backup.backup_id
454
+ # end
455
+ #
456
+ # @example List backups by page size
457
+ # require "google/cloud/spanner"
458
+ #
459
+ # spanner = Google::Cloud::Spanner.new
460
+ # database = spanner.database "my-instance", "my-database"
461
+ #
462
+ # database.backups(page_size: 5).all.each do |backup|
463
+ # puts backup.backup_id
464
+ # end
465
+ #
466
+ def backups page_size: nil
467
+ ensure_service!
468
+ grpc = service.list_backups \
469
+ instance_id,
470
+ filter: "database:#{database_id}",
471
+ page_size: page_size
472
+ Backup::List.from_grpc grpc, service
473
+ end
474
+
475
+ # Information about the source used to restore the database.
476
+ #
477
+ # @return [Google::Cloud::Spanner::Database::RestoreInfo, nil]
478
+ def restore_info
479
+ return nil unless @grpc.restore_info
480
+ RestoreInfo.from_grpc @grpc.restore_info
481
+ end
482
+
223
483
  ##
224
484
  # Gets the [Cloud IAM](https://cloud.google.com/iam/) access control
225
485
  # policy for this database.
@@ -0,0 +1,105 @@
1
+ # Copyright 2020 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+
16
+ module Google
17
+ module Cloud
18
+ module Spanner
19
+ class Database
20
+ class BackupInfo
21
+ ##
22
+ # @private Creates a new Database::BackupInfo instance.
23
+ def initialize grpc
24
+ @grpc = grpc
25
+ end
26
+
27
+ ##
28
+ # The unique identifier for the project.
29
+ # @return [String]
30
+ def project_id
31
+ @grpc.backup.split("/")[1]
32
+ end
33
+
34
+ ##
35
+ # The unique identifier for the instance.
36
+ # @return [String]
37
+ def instance_id
38
+ @grpc.backup.split("/")[3]
39
+ end
40
+
41
+ ##
42
+ # The unique identifier for the backup.
43
+ # @return [String]
44
+ def backup_id
45
+ @grpc.backup.split("/")[5]
46
+ end
47
+
48
+ ##
49
+ # The full path for the backup. Values are of the form
50
+ # `projects/<project>/instances/<instance>/backups/<backup_id>`.
51
+ # @return [String]
52
+ def path
53
+ @grpc.backup
54
+ end
55
+
56
+ ##
57
+ # Name of the database the backup was created from.
58
+ # @return [String]
59
+ def source_database_id
60
+ @grpc.source_database.split("/")[5]
61
+ end
62
+
63
+ ##
64
+ # The unique identifier for the source database project.
65
+ # @return [String]
66
+ def source_database_project_id
67
+ @grpc.backup.split("/")[1]
68
+ end
69
+
70
+ ##
71
+ # The unique identifier for the source database instance.
72
+ # @return [String]
73
+ def source_database_instance_id
74
+ @grpc.backup.split("/")[3]
75
+ end
76
+
77
+ ##
78
+ # The full path for the source database the backup was created from.
79
+ # Values are of the form
80
+ # `projects/<project>/instances/<instance>/database/<database_id>`.
81
+ # @return [String]
82
+ def source_database_path
83
+ @grpc.source_database
84
+ end
85
+
86
+ ##
87
+ # The backup contains an externally consistent copy of
88
+ # `source_database` at the timestamp specified by `create_time`.
89
+ # received.
90
+ # @return [Time]
91
+ def create_time
92
+ Convert.timestamp_to_time @grpc.create_time
93
+ end
94
+
95
+ ##
96
+ # @private Creates a new Database::BackupInfo instance from a
97
+ # Google::Spanner::Admin::Database::V1::BackupInfo.
98
+ def self.from_grpc grpc
99
+ new grpc
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
@@ -14,6 +14,7 @@
14
14
 
15
15
 
16
16
  require "google/cloud/spanner/status"
17
+ require "google/cloud/spanner/database/job/list"
17
18
 
18
19
  module Google
19
20
  module Cloud
@@ -87,6 +88,8 @@ module Google
87
88
  def database
88
89
  return nil unless done?
89
90
  return nil unless @grpc.grpc_op.result == :response
91
+ return nil unless @grpc.results.instance_of? \
92
+ Google::Spanner::Admin::Database::V1::Database
90
93
  Database.from_grpc @grpc.results, service
91
94
  end
92
95
 
@@ -0,0 +1,177 @@
1
+ # Copyright 2020 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+
16
+ require "delegate"
17
+
18
+ module Google
19
+ module Cloud
20
+ module Spanner
21
+ class Database
22
+ class Job
23
+ ##
24
+ # # List
25
+ #
26
+ # List is a special case Array with additional values for database
27
+ # operations.
28
+ #
29
+ class List < DelegateClass(::Array)
30
+ # @private
31
+ # The gRPC Service object.
32
+ attr_accessor :service
33
+
34
+ # @private
35
+ # The gRPC page enumerable object.
36
+ attr_accessor :grpc
37
+
38
+ ##
39
+ # @private Create a new Database::Job::List with an array of
40
+ # Google::Lognrunning::Operation instances.
41
+ def initialize arr = []
42
+ super arr
43
+ end
44
+
45
+ ##
46
+ # Whether there is a next page of database jobs.
47
+ #
48
+ # @return [Boolean]
49
+ #
50
+ # @example
51
+ # require "google/cloud/spanner"
52
+ #
53
+ # spanner = Google::Cloud::Spanner.new
54
+ #
55
+ # instance = spanner.instance "my-instance"
56
+ #
57
+ # jobs = instance.database_operations
58
+ # if jobs.next?
59
+ # next_jobs = jobs.next
60
+ # end
61
+ #
62
+ def next?
63
+ grpc.next_page?
64
+ end
65
+
66
+ ##
67
+ # Retrieve the next page of database jobs.
68
+ #
69
+ # @return [Google::Cloud::Spanner::Database::Job::List]
70
+ #
71
+ # @example
72
+ # require "google/cloud/spanner"
73
+ #
74
+ # spanner = Google::Cloud::Spanner.new
75
+ #
76
+ # instance = spanner.instance "my-instance"
77
+ #
78
+ # jobs = instance.database_operations
79
+ # if jobs.next?
80
+ # next_jobs = jobs.next
81
+ # end
82
+ #
83
+ def next
84
+ ensure_service!
85
+
86
+ return nil unless next?
87
+ grpc.next_page
88
+ self.class.from_grpc grpc, service
89
+ end
90
+
91
+ ##
92
+ # Retrieves remaining results by repeatedly invoking {#next} until
93
+ # {#next?} returns `false`. Calls the given block once for each
94
+ # result, which is passed as the argument to the block.
95
+ #
96
+ # An Enumerator is returned if no block is given.
97
+ #
98
+ # This method will make repeated API calls until all remaining
99
+ # results are retrieved. (Unlike `#each`, for example, which merely
100
+ # iterates over the results returned by a single API call.) Use with
101
+ # caution.
102
+ #
103
+ # @yield [job] The block for accessing each database job.
104
+ # @yieldparam [Google::Cloud::Spanner::Database::Job] job The
105
+ # database job object.
106
+ #
107
+ # @return [Enumerator]
108
+ #
109
+ # @example Iterating each database job by passing a block:
110
+ # require "google/cloud/spanner"
111
+ #
112
+ # spanner = Google::Cloud::Spanner.new
113
+ #
114
+ # instance = spanner.instance "my-instance"
115
+ #
116
+ # jobs = instance.database_operations
117
+ # jobs.all do |job|
118
+ # puts job.database.database_id
119
+ # end
120
+ #
121
+ # @example Using the enumerator by not passing a block:
122
+ # require "google/cloud/spanner"
123
+ #
124
+ # spanner = Google::Cloud::Spanner.new
125
+ #
126
+ # instance = spanner.instance "my-instance"
127
+ #
128
+ # jobs = instance.database_operations
129
+ # all_database_ids = jobs.all.map do |job|
130
+ # job.database.database_id
131
+ # end
132
+ #
133
+ def all
134
+ return enum_for :all unless block_given?
135
+
136
+ results = self
137
+ loop do
138
+ results.each { |r| yield r }
139
+ break unless next?
140
+ grpc.next_page
141
+ results = self.class.from_grpc grpc, service
142
+ end
143
+ end
144
+
145
+ ##
146
+ # @private
147
+ #
148
+ # New Database::Job::List from a
149
+ # Google::Gax::PagedEnumerable<Google::Longrunning::Operation>
150
+ # object. Operation object is a database operation.
151
+ #
152
+ def self.from_grpc grpc, service
153
+ operations_client = \
154
+ service.databases.instance_variable_get "@operations_client"
155
+ jobs = new(Array(grpc.response.operations).map do |job_grpc|
156
+ Job.from_grpc \
157
+ Google::Gax::Operation.new(job_grpc, operations_client),
158
+ service
159
+ end)
160
+ jobs.grpc = grpc
161
+ jobs.service = service
162
+ jobs
163
+ end
164
+
165
+ protected
166
+
167
+ ##
168
+ # Raise an error unless an active service is available.
169
+ def ensure_service!
170
+ raise "Must have active connection" unless @service
171
+ end
172
+ end
173
+ end
174
+ end
175
+ end
176
+ end
177
+ end