diff --git a/lib/fog/aws/parsers/storage/get_bucket_notification.rb b/lib/fog/aws/parsers/storage/get_bucket_notification.rb new file mode 100644 index 000000000..eaa3d170b --- /dev/null +++ b/lib/fog/aws/parsers/storage/get_bucket_notification.rb @@ -0,0 +1,61 @@ +module Fog + module Parsers + module Storage + module AWS + class GetBucketNotification < Fog::Parsers::Base + def reset + @func = {} + @queue = {} + @topic = {} + @response = { + 'Topics' => [], + 'Queues' => [], + 'CloudFunctions' => [] + } + end + + def start_element(name, attrs = []) + super + case name + when 'TopicConfiguration' + @configuration = 'topic' + when 'QueueConfiguration' + @configuration = 'queue' + when 'CloudFunctionConfiguration' + @configuration = 'func' + end + end + + def end_element(name) + case @configuration + when 'topic' + case name + when 'Id', 'Event', 'Topic' + @topic[name] = value + when 'TopicConfiguration' + @response['Topics'] << @topic + @topic = {} + end + when 'queue' + case name + when 'Id', 'Queue', 'Event' + @queue[name] = value + when 'QueueConfiguration' + @response['Queues'] << @queue + @queue = {} + end + when 'func' + case name + when 'Id', 'CloudFunction', 'InvocationRule', 'Event' + @func[name] = value + when 'CloudFunctionConfiguration' + @response['CloudFunctions'] << @func + @func = {} + end + end + end + end + end + end + end +end diff --git a/lib/fog/aws/requests/storage/get_bucket_notification.rb b/lib/fog/aws/requests/storage/get_bucket_notification.rb new file mode 100644 index 000000000..15645b472 --- /dev/null +++ b/lib/fog/aws/requests/storage/get_bucket_notification.rb @@ -0,0 +1,60 @@ +module Fog + module Storage + class AWS + class Real + require 'fog/aws/parsers/storage/get_bucket_notification' + + # Get bucket notification configuration + # + # @param bucket_name [String] name of bucket to get notification configuration for + # + # @return [Excon::Response] response: + # * body [Hash]: + # * Topics [Array] SNS topic configurations for the notification + # * ID [String] Unique identifier for the configuration + # * Topic [String] Amazon SNS topic ARN to which Amazon S3 will publish a message when it detects events of specified type + # * Event [String] Bucket event for which to send notifications + # * Queues [Array] SQS queue configurations for the notification + # * ID [String] Unique identifier for the configuration + # * Queue [String] Amazon SQS queue ARN to which Amazon S3 will publish a message when it detects events of specified type + # * Event [String] Bucket event for which to send notifications + # * CloudFunctions [Array] AWS Lambda notification configurations + # * ID [String] Unique identifier for the configuration + # * CloudFunction [String] Lambda cloud function ARN that Amazon S3 can invoke when it detects events of the specified type + # * InvocationRole [String] IAM role ARN that Amazon S3 can assume to invoke the specified cloud function on your behalf + # * Event [String] Bucket event for which to send notifications + # + # @see http://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGETnotification.html + def get_bucket_notification(bucket_name) + unless bucket_name + raise ArgumentError.new('bucket_name is required') + end + request({ + :expects => 200, + :headers => {}, + :bucket_name => bucket_name, + :idempotent => true, + :method => 'GET', + :parser => Fog::Parsers::Storage::AWS::GetBucketNotification.new, + :query => {'notification' => nil} + }) + end + end + + class Mock + def get_bucket_notification(bucket_name) + response = Excon::Response.new + + if self.data[:buckets][bucket_name] && self.data[:bucket_notifications][bucket_name] + response.status = 200 + response.body = self.data[:bucket_notifications][bucket_name] + else + response.status = 404 + raise(Excon::Errors.status_error({:expects => 200}, response)) + end + response + end + end + end + end +end diff --git a/lib/fog/aws/requests/storage/put_bucket_notification.rb b/lib/fog/aws/requests/storage/put_bucket_notification.rb new file mode 100644 index 000000000..bd9e0d050 --- /dev/null +++ b/lib/fog/aws/requests/storage/put_bucket_notification.rb @@ -0,0 +1,83 @@ +module Fog + module Storage + class AWS + class Real + # Change notification configuration for an S3 bucket + # + # @param bucket_name [String] name of bucket to set notification configuration for + # * notications [Hash]: + # * Topics [Array] SNS topic configurations for the notification + # * ID [String] Unique identifier for the configuration + # * Topic [String] Amazon SNS topic ARN to which Amazon S3 will publish a message when it detects events of specified type + # * Event [String] Bucket event for which to send notifications + # * Queues [Array] SQS queue configurations for the notification + # * ID [String] Unique identifier for the configuration + # * Queue [String] Amazon SQS queue ARN to which Amazon S3 will publish a message when it detects events of specified type + # * Event [String] Bucket event for which to send notifications + # * CloudFunctions [Array] AWS Lambda notification configurations + # * ID [String] Unique identifier for the configuration + # * CloudFunction [String] Lambda cloud function ARN that Amazon S3 can invoke when it detects events of the specified type + # * InvocationRole [String] IAM role ARN that Amazon S3 can assume to invoke the specified cloud function on your behalf + # * Event [String] Bucket event for which to send notifications + # + # @see http://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketPUTnotification.html + # + def put_bucket_notification(bucket_name, notification) + builder = Nokogiri::XML::Builder.new do + NotificationConfiguration do + notification.fetch('Topics', []).each do |topic| + TopicConfiguration do + Id topic['Id'] + Topic topic['Topic'] + Event topic['Event'] + end + end + notification.fetch('Queues', []).each do |queue| + QueueConfiguration do + Id queue['Id'] + Queue queue['Queue'] + Event topic['Event'] + end + end + notification.fetch('CloudFunctions', []).each do |func| + CloudFunctionConfiguration do + Id func['Id'] + CloudFunction func['CloudFunction'] + InvocationRole func['InvocationRole'] + Event func['Event'] + end + end + end + end + body = builder.to_xml + body.gsub!(/<([^<>]+)\/>/, '<\1>') + request({ + :body => body, + :expects => 200, + :headers => {'Content-MD5' => Base64.encode64(Digest::MD5.digest(body)).chomp!, + 'Content-Type' => 'application/xml'}, + :bucket_name => bucket_name, + :method => 'PUT', + :query => {'notification' => nil} + }) + end + end + + class Mock + def put_bucket_notification(bucket_name, notification) + response = Excon::Response.new + + if self.data[:buckets][bucket_name] + self.data[:bucket_notifications][bucket_name] = notification + response.status = 204 + else + response.status = 404 + raise(Excon::Errors.status_error({:expects => 204}, response)) + end + + response + end + end + end + end +end diff --git a/lib/fog/aws/storage.rb b/lib/fog/aws/storage.rb index e68eeb2d7..2a1498ef2 100644 --- a/lib/fog/aws/storage.rb +++ b/lib/fog/aws/storage.rb @@ -77,6 +77,7 @@ module Fog request :get_bucket_tagging request :get_bucket_versioning request :get_bucket_website + request :get_bucket_notification request :get_object request :get_object_acl request :get_object_torrent @@ -101,6 +102,7 @@ module Fog request :put_bucket_tagging request :put_bucket_versioning request :put_bucket_website + request :put_bucket_notification request :put_object request :put_object_acl request :put_object_url @@ -349,6 +351,7 @@ module Fog :cors => { :bucket => {} }, + :bucket_notifications => {}, :bucket_tagging => {}, :multipart_uploads => {} } diff --git a/tests/requests/storage/bucket_tests.rb b/tests/requests/storage/bucket_tests.rb index c182cc1d4..90824f51f 100644 --- a/tests/requests/storage/bucket_tests.rb +++ b/tests/requests/storage/bucket_tests.rb @@ -312,10 +312,26 @@ Shindo.tests('Fog::Storage[:aws] | bucket requests', ["aws"]) do end end + tests("bucket notification") do + @topic_arn = Fog::AWS[:sns].create_topic('fog_notifications_tests').body['TopicArn'] + + tests("#put_bucket_notification('#{@aws_bucket_name}')").succeeds do + Fog::Storage[:aws].put_bucket_notification(@aws_bucket_name, { 'Topics' => [{ + 'Topic' => @topic_arn, 'Event' => 's3:ObjectCreated:CompleteMultipartUpload' + }]}) + end + + tests("#get_bucket_notification('#{@aws_bucket_name}')"). + returns({'Topics' => [{ 'Topic' => @topic_arn, 'Event' => 's3:ObjectCreated:CompleteMultipartUpload' }]}) do + Fog::Storage[:aws].get_bucket_notification(@aws_bucket_name).body + end + + Fog::AWS[:sns].delete_topic(@topic_arn) + end + tests("#delete_bucket('#{@aws_bucket_name}')").succeeds do Fog::Storage[:aws].delete_bucket(@aws_bucket_name) end - end tests('failure') do @@ -342,6 +358,10 @@ Shindo.tests('Fog::Storage[:aws] | bucket requests', ["aws"]) do Fog::Storage[:aws].get_bucket_location('fognonbucket') end + tests("#get_bucket_notification('fognonbucket')").raises(Excon::Errors::NotFound) do + Fog::Storage[:aws].get_bucket_notification('fognonbucket') + end + tests("#get_request_payment('fognonbucket')").raises(Excon::Errors::NotFound) do Fog::Storage[:aws].get_request_payment('fognonbucket') end