google-cloud-storage 1.10.0 → 1.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +7 -0
- data/lib/google/cloud/storage/bucket.rb +5 -5
- data/lib/google/cloud/storage/file.rb +199 -54
- data/lib/google/cloud/storage/service.rb +16 -21
- data/lib/google/cloud/storage/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6df77120a6b6b06e34910f4150a4b4734e9f1ee6055f24dd1dcdcce6852c200a
|
4
|
+
data.tar.gz: d3d9ae16b4cafc4e8d033efa4686ebbeeffbcf70005a34e1804fdf67ea16fb58
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: db977a4ee0406302562c8d0d71f6a8a55bea904305a774dc2244898c7c08e3253b98ec77181d425f30a0953f9be693d36e27052b1e22a678bd6e3470b9aacfde
|
7
|
+
data.tar.gz: 827d0709cc5f86a215813a93ce308c354e61f2a9b5bbbd9d087b89776ff9a1818b5f4e34418f976689ea1bd415231b8d73ec870628e8dccd67c82bc71242e363
|
data/README.md
CHANGED
@@ -44,6 +44,13 @@ file.copy backup, file.name
|
|
44
44
|
|
45
45
|
This library is supported on Ruby 2.0+.
|
46
46
|
|
47
|
+
However, Ruby 2.3 or later is strongly recommended, as earlier releases have
|
48
|
+
reached or are nearing end-of-life. After June 1, 2018, Google will provide
|
49
|
+
official support only for Ruby versions that are considered current and
|
50
|
+
supported by Ruby Core (that is, Ruby versions that are either in normal
|
51
|
+
maintenance or in security maintenance).
|
52
|
+
See https://www.ruby-lang.org/en/downloads/branches/ for further details.
|
53
|
+
|
47
54
|
## Versioning
|
48
55
|
|
49
56
|
This library follows [Semantic Versioning](http://semver.org/).
|
@@ -561,8 +561,8 @@ module Google
|
|
561
561
|
|
562
562
|
##
|
563
563
|
# Creates a new {File} object by providing a path to a local file (or
|
564
|
-
# any
|
565
|
-
# store it in the bucket.
|
564
|
+
# any File-like object such as StringIO) to upload, along with the path
|
565
|
+
# at which to store it in the bucket.
|
566
566
|
#
|
567
567
|
# #### Customer-supplied encryption keys
|
568
568
|
#
|
@@ -577,9 +577,9 @@ module Google
|
|
577
577
|
# and you can read or update the metadata of an encrypted file without
|
578
578
|
# providing the encryption key.
|
579
579
|
#
|
580
|
-
# @param [String,
|
581
|
-
# upload. Can be an
|
582
|
-
#
|
580
|
+
# @param [String, ::File] file Path of the file on the filesystem to
|
581
|
+
# upload. Can be an File object, or File-like object such as StringIO.
|
582
|
+
# (If the object does not have path, a `path` argument must be also be
|
583
583
|
# provided.)
|
584
584
|
# @param [String] path Path to store the file in Google Cloud Storage.
|
585
585
|
# @param [String] acl A predefined set of access controls to apply to
|
@@ -411,7 +411,7 @@ module Google
|
|
411
411
|
end
|
412
412
|
|
413
413
|
##
|
414
|
-
# Download the file's contents to a local file or an
|
414
|
+
# Download the file's contents to a local file or an File-like object.
|
415
415
|
#
|
416
416
|
# By default, the download is verified by calculating the MD5 digest.
|
417
417
|
#
|
@@ -420,11 +420,12 @@ module Google
|
|
420
420
|
# was used with {Bucket#create_file}, the `encryption_key` option must
|
421
421
|
# be provided.
|
422
422
|
#
|
423
|
-
# @param [String,
|
424
|
-
# the data to. The path provided must be writable. Can also be
|
425
|
-
# object, or
|
426
|
-
# will be written to, not the filesystem. If
|
427
|
-
# instance will be written to and returned.
|
423
|
+
# @param [String, ::File] path The path on the local file system to
|
424
|
+
# write the data to. The path provided must be writable. Can also be
|
425
|
+
# an File object, or File-like object such as StringIO. If an file
|
426
|
+
# object, the object will be written to, not the filesystem. If
|
427
|
+
# omitted, a new StringIO instance will be written to and returned.
|
428
|
+
# Optional.
|
428
429
|
# @param [Symbol] verify The verification algorithm used to ensure the
|
429
430
|
# downloaded file contents are correct. Default is `:md5`.
|
430
431
|
#
|
@@ -438,6 +439,13 @@ module Google
|
|
438
439
|
# @param [String] encryption_key Optional. The customer-supplied,
|
439
440
|
# AES-256 encryption key used to encrypt the file, if one was provided
|
440
441
|
# to {Bucket#create_file}.
|
442
|
+
#
|
443
|
+
# @param [Range, String] range Optional. The byte range of the file's
|
444
|
+
# contents to download or a string header value. Provide this to
|
445
|
+
# perform a partial download. When a range is provided, no
|
446
|
+
# verification is performed regardless of the `verify` parameter's
|
447
|
+
# value.
|
448
|
+
#
|
441
449
|
# @param [Boolean] skip_decompress Optional. If `true`, the data for a
|
442
450
|
# Storage object returning a `Content-Encoding: gzip` response header
|
443
451
|
# will *not* be automatically decompressed by this client library. The
|
@@ -446,11 +454,11 @@ module Google
|
|
446
454
|
# not performed in the Storage service. (See [Transcoding of
|
447
455
|
# gzip-compressed files](https://cloud.google.com/storage/docs/transcoding))
|
448
456
|
#
|
449
|
-
# @return [
|
450
|
-
# will ordinarily be a `::File` object referencing the
|
451
|
-
# system. However, if the argument to `path` is `nil`, a
|
452
|
-
# instance will be returned. If the argument to `path` is an
|
453
|
-
# object, then that object will be returned.
|
457
|
+
# @return [::File, StringIO] Returns a file object representing the file
|
458
|
+
# data. This will ordinarily be a `::File` object referencing the
|
459
|
+
# local file system. However, if the argument to `path` is `nil`, a
|
460
|
+
# StringIO instance will be returned. If the argument to `path` is an
|
461
|
+
# File-like object, then that object will be returned.
|
454
462
|
#
|
455
463
|
# @example
|
456
464
|
# require "google/cloud/storage"
|
@@ -542,17 +550,32 @@ module Google
|
|
542
550
|
# file.download "path/to/downloaded/gzipped.txt",
|
543
551
|
# skip_decompress: true
|
544
552
|
#
|
545
|
-
|
553
|
+
# @example Partially download.
|
554
|
+
#
|
555
|
+
# require "google/cloud/storage"
|
556
|
+
#
|
557
|
+
# storage = Google::Cloud::Storage.new
|
558
|
+
# bucket = storage.bucket "my-bucket"
|
559
|
+
# file = bucket.file "path/to/my-file.ext"
|
560
|
+
#
|
561
|
+
# downloaded = file.download range: 6..10
|
562
|
+
# downloaded.rewind
|
563
|
+
# downloaded.read #=> "world"
|
564
|
+
#
|
565
|
+
def download path = nil, verify: :md5, encryption_key: nil, range: nil,
|
546
566
|
skip_decompress: nil
|
547
567
|
ensure_service!
|
548
568
|
if path.nil?
|
549
569
|
path = StringIO.new
|
550
570
|
path.set_encoding "ASCII-8BIT"
|
551
571
|
end
|
552
|
-
file, resp =
|
553
|
-
bucket, name, path,
|
572
|
+
file, resp =
|
573
|
+
service.download_file bucket, name, path,
|
574
|
+
key: encryption_key, range: range,
|
575
|
+
user_project: user_project
|
554
576
|
# FIX: downloading with encryption key will return nil
|
555
577
|
file ||= ::File.new(path)
|
578
|
+
verify = :none if range
|
556
579
|
verify_file! file, verify
|
557
580
|
if !skip_decompress &&
|
558
581
|
Array(resp.header["Content-Encoding"]).include?("gzip")
|
@@ -646,31 +669,155 @@ module Google
|
|
646
669
|
# f.metadata["copied_from"] = "#{file.bucket}/#{file.name}"
|
647
670
|
# end
|
648
671
|
#
|
649
|
-
def copy dest_bucket_or_path, dest_path = nil,
|
650
|
-
generation: nil, encryption_key: nil
|
672
|
+
def copy dest_bucket_or_path, dest_path = nil,
|
673
|
+
acl: nil, generation: nil, encryption_key: nil
|
674
|
+
rewrite dest_bucket_or_path, dest_path,
|
675
|
+
acl: acl, generation: generation,
|
676
|
+
encryption_key: encryption_key,
|
677
|
+
new_encryption_key: encryption_key do |updater|
|
678
|
+
yield updater if block_given?
|
679
|
+
end
|
680
|
+
end
|
681
|
+
|
682
|
+
##
|
683
|
+
# [Rewrites](https://cloud.google.com/storage/docs/json_api/v1/objects/rewrite)
|
684
|
+
# the file to a new location. Or the same location can be provided to
|
685
|
+
# rewrite the file in place.
|
686
|
+
#
|
687
|
+
# If a [customer-supplied encryption
|
688
|
+
# key](https://cloud.google.com/storage/docs/encryption#customer-supplied)
|
689
|
+
# was used with {Bucket#create_file}, the `encryption_key` option must
|
690
|
+
# be provided. Unlike {#copy}, separate encryption keys are used to read
|
691
|
+
# (encryption_key) and to write (new_encryption_key) file contents.
|
692
|
+
#
|
693
|
+
# @param [String] dest_bucket_or_path Either the bucket to rewrite the
|
694
|
+
# file to, or the path to rewrite the file to in the current bucket.
|
695
|
+
# @param [String] dest_path If a bucket was provided in the first
|
696
|
+
# parameter, this contains the path to rewrite the file to in the
|
697
|
+
# given bucket.
|
698
|
+
# @param [String] acl A predefined set of access controls to apply to
|
699
|
+
# new file.
|
700
|
+
#
|
701
|
+
# Acceptable values are:
|
702
|
+
#
|
703
|
+
# * `auth`, `auth_read`, `authenticated`, `authenticated_read`,
|
704
|
+
# `authenticatedRead` - File owner gets OWNER access, and
|
705
|
+
# allAuthenticatedUsers get READER access.
|
706
|
+
# * `owner_full`, `bucketOwnerFullControl` - File owner gets OWNER
|
707
|
+
# access, and project team owners get OWNER access.
|
708
|
+
# * `owner_read`, `bucketOwnerRead` - File owner gets OWNER access,
|
709
|
+
# and project team owners get READER access.
|
710
|
+
# * `private` - File owner gets OWNER access.
|
711
|
+
# * `project_private`, `projectPrivate` - File owner gets OWNER
|
712
|
+
# access, and project team members get access according to their
|
713
|
+
# roles.
|
714
|
+
# * `public`, `public_read`, `publicRead` - File owner gets OWNER
|
715
|
+
# access, and allUsers get READER access.
|
716
|
+
# @param [Integer] generation Select a specific revision of the file to
|
717
|
+
# rewrite. The default is the latest version.
|
718
|
+
# @param [String] encryption_key Optional. The customer-supplied,
|
719
|
+
# AES-256 encryption key used to decrypt the file, if the existing
|
720
|
+
# file is encrypted.
|
721
|
+
# @param [String] new_encryption_key Optional. The customer-supplied,
|
722
|
+
# AES-256 encryption key used to encrypt the file, if the rewritten
|
723
|
+
# file is intended to be encrypted.
|
724
|
+
# @yield [file] a block yielding a delegate object for updating
|
725
|
+
#
|
726
|
+
# @return [Google::Cloud::Storage::File]
|
727
|
+
#
|
728
|
+
# @example The file can be rewritten to a new path in the bucket:
|
729
|
+
# require "google/cloud/storage"
|
730
|
+
#
|
731
|
+
# storage = Google::Cloud::Storage.new
|
732
|
+
#
|
733
|
+
# bucket = storage.bucket "my-bucket"
|
734
|
+
#
|
735
|
+
# file = bucket.file "path/to/my-file.ext"
|
736
|
+
# file.rewrite "path/to/destination/file.ext"
|
737
|
+
#
|
738
|
+
# @example The file can also be rewritten to a different bucket:
|
739
|
+
# require "google/cloud/storage"
|
740
|
+
#
|
741
|
+
# storage = Google::Cloud::Storage.new
|
742
|
+
#
|
743
|
+
# bucket = storage.bucket "my-bucket"
|
744
|
+
#
|
745
|
+
# file = bucket.file "path/to/my-file.ext"
|
746
|
+
# file.rewrite "new-destination-bucket",
|
747
|
+
# "path/to/destination/file.ext"
|
748
|
+
#
|
749
|
+
# @example The file can also be rewritten by specifying a generation:
|
750
|
+
# require "google/cloud/storage"
|
751
|
+
#
|
752
|
+
# storage = Google::Cloud::Storage.new
|
753
|
+
#
|
754
|
+
# bucket = storage.bucket "my-bucket"
|
755
|
+
#
|
756
|
+
# file = bucket.file "path/to/my-file.ext"
|
757
|
+
# file.rewrite "copy/of/previous/generation/file.ext",
|
758
|
+
# generation: 123456
|
759
|
+
#
|
760
|
+
# @example The file can be modified during rewriting:
|
761
|
+
# require "google/cloud/storage"
|
762
|
+
#
|
763
|
+
# storage = Google::Cloud::Storage.new
|
764
|
+
#
|
765
|
+
# bucket = storage.bucket "my-bucket"
|
766
|
+
#
|
767
|
+
# file = bucket.file "path/to/my-file.ext"
|
768
|
+
# file.rewrite "new-destination-bucket",
|
769
|
+
# "path/to/destination/file.ext" do |f|
|
770
|
+
# f.metadata["rewritten_from"] = "#{file.bucket}/#{file.name}"
|
771
|
+
# end
|
772
|
+
#
|
773
|
+
# @example The file can be rewritten with a new encryption key:
|
774
|
+
# require "google/cloud/storage"
|
775
|
+
#
|
776
|
+
# storage = Google::Cloud::Storage.new
|
777
|
+
#
|
778
|
+
# bucket = storage.bucket "my-bucket"
|
779
|
+
#
|
780
|
+
# # Old key was stored securely for later use.
|
781
|
+
# old_key = "y\x03\"\x0E\xB6\xD3\x9B\x0E\xAB*\x19\xFAv\xDEY\xBEI..."
|
782
|
+
#
|
783
|
+
# # Key generation shown for example purposes only. Write your own.
|
784
|
+
# cipher = OpenSSL::Cipher.new "aes-256-cfb"
|
785
|
+
# cipher.encrypt
|
786
|
+
# new_key = cipher.random_key
|
787
|
+
#
|
788
|
+
# file = bucket.file "path/to/my-file.ext"
|
789
|
+
# file.rewrite "new-destination-bucket",
|
790
|
+
# "path/to/destination/file.ext",
|
791
|
+
# encryption_key: old_key,
|
792
|
+
# new_encryption_key: new_key do |f|
|
793
|
+
# f.metadata["rewritten_from"] = "#{file.bucket}/#{file.name}"
|
794
|
+
# end
|
795
|
+
#
|
796
|
+
def rewrite dest_bucket_or_path, dest_path = nil,
|
797
|
+
acl: nil, generation: nil,
|
798
|
+
encryption_key: nil, new_encryption_key: nil
|
651
799
|
ensure_service!
|
652
|
-
|
653
|
-
|
654
|
-
dest_bucket, dest_path, options = fix_copy_args dest_bucket_or_path,
|
655
|
-
dest_path, options
|
800
|
+
dest_bucket, dest_path = fix_rewrite_args dest_bucket_or_path,
|
801
|
+
dest_path
|
656
802
|
|
657
|
-
|
803
|
+
update_gapi = nil
|
658
804
|
if block_given?
|
659
805
|
updater = Updater.new gapi
|
660
806
|
yield updater
|
661
807
|
updater.check_for_changed_metadata!
|
662
|
-
|
808
|
+
if updater.updates.any?
|
809
|
+
update_gapi = gapi_from_attrs updater.updates
|
810
|
+
end
|
663
811
|
end
|
664
812
|
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
File.from_gapi resp.resource, service, user_project: user_project
|
813
|
+
new_gapi = rewrite_gapi bucket, name, update_gapi,
|
814
|
+
new_bucket: dest_bucket, new_name: dest_path,
|
815
|
+
acl: acl, generation: generation,
|
816
|
+
encryption_key: encryption_key,
|
817
|
+
new_encryption_key: new_encryption_key,
|
818
|
+
user_project: user_project
|
819
|
+
|
820
|
+
File.from_gapi new_gapi, service, user_project: user_project
|
674
821
|
end
|
675
822
|
|
676
823
|
##
|
@@ -719,17 +866,8 @@ module Google
|
|
719
866
|
# file.rotate encryption_key: old_key, new_encryption_key: new_key
|
720
867
|
#
|
721
868
|
def rotate encryption_key: nil, new_encryption_key: nil
|
722
|
-
|
723
|
-
|
724
|
-
destination_key: new_encryption_key,
|
725
|
-
user_project: user_project }
|
726
|
-
gapi = service.rewrite_file bucket, name, bucket, name, nil, options
|
727
|
-
until gapi.done
|
728
|
-
sleep 1
|
729
|
-
options[:token] = gapi.rewrite_token
|
730
|
-
gapi = service.rewrite_file bucket, name, bucket, name, nil, options
|
731
|
-
end
|
732
|
-
File.from_gapi gapi.resource, service, user_project: user_project
|
869
|
+
rewrite bucket, name, encryption_key: encryption_key,
|
870
|
+
new_encryption_key: new_encryption_key
|
733
871
|
end
|
734
872
|
|
735
873
|
##
|
@@ -1096,7 +1234,8 @@ module Google
|
|
1096
1234
|
ensure_service!
|
1097
1235
|
|
1098
1236
|
@gapi = if attributes.include? :storage_class
|
1099
|
-
rewrite_gapi
|
1237
|
+
rewrite_gapi \
|
1238
|
+
bucket, name, update_gapi, user_project: user_project
|
1100
1239
|
else
|
1101
1240
|
service.patch_file \
|
1102
1241
|
bucket, name, update_gapi, user_project: user_project
|
@@ -1112,30 +1251,36 @@ module Google
|
|
1112
1251
|
Google::Apis::StorageV1::Object.new attr_params
|
1113
1252
|
end
|
1114
1253
|
|
1115
|
-
def rewrite_gapi bucket, name,
|
1254
|
+
def rewrite_gapi bucket, name, updated_gapi,
|
1255
|
+
new_bucket: nil, new_name: nil, acl: nil,
|
1256
|
+
generation: nil, encryption_key: nil,
|
1257
|
+
new_encryption_key: nil, user_project: nil
|
1258
|
+
new_bucket ||= bucket
|
1259
|
+
new_name ||= name
|
1260
|
+
options = { acl: File::Acl.predefined_rule_for(acl),
|
1261
|
+
generation: generation, source_key: encryption_key,
|
1262
|
+
destination_key: new_encryption_key,
|
1263
|
+
user_project: user_project }.delete_if { |_k, v| v.nil? }
|
1264
|
+
|
1116
1265
|
resp = service.rewrite_file \
|
1117
|
-
bucket, name,
|
1266
|
+
bucket, name, new_bucket, new_name, updated_gapi, options
|
1118
1267
|
until resp.done
|
1119
1268
|
sleep 1
|
1269
|
+
retry_options = options.merge token: resp.rewrite_token
|
1120
1270
|
resp = service.rewrite_file \
|
1121
|
-
bucket, name,
|
1122
|
-
token: resp.rewrite_token, user_project: user_project
|
1271
|
+
bucket, name, new_bucket, new_name, updated_gapi, retry_options
|
1123
1272
|
end
|
1124
1273
|
resp.resource
|
1125
1274
|
end
|
1126
1275
|
|
1127
|
-
def
|
1128
|
-
if dest_path.respond_to?(:to_hash) && options.empty?
|
1129
|
-
options = dest_path
|
1130
|
-
dest_path = nil
|
1131
|
-
end
|
1276
|
+
def fix_rewrite_args dest_bucket, dest_path
|
1132
1277
|
if dest_path.nil?
|
1133
1278
|
dest_path = dest_bucket
|
1134
1279
|
dest_bucket = bucket
|
1135
1280
|
end
|
1136
1281
|
dest_bucket = dest_bucket.name if dest_bucket.respond_to? :name
|
1137
|
-
|
1138
|
-
[dest_bucket, dest_path
|
1282
|
+
dest_path = dest_path.name if dest_path.respond_to? :name
|
1283
|
+
[dest_bucket, dest_path]
|
1139
1284
|
end
|
1140
1285
|
|
1141
1286
|
def verify_file! file, verify = :md5
|
@@ -311,26 +311,6 @@ module Google
|
|
311
311
|
end
|
312
312
|
end
|
313
313
|
|
314
|
-
## Copy a file from source bucket/object to a
|
315
|
-
# destination bucket/object.
|
316
|
-
def copy_file source_bucket_name, source_file_path,
|
317
|
-
destination_bucket_name, destination_file_path,
|
318
|
-
file_gapi = nil, key: nil, acl: nil, generation: nil,
|
319
|
-
token: nil, user_project: nil
|
320
|
-
key_options = rewrite_key_options key, key
|
321
|
-
execute do
|
322
|
-
service.rewrite_object \
|
323
|
-
source_bucket_name, source_file_path,
|
324
|
-
destination_bucket_name, destination_file_path,
|
325
|
-
file_gapi,
|
326
|
-
destination_predefined_acl: acl,
|
327
|
-
source_generation: generation,
|
328
|
-
rewrite_token: token,
|
329
|
-
user_project: user_project(user_project),
|
330
|
-
options: key_options
|
331
|
-
end
|
332
|
-
end
|
333
|
-
|
334
314
|
## Rewrite a file from source bucket/object to a
|
335
315
|
# destination bucket/object.
|
336
316
|
def rewrite_file source_bucket_name, source_file_path,
|
@@ -381,8 +361,10 @@ module Google
|
|
381
361
|
# Apis::StorageV1::StorageService and Apis::Core::DownloadCommand at
|
382
362
|
# the end of this file.
|
383
363
|
def download_file bucket_name, file_path, target_path, generation: nil,
|
384
|
-
key: nil, user_project: nil
|
364
|
+
key: nil, range: nil, user_project: nil
|
385
365
|
options = key_options key
|
366
|
+
options = range_header options, range
|
367
|
+
|
386
368
|
execute do
|
387
369
|
service.get_object_with_response \
|
388
370
|
bucket_name, file_path,
|
@@ -501,6 +483,19 @@ module Google
|
|
501
483
|
options
|
502
484
|
end
|
503
485
|
|
486
|
+
def range_header options, range
|
487
|
+
case range
|
488
|
+
when Range
|
489
|
+
options[:header] ||= {}
|
490
|
+
options[:header]["Range"] = "bytes=#{range.min}-#{range.max}"
|
491
|
+
when String
|
492
|
+
options[:header] ||= {}
|
493
|
+
options[:header]["Range"] = range
|
494
|
+
end
|
495
|
+
|
496
|
+
options
|
497
|
+
end
|
498
|
+
|
504
499
|
def topic_path topic_name
|
505
500
|
return topic_name if topic_name.to_s.include? "/"
|
506
501
|
"//pubsub.googleapis.com/projects/#{project}/topics/#{topic_name}"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: google-cloud-storage
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Moore
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2018-02
|
12
|
+
date: 2018-05-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: google-cloud-core
|