google-cloud-storage 0.23.1 → 0.23.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
  SHA1:
3
- metadata.gz: d25ea51c3061bfb14179befa5250f8665e7f9691
4
- data.tar.gz: b431f5182d343bb654b7d57cc75db83d6d5470f7
3
+ metadata.gz: eacda730dbe4335f179257e4ca952498675b931c
4
+ data.tar.gz: bb21912a5d50d23f83e92e496954cd78eb6155cf
5
5
  SHA512:
6
- metadata.gz: f257e340fb77698aaa60a23ac31d86d42352ad6c70450e59a0a30166f96b3c9b111244033131041c1c567d5a34a0c981d1a74b662af844e1c6276a69b2ad35be
7
- data.tar.gz: 419052576260453c9595b6c1a6236e8f325d0104fdd0ffc81f71bde1d17e00d28871eff0f8951ef9e56bba825289c7e00cbabff7bec861459fc32a6c23988a56
6
+ metadata.gz: 0977c4f43a27b33c5de1cbefbcfb648269e0f181430dd186e97d511758797162821c7f8e2999262c1c0c32ef1f7f6555893f29596bffb8b1ddd815aff2b07f08
7
+ data.tar.gz: 8e56264bf22deac8a2440cde15e8e9a4507ae717a4fbdcf10250ab155fd08cd6c35c66106b6bad3036a899e6af8120bf8da2402bee8ab6c2dc9e9e3312406127
@@ -210,7 +210,6 @@ module Google
210
210
  #
211
211
  # ```ruby
212
212
  # require "google/cloud/storage"
213
- # require "digest/sha2"
214
213
  #
215
214
  # storage = Google::Cloud::Storage.new
216
215
  # bucket = storage.bucket "my-todo-app"
@@ -229,6 +228,28 @@ module Google
229
228
  # encryption_key: key
230
229
  # ```
231
230
  #
231
+ # Use {Google::Cloud::Storage::File#rotate} to rotate customer-supplied
232
+ # encryption keys.
233
+ #
234
+ # ```ruby
235
+ # require "google/cloud/storage"
236
+ #
237
+ # storage = Google::Cloud::Storage.new
238
+ # bucket = storage.bucket "my-todo-app"
239
+ #
240
+ # # Old key was stored securely for later use.
241
+ # old_key = "y\x03\"\x0E\xB6\xD3\x9B\x0E\xAB*\x19\xFAv\xDEY\xBEI..."
242
+ #
243
+ # file = bucket.file "path/to/my-file.ext", encryption_key: old_key
244
+ #
245
+ # # Key generation shown for example purposes only. Write your own.
246
+ # cipher = OpenSSL::Cipher.new "aes-256-cfb"
247
+ # cipher.encrypt
248
+ # new_key = cipher.random_key
249
+ #
250
+ # file.rotate encryption_key: old_key, new_encryption_key: new_key
251
+ # ```
252
+ #
232
253
  # ## Downloading a File
233
254
  #
234
255
  # Files can be downloaded to the local file system. (See
@@ -16,6 +16,7 @@
16
16
  require "google/cloud/storage/bucket/acl"
17
17
  require "google/cloud/storage/bucket/list"
18
18
  require "google/cloud/storage/bucket/cors"
19
+ require "google/cloud/storage/post_object"
19
20
  require "google/cloud/storage/file"
20
21
  require "pathname"
21
22
 
@@ -514,6 +515,16 @@ module Google
514
515
  # @param [Hash] metadata A hash of custom, user-provided web-safe keys
515
516
  # and arbitrary string values that will returned with requests for the
516
517
  # file as "x-goog-meta-" response headers.
518
+ # @param [Symbol, String] storage_class Storage class of the file.
519
+ # Determines how the file is stored and determines the SLA and the
520
+ # cost of storage. Values include `:multi_regional`, `:regional`,
521
+ # `:nearline`, `:coldline`, `:standard`, and `:dra` (Durable Reduced
522
+ # Availability), as well as the strings returned by
523
+ # {Bucket#storage_class}. For more information, see [Storage
524
+ # Classes](https://cloud.google.com/storage/docs/storage-classes) and
525
+ # [Per-Object Storage
526
+ # Class](https://cloud.google.com/storage/docs/per-object-storage-class).
527
+ # The default value is the default storage class for the bucket.
517
528
  # @param [String] encryption_key Optional. A customer-supplied, AES-256
518
529
  # encryption key that will be used to encrypt the file.
519
530
  #
@@ -540,7 +551,6 @@ module Google
540
551
  #
541
552
  # @example Providing a customer-supplied encryption key:
542
553
  # require "google/cloud/storage"
543
- # require "digest/sha2"
544
554
  #
545
555
  # storage = Google::Cloud::Storage.new
546
556
  # bucket = storage.bucket "my-bucket"
@@ -562,14 +572,14 @@ module Google
562
572
  content_disposition: nil, content_encoding: nil,
563
573
  content_language: nil, content_type: nil,
564
574
  crc32c: nil, md5: nil, metadata: nil,
565
- encryption_key: nil
575
+ storage_class: nil, encryption_key: nil
566
576
  ensure_service!
567
577
  options = { acl: File::Acl.predefined_rule_for(acl), md5: md5,
568
578
  cache_control: cache_control, content_type: content_type,
569
579
  content_disposition: content_disposition, crc32c: crc32c,
570
- content_encoding: content_encoding,
571
- content_language: content_language, metadata: metadata,
572
- key: encryption_key }
580
+ content_encoding: content_encoding, metadata: metadata,
581
+ content_language: content_language, key: encryption_key,
582
+ storage_class: storage_class_for(storage_class) }
573
583
  ensure_file_exists! file
574
584
  # TODO: Handle file as an IO and path is missing more gracefully
575
585
  path ||= Pathname(file).to_path
@@ -676,6 +686,114 @@ module Google
676
686
  signer.signed_url options
677
687
  end
678
688
 
689
+ ##
690
+ # Generate a PostObject that includes the fields and url to
691
+ # upload objects via html forms.
692
+ #
693
+ # Generating a PostObject requires service account credentials,
694
+ # either by connecting with a service account when calling
695
+ # {Google::Cloud.storage}, or by passing in the service account
696
+ # `issuer` and `signing_key` values. Although the private key can
697
+ # be passed as a string for convenience, creating and storing
698
+ # an instance of # `OpenSSL::PKey::RSA` is more efficient
699
+ # when making multiple calls to `post_object`.
700
+ #
701
+ # A {SignedUrlUnavailable} is raised if the service account credentials
702
+ # are missing. Service account credentials are acquired by following the
703
+ # steps in [Service Account Authentication](
704
+ # https://cloud.google.com/storage/docs/authentication#service_accounts).
705
+ #
706
+ # @see https://cloud.google.com/storage/docs/xml-api/post-object
707
+ #
708
+ # @param [String] path Path to of the file in Google Cloud Storage.
709
+ # @param [Hash] policy The security policy that describes what
710
+ # can and cannot be uploaded in the form. When provided,
711
+ # the PostObject fields will include a Signature based on the JSON
712
+ # representation of this Hash and the same policy in Base64 format.
713
+ # If you do not provide a security policy, requests are considered
714
+ # to be anonymous and will only work with buckets that have granted
715
+ # WRITE or FULL_CONTROL permission to anonymous users.
716
+ # See [Policy Document](https://cloud.google.com/storage/docs/xml-api/post-object#policydocument)
717
+ # for more information.
718
+ # @param [String] issuer Service Account's Client Email.
719
+ # @param [String] client_email Service Account's Client Email.
720
+ # @param [OpenSSL::PKey::RSA, String] signing_key Service Account's
721
+ # Private Key.
722
+ # @param [OpenSSL::PKey::RSA, String] private_key Service Account's
723
+ # Private Key.
724
+ #
725
+ # @return [PostObject]
726
+ #
727
+ # @example
728
+ # require "google/cloud/storage"
729
+ #
730
+ # storage = Google::Cloud::Storage.new
731
+ #
732
+ # bucket = storage.bucket "my-todo-app"
733
+ # post = bucket.post_object "avatars/heidi/400x400.png"
734
+ #
735
+ # post.url #=> "https://storage.googleapis.com"
736
+ # post.fields[:key] #=> "my-todo-app/avatars/heidi/400x400.png"
737
+ # post.fields[:GoogleAccessId] #=> "0123456789@gserviceaccount.com"
738
+ # post.fields[:signature] #=> "ABC...XYZ="
739
+ # post.fields[:policy] #=> "ABC...XYZ="
740
+ #
741
+ # @example Using a policy to define the upload authorization:
742
+ # require "google/cloud/storage"
743
+ #
744
+ # storage = Google::Cloud::Storage.new
745
+ #
746
+ # policy = {
747
+ # expiration: (Time.now + 3600).iso8601,
748
+ # conditions: [
749
+ # ["starts-with", "$key", ""],
750
+ # {acl: "bucket-owner-read"},
751
+ # {bucket: "travel-maps"},
752
+ # {success_action_redirect: "http://example.com/success.html"},
753
+ # ["eq", "$Content-Type", "image/jpeg"],
754
+ # ["content-length-range", 0, 1000000]
755
+ # ]
756
+ # }
757
+ #
758
+ # bucket = storage.bucket "my-todo-app"
759
+ # post = bucket.post_object "avatars/heidi/400x400.png",
760
+ # policy: policy
761
+ #
762
+ # post.url #=> "https://storage.googleapis.com"
763
+ # post.fields[:key] #=> "my-todo-app/avatars/heidi/400x400.png"
764
+ # post.fields[:GoogleAccessId] #=> "0123456789@gserviceaccount.com"
765
+ # post.fields[:signature] #=> "ABC...XYZ="
766
+ # post.fields[:policy] #=> "ABC...XYZ="
767
+ #
768
+ # @example Using the issuer and signing_key options:
769
+ # require "google/cloud/storage"
770
+ #
771
+ # storage = Google::Cloud::Storage.new
772
+ #
773
+ # bucket = storage.bucket "my-todo-app"
774
+ # key = OpenSSL::PKey::RSA.new
775
+ # post = bucket.post_object "avatars/heidi/400x400.png",
776
+ # issuer: "service-account@gcloud.com",
777
+ # signing_key: key
778
+ #
779
+ # post.url #=> "https://storage.googleapis.com"
780
+ # post.fields[:key] #=> "my-todo-app/avatars/heidi/400x400.png"
781
+ # post.fields[:GoogleAccessId] #=> "0123456789@gserviceaccount.com"
782
+ # post.fields[:signature] #=> "ABC...XYZ="
783
+ # post.fields[:policy] #=> "ABC...XYZ="
784
+ #
785
+ def post_object path, policy: nil, issuer: nil,
786
+ client_email: nil, signing_key: nil,
787
+ private_key: nil
788
+ ensure_service!
789
+ options = { issuer: issuer, client_email: client_email,
790
+ signing_key: signing_key, private_key: private_key,
791
+ policy: policy }
792
+
793
+ signer = File::Signer.from_bucket self, path
794
+ signer.post_object options
795
+ end
796
+
679
797
  ##
680
798
  # The Bucket::Acl instance used to control access to the bucket.
681
799
  #
@@ -806,6 +924,18 @@ module Google
806
924
  fail ArgumentError, "cannot find file #{file}"
807
925
  end
808
926
 
927
+ def storage_class_for str
928
+ return nil if str.nil?
929
+ { "durable_reduced_availability" => "DURABLE_REDUCED_AVAILABILITY",
930
+ "dra" => "DURABLE_REDUCED_AVAILABILITY",
931
+ "durable" => "DURABLE_REDUCED_AVAILABILITY",
932
+ "nearline" => "NEARLINE",
933
+ "coldline" => "COLDLINE",
934
+ "multi_regional" => "MULTI_REGIONAL",
935
+ "regional" => "REGIONAL",
936
+ "standard" => "STANDARD" }[str.to_s.downcase] || str.to_s
937
+ end
938
+
809
939
  ##
810
940
  # Yielded to a block to accumulate changes for a patch request.
811
941
  class Updater < Bucket
@@ -21,6 +21,8 @@ require "google/cloud/storage/file/verifier"
21
21
  module Google
22
22
  module Cloud
23
23
  module Storage
24
+ GOOGLEAPIS_URL = "https://storage.googleapis.com".freeze
25
+
24
26
  ##
25
27
  # # File
26
28
  #
@@ -265,6 +267,35 @@ module Google
265
267
  Base64.decode64 @gapi.customer_encryption.key_sha256
266
268
  end
267
269
 
270
+ ##
271
+ # The file's storage class. This defines how the file is stored and
272
+ # determines the SLA and the cost of storage. For more information, see
273
+ # [Storage
274
+ # Classes](https://cloud.google.com/storage/docs/storage-classes) and
275
+ # [Per-Object Storage
276
+ # Class](https://cloud.google.com/storage/docs/per-object-storage-class).
277
+ def storage_class
278
+ @gapi.storage_class
279
+ end
280
+
281
+ ##
282
+ # Updates how the file is stored and determines the SLA and the cost of
283
+ # storage. Values include `:multi_regional`, `:regional`, `:nearline`,
284
+ # `:coldline`, `:standard`, and `:dra` (Durable Reduced Availability),
285
+ # as well as the strings returned by {File#storage_class} or
286
+ # {Bucket#storage_class}. For more information, see [Storage
287
+ # Classes](https://cloud.google.com/storage/docs/storage-classes) and
288
+ # [Per-Object Storage
289
+ # Class](https://cloud.google.com/storage/docs/per-object-storage-class).
290
+ # The default value is the default storage class for the bucket. See
291
+ # {Bucket#storage_class}.
292
+ # @param [Symbol, String] storage_class Storage class of the file.
293
+ def storage_class= storage_class
294
+ resp = service.update_file_storage_class \
295
+ bucket, name, storage_class_for(storage_class)
296
+ @gapi = resp.resource
297
+ end
298
+
268
299
  ##
269
300
  # Updates the file with changes made in the given block in a single
270
301
  # PATCH request. The following attributes may be set: {#cache_control=},
@@ -460,6 +491,63 @@ module Google
460
491
  File.from_gapi gapi, service
461
492
  end
462
493
 
494
+ ##
495
+ # [Rewrites](https://cloud.google.com/storage/docs/json_api/v1/objects/rewrite)
496
+ # the file to the same {#bucket} and {#name} with a new
497
+ # [customer-supplied encryption
498
+ # key](https://cloud.google.com/storage/docs/encryption#customer-supplied).
499
+ #
500
+ # If a new key is provided to this method, the new key must be used to
501
+ # subsequently download or copy the file. You must securely manage your
502
+ # keys and ensure that they are not lost. Also, please note that file
503
+ # metadata is not encrypted, with the exception of the CRC32C checksum
504
+ # and MD5 hash. The names of files and buckets are also not encrypted,
505
+ # and you can read or update the metadata of an encrypted file without
506
+ # providing the encryption key.
507
+ #
508
+ # @see https://cloud.google.com/storage/docs/encryption
509
+ #
510
+ # @param [String, nil] encryption_key Optional. The last
511
+ # customer-supplied, AES-256 encryption key used to encrypt the file,
512
+ # if one was used.
513
+ # @param [String, nil] new_encryption_key Optional. The new
514
+ # customer-supplied, AES-256 encryption key with which to encrypt the
515
+ # file. If `nil`, the rewritten file will be encrypted using the
516
+ # default server-side encryption, not customer-supplied encryption
517
+ # keys.
518
+ #
519
+ # @return [Google::Cloud::Storage::File]
520
+ #
521
+ # @example The file will be rewritten with a new encryption key:
522
+ # require "google/cloud/storage"
523
+ #
524
+ # storage = Google::Cloud::Storage.new
525
+ # bucket = storage.bucket "my-bucket"
526
+ #
527
+ # # Old key was stored securely for later use.
528
+ # old_key = "y\x03\"\x0E\xB6\xD3\x9B\x0E\xAB*\x19\xFAv\xDEY\xBEI..."
529
+ #
530
+ # file = bucket.file "path/to/my-file.ext", encryption_key: old_key
531
+ #
532
+ # # Key generation shown for example purposes only. Write your own.
533
+ # cipher = OpenSSL::Cipher.new "aes-256-cfb"
534
+ # cipher.encrypt
535
+ # new_key = cipher.random_key
536
+ #
537
+ # file.rotate encryption_key: old_key, new_encryption_key: new_key
538
+ #
539
+ def rotate encryption_key: nil, new_encryption_key: nil
540
+ ensure_service!
541
+ options = { source_key: encryption_key,
542
+ destination_key: new_encryption_key }
543
+ gapi = service.rewrite_file bucket, name, bucket, name, options
544
+ until gapi.done
545
+ options[:token] = gapi.rewrite_token
546
+ gapi = service.rewrite_file bucket, name, bucket, name, options
547
+ end
548
+ File.from_gapi gapi.resource, service
549
+ end
550
+
463
551
  ##
464
552
  # Permanently deletes the file.
465
553
  #
@@ -723,6 +811,18 @@ module Google
723
811
  file
724
812
  end
725
813
 
814
+ def storage_class_for str
815
+ return nil if str.nil?
816
+ { "durable_reduced_availability" => "DURABLE_REDUCED_AVAILABILITY",
817
+ "dra" => "DURABLE_REDUCED_AVAILABILITY",
818
+ "durable" => "DURABLE_REDUCED_AVAILABILITY",
819
+ "nearline" => "NEARLINE",
820
+ "coldline" => "COLDLINE",
821
+ "multi_regional" => "MULTI_REGIONAL",
822
+ "regional" => "REGIONAL",
823
+ "standard" => "STANDARD" }[str.to_s.downcase] || str.to_s
824
+ end
825
+
726
826
  ##
727
827
  # @private Create a signed_url for a file.
728
828
  class Signer
@@ -749,7 +849,7 @@ module Google
749
849
  ##
750
850
  # The external url to the file.
751
851
  def ext_url
752
- "https://storage.googleapis.com#{ext_path}"
852
+ "#{GOOGLEAPIS_URL}#{ext_path}"
753
853
  end
754
854
 
755
855
  def apply_option_defaults options
@@ -775,6 +875,33 @@ module Google
775
875
  @service.credentials.issuer
776
876
  end
777
877
 
878
+ def post_object options
879
+ options = apply_option_defaults options
880
+
881
+ fields = {
882
+ key: ext_path.sub("/", "")
883
+ }
884
+
885
+ p = options[:policy] || {}
886
+ fail "Policy must be given in a Hash" unless p.is_a? Hash
887
+
888
+ i = determine_issuer options
889
+ s = determine_signing_key options
890
+
891
+ fail SignedUrlUnavailable unless i && s
892
+
893
+ policy_str = p.to_json
894
+ policy = Base64.strict_encode64(policy_str).delete("\n")
895
+
896
+ signature = generate_signature s, policy
897
+
898
+ fields[:GoogleAccessId] = i
899
+ fields[:signature] = signature
900
+ fields[:policy] = policy
901
+
902
+ Google::Cloud::Storage::PostObject.new GOOGLEAPIS_URL, fields
903
+ end
904
+
778
905
  def signed_url options
779
906
  options = apply_option_defaults options
780
907
 
@@ -783,22 +910,22 @@ module Google
783
910
 
784
911
  fail SignedUrlUnavailable unless i && s
785
912
 
786
- sig = generate_signature s, options
913
+ sig = generate_signature s, signature_str(options)
787
914
  generate_signed_url i, sig, options[:expires]
788
915
  end
789
916
 
790
- def generate_signature signing_key, options = {}
917
+ def generate_signature signing_key, secret
791
918
  unless signing_key.respond_to? :sign
792
919
  signing_key = OpenSSL::PKey::RSA.new signing_key
793
920
  end
794
- signing_key.sign OpenSSL::Digest::SHA256.new, signature_str(options)
921
+ signature = signing_key.sign OpenSSL::Digest::SHA256.new, secret
922
+ Base64.strict_encode64(signature).delete("\n")
795
923
  end
796
924
 
797
925
  def generate_signed_url issuer, signed_string, expires
798
- signature = Base64.strict_encode64(signed_string).delete("\n")
799
926
  "#{ext_url}?GoogleAccessId=#{CGI.escape issuer}" \
800
927
  "&Expires=#{expires}" \
801
- "&Signature=#{CGI.escape signature}"
928
+ "&Signature=#{CGI.escape signed_string}"
802
929
  end
803
930
 
804
931
  def format_extension_headers headers
@@ -815,9 +942,15 @@ module Google
815
942
  ##
816
943
  # Yielded to a block to accumulate changes for a patch request.
817
944
  class Updater < File
945
+ # @private Do not allow storage_class to be set in an update call.
946
+ # It cannot be set with PATCH.
947
+ undef :storage_class=
948
+
949
+ # @private
818
950
  attr_reader :updates
951
+
819
952
  ##
820
- # Create an Updater object.
953
+ # @private Create an Updater object.
821
954
  def initialize gapi
822
955
  @updates = []
823
956
  @gapi = gapi
@@ -0,0 +1,55 @@
1
+ # Copyright 2014 Google Inc. All rights reserved.
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
+ # http://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 Storage
19
+ ##
20
+ # PostObject represents the URL, fields, and values needed to upload
21
+ # objects via html forms.
22
+ #
23
+ # @see https://cloud.google.com/storage/docs/xml-api/post-object
24
+ #
25
+ # @attr_reader [String] url The URL the form must post to.
26
+ # @attr_reader [Hash] fields The input fields that must be included in the
27
+ # form. Each key/value pair should be set as an input tag's name and
28
+ # value.
29
+ #
30
+ # @example
31
+ # require "google/cloud/storage"
32
+ #
33
+ # storage = Google::Cloud::Storage.new
34
+ #
35
+ # bucket = storage.bucket "my-todo-app"
36
+ # post = bucket.post_object "avatars/heidi/400x400.png"
37
+ #
38
+ # post.url #=> "https://storage.googleapis.com"
39
+ # post.fields[:key] #=> "my-todo-app/avatars/heidi/400x400.png"
40
+ # post.fields[:GoogleAccessId] #=> "0123456789@gserviceaccount.com"
41
+ # post.fields[:signature] #=> "ABC...XYZ="
42
+ # post.fields[:policy] #=> "ABC...XYZ="
43
+ #
44
+ class PostObject
45
+ attr_reader :url, :fields
46
+
47
+ # @private
48
+ def initialize url, fields
49
+ @url = url
50
+ @fields = fields
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -231,7 +231,7 @@ module Google
231
231
  # Values include `:multi_regional`, `:regional`, `:nearline`,
232
232
  # `:coldline`, `:standard`, and `:dra` (Durable Reduced
233
233
  # Availability), as well as the strings returned by
234
- # Bucket#storage_class. For more information, see [Storage
234
+ # {Bucket#storage_class}. For more information, see [Storage
235
235
  # Classes](https://cloud.google.com/storage/docs/storage-classes). The
236
236
  # default value is `:standard`, which is equivalent to
237
237
  # `:multi_regional` or `:regional` depending on the bucket's location
@@ -306,6 +306,7 @@ module Google
306
306
  end
307
307
 
308
308
  def storage_class_for str
309
+ return nil if str.nil?
309
310
  { "durable_reduced_availability" => "DURABLE_REDUCED_AVAILABILITY",
310
311
  "dra" => "DURABLE_REDUCED_AVAILABILITY",
311
312
  "durable" => "DURABLE_REDUCED_AVAILABILITY",
@@ -313,7 +314,7 @@ module Google
313
314
  "coldline" => "COLDLINE",
314
315
  "multi_regional" => "MULTI_REGIONAL",
315
316
  "regional" => "REGIONAL",
316
- "standard" => "STANDARD" }[str.to_s.downcase]
317
+ "standard" => "STANDARD" }[str.to_s.downcase] || str.to_s
317
318
  end
318
319
  end
319
320
  end
@@ -171,12 +171,13 @@ module Google
171
171
  cache_control: nil, content_disposition: nil,
172
172
  content_encoding: nil, content_language: nil,
173
173
  content_type: nil, crc32c: nil, md5: nil, metadata: nil,
174
- key: nil
174
+ storage_class: nil, key: nil
175
175
  file_obj = Google::Apis::StorageV1::Object.new \
176
176
  cache_control: cache_control, content_type: content_type,
177
177
  content_disposition: content_disposition, md5_hash: md5,
178
178
  content_encoding: content_encoding, crc32c: crc32c,
179
- content_language: content_language, metadata: metadata
179
+ content_language: content_language, metadata: metadata,
180
+ storage_class: storage_class
180
181
  content_type ||= mime_type_for(Pathname(source).to_path)
181
182
  execute do
182
183
  service.insert_object \
@@ -213,6 +214,35 @@ module Google
213
214
  end
214
215
  end
215
216
 
217
+ ## Rewrite a file from source bucket/object to a
218
+ # destination bucket/object.
219
+ def rewrite_file source_bucket_name, source_file_path,
220
+ destination_bucket_name, destination_file_path,
221
+ options = {}
222
+ options = rewrite_key_options options[:source_key],
223
+ options[:destination_key]
224
+ execute do
225
+ service.rewrite_object \
226
+ source_bucket_name, source_file_path,
227
+ destination_bucket_name, destination_file_path,
228
+ destination_predefined_acl: options[:acl],
229
+ source_generation: options[:generation],
230
+ rewrite_token: options[:token],
231
+ options: options
232
+ end
233
+ end
234
+
235
+ ## Rewrite a file from source bucket/object to a
236
+ # destination bucket/object.
237
+ def update_file_storage_class bucket_name, file_path, storage_class
238
+ execute do
239
+ service.rewrite_object \
240
+ bucket_name, file_path,
241
+ bucket_name, file_path,
242
+ Google::Apis::StorageV1::Object.new(storage_class: storage_class)
243
+ end
244
+ end
245
+
216
246
  ##
217
247
  # Download contents of a file.
218
248
  def download_file bucket_name, file_path, target_path, generation: nil,
@@ -285,15 +315,32 @@ module Google
285
315
 
286
316
  def key_options key
287
317
  options = {}
288
- if key
289
- key_sha256 = Digest::SHA256.digest key
290
- headers = {}
291
- headers["x-goog-encryption-algorithm"] = "AES256"
292
- headers["x-goog-encryption-key"] = Base64.strict_encode64 key
293
- headers["x-goog-encryption-key-sha256"] = \
294
- Base64.strict_encode64 key_sha256
295
- options[:header] = headers
318
+ encryption_key_headers options, key if key
319
+ options
320
+ end
321
+
322
+ def rewrite_key_options source_key, destination_key
323
+ options = {}
324
+ if source_key
325
+ encryption_key_headers options, source_key, copy_source: true
296
326
  end
327
+ encryption_key_headers options, destination_key if destination_key
328
+ options
329
+ end
330
+
331
+ # @private
332
+ # @param copy_source If true, header names are those for source object
333
+ # in rewrite request. If false, the header names are for use with any
334
+ # method supporting customer-supplied encryption keys.
335
+ # See https://cloud.google.com/storage/docs/encryption#request
336
+ def encryption_key_headers options, key, copy_source: false
337
+ source = copy_source ? "copy-source-" : ""
338
+ key_sha256 = Digest::SHA256.digest key
339
+ headers = (options[:header] ||= {})
340
+ headers["x-goog-#{source}encryption-algorithm"] = "AES256"
341
+ headers["x-goog-#{source}encryption-key"] = Base64.strict_encode64 key
342
+ headers["x-goog-#{source}encryption-key-sha256"] = \
343
+ Base64.strict_encode64 key_sha256
297
344
  options
298
345
  end
299
346
 
@@ -16,7 +16,7 @@
16
16
  module Google
17
17
  module Cloud
18
18
  module Storage
19
- VERSION = "0.23.1"
19
+ VERSION = "0.23.2"
20
20
  end
21
21
  end
22
22
  end
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: 0.23.1
4
+ version: 0.23.2
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: 2016-12-14 00:00:00.000000000 Z
12
+ date: 2017-02-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: google-cloud-core
@@ -59,14 +59,14 @@ dependencies:
59
59
  requirements:
60
60
  - - "~>"
61
61
  - !ruby/object:Gem::Version
62
- version: '5.9'
62
+ version: '5.10'
63
63
  type: :development
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
67
  - - "~>"
68
68
  - !ruby/object:Gem::Version
69
- version: '5.9'
69
+ version: '5.10'
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: minitest-autotest
72
72
  requirement: !ruby/object:Gem::Requirement
@@ -169,14 +169,14 @@ dependencies:
169
169
  name: yard-doctest
170
170
  requirement: !ruby/object:Gem::Requirement
171
171
  requirements:
172
- - - "~>"
172
+ - - "<="
173
173
  - !ruby/object:Gem::Version
174
174
  version: 0.1.8
175
175
  type: :development
176
176
  prerelease: false
177
177
  version_requirements: !ruby/object:Gem::Requirement
178
178
  requirements:
179
- - - "~>"
179
+ - - "<="
180
180
  - !ruby/object:Gem::Version
181
181
  version: 0.1.8
182
182
  description: google-cloud-storage is the official library for Google Cloud Storage.
@@ -202,6 +202,7 @@ files:
202
202
  - lib/google/cloud/storage/file/acl.rb
203
203
  - lib/google/cloud/storage/file/list.rb
204
204
  - lib/google/cloud/storage/file/verifier.rb
205
+ - lib/google/cloud/storage/post_object.rb
205
206
  - lib/google/cloud/storage/project.rb
206
207
  - lib/google/cloud/storage/service.rb
207
208
  - lib/google/cloud/storage/version.rb
@@ -225,7 +226,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
225
226
  version: '0'
226
227
  requirements: []
227
228
  rubyforge_project:
228
- rubygems_version: 2.4.5.1
229
+ rubygems_version: 2.6.10
229
230
  signing_key:
230
231
  specification_version: 4
231
232
  summary: API Client library for Google Cloud Storage