diff --git a/.gitignore b/.gitignore index 28aa778c..21918d82 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ pkg/* .bundle tmp test_root +Gemfile.lock \ No newline at end of file diff --git a/Gemfile.lock b/Gemfile.lock index c05e2a4f..343af01a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -13,15 +13,17 @@ GEM mime-types xml-simple builder (3.2.2) - mime-types (1.25) - rake (10.1.0) - rest-client (1.6.7) - mime-types (>= 1.16) + mime-types (2.3) + netrc (0.7.7) + rake (10.3.2) + rest-client (1.7.2) + mime-types (>= 1.16, < 3.0) + netrc (~> 0.7) right_aws (3.1.0) right_http_connection (>= 1.2.5) right_http_connection (1.4.0) - thor (0.18.1) - xml-simple (1.1.2) + thor (0.19.1) + xml-simple (1.1.4) PLATFORMS ruby diff --git a/lib/fakes3/file_store.rb b/lib/fakes3/file_store.rb index 10546a8e..e63db186 100644 --- a/lib/fakes3/file_store.rb +++ b/lib/fakes3/file_store.rb @@ -20,6 +20,7 @@ def initialize(root) @buckets << bucket_obj @bucket_hash[bucket_name] = bucket_obj end + FileUtils.mkdir_p(File.join(@root,"policies")) end # Pass a rate limit in bytes per second @@ -60,6 +61,7 @@ def create_bucket(bucket) @buckets << bucket_obj @bucket_hash[bucket] = bucket_obj end + File.open(File.join(@root,"policies",bucket),'w') { |file| file.write("") } bucket_obj end @@ -68,6 +70,7 @@ def delete_bucket(bucket_name) raise NoSuchBucket if !bucket raise BucketNotEmpty if bucket.objects.count > 0 FileUtils.rm_r(get_bucket_folder(bucket)) + File.delete(File.join(@root,"policies",bucket_name)) @bucket_hash.delete(bucket_name) end @@ -75,15 +78,17 @@ def get_object(bucket,object_name, request) begin real_obj = S3Object.new obj_root = File.join(@root,bucket,object_name,SHUCK_METADATA_DIR) - metadata = YAML.load(File.open(File.join(obj_root,"metadata"),'rb')) - real_obj.name = object_name - real_obj.md5 = metadata[:md5] - real_obj.content_type = metadata.fetch(:content_type) { "application/octet-stream" } - #real_obj.io = File.open(File.join(obj_root,"content"),'rb') - real_obj.io = RateLimitableFile.open(File.join(obj_root,"content"),'rb') - real_obj.size = metadata.fetch(:size) { 0 } - real_obj.creation_date = File.ctime(obj_root).utc.iso8601() - real_obj.modified_date = metadata.fetch(:modified_date) { File.mtime(File.join(obj_root,"content")).utc.iso8601() } + File.open(File.join(obj_root,"metadata"),'rb') do |metadata_file| + metadata = YAML.load(metadata_file) + real_obj.name = object_name + real_obj.md5 = metadata[:md5] + real_obj.content_type = metadata.fetch(:content_type) { "application/octet-stream" } + #real_obj.io = File.open(File.join(obj_root,"content"),'rb') + real_obj.io = RateLimitableFile.open(File.join(obj_root,"content"),'rb') + real_obj.size = metadata.fetch(:size) { 0 } + real_obj.creation_date = File.ctime(obj_root).utc.iso8601() + real_obj.modified_date = metadata.fetch(:modified_date) { File.mtime(File.join(obj_root,"content")).utc.iso8601() } + end return real_obj rescue puts $! @@ -162,7 +167,7 @@ def store_object(bucket,object_name,request) # TODO put a tmpfile here first and mv it over at the end match=request.content_type.match(/^multipart\/form-data; boundary=(.+)/) - boundary = match[1] if match + boundary = match[1] if match if boundary boundary = WEBrick::HTTPUtils::dequote(boundary) filedata = WEBrick::HTTPUtils::parse_form_data(request.body, boundary) @@ -211,6 +216,20 @@ def delete_object(bucket,object_name,request) end end + def get_policy(bucket) + begin + policyname = File.join(@root,"policies",bucket) + return File.read(policyname) + end + end + + def put_policy(bucket,policy) + begin + policyname = File.join(@root,"policies",bucket) + File.open(policyname,'w') { |file| file.write(policy) } + end + end + def create_metadata(content,request) metadata = {} metadata[:md5] = Digest::MD5.file(content).hexdigest diff --git a/lib/fakes3/server.rb b/lib/fakes3/server.rb index e16c15de..1cd10633 100644 --- a/lib/fakes3/server.rb +++ b/lib/fakes3/server.rb @@ -20,6 +20,8 @@ class Request MOVE = "MOVE" DELETE_OBJECT = "DELETE_OBJECT" DELETE_BUCKET = "DELETE_BUCKET" + PUT_POLICY = "PUT_POLICY" + GET_POLICY = "GET_POLICY" attr_accessor :bucket,:object,:type,:src_bucket, :src_object,:method,:webrick_request, @@ -126,6 +128,11 @@ def do_GET(request, response) else response.body = real_obj.io end + when 'GET_POLICY' + response.status = 200 + response['Content-Type'] = "application/xml" + response.body = @store.get_policy(s_req.bucket) + response['Content-Length'] = response.body.length end end @@ -151,6 +158,8 @@ def do_PUT(request,response) response.header['ETag'] = "\"#{real_obj.md5}\"" when Request::CREATE_BUCKET @store.create_bucket(s_req.bucket) + when Request::PUT_POLICY + @store.put_policy(s_req.bucket, request.body) end end @@ -258,8 +267,12 @@ def normalize_get(webrick_req,s_req) end if elems.size < 2 - s_req.type = Request::LS_BUCKET - s_req.query = query + if webrick_req.query_string == "policy" + s_req.type = Request::GET_POLICY + else + s_req.type = Request::LS_BUCKET + s_req.query = query + end else if query["acl"] == "" s_req.type = Request::GET_ACL @@ -284,7 +297,11 @@ def normalize_put(webrick_req,s_req) elems = path[1,path_len].split("/") s_req.bucket = elems[0] if elems.size == 1 - s_req.type = Request::CREATE_BUCKET + if webrick_req.query_string == "policy" + s_req.type = Request::PUT_POLICY + else + s_req.type = Request::CREATE_BUCKET + end else if webrick_req.request_line =~ /\?acl/ s_req.type = Request::SET_ACL