fakes3 0.1.5 → 0.1.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0fd5e9498cd058b485b059f03ca06d9030d8d7c1
4
+ data.tar.gz: 31b5e10a57f2a723a8a04bbdec62f7c726c8cb5c
5
+ SHA512:
6
+ metadata.gz: 56353c5a81798343a51989019c484a5e203b91188e813a3bddbb33ff120d451b5d99c7c6c2d9cbf13b2c929f9c651eb9d0f846ddae3d1529fbfc3718b96d07e0
7
+ data.tar.gz: b24c2db7d546dd0772dd2c897f90d2ae331b9b286f326be62e8d5794eaa606b331e48a0216c3fddb0ccffa42719c7802b1b8952f3d9c0b796d8a27943470e6cb
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source :rubygems
1
+ source 'https://rubygems.org'
2
2
  gem 'fakes3', :path => '.' # for dev and test, use local fakes3
3
3
  # Specify your gem's dependencies in fakes3.gemspec
4
4
  gemspec
data/Gemfile.lock CHANGED
@@ -1,25 +1,25 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fakes3 (0.1.5)
4
+ fakes3 (0.1.5.2)
5
5
  builder
6
6
  thor
7
7
 
8
8
  GEM
9
- remote: http://rubygems.org/
9
+ remote: https://rubygems.org/
10
10
  specs:
11
- aws-s3 (0.6.2)
11
+ aws-s3 (0.6.3)
12
12
  builder
13
13
  mime-types
14
14
  xml-simple
15
- builder (3.0.0)
16
- mime-types (1.18)
17
- rake (0.9.2.2)
18
- right_aws (3.0.4)
15
+ builder (3.2.2)
16
+ mime-types (1.25)
17
+ rake (10.1.0)
18
+ right_aws (3.1.0)
19
19
  right_http_connection (>= 1.2.5)
20
- right_http_connection (1.3.0)
21
- thor (0.14.6)
22
- xml-simple (1.1.1)
20
+ right_http_connection (1.4.0)
21
+ thor (0.18.1)
22
+ xml-simple (1.1.2)
23
23
 
24
24
  PLATFORMS
25
25
  ruby
data/Rakefile CHANGED
@@ -6,7 +6,8 @@ Bundler::GemHelper.install_tasks
6
6
 
7
7
  Rake::TestTask.new(:test) do |t|
8
8
  t.libs << "."
9
- t.test_files = FileList['test/*_test.rb']
9
+ t.test_files =
10
+ FileList['test/*_test.rb'].exclude('test/s3_commands_test.rb')
10
11
  end
11
12
 
12
13
  desc "Run the test_server"
data/bin/fakes3 CHANGED
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ $: << './lib'
4
+
3
5
  require 'fakes3/cli'
4
6
  FakeS3::CLI.start
data/lib/fakes3/cli.rb CHANGED
@@ -9,6 +9,7 @@ module FakeS3
9
9
  desc "server", "Run a server on a particular hostname"
10
10
  method_option :root, :type => :string, :aliases => '-r', :required => true
11
11
  method_option :port, :type => :numeric, :aliases => '-p', :required => true
12
+ method_option :address, :type => :string, :aliases => '-a', :required => false, :desc => "Bind to this address. Defaults to 0.0.0.0"
12
13
  method_option :hostname, :type => :string, :aliases => '-h', :desc => "The root name of the host. Defaults to s3.amazonaws.com."
13
14
  method_option :limit, :aliases => '-l', :type => :string, :desc => 'Rate limit for serving (ie. 50K, 1.0M)'
14
15
  def server
@@ -42,8 +43,10 @@ module FakeS3
42
43
  end
43
44
  end
44
45
 
46
+ address = options[:address] || '0.0.0.0'
47
+
45
48
  puts "Loading FakeS3 with #{root} on port #{options[:port]} with hostname #{hostname}"
46
- server = FakeS3::Server.new(options[:port],store,hostname)
49
+ server = FakeS3::Server.new(address,options[:port],store,hostname)
47
50
  server.serve
48
51
  end
49
52
 
@@ -81,6 +81,9 @@ module FakeS3
81
81
  real_obj.content_type = metadata.fetch(:content_type) { "application/octet-stream" }
82
82
  #real_obj.io = File.open(File.join(obj_root,"content"),'rb')
83
83
  real_obj.io = RateLimitableFile.open(File.join(obj_root,"content"),'rb')
84
+ real_obj.size = metadata.fetch(:size) { 0 }
85
+ real_obj.creation_date = File.ctime(obj_root).iso8601()
86
+ real_obj.modified_date = metadata.fetch(:modified_date) { File.mtime(File.join(obj_root,"content")).iso8601() }
84
87
  return real_obj
85
88
  rescue
86
89
  puts $!
@@ -126,6 +129,8 @@ module FakeS3
126
129
  obj.name = dst_name
127
130
  obj.md5 = src_metadata[:md5]
128
131
  obj.content_type = src_metadata[:content_type]
132
+ obj.size = src_metadata[:size]
133
+ obj.modified_date = src_metadata[:modified_date]
129
134
 
130
135
  src_obj = src_bucket.find(src_name)
131
136
  dst_bucket.add(obj)
@@ -157,6 +162,8 @@ module FakeS3
157
162
  metadata_struct = {}
158
163
  metadata_struct[:md5] = md5.hexdigest
159
164
  metadata_struct[:content_type] = request.header["content-type"].first
165
+ metadata_struct[:size] = File.size(content)
166
+ metadata_struct[:modified_date] = File.mtime(content).iso8601()
160
167
 
161
168
  File.open(metadata,'w') do |f|
162
169
  f << YAML::dump(metadata_struct)
@@ -166,6 +173,8 @@ module FakeS3
166
173
  obj.name = object_name
167
174
  obj.md5 = metadata_struct[:md5]
168
175
  obj.content_type = metadata_struct[:content_type]
176
+ obj.size = metadata_struct[:size]
177
+ obj.modified_date = metadata_struct[:modified_date]
169
178
 
170
179
  bucket.add(obj)
171
180
  return obj
@@ -1,7 +1,7 @@
1
1
  module FakeS3
2
2
  class S3Object
3
3
  include Comparable
4
- attr_accessor :name,:size,:creation_date,:md5,:io,:content_type
4
+ attr_accessor :name,:size,:creation_date,:modified_date,:md5,:io,:content_type
5
5
 
6
6
  def hash
7
7
  @name.hash
data/lib/fakes3/server.rb CHANGED
@@ -87,9 +87,14 @@ module FakeS3
87
87
 
88
88
  response.status = 200
89
89
  response['Content-Type'] = real_obj.content_type
90
- content_length = File::Stat.new(real_obj.io.path).size
91
- response['Etag'] = real_obj.md5
90
+ stat = File::Stat.new(real_obj.io.path)
91
+
92
+ response['Last-Modified'] = stat.mtime.iso8601()
93
+ response.header['ETag'] = "\"#{real_obj.md5}\""
92
94
  response['Accept-Ranges'] = "bytes"
95
+ response['Last-Ranges'] = "bytes"
96
+
97
+ content_length = stat.size
93
98
 
94
99
  # Added Range Query support
95
100
  if range = request.header["range"].first
@@ -113,6 +118,7 @@ module FakeS3
113
118
  end
114
119
  end
115
120
  response['Content-Length'] = File::Stat.new(real_obj.io.path).size
121
+ response['Last-Modified'] = real_obj.modified_date
116
122
  if s_req.http_verb == 'HEAD'
117
123
  response.body = ""
118
124
  else
@@ -135,7 +141,7 @@ module FakeS3
135
141
  end
136
142
 
137
143
  real_obj = @store.store_object(bucket_obj,s_req.object,s_req.webrick_request)
138
- response['Etag'] = real_obj.md5
144
+ response.header['ETag'] = "\"#{real_obj.md5}\""
139
145
  when Request::CREATE_BUCKET
140
146
  @store.create_bucket(s_req.bucket)
141
147
  end
@@ -207,10 +213,7 @@ module FakeS3
207
213
  elems = path.split("/")
208
214
  end
209
215
 
210
- if elems.size == 0
211
- # List buckets
212
- s_req.type = Request::LIST_BUCKETS
213
- elsif elems.size == 1
216
+ if elems.size < 2
214
217
  s_req.type = Request::LS_BUCKET
215
218
  s_req.query = query
216
219
  else
@@ -311,14 +314,15 @@ module FakeS3
311
314
 
312
315
 
313
316
  class Server
314
- def initialize(port,store,hostname)
317
+ def initialize(address,port,store,hostname)
318
+ @address = address
315
319
  @port = port
316
320
  @store = store
317
321
  @hostname = hostname
318
322
  end
319
323
 
320
324
  def serve
321
- @server = WEBrick::HTTPServer.new(:Port => @port)
325
+ @server = WEBrick::HTTPServer.new(:BindAddress => @address, :Port => @port)
322
326
  @server.mount "/", Servlet, @store,@hostname
323
327
  trap "INT" do @server.shutdown end
324
328
  @server.start
@@ -1,3 +1,3 @@
1
1
  module FakeS3
2
- VERSION = "0.1.5"
2
+ VERSION = "0.1.5.2"
3
3
  end
@@ -124,7 +124,7 @@ module FakeS3
124
124
  objects.each do |s3_object|
125
125
  lbr.Contents { |contents|
126
126
  contents.Key(s3_object.name)
127
- contents.LastModifed(s3_object.creation_date)
127
+ contents.LastModified(s3_object.modified_date)
128
128
  contents.ETag("\"#{s3_object.md5}\"")
129
129
  contents.Size(s3_object.size)
130
130
  contents.StorageClass("STANDARD")
data/test/boto_test.rb ADDED
@@ -0,0 +1,25 @@
1
+ require 'test/test_helper'
2
+ require 'fileutils'
3
+
4
+ class BotoTest < Test::Unit::TestCase
5
+ def setup
6
+ cmdpath = File.expand_path(File.join(File.dirname(__FILE__),'botocmd.py'))
7
+ @botocmd = "python #{cmdpath} -t localhost -p 10453"
8
+ end
9
+
10
+ def teardown
11
+ end
12
+
13
+ def test_store
14
+ File.open(__FILE__,'rb') do |input|
15
+ File.open("/tmp/fakes3_upload",'wb') do |output|
16
+ output << input.read
17
+ end
18
+ end
19
+ output = `#{@botocmd} put /tmp/fakes3_upload s3://s3cmd_bucket/upload`
20
+ assert_match(/stored/,output)
21
+
22
+ FileUtils.rm("/tmp/fakes3_upload")
23
+ end
24
+
25
+ end
data/test/botocmd.py ADDED
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/python
2
+ # -*- coding: utf-8 -*-
3
+ # fakes3cmd.py -- an s3cmd-like script that accepts a custom host and portname
4
+ import re
5
+ import os
6
+ from optparse import OptionParser
7
+
8
+ try:
9
+ from boto.s3.connection import S3Connection, OrdinaryCallingFormat
10
+ from boto.s3.key import Key
11
+ except ImportError:
12
+ raise Exception('You must install the boto package for python')
13
+
14
+
15
+ class FakeS3Cmd(object):
16
+ COMMANDS = ['mb', 'rb', 'put', ]
17
+ def __init__(self, host, port):
18
+ self.host = host
19
+ self.port = port
20
+ self.conn = None
21
+ self._connect()
22
+
23
+ def _connect(self):
24
+ print 'Connecting: %s:%s' % (self.host, self.port)
25
+ self.conn = S3Connection(is_secure=False,
26
+ calling_format=OrdinaryCallingFormat(),
27
+ aws_access_key_id='',
28
+ aws_secret_access_key='',
29
+ port=self.port, host=self.host)
30
+
31
+
32
+ @staticmethod
33
+ def _parse_uri(path):
34
+ match = re.match(r's3://([^/]+)(?:/(.*))?', path, re.I)
35
+ ## (bucket, key)
36
+ return match.groups()
37
+
38
+ def mb(self, path, *args):
39
+ if not self.conn:
40
+ self._connect()
41
+
42
+ bucket, _ = self._parse_uri(path)
43
+ self.conn.create_bucket(bucket)
44
+ print 'made bucket: [%s]' % bucket
45
+
46
+ def rb(self, path, *args):
47
+ if not self.conn:
48
+ self._connect()
49
+
50
+ bucket, _ = self._parse_uri(path)
51
+ self.conn.delete_bucket(bucket)
52
+ print 'removed bucket: [%s]' % bucket
53
+
54
+ def put(self, *args):
55
+ if not self.conn:
56
+ self._connect()
57
+
58
+ args = list(args)
59
+ path = args.pop()
60
+ bucket_name, prefix = self._parse_uri(path)
61
+ bucket = self.conn.create_bucket(bucket_name)
62
+ for src_file in args:
63
+ key = Key(bucket)
64
+ key.key = os.path.join(prefix, os.path.basename(src_file))
65
+ key.set_contents_from_filename(src_file)
66
+ print 'stored: [%s]' % key.key
67
+
68
+
69
+ if __name__ == "__main__":
70
+ # check for options. TODO: This requires a more verbose help message
71
+ # to explain how the positional arguments work.
72
+ parser = OptionParser()
73
+ parser.add_option("-t", "--host", type="string", default='localhost')
74
+ parser.add_option("-p", "--port", type='int', default=80)
75
+ o, args = parser.parse_args()
76
+
77
+ if len(args) < 2:
78
+ raise ValueError('you must minimally supply a desired command and s3 uri')
79
+
80
+ cmd = args.pop(0)
81
+
82
+ if cmd not in FakeS3Cmd.COMMANDS:
83
+ raise ValueError('%s is not a valid command' % cmd)
84
+
85
+ fs3 = FakeS3Cmd(o.host, o.port)
86
+ handler = getattr(fs3, cmd)
87
+ handler(*args)
@@ -60,4 +60,33 @@ class RightAWSCommandsTest < Test::Unit::TestCase
60
60
  assert_equal "Hello World",obj[:object]
61
61
  end
62
62
 
63
+ def test_larger_lists
64
+ @s3.create_bucket('right_aws_many')
65
+ (0..50).each do |i|
66
+ ('a'..'z').each do |letter|
67
+ name = "#{letter}#{i}"
68
+ @s3.put('right_aws_many', name, 'asdf')
69
+ end
70
+ end
71
+
72
+ keys = @s3.list_bucket('right_aws_many')
73
+ assert_equal(1000, keys.size)
74
+ assert_equal('a0', keys.first[:key])
75
+ end
76
+
77
+ def test_destroy_bucket
78
+ @s3.create_bucket('deletebucket')
79
+ @s3.delete_bucket('deletebucket')
80
+
81
+ begin
82
+ bucket = @s3.list_bucket('deletebucket')
83
+ fail("Shouldn't succeed here")
84
+ rescue RightAws::AwsError
85
+ assert $!.message.include?('NoSuchBucket')
86
+ rescue
87
+ fail 'Should have caught NoSuchBucket Exception'
88
+ end
89
+
90
+ end
91
+
63
92
  end
metadata CHANGED
@@ -1,112 +1,108 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: fakes3
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 1
8
- - 5
9
- version: 0.1.5
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.5.2
10
5
  platform: ruby
11
- authors:
6
+ authors:
12
7
  - Curtis Spencer
13
8
  autorequire:
14
9
  bindir: bin
15
10
  cert_chain: []
16
-
17
- date: 2012-04-20 00:00:00 -07:00
18
- default_executable:
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
11
+ date: 2013-10-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
21
14
  name: bundler
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
- none: false
25
- requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- segments:
29
- - 1
30
- - 0
31
- - 0
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
32
19
  version: 1.0.0
33
20
  type: :development
34
- version_requirements: *id001
35
- - !ruby/object:Gem::Dependency
36
- name: aws-s3
37
21
  prerelease: false
38
- requirement: &id002 !ruby/object:Gem::Requirement
39
- none: false
40
- requirements:
41
- - - ">="
42
- - !ruby/object:Gem::Version
43
- segments:
44
- - 0
45
- version: "0"
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: 1.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: aws-s3
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
46
34
  type: :development
47
- version_requirements: *id002
48
- - !ruby/object:Gem::Dependency
49
- name: right_aws
50
35
  prerelease: false
51
- requirement: &id003 !ruby/object:Gem::Requirement
52
- none: false
53
- requirements:
54
- - - ">="
55
- - !ruby/object:Gem::Version
56
- segments:
57
- - 0
58
- version: "0"
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: right_aws
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
59
48
  type: :development
60
- version_requirements: *id003
61
- - !ruby/object:Gem::Dependency
62
- name: rake
63
49
  prerelease: false
64
- requirement: &id004 !ruby/object:Gem::Requirement
65
- none: false
66
- requirements:
67
- - - ">="
68
- - !ruby/object:Gem::Version
69
- segments:
70
- - 0
71
- version: "0"
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
72
62
  type: :development
73
- version_requirements: *id004
74
- - !ruby/object:Gem::Dependency
75
- name: thor
76
63
  prerelease: false
77
- requirement: &id005 !ruby/object:Gem::Requirement
78
- none: false
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- segments:
83
- - 0
84
- version: "0"
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: thor
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
85
76
  type: :runtime
86
- version_requirements: *id005
87
- - !ruby/object:Gem::Dependency
88
- name: builder
89
77
  prerelease: false
90
- requirement: &id006 !ruby/object:Gem::Requirement
91
- none: false
92
- requirements:
93
- - - ">="
94
- - !ruby/object:Gem::Version
95
- segments:
96
- - 0
97
- version: "0"
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: builder
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
98
90
  type: :runtime
99
- version_requirements: *id006
100
- description: Use FakeS3 to test basic S3 functionality without actually connecting to S3
101
- email:
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Use FakeS3 to test basic S3 functionality without actually connecting
98
+ to S3
99
+ email:
102
100
  - thorin@gmail.com
103
- executables:
101
+ executables:
104
102
  - fakes3
105
103
  extensions: []
106
-
107
104
  extra_rdoc_files: []
108
-
109
- files:
105
+ files:
110
106
  - .gitignore
111
107
  - Gemfile
112
108
  - Gemfile.lock
@@ -128,44 +124,40 @@ files:
128
124
  - lib/fakes3/unsupported_operation.rb
129
125
  - lib/fakes3/version.rb
130
126
  - lib/fakes3/xml_adapter.rb
127
+ - test/boto_test.rb
128
+ - test/botocmd.py
131
129
  - test/local_s3_cfg
132
130
  - test/right_aws_commands_test.rb
133
131
  - test/s3_commands_test.rb
134
132
  - test/s3cmd_test.rb
135
133
  - test/test_helper.rb
136
- has_rdoc: true
137
- homepage: ""
134
+ homepage: ''
138
135
  licenses: []
139
-
136
+ metadata: {}
140
137
  post_install_message:
141
138
  rdoc_options: []
142
-
143
- require_paths:
139
+ require_paths:
144
140
  - lib
145
- required_ruby_version: !ruby/object:Gem::Requirement
146
- none: false
147
- requirements:
148
- - - ">="
149
- - !ruby/object:Gem::Version
150
- segments:
151
- - 0
152
- version: "0"
153
- required_rubygems_version: !ruby/object:Gem::Requirement
154
- none: false
155
- requirements:
156
- - - ">="
157
- - !ruby/object:Gem::Version
158
- segments:
159
- - 0
160
- version: "0"
141
+ required_ruby_version: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - '>='
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ required_rubygems_version: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - '>='
149
+ - !ruby/object:Gem::Version
150
+ version: '0'
161
151
  requirements: []
162
-
163
152
  rubyforge_project: fakes3
164
- rubygems_version: 1.3.7
153
+ rubygems_version: 2.0.2
165
154
  signing_key:
166
- specification_version: 3
167
- summary: FakeS3 is a server that simulates S3 commands so you can test your S3 functionality in your projects
168
- test_files:
155
+ specification_version: 4
156
+ summary: FakeS3 is a server that simulates S3 commands so you can test your S3 functionality
157
+ in your projects
158
+ test_files:
159
+ - test/boto_test.rb
160
+ - test/botocmd.py
169
161
  - test/local_s3_cfg
170
162
  - test/right_aws_commands_test.rb
171
163
  - test/s3_commands_test.rb