diff --git a/.gitignore b/.gitignore index 0feb89006..a8bfa23eb 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ mkmf.log tests/.fog gemfiles/Gemfile-edge.lock +.idea diff --git a/lib/fog/aws/models/storage/file.rb b/lib/fog/aws/models/storage/file.rb index 4e16cb19a..15b1d3da3 100644 --- a/lib/fog/aws/models/storage/file.rb +++ b/lib/fog/aws/models/storage/file.rb @@ -25,6 +25,7 @@ module Fog attribute :encryption_key, :aliases => 'x-amz-server-side-encryption-customer-key' attribute :version, :aliases => 'x-amz-version-id' attribute :kms_key_id, :aliases => 'x-amz-server-side-encryption-aws-kms-key-id' + attribute :tags, :aliases => 'x-amz-tagging' # @note Chunk size to use for multipart uploads. # Use small chunk sizes to minimize memory. E.g. 5242880 = 5mb @@ -192,6 +193,7 @@ module Fog # @option options [String] expires sets number of seconds before AWS Object expires. # @option options [String] storage_class sets x-amz-storage-class HTTP header. Defaults to 'STANDARD'. Or, 'REDUCED_REDUNDANCY' # @option options [String] encryption sets HTTP encryption header. Set to 'AES256' to encrypt files at rest on S3 + # @option options [String] tags sets x-amz-tagging HTTP header. For example, 'Org-Id=1' or 'Org-Id=1&Service=MyService' # @return [Boolean] true if no errors # def save(options = {}) @@ -208,6 +210,7 @@ module Fog options['Expires'] = expires if expires options.merge!(metadata) options['x-amz-storage-class'] = storage_class if storage_class + options['x-amz-tagging'] = tags if tags options.merge!(encryption_headers) # With a single PUT operation you can upload objects up to 5 GB in size. Automatically set MP for larger objects. diff --git a/lib/fog/aws/parsers/storage/get_object_tagging.rb b/lib/fog/aws/parsers/storage/get_object_tagging.rb new file mode 100644 index 000000000..94fae7feb --- /dev/null +++ b/lib/fog/aws/parsers/storage/get_object_tagging.rb @@ -0,0 +1,33 @@ +module Fog + module Parsers + module AWS + module Storage + class GetObjectTagging < Fog::Parsers::Base + def reset + @in_tag = {} + @response = {'ObjectTagging' => {}} + end + + def start_element(name, *args) + super + if name == 'Tag' + @in_tag = {} + end + end + + def end_element(name) + case name + when 'Tag' + @response['ObjectTagging'].merge!(@in_tag) + @in_tag = {} + when 'Key' + @in_tag[value] = nil + when 'Value' + @in_tag = {@in_tag.keys.first => value} + end + end + end + end + end + end +end diff --git a/lib/fog/aws/requests/storage/get_object_tagging.rb b/lib/fog/aws/requests/storage/get_object_tagging.rb new file mode 100644 index 000000000..c14f07078 --- /dev/null +++ b/lib/fog/aws/requests/storage/get_object_tagging.rb @@ -0,0 +1,41 @@ +module Fog + module AWS + class Storage + class Real + require 'fog/aws/parsers/storage/get_object_tagging' + + # Get tags for an S3 object + # + # @param bucket_name [String] Name of bucket to read from + # @param object_name [String] Name of object to get tags for + # + # @return [Excon::Response] response: + # * body [Hash]: + # * ObjectTagging [Hash]: + # * Key [String] - tag key + # * Value [String] - tag value + # @see https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectTagging.html + + def get_object_tagging(bucket_name, object_name) + unless bucket_name + raise ArgumentError.new('bucket_name is required') + end + unless object_name + raise ArgumentError.new('object_name is required') + end + + request({ + :expects => 200, + :headers => {}, + :bucket_name => bucket_name, + :object_name => object_name, + :idempotent => true, + :method => 'GET', + :parser => Fog::Parsers::AWS::Storage::GetObjectTagging.new, + :query => {'tagging' => nil} + }) + end + end + end + end +end diff --git a/lib/fog/aws/requests/storage/put_object_tagging.rb b/lib/fog/aws/requests/storage/put_object_tagging.rb new file mode 100644 index 000000000..d6d5aed37 --- /dev/null +++ b/lib/fog/aws/requests/storage/put_object_tagging.rb @@ -0,0 +1,42 @@ +module Fog + module AWS + class Storage + class Real + # Change tag set for an S3 object + # + # @param bucket_name [String] Name of bucket to modify object in + # @param object_name [String] Name of object to modify + # + # @param tags [Hash]: + # * Key [String]: tag key + # * Value [String]: tag value + # + # @see https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectTagging.html + + def put_object_tagging(bucket_name, object_name, tags) + tagging = tags.map do |k,v| + "#{k}#{v}" + end.join("\n") + data = + <<-DATA + + + #{tagging} + + + DATA + + request({ + :body => data, + :expects => 200, + :headers => {'Content-MD5' => Base64.encode64(OpenSSL::Digest::MD5.digest(data)).chomp!, 'Content-Type' => 'application/xml'}, + :bucket_name => bucket_name, + :object_name => object_name, + :method => 'PUT', + :query => {'tagging' => nil} + }) + end + end + end + end +end diff --git a/lib/fog/aws/storage.rb b/lib/fog/aws/storage.rb index b9fd1f876..1df27637d 100644 --- a/lib/fog/aws/storage.rb +++ b/lib/fog/aws/storage.rb @@ -84,6 +84,7 @@ module Fog request :get_object_http_url request :get_object_https_url request :get_object_url + request :get_object_tagging request :get_request_payment request :get_service request :head_bucket @@ -107,6 +108,7 @@ module Fog request :put_object request :put_object_acl request :put_object_url + request :put_object_tagging request :put_request_payment request :sync_clock request :upload_part