From 2e2d447ff007660ac1481e88b2dcb1bc147941b0 Mon Sep 17 00:00:00 2001 From: Shubhangi Singh Date: Wed, 11 Mar 2026 08:37:03 +0000 Subject: [PATCH 1/2] adding functionality and test --- .../bucket_list_object_contexts_test.rb | 71 +++++++++ .../acceptance/storage/file_test.rb | 93 ++++++++++++ .../acceptance/storage_helper.rb | 21 +++ .../lib/google/cloud/storage/bucket.rb | 33 ++++- .../lib/google/cloud/storage/file.rb | 39 +++++ .../lib/google/cloud/storage/file/list.rb | 3 +- .../lib/google/cloud/storage/service.rb | 3 +- .../samples/acceptance/files_test.rb | 74 ++++++++++ .../samples/storage_delete_object_contexts.rb | 56 +++++++ .../samples/storage_get_metadata.rb | 1 + .../samples/storage_get_object_contexts.rb | 43 ++++++ .../samples/storage_list_object_contexts.rb | 45 ++++++ .../samples/storage_set_object_contexts.rb | 53 +++++++ .../storage/bucket_objects_contexts_test.rb | 137 ++++++++++++++++++ .../test/google/cloud/storage/bucket_test.rb | 78 +++++----- .../test/google/cloud/storage/file_test.rb | 4 +- .../google/cloud/storage/lazy/bucket_test.rb | 76 +++++----- .../cloud/storage/project_anonymous_test.rb | 2 +- google-cloud-storage/test/helper.rb | 31 +++- 19 files changed, 772 insertions(+), 91 deletions(-) create mode 100644 google-cloud-storage/acceptance/storage/bucket_list_object_contexts_test.rb create mode 100644 google-cloud-storage/samples/storage_delete_object_contexts.rb create mode 100644 google-cloud-storage/samples/storage_get_object_contexts.rb create mode 100644 google-cloud-storage/samples/storage_list_object_contexts.rb create mode 100644 google-cloud-storage/samples/storage_set_object_contexts.rb create mode 100644 google-cloud-storage/test/google/cloud/storage/bucket_objects_contexts_test.rb diff --git a/google-cloud-storage/acceptance/storage/bucket_list_object_contexts_test.rb b/google-cloud-storage/acceptance/storage/bucket_list_object_contexts_test.rb new file mode 100644 index 000000000000..501102841a83 --- /dev/null +++ b/google-cloud-storage/acceptance/storage/bucket_list_object_contexts_test.rb @@ -0,0 +1,71 @@ +# Copyright 2026 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 "storage_helper" +require 'pry' + +describe Google::Cloud::Storage::Bucket, :contexts, :storage do + let(:bucket_name) { $bucket_names[0] } + let :bucket do + storage.bucket(bucket_name) || + storage.create_bucket(bucket_name) + end + let(:custom_context_key1) { "my-custom-key" } + let(:custom_context_value1) { "my-custom-value" } + let(:custom_context_key2) { "my-custom-key-2" } + let(:custom_context_value2) { "my-custom-value-2" } + + let(:local_file) { "acceptance/data/CloudPlatform_128px_Retina.png" } + let(:file_name) { "CloudLogo1" } + let(:file_name2) { "CloudLogo2" } + + before(:all) do + bucket.create_file local_file, file_name + bucket.create_file local_file, file_name2 + custom_hash1 = context_custom_hash custom_context_key: custom_context_key1, custom_context_value: custom_context_value1 + custom_hash2 = context_custom_hash custom_context_key: custom_context_key2, custom_context_value: custom_context_value2 + set_object_contexts bucket_name: bucket.name, file_name: file_name, custom_context_key: custom_context_key1, custom_context_value: custom_context_value1 + set_object_contexts bucket_name: bucket.name, file_name: file_name2, custom_context_key: custom_context_key2, custom_context_value: custom_context_value2 + end + + it "lists objects with a specific context key and value" do + list = bucket.files filter: "contexts.\"#{custom_context_key1}\"=\"#{custom_context_value1}\"" + list.each do |file| + _(file.name).must_equal file_name + end + end + + it "lists objects with a specific context key" do + list = bucket.files filter: "contexts.\"#{custom_context_key1}\":*" + list.each do |file| + _(file.name).must_equal file_name + end + end + + it "lists objects that do not have a specific context key" do + list = bucket.files filter: "-contexts.\"#{custom_context_key1}\":*" + list.each do |file| + _(file.name).wont_equal file_name + end + end + + it "lists objects that do not have a specific context key and value" do + list = bucket.files filter: "-contexts.\"#{custom_context_key2}\"=\"#{custom_context_value2}\"" + list.each do |file| + _(file.name).must_equal file_name + _(file.name).wont_equal file_name2 + end + end + +end diff --git a/google-cloud-storage/acceptance/storage/file_test.rb b/google-cloud-storage/acceptance/storage/file_test.rb index f6aadc89fcd9..dfd787a53439 100644 --- a/google-cloud-storage/acceptance/storage/file_test.rb +++ b/google-cloud-storage/acceptance/storage/file_test.rb @@ -1044,4 +1044,97 @@ expect { uploaded_file.retention = retention }.must_raise Google::Cloud::PermissionDeniedError end end + + describe "object contexts" do + let(:custom_context_key1) { "my-custom-key" } + let(:custom_context_value1) { "my-custom-value" } + let(:custom_context_key2) { "my-custom-key-2" } + let(:custom_context_value2) { "my-custom-value-2" } + let(:local_file) { "acceptance/data/CloudPlatform_128px_Retina.png" } + let(:file_name) { "CloudLogo1" } + let(:file_name2) { "CloudLogo2" } + + before do + bucket.create_file local_file, file_name + end + + it "sets and retrieves custom context key and value" do + file = bucket.file file_name + file.contexts = Google::Apis::StorageV1::Object::Contexts.new( + custom: context_custom_hash(custom_context_key: custom_context_key1 ,custom_context_value: custom_context_value1) + ) + file.reload! + _(file.contexts.custom[custom_context_key1].value).must_equal custom_context_value1 + end + + it "overwrites existing custom context key and value" do + file = bucket.file file_name + file.contexts = Google::Apis::StorageV1::Object::Contexts.new( + custom: context_custom_hash(custom_context_key: custom_context_key1 ,custom_context_value: custom_context_value1) + ) + file.reload! + _(file.contexts.custom[custom_context_key1].value).must_equal custom_context_value1 + + file.contexts = Google::Apis::StorageV1::Object::Contexts.new( + custom: context_custom_hash(custom_context_key: custom_context_key1 ,custom_context_value: custom_context_value2) + ) + file.reload! + _(file.contexts.custom[custom_context_key1].value).must_equal custom_context_value2 + end + + it "sets and retrieves multiple custom context keys and values" do + file = bucket.file file_name + custom_hash1 = context_custom_hash custom_context_key: custom_context_key1, custom_context_value: custom_context_value1 + custom_hash2 = context_custom_hash custom_context_key: custom_context_key2, custom_context_value: custom_context_value2 + file.contexts = Google::Apis::StorageV1::Object::Contexts.new( + custom: { + custom_context_key1 => custom_hash1[custom_context_key1], + custom_context_key2 => custom_hash2[custom_context_key2] + } + ) + file.reload! + _(file.contexts.custom[custom_context_key1].value).must_equal custom_context_value1 + _(file.contexts.custom[custom_context_key2].value).must_equal custom_context_value2 + end + + it "deletes custom context keys and values" do + file = bucket.file file_name + custom_hash1 = context_custom_hash custom_context_key: custom_context_key1, custom_context_value: custom_context_value1 + custom_hash2 = context_custom_hash custom_context_key: custom_context_key2, custom_context_value: custom_context_value2 + file.contexts = Google::Apis::StorageV1::Object::Contexts.new( + custom: { + custom_context_key1 => custom_hash1[custom_context_key1], + custom_context_key2 => custom_hash2[custom_context_key2] + } + ) + file.reload! + _(file.contexts.custom[custom_context_key1].value).must_equal custom_context_value1 + _(file.contexts.custom[custom_context_key2].value).must_equal custom_context_value2 + + file.contexts = Google::Apis::StorageV1::Object::Contexts.new( + custom: { + custom_context_key1 => nil + } + ) + file.reload! + _(file.contexts.custom[custom_context_key1]).must_be_nil + _(file.contexts.custom[custom_context_key2].value).must_equal custom_context_value2 + end + + it "deletes object contexts" do + file = bucket.file file_name + custom_hash1 = context_custom_hash custom_context_key: custom_context_key1, custom_context_value: custom_context_value1 + file.contexts = Google::Apis::StorageV1::Object::Contexts.new( + custom: { + custom_context_key1=> custom_hash1[custom_context_key1] + } + ) + file.reload! + _(file.contexts.custom[custom_context_key1].value).must_equal custom_context_value1 + + file.contexts = nil + file.reload! + _(file.contexts).must_be_nil + end + end end diff --git a/google-cloud-storage/acceptance/storage_helper.rb b/google-cloud-storage/acceptance/storage_helper.rb index 3e10cc64ede0..00acabb3c803 100644 --- a/google-cloud-storage/acceptance/storage_helper.rb +++ b/google-cloud-storage/acceptance/storage_helper.rb @@ -206,6 +206,27 @@ def clean_up_storage_bucket bucket puts "Error while cleaning up bucket #{bucket.name}\n\n#{e}" end +def set_object_contexts bucket_name:, file_name:, custom_context_key:, custom_context_value: + bucket = storage.bucket bucket_name + file = bucket.file file_name + contexts = Google::Apis::StorageV1::Object::Contexts.new( + custom: context_custom_hash(custom_context_key: custom_context_key ,custom_context_value: custom_context_value) + ) + file.update do |file| + file.contexts = contexts + end +end + +def context_custom_hash custom_context_key: ,custom_context_value: + payload = Google::Apis::StorageV1::ObjectCustomContextPayload.new( + value: custom_context_value + ) + custom_hash = { + custom_context_key => payload + } + custom_hash +end + Minitest.after_run do clean_up_storage_buckets if $storage_2 diff --git a/google-cloud-storage/lib/google/cloud/storage/bucket.rb b/google-cloud-storage/lib/google/cloud/storage/bucket.rb index ca8461354bb7..d5798f937859 100644 --- a/google-cloud-storage/lib/google/cloud/storage/bucket.rb +++ b/google-cloud-storage/lib/google/cloud/storage/bucket.rb @@ -1439,7 +1439,23 @@ def delete if_metageneration_match: nil, if_metageneration_not_match: nil # Only applicable if delimiter is set to '/'. # @param [Boolean] soft_deleted If true, only soft-deleted object # versions will be listed. The default is false. + # @param [String] filter An optional string for filtering listed objects. + # Currently only supported for the contexts field. + # If delimiter is set, the returned prefixes are exempt from this filter + # List any object that has a context with the specified key attached + # filter = "contexts.\"KEY\":*"; # + # List any object that has a context with the specified key attached and value attached + # filter = "contexts.\"keyA\"=\"valueA\"" + # + # List any object that does not have a context with the specified key attached + # filter = "-contexts.\"KEY\":*"; + # + # List any object that has a context with the specified key and value attached + # filter = "contexts.\"KEY\"=\"VALUE\""; + # + # List any object that does not have a context with the specified key and value attached + # filter = "-contexts.\"KEY\"=\"VALUE\""; # @return [Array] (See # {Google::Cloud::Storage::File::List}) # @@ -1465,9 +1481,18 @@ def delete if_metageneration_match: nil, if_metageneration_not_match: nil # puts file.name # end # + # @example Filter files by context: + # require "google/cloud/storage" + # storage = Google::Cloud::Storage.new + # bucket = storage.bucket "my-bucket" + # files = bucket.files filter: "contexts.\"myKey\"=\"myValue\"" + # files.each do |file| + # puts file.name + # end + # def files prefix: nil, delimiter: nil, token: nil, max: nil, versions: nil, match_glob: nil, include_folders_as_prefixes: nil, - soft_deleted: nil + soft_deleted: nil, filter: nil ensure_service! gapi = service.list_files name, prefix: prefix, delimiter: delimiter, token: token, max: max, @@ -1475,13 +1500,15 @@ def files prefix: nil, delimiter: nil, token: nil, max: nil, user_project: user_project, match_glob: match_glob, include_folders_as_prefixes: include_folders_as_prefixes, - soft_deleted: soft_deleted + soft_deleted: soft_deleted, + filter: filter File::List.from_gapi gapi, service, name, prefix, delimiter, max, versions, user_project: user_project, match_glob: match_glob, include_folders_as_prefixes: include_folders_as_prefixes, - soft_deleted: soft_deleted + soft_deleted: soft_deleted, + filter: filter end alias find_files files diff --git a/google-cloud-storage/lib/google/cloud/storage/file.rb b/google-cloud-storage/lib/google/cloud/storage/file.rb index 8df9f7b13a5a..7e0f37dc6a78 100644 --- a/google-cloud-storage/lib/google/cloud/storage/file.rb +++ b/google-cloud-storage/lib/google/cloud/storage/file.rb @@ -370,6 +370,45 @@ def content_type= content_type update_gapi! :content_type end + ## + # User-defined or system-defined object contexts. Each object context is a key- + # payload pair, where the key provides the identification and the payload holds + # the associated value and additional metadata. + # Object contexts are used to provide additional information about an object and its + # @return [Google::Apis::StorageV1::Object::Contexts, nil] The object contexts, or `nil` if there are none. + + def contexts + @gapi.contexts + end + + ## + # Sets the object context. + # To pass generation and/or metageneration preconditions, call this + # method within a block passed to {#update}. + # @param [Google::Apis::StorageV1::Object::Contexts] contexts The object contexts to set. + # @see https://docs.cloud.google.com/storage/docs/use-object-contexts#attach-modify-contexts Object Contexts documentation + # @example + # require "google/cloud/storage" + # storage = Google::Cloud::Storage.new + # bucket = storage.bucket "my-bucket" + # file = bucket.file "path/to/my-file.ext" + # payload = Google::Apis::StorageV1::ObjectCustomContextPayload.new( + # value: "your-custom-context-value" + # ) + # custom_hash = { + # "your-custom-context-key" => payload + # } + # contexts = Google::Apis::StorageV1::Object::Contexts.new( + # custom: custom_hash + # ) + # file.update do |file| + # file.contexts = contexts + # en + def contexts= contexts + @gapi.contexts = contexts + update_gapi! :contexts + end + ## # A custom time specified by the user for the file, or `nil`. # diff --git a/google-cloud-storage/lib/google/cloud/storage/file/list.rb b/google-cloud-storage/lib/google/cloud/storage/file/list.rb index 631322bd76be..d7e71c1e583e 100644 --- a/google-cloud-storage/lib/google/cloud/storage/file/list.rb +++ b/google-cloud-storage/lib/google/cloud/storage/file/list.rb @@ -167,7 +167,7 @@ def self.from_gapi gapi_list, service, bucket = nil, prefix = nil, delimiter = nil, max = nil, versions = nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, - soft_deleted: nil + soft_deleted: nil, filter: nil files = new(Array(gapi_list.items).map do |gapi_object| File.from_gapi gapi_object, service, user_project: user_project end) @@ -183,6 +183,7 @@ def self.from_gapi gapi_list, service, bucket = nil, prefix = nil, files.instance_variable_set :@match_glob, match_glob files.instance_variable_set :@include_folders_as_prefixes, include_folders_as_prefixes files.instance_variable_set :@soft_deleted, soft_deleted + files.instance_variable_set :@filter, filter files end diff --git a/google-cloud-storage/lib/google/cloud/storage/service.rb b/google-cloud-storage/lib/google/cloud/storage/service.rb index df61e682f8e0..d721509aa08d 100644 --- a/google-cloud-storage/lib/google/cloud/storage/service.rb +++ b/google-cloud-storage/lib/google/cloud/storage/service.rb @@ -372,7 +372,7 @@ def delete_notification bucket_name, notification_id, user_project: nil, options def list_files bucket_name, delimiter: nil, max: nil, token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, - soft_deleted: nil, options: {} + soft_deleted: nil, filter: nil, options: {} execute do service.list_objects \ bucket_name, delimiter: delimiter, max_results: max, @@ -382,6 +382,7 @@ def list_files bucket_name, delimiter: nil, max: nil, token: nil, match_glob: match_glob, include_folders_as_prefixes: include_folders_as_prefixes, soft_deleted: soft_deleted, + filter: filter, options: options end end diff --git a/google-cloud-storage/samples/acceptance/files_test.rb b/google-cloud-storage/samples/acceptance/files_test.rb index c7858d74d2bc..26a630dac660 100644 --- a/google-cloud-storage/samples/acceptance/files_test.rb +++ b/google-cloud-storage/samples/acceptance/files_test.rb @@ -20,6 +20,7 @@ require_relative "../storage_copy_file_archived_generation" require_relative "../storage_delete_file" require_relative "../storage_delete_file_archived_generation" +require_relative "../storage_delete_object_contexts" require_relative "../storage_download_byte_range" require_relative "../storage_download_encrypted_file" require_relative "../storage_download_file" @@ -31,6 +32,8 @@ require_relative "../storage_generate_signed_url_v4" require_relative "../storage_generate_upload_signed_url_v4" require_relative "../storage_get_metadata" +require_relative "../storage_get_object_contexts" +require_relative "../storage_list_object_contexts" require_relative "../storage_list_files" require_relative "../storage_list_files_with_prefix" require_relative "../storage_list_file_archived_generations" @@ -40,6 +43,7 @@ require_relative "../storage_release_event_based_hold" require_relative "../storage_release_temporary_hold" require_relative "../storage_rotate_encryption_key" +require_relative "../storage_set_object_contexts" require_relative "../storage_set_event_based_hold" require_relative "../storage_set_metadata" require_relative "../storage_set_temporary_hold" @@ -293,6 +297,7 @@ def mock_cipher.random_key md5_hash: #{file.md5} Cache-control: #{file.cache_control} Content-type: #{file.content_type} + Contexts: #{file.contexts} Content-disposition: #{file.content_disposition} Content-encoding: #{file.content_encoding} Content-language: #{file.content_language} @@ -310,6 +315,75 @@ def mock_cipher.random_key end end + it "set_object_contexts" do + bucket.create_file local_file, remote_file_name + custom_context_key = "your-custom-context-key" + custom_context_value = "your-custom-context-value" + assert_output "Contexts for #{remote_file_name} has been updated.\n" do + set_object_contexts bucket_name: bucket.name, file_name: remote_file_name, custom_context_key: custom_context_key, custom_context_value: custom_context_value + end + end + + it "get_object_contexts" do + bucket.create_file local_file, remote_file_name + custom_context_key = "my-custom-key" + custom_context_value = "my-custom-value" + set_object_contexts bucket_name: bucket.name, file_name: remote_file_name, custom_context_key: custom_context_key, custom_context_value: custom_context_value + assert_output "Custom Contexts for #{remote_file_name} are: #{custom_context_key} with value: #{custom_context_value}\n" do + get_object_contexts bucket_name: bucket.name, file_name: remote_file_name + end + end + + describe "list_object_contexts" do + let(:custom_context_key1) { "my-custom-key" } + let(:custom_context_value1) { "my-custom-value" } + let(:custom_context_key2) { "my-custom-key-2" } + let(:custom_context_value2) { "my-custom-value-2" } + + before(:all) do + bucket.create_file local_file, remote_file_name + bucket.create_file local_file, remote_file_name+"2" + + set_object_contexts bucket_name: bucket.name, file_name: remote_file_name, custom_context_key: custom_context_key1, custom_context_value: custom_context_value1 + set_object_contexts bucket_name: bucket.name, file_name: remote_file_name+"2", custom_context_key: custom_context_key2, custom_context_value: custom_context_value2 + end + + it "filters out files on the basis of custom context key" do + assert_output "File: #{remote_file_name} has context key: #{custom_context_key1}\n" do + list_object_contexts bucket_name: bucket.name, custom_context_key: custom_context_key1 + end + end + + it "filters out files on the basis of custom context key and value" do + assert_output "File: #{remote_file_name+"2"} has context key: #{custom_context_key2}\n" do + list_object_contexts bucket_name: bucket.name, custom_context_key: custom_context_key2, custom_context_value: custom_context_value2 + end + end + + end + + describe "delete object contexts" do + let(:custom_context_key) { "my-custom-key" } + let(:custom_context_value) { "my-custom-value" } + let(:custom_context_key2) { "my-custom-key-2" } + let(:custom_context_value2) { "my-custom-value-2" } + + before(:all) do + bucket.create_file local_file, remote_file_name + set_object_contexts bucket_name: bucket.name, file_name: remote_file_name, custom_context_key: custom_context_key, custom_context_value: custom_context_value + set_object_contexts bucket_name: bucket.name, file_name: remote_file_name, custom_context_key: custom_context_key2, custom_context_value: custom_context_value2 + end + + it "deletes the custom object contexts when nil is passed in value" do + assert_output "Contexts for #{remote_file_name} has been deleted.\n" do + delete_object_contexts bucket_name: bucket.name, file_name: remote_file_name, custom_context_key: custom_context_key, custom_context_value: nil + end + + assert_nil bucket.file(remote_file_name).contexts.custom[custom_context_key] + refute_nil bucket.file(remote_file_name).contexts.custom[custom_context_key2] + end + end + it "set_metadata" do bucket.create_file local_file, remote_file_name diff --git a/google-cloud-storage/samples/storage_delete_object_contexts.rb b/google-cloud-storage/samples/storage_delete_object_contexts.rb new file mode 100644 index 000000000000..4a7ccfc2a611 --- /dev/null +++ b/google-cloud-storage/samples/storage_delete_object_contexts.rb @@ -0,0 +1,56 @@ +# Copyright 2026 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 +# +# http://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/storage" + +# [START storage_delete_object_contexts] +def delete_object_contexts bucket_name:, file_name:, custom_context_key:, custom_context_value: nil + # The ID of your GCS bucket + # bucket_name = "your-unique-bucket-name" + + # The ID of your GCS object + # file_name = "your-file-name" + + # The key and value of the custom context to be added + # custom_context_key = "your-custom-context-key" + # custom_context_value = "your-custom-context-value" + + storage = Google::Cloud::Storage.new + bucket = storage.bucket bucket_name + file = bucket.file file_name + + # If value is nil, the payload itself is nil, which triggers a deletion for that key. + payload = if custom_context_value + Google::Apis::StorageV1::ObjectCustomContextPayload.new.tap do |p| + p.value = custom_context_value + end + end + custom_hash = { + custom_context_key => payload + } + contexts = Google::Apis::StorageV1::Object::Contexts.new( + custom: custom_hash + ) + file.update do |file| + file.contexts = contexts + end + + puts "Contexts for #{file_name} has been deleted." +end +# [END storage_delete_object_contexts] + +if $PROGRAM_NAME == __FILE__ + delete_object_contexts bucket_name: ARGV.shift, file_name: ARGV.shift, + custom_context_key: ARGV.shift, custom_context_value: ARGV.shift +end diff --git a/google-cloud-storage/samples/storage_get_metadata.rb b/google-cloud-storage/samples/storage_get_metadata.rb index 447a5bb0da4e..ada820a3e32f 100644 --- a/google-cloud-storage/samples/storage_get_metadata.rb +++ b/google-cloud-storage/samples/storage_get_metadata.rb @@ -41,6 +41,7 @@ def get_metadata bucket_name:, file_name: puts "md5_hash: #{file.md5}" puts "Cache-control: #{file.cache_control}" puts "Content-type: #{file.content_type}" + puts "Contexts: #{file.contexts}" puts "Content-disposition: #{file.content_disposition}" puts "Content-encoding: #{file.content_encoding}" puts "Content-language: #{file.content_language}" diff --git a/google-cloud-storage/samples/storage_get_object_contexts.rb b/google-cloud-storage/samples/storage_get_object_contexts.rb new file mode 100644 index 000000000000..f2618100d2ae --- /dev/null +++ b/google-cloud-storage/samples/storage_get_object_contexts.rb @@ -0,0 +1,43 @@ +# Copyright 2026 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 +# +# http://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/storage" + +# [START storage_get_object_contexts] +def get_object_contexts bucket_name:, file_name: + # The ID of your GCS bucket + # bucket_name = "your-unique-bucket-name" + + # The ID of your GCS object + # file_name = "your-file-name" + + # The key and value of the custom context to be added + # custom_context_key = "your-custom-context-key" + # custom_context_value = "your-custom-context-value" + + storage = Google::Cloud::Storage.new + bucket = storage.bucket bucket_name + file = bucket.file file_name + + contexts = file.contexts + custom_context_key = contexts.custom.keys.first + custom_context_value = contexts.custom[custom_context_key].value + puts "Custom Contexts for #{file_name} are: #{custom_context_key} with value: #{custom_context_value}" +end +# [END storage_get_object_contexts] + +if $PROGRAM_NAME == __FILE__ + get_object_contexts bucket_name: ARGV.shift, file_name: ARGV.shift +end + diff --git a/google-cloud-storage/samples/storage_list_object_contexts.rb b/google-cloud-storage/samples/storage_list_object_contexts.rb new file mode 100644 index 000000000000..08bd31e39d3f --- /dev/null +++ b/google-cloud-storage/samples/storage_list_object_contexts.rb @@ -0,0 +1,45 @@ +# Copyright 2026 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 +# +# http://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/storage" + +# [START storage_list_object_contexts] +def list_object_contexts bucket_name:, custom_context_key:, custom_context_value: nil + # The ID of your GCS bucket + # bucket_name = "your-unique-bucket-name" + + # The key of the custom context to be filtered + # custom_context_key = "your-custom-context-key" + # The value of the custom context to be filtered + # custom_context_value = "your-custom-context-value" + + storage = Google::Cloud::Storage.new + bucket = storage.bucket bucket_name + + filter_query = if custom_context_value.nil? + "contexts.\"#{custom_context_key}\":*" + else + "contexts.\"#{custom_context_key}\"=\"#{custom_context_value}\"" + end + + list = bucket.files filter: filter_query + list.each do |file| + puts "File: #{file.name} has context key: #{custom_context_key}" + end +end +# [END storage_list_object_contexts] + +if $PROGRAM_NAME == __FILE__ + list_object_contexts bucket_name: ARGV.shift, custom_context_key: ARGV.shift, custom_context_value: ARGV.shift +end diff --git a/google-cloud-storage/samples/storage_set_object_contexts.rb b/google-cloud-storage/samples/storage_set_object_contexts.rb new file mode 100644 index 000000000000..b10f5e361884 --- /dev/null +++ b/google-cloud-storage/samples/storage_set_object_contexts.rb @@ -0,0 +1,53 @@ +# Copyright 2026 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 +# +# http://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/storage" + +# [START storage_set_object_contexts] +def set_object_contexts bucket_name:, file_name:, custom_context_key:, custom_context_value: + # The ID of your GCS bucket + # bucket_name = "your-unique-bucket-name" + + # The ID of your GCS object + # file_name = "your-file-name" + + # The key and value of the custom context to be added + # custom_context_key = "your-custom-context-key" + # custom_context_value = "your-custom-context-value" + + storage = Google::Cloud::Storage.new + bucket = storage.bucket bucket_name + file = bucket.file file_name + + payload = Google::Apis::StorageV1::ObjectCustomContextPayload.new( + value: custom_context_value + ) + custom_hash = { + custom_context_key => payload + } + contexts = Google::Apis::StorageV1::Object::Contexts.new( + custom: custom_hash + ) + + file.update do |file| + file.contexts = contexts + end + puts "Contexts for #{file_name} has been updated." +end +# [END storage_set_object_contexts] + +if $PROGRAM_NAME == __FILE__ + set_object_contexts bucket_name: ARGV.shift, file_name: ARGV.shift, + custom_context_key: ARGV.shift, custom_context_value: ARGV.shift +end diff --git a/google-cloud-storage/test/google/cloud/storage/bucket_objects_contexts_test.rb b/google-cloud-storage/test/google/cloud/storage/bucket_objects_contexts_test.rb new file mode 100644 index 000000000000..bf4cd2aa73d1 --- /dev/null +++ b/google-cloud-storage/test/google/cloud/storage/bucket_objects_contexts_test.rb @@ -0,0 +1,137 @@ +# Copyright 2026 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 "helper" +require "pry" + +describe Google::Cloud::Storage::Bucket, :mock_storage do + let(:bucket_name) { "new-bucket-#{Time.now.to_i}" } + let(:bucket_hash) { random_bucket_hash name: bucket_name } + let(:bucket_json) { bucket_hash.to_json } + let(:bucket_gapi) { Google::Apis::StorageV1::Bucket.from_json bucket_json } + let(:bucket) { Google::Cloud::Storage::Bucket.from_gapi bucket_gapi, storage.service } + let(:custom_context_key1) { "my-custom-key" } + let(:custom_context_value1) { "my-custom-value" } + let(:custom_context_key2) { "my-custom-key-2" } + let(:custom_context_value2) { "my-custom-value-2" } + + describe "listing files with contexts" do + it "lists files with specific contexts" do + num_files = 2 + expected_filter = "contexts.\"#{custom_context_key1}\"=\"#{custom_context_value1}\"" + mock = Minitest::Mock.new + mock.expect :list_objects, list_files_gapi(num_files, custom_context_key1, custom_context_value1), + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: expected_filter, options: {} + + bucket.service.mocked_service = mock + + files = bucket.files filter: expected_filter + + mock.verify + _(files.size).must_equal num_files + files.each do |file| + _(file).must_be_kind_of Google::Cloud::Storage::File + end + end + + it "lists files without specific contexts" do + num_files = 1 + expected_filter = "-contexts.\"#{custom_context_key1}\"=\"#{custom_context_value1}\"" + mock = Minitest::Mock.new + mock.expect :list_objects, list_files_gapi(num_files, custom_context_key1, custom_context_value1), + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: expected_filter, options: {} + + bucket.service.mocked_service = mock + files = bucket.files filter: expected_filter + mock.verify + _(files.size).must_equal num_files + files.each do |file| + _(file).must_be_kind_of Google::Cloud::Storage::File + end + end + end + + describe "setting and deleting contexts" do + let(:file_name) { "my-file" } + let(:file_gapi) { create_file_gapi bucket.name, file_name } + let(:file) { Google::Cloud::Storage::File.from_gapi file_gapi, storage.service } + it "sets contexts for a file" do + expected_contexts = context_custom_hash custom_context_key: custom_context_key1, + custom_context_value: custom_context_value1 + + mock = Minitest::Mock.new + + mock.expect :patch_object, file_gapi do |bucket_name, file_name, patch_obj, **args| + bucket_name == bucket.name && + file_name == file.name && + patch_obj.contexts == expected_contexts && + args[:options][:retries].zero? + end + bucket.service.mocked_service = mock + file.contexts = expected_contexts + mock.verify + end + + it "deletes contexts for a file" do + file_gapi = create_file_gapi_with_contexts bucket.name, file_name, custom_context_key: custom_context_key1,custom_context_value: custom_context_value1 + file = Google::Cloud::Storage::File.from_gapi file_gapi, storage.service + mock = Minitest::Mock.new + + mock.expect :patch_object, file_gapi do |bucket_name, file_name, patch_obj, **args| + bucket_name == bucket.name && + file_name == file.name && + patch_obj.contexts.nil? && + args[:options][:retries].zero? + end + bucket.service.mocked_service = mock + file.contexts = nil + mock.verify + _(file.contexts).must_be_nil + end + end + + + def create_file_gapi bucket = nil, name = nil + Google::Apis::StorageV1::Object.from_json random_file_hash(bucket, name).to_json + end + + def create_file_gapi_with_contexts bucket = nil, name = nil, _custom_context_key = nil, _custom_context_value = nil + Google::Apis::StorageV1::Object.from_json random_file_hash(bucket, name, custom_context_key1, + custom_context_value1).to_json + end + + def empty_file_gapi cache_control: nil, content_disposition: nil, + content_encoding: nil, content_language: nil, + content_type: nil, crc32c: nil, md5: nil, metadata: nil, + storage_class: nil + params = { + cache_control: cache_control, content_type: content_type, + content_disposition: content_disposition, md5_hash: md5, + content_encoding: content_encoding, crc32c: crc32c, + content_language: content_language, metadata: metadata, + storage_class: storage_class + }.delete_if { |_k, v| v.nil? } + Google::Apis::StorageV1::Object.new(**params) + end + + def find_file_gapi bucket = nil, name = nil + Google::Apis::StorageV1::Object.from_json random_file_hash(bucket, name).to_json + end + + def list_files_gapi count = 2, custom_context_key = nil, custom_context_value = nil, token = nil, prefixes = nil + files = count.times.map { Google::Apis::StorageV1::Object.from_json random_file_hash(custom_context_key = custom_context_key, custom_context_value = custom_context_value).to_json } + Google::Apis::StorageV1::Objects.new kind: "storage#objects", items: files, next_page_token: token, + prefixes: prefixes + end +end diff --git a/google-cloud-storage/test/google/cloud/storage/bucket_test.rb b/google-cloud-storage/test/google/cloud/storage/bucket_test.rb index 203e423467e5..902a3a32a602 100644 --- a/google-cloud-storage/test/google/cloud/storage/bucket_test.rb +++ b/google-cloud-storage/test/google/cloud/storage/bucket_test.rb @@ -639,7 +639,7 @@ mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(num_files), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} bucket.service.mocked_service = mock @@ -659,7 +659,7 @@ mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(num_files), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil,filter: nil, options: {} bucket.service.mocked_service = mock @@ -677,7 +677,7 @@ it "lists files with prefix set" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, nil, ["/prefix/path1/", "/prefix/path2/"]), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: "/prefix/", versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: "/prefix/", versions: nil, user_project: nil, filter: nil,match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} bucket.service.mocked_service = mock @@ -698,7 +698,7 @@ it "lists files with delimiter set" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, nil, ["/prefix/path1/", "/prefix/path2/"]), - [bucket.name], delimiter: "/", max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: "/", max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, filter: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} bucket.service.mocked_service = mock @@ -719,7 +719,7 @@ it "lists files with folders as prefix set" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, nil, ["/prefix/path1/", "/prefix/path2/"], include_folders_as_prefixes: true), - [bucket.name], delimiter: "/", max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: "/", max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, filter: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} bucket.service.mocked_service = mock @@ -741,7 +741,7 @@ it "lists files with match_glob set" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(2), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: "/foo/**/bar/", include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: "/foo/**/bar/", include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} bucket.service.mocked_service = mock @@ -760,7 +760,7 @@ it "lists files with max set" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket.name], delimiter: nil, max_results: 3, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: 3, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} bucket.service.mocked_service = mock @@ -780,7 +780,7 @@ it "lists files with versions set" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: true, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: true, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} bucket.service.mocked_service = mock @@ -800,7 +800,7 @@ mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(num_files), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: "test", match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: "test", match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} bucket_user_project.service.mocked_service = mock @@ -818,9 +818,9 @@ it "paginates files" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} mock.expect :list_objects, list_files_gapi(2), - [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} bucket.service.mocked_service = mock @@ -848,9 +848,9 @@ it "paginates files with next? and next" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} mock.expect :list_objects, list_files_gapi(2), - [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} bucket.service.mocked_service = mock @@ -877,9 +877,9 @@ it "paginates files with next? and next and prefix set" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: "/prefix/", versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: "/prefix/", versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} mock.expect :list_objects, list_files_gapi(2), - [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: "/prefix/", versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: "/prefix/", versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} bucket.service.mocked_service = mock @@ -906,9 +906,9 @@ it "paginates files with next? and next and delimiter set" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket.name], delimiter: "/", max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: "/", max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} mock.expect :list_objects, list_files_gapi(2), - [bucket.name], delimiter: "/", max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: "/", max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} bucket.service.mocked_service = mock @@ -935,9 +935,9 @@ it "paginates files with next? and next and max set" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket.name], delimiter: nil, max_results: 3, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: 3, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} mock.expect :list_objects, list_files_gapi(2), - [bucket.name], delimiter: nil, max_results: 3, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: 3, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} bucket.service.mocked_service = mock @@ -964,9 +964,9 @@ it "paginates files with next? and next and versions set" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: true, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: true, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} mock.expect :list_objects, list_files_gapi(2), - [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: true, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: true, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} bucket.service.mocked_service = mock @@ -993,9 +993,9 @@ it "paginates files with user_project set to true" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: "test", match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: "test", match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} mock.expect :list_objects, list_files_gapi(2), - [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: "test", match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: "test", match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} bucket_user_project.service.mocked_service = mock @@ -1023,9 +1023,9 @@ it "paginates files with all" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} mock.expect :list_objects, list_files_gapi(2), - [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} bucket.service.mocked_service = mock @@ -1043,9 +1043,9 @@ it "paginates files with all and prefix set" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: "/prefix/", versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: "/prefix/", versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} mock.expect :list_objects, list_files_gapi(2), - [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: "/prefix/", versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: "/prefix/", versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} bucket.service.mocked_service = mock @@ -1063,9 +1063,9 @@ it "paginates files with all and delimiter set" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket.name], delimiter: "/", max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: "/", max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} mock.expect :list_objects, list_files_gapi(2), - [bucket.name], delimiter: "/", max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: "/", max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} bucket.service.mocked_service = mock @@ -1083,9 +1083,9 @@ it "paginates files with all and max set" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket.name], delimiter: nil, max_results: 3, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: 3, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} mock.expect :list_objects, list_files_gapi(2), - [bucket.name], delimiter: nil, max_results: 3, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: 3, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} bucket.service.mocked_service = mock @@ -1103,9 +1103,9 @@ it "paginates files with all and versions set" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: true, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: true, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} mock.expect :list_objects, list_files_gapi(2), - [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: true, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: true, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} bucket.service.mocked_service = mock @@ -1123,9 +1123,9 @@ it "paginates files with all using Enumerator" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} mock.expect :list_objects, list_files_gapi(3, "second_page_token"), - [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} bucket.service.mocked_service = mock @@ -1143,9 +1143,9 @@ it "paginates files with all and request_limit set" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} mock.expect :list_objects, list_files_gapi(3, "second_page_token"), - [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} bucket.service.mocked_service = mock @@ -1163,9 +1163,9 @@ it "paginates files with all and user_project set to true" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket_user_project.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: "test", match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket_user_project.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: "test", match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} mock.expect :list_objects, list_files_gapi(3, "second_page_token"), - [bucket_user_project.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: "test", match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket_user_project.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: "test", match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter: nil, options: {} bucket_user_project.service.mocked_service = mock diff --git a/google-cloud-storage/test/google/cloud/storage/file_test.rb b/google-cloud-storage/test/google/cloud/storage/file_test.rb index 4b52e9954b82..0312d7781a0a 100644 --- a/google-cloud-storage/test/google/cloud/storage/file_test.rb +++ b/google-cloud-storage/test/google/cloud/storage/file_test.rb @@ -1492,7 +1492,7 @@ def file_user_project.sleep *args mock.expect :get_object, Google::Apis::StorageV1::Object.from_json(random_file_hash(bucket.name, file_name, generations[0]).to_json), [bucket.name, file_name], **get_object_args mock.expect :list_objects, Google::Apis::StorageV1::Objects.new(kind: "storage#objects", items: file_gapis), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: file_name, versions: true, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: file_name, versions: true, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, filter:nil,soft_deleted: nil, options: {} bucket.service.mocked_service = mock file.service.mocked_service = mock @@ -1518,7 +1518,7 @@ def file_user_project.sleep *args mock.expect :get_object, Google::Apis::StorageV1::Object.from_json(random_file_hash(bucket_user_project.name, file_name, generations[0]).to_json), [bucket_user_project.name, file_name], **get_object_args(user_project: "test") mock.expect :list_objects, Google::Apis::StorageV1::Objects.new(kind: "storage#objects", items: file_gapis), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: file_name, versions: true, user_project: "test", match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: file_name, versions: true, user_project: "test", match_glob: nil, include_folders_as_prefixes: nil, filter:nil, soft_deleted: nil, options: {} bucket_user_project.service.mocked_service = mock file.service.mocked_service = mock diff --git a/google-cloud-storage/test/google/cloud/storage/lazy/bucket_test.rb b/google-cloud-storage/test/google/cloud/storage/lazy/bucket_test.rb index c304f54b3838..bdef33c69e4f 100644 --- a/google-cloud-storage/test/google/cloud/storage/lazy/bucket_test.rb +++ b/google-cloud-storage/test/google/cloud/storage/lazy/bucket_test.rb @@ -369,7 +369,7 @@ mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(num_files), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter:nil, options: {} bucket.service.mocked_service = mock @@ -389,7 +389,7 @@ mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(num_files), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter:nil, options: {} bucket.service.mocked_service = mock files = bucket.find_files @@ -406,7 +406,7 @@ it "lists files with prefix set" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, nil, ["/prefix/path1/", "/prefix/path2/"]), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: "/prefix/", versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: "/prefix/", versions: nil, user_project: nil, filter:nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} bucket.service.mocked_service = mock @@ -427,7 +427,7 @@ it "lists files with delimiter set" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, nil, ["/prefix/path1/", "/prefix/path2/"]), - [bucket.name], delimiter: "/", max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: "/", max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter:nil, options: {} bucket.service.mocked_service = mock files = bucket.files delimiter: "/" @@ -447,7 +447,7 @@ it "lists files with match_glob set" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(2), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: "/foo/**/bar/", include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: "/foo/**/bar/", include_folders_as_prefixes: nil, soft_deleted: nil, filter:nil, options: {} bucket.service.mocked_service = mock @@ -466,7 +466,7 @@ it "lists files with max set" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket.name], delimiter: nil, max_results: 3, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: 3, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter:nil, options: {} bucket.service.mocked_service = mock @@ -486,7 +486,7 @@ it "lists files with versions set" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: true, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, filter:nil, prefix: nil, versions: true, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} bucket.service.mocked_service = mock @@ -506,7 +506,7 @@ mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(num_files), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: "test", match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: "test", match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter:nil, options: {} bucket_user_project.service.mocked_service = mock @@ -524,9 +524,9 @@ it "paginates files" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, filter:nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} mock.expect :list_objects, list_files_gapi(2), - [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, filter:nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} bucket.service.mocked_service = mock @@ -554,9 +554,9 @@ it "paginates files with next? and next" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, filter:nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} mock.expect :list_objects, list_files_gapi(2), - [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, filter:nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} bucket.service.mocked_service = mock first_files = bucket.files @@ -582,9 +582,9 @@ it "paginates files with next? and next and prefix set" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: "/prefix/", versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: "/prefix/", versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter:nil, options: {} mock.expect :list_objects, list_files_gapi(2), - [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: "/prefix/", versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: "/prefix/", versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter:nil, options: {} bucket.service.mocked_service = mock @@ -611,9 +611,9 @@ it "paginates files with next? and next and delimiter set" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket.name], delimiter: "/", max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: "/", max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter:nil, options: {} mock.expect :list_objects, list_files_gapi(2), - [bucket.name], delimiter: "/", max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: "/", max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter:nil, options: {} bucket.service.mocked_service = mock @@ -640,9 +640,9 @@ it "paginates files with next? and next and max set" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket.name], delimiter: nil, max_results: 3, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: 3, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter:nil, options: {} mock.expect :list_objects, list_files_gapi(2), - [bucket.name], delimiter: nil, max_results: 3, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: 3, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil,filter:nil, options: {} bucket.service.mocked_service = mock first_files = bucket.files max: 3 @@ -668,9 +668,9 @@ it "paginates files with next? and next and versions set" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: true, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: true, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter:nil, options: {} mock.expect :list_objects, list_files_gapi(2), - [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: true, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: true, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter:nil, options: {} bucket.service.mocked_service = mock @@ -697,9 +697,9 @@ it "paginates files with user_project set to true" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: "test", match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: "test", match_glob: nil, filter:nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} mock.expect :list_objects, list_files_gapi(2), - [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: "test", match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: "test", filter:nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} bucket_user_project.service.mocked_service = mock @@ -727,9 +727,9 @@ it "paginates files with all" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter:nil, options: {} mock.expect :list_objects, list_files_gapi(2), - [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter:nil, options: {} bucket.service.mocked_service = mock files = bucket.files.all.to_a @@ -746,9 +746,9 @@ it "paginates files with all and prefix set" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: "/prefix/", versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: "/prefix/", versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter:nil, options: {} mock.expect :list_objects, list_files_gapi(2), - [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: "/prefix/", versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: "/prefix/", versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter:nil, options: {} bucket.service.mocked_service = mock @@ -766,9 +766,9 @@ it "paginates files with all and delimiter set" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket.name], delimiter: "/", max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: "/", max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter:nil, options: {} mock.expect :list_objects, list_files_gapi(2), - [bucket.name], delimiter: "/", max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: "/", max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter:nil, options: {} bucket.service.mocked_service = mock @@ -786,9 +786,9 @@ it "paginates files with all and max set" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket.name], delimiter: nil, max_results: 3, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: 3, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter:nil, options: {} mock.expect :list_objects, list_files_gapi(2), - [bucket.name], delimiter: nil, max_results: 3, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: 3, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter:nil, options: {} bucket.service.mocked_service = mock @@ -806,9 +806,9 @@ it "paginates files with all and versions set" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: true, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: true, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter:nil, options: {} mock.expect :list_objects, list_files_gapi(2), - [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: true, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: true, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter:nil, options: {} bucket.service.mocked_service = mock @@ -826,9 +826,9 @@ it "paginates files with all using Enumerator" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter:nil, options: {} mock.expect :list_objects, list_files_gapi(3, "second_page_token"), - [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter:nil, options: {} bucket.service.mocked_service = mock @@ -846,9 +846,9 @@ it "paginates files with all and request_limit set" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter:nil, options: {} mock.expect :list_objects, list_files_gapi(3, "second_page_token"), - [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter:nil, options: {} bucket.service.mocked_service = mock @@ -866,9 +866,9 @@ it "paginates files with all and user_project set to true" do mock = Minitest::Mock.new mock.expect :list_objects, list_files_gapi(3, "next_page_token"), - [bucket_user_project.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: "test", match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket_user_project.name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: "test", match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter:nil, options: {} mock.expect :list_objects, list_files_gapi(3, "second_page_token"), - [bucket_user_project.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: "test", match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket_user_project.name], delimiter: nil, max_results: nil, page_token: "next_page_token", prefix: nil, versions: nil, user_project: "test", match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, filter:nil, options: {} bucket_user_project.service.mocked_service = mock diff --git a/google-cloud-storage/test/google/cloud/storage/project_anonymous_test.rb b/google-cloud-storage/test/google/cloud/storage/project_anonymous_test.rb index 40d7855fcb0d..62d9b7fc9d4a 100644 --- a/google-cloud-storage/test/google/cloud/storage/project_anonymous_test.rb +++ b/google-cloud-storage/test/google/cloud/storage/project_anonymous_test.rb @@ -63,7 +63,7 @@ def stub.list_buckets *args mock = Minitest::Mock.new mock.expect :get_bucket, find_bucket_gapi(bucket_name), [bucket_name], **get_bucket_args mock.expect :list_objects, list_files_gapi(num_files), - [bucket_name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} + [bucket_name], delimiter: nil, max_results: nil, page_token: nil, prefix: nil, filter:nil, versions: nil, user_project: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, options: {} anonymous_storage.service.mocked_service = mock bucket = anonymous_storage.bucket bucket_name diff --git a/google-cloud-storage/test/helper.rb b/google-cloud-storage/test/helper.rb index 5d37f92feb26..27867b2bb4f3 100644 --- a/google-cloud-storage/test/helper.rb +++ b/google-cloud-storage/test/helper.rb @@ -164,15 +164,19 @@ def file_retention_hash(retention_params) }.delete_if { |_, v| v.nil? } if !retention_params.nil? && !retention_params.empty? end - def random_file_hash bucket=random_bucket_name, - name=random_file_path, - generation="1234567890", - kms_key_name="path/to/encryption_key_name", + def random_file_hash bucket = random_bucket_name, + name = random_file_path, + generation = "1234567890", + kms_key_name = "path/to/encryption_key_name", custom_time: nil, retention_params: nil, override_unlocked_retention: nil, soft_delete_time: nil, - hard_delete_time: nil + hard_delete_time: nil, + custom_context_key: nil, + custom_context_value: nil + + # binding.pry { "kind" => "storage#object", "id" => "#{bucket}/#{name}/1234567890", "selfLink" => "https://www.googleapis.com/storage/v1/b/#{bucket}/o/#{name}", @@ -203,9 +207,22 @@ def random_file_hash bucket=random_bucket_name, "retention" => file_retention_hash(retention_params), "overrideUnlockedRetention" => override_unlocked_retention, "softDeleteTime" => soft_delete_time, - "hardDeleteTime" => hard_delete_time } + "hardDeleteTime" => hard_delete_time, + "contexts" => context_custom_hash(custom_context_key: custom_context_key, custom_context_value: custom_context_value) + } + end + + def context_custom_hash custom_context_key:, custom_context_value: + if custom_context_key + custom_hash = { + custom: { custom_context_key => { "value" => custom_context_value, "createTime" => Time.now } } + } + else + nil + end end + def random_bucket_name (0...50).map { ("a".."z").to_a[rand(26)] }.join end @@ -420,6 +437,7 @@ def list_objects_args delimiter: nil, match_glob: nil, include_folders_as_prefixes: nil, soft_deleted: nil, + filter: nil, options: {} { delimiter: delimiter, @@ -431,6 +449,7 @@ def list_objects_args delimiter: nil, match_glob: match_glob, include_folders_as_prefixes: include_folders_as_prefixes, soft_deleted: soft_deleted, + filter: filter, options: options } end From 9112800339ca12d68f15c2d808c8b10d9a139912 Mon Sep 17 00:00:00 2001 From: Shubhangi Singh Date: Fri, 13 Mar 2026 13:06:29 +0000 Subject: [PATCH 2/2] adding tests --- .../bucket_list_object_contexts_test.rb | 1 - .../acceptance/storage/file_test.rb | 89 ++++++++++++++++--- .../lib/google/cloud/storage/file.rb | 6 +- .../samples/acceptance/files_test.rb | 23 ----- .../samples/storage_delete_object_contexts.rb | 56 ------------ .../samples/storage_get_object_contexts.rb | 10 ++- .../storage/bucket_objects_contexts_test.rb | 9 +- google-cloud-storage/test/helper.rb | 1 - 8 files changed, 93 insertions(+), 102 deletions(-) delete mode 100644 google-cloud-storage/samples/storage_delete_object_contexts.rb diff --git a/google-cloud-storage/acceptance/storage/bucket_list_object_contexts_test.rb b/google-cloud-storage/acceptance/storage/bucket_list_object_contexts_test.rb index 501102841a83..d9896e9d6060 100644 --- a/google-cloud-storage/acceptance/storage/bucket_list_object_contexts_test.rb +++ b/google-cloud-storage/acceptance/storage/bucket_list_object_contexts_test.rb @@ -13,7 +13,6 @@ # limitations under the License. require "storage_helper" -require 'pry' describe Google::Cloud::Storage::Bucket, :contexts, :storage do let(:bucket_name) { $bucket_names[0] } diff --git a/google-cloud-storage/acceptance/storage/file_test.rb b/google-cloud-storage/acceptance/storage/file_test.rb index dfd787a53439..ec89df46d448 100644 --- a/google-cloud-storage/acceptance/storage/file_test.rb +++ b/google-cloud-storage/acceptance/storage/file_test.rb @@ -1052,7 +1052,6 @@ let(:custom_context_value2) { "my-custom-value-2" } let(:local_file) { "acceptance/data/CloudPlatform_128px_Retina.png" } let(:file_name) { "CloudLogo1" } - let(:file_name2) { "CloudLogo2" } before do bucket.create_file local_file, file_name @@ -1067,7 +1066,59 @@ _(file.contexts.custom[custom_context_key1].value).must_equal custom_context_value1 end - it "overwrites existing custom context key and value" do + it "rejects special characters in custom context key and value" do + invalid_key = 'my"-invalid-key' + custom_value = 'my-custom-value' + + file = bucket.file file_name + + err = _ { + file.contexts = Google::Apis::StorageV1::Object::Contexts.new( + custom: context_custom_hash(custom_context_key: invalid_key, custom_context_value: custom_value) + ) + }.must_raise Google::Cloud::InvalidArgumentError + + _(err.message).must_match(/Object context key cannot contain/) + + invalid_key = 'my-custom-key' + custom_value = 'my-invalid/value' + + err = _ { + file.contexts = Google::Apis::StorageV1::Object::Contexts.new( + custom: context_custom_hash(custom_context_key: invalid_key, custom_context_value: custom_value) + ) + }.must_raise Google::Cloud::InvalidArgumentError + + _(err.message).must_match(/Object context value cannot contain/) + + end + + it "rejects unicode characters in keys and values" do + invalid_key = '🚀-launcher' + custom_value = 'my-custom-value' + file = bucket.file file_name + err = _ { + file.contexts = Google::Apis::StorageV1::Object::Contexts.new( + custom: context_custom_hash(custom_context_key: invalid_key, custom_context_value: custom_value) + ) + }.must_raise Google::Cloud::InvalidArgumentError + + # Optional: Verify the message matches what you saw + _(err.message).must_match(/Object context key must start with an alphanumeric character./) + + invalid_key = "my-custom-key" + custom_value = '✨-sparkle' + + err = _ { + file.contexts = Google::Apis::StorageV1::Object::Contexts.new( + custom: context_custom_hash(custom_context_key: invalid_key, custom_context_value: custom_value) + ) + }.must_raise Google::Cloud::InvalidArgumentError + + _(err.message).must_match(/Object context value must start with an alphanumeric character./) + end + + it "modifies existing custom context key and value" do file = bucket.file file_name file.contexts = Google::Apis::StorageV1::Object::Contexts.new( custom: context_custom_hash(custom_context_key: custom_context_key1 ,custom_context_value: custom_context_value1) @@ -1082,22 +1133,38 @@ _(file.contexts.custom[custom_context_key1].value).must_equal custom_context_value2 end - it "sets and retrieves multiple custom context keys and values" do + it "overwrites existing context key and value" do file = bucket.file file_name - custom_hash1 = context_custom_hash custom_context_key: custom_context_key1, custom_context_value: custom_context_value1 - custom_hash2 = context_custom_hash custom_context_key: custom_context_key2, custom_context_value: custom_context_value2 file.contexts = Google::Apis::StorageV1::Object::Contexts.new( - custom: { - custom_context_key1 => custom_hash1[custom_context_key1], - custom_context_key2 => custom_hash2[custom_context_key2] - } + custom: context_custom_hash(custom_context_key: custom_context_key1 ,custom_context_value: custom_context_value1) ) file.reload! _(file.contexts.custom[custom_context_key1].value).must_equal custom_context_value1 + + file.contexts = Google::Apis::StorageV1::Object::Contexts.new( + custom: context_custom_hash(custom_context_key: custom_context_key2 ,custom_context_value: custom_context_value2) + ) + file.reload! _(file.contexts.custom[custom_context_key2].value).must_equal custom_context_value2 end - it "deletes custom context keys and values" do + it "sets and retrieves multiple custom context keys and values" do + file = bucket.file file_name + custom_hash1 = context_custom_hash custom_context_key: custom_context_key1, custom_context_value: custom_context_value1 + custom_hash2 = context_custom_hash custom_context_key: custom_context_key2, custom_context_value: custom_context_value2 + + file.contexts = Google::Apis::StorageV1::Object::Contexts.new( + custom: { + custom_context_key1 => custom_hash1[custom_context_key1], + custom_context_key2 => custom_hash2[custom_context_key2] + } + ) + file.reload! + _(file.contexts.custom[custom_context_key1].value).must_equal custom_context_value1 + _(file.contexts.custom[custom_context_key2].value).must_equal custom_context_value2 + end + + it "removes individual context" do file = bucket.file file_name custom_hash1 = context_custom_hash custom_context_key: custom_context_key1, custom_context_value: custom_context_value1 custom_hash2 = context_custom_hash custom_context_key: custom_context_key2, custom_context_value: custom_context_value2 @@ -1121,7 +1188,7 @@ _(file.contexts.custom[custom_context_key2].value).must_equal custom_context_value2 end - it "deletes object contexts" do + it "clears all contexts" do file = bucket.file file_name custom_hash1 = context_custom_hash custom_context_key: custom_context_key1, custom_context_value: custom_context_value1 file.contexts = Google::Apis::StorageV1::Object::Contexts.new( diff --git a/google-cloud-storage/lib/google/cloud/storage/file.rb b/google-cloud-storage/lib/google/cloud/storage/file.rb index 7e0f37dc6a78..6b81d5ebd304 100644 --- a/google-cloud-storage/lib/google/cloud/storage/file.rb +++ b/google-cloud-storage/lib/google/cloud/storage/file.rb @@ -371,10 +371,10 @@ def content_type= content_type end ## - # User-defined or system-defined object contexts. Each object context is a key- + # User-defined object contexts. Each object context is a key- # payload pair, where the key provides the identification and the payload holds # the associated value and additional metadata. - # Object contexts are used to provide additional information about an object and its + # Object contexts are used to provide additional information about an object # @return [Google::Apis::StorageV1::Object::Contexts, nil] The object contexts, or `nil` if there are none. def contexts @@ -403,7 +403,7 @@ def contexts # ) # file.update do |file| # file.contexts = contexts - # en + # end def contexts= contexts @gapi.contexts = contexts update_gapi! :contexts diff --git a/google-cloud-storage/samples/acceptance/files_test.rb b/google-cloud-storage/samples/acceptance/files_test.rb index 26a630dac660..f4b8abe3477d 100644 --- a/google-cloud-storage/samples/acceptance/files_test.rb +++ b/google-cloud-storage/samples/acceptance/files_test.rb @@ -20,7 +20,6 @@ require_relative "../storage_copy_file_archived_generation" require_relative "../storage_delete_file" require_relative "../storage_delete_file_archived_generation" -require_relative "../storage_delete_object_contexts" require_relative "../storage_download_byte_range" require_relative "../storage_download_encrypted_file" require_relative "../storage_download_file" @@ -362,28 +361,6 @@ def mock_cipher.random_key end - describe "delete object contexts" do - let(:custom_context_key) { "my-custom-key" } - let(:custom_context_value) { "my-custom-value" } - let(:custom_context_key2) { "my-custom-key-2" } - let(:custom_context_value2) { "my-custom-value-2" } - - before(:all) do - bucket.create_file local_file, remote_file_name - set_object_contexts bucket_name: bucket.name, file_name: remote_file_name, custom_context_key: custom_context_key, custom_context_value: custom_context_value - set_object_contexts bucket_name: bucket.name, file_name: remote_file_name, custom_context_key: custom_context_key2, custom_context_value: custom_context_value2 - end - - it "deletes the custom object contexts when nil is passed in value" do - assert_output "Contexts for #{remote_file_name} has been deleted.\n" do - delete_object_contexts bucket_name: bucket.name, file_name: remote_file_name, custom_context_key: custom_context_key, custom_context_value: nil - end - - assert_nil bucket.file(remote_file_name).contexts.custom[custom_context_key] - refute_nil bucket.file(remote_file_name).contexts.custom[custom_context_key2] - end - end - it "set_metadata" do bucket.create_file local_file, remote_file_name diff --git a/google-cloud-storage/samples/storage_delete_object_contexts.rb b/google-cloud-storage/samples/storage_delete_object_contexts.rb deleted file mode 100644 index 4a7ccfc2a611..000000000000 --- a/google-cloud-storage/samples/storage_delete_object_contexts.rb +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright 2026 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 -# -# http://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/storage" - -# [START storage_delete_object_contexts] -def delete_object_contexts bucket_name:, file_name:, custom_context_key:, custom_context_value: nil - # The ID of your GCS bucket - # bucket_name = "your-unique-bucket-name" - - # The ID of your GCS object - # file_name = "your-file-name" - - # The key and value of the custom context to be added - # custom_context_key = "your-custom-context-key" - # custom_context_value = "your-custom-context-value" - - storage = Google::Cloud::Storage.new - bucket = storage.bucket bucket_name - file = bucket.file file_name - - # If value is nil, the payload itself is nil, which triggers a deletion for that key. - payload = if custom_context_value - Google::Apis::StorageV1::ObjectCustomContextPayload.new.tap do |p| - p.value = custom_context_value - end - end - custom_hash = { - custom_context_key => payload - } - contexts = Google::Apis::StorageV1::Object::Contexts.new( - custom: custom_hash - ) - file.update do |file| - file.contexts = contexts - end - - puts "Contexts for #{file_name} has been deleted." -end -# [END storage_delete_object_contexts] - -if $PROGRAM_NAME == __FILE__ - delete_object_contexts bucket_name: ARGV.shift, file_name: ARGV.shift, - custom_context_key: ARGV.shift, custom_context_value: ARGV.shift -end diff --git a/google-cloud-storage/samples/storage_get_object_contexts.rb b/google-cloud-storage/samples/storage_get_object_contexts.rb index f2618100d2ae..c35eaea13934 100644 --- a/google-cloud-storage/samples/storage_get_object_contexts.rb +++ b/google-cloud-storage/samples/storage_get_object_contexts.rb @@ -31,9 +31,13 @@ def get_object_contexts bucket_name:, file_name: file = bucket.file file_name contexts = file.contexts - custom_context_key = contexts.custom.keys.first - custom_context_value = contexts.custom[custom_context_key].value - puts "Custom Contexts for #{file_name} are: #{custom_context_key} with value: #{custom_context_value}" + if contexts&.custom&.any? + custom_context_key = contexts.custom.keys.first + custom_context_value = contexts.custom[custom_context_key].value + puts "Custom Contexts for #{file_name} are: #{custom_context_key} with value: #{custom_context_value}" + else + puts "No custom contexts found for #{file_name}." + end end # [END storage_get_object_contexts] diff --git a/google-cloud-storage/test/google/cloud/storage/bucket_objects_contexts_test.rb b/google-cloud-storage/test/google/cloud/storage/bucket_objects_contexts_test.rb index bf4cd2aa73d1..b82dd116e5a7 100644 --- a/google-cloud-storage/test/google/cloud/storage/bucket_objects_contexts_test.rb +++ b/google-cloud-storage/test/google/cloud/storage/bucket_objects_contexts_test.rb @@ -13,7 +13,6 @@ # limitations under the License. require "helper" -require "pry" describe Google::Cloud::Storage::Bucket, :mock_storage do let(:bucket_name) { "new-bucket-#{Time.now.to_i}" } @@ -66,6 +65,7 @@ let(:file_name) { "my-file" } let(:file_gapi) { create_file_gapi bucket.name, file_name } let(:file) { Google::Cloud::Storage::File.from_gapi file_gapi, storage.service } + it "sets contexts for a file" do expected_contexts = context_custom_hash custom_context_key: custom_context_key1, custom_context_value: custom_context_value1 @@ -78,6 +78,7 @@ patch_obj.contexts == expected_contexts && args[:options][:retries].zero? end + bucket.service.mocked_service = mock file.contexts = expected_contexts mock.verify @@ -106,9 +107,9 @@ def create_file_gapi bucket = nil, name = nil Google::Apis::StorageV1::Object.from_json random_file_hash(bucket, name).to_json end - def create_file_gapi_with_contexts bucket = nil, name = nil, _custom_context_key = nil, _custom_context_value = nil - Google::Apis::StorageV1::Object.from_json random_file_hash(bucket, name, custom_context_key1, - custom_context_value1).to_json + def create_file_gapi_with_contexts bucket = nil, name = nil, custom_context_key = nil, custom_context_value = nil + Google::Apis::StorageV1::Object.from_json random_file_hash(bucket, name, custom_context_key: custom_context_key, + custom_context_value: custom_context_value).to_json end def empty_file_gapi cache_control: nil, content_disposition: nil, diff --git a/google-cloud-storage/test/helper.rb b/google-cloud-storage/test/helper.rb index 27867b2bb4f3..67ac7e60fa3b 100644 --- a/google-cloud-storage/test/helper.rb +++ b/google-cloud-storage/test/helper.rb @@ -176,7 +176,6 @@ def random_file_hash bucket = random_bucket_name, custom_context_key: nil, custom_context_value: nil - # binding.pry { "kind" => "storage#object", "id" => "#{bucket}/#{name}/1234567890", "selfLink" => "https://www.googleapis.com/storage/v1/b/#{bucket}/o/#{name}",