From b2ab9d4b9d6c419660d65dc0aa759edf7eb22578 Mon Sep 17 00:00:00 2001
From: Wesley Beary <me@geemus.com>
Date: Fri, 5 Jun 2009 16:51:17 -0700
Subject: [PATCH] continuing to flesh out s3

---
 lib/fog/aws.rb                          | 10 +---
 lib/fog/aws/s3.rb                       | 63 +++++++++++++++++++++----
 lib/fog/aws/s3/parsers.rb               | 40 ++++++++++++++++
 lib/fog/aws/simpledb.rb                 |  4 +-
 spec/aws/s3/delete_bucket_spec.rb       | 19 ++++++--
 spec/aws/s3/get_bucket_spec.rb          | 18 +++++++
 spec/aws/s3/get_service_spec.rb         | 17 ++++++-
 spec/aws/s3/put_bucket_spec.rb          | 17 ++++++-
 spec/aws/simpledb/create_domain_spec.rb |  4 +-
 9 files changed, 164 insertions(+), 28 deletions(-)
 create mode 100644 spec/aws/s3/get_bucket_spec.rb

diff --git a/lib/fog/aws.rb b/lib/fog/aws.rb
index 0479afb78..f9f9f7975 100644
--- a/lib/fog/aws.rb
+++ b/lib/fog/aws.rb
@@ -16,19 +16,13 @@ module Fog
       def post_init
         @data ||= nil
         @headers ||= {}
+        @method ||= 'GET'
         @response ||= Fog::AWS::Response.new
       end
 
       def connection_completed
         uri = URI.parse(@url)
-        if uri.scheme == 'https'
-          start_tls
-        else
-          request
-        end
-      end
-
-      def ssl_handshake_completed
+        start_tls if uri.scheme == 'https'
         request
       end
 
diff --git a/lib/fog/aws/s3.rb b/lib/fog/aws/s3.rb
index eb98a884d..628bd7ffd 100644
--- a/lib/fog/aws/s3.rb
+++ b/lib/fog/aws/s3.rb
@@ -36,21 +36,66 @@ module Fog
         @scheme     = options[:scheme]    || 'https'
       end
 
+      # List information about S3 buckets for authorized user
       def get_service
-        request('GET', "#{@scheme}://#{@host}:#{@port}/", Fog::Parsers::AWS::S3::GetServiceParser.new)
+        request(
+          'GET',
+          "#{@scheme}://#{@host}:#{@port}/",
+          Fog::Parsers::AWS::S3::GetServiceParser.new
+        )
       end
 
-      def put_bucket(name)
-        request('PUT', "#{@scheme}://#{name}.#{@host}:#{@port}/", Fog::Parsers::AWS::S3::BasicParser.new)
+      # Create an S3 bucket
+      #
+      # ==== Parameters
+      # bucket_name<~String>:: name of bucket to create
+      def put_bucket(bucket_name)
+        request(
+          'PUT',
+          "#{@scheme}://#{bucket_name}.#{@host}:#{@port}/",
+          Fog::Parsers::AWS::S3::BasicParser.new
+        )
       end
-      
-      def delete_bucket(name)
-        request('DELETE', "#{@scheme}://#{name}.#{@host}:#{@port}/", Fog::Parsers::AWS::S3::BasicParser.new)
+
+      # List information about objects in an S3 bucket
+      #
+      # ==== Parameters
+      # bucket_name<~String>:: name of bucket to list object keys from
+      # options<~Hash>:: config arguments for list.  Defaults to {}.
+      #   'prefix' limits object keys to those beginning with its value.
+      #   'marker' limits object keys to only those that appear
+      #     lexicographically after its value.
+      #   'max-keys' limits number of object keys returned
+      #   'delimiter' causes keys with the same string between the prefix
+      #     value and the first occurence of delimiter to be rolled up
+      def get_bucket(bucket_name, options = {})
+        query = '?'
+        options.each do |key, value|
+          query << "#{key}=#{value};"
+        end
+        query.chop!
+        request(
+          'GET',
+          "#{@scheme}://#{bucket_name}.#{@host}:#{@port}/#{query}",
+          Fog::Parsers::AWS::S3::GetBucketParser.new
+        )
+      end
+
+      # Delete an S3 bucket
+      #
+      # ==== Parameters
+      # bucket_name<~String>:: name of bucket to delete
+      def delete_bucket(bucket_name)
+        request(
+          'DELETE',
+          "#{@scheme}://#{bucket_name}.#{@host}:#{@port}/",
+          Fog::Parsers::AWS::S3::BasicParser.new
+        )
       end
 
       private
 
-      def request(method, url, parser, data=nil)
+      def request(method, url, parser, data = nil)
         uri = URI.parse(url)
         headers = { 'Date' => Time.now.utc.strftime("%a, %d %b %Y %H:%M:%S +0000") }
         params = [
@@ -65,7 +110,7 @@ module Fog
         hmac = @hmac.update(string_to_sign)
         signature = Base64.encode64(hmac.digest).strip
         headers['Authorization'] = "AWS #{@aws_access_key_id}:#{signature}"
-        
+
         response = nil
         EventMachine::run {
           http = EventMachine.connect(@host, @port, Fog::AWS::Connection) {|connection|
@@ -78,7 +123,7 @@ module Fog
         }
         response
       end
-   
+
     end
   end
 end
\ No newline at end of file
diff --git a/lib/fog/aws/s3/parsers.rb b/lib/fog/aws/s3/parsers.rb
index cae8034b4..62a18e014 100644
--- a/lib/fog/aws/s3/parsers.rb
+++ b/lib/fog/aws/s3/parsers.rb
@@ -52,6 +52,46 @@ module Fog
 
         end
 
+        class GetBucketParser < Fog::Parsers::AWS::S3::BasicParser
+
+          def reset
+            @object = { :owner => {} }
+            @response = { :contents => [] }
+          end
+
+          def end_element(name)
+            case name
+            when 'Contents'
+              @response[:contents] << @object
+              @object = { :owner => {} }
+            when 'DisplayName'
+              @object[:owner][:display_name] = @value
+            when 'ETag'
+              @object[:etag] = @value
+            when 'ID'
+              @object[:owner][:id] = @value
+            when 'IsTruncated'
+              @response[:is_truncated] = @value
+            when 'Key'
+              @object[:key] = @value
+            when 'LastModified'
+              @object[:last_modified] = @value
+            when 'Marker'
+              @response[:marker] = @value
+            when 'MaxKeys'
+              @response[:max_keys] = @value
+            when 'Name'
+              @response[:name] = @value
+            when 'Prefix'
+              @response[:prefix] = @value
+            when 'Size'
+              @object[:size] = @value
+            when 'StorageClass'
+              @object[:storage_class] = @value
+            end
+          end
+
+        end
 
       end
     end
diff --git a/lib/fog/aws/simpledb.rb b/lib/fog/aws/simpledb.rb
index 8a572c1cb..89119b0df 100644
--- a/lib/fog/aws/simpledb.rb
+++ b/lib/fog/aws/simpledb.rb
@@ -8,7 +8,7 @@ require File.dirname(__FILE__) + '/simpledb/parsers'
 module Fog
   module AWS
     class SimpleDB
-      
+
       # Initialize connection to SimpleDB
       #
       # ==== Notes
@@ -289,7 +289,7 @@ module Fog
         string_to_sign = "#{method}\n#{@host + (@port == 80 ? "" : ":#{@port}")}\n/\n" << query.chop
         hmac = @hmac.update(string_to_sign)
         query << "Signature=#{CGI.escape(Base64.encode64(hmac.digest).strip).gsub(/\+/, '%20')}"
-        
+
         response = nil
         EventMachine::run {
           http = EventMachine.connect(@host, @port, Fog::AWS::Connection) {|connection|
diff --git a/spec/aws/s3/delete_bucket_spec.rb b/spec/aws/s3/delete_bucket_spec.rb
index 8e2eee6a2..98b8e7c13 100644
--- a/spec/aws/s3/delete_bucket_spec.rb
+++ b/spec/aws/s3/delete_bucket_spec.rb
@@ -2,8 +2,21 @@ require File.dirname(__FILE__) + '/../../spec_helper'
 
 describe 'S3.delete_bucket' do
 
-  it 'should return stuff' do
-    p s3.delete_bucket('fogputbucket')
+  before(:all) do
+    s3.put_bucket('fogdeletebucket')
   end
 
-end
\ No newline at end of file
+  it 'should include fogdeletebucket in get_service before delete_bucket' do
+    lambda { s3.get_service }.should eventually { |expected| expected.body[:buckets].collect { |bucket| bucket[:name] }.should include('fogdeletebucket') }
+  end
+
+  it 'should return proper attributes' do
+    p 'SHOULD CHECK FOR PROPER ATTRIBUTES'
+    p s3.delete_bucket('fogdeletebucket')
+  end
+
+  it 'should not include fogdeletebucket in get_service after delete_bucket' do
+    lambda { s3.get_service }.should_not eventually { |expected| expected.body[:buckets].collect { |bucket| bucket[:name] }.should_not include('fogdeletebucket') }
+  end
+
+end
diff --git a/spec/aws/s3/get_bucket_spec.rb b/spec/aws/s3/get_bucket_spec.rb
new file mode 100644
index 000000000..eaca3aefe
--- /dev/null
+++ b/spec/aws/s3/get_bucket_spec.rb
@@ -0,0 +1,18 @@
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+describe 'S3.get_bucket' do
+
+  before(:all) do
+    s3.put_bucket('foggetbucket')
+  end
+
+  after(:all) do
+    s3.delete_bucket('foggetbucket')
+  end
+
+  it 'should return proper attributes' do
+    p 'SHOULD CHECK FOR PROPER ATTRIBUTES'
+    p s3.get_bucket('fogputbucket')
+  end
+
+end
diff --git a/spec/aws/s3/get_service_spec.rb b/spec/aws/s3/get_service_spec.rb
index fb1676cbb..54e630fed 100644
--- a/spec/aws/s3/get_service_spec.rb
+++ b/spec/aws/s3/get_service_spec.rb
@@ -2,8 +2,21 @@ require File.dirname(__FILE__) + '/../../spec_helper'
 
 describe 'S3.get_service' do
 
-  it 'should return stuff' do
+  before(:all) do
+    s3.put_bucket('foggetservice')
+  end
+
+  after(:all) do
+    s3.delete_bucket('foggetservice')
+  end
+
+  it 'should return proper_attributes' do
+    p 'SHOULD CHECK FOR PROPER ATTRIBUTES'
     p s3.get_service
   end
 
-end
\ No newline at end of file
+  it 'should include foggetservice in get_service' do
+    lambda { s3.get_service }.should eventually { |expected| expected.body[:buckets].collect { |bucket| bucket[:name] }.should include('list_domains') }
+  end
+
+end
diff --git a/spec/aws/s3/put_bucket_spec.rb b/spec/aws/s3/put_bucket_spec.rb
index d4b5d60a2..0261f8937 100644
--- a/spec/aws/s3/put_bucket_spec.rb
+++ b/spec/aws/s3/put_bucket_spec.rb
@@ -2,8 +2,21 @@ require File.dirname(__FILE__) + '/../../spec_helper'
 
 describe 'S3.put_bucket' do
 
-  it 'should return stuff' do
+  after(:all) do
+    s3.delete_bucket('fogputbucket')
+  end
+
+  it 'should not include fogputbucket in get_service buckets before put_bucket' do
+    lambda { s3.get_service }.should_not eventually { |expected| expected.body[:buckets].collect { |bucket| bucket[:name] }.should_not include('fogputbucket') }
+  end
+
+  it 'should return proper attributes' do
+    p 'SHOULD CHECK FOR PROPER ATTRIBUTES'
     p s3.put_bucket('fogputbucket')
   end
 
-end
\ No newline at end of file
+  it 'should include fogputbucket in get_service buckets after put_bucket' do
+    lambda { s3.get_service }.should eventually { |expected| expected.body[:buckets].collect { |bucket| bucket[:name] }.should include('fogputbucket') }
+  end
+
+end
diff --git a/spec/aws/simpledb/create_domain_spec.rb b/spec/aws/simpledb/create_domain_spec.rb
index bba968dd6..1f834488d 100644
--- a/spec/aws/simpledb/create_domain_spec.rb
+++ b/spec/aws/simpledb/create_domain_spec.rb
@@ -6,7 +6,7 @@ describe 'SimpleDB.create_domain' do
     sdb.delete_domain('create_domain')
   end
 
-  it 'should not include test domain in list_domains before create_domain' do
+  it 'should not include create_domain in list_domains before create_domain' do
     lambda { sdb.list_domains }.should_not eventually { |expected| expected.body[:domains].should_not include('create_domain') }
   end
 
@@ -16,7 +16,7 @@ describe 'SimpleDB.create_domain' do
     actual.body[:box_usage].should be_a(Float)
   end
 
-  it 'should include test in list_domains after create_domain' do
+  it 'should include create_domain in list_domains after create_domain' do
     lambda { sdb.list_domains }.should eventually { |expected| expected.body[:domains].should include('create_domain') }
   end